Merge "Testing initial value for 0-duration animations" into nyc-dev
diff --git a/Android.mk b/Android.mk
index 683cdf8..4dc5fd34 100644
--- a/Android.mk
+++ b/Android.mk
@@ -149,15 +149,16 @@
 	core/java/android/content/pm/IPackageMoveObserver.aidl \
 	core/java/android/content/pm/IPackageStatsObserver.aidl \
 	core/java/android/content/pm/IOnPermissionsChangeListener.aidl \
+	core/java/android/content/pm/IShortcutService.aidl \
 	core/java/android/database/IContentObserver.aidl \
-	core/java/android/hardware/ICameraService.aidl \
-	core/java/android/hardware/ICameraServiceListener.aidl \
-	core/java/android/hardware/ICameraServiceProxy.aidl \
-	core/java/android/hardware/ICamera.aidl \
-	core/java/android/hardware/ICameraClient.aidl \
+	../av/camera/aidl/android/hardware/ICameraService.aidl \
+	../av/camera/aidl/android/hardware/ICameraServiceListener.aidl \
+	../av/camera/aidl/android/hardware/ICameraServiceProxy.aidl \
+	../av/camera/aidl/android/hardware/ICamera.aidl \
+	../av/camera/aidl/android/hardware/ICameraClient.aidl \
+	../av/camera/aidl/android/hardware/camera2/ICameraDeviceUser.aidl \
+	../av/camera/aidl/android/hardware/camera2/ICameraDeviceCallbacks.aidl \
 	core/java/android/hardware/IConsumerIrService.aidl \
-	core/java/android/hardware/camera2/ICameraDeviceUser.aidl \
-	core/java/android/hardware/camera2/ICameraDeviceCallbacks.aidl \
 	core/java/android/hardware/ISerialManager.aidl \
 	core/java/android/hardware/display/IDisplayManager.aidl \
 	core/java/android/hardware/display/IDisplayManagerCallback.aidl \
@@ -241,11 +242,13 @@
 	core/java/android/service/notification/IStatusBarNotificationHolder.aidl \
 	core/java/android/service/notification/IConditionListener.aidl \
 	core/java/android/service/notification/IConditionProvider.aidl \
+	core/java/android/service/vr/IVrListener.aidl \
 	core/java/android/print/ILayoutResultCallback.aidl \
 	core/java/android/print/IPrinterDiscoveryObserver.aidl \
 	core/java/android/print/IPrintDocumentAdapter.aidl \
 	core/java/android/print/IPrintDocumentAdapterObserver.aidl \
 	core/java/android/print/IPrintJobStateChangeListener.aidl \
+	core/java/android/print/IPrintServicesChangeListener.aidl \
 	core/java/android/print/IPrintManager.aidl \
 	core/java/android/print/IPrintSpooler.aidl \
 	core/java/android/print/IPrintSpoolerCallbacks.aidl \
@@ -311,6 +314,7 @@
 	core/java/com/android/internal/policy/IKeyguardExitCallback.aidl \
 	core/java/com/android/internal/policy/IKeyguardService.aidl \
 	core/java/com/android/internal/policy/IKeyguardStateCallback.aidl \
+	core/java/com/android/internal/policy/IShortcutService.aidl \
 	core/java/com/android/internal/os/IDropBoxManagerService.aidl \
 	core/java/com/android/internal/os/IParcelFileDescriptorFactory.aidl \
 	core/java/com/android/internal/os/IResultReceiver.aidl \
@@ -454,6 +458,10 @@
       $(FRAMEWORKS_BASE_JAVA_SRC_DIRS) \
       frameworks/native/aidl/binder
 
+LOCAL_AIDL_INCLUDES += \
+	frameworks/av/camera/aidl \
+	frameworks/native/aidl/gui
+
 LOCAL_INTERMEDIATE_SOURCES := \
 			$(framework_res_source_path)/android/R.java \
 			$(framework_res_source_path)/android/Manifest.java \
@@ -576,7 +584,7 @@
 	frameworks/base/core/java/android/view/Display.aidl \
 	frameworks/base/core/java/android/view/InputDevice.aidl \
 	frameworks/base/core/java/android/view/InputEvent.aidl \
-	frameworks/base/core/java/android/view/Surface.aidl \
+	frameworks/native/aidl/gui/android/view/Surface.aidl \
 	frameworks/base/core/java/android/view/WindowContentFrameStats.aidl \
 	frameworks/base/core/java/android/view/inputmethod/InputMethodSubtype.aidl \
 	frameworks/base/core/java/android/view/inputmethod/CursorAnchorInfo.aidl \
@@ -645,6 +653,7 @@
 	frameworks/base/core/java/android/content/pm/ProviderInfo.aidl \
 	frameworks/base/core/java/android/content/pm/PackageStats.aidl \
 	frameworks/base/core/java/android/content/pm/PermissionGroupInfo.aidl \
+	frameworks/base/core/java/android/content/pm/ShortcutInfo.aidl \
 	frameworks/base/core/java/android/content/pm/LabeledIntent.aidl \
 	frameworks/base/core/java/android/content/ComponentName.aidl \
 	frameworks/base/core/java/android/content/SyncStats.aidl \
@@ -818,6 +827,7 @@
     -since $(SRC_API_DIR)/21.txt 21 \
     -since $(SRC_API_DIR)/22.txt 22 \
     -since $(SRC_API_DIR)/23.txt 23 \
+    -since ./frameworks/base/api/current.txt N \
 		-werror -hide 111 -hide 113 \
 		-overview $(LOCAL_PATH)/core/java/overview.html
 
@@ -861,9 +871,11 @@
 framework_docs_SDK_REL_ID:=1
 
 framework_docs_LOCAL_DROIDDOC_OPTIONS += \
+		-hdf sdk.codename N \
+		-hdf sdk.preview.version 2 \
 		-hdf sdk.version $(framework_docs_SDK_VERSION) \
 		-hdf sdk.rel.id $(framework_docs_SDK_REL_ID) \
-		-hdf sdk.preview 0
+		-hdf sdk.preview 1
 
 # ====  the api stubs and current.xml ===========================
 include $(CLEAR_VARS)
@@ -1018,23 +1030,24 @@
 		-offlinemode \
 		-title "Android SDK" \
 		-proofread $(OUT_DOCS)/$(LOCAL_MODULE)-proofread.txt \
-		-todo $(OUT_DOCS)/$(LOCAL_MODULE)-docs-todo.html \
 		-sdkvalues $(OUT_DOCS) \
-		-hdf android.whichdoc offline
+		-hdf android.whichdoc offline \
+		-referenceonly
 
-LOCAL_DROIDDOC_CUSTOM_TEMPLATE_DIR:=build/tools/droiddoc/templates-sdk
+LOCAL_DROIDDOC_CUSTOM_TEMPLATE_DIR:=build/tools/droiddoc/templates-sdk-refonly
 
 include $(BUILD_DROIDDOC)
 
 static_doc_index_redirect := $(out_dir)/index.html
 $(static_doc_index_redirect): \
-	$(LOCAL_PATH)/docs/docs-documentation-redirect.html | $(ACP)
+	$(LOCAL_PATH)/docs/docs-preview-index.html | $(ACP)
 	$(hide) mkdir -p $(dir $@)
 	$(hide) $(ACP) $< $@
 
 $(full_target): $(static_doc_index_redirect)
 $(full_target): $(framework_built)
 
+
 # ==== docs for the web (on the androiddevdocs app engine server) =======================
 include $(CLEAR_VARS)
 
diff --git a/CleanSpec.mk b/CleanSpec.mk
index 2fe5cbe..cee8fdb 100644
--- a/CleanSpec.mk
+++ b/CleanSpec.mk
@@ -240,6 +240,7 @@
 $(call add-clean-step, rm -f $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework_intermediates/src/media/java/android/media/IRemoteControlDisplay.*)
 $(call add-clean-step, rm -f $(OUT_DIR)/target/common/obj/APPS/FeatureSplit1_intermediates/src/com/android/test/split/feature/R.java)
 $(call add-clean-step, rm -f $(OUT_DIR)/target/common/obj/APPS/FeatureSplit2_intermediates/src/com/android/test/split/feature/R.java)
+$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework_intermediates/src/core/java/android/hardware)
 
 # ******************************************************************
 # NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST ABOVE THIS BANNER
diff --git a/api/current.txt b/api/current.txt
index 3245c0a..e253ae1 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -38,6 +38,7 @@
     field public static final java.lang.String BIND_TV_INPUT = "android.permission.BIND_TV_INPUT";
     field public static final java.lang.String BIND_VOICE_INTERACTION = "android.permission.BIND_VOICE_INTERACTION";
     field public static final java.lang.String BIND_VPN_SERVICE = "android.permission.BIND_VPN_SERVICE";
+    field public static final java.lang.String BIND_VR_LISTENER_SERVICE = "android.permission.BIND_VR_LISTENER_SERVICE";
     field public static final java.lang.String BIND_WALLPAPER = "android.permission.BIND_WALLPAPER";
     field public static final java.lang.String BLUETOOTH = "android.permission.BLUETOOTH";
     field public static final java.lang.String BLUETOOTH_ADMIN = "android.permission.BLUETOOTH_ADMIN";
@@ -101,7 +102,6 @@
     field public static final java.lang.String READ_SYNC_SETTINGS = "android.permission.READ_SYNC_SETTINGS";
     field public static final java.lang.String READ_SYNC_STATS = "android.permission.READ_SYNC_STATS";
     field public static final java.lang.String READ_VOICEMAIL = "com.android.voicemail.permission.READ_VOICEMAIL";
-    field public static final java.lang.String READ_WRITE_CONTACT_METADATA = "android.permission.READ_WRITE_CONTACT_METADATA";
     field public static final java.lang.String REBOOT = "android.permission.REBOOT";
     field public static final java.lang.String RECEIVE_BOOT_COMPLETED = "android.permission.RECEIVE_BOOT_COMPLETED";
     field public static final java.lang.String RECEIVE_EMERGENCY_BROADCAST = "android.permission.RECEIVE_EMERGENCY_BROADCAST";
@@ -115,6 +115,7 @@
     field public static final deprecated java.lang.String RESTART_PACKAGES = "android.permission.RESTART_PACKAGES";
     field public static final java.lang.String SEND_RESPOND_VIA_MESSAGE = "android.permission.SEND_RESPOND_VIA_MESSAGE";
     field public static final java.lang.String SEND_SMS = "android.permission.SEND_SMS";
+    field public static final java.lang.String SEND_SMS_NO_CONFIRMATION = "android.permission.SEND_SMS_NO_CONFIRMATION";
     field public static final java.lang.String SET_ALARM = "com.android.alarm.permission.SET_ALARM";
     field public static final java.lang.String SET_ALWAYS_FINISH = "android.permission.SET_ALWAYS_FINISH";
     field public static final java.lang.String SET_ANIMATION_SCALE = "android.permission.SET_ANIMATION_SCALE";
@@ -878,6 +879,7 @@
     field public static final int nextFocusLeft = 16842977; // 0x10100e1
     field public static final int nextFocusRight = 16842978; // 0x10100e2
     field public static final int nextFocusUp = 16842979; // 0x10100e3
+    field public static final int nfcAntennaPositionDrawable = 16844063; // 0x101051f
     field public static final int noHistory = 16843309; // 0x101022d
     field public static final int normalScreens = 16843397; // 0x1010285
     field public static final int notificationTimeout = 16843651; // 0x1010383
@@ -2669,6 +2671,8 @@
     field public static final int GLOBAL_ACTION_TOGGLE_SPLIT_SCREEN = 7; // 0x7
     field public static final java.lang.String SERVICE_INTERFACE = "android.accessibilityservice.AccessibilityService";
     field public static final java.lang.String SERVICE_META_DATA = "android.accessibilityservice";
+    field public static final int SHOW_MODE_AUTO = 0; // 0x0
+    field public static final int SHOW_MODE_HIDDEN = 1; // 0x1
   }
 
   public static abstract class AccessibilityService.GestureResultCallback {
@@ -3603,7 +3607,7 @@
     method public deprecated void setTitleColor(int);
     method public void setVisible(boolean);
     method public final void setVolumeControlStream(int);
-    method public void setVrMode(boolean);
+    method public void setVrModeEnabled(boolean, android.content.ComponentName) throws android.content.pm.PackageManager.NameNotFoundException;
     method public boolean shouldShowRequestPermissionRationale(java.lang.String);
     method public boolean shouldUpRecreateTask(android.content.Intent);
     method public boolean showAssist(android.os.Bundle);
@@ -4127,13 +4131,12 @@
     field public java.lang.String serviceDetails;
   }
 
-  public class AutomaticZenRule implements android.os.Parcelable {
+  public final class AutomaticZenRule implements android.os.Parcelable {
     ctor public AutomaticZenRule(java.lang.String, android.content.ComponentName, android.net.Uri, int, boolean);
     ctor public AutomaticZenRule(android.os.Parcel);
     method public int describeContents();
     method public android.net.Uri getConditionId();
     method public long getCreationTime();
-    method public java.lang.String getId();
     method public int getInterruptionFilter();
     method public java.lang.String getName();
     method public android.content.ComponentName getOwner();
@@ -4908,6 +4911,7 @@
     field public static final int DEFAULT_VIBRATE = 2; // 0x2
     field public static final java.lang.String EXTRA_BACKGROUND_IMAGE_URI = "android.backgroundImageUri";
     field public static final java.lang.String EXTRA_BIG_TEXT = "android.bigText";
+    field public static final java.lang.String EXTRA_CHRONOMETER_COUNTS_DOWN = "android.chronometerCountsDown";
     field public static final java.lang.String EXTRA_COMPACT_ACTIONS = "android.compactActions";
     field public static final java.lang.String EXTRA_INFO_TEXT = "android.infoText";
     field public static final java.lang.String EXTRA_LARGE_ICON = "android.largeIcon";
@@ -5049,16 +5053,17 @@
     method public android.app.Notification.Builder addExtras(android.os.Bundle);
     method public android.app.Notification.Builder addPerson(java.lang.String);
     method public android.app.Notification build();
+    method public android.widget.RemoteViews createBigContentView();
+    method public android.widget.RemoteViews createContentView();
+    method public android.widget.RemoteViews createHeadsUpContentView();
     method public android.app.Notification.Builder extend(android.app.Notification.Extender);
     method public android.os.Bundle getExtras();
     method public deprecated android.app.Notification getNotification();
-    method public android.widget.RemoteViews makeBigContentView();
-    method public android.widget.RemoteViews makeContentView();
-    method public android.widget.RemoteViews makeHeadsUpContentView();
     method public static android.app.Notification.Builder recoverBuilder(android.content.Context, android.app.Notification);
     method public android.app.Notification.Builder setActions(android.app.Notification.Action...);
     method public android.app.Notification.Builder setAutoCancel(boolean);
     method public android.app.Notification.Builder setCategory(java.lang.String);
+    method public android.app.Notification.Builder setChronometerCountsDown(boolean);
     method public android.app.Notification.Builder setColor(int);
     method public deprecated android.app.Notification.Builder setContent(android.widget.RemoteViews);
     method public android.app.Notification.Builder setContentInfo(java.lang.CharSequence);
@@ -5227,14 +5232,14 @@
   }
 
   public class NotificationManager {
-    method public android.app.AutomaticZenRule addAutomaticZenRule(android.app.AutomaticZenRule);
+    method public java.lang.String addAutomaticZenRule(android.app.AutomaticZenRule);
     method public boolean areNotificationsEnabled();
     method public void cancel(int);
     method public void cancel(java.lang.String, int);
     method public void cancelAll();
     method public android.service.notification.StatusBarNotification[] getActiveNotifications();
     method public android.app.AutomaticZenRule getAutomaticZenRule(java.lang.String);
-    method public java.util.List<android.app.AutomaticZenRule> getAutomaticZenRules();
+    method public java.util.Map<java.lang.String, android.app.AutomaticZenRule> getAutomaticZenRules();
     method public final int getCurrentInterruptionFilter();
     method public int getImportance();
     method public android.app.NotificationManager.Policy getNotificationPolicy();
@@ -5244,7 +5249,7 @@
     method public boolean removeAutomaticZenRule(java.lang.String);
     method public final void setInterruptionFilter(int);
     method public void setNotificationPolicy(android.app.NotificationManager.Policy);
-    method public boolean updateAutomaticZenRule(android.app.AutomaticZenRule);
+    method public boolean updateAutomaticZenRule(java.lang.String, android.app.AutomaticZenRule);
     field public static final java.lang.String ACTION_INTERRUPTION_FILTER_CHANGED = "android.app.action.INTERRUPTION_FILTER_CHANGED";
     field public static final java.lang.String ACTION_NOTIFICATION_POLICY_ACCESS_GRANTED_CHANGED = "android.app.action.NOTIFICATION_POLICY_ACCESS_GRANTED_CHANGED";
     field public static final java.lang.String ACTION_NOTIFICATION_POLICY_CHANGED = "android.app.action.NOTIFICATION_POLICY_CHANGED";
@@ -5256,7 +5261,7 @@
   }
 
   public static class NotificationManager.Policy implements android.os.Parcelable {
-    ctor public deprecated NotificationManager.Policy(int, int, int);
+    ctor public NotificationManager.Policy(int, int, int);
     ctor public NotificationManager.Policy(int, int, int, int);
     method public int describeContents();
     method public static java.lang.String priorityCategoriesToString(int);
@@ -5608,8 +5613,6 @@
     method public void enableCarMode(int);
     method public int getCurrentModeType();
     method public int getNightMode();
-    method public boolean isNightModeLocked();
-    method public boolean isUiModeLocked();
     method public void setNightMode(int);
     field public static java.lang.String ACTION_ENTER_CAR_MODE;
     field public static java.lang.String ACTION_ENTER_DESK_MODE;
@@ -5711,6 +5714,7 @@
 
   public class WallpaperManager {
     method public void clear() throws java.io.IOException;
+    method public void clear(int) throws java.io.IOException;
     method public void clearWallpaperOffsets(android.os.IBinder);
     method public void forgetLoadedWallpaper();
     method public android.graphics.drawable.Drawable getBuiltInDrawable();
@@ -5882,7 +5886,7 @@
     method public android.app.admin.SystemUpdatePolicy getSystemUpdatePolicy();
     method public java.util.List<android.os.PersistableBundle> getTrustAgentConfiguration(android.content.ComponentName, android.content.ComponentName);
     method public android.os.Bundle getUserRestrictions(android.content.ComponentName);
-    method public java.lang.String getWifiMacAddress();
+    method public java.lang.String getWifiMacAddress(android.content.ComponentName);
     method public boolean hasCaCertInstalled(android.content.ComponentName, byte[]);
     method public boolean hasGrantedPolicy(android.content.ComponentName, int);
     method public boolean installCaCert(android.content.ComponentName, byte[]);
@@ -6590,7 +6594,7 @@
     field public static final int TAG_SYNC_SEND_FILE = 210004; // 0x33454
   }
 
-  public static class SecurityLog.SecurityEvent implements android.os.Parcelable {
+  public static final class SecurityLog.SecurityEvent implements android.os.Parcelable {
     method public int describeContents();
     method public java.lang.Object getData();
     method public int getTag();
@@ -7334,15 +7338,6 @@
     field public static final int TYPE_SCO = 2; // 0x2
   }
 
-  public class OobData implements android.os.Parcelable {
-    ctor public OobData();
-    method public int describeContents();
-    method public byte[] getSecurityManagerTk();
-    method public void setSecurityManagerTk(byte[]);
-    method public void writeToParcel(android.os.Parcel, int);
-    field public static final android.os.Parcelable.Creator<android.bluetooth.OobData> CREATOR;
-  }
-
 }
 
 package android.bluetooth.le {
@@ -8146,7 +8141,9 @@
     field public static final java.lang.String RESTRICTIONS_SERVICE = "restrictions";
     field public static final java.lang.String SEARCH_SERVICE = "search";
     field public static final java.lang.String SENSOR_SERVICE = "sensor";
+    field public static final java.lang.String SHORTCUT_SERVICE = "shortcut";
     field public static final java.lang.String STORAGE_SERVICE = "storage";
+    field public static final java.lang.String SYSTEM_HEALTH_SERVICE = "systemhealth";
     field public static final java.lang.String TELECOM_SERVICE = "telecom";
     field public static final java.lang.String TELEPHONY_SERVICE = "phone";
     field public static final java.lang.String TELEPHONY_SUBSCRIPTION_SERVICE = "telephony_subscription_service";
@@ -9330,6 +9327,7 @@
     field public int flags;
     field public int largestWidthLimitDp;
     field public java.lang.String manageSpaceActivityName;
+    field public java.lang.String minSdkVersion;
     field public java.lang.String nativeLibraryDir;
     field public java.lang.String permission;
     field public java.lang.String processName;
@@ -9451,13 +9449,19 @@
   public class LauncherApps {
     method public java.util.List<android.content.pm.LauncherActivityInfo> getActivityList(java.lang.String, android.os.UserHandle);
     method public android.content.pm.ApplicationInfo getApplicationInfo(java.lang.String, int, android.os.UserHandle);
+    method public android.os.ParcelFileDescriptor getShortcutIconFd(android.content.pm.ShortcutInfo, android.os.UserHandle);
+    method public int getShortcutIconResId(android.content.pm.ShortcutInfo, android.os.UserHandle);
+    method public java.util.List<android.content.pm.ShortcutInfo> getShortcutInfo(java.lang.String, java.util.List<java.lang.String>, android.os.UserHandle);
+    method public java.util.List<android.content.pm.ShortcutInfo> getShortcuts(android.content.pm.LauncherApps.ShortcutQuery, android.os.UserHandle);
     method public boolean isActivityEnabled(android.content.ComponentName, android.os.UserHandle);
     method public boolean isPackageEnabled(java.lang.String, android.os.UserHandle);
+    method public void pinShortcuts(java.lang.String, java.util.List<java.lang.String>, android.os.UserHandle);
     method public void registerCallback(android.content.pm.LauncherApps.Callback);
     method public void registerCallback(android.content.pm.LauncherApps.Callback, android.os.Handler);
     method public android.content.pm.LauncherActivityInfo resolveActivity(android.content.Intent, android.os.UserHandle);
     method public void startAppDetailsActivity(android.content.ComponentName, android.os.UserHandle, android.graphics.Rect, android.os.Bundle);
     method public void startMainActivity(android.content.ComponentName, android.os.UserHandle, android.graphics.Rect, android.os.Bundle);
+    method public boolean startShortcut(java.lang.String, java.lang.String, android.graphics.Rect, android.os.Bundle, android.os.UserHandle);
     method public void unregisterCallback(android.content.pm.LauncherApps.Callback);
   }
 
@@ -9470,6 +9474,18 @@
     method public void onPackagesSuspended(java.lang.String[], android.os.UserHandle);
     method public abstract void onPackagesUnavailable(java.lang.String[], android.os.UserHandle, boolean);
     method public void onPackagesUnsuspended(java.lang.String[], android.os.UserHandle);
+    method public void onShortcutsChanged(java.lang.String, java.util.List<android.content.pm.ShortcutInfo>, android.os.UserHandle);
+  }
+
+  public static class LauncherApps.ShortcutQuery {
+    ctor public LauncherApps.ShortcutQuery();
+    method public void setActivity(android.content.ComponentName);
+    method public void setChangedSince(long);
+    method public void setPackage(java.lang.String);
+    method public void setQueryFlags(int);
+    field public static final int FLAG_GET_DYNAMIC = 1; // 0x1
+    field public static final int FLAG_GET_KEY_FIELDS_ONLY = 4; // 0x4
+    field public static final int FLAG_GET_PINNED = 2; // 0x2
   }
 
   public class PackageInfo implements android.os.Parcelable {
@@ -9547,6 +9563,7 @@
     method public java.lang.String[] getNames() throws java.io.IOException;
     method public java.io.InputStream openRead(java.lang.String) throws java.io.IOException;
     method public java.io.OutputStream openWrite(java.lang.String, long, long) throws java.io.IOException;
+    method public void removeSplit(java.lang.String) throws java.io.IOException;
     method public void setStagingProgress(float);
   }
 
@@ -9969,6 +9986,59 @@
     field public java.lang.String permission;
   }
 
+  public class ShortcutInfo implements android.os.Parcelable {
+    method public int describeContents();
+    method public android.content.ComponentName getActivityComponent();
+    method public android.os.PersistableBundle getExtras();
+    method public java.lang.String getId();
+    method public android.content.Intent getIntent();
+    method public long getLastChangedTimestamp();
+    method public java.lang.String getPackageName();
+    method public java.lang.String getTitle();
+    method public int getWeight();
+    method public boolean hasIconFile();
+    method public boolean hasIconResource();
+    method public boolean hasKeyFieldsOnly();
+    method public boolean isDynamic();
+    method public boolean isPinned();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final int CLONE_REMOVE_FOR_CREATOR = 1; // 0x1
+    field public static final int CLONE_REMOVE_FOR_LAUNCHER = 3; // 0x3
+    field public static final int CLONE_REMOVE_NON_KEY_INFO = 4; // 0x4
+    field public static final android.os.Parcelable.Creator<android.content.pm.ShortcutInfo> CREATOR;
+    field public static final int FLAG_DYNAMIC = 1; // 0x1
+    field public static final int FLAG_HAS_ICON_FILE = 8; // 0x8
+    field public static final int FLAG_HAS_ICON_RES = 4; // 0x4
+    field public static final int FLAG_KEY_FIELDS_ONLY = 16; // 0x10
+    field public static final int FLAG_PINNED = 2; // 0x2
+  }
+
+  public static class ShortcutInfo.Builder {
+    ctor public ShortcutInfo.Builder(android.content.Context);
+    method public android.content.pm.ShortcutInfo build();
+    method public android.content.pm.ShortcutInfo.Builder setActivityComponent(android.content.ComponentName);
+    method public android.content.pm.ShortcutInfo.Builder setExtras(android.os.PersistableBundle);
+    method public android.content.pm.ShortcutInfo.Builder setIcon(android.graphics.drawable.Icon);
+    method public android.content.pm.ShortcutInfo.Builder setId(java.lang.String);
+    method public android.content.pm.ShortcutInfo.Builder setIntent(android.content.Intent);
+    method public android.content.pm.ShortcutInfo.Builder setTitle(java.lang.String);
+    method public android.content.pm.ShortcutInfo.Builder setWeight(int);
+  }
+
+  public class ShortcutManager {
+    method public boolean addDynamicShortcut(android.content.pm.ShortcutInfo);
+    method public void deleteAllDynamicShortcuts();
+    method public void deleteDynamicShortcut(java.lang.String);
+    method public java.util.List<android.content.pm.ShortcutInfo> getDynamicShortcuts();
+    method public int getIconMaxDimensions();
+    method public int getMaxDynamicShortcutCount();
+    method public java.util.List<android.content.pm.ShortcutInfo> getPinnedShortcuts();
+    method public long getRateLimitResetTime();
+    method public int getRemainingCallCount();
+    method public boolean setDynamicShortcuts(java.util.List<android.content.pm.ShortcutInfo>);
+    method public boolean updateShortcuts(java.util.List<android.content.pm.ShortcutInfo>);
+  }
+
   public class Signature implements android.os.Parcelable {
     ctor public Signature(byte[]);
     ctor public Signature(java.lang.String);
@@ -10474,7 +10544,6 @@
     method public boolean hasNext();
     method public java.util.Iterator<android.database.CursorJoiner.Result> iterator();
     method public android.database.CursorJoiner.Result next();
-    method public void remove();
   }
 
   public static final class CursorJoiner.Result extends java.lang.Enum {
@@ -12845,7 +12914,8 @@
     method public int getGradientType();
     method public int getOpacity();
     method public android.graphics.drawable.GradientDrawable.Orientation getOrientation();
-    method public boolean isUseLevel();
+    method public int getShape();
+    method public boolean getUseLevel();
     method public void setAlpha(int);
     method public void setColor(int);
     method public void setColor(android.content.res.ColorStateList);
@@ -13707,6 +13777,7 @@
 
   public static abstract class CameraCaptureSession.CaptureCallback {
     ctor public CameraCaptureSession.CaptureCallback();
+    method public void onCaptureBufferLost(android.hardware.camera2.CameraCaptureSession, android.hardware.camera2.CaptureRequest, android.view.Surface, long);
     method public void onCaptureCompleted(android.hardware.camera2.CameraCaptureSession, android.hardware.camera2.CaptureRequest, android.hardware.camera2.TotalCaptureResult);
     method public void onCaptureFailed(android.hardware.camera2.CameraCaptureSession, android.hardware.camera2.CaptureRequest, android.hardware.camera2.CaptureFailure);
     method public void onCaptureProgressed(android.hardware.camera2.CameraCaptureSession, android.hardware.camera2.CaptureRequest, android.hardware.camera2.CaptureResult);
@@ -19164,168 +19235,67 @@
 
   public final class GnssClock implements android.os.Parcelable {
     method public int describeContents();
-    method public double getBiasInNs();
-    method public double getBiasUncertaintyInNs();
-    method public double getDriftInNsPerSec();
-    method public double getDriftUncertaintyInNsPerSec();
-    method public long getFullBiasInNs();
+    method public double getBiasNanos();
+    method public double getBiasUncertaintyNanos();
+    method public double getDriftNanosPerSecond();
+    method public double getDriftUncertaintyNanosPerSecond();
+    method public long getFullBiasNanos();
     method public int getHardwareClockDiscontinuityCount();
-    method public short getLeapSecond();
-    method public long getTimeInNs();
-    method public double getTimeUncertaintyInNs();
-    method public boolean hasBiasInNs();
-    method public boolean hasBiasUncertaintyInNs();
-    method public boolean hasDriftInNsPerSec();
-    method public boolean hasDriftUncertaintyInNsPerSec();
-    method public boolean hasFullBiasInNs();
+    method public int getLeapSecond();
+    method public long getTimeNanos();
+    method public double getTimeUncertaintyNanos();
+    method public boolean hasBiasNanos();
+    method public boolean hasBiasUncertaintyNanos();
+    method public boolean hasDriftNanosPerSecond();
+    method public boolean hasDriftUncertaintyNanosPerSecond();
+    method public boolean hasFullBiasNanos();
     method public boolean hasLeapSecond();
-    method public boolean hasTimeUncertaintyInNs();
-    method public void reset();
-    method public void resetBiasInNs();
-    method public void resetBiasUncertaintyInNs();
-    method public void resetDriftInNsPerSec();
-    method public void resetDriftUncertaintyInNsPerSec();
-    method public void resetFullBiasInNs();
-    method public void resetLeapSecond();
-    method public void resetTimeUncertaintyInNs();
-    method public void set(android.location.GnssClock);
-    method public void setBiasInNs(double);
-    method public void setBiasUncertaintyInNs(double);
-    method public void setDriftInNsPerSec(double);
-    method public void setDriftUncertaintyInNsPerSec(double);
-    method public void setFullBiasInNs(long);
-    method public void setHardwareClockDiscontinuityCount(int);
-    method public void setLeapSecond(short);
-    method public void setTimeInNs(long);
-    method public void setTimeUncertaintyInNs(double);
+    method public boolean hasTimeUncertaintyNanos();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.location.GnssClock> CREATOR;
   }
 
   public final class GnssMeasurement implements android.os.Parcelable {
     method public int describeContents();
-    method public double getAccumulatedDeltaRangeInMeters();
-    method public short getAccumulatedDeltaRangeState();
-    method public double getAccumulatedDeltaRangeUncertaintyInMeters();
-    method public double getAzimuthInDeg();
-    method public double getAzimuthUncertaintyInDeg();
-    method public int getBitNumber();
+    method public double getAccumulatedDeltaRangeMeters();
+    method public int getAccumulatedDeltaRangeState();
+    method public double getAccumulatedDeltaRangeUncertaintyMeters();
     method public long getCarrierCycles();
-    method public float getCarrierFrequencyInHz();
+    method public float getCarrierFrequencyHz();
     method public double getCarrierPhase();
     method public double getCarrierPhaseUncertainty();
-    method public double getCn0InDbHz();
-    method public double getCodePhaseInChips();
-    method public double getCodePhaseUncertaintyInChips();
-    method public byte getConstellationType();
-    method public double getDopplerShiftInHz();
-    method public double getDopplerShiftUncertaintyInHz();
-    method public double getElevationInDeg();
-    method public double getElevationUncertaintyInDeg();
-    method public byte getLossOfLock();
-    method public byte getMultipathIndicator();
-    method public double getPseudorangeInMeters();
-    method public double getPseudorangeRateInMetersPerSec();
-    method public double getPseudorangeRateUncertaintyInMetersPerSec();
-    method public double getPseudorangeUncertaintyInMeters();
-    method public long getReceivedSvTimeInNs();
-    method public long getReceivedSvTimeUncertaintyInNs();
+    method public double getCn0DbHz();
+    method public int getConstellationType();
+    method public int getMultipathIndicator();
+    method public double getPseudorangeRateMetersPerSecond();
+    method public double getPseudorangeRateUncertaintyMetersPerSecond();
+    method public long getReceivedSvTimeNanos();
+    method public long getReceivedSvTimeUncertaintyNanos();
     method public double getSnrInDb();
-    method public short getState();
-    method public short getSvid();
-    method public short getTimeFromLastBitInMs();
-    method public double getTimeOffsetInNs();
-    method public boolean hasAzimuthInDeg();
-    method public boolean hasAzimuthUncertaintyInDeg();
-    method public boolean hasBitNumber();
+    method public int getState();
+    method public int getSvid();
+    method public double getTimeOffsetNanos();
     method public boolean hasCarrierCycles();
-    method public boolean hasCarrierFrequencyInHz();
+    method public boolean hasCarrierFrequencyHz();
     method public boolean hasCarrierPhase();
     method public boolean hasCarrierPhaseUncertainty();
-    method public boolean hasCodePhaseInChips();
-    method public boolean hasCodePhaseUncertaintyInChips();
-    method public boolean hasDopplerShiftInHz();
-    method public boolean hasDopplerShiftUncertaintyInHz();
-    method public boolean hasElevationInDeg();
-    method public boolean hasElevationUncertaintyInDeg();
-    method public boolean hasPseudorangeInMeters();
-    method public boolean hasPseudorangeUncertaintyInMeters();
     method public boolean hasSnrInDb();
-    method public boolean hasTimeFromLastBitInMs();
     method public boolean isPseudorangeRateCorrected();
-    method public boolean isUsedInFix();
-    method public void reset();
-    method public void resetAzimuthInDeg();
-    method public void resetAzimuthUncertaintyInDeg();
-    method public void resetBitNumber();
-    method public void resetCarrierCycles();
-    method public void resetCarrierFrequencyInHz();
-    method public void resetCarrierPhase();
-    method public void resetCarrierPhaseUncertainty();
-    method public void resetCodePhaseInChips();
-    method public void resetCodePhaseUncertaintyInChips();
-    method public void resetDopplerShiftInHz();
-    method public void resetDopplerShiftUncertaintyInHz();
-    method public void resetElevationInDeg();
-    method public void resetElevationUncertaintyInDeg();
-    method public void resetPseudorangeInMeters();
-    method public void resetPseudorangeUncertaintyInMeters();
-    method public void resetSnrInDb();
-    method public void resetTimeFromLastBitInMs();
-    method public void set(android.location.GnssMeasurement);
-    method public void setAccumulatedDeltaRangeInMeters(double);
-    method public void setAccumulatedDeltaRangeState(short);
-    method public void setAccumulatedDeltaRangeUncertaintyInMeters(double);
-    method public void setAzimuthInDeg(double);
-    method public void setAzimuthUncertaintyInDeg(double);
-    method public void setBitNumber(int);
-    method public void setCarrierCycles(long);
-    method public void setCarrierFrequencyInHz(float);
-    method public void setCarrierPhase(double);
-    method public void setCarrierPhaseUncertainty(double);
-    method public void setCn0InDbHz(double);
-    method public void setCodePhaseInChips(double);
-    method public void setCodePhaseUncertaintyInChips(double);
-    method public void setConstellationType(byte);
-    method public void setDopplerShiftInHz(double);
-    method public void setDopplerShiftUncertaintyInHz(double);
-    method public void setElevationInDeg(double);
-    method public void setElevationUncertaintyInDeg(double);
-    method public void setLossOfLock(byte);
-    method public void setMultipathIndicator(byte);
-    method public void setPseudorangeInMeters(double);
-    method public void setPseudorangeRateInMetersPerSec(double);
-    method public void setPseudorangeRateUncertaintyInMetersPerSec(double);
-    method public void setPseudorangeUncertaintyInMeters(double);
-    method public void setReceivedSvTimeInNs(long);
-    method public void setReceivedSvTimeUncertaintyInNs(long);
-    method public void setSnrInDb(double);
-    method public void setState(short);
-    method public void setSvid(short);
-    method public void setTimeFromLastBitInMs(short);
-    method public void setTimeOffsetInNs(double);
-    method public void setUsedInFix(boolean);
     method public void writeToParcel(android.os.Parcel, int);
-    field public static final short ADR_STATE_CYCLE_SLIP = 4; // 0x4
-    field public static final short ADR_STATE_RESET = 2; // 0x2
-    field public static final short ADR_STATE_UNKNOWN = 0; // 0x0
-    field public static final short ADR_STATE_VALID = 1; // 0x1
+    field public static final int ADR_STATE_CYCLE_SLIP = 4; // 0x4
+    field public static final int ADR_STATE_RESET = 2; // 0x2
+    field public static final int ADR_STATE_UNKNOWN = 0; // 0x0
+    field public static final int ADR_STATE_VALID = 1; // 0x1
     field public static final android.os.Parcelable.Creator<android.location.GnssMeasurement> CREATOR;
-    field public static final byte LOSS_OF_LOCK_CYCLE_SLIP = 2; // 0x2
-    field public static final byte LOSS_OF_LOCK_OK = 1; // 0x1
-    field public static final byte LOSS_OF_LOCK_UNKNOWN = 0; // 0x0
-    field public static final byte MULTIPATH_INDICATOR_DETECTED = 1; // 0x1
-    field public static final byte MULTIPATH_INDICATOR_NOT_USED = 2; // 0x2
-    field public static final byte MULTIPATH_INDICATOR_UNKNOWN = 0; // 0x0
-    field public static final short STATE_BIT_SYNC = 2; // 0x2
-    field public static final short STATE_CODE_LOCK = 1; // 0x1
-    field public static final short STATE_MSEC_AMBIGUOUS = 16; // 0x10
-    field public static final short STATE_SUBFRAME_SYNC = 4; // 0x4
-    field public static final short STATE_TOW_DECODED = 8; // 0x8
-    field public static final short STATE_UNKNOWN = 0; // 0x0
-  }
-
-  public static abstract class GnssMeasurement.LossOfLockStatus implements java.lang.annotation.Annotation {
+    field public static final int MULTIPATH_INDICATOR_DETECTED = 1; // 0x1
+    field public static final int MULTIPATH_INDICATOR_NOT_USED = 2; // 0x2
+    field public static final int MULTIPATH_INDICATOR_UNKNOWN = 0; // 0x0
+    field public static final int STATE_BIT_SYNC = 2; // 0x2
+    field public static final int STATE_CODE_LOCK = 1; // 0x1
+    field public static final int STATE_MSEC_AMBIGUOUS = 16; // 0x10
+    field public static final int STATE_SUBFRAME_SYNC = 4; // 0x4
+    field public static final int STATE_TOW_DECODED = 8; // 0x8
+    field public static final int STATE_UNKNOWN = 0; // 0x0
   }
 
   public static abstract class GnssMeasurement.MultipathIndicator implements java.lang.annotation.Annotation {
@@ -19338,7 +19308,7 @@
     method public java.util.Collection<android.location.GnssMeasurement> getMeasurements();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.location.GnssMeasurementsEvent> CREATOR;
-    field public static final int STATUS_GPS_LOCATION_DISABLED = 2; // 0x2
+    field public static final int STATUS_GNSS_LOCATION_DISABLED = 2; // 0x2
     field public static final int STATUS_NOT_SUPPORTED = 0; // 0x0
     field public static final int STATUS_READY = 1; // 0x1
   }
@@ -19355,34 +19325,26 @@
   public final class GnssNavigationMessage implements android.os.Parcelable {
     method public int describeContents();
     method public byte[] getData();
-    method public short getMessageId();
-    method public short getStatus();
-    method public short getSubmessageId();
-    method public short getSvid();
-    method public short getType();
-    method public void reset();
-    method public void set(android.location.GnssNavigationMessage);
-    method public void setData(byte[]);
-    method public void setMessageId(short);
-    method public void setStatus(short);
-    method public void setSubmessageId(short);
-    method public void setSvid(short);
-    method public void setType(short);
+    method public int getMessageId();
+    method public int getStatus();
+    method public int getSubmessageId();
+    method public int getSvid();
+    method public int getType();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.location.GnssNavigationMessage> CREATOR;
-    field public static final short MESSAGE_TYPE_BDS_D1 = 1281; // 0x501
-    field public static final short MESSAGE_TYPE_BDS_D2 = 1282; // 0x502
-    field public static final short MESSAGE_TYPE_GAL_F = 1538; // 0x602
-    field public static final short MESSAGE_TYPE_GAL_I = 1537; // 0x601
-    field public static final short MESSAGE_TYPE_GLO_L1CA = 769; // 0x301
-    field public static final short MESSAGE_TYPE_GPS_CNAV2 = 260; // 0x104
-    field public static final short MESSAGE_TYPE_GPS_L1CA = 257; // 0x101
-    field public static final short MESSAGE_TYPE_GPS_L2CNAV = 258; // 0x102
-    field public static final short MESSAGE_TYPE_GPS_L5CNAV = 259; // 0x103
-    field public static final short MESSAGE_TYPE_UNKNOWN = 0; // 0x0
-    field public static final short STATUS_PARITY_PASSED = 1; // 0x1
-    field public static final short STATUS_PARITY_REBUILT = 2; // 0x2
-    field public static final short STATUS_UNKNOWN = 0; // 0x0
+    field public static final int STATUS_PARITY_PASSED = 1; // 0x1
+    field public static final int STATUS_PARITY_REBUILT = 2; // 0x2
+    field public static final int STATUS_UNKNOWN = 0; // 0x0
+    field public static final int TYPE_BDS_D1 = 1281; // 0x501
+    field public static final int TYPE_BDS_D2 = 1282; // 0x502
+    field public static final int TYPE_GAL_F = 1538; // 0x602
+    field public static final int TYPE_GAL_I = 1537; // 0x601
+    field public static final int TYPE_GLO_L1CA = 769; // 0x301
+    field public static final int TYPE_GPS_CNAV2 = 260; // 0x104
+    field public static final int TYPE_GPS_L1CA = 257; // 0x101
+    field public static final int TYPE_GPS_L2CNAV = 258; // 0x102
+    field public static final int TYPE_GPS_L5CNAV = 259; // 0x103
+    field public static final int TYPE_UNKNOWN = 0; // 0x0
   }
 
   public static abstract class GnssNavigationMessage.GnssNavigationMessageType implements java.lang.annotation.Annotation {
@@ -19394,7 +19356,7 @@
     method public android.location.GnssNavigationMessage getNavigationMessage();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.location.GnssNavigationMessageEvent> CREATOR;
-    field public static final int STATUS_GPS_LOCATION_DISABLED = 2; // 0x2
+    field public static final int STATUS_GNSS_LOCATION_DISABLED = 2; // 0x2
     field public static final int STATUS_NOT_SUPPORTED = 0; // 0x0
     field public static final int STATUS_READY = 1; // 0x1
   }
@@ -19413,22 +19375,22 @@
   }
 
   public final class GnssStatus {
-    method public float getAzimuth(int);
-    method public byte getConstellationType(int);
-    method public float getElevation(int);
+    method public float getAzimuthDegrees(int);
+    method public float getCn0DbHz(int);
+    method public int getConstellationType(int);
+    method public float getElevationDegrees(int);
     method public int getNumSatellites();
-    method public float getSnr(int);
     method public int getSvid(int);
     method public boolean hasAlmanac(int);
     method public boolean hasEphemeris(int);
     method public boolean usedInFix(int);
-    field public static final byte CONSTELLATION_BEIDOU = 5; // 0x5
-    field public static final byte CONSTELLATION_GALILEO = 6; // 0x6
-    field public static final byte CONSTELLATION_GLONASS = 3; // 0x3
-    field public static final byte CONSTELLATION_GPS = 1; // 0x1
-    field public static final byte CONSTELLATION_QZSS = 4; // 0x4
-    field public static final byte CONSTELLATION_SBAS = 2; // 0x2
-    field public static final byte CONSTELLATION_UNKNOWN = 0; // 0x0
+    field public static final int CONSTELLATION_BEIDOU = 5; // 0x5
+    field public static final int CONSTELLATION_GALILEO = 6; // 0x6
+    field public static final int CONSTELLATION_GLONASS = 3; // 0x3
+    field public static final int CONSTELLATION_GPS = 1; // 0x1
+    field public static final int CONSTELLATION_QZSS = 4; // 0x4
+    field public static final int CONSTELLATION_SBAS = 2; // 0x2
+    field public static final int CONSTELLATION_UNKNOWN = 0; // 0x0
   }
 
   public static abstract class GnssStatus.ConstellationType implements java.lang.annotation.Annotation {
@@ -19543,8 +19505,8 @@
     method public java.util.List<java.lang.String> getProviders(boolean);
     method public java.util.List<java.lang.String> getProviders(android.location.Criteria, boolean);
     method public boolean isProviderEnabled(java.lang.String);
-    method public boolean registerGnssMeasurementCallback(android.location.GnssMeasurementsEvent.Callback);
-    method public boolean registerGnssMeasurementCallback(android.location.GnssMeasurementsEvent.Callback, android.os.Handler);
+    method public boolean registerGnssMeasurementsCallback(android.location.GnssMeasurementsEvent.Callback);
+    method public boolean registerGnssMeasurementsCallback(android.location.GnssMeasurementsEvent.Callback, android.os.Handler);
     method public boolean registerGnssNavigationMessageCallback(android.location.GnssNavigationMessageEvent.Callback);
     method public boolean registerGnssNavigationMessageCallback(android.location.GnssNavigationMessageEvent.Callback, android.os.Handler);
     method public boolean registerGnssStatusCallback(android.location.GnssStatusCallback);
@@ -19569,7 +19531,7 @@
     method public void setTestProviderEnabled(java.lang.String, boolean);
     method public void setTestProviderLocation(java.lang.String, android.location.Location);
     method public void setTestProviderStatus(java.lang.String, int, android.os.Bundle, long);
-    method public void unregisterGnssMeasurementCallback(android.location.GnssMeasurementsEvent.Callback);
+    method public void unregisterGnssMeasurementsCallback(android.location.GnssMeasurementsEvent.Callback);
     method public void unregisterGnssNavigationMessageCallback(android.location.GnssNavigationMessageEvent.Callback);
     method public void unregisterGnssStatusCallback(android.location.GnssStatusCallback);
     field public static final java.lang.String GPS_PROVIDER = "gps";
@@ -19707,7 +19669,7 @@
     field public static final int TYPE_WIRED_HEADSET = 3; // 0x3
   }
 
-  public class AudioFormat implements android.os.Parcelable {
+  public final class AudioFormat implements android.os.Parcelable {
     method public int describeContents();
     method public int getChannelCount();
     method public int getChannelIndexMask();
@@ -19787,7 +19749,7 @@
     method public void adjustVolume(int, int);
     method public void dispatchMediaKeyEvent(android.view.KeyEvent);
     method public int generateAudioSessionId();
-    method public android.media.AudioRecordConfiguration[] getActiveRecordConfigurations();
+    method public android.media.AudioRecordingConfiguration[] getActiveRecordingConfigurations();
     method public android.media.AudioDeviceInfo[] getDevices(int);
     method public int getMode();
     method public java.lang.String getParameters(java.lang.String);
@@ -19933,7 +19895,7 @@
 
   public static abstract class AudioManager.AudioRecordingCallback {
     ctor public AudioManager.AudioRecordingCallback();
-    method public void onRecordConfigChanged();
+    method public void onRecordConfigChanged(android.media.AudioRecordingConfiguration[]);
   }
 
   public static abstract interface AudioManager.OnAudioFocusChangeListener {
@@ -20007,7 +19969,7 @@
     method public abstract void onRoutingChanged(android.media.AudioRecord);
   }
 
-  public class AudioRecordConfiguration implements android.os.Parcelable {
+  public final class AudioRecordingConfiguration implements android.os.Parcelable {
     method public int describeContents();
     method public android.media.AudioDeviceInfo getAudioDevice();
     method public int getClientAudioSessionId();
@@ -20015,12 +19977,13 @@
     method public android.media.AudioFormat getClientFormat();
     method public android.media.AudioFormat getFormat();
     method public void writeToParcel(android.os.Parcel, int);
-    field public static final android.os.Parcelable.Creator<android.media.AudioRecordConfiguration> CREATOR;
+    field public static final android.os.Parcelable.Creator<android.media.AudioRecordingConfiguration> CREATOR;
   }
 
   public abstract interface AudioRouting {
     method public abstract void addOnRoutingListener(android.media.AudioRouting.OnRoutingChangedListener, android.os.Handler);
     method public abstract android.media.AudioDeviceInfo getPreferredDevice();
+    method public abstract android.media.AudioDeviceInfo getRoutedDevice();
     method public abstract void removeOnRoutingListener(android.media.AudioRouting.OnRoutingChangedListener);
     method public abstract boolean setPreferredDevice(android.media.AudioDeviceInfo);
   }
@@ -20222,37 +20185,129 @@
     field public static final int ORIENTATION_TRANSVERSE = 7; // 0x7
     field public static final int ORIENTATION_UNDEFINED = 0; // 0x0
     field public static final java.lang.String TAG_APERTURE = "FNumber";
+    field public static final java.lang.String TAG_APERTURE_VALUE = "ApertureValue";
+    field public static final java.lang.String TAG_ARTIST = "Artist";
+    field public static final java.lang.String TAG_BITS_PER_SAMPLE = "BitsPerSample";
+    field public static final java.lang.String TAG_BRIGHTNESS_VALUE = "BrightnessValue";
+    field public static final java.lang.String TAG_CFA_PATTERN = "CFAPattern";
+    field public static final java.lang.String TAG_COLOR_SPACE = "ColorSpace";
+    field public static final java.lang.String TAG_COMPONENTS_CONFIGURATION = "ComponentsConfiguration";
+    field public static final java.lang.String TAG_COMPRESSED_BITS_PER_PIXEL = "CompressedBitsPerPixel";
+    field public static final java.lang.String TAG_COMPRESSION = "Compression";
+    field public static final java.lang.String TAG_CONTRAST = "Contrast";
+    field public static final java.lang.String TAG_COPYRIGHT = "Copyright";
+    field public static final java.lang.String TAG_CUSTOM_RENDERED = "CustomRendered";
     field public static final java.lang.String TAG_DATETIME = "DateTime";
     field public static final java.lang.String TAG_DATETIME_DIGITIZED = "DateTimeDigitized";
+    field public static final java.lang.String TAG_DATETIME_ORIGINAL = "DateTimeOriginal";
+    field public static final java.lang.String TAG_DEVICE_SETTING_DESCRIPTION = "DeviceSettingDescription";
     field public static final java.lang.String TAG_DIGITAL_ZOOM_RATIO = "DigitalZoomRatio";
+    field public static final java.lang.String TAG_EXIF_VERSION = "ExifVersion";
     field public static final java.lang.String TAG_EXPOSURE_BIAS_VALUE = "ExposureBiasValue";
+    field public static final java.lang.String TAG_EXPOSURE_INDEX = "ExposureIndex";
     field public static final java.lang.String TAG_EXPOSURE_MODE = "ExposureMode";
     field public static final java.lang.String TAG_EXPOSURE_PROGRAM = "ExposureProgram";
     field public static final java.lang.String TAG_EXPOSURE_TIME = "ExposureTime";
+    field public static final java.lang.String TAG_FILE_SOURCE = "FileSource";
     field public static final java.lang.String TAG_FLASH = "Flash";
+    field public static final java.lang.String TAG_FLASHPIX_VERSION = "FlashpixVersion";
+    field public static final java.lang.String TAG_FLASH_ENERGY = "FlashEnergy";
     field public static final java.lang.String TAG_FOCAL_LENGTH = "FocalLength";
+    field public static final java.lang.String TAG_FOCAL_LENGTH_IN_35MM_FILM = "FocalLengthIn35mmFilm";
+    field public static final java.lang.String TAG_FOCAL_PLANE_RESOLUTION_UNIT = "FocalPlaneResolutionUnit";
+    field public static final java.lang.String TAG_FOCAL_PLANE_X_RESOLUTION = "FocalPlaneXResolution";
+    field public static final java.lang.String TAG_FOCAL_PLANE_Y_RESOLUTION = "FocalPlaneYResolution";
+    field public static final java.lang.String TAG_F_NUMBER = "FNumber";
+    field public static final java.lang.String TAG_GAIN_CONTROL = "GainControl";
     field public static final java.lang.String TAG_GPS_ALTITUDE = "GPSAltitude";
     field public static final java.lang.String TAG_GPS_ALTITUDE_REF = "GPSAltitudeRef";
+    field public static final java.lang.String TAG_GPS_AREA_INFORMATION = "GPSAreaInformation";
     field public static final java.lang.String TAG_GPS_DATESTAMP = "GPSDateStamp";
+    field public static final java.lang.String TAG_GPS_DEST_BEARING = "GPSDestBearing";
+    field public static final java.lang.String TAG_GPS_DEST_BEARING_REF = "GPSDestBearingRef";
+    field public static final java.lang.String TAG_GPS_DEST_DISTANCE = "GPSDestDistance";
+    field public static final java.lang.String TAG_GPS_DEST_DISTANCE_REF = "GPSDestDistanceRef";
+    field public static final java.lang.String TAG_GPS_DEST_LATITUDE = "GPSDestLatitude";
+    field public static final java.lang.String TAG_GPS_DEST_LATITUDE_REF = "GPSDestLatitudeRef";
+    field public static final java.lang.String TAG_GPS_DEST_LONGITUDE = "GPSDestLongitude";
+    field public static final java.lang.String TAG_GPS_DEST_LONGITUDE_REF = "GPSDestLongitudeRef";
+    field public static final java.lang.String TAG_GPS_DIFFERENTIAL = "GPSDifferential";
+    field public static final java.lang.String TAG_GPS_DOP = "GPSDOP";
+    field public static final java.lang.String TAG_GPS_IMG_DIRECTION = "GPSImgDirection";
+    field public static final java.lang.String TAG_GPS_IMG_DIRECTION_REF = "GPSImgDirectionRef";
     field public static final java.lang.String TAG_GPS_LATITUDE = "GPSLatitude";
     field public static final java.lang.String TAG_GPS_LATITUDE_REF = "GPSLatitudeRef";
     field public static final java.lang.String TAG_GPS_LONGITUDE = "GPSLongitude";
     field public static final java.lang.String TAG_GPS_LONGITUDE_REF = "GPSLongitudeRef";
+    field public static final java.lang.String TAG_GPS_MAP_DATUM = "GPSMapDatum";
+    field public static final java.lang.String TAG_GPS_MEASURE_MODE = "GPSMeasureMode";
     field public static final java.lang.String TAG_GPS_PROCESSING_METHOD = "GPSProcessingMethod";
+    field public static final java.lang.String TAG_GPS_SATELLITES = "GPSSatellites";
+    field public static final java.lang.String TAG_GPS_SPEED = "GPSSpeed";
+    field public static final java.lang.String TAG_GPS_SPEED_REF = "GPSSpeedRef";
+    field public static final java.lang.String TAG_GPS_STATUS = "GPSStatus";
     field public static final java.lang.String TAG_GPS_TIMESTAMP = "GPSTimeStamp";
+    field public static final java.lang.String TAG_GPS_TRACK = "GPSTrack";
+    field public static final java.lang.String TAG_GPS_TRACK_REF = "GPSTrackRef";
+    field public static final java.lang.String TAG_GPS_VERSION_ID = "GPSVersionID";
+    field public static final java.lang.String TAG_IMAGE_DESCRIPTION = "ImageDescription";
     field public static final java.lang.String TAG_IMAGE_LENGTH = "ImageLength";
+    field public static final java.lang.String TAG_IMAGE_UNIQUE_ID = "ImageUniqueID";
     field public static final java.lang.String TAG_IMAGE_WIDTH = "ImageWidth";
+    field public static final java.lang.String TAG_INTEROPERABILITY_INDEX = "InteroperabilityIndex";
     field public static final java.lang.String TAG_ISO = "ISOSpeedRatings";
+    field public static final java.lang.String TAG_ISO_SPEED_RATINGS = "ISOSpeedRatings";
+    field public static final java.lang.String TAG_JPEG_INTERCHANGE_FORMAT = "JPEGInterchangeFormat";
+    field public static final java.lang.String TAG_JPEG_INTERCHANGE_FORMAT_LENGTH = "JPEGInterchangeFormatLength";
     field public static final java.lang.String TAG_LIGHT_SOURCE = "LightSource";
     field public static final java.lang.String TAG_MAKE = "Make";
+    field public static final java.lang.String TAG_MAKER_NOTE = "MakerNote";
+    field public static final java.lang.String TAG_MAX_APERTURE_VALUE = "MaxApertureValue";
     field public static final java.lang.String TAG_METERING_MODE = "MeteringMode";
     field public static final java.lang.String TAG_MODEL = "Model";
+    field public static final java.lang.String TAG_OECF = "OECF";
     field public static final java.lang.String TAG_ORIENTATION = "Orientation";
+    field public static final java.lang.String TAG_PHOTOMETRIC_INTERPRETATION = "PhotometricInterpretation";
+    field public static final java.lang.String TAG_PIXEL_X_DIMENSION = "PixelXDimension";
+    field public static final java.lang.String TAG_PIXEL_Y_DIMENSION = "PixelYDimension";
+    field public static final java.lang.String TAG_PLANAR_CONFIGURATION = "PlanarConfiguration";
+    field public static final java.lang.String TAG_PRIMARY_CHROMATICITIES = "PrimaryChromaticities";
+    field public static final java.lang.String TAG_REFERENCE_BLACK_WHITE = "ReferenceBlackWhite";
+    field public static final java.lang.String TAG_RELATED_SOUND_FILE = "RelatedSoundFile";
+    field public static final java.lang.String TAG_RESOLUTION_UNIT = "ResolutionUnit";
+    field public static final java.lang.String TAG_ROWS_PER_STRIP = "RowsPerStrip";
+    field public static final java.lang.String TAG_SAMPLES_PER_PIXEL = "SamplesPerPixel";
+    field public static final java.lang.String TAG_SATURATION = "Saturation";
+    field public static final java.lang.String TAG_SCENE_CAPTURE_TYPE = "SceneCaptureType";
+    field public static final java.lang.String TAG_SCENE_TYPE = "SceneType";
+    field public static final java.lang.String TAG_SENSING_METHOD = "SensingMethod";
+    field public static final java.lang.String TAG_SHARPNESS = "Sharpness";
+    field public static final java.lang.String TAG_SHUTTER_SPEED_VALUE = "ShutterSpeedValue";
+    field public static final java.lang.String TAG_SOFTWARE = "Software";
+    field public static final java.lang.String TAG_SPATIAL_FREQUENCY_RESPONSE = "SpatialFrequencyResponse";
+    field public static final java.lang.String TAG_SPECTRAL_SENSITIVITY = "SpectralSensitivity";
+    field public static final java.lang.String TAG_STRIP_BYTE_COUNTS = "StripByteCounts";
+    field public static final java.lang.String TAG_STRIP_OFFSETS = "StripOffsets";
+    field public static final java.lang.String TAG_SUBJECT_AREA = "SubjectArea";
     field public static final java.lang.String TAG_SUBJECT_DISTANCE = "SubjectDistance";
+    field public static final java.lang.String TAG_SUBJECT_DISTANCE_RANGE = "SubjectDistanceRange";
+    field public static final java.lang.String TAG_SUBJECT_LOCATION = "SubjectLocation";
     field public static final java.lang.String TAG_SUBSEC_TIME = "SubSecTime";
     field public static final java.lang.String TAG_SUBSEC_TIME_DIG = "SubSecTimeDigitized";
+    field public static final java.lang.String TAG_SUBSEC_TIME_DIGITIZED = "SubSecTimeDigitized";
     field public static final java.lang.String TAG_SUBSEC_TIME_ORIG = "SubSecTimeOriginal";
+    field public static final java.lang.String TAG_SUBSEC_TIME_ORIGINAL = "SubSecTimeOriginal";
+    field public static final java.lang.String TAG_THUMBNAIL_IMAGE_LENGTH = "ThumbnailImageLength";
+    field public static final java.lang.String TAG_THUMBNAIL_IMAGE_WIDTH = "ThumbnailImageWidth";
+    field public static final java.lang.String TAG_TRANSFER_FUNCTION = "TransferFunction";
+    field public static final java.lang.String TAG_USER_COMMENT = "UserComment";
     field public static final java.lang.String TAG_WHITE_BALANCE = "WhiteBalance";
+    field public static final java.lang.String TAG_WHITE_POINT = "WhitePoint";
+    field public static final java.lang.String TAG_X_RESOLUTION = "XResolution";
+    field public static final java.lang.String TAG_Y_CB_CR_COEFFICIENTS = "YCbCrCoefficients";
+    field public static final java.lang.String TAG_Y_CB_CR_POSITIONING = "YCbCrPositioning";
+    field public static final java.lang.String TAG_Y_CB_CR_SUB_SAMPLING = "YCbCrSubSampling";
+    field public static final java.lang.String TAG_Y_RESOLUTION = "YResolution";
     field public static final int WHITEBALANCE_AUTO = 0; // 0x0
     field public static final int WHITEBALANCE_MANUAL = 1; // 0x1
   }
@@ -20450,6 +20505,7 @@
     field public static final int ERROR_NO_KEY = 1; // 0x1
     field public static final int ERROR_RESOURCE_BUSY = 3; // 0x3
     field public static final int ERROR_SESSION_NOT_OPENED = 5; // 0x5
+    field public static final int ERROR_UNSUPPORTED_OPERATION = 6; // 0x6
   }
 
   public static final class MediaCodec.CryptoInfo {
@@ -20658,6 +20714,7 @@
     field public static final int HEVCMainTierLevel62 = 16777216; // 0x1000000
     field public static final int HEVCProfileMain = 1; // 0x1
     field public static final int HEVCProfileMain10 = 2; // 0x2
+    field public static final int HEVCProfileMain10HDR10 = 4096; // 0x1000
     field public static final int MPEG2LevelH14 = 2; // 0x2
     field public static final int MPEG2LevelHL = 3; // 0x3
     field public static final int MPEG2LevelLL = 0; // 0x0
@@ -20915,6 +20972,7 @@
     method public final void setDataSource(android.content.Context, android.net.Uri, java.util.Map<java.lang.String, java.lang.String>) throws java.io.IOException;
     method public final void setDataSource(java.lang.String, java.util.Map<java.lang.String, java.lang.String>) throws java.io.IOException;
     method public final void setDataSource(java.lang.String) throws java.io.IOException;
+    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 void unselectTrack(int);
@@ -20975,6 +21033,7 @@
     field public static final java.lang.String KEY_DURATION = "durationUs";
     field public static final java.lang.String KEY_FLAC_COMPRESSION_LEVEL = "flac-compression-level";
     field public static final java.lang.String KEY_FRAME_RATE = "frame-rate";
+    field public static final java.lang.String KEY_HDR_STATIC_INFO = "hdr-static-info";
     field public static final java.lang.String KEY_HEIGHT = "height";
     field public static final java.lang.String KEY_INTRA_REFRESH_PERIOD = "intra-refresh-period";
     field public static final java.lang.String KEY_IS_ADTS = "is-adts";
@@ -20999,6 +21058,7 @@
     field public static final java.lang.String KEY_SLICE_HEIGHT = "slice-height";
     field public static final java.lang.String KEY_STRIDE = "stride";
     field public static final java.lang.String KEY_TEMPORAL_LAYERING = "ts-schema";
+    field public static final java.lang.String KEY_TRACK_ID = "track-id";
     field public static final java.lang.String KEY_WIDTH = "width";
     field public static final java.lang.String MIMETYPE_AUDIO_AAC = "audio/mp4a-latm";
     field public static final java.lang.String MIMETYPE_AUDIO_AC3 = "audio/ac3";
@@ -22974,7 +23034,7 @@
   }
 
   public static final class TvInputInfo.Builder {
-    ctor public TvInputInfo.Builder(android.content.Context, java.lang.Class<?>);
+    ctor public TvInputInfo.Builder(android.content.Context, android.content.ComponentName);
     method public android.media.tv.TvInputInfo build() throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
     method public android.media.tv.TvInputInfo.Builder setCanRecord(boolean);
     method public android.media.tv.TvInputInfo.Builder setTunerCount(int);
@@ -23042,7 +23102,7 @@
     ctor public TvInputService.RecordingSession(android.content.Context);
     method public void notifyError(int);
     method public void notifyRecordingStopped(android.net.Uri);
-    method public void notifyTuned();
+    method public void notifyTuned(android.net.Uri);
     method public abstract void onRelease();
     method public abstract void onStartRecording(android.net.Uri);
     method public abstract void onStopRecording();
@@ -23083,6 +23143,7 @@
     method public boolean onTouchEvent(android.view.MotionEvent);
     method public boolean onTrackballEvent(android.view.MotionEvent);
     method public abstract boolean onTune(android.net.Uri);
+    method public boolean onTune(android.net.Uri, android.os.Bundle);
     method public void onUnblockContent(android.media.tv.TvContentRating);
     method public void setOverlayViewEnabled(boolean);
   }
@@ -23101,7 +23162,7 @@
     method public void onDisconnected(java.lang.String);
     method public void onError(int);
     method public void onRecordingStopped(android.net.Uri);
-    method public void onTuned();
+    method public void onTuned(android.net.Uri);
   }
 
   public final class TvTrackInfo implements android.os.Parcelable {
@@ -23156,12 +23217,15 @@
     method public void setOnUnhandledInputEventListener(android.media.tv.TvView.OnUnhandledInputEventListener);
     method public void setStreamVolume(float);
     method public void setTimeShiftPositionCallback(android.media.tv.TvView.TimeShiftPositionCallback);
+    method public void setZOrderMediaOverlay(boolean);
+    method public void setZOrderOnTop(boolean);
     method public void timeShiftPause();
     method public void timeShiftPlay(java.lang.String, android.net.Uri);
     method public void timeShiftResume();
     method public void timeShiftSeekTo(long);
     method public void timeShiftSetPlaybackParams(android.media.PlaybackParams);
     method public void tune(java.lang.String, android.net.Uri);
+    method public void tune(java.lang.String, android.net.Uri, android.os.Bundle);
   }
 
   public static abstract interface TvView.OnUnhandledInputEventListener {
@@ -23521,17 +23585,6 @@
     method public abstract void onNetworkActive();
   }
 
-  public 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 class Credentials {
     ctor public Credentials(int, int, int);
     method public int getGid();
@@ -23539,7 +23592,7 @@
     method public int getUid();
   }
 
-  public class DataUsageRequest implements android.os.Parcelable {
+  public final class DataUsageRequest 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.DataUsageRequest> CREATOR;
@@ -26857,7 +26910,8 @@
     method public static void glGetSynciv(long, int, int, int[], int, int[], int);
     method public static void glGetSynciv(long, int, int, java.nio.IntBuffer, java.nio.IntBuffer);
     method public static void glGetTransformFeedbackVarying(int, int, int, int[], int, int[], int, int[], int, byte[], int);
-    method public static void glGetTransformFeedbackVarying(int, int, int, java.nio.IntBuffer, java.nio.IntBuffer, java.nio.IntBuffer, byte);
+    method public static deprecated void glGetTransformFeedbackVarying(int, int, int, java.nio.IntBuffer, java.nio.IntBuffer, java.nio.IntBuffer, byte);
+    method public static void glGetTransformFeedbackVarying(int, int, int, java.nio.IntBuffer, java.nio.IntBuffer, java.nio.IntBuffer, java.nio.ByteBuffer);
     method public static java.lang.String glGetTransformFeedbackVarying(int, int, int[], int, int[], int);
     method public static java.lang.String glGetTransformFeedbackVarying(int, int, java.nio.IntBuffer, java.nio.IntBuffer);
     method public static int glGetUniformBlockIndex(int, java.lang.String);
@@ -28469,6 +28523,10 @@
     ctor public DeadObjectException(java.lang.String);
   }
 
+  public class DeadSystemException extends android.os.DeadObjectException {
+    ctor public DeadSystemException();
+  }
+
   public final class Debug {
     method public static deprecated void changeDebugPort(int);
     method public static void dumpHprofData(java.lang.String) throws java.io.IOException;
@@ -29116,7 +29174,10 @@
   public class Process {
     ctor public Process();
     method public static final long getElapsedCpuTime();
+    method public static final int[] getExclusiveCores();
     method public static final int getGidForName(java.lang.String);
+    method public static final long getStartElapsedRealtime();
+    method public static final long getStartUptimeMillis();
     method public static final int getThreadPriority(int) throws java.lang.IllegalArgumentException;
     method public static final int getUidForName(java.lang.String);
     method public static final boolean is64Bit();
@@ -29398,6 +29459,147 @@
 
 }
 
+package android.os.health {
+
+  public class HealthStats {
+    method public java.lang.String getDataType();
+    method public long getMeasurement(int);
+    method public int getMeasurementKeyAt(int);
+    method public int getMeasurementKeyCount();
+    method public java.util.Map<java.lang.String, java.lang.Long> getMeasurements(int);
+    method public int getMeasurementsKeyAt(int);
+    method public int getMeasurementsKeyCount();
+    method public java.util.Map<java.lang.String, android.os.health.HealthStats> getStats(int);
+    method public int getStatsKeyAt(int);
+    method public int getStatsKeyCount();
+    method public android.os.health.TimerStat getTimer(int);
+    method public int getTimerCount(int);
+    method public int getTimerKeyAt(int);
+    method public int getTimerKeyCount();
+    method public long getTimerTime(int);
+    method public java.util.Map<java.lang.String, android.os.health.TimerStat> getTimers(int);
+    method public int getTimersKeyAt(int);
+    method public int getTimersKeyCount();
+    method public boolean hasMeasurement(int);
+    method public boolean hasMeasurements(int);
+    method public boolean hasStats(int);
+    method public boolean hasTimer(int);
+    method public boolean hasTimers(int);
+  }
+
+  public final class PackageHealthStats {
+    field public static final int MEASUREMENTS_WAKEUP_ALARMS_COUNT = 40002; // 0x9c42
+    field public static final int STATS_SERVICES = 40001; // 0x9c41
+  }
+
+  public final class PidHealthStats {
+    field public static final int MEASUREMENT_WAKE_NESTING_COUNT = 20001; // 0x4e21
+    field public static final int MEASUREMENT_WAKE_START_MS = 20003; // 0x4e23
+    field public static final int MEASUREMENT_WAKE_SUM_MS = 20002; // 0x4e22
+  }
+
+  public final class ProcessHealthStats {
+    field public static final int MEASUREMENT_ANR_COUNT = 30005; // 0x7535
+    field public static final int MEASUREMENT_CRASHES_COUNT = 30004; // 0x7534
+    field public static final int MEASUREMENT_FOREGROUND_MS = 30006; // 0x7536
+    field public static final int MEASUREMENT_STARTS_COUNT = 30003; // 0x7533
+    field public static final int MEASUREMENT_SYSTEM_TIME_MS = 30002; // 0x7532
+    field public static final int MEASUREMENT_USER_TIME_MS = 30001; // 0x7531
+  }
+
+  public final class ServiceHealthStats {
+    field public static final int MEASUREMENT_LAUNCH_COUNT = 50002; // 0xc352
+    field public static final int MEASUREMENT_START_SERVICE_COUNT = 50001; // 0xc351
+  }
+
+  public class SystemHealthManager {
+    method public static android.os.health.SystemHealthManager from(android.content.Context);
+    method public android.os.health.HealthStats takeMyUidSnapshot();
+    method public android.os.health.HealthStats takeUidSnapshot(int);
+    method public android.os.health.HealthStats[] takeUidSnapshots(int[]);
+  }
+
+  public class TimerStat implements android.os.Parcelable {
+    ctor public TimerStat();
+    ctor public TimerStat(int, long);
+    ctor public TimerStat(android.os.Parcel);
+    method public int describeContents();
+    method public int getCount();
+    method public long getTime();
+    method public void setCount(int);
+    method public void setTime(long);
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.os.health.TimerStat> CREATOR;
+  }
+
+  public final class UidHealthStats {
+    field public static final int MEASUREMENT_BLUETOOTH_IDLE_MS = 10020; // 0x2724
+    field public static final int MEASUREMENT_BLUETOOTH_POWER_MAMS = 10023; // 0x2727
+    field public static final int MEASUREMENT_BLUETOOTH_RX_BYTES = 10052; // 0x2744
+    field public static final int MEASUREMENT_BLUETOOTH_RX_MS = 10021; // 0x2725
+    field public static final int MEASUREMENT_BLUETOOTH_RX_PACKETS = 10058; // 0x274a
+    field public static final int MEASUREMENT_BLUETOOTH_TX_BYTES = 10053; // 0x2745
+    field public static final int MEASUREMENT_BLUETOOTH_TX_MS = 10022; // 0x2726
+    field public static final int MEASUREMENT_BLUETOOTH_TX_PACKETS = 10059; // 0x274b
+    field public static final int MEASUREMENT_BUTTON_USER_ACTIVITY_COUNT = 10046; // 0x273e
+    field public static final int MEASUREMENT_CPU_POWER_MAUS = 10064; // 0x2750
+    field public static final int MEASUREMENT_MOBILE_IDLE_MS = 10024; // 0x2728
+    field public static final int MEASUREMENT_MOBILE_POWER_MAMS = 10027; // 0x272b
+    field public static final int MEASUREMENT_MOBILE_RX_BYTES = 10048; // 0x2740
+    field public static final int MEASUREMENT_MOBILE_RX_MS = 10025; // 0x2729
+    field public static final int MEASUREMENT_MOBILE_RX_PACKETS = 10054; // 0x2746
+    field public static final int MEASUREMENT_MOBILE_TX_BYTES = 10049; // 0x2741
+    field public static final int MEASUREMENT_MOBILE_TX_MS = 10026; // 0x272a
+    field public static final int MEASUREMENT_MOBILE_TX_PACKETS = 10055; // 0x2747
+    field public static final int MEASUREMENT_OTHER_USER_ACTIVITY_COUNT = 10045; // 0x273d
+    field public static final int MEASUREMENT_REALTIME_BATTERY_MS = 10001; // 0x2711
+    field public static final int MEASUREMENT_REALTIME_SCREEN_OFF_BATTERY_MS = 10003; // 0x2713
+    field public static final int MEASUREMENT_SYSTEM_CPU_TIME_US = 10063; // 0x274f
+    field public static final int MEASUREMENT_TOUCH_USER_ACTIVITY_COUNT = 10047; // 0x273f
+    field public static final int MEASUREMENT_UPTIME_BATTERY_MS = 10002; // 0x2712
+    field public static final int MEASUREMENT_UPTIME_SCREEN_OFF_BATTERY_MS = 10004; // 0x2714
+    field public static final int MEASUREMENT_USER_CPU_TIME_US = 10062; // 0x274e
+    field public static final int MEASUREMENT_WIFI_FULL_LOCK_MS = 10029; // 0x272d
+    field public static final int MEASUREMENT_WIFI_IDLE_MS = 10016; // 0x2720
+    field public static final int MEASUREMENT_WIFI_MULTICAST_MS = 10031; // 0x272f
+    field public static final int MEASUREMENT_WIFI_POWER_MAMS = 10019; // 0x2723
+    field public static final int MEASUREMENT_WIFI_RUNNING_MS = 10028; // 0x272c
+    field public static final int MEASUREMENT_WIFI_RX_BYTES = 10050; // 0x2742
+    field public static final int MEASUREMENT_WIFI_RX_MS = 10017; // 0x2721
+    field public static final int MEASUREMENT_WIFI_RX_PACKETS = 10056; // 0x2748
+    field public static final int MEASUREMENT_WIFI_TX_BYTES = 10051; // 0x2743
+    field public static final int MEASUREMENT_WIFI_TX_MS = 10018; // 0x2722
+    field public static final int MEASUREMENT_WIFI_TX_PACKETS = 10057; // 0x2749
+    field public static final int STATS_PACKAGES = 10015; // 0x271f
+    field public static final int STATS_PIDS = 10013; // 0x271d
+    field public static final int STATS_PROCESSES = 10014; // 0x271e
+    field public static final int TIMERS_JOBS = 10010; // 0x271a
+    field public static final int TIMERS_SENSORS = 10012; // 0x271c
+    field public static final int TIMERS_SYNCS = 10009; // 0x2719
+    field public static final int TIMERS_WAKELOCKS_DRAW = 10008; // 0x2718
+    field public static final int TIMERS_WAKELOCKS_FULL = 10005; // 0x2715
+    field public static final int TIMERS_WAKELOCKS_PARTIAL = 10006; // 0x2716
+    field public static final int TIMERS_WAKELOCKS_WINDOW = 10007; // 0x2717
+    field public static final int TIMER_AUDIO = 10032; // 0x2730
+    field public static final int TIMER_BLUETOOTH_SCAN = 10037; // 0x2735
+    field public static final int TIMER_CAMERA = 10035; // 0x2733
+    field public static final int TIMER_FLASHLIGHT = 10034; // 0x2732
+    field public static final int TIMER_FOREGROUND_ACTIVITY = 10036; // 0x2734
+    field public static final int TIMER_GPS_SENSOR = 10011; // 0x271b
+    field public static final int TIMER_MOBILE_RADIO_ACTIVE = 10061; // 0x274d
+    field public static final int TIMER_PROCESS_STATE_BACKGROUND_MS = 10042; // 0x273a
+    field public static final int TIMER_PROCESS_STATE_CACHED_MS = 10043; // 0x273b
+    field public static final int TIMER_PROCESS_STATE_FOREGROUND_MS = 10041; // 0x2739
+    field public static final int TIMER_PROCESS_STATE_FOREGROUND_SERVICE_MS = 10039; // 0x2737
+    field public static final int TIMER_PROCESS_STATE_TOP_MS = 10038; // 0x2736
+    field public static final int TIMER_PROCESS_STATE_TOP_SLEEPING_MS = 10040; // 0x2738
+    field public static final int TIMER_VIBRATOR = 10044; // 0x273c
+    field public static final int TIMER_VIDEO = 10033; // 0x2731
+    field public static final int TIMER_WIFI_SCAN = 10030; // 0x272e
+  }
+
+}
+
 package android.os.storage {
 
   public abstract class OnObbStateChangeListener {
@@ -29422,7 +29624,7 @@
     method public boolean unmountObb(java.lang.String, boolean, android.os.storage.OnObbStateChangeListener);
   }
 
-  public class StorageVolume implements android.os.Parcelable {
+  public final class StorageVolume implements android.os.Parcelable {
     method public android.content.Intent createAccessIntent(java.lang.String);
     method public int describeContents();
     method public java.lang.String getDescription(android.content.Context);
@@ -30255,7 +30457,7 @@
     field public static final java.lang.String COLUMN_ID = "_id";
     field public static final java.lang.String COLUMN_ORIGINAL_NUMBER = "original_number";
     field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/blocked_number";
-    field public static final java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/blocked_numbers";
+    field public static final java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/blocked_number";
     field public static final android.net.Uri CONTENT_URI;
   }
 
@@ -31782,6 +31984,7 @@
 
   public static final class DocumentsContract.Root {
     field public static final java.lang.String COLUMN_AVAILABLE_BYTES = "available_bytes";
+    field public static final java.lang.String COLUMN_CAPACITY_BYTES = "capacity_bytes";
     field public static final java.lang.String COLUMN_DOCUMENT_ID = "document_id";
     field public static final java.lang.String COLUMN_FLAGS = "flags";
     field public static final java.lang.String COLUMN_ICON = "icon";
@@ -32236,6 +32439,7 @@
     field public static final java.lang.String ACTION_VOICE_CONTROL_BATTERY_SAVER_MODE = "android.settings.VOICE_CONTROL_BATTERY_SAVER_MODE";
     field public static final java.lang.String ACTION_VOICE_CONTROL_DO_NOT_DISTURB_MODE = "android.settings.VOICE_CONTROL_DO_NOT_DISTURB_MODE";
     field public static final java.lang.String ACTION_VOICE_INPUT_SETTINGS = "android.settings.VOICE_INPUT_SETTINGS";
+    field public static final java.lang.String ACTION_VR_LISTENER_SETTINGS = "android.settings.VR_LISTENER_SETTINGS";
     field public static final java.lang.String ACTION_WIFI_IP_SETTINGS = "android.settings.WIFI_IP_SETTINGS";
     field public static final java.lang.String ACTION_WIFI_SETTINGS = "android.settings.WIFI_SETTINGS";
     field public static final java.lang.String ACTION_WIRELESS_SETTINGS = "android.settings.WIRELESS_SETTINGS";
@@ -32273,6 +32477,7 @@
     field public static final java.lang.String AUTO_TIME = "auto_time";
     field public static final java.lang.String AUTO_TIME_ZONE = "auto_time_zone";
     field public static final java.lang.String BLUETOOTH_ON = "bluetooth_on";
+    field public static final java.lang.String BOOT_COUNT = "boot_count";
     field public static final java.lang.String CONTACT_METADATA_SYNC = "contact_metadata_sync";
     field public static final android.net.Uri CONTENT_URI;
     field public static final java.lang.String DATA_ROAMING = "data_roaming";
@@ -34304,7 +34509,8 @@
     ctor public CarrierMessagingService();
     method public android.os.IBinder onBind(android.content.Intent);
     method public void onDownloadMms(android.net.Uri, int, android.net.Uri, android.service.carrier.CarrierMessagingService.ResultCallback<java.lang.Integer>);
-    method public void onFilterSms(android.service.carrier.MessagePdu, java.lang.String, int, int, android.service.carrier.CarrierMessagingService.ResultCallback<java.lang.Boolean>);
+    method public deprecated void onFilterSms(android.service.carrier.MessagePdu, java.lang.String, int, int, android.service.carrier.CarrierMessagingService.ResultCallback<java.lang.Boolean>);
+    method public void onReceiveTextSms(android.service.carrier.MessagePdu, java.lang.String, int, int, android.service.carrier.CarrierMessagingService.ResultCallback<java.lang.Integer>);
     method public deprecated void onSendDataSms(byte[], int, java.lang.String, int, android.service.carrier.CarrierMessagingService.ResultCallback<android.service.carrier.CarrierMessagingService.SendSmsResult>);
     method public void onSendDataSms(byte[], int, java.lang.String, int, int, android.service.carrier.CarrierMessagingService.ResultCallback<android.service.carrier.CarrierMessagingService.SendSmsResult>);
     method public void onSendMms(android.net.Uri, int, android.net.Uri, android.service.carrier.CarrierMessagingService.ResultCallback<android.service.carrier.CarrierMessagingService.SendMmsResult>);
@@ -34315,6 +34521,9 @@
     field public static final int DOWNLOAD_STATUS_ERROR = 2; // 0x2
     field public static final int DOWNLOAD_STATUS_OK = 0; // 0x0
     field public static final int DOWNLOAD_STATUS_RETRY_ON_CARRIER_NETWORK = 1; // 0x1
+    field public static final int RECEIVE_OPTIONS_DEFAULT = 0; // 0x0
+    field public static final int RECEIVE_OPTIONS_DROP = 1; // 0x1
+    field public static final int RECEIVE_OPTIONS_SKIP_NOTIFY_WHEN_CREDENTIAL_ENCRYPTED_STORAGE_UNAVAILABLE = 2; // 0x2
     field public static final int SEND_FLAG_REQUEST_DELIVERY_STATUS = 1; // 0x1
     field public static final int SEND_STATUS_ERROR = 2; // 0x2
     field public static final int SEND_STATUS_OK = 0; // 0x0
@@ -34483,8 +34692,9 @@
 package android.service.notification {
 
   public class Condition implements android.os.Parcelable {
-    ctor public Condition(android.net.Uri, java.lang.String, java.lang.String, java.lang.String, int);
+    ctor public Condition(android.net.Uri, java.lang.String, int);
     ctor public Condition(android.net.Uri, java.lang.String, java.lang.String, java.lang.String, int, int, int);
+    ctor public Condition(android.os.Parcel);
     method public android.service.notification.Condition copy();
     method public int describeContents();
     method public static boolean isValidId(android.net.Uri, java.lang.String);
@@ -34515,6 +34725,7 @@
     method public final void notifyConditions(android.service.notification.Condition...);
     method public android.os.IBinder onBind(android.content.Intent);
     method public abstract void onConnected();
+    method public void onRequestConditions(int);
     method public abstract void onSubscribe(android.net.Uri);
     method public abstract void onUnsubscribe(android.net.Uri);
     field public static final java.lang.String EXTRA_RULE_ID = "android.content.automatic.ruleId";
@@ -34546,10 +34757,9 @@
     method public void onNotificationRemoved(android.service.notification.StatusBarNotification, android.service.notification.NotificationListenerService.RankingMap);
     method public final void requestInterruptionFilter(int);
     method public final void requestListenerHints(int);
-    method public static final void requestRebind(android.content.ComponentName) throws android.os.RemoteException;
+    method public static void requestRebind(android.content.ComponentName) throws android.os.RemoteException;
     method public final void requestUnbind() throws android.os.RemoteException;
     method public final void setNotificationsShown(java.lang.String[]);
-    field public static final java.lang.String CATEGORY_VR_NOTIFICATIONS = "android.intent.category.vr.notifications";
     field public static final int HINT_HOST_DISABLE_EFFECTS = 1; // 0x1
     field public static final int INTERRUPTION_FILTER_ALARMS = 4; // 0x4
     field public static final int INTERRUPTION_FILTER_ALL = 1; // 0x1
@@ -34570,10 +34780,11 @@
     method public int getSuppressedVisualEffects();
     method public boolean isAmbient();
     method public boolean matchesInterruptionFilter();
-    field public static final int IMPORTANCE_DEFAULT = 2; // 0x2
-    field public static final int IMPORTANCE_HIGH = 3; // 0x3
-    field public static final int IMPORTANCE_LOW = 1; // 0x1
-    field public static final int IMPORTANCE_MAX = 4; // 0x4
+    field public static final int IMPORTANCE_DEFAULT = 3; // 0x3
+    field public static final int IMPORTANCE_HIGH = 4; // 0x4
+    field public static final int IMPORTANCE_LOW = 2; // 0x2
+    field public static final int IMPORTANCE_MAX = 5; // 0x5
+    field public static final int IMPORTANCE_MIN = 1; // 0x1
     field public static final int IMPORTANCE_NONE = 0; // 0x0
     field public static final int IMPORTANCE_UNSPECIFIED = -1000; // 0xfffffc18
   }
@@ -34843,6 +35054,17 @@
 
 }
 
+package android.service.vr {
+
+  public abstract class VrListenerService extends android.app.Service {
+    ctor public VrListenerService();
+    method public static final boolean isVrModePackageEnabled(android.content.Context, android.content.ComponentName);
+    method public android.os.IBinder onBind(android.content.Intent);
+    field public static final java.lang.String SERVICE_INTERFACE = "android.service.vr.VrListenerService";
+  }
+
+}
+
 package android.service.wallpaper {
 
   public abstract class WallpaperService extends android.app.Service {
@@ -36412,6 +36634,7 @@
   public class TelecomManager {
     method public void addNewIncomingCall(android.telecom.PhoneAccountHandle, android.os.Bundle);
     method public void cancelMissedCallsNotification();
+    method public android.content.Intent createManageBlockedNumbersIntent();
     method public android.net.Uri getAdnUriForPhoneAccount(android.telecom.PhoneAccountHandle);
     method public java.util.List<android.telecom.PhoneAccountHandle> getCallCapablePhoneAccounts();
     method public java.lang.String getDefaultDialerPackage();
@@ -36424,7 +36647,7 @@
     method public boolean handleMmi(java.lang.String, android.telecom.PhoneAccountHandle);
     method public boolean isInCall();
     method public boolean isVoiceMailNumber(android.telecom.PhoneAccountHandle, java.lang.String);
-    method public void launchManageBlockedNumbersActivity();
+    method public deprecated void launchManageBlockedNumbersActivity();
     method public void placeCall(android.net.Uri, android.os.Bundle);
     method public void registerPhoneAccount(android.telecom.PhoneAccount);
     method public void showInCallScreen(boolean);
@@ -38539,7 +38762,6 @@
     method public boolean hasNext();
     method public java.util.Iterator<java.lang.String> iterator();
     method public java.lang.String next();
-    method public void remove();
     method public void setString(java.lang.String);
   }
 
@@ -40151,6 +40373,7 @@
     method public int describeContents();
     method public static android.util.LocaleList forLanguageTags(java.lang.String);
     method public java.util.Locale get(int);
+    method public static android.util.LocaleList getAdjustedDefault();
     method public static android.util.LocaleList getDefault();
     method public static android.util.LocaleList getEmptyLocaleList();
     method public java.util.Locale getFirstMatch(java.lang.String[]);
@@ -47215,6 +47438,7 @@
     method public void setChar(int, java.lang.String, char);
     method public void setCharSequence(int, java.lang.String, java.lang.CharSequence);
     method public void setChronometer(int, long, java.lang.String, boolean);
+    method public void setChronometerCountsDown(int, boolean);
     method public void setContentDescription(int, java.lang.CharSequence);
     method public void setDisplayedChild(int, int);
     method public void setDouble(int, java.lang.String, double);
@@ -50461,6 +50685,7 @@
     method public static long doubleToRawLongBits(double);
     method public double doubleValue();
     method public float floatValue();
+    method public static int hashCode(double);
     method public int intValue();
     method public static boolean isInfinite(double);
     method public boolean isInfinite();
@@ -50468,11 +50693,15 @@
     method public boolean isNaN();
     method public static double longBitsToDouble(long);
     method public long longValue();
+    method public static double max(double, double);
+    method public static double min(double, double);
     method public static double parseDouble(java.lang.String) throws java.lang.NumberFormatException;
+    method public static double sum(double, double);
     method public static java.lang.String toHexString(double);
     method public static java.lang.String toString(double);
     method public static java.lang.Double valueOf(java.lang.String) throws java.lang.NumberFormatException;
     method public static java.lang.Double valueOf(double);
+    field public static final int BYTES = 8; // 0x8
     field public static final int MAX_EXPONENT = 1023; // 0x3ff
     field public static final double MAX_VALUE = 1.7976931348623157E308;
     field public static final int MIN_EXPONENT = -1022; // 0xfffffc02
@@ -50635,10 +50864,13 @@
     method public static java.lang.Integer getInteger(java.lang.String);
     method public static java.lang.Integer getInteger(java.lang.String, int);
     method public static java.lang.Integer getInteger(java.lang.String, java.lang.Integer);
+    method public static int hashCode(int);
     method public static int highestOneBit(int);
     method public int intValue();
     method public long longValue();
     method public static int lowestOneBit(int);
+    method public static int max(int, int);
+    method public static int min(int, int);
     method public static int numberOfLeadingZeros(int);
     method public static int numberOfTrailingZeros(int);
     method public static int parseInt(java.lang.String, int) throws java.lang.NumberFormatException;
@@ -50648,6 +50880,7 @@
     method public static int rotateLeft(int, int);
     method public static int rotateRight(int, int);
     method public static int signum(int);
+    method public static int sum(int, int);
     method public static java.lang.String toBinaryString(int);
     method public static java.lang.String toHexString(int);
     method public static java.lang.String toOctalString(int);
@@ -50656,6 +50889,7 @@
     method public static java.lang.Integer valueOf(java.lang.String, int) throws java.lang.NumberFormatException;
     method public static java.lang.Integer valueOf(java.lang.String) throws java.lang.NumberFormatException;
     method public static java.lang.Integer valueOf(int);
+    field public static final int BYTES = 4; // 0x4
     field public static final int MAX_VALUE = 2147483647; // 0x7fffffff
     field public static final int MIN_VALUE = -2147483648; // 0x80000000
     field public static final int SIZE = 32; // 0x20
@@ -50675,7 +50909,9 @@
   }
 
   public abstract interface Iterable {
+    method public default void forEach(java.util.function.Consumer<? super T>);
     method public abstract java.util.Iterator<T> iterator();
+    method public default java.util.Spliterator<T> spliterator();
   }
 
   public class LinkageError extends java.lang.Error {
@@ -50696,10 +50932,13 @@
     method public static java.lang.Long getLong(java.lang.String);
     method public static java.lang.Long getLong(java.lang.String, long);
     method public static java.lang.Long getLong(java.lang.String, java.lang.Long);
+    method public static int hashCode(long);
     method public static long highestOneBit(long);
     method public int intValue();
     method public long longValue();
     method public static long lowestOneBit(long);
+    method public static long max(long, long);
+    method public static long min(long, long);
     method public static int numberOfLeadingZeros(long);
     method public static int numberOfTrailingZeros(long);
     method public static long parseLong(java.lang.String, int) throws java.lang.NumberFormatException;
@@ -50709,6 +50948,7 @@
     method public static long rotateLeft(long, int);
     method public static long rotateRight(long, int);
     method public static int signum(long);
+    method public static long sum(long, long);
     method public static java.lang.String toBinaryString(long);
     method public static java.lang.String toHexString(long);
     method public static java.lang.String toOctalString(long);
@@ -54150,6 +54390,7 @@
 
   public abstract class Provider extends java.util.Properties {
     ctor protected Provider(java.lang.String, double, java.lang.String);
+    method public synchronized void forEach(java.util.function.BiConsumer<? super java.lang.Object, ? super java.lang.Object>);
     method public java.lang.String getInfo();
     method public java.lang.String getName();
     method public synchronized java.security.Provider.Service getService(java.lang.String, java.lang.String);
@@ -57091,6 +57332,7 @@
     method public E removeLast();
     method public boolean removeLastOccurrence(java.lang.Object);
     method public int size();
+    method public java.util.Spliterator<E> spliterator();
   }
 
   public class ArrayList extends java.util.AbstractList implements java.lang.Cloneable java.util.List java.util.RandomAccess java.io.Serializable {
@@ -57099,8 +57341,10 @@
     ctor public ArrayList(java.util.Collection<? extends E>);
     method public java.lang.Object clone();
     method public void ensureCapacity(int);
+    method public void forEach(java.util.function.Consumer<? super E>);
     method public E get(int);
     method public int size();
+    method public java.util.Spliterator<E> spliterator();
     method public void trimToSize();
   }
 
@@ -57201,6 +57445,14 @@
     method public static void sort(java.lang.Object[], int, int);
     method public static void sort(T[], java.util.Comparator<? super T>);
     method public static void sort(T[], int, int, java.util.Comparator<? super T>);
+    method public static java.util.Spliterator<T> spliterator(T[]);
+    method public static java.util.Spliterator<T> spliterator(T[], int, int);
+    method public static java.util.Spliterator.OfInt spliterator(int[]);
+    method public static java.util.Spliterator.OfInt spliterator(int[], int, int);
+    method public static java.util.Spliterator.OfLong spliterator(long[]);
+    method public static java.util.Spliterator.OfLong spliterator(long[], int, int);
+    method public static java.util.Spliterator.OfDouble spliterator(double[]);
+    method public static java.util.Spliterator.OfDouble spliterator(double[], int, int);
     method public static java.lang.String toString(long[]);
     method public static java.lang.String toString(int[]);
     method public static java.lang.String toString(short[]);
@@ -57431,7 +57683,23 @@
 
   public abstract interface Comparator {
     method public abstract int compare(T, T);
+    method public static java.util.Comparator<T> comparing(java.util.function.Function<? super T, ? extends U>, java.util.Comparator<? super U>);
+    method public static java.util.Comparator<T> comparing(java.util.function.Function<? super T, ? extends U>);
+    method public static java.util.Comparator<T> comparingDouble(java.util.function.ToDoubleFunction<? super T>);
+    method public static java.util.Comparator<T> comparingInt(java.util.function.ToIntFunction<? super T>);
+    method public static java.util.Comparator<T> comparingLong(java.util.function.ToLongFunction<? super T>);
     method public abstract boolean equals(java.lang.Object);
+    method public static java.util.Comparator<T> naturalOrder();
+    method public static java.util.Comparator<T> nullsFirst(java.util.Comparator<? super T>);
+    method public static java.util.Comparator<T> nullsLast(java.util.Comparator<? super T>);
+    method public static java.util.Comparator<T> reverseOrder();
+    method public default java.util.Comparator<T> reversed();
+    method public default java.util.Comparator<T> thenComparing(java.util.Comparator<? super T>);
+    method public default java.util.Comparator<T> thenComparing(java.util.function.Function<? super T, ? extends U>, java.util.Comparator<? super U>);
+    method public default java.util.Comparator<T> thenComparing(java.util.function.Function<? super T, ? extends U>);
+    method public default java.util.Comparator<T> thenComparingDouble(java.util.function.ToDoubleFunction<? super T>);
+    method public default java.util.Comparator<T> thenComparingInt(java.util.function.ToIntFunction<? super T>);
+    method public default java.util.Comparator<T> thenComparingLong(java.util.function.ToLongFunction<? super T>);
   }
 
   public class ConcurrentModificationException extends java.lang.RuntimeException {
@@ -57528,6 +57796,17 @@
     method public abstract int size();
   }
 
+  public class DoubleSummaryStatistics implements java.util.function.DoubleConsumer {
+    ctor public DoubleSummaryStatistics();
+    method public void accept(double);
+    method public void combine(java.util.DoubleSummaryStatistics);
+    method public final double getAverage();
+    method public final long getCount();
+    method public final double getMax();
+    method public final double getMin();
+    method public final double getSum();
+  }
+
   public class DuplicateFormatFlagsException extends java.util.IllegalFormatException {
     ctor public DuplicateFormatFlagsException(java.lang.String);
     method public java.lang.String getFlags();
@@ -57662,6 +57941,7 @@
     ctor public HashMap(java.util.Map<? extends K, ? extends V>);
     method public java.lang.Object clone();
     method public java.util.Set<java.util.Map.Entry<K, V>> entrySet();
+    method public void forEach(java.util.function.BiConsumer<? super K, ? super V>);
   }
 
   public class HashSet extends java.util.AbstractSet implements java.lang.Cloneable java.io.Serializable java.util.Set {
@@ -57672,6 +57952,7 @@
     method public java.lang.Object clone();
     method public java.util.Iterator<E> iterator();
     method public int size();
+    method public java.util.Spliterator<E> spliterator();
   }
 
   public class Hashtable extends java.util.Dictionary implements java.lang.Cloneable java.util.Map java.io.Serializable {
@@ -57686,6 +57967,7 @@
     method public boolean containsValue(java.lang.Object);
     method public synchronized java.util.Enumeration<V> elements();
     method public java.util.Set<java.util.Map.Entry<K, V>> entrySet();
+    method public synchronized void forEach(java.util.function.BiConsumer<? super K, ? super V>);
     method public synchronized V get(java.lang.Object);
     method public synchronized boolean isEmpty();
     method public java.util.Set<K> keySet();
@@ -57704,6 +57986,7 @@
     ctor public IdentityHashMap(java.util.Map<? extends K, ? extends V>);
     method public java.lang.Object clone();
     method public java.util.Set<java.util.Map.Entry<K, V>> entrySet();
+    method public void forEach(java.util.function.BiConsumer<? super K, ? super V>);
   }
 
   public class IllegalFormatCodePointException extends java.util.IllegalFormatException {
@@ -57747,15 +58030,27 @@
     ctor public InputMismatchException(java.lang.String);
   }
 
+  public class IntSummaryStatistics implements java.util.function.IntConsumer {
+    ctor public IntSummaryStatistics();
+    method public void accept(int);
+    method public void combine(java.util.IntSummaryStatistics);
+    method public final double getAverage();
+    method public final long getCount();
+    method public final int getMax();
+    method public final int getMin();
+    method public final long getSum();
+  }
+
   public class InvalidPropertiesFormatException extends java.io.IOException {
     ctor public InvalidPropertiesFormatException(java.lang.Throwable);
     ctor public InvalidPropertiesFormatException(java.lang.String);
   }
 
   public abstract interface Iterator {
+    method public default void forEachRemaining(java.util.function.Consumer<? super E>);
     method public abstract boolean hasNext();
     method public abstract E next();
-    method public abstract void remove();
+    method public default void remove();
   }
 
   public class LinkedHashMap extends java.util.HashMap implements java.util.Map {
@@ -57802,6 +58097,7 @@
     method public E removeLast();
     method public boolean removeLastOccurrence(java.lang.Object);
     method public int size();
+    method public java.util.Spliterator<E> spliterator();
   }
 
   public abstract interface List implements java.util.Collection {
@@ -57937,12 +58233,25 @@
     enum_constant public static final java.util.Locale.Category FORMAT;
   }
 
+  public class LongSummaryStatistics implements java.util.function.IntConsumer java.util.function.LongConsumer {
+    ctor public LongSummaryStatistics();
+    method public void accept(int);
+    method public void accept(long);
+    method public void combine(java.util.LongSummaryStatistics);
+    method public final double getAverage();
+    method public final long getCount();
+    method public final long getMax();
+    method public final long getMin();
+    method public final long getSum();
+  }
+
   public abstract interface Map {
     method public abstract void clear();
     method public abstract boolean containsKey(java.lang.Object);
     method public abstract boolean containsValue(java.lang.Object);
     method public abstract java.util.Set<java.util.Map.Entry<K, V>> entrySet();
     method public abstract boolean equals(java.lang.Object);
+    method public default void forEach(java.util.function.BiConsumer<? super K, ? super V>);
     method public abstract V get(java.lang.Object);
     method public abstract int hashCode();
     method public abstract boolean isEmpty();
@@ -57955,6 +58264,8 @@
   }
 
   public static abstract interface Map.Entry {
+    method public static java.util.Comparator<java.util.Map.Entry<K, V>> comparingByKey();
+    method public static java.util.Comparator<java.util.Map.Entry<K, V>> comparingByKey(java.util.Comparator<? super K>);
     method public abstract boolean equals(java.lang.Object);
     method public abstract K getKey();
     method public abstract V getValue();
@@ -58057,9 +58368,83 @@
     method public abstract void update(java.util.Observable, java.lang.Object);
   }
 
+  public final class Optional {
+    method public static java.util.Optional<T> empty();
+    method public java.util.Optional<T> filter(java.util.function.Predicate<? super T>);
+    method public java.util.Optional<U> flatMap(java.util.function.Function<? super T, java.util.Optional<U>>);
+    method public T get();
+    method public void ifPresent(java.util.function.Consumer<? super T>);
+    method public boolean isPresent();
+    method public java.util.Optional<U> map(java.util.function.Function<? super T, ? extends U>);
+    method public static java.util.Optional<T> of(T);
+    method public static java.util.Optional<T> ofNullable(T);
+    method public T orElse(T);
+    method public T orElseGet(java.util.function.Supplier<? extends T>);
+    method public T orElseThrow(java.util.function.Supplier<? extends X>) throws java.lang.Throwable;
+  }
+
+  public final class OptionalDouble {
+    method public static java.util.OptionalDouble empty();
+    method public double getAsDouble();
+    method public void ifPresent(java.util.function.DoubleConsumer);
+    method public boolean isPresent();
+    method public static java.util.OptionalDouble of(double);
+    method public double orElse(double);
+    method public double orElseGet(java.util.function.DoubleSupplier);
+    method public double orElseThrow(java.util.function.Supplier<X>) throws java.lang.Throwable;
+  }
+
+  public final class OptionalInt {
+    method public static java.util.OptionalInt empty();
+    method public int getAsInt();
+    method public void ifPresent(java.util.function.IntConsumer);
+    method public boolean isPresent();
+    method public static java.util.OptionalInt of(int);
+    method public int orElse(int);
+    method public int orElseGet(java.util.function.IntSupplier);
+    method public int orElseThrow(java.util.function.Supplier<X>) throws java.lang.Throwable;
+  }
+
+  public final class OptionalLong {
+    method public static java.util.OptionalLong empty();
+    method public long getAsLong();
+    method public void ifPresent(java.util.function.LongConsumer);
+    method public boolean isPresent();
+    method public static java.util.OptionalLong of(long);
+    method public long orElse(long);
+    method public long orElseGet(java.util.function.LongSupplier);
+    method public long orElseThrow(java.util.function.Supplier<X>) throws java.lang.Throwable;
+  }
+
+  public abstract interface PrimitiveIterator implements java.util.Iterator {
+    method public abstract void forEachRemaining(T_CONS);
+  }
+
+  public static abstract interface PrimitiveIterator.OfDouble implements java.util.PrimitiveIterator {
+    method public default void forEachRemaining(java.util.function.DoubleConsumer);
+    method public default void forEachRemaining(java.util.function.Consumer<? super java.lang.Double>);
+    method public default java.lang.Double next();
+    method public abstract double nextDouble();
+  }
+
+  public static abstract interface PrimitiveIterator.OfInt implements java.util.PrimitiveIterator {
+    method public default void forEachRemaining(java.util.function.IntConsumer);
+    method public default void forEachRemaining(java.util.function.Consumer<? super java.lang.Integer>);
+    method public default java.lang.Integer next();
+    method public abstract int nextInt();
+  }
+
+  public static abstract interface PrimitiveIterator.OfLong implements java.util.PrimitiveIterator {
+    method public default void forEachRemaining(java.util.function.LongConsumer);
+    method public default void forEachRemaining(java.util.function.Consumer<? super java.lang.Long>);
+    method public default java.lang.Long next();
+    method public abstract long nextLong();
+  }
+
   public class PriorityQueue extends java.util.AbstractQueue implements java.io.Serializable {
     ctor public PriorityQueue();
     ctor public PriorityQueue(int);
+    ctor public PriorityQueue(java.util.Comparator<? super E>);
     ctor public PriorityQueue(int, java.util.Comparator<? super E>);
     ctor public PriorityQueue(java.util.Collection<? extends E>);
     ctor public PriorityQueue(java.util.PriorityQueue<? extends E>);
@@ -58070,6 +58455,7 @@
     method public E peek();
     method public E poll();
     method public int size();
+    method public final java.util.Spliterator<E> spliterator();
   }
 
   public class Properties extends java.util.Hashtable {
@@ -58228,7 +58614,6 @@
     method public short nextShort();
     method public short nextShort(int);
     method public int radix();
-    method public void remove();
     method public java.util.Scanner reset();
     method public java.util.Scanner skip(java.util.regex.Pattern);
     method public java.util.Scanner skip(java.lang.String);
@@ -58313,6 +58698,111 @@
     method public abstract java.util.SortedSet<E> tailSet(E);
   }
 
+  public abstract interface Spliterator {
+    method public abstract int characteristics();
+    method public abstract long estimateSize();
+    method public default void forEachRemaining(java.util.function.Consumer<? super T>);
+    method public default java.util.Comparator<? super T> getComparator();
+    method public default long getExactSizeIfKnown();
+    method public default boolean hasCharacteristics(int);
+    method public abstract boolean tryAdvance(java.util.function.Consumer<? super T>);
+    method public abstract java.util.Spliterator<T> trySplit();
+    field public static final int CONCURRENT = 4096; // 0x1000
+    field public static final int DISTINCT = 1; // 0x1
+    field public static final int IMMUTABLE = 1024; // 0x400
+    field public static final int NONNULL = 256; // 0x100
+    field public static final int ORDERED = 16; // 0x10
+    field public static final int SIZED = 64; // 0x40
+    field public static final int SORTED = 4; // 0x4
+    field public static final int SUBSIZED = 16384; // 0x4000
+  }
+
+  public static abstract interface Spliterator.OfDouble implements java.util.Spliterator.OfPrimitive {
+    method public default void forEachRemaining(java.util.function.DoubleConsumer);
+    method public default void forEachRemaining(java.util.function.Consumer<? super java.lang.Double>);
+    method public abstract boolean tryAdvance(java.util.function.DoubleConsumer);
+    method public default boolean tryAdvance(java.util.function.Consumer<? super java.lang.Double>);
+    method public abstract java.util.Spliterator.OfDouble trySplit();
+  }
+
+  public static abstract interface Spliterator.OfInt implements java.util.Spliterator.OfPrimitive {
+    method public default void forEachRemaining(java.util.function.IntConsumer);
+    method public default void forEachRemaining(java.util.function.Consumer<? super java.lang.Integer>);
+    method public abstract boolean tryAdvance(java.util.function.IntConsumer);
+    method public default boolean tryAdvance(java.util.function.Consumer<? super java.lang.Integer>);
+    method public abstract java.util.Spliterator.OfInt trySplit();
+  }
+
+  public static abstract interface Spliterator.OfLong implements java.util.Spliterator.OfPrimitive {
+    method public default void forEachRemaining(java.util.function.LongConsumer);
+    method public default void forEachRemaining(java.util.function.Consumer<? super java.lang.Long>);
+    method public abstract boolean tryAdvance(java.util.function.LongConsumer);
+    method public default boolean tryAdvance(java.util.function.Consumer<? super java.lang.Long>);
+    method public abstract java.util.Spliterator.OfLong trySplit();
+  }
+
+  public static abstract interface Spliterator.OfPrimitive implements java.util.Spliterator {
+    method public default void forEachRemaining(T_CONS);
+    method public abstract boolean tryAdvance(T_CONS);
+    method public abstract T_SPLITR trySplit();
+  }
+
+  public final class Spliterators {
+    method public static java.util.Spliterator.OfDouble emptyDoubleSpliterator();
+    method public static java.util.Spliterator.OfInt emptyIntSpliterator();
+    method public static java.util.Spliterator.OfLong emptyLongSpliterator();
+    method public static java.util.Spliterator<T> emptySpliterator();
+    method public static java.util.Iterator<T> iterator(java.util.Spliterator<? extends T>);
+    method public static java.util.PrimitiveIterator.OfInt iterator(java.util.Spliterator.OfInt);
+    method public static java.util.PrimitiveIterator.OfLong iterator(java.util.Spliterator.OfLong);
+    method public static java.util.PrimitiveIterator.OfDouble iterator(java.util.Spliterator.OfDouble);
+    method public static java.util.Spliterator<T> spliterator(java.lang.Object[], int);
+    method public static java.util.Spliterator<T> spliterator(java.lang.Object[], int, int, int);
+    method public static java.util.Spliterator.OfInt spliterator(int[], int);
+    method public static java.util.Spliterator.OfInt spliterator(int[], int, int, int);
+    method public static java.util.Spliterator.OfLong spliterator(long[], int);
+    method public static java.util.Spliterator.OfLong spliterator(long[], int, int, int);
+    method public static java.util.Spliterator.OfDouble spliterator(double[], int);
+    method public static java.util.Spliterator.OfDouble spliterator(double[], int, int, int);
+    method public static java.util.Spliterator<T> spliterator(java.util.Collection<? extends T>, int);
+    method public static java.util.Spliterator<T> spliterator(java.util.Iterator<? extends T>, long, int);
+    method public static java.util.Spliterator.OfInt spliterator(java.util.PrimitiveIterator.OfInt, long, int);
+    method public static java.util.Spliterator.OfLong spliterator(java.util.PrimitiveIterator.OfLong, long, int);
+    method public static java.util.Spliterator.OfDouble spliterator(java.util.PrimitiveIterator.OfDouble, long, int);
+    method public static java.util.Spliterator<T> spliteratorUnknownSize(java.util.Iterator<? extends T>, int);
+    method public static java.util.Spliterator.OfInt spliteratorUnknownSize(java.util.PrimitiveIterator.OfInt, int);
+    method public static java.util.Spliterator.OfLong spliteratorUnknownSize(java.util.PrimitiveIterator.OfLong, int);
+    method public static java.util.Spliterator.OfDouble spliteratorUnknownSize(java.util.PrimitiveIterator.OfDouble, int);
+  }
+
+  public static abstract class Spliterators.AbstractDoubleSpliterator implements java.util.Spliterator.OfDouble {
+    ctor protected Spliterators.AbstractDoubleSpliterator(long, int);
+    method public int characteristics();
+    method public long estimateSize();
+    method public java.util.Spliterator.OfDouble trySplit();
+  }
+
+  public static abstract class Spliterators.AbstractIntSpliterator implements java.util.Spliterator.OfInt {
+    ctor protected Spliterators.AbstractIntSpliterator(long, int);
+    method public int characteristics();
+    method public long estimateSize();
+    method public java.util.Spliterator.OfInt trySplit();
+  }
+
+  public static abstract class Spliterators.AbstractLongSpliterator implements java.util.Spliterator.OfLong {
+    ctor protected Spliterators.AbstractLongSpliterator(long, int);
+    method public int characteristics();
+    method public long estimateSize();
+    method public java.util.Spliterator.OfLong trySplit();
+  }
+
+  public static abstract class Spliterators.AbstractSpliterator implements java.util.Spliterator {
+    ctor protected Spliterators.AbstractSpliterator(long, int);
+    method public int characteristics();
+    method public long estimateSize();
+    method public java.util.Spliterator<T> trySplit();
+  }
+
   public class Stack extends java.util.Vector {
     ctor public Stack();
     method public boolean empty();
@@ -58322,6 +58812,15 @@
     method public synchronized int search(java.lang.Object);
   }
 
+  public final class StringJoiner {
+    ctor public StringJoiner(java.lang.CharSequence);
+    ctor public StringJoiner(java.lang.CharSequence, java.lang.CharSequence, java.lang.CharSequence);
+    method public java.util.StringJoiner add(java.lang.CharSequence);
+    method public int length();
+    method public java.util.StringJoiner merge(java.util.StringJoiner);
+    method public java.util.StringJoiner setEmptyValue(java.lang.CharSequence);
+  }
+
   public class StringTokenizer implements java.util.Enumeration {
     ctor public StringTokenizer(java.lang.String, java.lang.String, boolean);
     ctor public StringTokenizer(java.lang.String, java.lang.String);
@@ -58404,6 +58903,7 @@
     method public K firstKey();
     method public java.util.Map.Entry<K, V> floorEntry(K);
     method public K floorKey(K);
+    method public void forEach(java.util.function.BiConsumer<? super K, ? super V>);
     method public java.util.NavigableMap<K, V> headMap(K, boolean);
     method public java.util.SortedMap<K, V> headMap(K);
     method public java.util.Map.Entry<K, V> higherEntry(K);
@@ -58442,6 +58942,7 @@
     method public E pollFirst();
     method public E pollLast();
     method public int size();
+    method public java.util.Spliterator<E> spliterator();
     method public java.util.NavigableSet<E> subSet(E, boolean, E, boolean);
     method public java.util.SortedSet<E> subSet(E, E);
     method public java.util.NavigableSet<E> tailSet(E, boolean);
@@ -58486,6 +58987,7 @@
     method public java.util.Enumeration<E> elements();
     method public synchronized void ensureCapacity(int);
     method public synchronized E firstElement();
+    method public synchronized void forEach(java.util.function.Consumer<? super E>);
     method public synchronized E get(int);
     method public synchronized int indexOf(java.lang.Object, int);
     method public synchronized void insertElementAt(E, int);
@@ -58497,6 +58999,7 @@
     method public synchronized void setElementAt(E, int);
     method public synchronized void setSize(int);
     method public synchronized int size();
+    method public java.util.Spliterator<E> spliterator();
     method public synchronized void trimToSize();
     field protected int capacityIncrement;
     field protected int elementCount;
@@ -58509,6 +59012,7 @@
     ctor public WeakHashMap();
     ctor public WeakHashMap(java.util.Map<? extends K, ? extends V>);
     method public java.util.Set<java.util.Map.Entry<K, V>> entrySet();
+    method public void forEach(java.util.function.BiConsumer<? super K, ? super V>);
   }
 
 }
diff --git a/api/removed.txt b/api/removed.txt
index 50a24f6..2f55373 100644
--- a/api/removed.txt
+++ b/api/removed.txt
@@ -37,12 +37,20 @@
 
 package android.media {
 
-  public class AudioFormat implements android.os.Parcelable {
+  public final class AudioFormat implements android.os.Parcelable {
     ctor public AudioFormat();
   }
 
 }
 
+package android.media.tv {
+
+  public class TvView extends android.view.ViewGroup {
+    method public void requestUnblockContent(android.media.tv.TvContentRating);
+  }
+
+}
+
 package android.net {
 
   public class SSLCertificateSocketFactory extends javax.net.ssl.SSLSocketFactory {
@@ -201,14 +209,6 @@
 
 }
 
-package android.service.notification {
-
-  public abstract class ConditionProviderService extends android.app.Service {
-    method public void onRequestConditions(int);
-  }
-
-}
-
 package android.test.mock {
 
   public deprecated class MockPackageManager extends android.content.pm.PackageManager {
diff --git a/api/system-current.txt b/api/system-current.txt
index 9a22101..c9176ec 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -52,6 +52,7 @@
     field public static final java.lang.String BIND_TV_INPUT = "android.permission.BIND_TV_INPUT";
     field public static final java.lang.String BIND_VOICE_INTERACTION = "android.permission.BIND_VOICE_INTERACTION";
     field public static final java.lang.String BIND_VPN_SERVICE = "android.permission.BIND_VPN_SERVICE";
+    field public static final java.lang.String BIND_VR_LISTENER_SERVICE = "android.permission.BIND_VR_LISTENER_SERVICE";
     field public static final java.lang.String BIND_WALLPAPER = "android.permission.BIND_WALLPAPER";
     field public static final java.lang.String BLUETOOTH = "android.permission.BLUETOOTH";
     field public static final java.lang.String BLUETOOTH_ADMIN = "android.permission.BLUETOOTH_ADMIN";
@@ -169,7 +170,6 @@
     field public static final java.lang.String READ_SYNC_STATS = "android.permission.READ_SYNC_STATS";
     field public static final java.lang.String READ_VOICEMAIL = "com.android.voicemail.permission.READ_VOICEMAIL";
     field public static final java.lang.String READ_WIFI_CREDENTIAL = "android.permission.READ_WIFI_CREDENTIAL";
-    field public static final java.lang.String READ_WRITE_CONTACT_METADATA = "android.permission.READ_WRITE_CONTACT_METADATA";
     field public static final java.lang.String REAL_GET_TASKS = "android.permission.REAL_GET_TASKS";
     field public static final java.lang.String REBOOT = "android.permission.REBOOT";
     field public static final java.lang.String RECEIVE_BOOT_COMPLETED = "android.permission.RECEIVE_BOOT_COMPLETED";
@@ -194,6 +194,7 @@
     field public static final java.lang.String SCORE_NETWORKS = "android.permission.SCORE_NETWORKS";
     field public static final java.lang.String SEND_RESPOND_VIA_MESSAGE = "android.permission.SEND_RESPOND_VIA_MESSAGE";
     field public static final java.lang.String SEND_SMS = "android.permission.SEND_SMS";
+    field public static final java.lang.String SEND_SMS_NO_CONFIRMATION = "android.permission.SEND_SMS_NO_CONFIRMATION";
     field public static final java.lang.String SERIAL_PORT = "android.permission.SERIAL_PORT";
     field public static final java.lang.String SET_ACTIVITY_WATCHER = "android.permission.SET_ACTIVITY_WATCHER";
     field public static final java.lang.String SET_ALARM = "com.android.alarm.permission.SET_ALARM";
@@ -973,6 +974,7 @@
     field public static final int nextFocusLeft = 16842977; // 0x10100e1
     field public static final int nextFocusRight = 16842978; // 0x10100e2
     field public static final int nextFocusUp = 16842979; // 0x10100e3
+    field public static final int nfcAntennaPositionDrawable = 16844063; // 0x101051f
     field public static final int noHistory = 16843309; // 0x101022d
     field public static final int normalScreens = 16843397; // 0x1010285
     field public static final int notificationTimeout = 16843651; // 0x1010383
@@ -2771,6 +2773,8 @@
     field public static final int GLOBAL_ACTION_TOGGLE_SPLIT_SCREEN = 7; // 0x7
     field public static final java.lang.String SERVICE_INTERFACE = "android.accessibilityservice.AccessibilityService";
     field public static final java.lang.String SERVICE_META_DATA = "android.accessibilityservice";
+    field public static final int SHOW_MODE_AUTO = 0; // 0x0
+    field public static final int SHOW_MODE_HIDDEN = 1; // 0x1
   }
 
   public static abstract class AccessibilityService.GestureResultCallback {
@@ -3720,7 +3724,7 @@
     method public deprecated void setTitleColor(int);
     method public void setVisible(boolean);
     method public final void setVolumeControlStream(int);
-    method public void setVrMode(boolean);
+    method public void setVrModeEnabled(boolean, android.content.ComponentName) throws android.content.pm.PackageManager.NameNotFoundException;
     method public boolean shouldShowRequestPermissionRationale(java.lang.String);
     method public boolean shouldUpRecreateTask(android.content.Intent);
     method public boolean showAssist(android.os.Bundle);
@@ -4253,13 +4257,12 @@
     field public java.lang.String serviceDetails;
   }
 
-  public class AutomaticZenRule implements android.os.Parcelable {
+  public final class AutomaticZenRule implements android.os.Parcelable {
     ctor public AutomaticZenRule(java.lang.String, android.content.ComponentName, android.net.Uri, int, boolean);
     ctor public AutomaticZenRule(android.os.Parcel);
     method public int describeContents();
     method public android.net.Uri getConditionId();
     method public long getCreationTime();
-    method public java.lang.String getId();
     method public int getInterruptionFilter();
     method public java.lang.String getName();
     method public android.content.ComponentName getOwner();
@@ -5040,6 +5043,7 @@
     field public static final int DEFAULT_VIBRATE = 2; // 0x2
     field public static final java.lang.String EXTRA_BACKGROUND_IMAGE_URI = "android.backgroundImageUri";
     field public static final java.lang.String EXTRA_BIG_TEXT = "android.bigText";
+    field public static final java.lang.String EXTRA_CHRONOMETER_COUNTS_DOWN = "android.chronometerCountsDown";
     field public static final java.lang.String EXTRA_COMPACT_ACTIONS = "android.compactActions";
     field public static final java.lang.String EXTRA_INFO_TEXT = "android.infoText";
     field public static final java.lang.String EXTRA_LARGE_ICON = "android.largeIcon";
@@ -5181,16 +5185,17 @@
     method public android.app.Notification.Builder addExtras(android.os.Bundle);
     method public android.app.Notification.Builder addPerson(java.lang.String);
     method public android.app.Notification build();
+    method public android.widget.RemoteViews createBigContentView();
+    method public android.widget.RemoteViews createContentView();
+    method public android.widget.RemoteViews createHeadsUpContentView();
     method public android.app.Notification.Builder extend(android.app.Notification.Extender);
     method public android.os.Bundle getExtras();
     method public deprecated android.app.Notification getNotification();
-    method public android.widget.RemoteViews makeBigContentView();
-    method public android.widget.RemoteViews makeContentView();
-    method public android.widget.RemoteViews makeHeadsUpContentView();
     method public static android.app.Notification.Builder recoverBuilder(android.content.Context, android.app.Notification);
     method public android.app.Notification.Builder setActions(android.app.Notification.Action...);
     method public android.app.Notification.Builder setAutoCancel(boolean);
     method public android.app.Notification.Builder setCategory(java.lang.String);
+    method public android.app.Notification.Builder setChronometerCountsDown(boolean);
     method public android.app.Notification.Builder setColor(int);
     method public deprecated android.app.Notification.Builder setContent(android.widget.RemoteViews);
     method public android.app.Notification.Builder setContentInfo(java.lang.CharSequence);
@@ -5359,14 +5364,14 @@
   }
 
   public class NotificationManager {
-    method public android.app.AutomaticZenRule addAutomaticZenRule(android.app.AutomaticZenRule);
+    method public java.lang.String addAutomaticZenRule(android.app.AutomaticZenRule);
     method public boolean areNotificationsEnabled();
     method public void cancel(int);
     method public void cancel(java.lang.String, int);
     method public void cancelAll();
     method public android.service.notification.StatusBarNotification[] getActiveNotifications();
     method public android.app.AutomaticZenRule getAutomaticZenRule(java.lang.String);
-    method public java.util.List<android.app.AutomaticZenRule> getAutomaticZenRules();
+    method public java.util.Map<java.lang.String, android.app.AutomaticZenRule> getAutomaticZenRules();
     method public final int getCurrentInterruptionFilter();
     method public int getImportance();
     method public android.app.NotificationManager.Policy getNotificationPolicy();
@@ -5376,7 +5381,7 @@
     method public boolean removeAutomaticZenRule(java.lang.String);
     method public final void setInterruptionFilter(int);
     method public void setNotificationPolicy(android.app.NotificationManager.Policy);
-    method public boolean updateAutomaticZenRule(android.app.AutomaticZenRule);
+    method public boolean updateAutomaticZenRule(java.lang.String, android.app.AutomaticZenRule);
     field public static final java.lang.String ACTION_INTERRUPTION_FILTER_CHANGED = "android.app.action.INTERRUPTION_FILTER_CHANGED";
     field public static final java.lang.String ACTION_NOTIFICATION_POLICY_ACCESS_GRANTED_CHANGED = "android.app.action.NOTIFICATION_POLICY_ACCESS_GRANTED_CHANGED";
     field public static final java.lang.String ACTION_NOTIFICATION_POLICY_CHANGED = "android.app.action.NOTIFICATION_POLICY_CHANGED";
@@ -5388,7 +5393,7 @@
   }
 
   public static class NotificationManager.Policy implements android.os.Parcelable {
-    ctor public deprecated NotificationManager.Policy(int, int, int);
+    ctor public NotificationManager.Policy(int, int, int);
     ctor public NotificationManager.Policy(int, int, int, int);
     method public int describeContents();
     method public static java.lang.String priorityCategoriesToString(int);
@@ -5740,8 +5745,6 @@
     method public void enableCarMode(int);
     method public int getCurrentModeType();
     method public int getNightMode();
-    method public boolean isNightModeLocked();
-    method public boolean isUiModeLocked();
     method public void setNightMode(int);
     field public static java.lang.String ACTION_ENTER_CAR_MODE;
     field public static java.lang.String ACTION_ENTER_DESK_MODE;
@@ -5843,6 +5846,7 @@
 
   public class WallpaperManager {
     method public void clear() throws java.io.IOException;
+    method public void clear(int) throws java.io.IOException;
     method public void clearWallpaper();
     method public void clearWallpaper(int, int);
     method public void clearWallpaperOffsets(android.os.IBinder);
@@ -6028,7 +6032,7 @@
     method public java.util.List<android.os.PersistableBundle> getTrustAgentConfiguration(android.content.ComponentName, android.content.ComponentName);
     method public int getUserProvisioningState();
     method public android.os.Bundle getUserRestrictions(android.content.ComponentName);
-    method public java.lang.String getWifiMacAddress();
+    method public java.lang.String getWifiMacAddress(android.content.ComponentName);
     method public boolean hasCaCertInstalled(android.content.ComponentName, byte[]);
     method public boolean hasGrantedPolicy(android.content.ComponentName, int);
     method public boolean installCaCert(android.content.ComponentName, byte[]);
@@ -6857,7 +6861,7 @@
     field public static final int TAG_SYNC_SEND_FILE = 210004; // 0x33454
   }
 
-  public static class SecurityLog.SecurityEvent implements android.os.Parcelable {
+  public static final class SecurityLog.SecurityEvent implements android.os.Parcelable {
     method public int describeContents();
     method public java.lang.Object getData();
     method public int getTag();
@@ -7609,15 +7613,6 @@
     field public static final int TYPE_SCO = 2; // 0x2
   }
 
-  public class OobData implements android.os.Parcelable {
-    ctor public OobData();
-    method public int describeContents();
-    method public byte[] getSecurityManagerTk();
-    method public void setSecurityManagerTk(byte[]);
-    method public void writeToParcel(android.os.Parcel, int);
-    field public static final android.os.Parcelable.Creator<android.bluetooth.OobData> CREATOR;
-  }
-
 }
 
 package android.bluetooth.le {
@@ -8452,7 +8447,9 @@
     field public static final java.lang.String RESTRICTIONS_SERVICE = "restrictions";
     field public static final java.lang.String SEARCH_SERVICE = "search";
     field public static final java.lang.String SENSOR_SERVICE = "sensor";
+    field public static final java.lang.String SHORTCUT_SERVICE = "shortcut";
     field public static final java.lang.String STORAGE_SERVICE = "storage";
+    field public static final java.lang.String SYSTEM_HEALTH_SERVICE = "systemhealth";
     field public static final java.lang.String TELECOM_SERVICE = "telecom";
     field public static final java.lang.String TELEPHONY_SERVICE = "phone";
     field public static final java.lang.String TELEPHONY_SUBSCRIPTION_SERVICE = "telephony_subscription_service";
@@ -9652,6 +9649,7 @@
     field public int flags;
     field public int largestWidthLimitDp;
     field public java.lang.String manageSpaceActivityName;
+    field public java.lang.String minSdkVersion;
     field public java.lang.String nativeLibraryDir;
     field public java.lang.String permission;
     field public java.lang.String processName;
@@ -9706,25 +9704,6 @@
     field public int reqTouchScreen;
   }
 
-  public deprecated class ContainerEncryptionParams implements android.os.Parcelable {
-    ctor public ContainerEncryptionParams(java.lang.String, java.security.spec.AlgorithmParameterSpec, javax.crypto.SecretKey) throws java.security.InvalidAlgorithmParameterException;
-    ctor public ContainerEncryptionParams(java.lang.String, java.security.spec.AlgorithmParameterSpec, javax.crypto.SecretKey, java.lang.String, java.security.spec.AlgorithmParameterSpec, javax.crypto.SecretKey, byte[], long, long, long) throws java.security.InvalidAlgorithmParameterException;
-    method public int describeContents();
-    method public long getAuthenticatedDataStart();
-    method public long getDataEnd();
-    method public long getEncryptedDataStart();
-    method public java.lang.String getEncryptionAlgorithm();
-    method public javax.crypto.SecretKey getEncryptionKey();
-    method public java.security.spec.AlgorithmParameterSpec getEncryptionSpec();
-    method public java.lang.String getMacAlgorithm();
-    method public javax.crypto.SecretKey getMacKey();
-    method public java.security.spec.AlgorithmParameterSpec getMacSpec();
-    method public byte[] getMacTag();
-    method public void writeToParcel(android.os.Parcel, int);
-    field public static final android.os.Parcelable.Creator<android.content.pm.ContainerEncryptionParams> CREATOR;
-    field protected static final java.lang.String TAG = "ContainerEncryptionParams";
-  }
-
   public final class EphemeralResolveInfo implements android.os.Parcelable {
     ctor public EphemeralResolveInfo(android.net.Uri, java.lang.String, java.util.List<android.content.IntentFilter>);
     method public int describeContents();
@@ -9804,13 +9783,19 @@
   public class LauncherApps {
     method public java.util.List<android.content.pm.LauncherActivityInfo> getActivityList(java.lang.String, android.os.UserHandle);
     method public android.content.pm.ApplicationInfo getApplicationInfo(java.lang.String, int, android.os.UserHandle);
+    method public android.os.ParcelFileDescriptor getShortcutIconFd(android.content.pm.ShortcutInfo, android.os.UserHandle);
+    method public int getShortcutIconResId(android.content.pm.ShortcutInfo, android.os.UserHandle);
+    method public java.util.List<android.content.pm.ShortcutInfo> getShortcutInfo(java.lang.String, java.util.List<java.lang.String>, android.os.UserHandle);
+    method public java.util.List<android.content.pm.ShortcutInfo> getShortcuts(android.content.pm.LauncherApps.ShortcutQuery, android.os.UserHandle);
     method public boolean isActivityEnabled(android.content.ComponentName, android.os.UserHandle);
     method public boolean isPackageEnabled(java.lang.String, android.os.UserHandle);
+    method public void pinShortcuts(java.lang.String, java.util.List<java.lang.String>, android.os.UserHandle);
     method public void registerCallback(android.content.pm.LauncherApps.Callback);
     method public void registerCallback(android.content.pm.LauncherApps.Callback, android.os.Handler);
     method public android.content.pm.LauncherActivityInfo resolveActivity(android.content.Intent, android.os.UserHandle);
     method public void startAppDetailsActivity(android.content.ComponentName, android.os.UserHandle, android.graphics.Rect, android.os.Bundle);
     method public void startMainActivity(android.content.ComponentName, android.os.UserHandle, android.graphics.Rect, android.os.Bundle);
+    method public boolean startShortcut(java.lang.String, java.lang.String, android.graphics.Rect, android.os.Bundle, android.os.UserHandle);
     method public void unregisterCallback(android.content.pm.LauncherApps.Callback);
   }
 
@@ -9823,6 +9808,18 @@
     method public void onPackagesSuspended(java.lang.String[], android.os.UserHandle);
     method public abstract void onPackagesUnavailable(java.lang.String[], android.os.UserHandle, boolean);
     method public void onPackagesUnsuspended(java.lang.String[], android.os.UserHandle);
+    method public void onShortcutsChanged(java.lang.String, java.util.List<android.content.pm.ShortcutInfo>, android.os.UserHandle);
+  }
+
+  public static class LauncherApps.ShortcutQuery {
+    ctor public LauncherApps.ShortcutQuery();
+    method public void setActivity(android.content.ComponentName);
+    method public void setChangedSince(long);
+    method public void setPackage(java.lang.String);
+    method public void setQueryFlags(int);
+    field public static final int FLAG_GET_DYNAMIC = 1; // 0x1
+    field public static final int FLAG_GET_KEY_FIELDS_ONLY = 4; // 0x4
+    field public static final int FLAG_GET_PINNED = 2; // 0x2
   }
 
   public class PackageInfo implements android.os.Parcelable {
@@ -9900,6 +9897,7 @@
     method public java.lang.String[] getNames() throws java.io.IOException;
     method public java.io.InputStream openRead(java.lang.String) throws java.io.IOException;
     method public java.io.OutputStream openWrite(java.lang.String, long, long) throws java.io.IOException;
+    method public void removeSplit(java.lang.String) throws java.io.IOException;
     method public void setStagingProgress(float);
   }
 
@@ -9933,6 +9931,7 @@
     method public void setAppLabel(java.lang.CharSequence);
     method public void setAppPackageName(java.lang.String);
     method public void setGrantedRuntimePermissions(java.lang.String[]);
+    method public void setInstallFlagsDowngrade();
     method public void setInstallLocation(int);
     method public void setOriginatingUid(int);
     method public void setOriginatingUri(android.net.Uri);
@@ -9954,6 +9953,7 @@
     method public android.graphics.drawable.Drawable loadIcon(android.content.pm.PackageManager);
     method public java.lang.CharSequence loadLabel(android.content.pm.PackageManager);
     method public android.graphics.drawable.Drawable loadLogo(android.content.pm.PackageManager);
+    method public java.lang.CharSequence loadSafeLabel(android.content.pm.PackageManager);
     method public android.graphics.drawable.Drawable loadUnbadgedIcon(android.content.pm.PackageManager);
     method public android.content.res.XmlResourceParser loadXmlMetaData(android.content.pm.PackageManager, java.lang.String);
     method public void writeToParcel(android.os.Parcel, int);
@@ -10212,6 +10212,8 @@
     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_SUCCEEDED = 1; // 0x1
+    field public static final int INTENT_FILTER_VERIFICATION_FAILURE = -1; // 0xffffffff
+    field public static final int INTENT_FILTER_VERIFICATION_SUCCESS = 1; // 0x1
     field public static final int MASK_PERMISSION_FLAGS = 255; // 0xff
     field public static final int MATCH_ALL = 131072; // 0x20000
     field public static final int MATCH_DEFAULT_ONLY = 65536; // 0x10000
@@ -10379,6 +10381,59 @@
     field public java.lang.String permission;
   }
 
+  public class ShortcutInfo implements android.os.Parcelable {
+    method public int describeContents();
+    method public android.content.ComponentName getActivityComponent();
+    method public android.os.PersistableBundle getExtras();
+    method public java.lang.String getId();
+    method public android.content.Intent getIntent();
+    method public long getLastChangedTimestamp();
+    method public java.lang.String getPackageName();
+    method public java.lang.String getTitle();
+    method public int getWeight();
+    method public boolean hasIconFile();
+    method public boolean hasIconResource();
+    method public boolean hasKeyFieldsOnly();
+    method public boolean isDynamic();
+    method public boolean isPinned();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final int CLONE_REMOVE_FOR_CREATOR = 1; // 0x1
+    field public static final int CLONE_REMOVE_FOR_LAUNCHER = 3; // 0x3
+    field public static final int CLONE_REMOVE_NON_KEY_INFO = 4; // 0x4
+    field public static final android.os.Parcelable.Creator<android.content.pm.ShortcutInfo> CREATOR;
+    field public static final int FLAG_DYNAMIC = 1; // 0x1
+    field public static final int FLAG_HAS_ICON_FILE = 8; // 0x8
+    field public static final int FLAG_HAS_ICON_RES = 4; // 0x4
+    field public static final int FLAG_KEY_FIELDS_ONLY = 16; // 0x10
+    field public static final int FLAG_PINNED = 2; // 0x2
+  }
+
+  public static class ShortcutInfo.Builder {
+    ctor public ShortcutInfo.Builder(android.content.Context);
+    method public android.content.pm.ShortcutInfo build();
+    method public android.content.pm.ShortcutInfo.Builder setActivityComponent(android.content.ComponentName);
+    method public android.content.pm.ShortcutInfo.Builder setExtras(android.os.PersistableBundle);
+    method public android.content.pm.ShortcutInfo.Builder setIcon(android.graphics.drawable.Icon);
+    method public android.content.pm.ShortcutInfo.Builder setId(java.lang.String);
+    method public android.content.pm.ShortcutInfo.Builder setIntent(android.content.Intent);
+    method public android.content.pm.ShortcutInfo.Builder setTitle(java.lang.String);
+    method public android.content.pm.ShortcutInfo.Builder setWeight(int);
+  }
+
+  public class ShortcutManager {
+    method public boolean addDynamicShortcut(android.content.pm.ShortcutInfo);
+    method public void deleteAllDynamicShortcuts();
+    method public void deleteDynamicShortcut(java.lang.String);
+    method public java.util.List<android.content.pm.ShortcutInfo> getDynamicShortcuts();
+    method public int getIconMaxDimensions();
+    method public int getMaxDynamicShortcutCount();
+    method public java.util.List<android.content.pm.ShortcutInfo> getPinnedShortcuts();
+    method public long getRateLimitResetTime();
+    method public int getRemainingCallCount();
+    method public boolean setDynamicShortcuts(java.util.List<android.content.pm.ShortcutInfo>);
+    method public boolean updateShortcuts(java.util.List<android.content.pm.ShortcutInfo>);
+  }
+
   public class Signature implements android.os.Parcelable {
     ctor public Signature(byte[]);
     ctor public Signature(java.lang.String);
@@ -10884,7 +10939,6 @@
     method public boolean hasNext();
     method public java.util.Iterator<android.database.CursorJoiner.Result> iterator();
     method public android.database.CursorJoiner.Result next();
-    method public void remove();
   }
 
   public static final class CursorJoiner.Result extends java.lang.Enum {
@@ -13255,7 +13309,8 @@
     method public int getGradientType();
     method public int getOpacity();
     method public android.graphics.drawable.GradientDrawable.Orientation getOrientation();
-    method public boolean isUseLevel();
+    method public int getShape();
+    method public boolean getUseLevel();
     method public void setAlpha(int);
     method public void setColor(int);
     method public void setColor(android.content.res.ColorStateList);
@@ -14124,6 +14179,7 @@
 
   public static abstract class CameraCaptureSession.CaptureCallback {
     ctor public CameraCaptureSession.CaptureCallback();
+    method public void onCaptureBufferLost(android.hardware.camera2.CameraCaptureSession, android.hardware.camera2.CaptureRequest, android.view.Surface, long);
     method public void onCaptureCompleted(android.hardware.camera2.CameraCaptureSession, android.hardware.camera2.CaptureRequest, android.hardware.camera2.TotalCaptureResult);
     method public void onCaptureFailed(android.hardware.camera2.CameraCaptureSession, android.hardware.camera2.CaptureRequest, android.hardware.camera2.CaptureFailure);
     method public void onCaptureProgressed(android.hardware.camera2.CameraCaptureSession, android.hardware.camera2.CaptureRequest, android.hardware.camera2.CaptureResult);
@@ -20353,168 +20409,67 @@
 
   public final class GnssClock implements android.os.Parcelable {
     method public int describeContents();
-    method public double getBiasInNs();
-    method public double getBiasUncertaintyInNs();
-    method public double getDriftInNsPerSec();
-    method public double getDriftUncertaintyInNsPerSec();
-    method public long getFullBiasInNs();
+    method public double getBiasNanos();
+    method public double getBiasUncertaintyNanos();
+    method public double getDriftNanosPerSecond();
+    method public double getDriftUncertaintyNanosPerSecond();
+    method public long getFullBiasNanos();
     method public int getHardwareClockDiscontinuityCount();
-    method public short getLeapSecond();
-    method public long getTimeInNs();
-    method public double getTimeUncertaintyInNs();
-    method public boolean hasBiasInNs();
-    method public boolean hasBiasUncertaintyInNs();
-    method public boolean hasDriftInNsPerSec();
-    method public boolean hasDriftUncertaintyInNsPerSec();
-    method public boolean hasFullBiasInNs();
+    method public int getLeapSecond();
+    method public long getTimeNanos();
+    method public double getTimeUncertaintyNanos();
+    method public boolean hasBiasNanos();
+    method public boolean hasBiasUncertaintyNanos();
+    method public boolean hasDriftNanosPerSecond();
+    method public boolean hasDriftUncertaintyNanosPerSecond();
+    method public boolean hasFullBiasNanos();
     method public boolean hasLeapSecond();
-    method public boolean hasTimeUncertaintyInNs();
-    method public void reset();
-    method public void resetBiasInNs();
-    method public void resetBiasUncertaintyInNs();
-    method public void resetDriftInNsPerSec();
-    method public void resetDriftUncertaintyInNsPerSec();
-    method public void resetFullBiasInNs();
-    method public void resetLeapSecond();
-    method public void resetTimeUncertaintyInNs();
-    method public void set(android.location.GnssClock);
-    method public void setBiasInNs(double);
-    method public void setBiasUncertaintyInNs(double);
-    method public void setDriftInNsPerSec(double);
-    method public void setDriftUncertaintyInNsPerSec(double);
-    method public void setFullBiasInNs(long);
-    method public void setHardwareClockDiscontinuityCount(int);
-    method public void setLeapSecond(short);
-    method public void setTimeInNs(long);
-    method public void setTimeUncertaintyInNs(double);
+    method public boolean hasTimeUncertaintyNanos();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.location.GnssClock> CREATOR;
   }
 
   public final class GnssMeasurement implements android.os.Parcelable {
     method public int describeContents();
-    method public double getAccumulatedDeltaRangeInMeters();
-    method public short getAccumulatedDeltaRangeState();
-    method public double getAccumulatedDeltaRangeUncertaintyInMeters();
-    method public double getAzimuthInDeg();
-    method public double getAzimuthUncertaintyInDeg();
-    method public int getBitNumber();
+    method public double getAccumulatedDeltaRangeMeters();
+    method public int getAccumulatedDeltaRangeState();
+    method public double getAccumulatedDeltaRangeUncertaintyMeters();
     method public long getCarrierCycles();
-    method public float getCarrierFrequencyInHz();
+    method public float getCarrierFrequencyHz();
     method public double getCarrierPhase();
     method public double getCarrierPhaseUncertainty();
-    method public double getCn0InDbHz();
-    method public double getCodePhaseInChips();
-    method public double getCodePhaseUncertaintyInChips();
-    method public byte getConstellationType();
-    method public double getDopplerShiftInHz();
-    method public double getDopplerShiftUncertaintyInHz();
-    method public double getElevationInDeg();
-    method public double getElevationUncertaintyInDeg();
-    method public byte getLossOfLock();
-    method public byte getMultipathIndicator();
-    method public double getPseudorangeInMeters();
-    method public double getPseudorangeRateInMetersPerSec();
-    method public double getPseudorangeRateUncertaintyInMetersPerSec();
-    method public double getPseudorangeUncertaintyInMeters();
-    method public long getReceivedSvTimeInNs();
-    method public long getReceivedSvTimeUncertaintyInNs();
+    method public double getCn0DbHz();
+    method public int getConstellationType();
+    method public int getMultipathIndicator();
+    method public double getPseudorangeRateMetersPerSecond();
+    method public double getPseudorangeRateUncertaintyMetersPerSecond();
+    method public long getReceivedSvTimeNanos();
+    method public long getReceivedSvTimeUncertaintyNanos();
     method public double getSnrInDb();
-    method public short getState();
-    method public short getSvid();
-    method public short getTimeFromLastBitInMs();
-    method public double getTimeOffsetInNs();
-    method public boolean hasAzimuthInDeg();
-    method public boolean hasAzimuthUncertaintyInDeg();
-    method public boolean hasBitNumber();
+    method public int getState();
+    method public int getSvid();
+    method public double getTimeOffsetNanos();
     method public boolean hasCarrierCycles();
-    method public boolean hasCarrierFrequencyInHz();
+    method public boolean hasCarrierFrequencyHz();
     method public boolean hasCarrierPhase();
     method public boolean hasCarrierPhaseUncertainty();
-    method public boolean hasCodePhaseInChips();
-    method public boolean hasCodePhaseUncertaintyInChips();
-    method public boolean hasDopplerShiftInHz();
-    method public boolean hasDopplerShiftUncertaintyInHz();
-    method public boolean hasElevationInDeg();
-    method public boolean hasElevationUncertaintyInDeg();
-    method public boolean hasPseudorangeInMeters();
-    method public boolean hasPseudorangeUncertaintyInMeters();
     method public boolean hasSnrInDb();
-    method public boolean hasTimeFromLastBitInMs();
     method public boolean isPseudorangeRateCorrected();
-    method public boolean isUsedInFix();
-    method public void reset();
-    method public void resetAzimuthInDeg();
-    method public void resetAzimuthUncertaintyInDeg();
-    method public void resetBitNumber();
-    method public void resetCarrierCycles();
-    method public void resetCarrierFrequencyInHz();
-    method public void resetCarrierPhase();
-    method public void resetCarrierPhaseUncertainty();
-    method public void resetCodePhaseInChips();
-    method public void resetCodePhaseUncertaintyInChips();
-    method public void resetDopplerShiftInHz();
-    method public void resetDopplerShiftUncertaintyInHz();
-    method public void resetElevationInDeg();
-    method public void resetElevationUncertaintyInDeg();
-    method public void resetPseudorangeInMeters();
-    method public void resetPseudorangeUncertaintyInMeters();
-    method public void resetSnrInDb();
-    method public void resetTimeFromLastBitInMs();
-    method public void set(android.location.GnssMeasurement);
-    method public void setAccumulatedDeltaRangeInMeters(double);
-    method public void setAccumulatedDeltaRangeState(short);
-    method public void setAccumulatedDeltaRangeUncertaintyInMeters(double);
-    method public void setAzimuthInDeg(double);
-    method public void setAzimuthUncertaintyInDeg(double);
-    method public void setBitNumber(int);
-    method public void setCarrierCycles(long);
-    method public void setCarrierFrequencyInHz(float);
-    method public void setCarrierPhase(double);
-    method public void setCarrierPhaseUncertainty(double);
-    method public void setCn0InDbHz(double);
-    method public void setCodePhaseInChips(double);
-    method public void setCodePhaseUncertaintyInChips(double);
-    method public void setConstellationType(byte);
-    method public void setDopplerShiftInHz(double);
-    method public void setDopplerShiftUncertaintyInHz(double);
-    method public void setElevationInDeg(double);
-    method public void setElevationUncertaintyInDeg(double);
-    method public void setLossOfLock(byte);
-    method public void setMultipathIndicator(byte);
-    method public void setPseudorangeInMeters(double);
-    method public void setPseudorangeRateInMetersPerSec(double);
-    method public void setPseudorangeRateUncertaintyInMetersPerSec(double);
-    method public void setPseudorangeUncertaintyInMeters(double);
-    method public void setReceivedSvTimeInNs(long);
-    method public void setReceivedSvTimeUncertaintyInNs(long);
-    method public void setSnrInDb(double);
-    method public void setState(short);
-    method public void setSvid(short);
-    method public void setTimeFromLastBitInMs(short);
-    method public void setTimeOffsetInNs(double);
-    method public void setUsedInFix(boolean);
     method public void writeToParcel(android.os.Parcel, int);
-    field public static final short ADR_STATE_CYCLE_SLIP = 4; // 0x4
-    field public static final short ADR_STATE_RESET = 2; // 0x2
-    field public static final short ADR_STATE_UNKNOWN = 0; // 0x0
-    field public static final short ADR_STATE_VALID = 1; // 0x1
+    field public static final int ADR_STATE_CYCLE_SLIP = 4; // 0x4
+    field public static final int ADR_STATE_RESET = 2; // 0x2
+    field public static final int ADR_STATE_UNKNOWN = 0; // 0x0
+    field public static final int ADR_STATE_VALID = 1; // 0x1
     field public static final android.os.Parcelable.Creator<android.location.GnssMeasurement> CREATOR;
-    field public static final byte LOSS_OF_LOCK_CYCLE_SLIP = 2; // 0x2
-    field public static final byte LOSS_OF_LOCK_OK = 1; // 0x1
-    field public static final byte LOSS_OF_LOCK_UNKNOWN = 0; // 0x0
-    field public static final byte MULTIPATH_INDICATOR_DETECTED = 1; // 0x1
-    field public static final byte MULTIPATH_INDICATOR_NOT_USED = 2; // 0x2
-    field public static final byte MULTIPATH_INDICATOR_UNKNOWN = 0; // 0x0
-    field public static final short STATE_BIT_SYNC = 2; // 0x2
-    field public static final short STATE_CODE_LOCK = 1; // 0x1
-    field public static final short STATE_MSEC_AMBIGUOUS = 16; // 0x10
-    field public static final short STATE_SUBFRAME_SYNC = 4; // 0x4
-    field public static final short STATE_TOW_DECODED = 8; // 0x8
-    field public static final short STATE_UNKNOWN = 0; // 0x0
-  }
-
-  public static abstract class GnssMeasurement.LossOfLockStatus implements java.lang.annotation.Annotation {
+    field public static final int MULTIPATH_INDICATOR_DETECTED = 1; // 0x1
+    field public static final int MULTIPATH_INDICATOR_NOT_USED = 2; // 0x2
+    field public static final int MULTIPATH_INDICATOR_UNKNOWN = 0; // 0x0
+    field public static final int STATE_BIT_SYNC = 2; // 0x2
+    field public static final int STATE_CODE_LOCK = 1; // 0x1
+    field public static final int STATE_MSEC_AMBIGUOUS = 16; // 0x10
+    field public static final int STATE_SUBFRAME_SYNC = 4; // 0x4
+    field public static final int STATE_TOW_DECODED = 8; // 0x8
+    field public static final int STATE_UNKNOWN = 0; // 0x0
   }
 
   public static abstract class GnssMeasurement.MultipathIndicator implements java.lang.annotation.Annotation {
@@ -20527,7 +20482,7 @@
     method public java.util.Collection<android.location.GnssMeasurement> getMeasurements();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.location.GnssMeasurementsEvent> CREATOR;
-    field public static final int STATUS_GPS_LOCATION_DISABLED = 2; // 0x2
+    field public static final int STATUS_GNSS_LOCATION_DISABLED = 2; // 0x2
     field public static final int STATUS_NOT_SUPPORTED = 0; // 0x0
     field public static final int STATUS_READY = 1; // 0x1
   }
@@ -20544,34 +20499,26 @@
   public final class GnssNavigationMessage implements android.os.Parcelable {
     method public int describeContents();
     method public byte[] getData();
-    method public short getMessageId();
-    method public short getStatus();
-    method public short getSubmessageId();
-    method public short getSvid();
-    method public short getType();
-    method public void reset();
-    method public void set(android.location.GnssNavigationMessage);
-    method public void setData(byte[]);
-    method public void setMessageId(short);
-    method public void setStatus(short);
-    method public void setSubmessageId(short);
-    method public void setSvid(short);
-    method public void setType(short);
+    method public int getMessageId();
+    method public int getStatus();
+    method public int getSubmessageId();
+    method public int getSvid();
+    method public int getType();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.location.GnssNavigationMessage> CREATOR;
-    field public static final short MESSAGE_TYPE_BDS_D1 = 1281; // 0x501
-    field public static final short MESSAGE_TYPE_BDS_D2 = 1282; // 0x502
-    field public static final short MESSAGE_TYPE_GAL_F = 1538; // 0x602
-    field public static final short MESSAGE_TYPE_GAL_I = 1537; // 0x601
-    field public static final short MESSAGE_TYPE_GLO_L1CA = 769; // 0x301
-    field public static final short MESSAGE_TYPE_GPS_CNAV2 = 260; // 0x104
-    field public static final short MESSAGE_TYPE_GPS_L1CA = 257; // 0x101
-    field public static final short MESSAGE_TYPE_GPS_L2CNAV = 258; // 0x102
-    field public static final short MESSAGE_TYPE_GPS_L5CNAV = 259; // 0x103
-    field public static final short MESSAGE_TYPE_UNKNOWN = 0; // 0x0
-    field public static final short STATUS_PARITY_PASSED = 1; // 0x1
-    field public static final short STATUS_PARITY_REBUILT = 2; // 0x2
-    field public static final short STATUS_UNKNOWN = 0; // 0x0
+    field public static final int STATUS_PARITY_PASSED = 1; // 0x1
+    field public static final int STATUS_PARITY_REBUILT = 2; // 0x2
+    field public static final int STATUS_UNKNOWN = 0; // 0x0
+    field public static final int TYPE_BDS_D1 = 1281; // 0x501
+    field public static final int TYPE_BDS_D2 = 1282; // 0x502
+    field public static final int TYPE_GAL_F = 1538; // 0x602
+    field public static final int TYPE_GAL_I = 1537; // 0x601
+    field public static final int TYPE_GLO_L1CA = 769; // 0x301
+    field public static final int TYPE_GPS_CNAV2 = 260; // 0x104
+    field public static final int TYPE_GPS_L1CA = 257; // 0x101
+    field public static final int TYPE_GPS_L2CNAV = 258; // 0x102
+    field public static final int TYPE_GPS_L5CNAV = 259; // 0x103
+    field public static final int TYPE_UNKNOWN = 0; // 0x0
   }
 
   public static abstract class GnssNavigationMessage.GnssNavigationMessageType implements java.lang.annotation.Annotation {
@@ -20583,7 +20530,7 @@
     method public android.location.GnssNavigationMessage getNavigationMessage();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.location.GnssNavigationMessageEvent> CREATOR;
-    field public static final int STATUS_GPS_LOCATION_DISABLED = 2; // 0x2
+    field public static final int STATUS_GNSS_LOCATION_DISABLED = 2; // 0x2
     field public static final int STATUS_NOT_SUPPORTED = 0; // 0x0
     field public static final int STATUS_READY = 1; // 0x1
   }
@@ -20602,22 +20549,22 @@
   }
 
   public final class GnssStatus {
-    method public float getAzimuth(int);
-    method public byte getConstellationType(int);
-    method public float getElevation(int);
+    method public float getAzimuthDegrees(int);
+    method public float getCn0DbHz(int);
+    method public int getConstellationType(int);
+    method public float getElevationDegrees(int);
     method public int getNumSatellites();
-    method public float getSnr(int);
     method public int getSvid(int);
     method public boolean hasAlmanac(int);
     method public boolean hasEphemeris(int);
     method public boolean usedInFix(int);
-    field public static final byte CONSTELLATION_BEIDOU = 5; // 0x5
-    field public static final byte CONSTELLATION_GALILEO = 6; // 0x6
-    field public static final byte CONSTELLATION_GLONASS = 3; // 0x3
-    field public static final byte CONSTELLATION_GPS = 1; // 0x1
-    field public static final byte CONSTELLATION_QZSS = 4; // 0x4
-    field public static final byte CONSTELLATION_SBAS = 2; // 0x2
-    field public static final byte CONSTELLATION_UNKNOWN = 0; // 0x0
+    field public static final int CONSTELLATION_BEIDOU = 5; // 0x5
+    field public static final int CONSTELLATION_GALILEO = 6; // 0x6
+    field public static final int CONSTELLATION_GLONASS = 3; // 0x3
+    field public static final int CONSTELLATION_GPS = 1; // 0x1
+    field public static final int CONSTELLATION_QZSS = 4; // 0x4
+    field public static final int CONSTELLATION_SBAS = 2; // 0x2
+    field public static final int CONSTELLATION_UNKNOWN = 0; // 0x0
   }
 
   public static abstract class GnssStatus.ConstellationType implements java.lang.annotation.Annotation {
@@ -20979,8 +20926,8 @@
     method public java.util.List<java.lang.String> getProviders(boolean);
     method public java.util.List<java.lang.String> getProviders(android.location.Criteria, boolean);
     method public boolean isProviderEnabled(java.lang.String);
-    method public boolean registerGnssMeasurementCallback(android.location.GnssMeasurementsEvent.Callback);
-    method public boolean registerGnssMeasurementCallback(android.location.GnssMeasurementsEvent.Callback, android.os.Handler);
+    method public boolean registerGnssMeasurementsCallback(android.location.GnssMeasurementsEvent.Callback);
+    method public boolean registerGnssMeasurementsCallback(android.location.GnssMeasurementsEvent.Callback, android.os.Handler);
     method public boolean registerGnssNavigationMessageCallback(android.location.GnssNavigationMessageEvent.Callback);
     method public boolean registerGnssNavigationMessageCallback(android.location.GnssNavigationMessageEvent.Callback, android.os.Handler);
     method public boolean registerGnssStatusCallback(android.location.GnssStatusCallback);
@@ -21009,7 +20956,7 @@
     method public void setTestProviderEnabled(java.lang.String, boolean);
     method public void setTestProviderLocation(java.lang.String, android.location.Location);
     method public void setTestProviderStatus(java.lang.String, int, android.os.Bundle, long);
-    method public void unregisterGnssMeasurementCallback(android.location.GnssMeasurementsEvent.Callback);
+    method public void unregisterGnssMeasurementsCallback(android.location.GnssMeasurementsEvent.Callback);
     method public void unregisterGnssNavigationMessageCallback(android.location.GnssNavigationMessageEvent.Callback);
     method public void unregisterGnssStatusCallback(android.location.GnssStatusCallback);
     field public static final java.lang.String GPS_PROVIDER = "gps";
@@ -21203,7 +21150,7 @@
     field public static final android.os.Parcelable.Creator<android.media.AudioFocusInfo> CREATOR;
   }
 
-  public class AudioFormat implements android.os.Parcelable {
+  public final class AudioFormat implements android.os.Parcelable {
     method public int describeContents();
     method public int getChannelCount();
     method public int getChannelIndexMask();
@@ -21284,7 +21231,7 @@
     method public void adjustVolume(int, int);
     method public void dispatchMediaKeyEvent(android.view.KeyEvent);
     method public int generateAudioSessionId();
-    method public android.media.AudioRecordConfiguration[] getActiveRecordConfigurations();
+    method public android.media.AudioRecordingConfiguration[] getActiveRecordingConfigurations();
     method public android.media.AudioDeviceInfo[] getDevices(int);
     method public int getMode();
     method public java.lang.String getParameters(java.lang.String);
@@ -21438,7 +21385,7 @@
 
   public static abstract class AudioManager.AudioRecordingCallback {
     ctor public AudioManager.AudioRecordingCallback();
-    method public void onRecordConfigChanged();
+    method public void onRecordConfigChanged(android.media.AudioRecordingConfiguration[]);
   }
 
   public static abstract interface AudioManager.OnAudioFocusChangeListener {
@@ -21515,7 +21462,7 @@
     method public abstract void onRoutingChanged(android.media.AudioRecord);
   }
 
-  public class AudioRecordConfiguration implements android.os.Parcelable {
+  public final class AudioRecordingConfiguration implements android.os.Parcelable {
     method public int describeContents();
     method public android.media.AudioDeviceInfo getAudioDevice();
     method public int getClientAudioSessionId();
@@ -21523,12 +21470,13 @@
     method public android.media.AudioFormat getClientFormat();
     method public android.media.AudioFormat getFormat();
     method public void writeToParcel(android.os.Parcel, int);
-    field public static final android.os.Parcelable.Creator<android.media.AudioRecordConfiguration> CREATOR;
+    field public static final android.os.Parcelable.Creator<android.media.AudioRecordingConfiguration> CREATOR;
   }
 
   public abstract interface AudioRouting {
     method public abstract void addOnRoutingListener(android.media.AudioRouting.OnRoutingChangedListener, android.os.Handler);
     method public abstract android.media.AudioDeviceInfo getPreferredDevice();
+    method public abstract android.media.AudioDeviceInfo getRoutedDevice();
     method public abstract void removeOnRoutingListener(android.media.AudioRouting.OnRoutingChangedListener);
     method public abstract boolean setPreferredDevice(android.media.AudioDeviceInfo);
   }
@@ -21730,37 +21678,129 @@
     field public static final int ORIENTATION_TRANSVERSE = 7; // 0x7
     field public static final int ORIENTATION_UNDEFINED = 0; // 0x0
     field public static final java.lang.String TAG_APERTURE = "FNumber";
+    field public static final java.lang.String TAG_APERTURE_VALUE = "ApertureValue";
+    field public static final java.lang.String TAG_ARTIST = "Artist";
+    field public static final java.lang.String TAG_BITS_PER_SAMPLE = "BitsPerSample";
+    field public static final java.lang.String TAG_BRIGHTNESS_VALUE = "BrightnessValue";
+    field public static final java.lang.String TAG_CFA_PATTERN = "CFAPattern";
+    field public static final java.lang.String TAG_COLOR_SPACE = "ColorSpace";
+    field public static final java.lang.String TAG_COMPONENTS_CONFIGURATION = "ComponentsConfiguration";
+    field public static final java.lang.String TAG_COMPRESSED_BITS_PER_PIXEL = "CompressedBitsPerPixel";
+    field public static final java.lang.String TAG_COMPRESSION = "Compression";
+    field public static final java.lang.String TAG_CONTRAST = "Contrast";
+    field public static final java.lang.String TAG_COPYRIGHT = "Copyright";
+    field public static final java.lang.String TAG_CUSTOM_RENDERED = "CustomRendered";
     field public static final java.lang.String TAG_DATETIME = "DateTime";
     field public static final java.lang.String TAG_DATETIME_DIGITIZED = "DateTimeDigitized";
+    field public static final java.lang.String TAG_DATETIME_ORIGINAL = "DateTimeOriginal";
+    field public static final java.lang.String TAG_DEVICE_SETTING_DESCRIPTION = "DeviceSettingDescription";
     field public static final java.lang.String TAG_DIGITAL_ZOOM_RATIO = "DigitalZoomRatio";
+    field public static final java.lang.String TAG_EXIF_VERSION = "ExifVersion";
     field public static final java.lang.String TAG_EXPOSURE_BIAS_VALUE = "ExposureBiasValue";
+    field public static final java.lang.String TAG_EXPOSURE_INDEX = "ExposureIndex";
     field public static final java.lang.String TAG_EXPOSURE_MODE = "ExposureMode";
     field public static final java.lang.String TAG_EXPOSURE_PROGRAM = "ExposureProgram";
     field public static final java.lang.String TAG_EXPOSURE_TIME = "ExposureTime";
+    field public static final java.lang.String TAG_FILE_SOURCE = "FileSource";
     field public static final java.lang.String TAG_FLASH = "Flash";
+    field public static final java.lang.String TAG_FLASHPIX_VERSION = "FlashpixVersion";
+    field public static final java.lang.String TAG_FLASH_ENERGY = "FlashEnergy";
     field public static final java.lang.String TAG_FOCAL_LENGTH = "FocalLength";
+    field public static final java.lang.String TAG_FOCAL_LENGTH_IN_35MM_FILM = "FocalLengthIn35mmFilm";
+    field public static final java.lang.String TAG_FOCAL_PLANE_RESOLUTION_UNIT = "FocalPlaneResolutionUnit";
+    field public static final java.lang.String TAG_FOCAL_PLANE_X_RESOLUTION = "FocalPlaneXResolution";
+    field public static final java.lang.String TAG_FOCAL_PLANE_Y_RESOLUTION = "FocalPlaneYResolution";
+    field public static final java.lang.String TAG_F_NUMBER = "FNumber";
+    field public static final java.lang.String TAG_GAIN_CONTROL = "GainControl";
     field public static final java.lang.String TAG_GPS_ALTITUDE = "GPSAltitude";
     field public static final java.lang.String TAG_GPS_ALTITUDE_REF = "GPSAltitudeRef";
+    field public static final java.lang.String TAG_GPS_AREA_INFORMATION = "GPSAreaInformation";
     field public static final java.lang.String TAG_GPS_DATESTAMP = "GPSDateStamp";
+    field public static final java.lang.String TAG_GPS_DEST_BEARING = "GPSDestBearing";
+    field public static final java.lang.String TAG_GPS_DEST_BEARING_REF = "GPSDestBearingRef";
+    field public static final java.lang.String TAG_GPS_DEST_DISTANCE = "GPSDestDistance";
+    field public static final java.lang.String TAG_GPS_DEST_DISTANCE_REF = "GPSDestDistanceRef";
+    field public static final java.lang.String TAG_GPS_DEST_LATITUDE = "GPSDestLatitude";
+    field public static final java.lang.String TAG_GPS_DEST_LATITUDE_REF = "GPSDestLatitudeRef";
+    field public static final java.lang.String TAG_GPS_DEST_LONGITUDE = "GPSDestLongitude";
+    field public static final java.lang.String TAG_GPS_DEST_LONGITUDE_REF = "GPSDestLongitudeRef";
+    field public static final java.lang.String TAG_GPS_DIFFERENTIAL = "GPSDifferential";
+    field public static final java.lang.String TAG_GPS_DOP = "GPSDOP";
+    field public static final java.lang.String TAG_GPS_IMG_DIRECTION = "GPSImgDirection";
+    field public static final java.lang.String TAG_GPS_IMG_DIRECTION_REF = "GPSImgDirectionRef";
     field public static final java.lang.String TAG_GPS_LATITUDE = "GPSLatitude";
     field public static final java.lang.String TAG_GPS_LATITUDE_REF = "GPSLatitudeRef";
     field public static final java.lang.String TAG_GPS_LONGITUDE = "GPSLongitude";
     field public static final java.lang.String TAG_GPS_LONGITUDE_REF = "GPSLongitudeRef";
+    field public static final java.lang.String TAG_GPS_MAP_DATUM = "GPSMapDatum";
+    field public static final java.lang.String TAG_GPS_MEASURE_MODE = "GPSMeasureMode";
     field public static final java.lang.String TAG_GPS_PROCESSING_METHOD = "GPSProcessingMethod";
+    field public static final java.lang.String TAG_GPS_SATELLITES = "GPSSatellites";
+    field public static final java.lang.String TAG_GPS_SPEED = "GPSSpeed";
+    field public static final java.lang.String TAG_GPS_SPEED_REF = "GPSSpeedRef";
+    field public static final java.lang.String TAG_GPS_STATUS = "GPSStatus";
     field public static final java.lang.String TAG_GPS_TIMESTAMP = "GPSTimeStamp";
+    field public static final java.lang.String TAG_GPS_TRACK = "GPSTrack";
+    field public static final java.lang.String TAG_GPS_TRACK_REF = "GPSTrackRef";
+    field public static final java.lang.String TAG_GPS_VERSION_ID = "GPSVersionID";
+    field public static final java.lang.String TAG_IMAGE_DESCRIPTION = "ImageDescription";
     field public static final java.lang.String TAG_IMAGE_LENGTH = "ImageLength";
+    field public static final java.lang.String TAG_IMAGE_UNIQUE_ID = "ImageUniqueID";
     field public static final java.lang.String TAG_IMAGE_WIDTH = "ImageWidth";
+    field public static final java.lang.String TAG_INTEROPERABILITY_INDEX = "InteroperabilityIndex";
     field public static final java.lang.String TAG_ISO = "ISOSpeedRatings";
+    field public static final java.lang.String TAG_ISO_SPEED_RATINGS = "ISOSpeedRatings";
+    field public static final java.lang.String TAG_JPEG_INTERCHANGE_FORMAT = "JPEGInterchangeFormat";
+    field public static final java.lang.String TAG_JPEG_INTERCHANGE_FORMAT_LENGTH = "JPEGInterchangeFormatLength";
     field public static final java.lang.String TAG_LIGHT_SOURCE = "LightSource";
     field public static final java.lang.String TAG_MAKE = "Make";
+    field public static final java.lang.String TAG_MAKER_NOTE = "MakerNote";
+    field public static final java.lang.String TAG_MAX_APERTURE_VALUE = "MaxApertureValue";
     field public static final java.lang.String TAG_METERING_MODE = "MeteringMode";
     field public static final java.lang.String TAG_MODEL = "Model";
+    field public static final java.lang.String TAG_OECF = "OECF";
     field public static final java.lang.String TAG_ORIENTATION = "Orientation";
+    field public static final java.lang.String TAG_PHOTOMETRIC_INTERPRETATION = "PhotometricInterpretation";
+    field public static final java.lang.String TAG_PIXEL_X_DIMENSION = "PixelXDimension";
+    field public static final java.lang.String TAG_PIXEL_Y_DIMENSION = "PixelYDimension";
+    field public static final java.lang.String TAG_PLANAR_CONFIGURATION = "PlanarConfiguration";
+    field public static final java.lang.String TAG_PRIMARY_CHROMATICITIES = "PrimaryChromaticities";
+    field public static final java.lang.String TAG_REFERENCE_BLACK_WHITE = "ReferenceBlackWhite";
+    field public static final java.lang.String TAG_RELATED_SOUND_FILE = "RelatedSoundFile";
+    field public static final java.lang.String TAG_RESOLUTION_UNIT = "ResolutionUnit";
+    field public static final java.lang.String TAG_ROWS_PER_STRIP = "RowsPerStrip";
+    field public static final java.lang.String TAG_SAMPLES_PER_PIXEL = "SamplesPerPixel";
+    field public static final java.lang.String TAG_SATURATION = "Saturation";
+    field public static final java.lang.String TAG_SCENE_CAPTURE_TYPE = "SceneCaptureType";
+    field public static final java.lang.String TAG_SCENE_TYPE = "SceneType";
+    field public static final java.lang.String TAG_SENSING_METHOD = "SensingMethod";
+    field public static final java.lang.String TAG_SHARPNESS = "Sharpness";
+    field public static final java.lang.String TAG_SHUTTER_SPEED_VALUE = "ShutterSpeedValue";
+    field public static final java.lang.String TAG_SOFTWARE = "Software";
+    field public static final java.lang.String TAG_SPATIAL_FREQUENCY_RESPONSE = "SpatialFrequencyResponse";
+    field public static final java.lang.String TAG_SPECTRAL_SENSITIVITY = "SpectralSensitivity";
+    field public static final java.lang.String TAG_STRIP_BYTE_COUNTS = "StripByteCounts";
+    field public static final java.lang.String TAG_STRIP_OFFSETS = "StripOffsets";
+    field public static final java.lang.String TAG_SUBJECT_AREA = "SubjectArea";
     field public static final java.lang.String TAG_SUBJECT_DISTANCE = "SubjectDistance";
+    field public static final java.lang.String TAG_SUBJECT_DISTANCE_RANGE = "SubjectDistanceRange";
+    field public static final java.lang.String TAG_SUBJECT_LOCATION = "SubjectLocation";
     field public static final java.lang.String TAG_SUBSEC_TIME = "SubSecTime";
     field public static final java.lang.String TAG_SUBSEC_TIME_DIG = "SubSecTimeDigitized";
+    field public static final java.lang.String TAG_SUBSEC_TIME_DIGITIZED = "SubSecTimeDigitized";
     field public static final java.lang.String TAG_SUBSEC_TIME_ORIG = "SubSecTimeOriginal";
+    field public static final java.lang.String TAG_SUBSEC_TIME_ORIGINAL = "SubSecTimeOriginal";
+    field public static final java.lang.String TAG_THUMBNAIL_IMAGE_LENGTH = "ThumbnailImageLength";
+    field public static final java.lang.String TAG_THUMBNAIL_IMAGE_WIDTH = "ThumbnailImageWidth";
+    field public static final java.lang.String TAG_TRANSFER_FUNCTION = "TransferFunction";
+    field public static final java.lang.String TAG_USER_COMMENT = "UserComment";
     field public static final java.lang.String TAG_WHITE_BALANCE = "WhiteBalance";
+    field public static final java.lang.String TAG_WHITE_POINT = "WhitePoint";
+    field public static final java.lang.String TAG_X_RESOLUTION = "XResolution";
+    field public static final java.lang.String TAG_Y_CB_CR_COEFFICIENTS = "YCbCrCoefficients";
+    field public static final java.lang.String TAG_Y_CB_CR_POSITIONING = "YCbCrPositioning";
+    field public static final java.lang.String TAG_Y_CB_CR_SUB_SAMPLING = "YCbCrSubSampling";
+    field public static final java.lang.String TAG_Y_RESOLUTION = "YResolution";
     field public static final int WHITEBALANCE_AUTO = 0; // 0x0
     field public static final int WHITEBALANCE_MANUAL = 1; // 0x1
   }
@@ -21958,6 +21998,7 @@
     field public static final int ERROR_NO_KEY = 1; // 0x1
     field public static final int ERROR_RESOURCE_BUSY = 3; // 0x3
     field public static final int ERROR_SESSION_NOT_OPENED = 5; // 0x5
+    field public static final int ERROR_UNSUPPORTED_OPERATION = 6; // 0x6
   }
 
   public static final class MediaCodec.CryptoInfo {
@@ -22166,6 +22207,7 @@
     field public static final int HEVCMainTierLevel62 = 16777216; // 0x1000000
     field public static final int HEVCProfileMain = 1; // 0x1
     field public static final int HEVCProfileMain10 = 2; // 0x2
+    field public static final int HEVCProfileMain10HDR10 = 4096; // 0x1000
     field public static final int MPEG2LevelH14 = 2; // 0x2
     field public static final int MPEG2LevelHL = 3; // 0x3
     field public static final int MPEG2LevelLL = 0; // 0x0
@@ -22423,6 +22465,7 @@
     method public final void setDataSource(android.content.Context, android.net.Uri, java.util.Map<java.lang.String, java.lang.String>) throws java.io.IOException;
     method public final void setDataSource(java.lang.String, java.util.Map<java.lang.String, java.lang.String>) throws java.io.IOException;
     method public final void setDataSource(java.lang.String) throws java.io.IOException;
+    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 void unselectTrack(int);
@@ -22483,6 +22526,7 @@
     field public static final java.lang.String KEY_DURATION = "durationUs";
     field public static final java.lang.String KEY_FLAC_COMPRESSION_LEVEL = "flac-compression-level";
     field public static final java.lang.String KEY_FRAME_RATE = "frame-rate";
+    field public static final java.lang.String KEY_HDR_STATIC_INFO = "hdr-static-info";
     field public static final java.lang.String KEY_HEIGHT = "height";
     field public static final java.lang.String KEY_INTRA_REFRESH_PERIOD = "intra-refresh-period";
     field public static final java.lang.String KEY_IS_ADTS = "is-adts";
@@ -22507,6 +22551,7 @@
     field public static final java.lang.String KEY_SLICE_HEIGHT = "slice-height";
     field public static final java.lang.String KEY_STRIDE = "stride";
     field public static final java.lang.String KEY_TEMPORAL_LAYERING = "ts-schema";
+    field public static final java.lang.String KEY_TRACK_ID = "track-id";
     field public static final java.lang.String KEY_WIDTH = "width";
     field public static final java.lang.String MIMETYPE_AUDIO_AAC = "audio/mp4a-latm";
     field public static final java.lang.String MIMETYPE_AUDIO_AC3 = "audio/ac3";
@@ -24643,6 +24688,7 @@
     method public boolean isPassthroughInput();
     method public java.lang.CharSequence loadCustomLabel(android.content.Context);
     method public android.graphics.drawable.Drawable loadIcon(android.content.Context);
+    method public android.graphics.drawable.Drawable loadIcon(android.content.Context, int);
     method public java.lang.CharSequence loadLabel(android.content.Context);
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.media.tv.TvInputInfo> CREATOR;
@@ -24660,11 +24706,12 @@
   }
 
   public static final class TvInputInfo.Builder {
-    ctor public TvInputInfo.Builder(android.content.Context, java.lang.Class<?>);
+    ctor public TvInputInfo.Builder(android.content.Context, android.content.ComponentName);
     method public android.media.tv.TvInputInfo build() throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
     method public android.media.tv.TvInputInfo.Builder setCanRecord(boolean);
     method public android.media.tv.TvInputInfo.Builder setHdmiDeviceInfo(android.hardware.hdmi.HdmiDeviceInfo);
     method public android.media.tv.TvInputInfo.Builder setIcon(android.graphics.drawable.Icon);
+    method public android.media.tv.TvInputInfo.Builder setIcon(android.graphics.drawable.Icon, int);
     method public android.media.tv.TvInputInfo.Builder setLabel(int);
     method public android.media.tv.TvInputInfo.Builder setParentId(java.lang.String);
     method public android.media.tv.TvInputInfo.Builder setTunerCount(int);
@@ -24804,7 +24851,7 @@
     method public void notifyError(int);
     method public void notifyRecordingStopped(android.net.Uri);
     method public void notifySessionEvent(java.lang.String, android.os.Bundle);
-    method public void notifyTuned();
+    method public void notifyTuned(android.net.Uri);
     method public void onAppPrivateCommand(java.lang.String, android.os.Bundle);
     method public abstract void onRelease();
     method public abstract void onStartRecording(android.net.Uri);
@@ -24872,7 +24919,7 @@
     method public void onError(int);
     method public void onEvent(java.lang.String, java.lang.String, android.os.Bundle);
     method public void onRecordingStopped(android.net.Uri);
-    method public void onTuned();
+    method public void onTuned(android.net.Uri);
   }
 
   public class TvStreamConfig implements android.os.Parcelable {
@@ -24946,7 +24993,6 @@
     method public java.util.List<android.media.tv.TvTrackInfo> getTracks(int);
     method protected void onLayout(boolean, int, int, int, int);
     method public boolean onUnhandledInputEvent(android.view.InputEvent);
-    method public deprecated void requestUnblockContent(android.media.tv.TvContentRating);
     method public void reset();
     method public void selectTrack(int, java.lang.String);
     method public void sendAppPrivateCommand(java.lang.String, android.os.Bundle);
@@ -25340,17 +25386,6 @@
     method public void onTetheringStarted();
   }
 
-  public 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 class Credentials {
     ctor public Credentials(int, int, int);
     method public int getGid();
@@ -25358,7 +25393,7 @@
     method public int getUid();
   }
 
-  public class DataUsageRequest implements android.os.Parcelable {
+  public final class DataUsageRequest 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.DataUsageRequest> CREATOR;
@@ -26753,7 +26788,6 @@
     method public boolean reconnect();
     method public boolean removeNetwork(int);
     method public boolean saveConfiguration();
-    method public boolean setMetered(int, boolean);
     method public void setTdlsEnabled(java.net.InetAddress, boolean);
     method public void setTdlsEnabledWithMacAddress(java.lang.String, boolean);
     method public boolean setWifiApConfiguration(android.net.wifi.WifiConfiguration);
@@ -29157,7 +29191,8 @@
     method public static void glGetSynciv(long, int, int, int[], int, int[], int);
     method public static void glGetSynciv(long, int, int, java.nio.IntBuffer, java.nio.IntBuffer);
     method public static void glGetTransformFeedbackVarying(int, int, int, int[], int, int[], int, int[], int, byte[], int);
-    method public static void glGetTransformFeedbackVarying(int, int, int, java.nio.IntBuffer, java.nio.IntBuffer, java.nio.IntBuffer, byte);
+    method public static deprecated void glGetTransformFeedbackVarying(int, int, int, java.nio.IntBuffer, java.nio.IntBuffer, java.nio.IntBuffer, byte);
+    method public static void glGetTransformFeedbackVarying(int, int, int, java.nio.IntBuffer, java.nio.IntBuffer, java.nio.IntBuffer, java.nio.ByteBuffer);
     method public static java.lang.String glGetTransformFeedbackVarying(int, int, int[], int, int[], int);
     method public static java.lang.String glGetTransformFeedbackVarying(int, int, java.nio.IntBuffer, java.nio.IntBuffer);
     method public static int glGetUniformBlockIndex(int, java.lang.String);
@@ -30769,6 +30804,10 @@
     ctor public DeadObjectException(java.lang.String);
   }
 
+  public class DeadSystemException extends android.os.DeadObjectException {
+    ctor public DeadSystemException();
+  }
+
   public final class Debug {
     method public static deprecated void changeDebugPort(int);
     method public static void dumpHprofData(java.lang.String) throws java.io.IOException;
@@ -31424,7 +31463,10 @@
   public class Process {
     ctor public Process();
     method public static final long getElapsedCpuTime();
+    method public static final int[] getExclusiveCores();
     method public static final int getGidForName(java.lang.String);
+    method public static final long getStartElapsedRealtime();
+    method public static final long getStartUptimeMillis();
     method public static final int getThreadPriority(int) throws java.lang.IllegalArgumentException;
     method public static final int getUidForName(java.lang.String);
     method public static final boolean is64Bit();
@@ -31767,6 +31809,147 @@
 
 }
 
+package android.os.health {
+
+  public class HealthStats {
+    method public java.lang.String getDataType();
+    method public long getMeasurement(int);
+    method public int getMeasurementKeyAt(int);
+    method public int getMeasurementKeyCount();
+    method public java.util.Map<java.lang.String, java.lang.Long> getMeasurements(int);
+    method public int getMeasurementsKeyAt(int);
+    method public int getMeasurementsKeyCount();
+    method public java.util.Map<java.lang.String, android.os.health.HealthStats> getStats(int);
+    method public int getStatsKeyAt(int);
+    method public int getStatsKeyCount();
+    method public android.os.health.TimerStat getTimer(int);
+    method public int getTimerCount(int);
+    method public int getTimerKeyAt(int);
+    method public int getTimerKeyCount();
+    method public long getTimerTime(int);
+    method public java.util.Map<java.lang.String, android.os.health.TimerStat> getTimers(int);
+    method public int getTimersKeyAt(int);
+    method public int getTimersKeyCount();
+    method public boolean hasMeasurement(int);
+    method public boolean hasMeasurements(int);
+    method public boolean hasStats(int);
+    method public boolean hasTimer(int);
+    method public boolean hasTimers(int);
+  }
+
+  public final class PackageHealthStats {
+    field public static final int MEASUREMENTS_WAKEUP_ALARMS_COUNT = 40002; // 0x9c42
+    field public static final int STATS_SERVICES = 40001; // 0x9c41
+  }
+
+  public final class PidHealthStats {
+    field public static final int MEASUREMENT_WAKE_NESTING_COUNT = 20001; // 0x4e21
+    field public static final int MEASUREMENT_WAKE_START_MS = 20003; // 0x4e23
+    field public static final int MEASUREMENT_WAKE_SUM_MS = 20002; // 0x4e22
+  }
+
+  public final class ProcessHealthStats {
+    field public static final int MEASUREMENT_ANR_COUNT = 30005; // 0x7535
+    field public static final int MEASUREMENT_CRASHES_COUNT = 30004; // 0x7534
+    field public static final int MEASUREMENT_FOREGROUND_MS = 30006; // 0x7536
+    field public static final int MEASUREMENT_STARTS_COUNT = 30003; // 0x7533
+    field public static final int MEASUREMENT_SYSTEM_TIME_MS = 30002; // 0x7532
+    field public static final int MEASUREMENT_USER_TIME_MS = 30001; // 0x7531
+  }
+
+  public final class ServiceHealthStats {
+    field public static final int MEASUREMENT_LAUNCH_COUNT = 50002; // 0xc352
+    field public static final int MEASUREMENT_START_SERVICE_COUNT = 50001; // 0xc351
+  }
+
+  public class SystemHealthManager {
+    method public static android.os.health.SystemHealthManager from(android.content.Context);
+    method public android.os.health.HealthStats takeMyUidSnapshot();
+    method public android.os.health.HealthStats takeUidSnapshot(int);
+    method public android.os.health.HealthStats[] takeUidSnapshots(int[]);
+  }
+
+  public class TimerStat implements android.os.Parcelable {
+    ctor public TimerStat();
+    ctor public TimerStat(int, long);
+    ctor public TimerStat(android.os.Parcel);
+    method public int describeContents();
+    method public int getCount();
+    method public long getTime();
+    method public void setCount(int);
+    method public void setTime(long);
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.os.health.TimerStat> CREATOR;
+  }
+
+  public final class UidHealthStats {
+    field public static final int MEASUREMENT_BLUETOOTH_IDLE_MS = 10020; // 0x2724
+    field public static final int MEASUREMENT_BLUETOOTH_POWER_MAMS = 10023; // 0x2727
+    field public static final int MEASUREMENT_BLUETOOTH_RX_BYTES = 10052; // 0x2744
+    field public static final int MEASUREMENT_BLUETOOTH_RX_MS = 10021; // 0x2725
+    field public static final int MEASUREMENT_BLUETOOTH_RX_PACKETS = 10058; // 0x274a
+    field public static final int MEASUREMENT_BLUETOOTH_TX_BYTES = 10053; // 0x2745
+    field public static final int MEASUREMENT_BLUETOOTH_TX_MS = 10022; // 0x2726
+    field public static final int MEASUREMENT_BLUETOOTH_TX_PACKETS = 10059; // 0x274b
+    field public static final int MEASUREMENT_BUTTON_USER_ACTIVITY_COUNT = 10046; // 0x273e
+    field public static final int MEASUREMENT_CPU_POWER_MAUS = 10064; // 0x2750
+    field public static final int MEASUREMENT_MOBILE_IDLE_MS = 10024; // 0x2728
+    field public static final int MEASUREMENT_MOBILE_POWER_MAMS = 10027; // 0x272b
+    field public static final int MEASUREMENT_MOBILE_RX_BYTES = 10048; // 0x2740
+    field public static final int MEASUREMENT_MOBILE_RX_MS = 10025; // 0x2729
+    field public static final int MEASUREMENT_MOBILE_RX_PACKETS = 10054; // 0x2746
+    field public static final int MEASUREMENT_MOBILE_TX_BYTES = 10049; // 0x2741
+    field public static final int MEASUREMENT_MOBILE_TX_MS = 10026; // 0x272a
+    field public static final int MEASUREMENT_MOBILE_TX_PACKETS = 10055; // 0x2747
+    field public static final int MEASUREMENT_OTHER_USER_ACTIVITY_COUNT = 10045; // 0x273d
+    field public static final int MEASUREMENT_REALTIME_BATTERY_MS = 10001; // 0x2711
+    field public static final int MEASUREMENT_REALTIME_SCREEN_OFF_BATTERY_MS = 10003; // 0x2713
+    field public static final int MEASUREMENT_SYSTEM_CPU_TIME_US = 10063; // 0x274f
+    field public static final int MEASUREMENT_TOUCH_USER_ACTIVITY_COUNT = 10047; // 0x273f
+    field public static final int MEASUREMENT_UPTIME_BATTERY_MS = 10002; // 0x2712
+    field public static final int MEASUREMENT_UPTIME_SCREEN_OFF_BATTERY_MS = 10004; // 0x2714
+    field public static final int MEASUREMENT_USER_CPU_TIME_US = 10062; // 0x274e
+    field public static final int MEASUREMENT_WIFI_FULL_LOCK_MS = 10029; // 0x272d
+    field public static final int MEASUREMENT_WIFI_IDLE_MS = 10016; // 0x2720
+    field public static final int MEASUREMENT_WIFI_MULTICAST_MS = 10031; // 0x272f
+    field public static final int MEASUREMENT_WIFI_POWER_MAMS = 10019; // 0x2723
+    field public static final int MEASUREMENT_WIFI_RUNNING_MS = 10028; // 0x272c
+    field public static final int MEASUREMENT_WIFI_RX_BYTES = 10050; // 0x2742
+    field public static final int MEASUREMENT_WIFI_RX_MS = 10017; // 0x2721
+    field public static final int MEASUREMENT_WIFI_RX_PACKETS = 10056; // 0x2748
+    field public static final int MEASUREMENT_WIFI_TX_BYTES = 10051; // 0x2743
+    field public static final int MEASUREMENT_WIFI_TX_MS = 10018; // 0x2722
+    field public static final int MEASUREMENT_WIFI_TX_PACKETS = 10057; // 0x2749
+    field public static final int STATS_PACKAGES = 10015; // 0x271f
+    field public static final int STATS_PIDS = 10013; // 0x271d
+    field public static final int STATS_PROCESSES = 10014; // 0x271e
+    field public static final int TIMERS_JOBS = 10010; // 0x271a
+    field public static final int TIMERS_SENSORS = 10012; // 0x271c
+    field public static final int TIMERS_SYNCS = 10009; // 0x2719
+    field public static final int TIMERS_WAKELOCKS_DRAW = 10008; // 0x2718
+    field public static final int TIMERS_WAKELOCKS_FULL = 10005; // 0x2715
+    field public static final int TIMERS_WAKELOCKS_PARTIAL = 10006; // 0x2716
+    field public static final int TIMERS_WAKELOCKS_WINDOW = 10007; // 0x2717
+    field public static final int TIMER_AUDIO = 10032; // 0x2730
+    field public static final int TIMER_BLUETOOTH_SCAN = 10037; // 0x2735
+    field public static final int TIMER_CAMERA = 10035; // 0x2733
+    field public static final int TIMER_FLASHLIGHT = 10034; // 0x2732
+    field public static final int TIMER_FOREGROUND_ACTIVITY = 10036; // 0x2734
+    field public static final int TIMER_GPS_SENSOR = 10011; // 0x271b
+    field public static final int TIMER_MOBILE_RADIO_ACTIVE = 10061; // 0x274d
+    field public static final int TIMER_PROCESS_STATE_BACKGROUND_MS = 10042; // 0x273a
+    field public static final int TIMER_PROCESS_STATE_CACHED_MS = 10043; // 0x273b
+    field public static final int TIMER_PROCESS_STATE_FOREGROUND_MS = 10041; // 0x2739
+    field public static final int TIMER_PROCESS_STATE_FOREGROUND_SERVICE_MS = 10039; // 0x2737
+    field public static final int TIMER_PROCESS_STATE_TOP_MS = 10038; // 0x2736
+    field public static final int TIMER_PROCESS_STATE_TOP_SLEEPING_MS = 10040; // 0x2738
+    field public static final int TIMER_VIBRATOR = 10044; // 0x273c
+    field public static final int TIMER_VIDEO = 10033; // 0x2731
+    field public static final int TIMER_WIFI_SCAN = 10030; // 0x272e
+  }
+
+}
+
 package android.os.storage {
 
   public abstract class OnObbStateChangeListener {
@@ -31791,7 +31974,7 @@
     method public boolean unmountObb(java.lang.String, boolean, android.os.storage.OnObbStateChangeListener);
   }
 
-  public class StorageVolume implements android.os.Parcelable {
+  public final class StorageVolume implements android.os.Parcelable {
     method public android.content.Intent createAccessIntent(java.lang.String);
     method public int describeContents();
     method public java.lang.String getDescription(android.content.Context);
@@ -32625,7 +32808,7 @@
     field public static final java.lang.String COLUMN_ID = "_id";
     field public static final java.lang.String COLUMN_ORIGINAL_NUMBER = "original_number";
     field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/blocked_number";
-    field public static final java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/blocked_numbers";
+    field public static final java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/blocked_number";
     field public static final android.net.Uri CONTENT_URI;
   }
 
@@ -34182,6 +34365,7 @@
 
   public static final class DocumentsContract.Root {
     field public static final java.lang.String COLUMN_AVAILABLE_BYTES = "available_bytes";
+    field public static final java.lang.String COLUMN_CAPACITY_BYTES = "capacity_bytes";
     field public static final java.lang.String COLUMN_DOCUMENT_ID = "document_id";
     field public static final java.lang.String COLUMN_FLAGS = "flags";
     field public static final java.lang.String COLUMN_ICON = "icon";
@@ -34738,6 +34922,7 @@
     field public static final java.lang.String ACTION_VOICE_CONTROL_BATTERY_SAVER_MODE = "android.settings.VOICE_CONTROL_BATTERY_SAVER_MODE";
     field public static final java.lang.String ACTION_VOICE_CONTROL_DO_NOT_DISTURB_MODE = "android.settings.VOICE_CONTROL_DO_NOT_DISTURB_MODE";
     field public static final java.lang.String ACTION_VOICE_INPUT_SETTINGS = "android.settings.VOICE_INPUT_SETTINGS";
+    field public static final java.lang.String ACTION_VR_LISTENER_SETTINGS = "android.settings.VR_LISTENER_SETTINGS";
     field public static final java.lang.String ACTION_WIFI_IP_SETTINGS = "android.settings.WIFI_IP_SETTINGS";
     field public static final java.lang.String ACTION_WIFI_SETTINGS = "android.settings.WIFI_SETTINGS";
     field public static final java.lang.String ACTION_WIRELESS_SETTINGS = "android.settings.WIRELESS_SETTINGS";
@@ -34775,6 +34960,7 @@
     field public static final java.lang.String AUTO_TIME = "auto_time";
     field public static final java.lang.String AUTO_TIME_ZONE = "auto_time_zone";
     field public static final java.lang.String BLUETOOTH_ON = "bluetooth_on";
+    field public static final java.lang.String BOOT_COUNT = "boot_count";
     field public static final java.lang.String CONTACT_METADATA_SYNC = "contact_metadata_sync";
     field public static final android.net.Uri CONTENT_URI;
     field public static final java.lang.String DATA_ROAMING = "data_roaming";
@@ -36809,7 +36995,8 @@
     ctor public CarrierMessagingService();
     method public android.os.IBinder onBind(android.content.Intent);
     method public void onDownloadMms(android.net.Uri, int, android.net.Uri, android.service.carrier.CarrierMessagingService.ResultCallback<java.lang.Integer>);
-    method public void onFilterSms(android.service.carrier.MessagePdu, java.lang.String, int, int, android.service.carrier.CarrierMessagingService.ResultCallback<java.lang.Boolean>);
+    method public deprecated void onFilterSms(android.service.carrier.MessagePdu, java.lang.String, int, int, android.service.carrier.CarrierMessagingService.ResultCallback<java.lang.Boolean>);
+    method public void onReceiveTextSms(android.service.carrier.MessagePdu, java.lang.String, int, int, android.service.carrier.CarrierMessagingService.ResultCallback<java.lang.Integer>);
     method public deprecated void onSendDataSms(byte[], int, java.lang.String, int, android.service.carrier.CarrierMessagingService.ResultCallback<android.service.carrier.CarrierMessagingService.SendSmsResult>);
     method public void onSendDataSms(byte[], int, java.lang.String, int, int, android.service.carrier.CarrierMessagingService.ResultCallback<android.service.carrier.CarrierMessagingService.SendSmsResult>);
     method public void onSendMms(android.net.Uri, int, android.net.Uri, android.service.carrier.CarrierMessagingService.ResultCallback<android.service.carrier.CarrierMessagingService.SendMmsResult>);
@@ -36820,6 +37007,9 @@
     field public static final int DOWNLOAD_STATUS_ERROR = 2; // 0x2
     field public static final int DOWNLOAD_STATUS_OK = 0; // 0x0
     field public static final int DOWNLOAD_STATUS_RETRY_ON_CARRIER_NETWORK = 1; // 0x1
+    field public static final int RECEIVE_OPTIONS_DEFAULT = 0; // 0x0
+    field public static final int RECEIVE_OPTIONS_DROP = 1; // 0x1
+    field public static final int RECEIVE_OPTIONS_SKIP_NOTIFY_WHEN_CREDENTIAL_ENCRYPTED_STORAGE_UNAVAILABLE = 2; // 0x2
     field public static final int SEND_FLAG_REQUEST_DELIVERY_STATUS = 1; // 0x1
     field public static final int SEND_STATUS_ERROR = 2; // 0x2
     field public static final int SEND_STATUS_OK = 0; // 0x0
@@ -36988,8 +37178,9 @@
 package android.service.notification {
 
   public class Condition implements android.os.Parcelable {
-    ctor public Condition(android.net.Uri, java.lang.String, java.lang.String, java.lang.String, int);
+    ctor public Condition(android.net.Uri, java.lang.String, int);
     ctor public Condition(android.net.Uri, java.lang.String, java.lang.String, java.lang.String, int, int, int);
+    ctor public Condition(android.os.Parcel);
     method public android.service.notification.Condition copy();
     method public int describeContents();
     method public static boolean isValidId(android.net.Uri, java.lang.String);
@@ -37030,36 +37221,6 @@
     field public static final java.lang.String SERVICE_INTERFACE = "android.service.notification.ConditionProviderService";
   }
 
-  public abstract class NotificationAssistantService extends android.service.notification.NotificationListenerService {
-    ctor public NotificationAssistantService();
-    method public final void adjustImportance(java.lang.String, android.service.notification.NotificationAssistantService.Adjustment);
-    method public void onNotificationActionClick(java.lang.String, long, int);
-    method public void onNotificationClick(java.lang.String, long);
-    method public abstract android.service.notification.NotificationAssistantService.Adjustment onNotificationEnqueued(android.service.notification.StatusBarNotification, int, boolean);
-    method public void onNotificationRemoved(java.lang.String, long, int);
-    method public void onNotificationVisibilityChanged(java.lang.String, long, boolean);
-    field public static final int REASON_APP_CANCEL = 8; // 0x8
-    field public static final int REASON_APP_CANCEL_ALL = 9; // 0x9
-    field public static final int REASON_DELEGATE_CANCEL = 2; // 0x2
-    field public static final int REASON_DELEGATE_CANCEL_ALL = 3; // 0x3
-    field public static final int REASON_DELEGATE_CLICK = 1; // 0x1
-    field public static final int REASON_DELEGATE_ERROR = 4; // 0x4
-    field public static final int REASON_GROUP_OPTIMIZATION = 13; // 0xd
-    field public static final int REASON_GROUP_SUMMARY_CANCELED = 12; // 0xc
-    field public static final int REASON_LISTENER_CANCEL = 10; // 0xa
-    field public static final int REASON_LISTENER_CANCEL_ALL = 11; // 0xb
-    field public static final int REASON_PACKAGE_BANNED = 7; // 0x7
-    field public static final int REASON_PACKAGE_CHANGED = 5; // 0x5
-    field public static final int REASON_PACKAGE_SUSPENDED = 14; // 0xe
-    field public static final int REASON_PROFILE_TURNED_OFF = 15; // 0xf
-    field public static final int REASON_USER_STOPPED = 6; // 0x6
-    field public static final java.lang.String SERVICE_INTERFACE = "android.service.notification.NotificationAssistantService";
-  }
-
-  public class NotificationAssistantService.Adjustment {
-    ctor public NotificationAssistantService.Adjustment(int, java.lang.CharSequence, android.net.Uri);
-  }
-
   public abstract class NotificationListenerService extends android.app.Service {
     ctor public NotificationListenerService();
     method public final void cancelAllNotifications();
@@ -37085,12 +37246,11 @@
     method public void registerAsSystemService(android.content.Context, android.content.ComponentName, int) throws android.os.RemoteException;
     method public final void requestInterruptionFilter(int);
     method public final void requestListenerHints(int);
-    method public static final void requestRebind(android.content.ComponentName) throws android.os.RemoteException;
+    method public static void requestRebind(android.content.ComponentName) throws android.os.RemoteException;
     method public final void requestUnbind() throws android.os.RemoteException;
     method public final void setNotificationsShown(java.lang.String[]);
     method public final void setOnNotificationPostedTrim(int);
     method public void unregisterAsSystemService() throws android.os.RemoteException;
-    field public static final java.lang.String CATEGORY_VR_NOTIFICATIONS = "android.intent.category.vr.notifications";
     field public static final int HINT_HOST_DISABLE_EFFECTS = 1; // 0x1
     field public static final int INTERRUPTION_FILTER_ALARMS = 4; // 0x4
     field public static final int INTERRUPTION_FILTER_ALL = 1; // 0x1
@@ -37113,10 +37273,11 @@
     method public int getSuppressedVisualEffects();
     method public boolean isAmbient();
     method public boolean matchesInterruptionFilter();
-    field public static final int IMPORTANCE_DEFAULT = 2; // 0x2
-    field public static final int IMPORTANCE_HIGH = 3; // 0x3
-    field public static final int IMPORTANCE_LOW = 1; // 0x1
-    field public static final int IMPORTANCE_MAX = 4; // 0x4
+    field public static final int IMPORTANCE_DEFAULT = 3; // 0x3
+    field public static final int IMPORTANCE_HIGH = 4; // 0x4
+    field public static final int IMPORTANCE_LOW = 2; // 0x2
+    field public static final int IMPORTANCE_MAX = 5; // 0x5
+    field public static final int IMPORTANCE_MIN = 1; // 0x1
     field public static final int IMPORTANCE_NONE = 0; // 0x0
     field public static final int IMPORTANCE_UNSPECIFIED = -1000; // 0xfffffc18
   }
@@ -37129,6 +37290,37 @@
     field public static final android.os.Parcelable.Creator<android.service.notification.NotificationListenerService.RankingMap> CREATOR;
   }
 
+  public abstract class NotificationRankerService extends android.service.notification.NotificationListenerService {
+    ctor public NotificationRankerService();
+    method public final void adjustImportance(java.lang.String, android.service.notification.NotificationRankerService.Adjustment);
+    method public final android.os.IBinder onBind(android.content.Intent);
+    method public void onNotificationActionClick(java.lang.String, long, int);
+    method public void onNotificationClick(java.lang.String, long);
+    method public abstract android.service.notification.NotificationRankerService.Adjustment onNotificationEnqueued(android.service.notification.StatusBarNotification, int, boolean);
+    method public void onNotificationRemoved(java.lang.String, long, int);
+    method public void onNotificationVisibilityChanged(java.lang.String, long, boolean);
+    field public static final int REASON_APP_CANCEL = 8; // 0x8
+    field public static final int REASON_APP_CANCEL_ALL = 9; // 0x9
+    field public static final int REASON_DELEGATE_CANCEL = 2; // 0x2
+    field public static final int REASON_DELEGATE_CANCEL_ALL = 3; // 0x3
+    field public static final int REASON_DELEGATE_CLICK = 1; // 0x1
+    field public static final int REASON_DELEGATE_ERROR = 4; // 0x4
+    field public static final int REASON_GROUP_OPTIMIZATION = 13; // 0xd
+    field public static final int REASON_GROUP_SUMMARY_CANCELED = 12; // 0xc
+    field public static final int REASON_LISTENER_CANCEL = 10; // 0xa
+    field public static final int REASON_LISTENER_CANCEL_ALL = 11; // 0xb
+    field public static final int REASON_PACKAGE_BANNED = 7; // 0x7
+    field public static final int REASON_PACKAGE_CHANGED = 5; // 0x5
+    field public static final int REASON_PACKAGE_SUSPENDED = 14; // 0xe
+    field public static final int REASON_PROFILE_TURNED_OFF = 15; // 0xf
+    field public static final int REASON_USER_STOPPED = 6; // 0x6
+    field public static final java.lang.String SERVICE_INTERFACE = "android.service.notification.NotificationRankerService";
+  }
+
+  public class NotificationRankerService.Adjustment {
+    ctor public NotificationRankerService.Adjustment(int, java.lang.CharSequence, android.net.Uri);
+  }
+
   public class StatusBarNotification implements android.os.Parcelable {
     ctor public StatusBarNotification(java.lang.String, java.lang.String, int, java.lang.String, int, int, int, android.app.Notification, android.os.UserHandle, long);
     ctor public StatusBarNotification(android.os.Parcel);
@@ -37442,6 +37634,17 @@
 
 }
 
+package android.service.vr {
+
+  public abstract class VrListenerService extends android.app.Service {
+    ctor public VrListenerService();
+    method public static final boolean isVrModePackageEnabled(android.content.Context, android.content.ComponentName);
+    method public android.os.IBinder onBind(android.content.Intent);
+    field public static final java.lang.String SERVICE_INTERFACE = "android.service.vr.VrListenerService";
+  }
+
+}
+
 package android.service.wallpaper {
 
   public abstract class WallpaperService extends android.app.Service {
@@ -39109,6 +39312,7 @@
     method public void cancelMissedCallsNotification();
     method public deprecated void clearAccounts();
     method public void clearPhoneAccounts();
+    method public android.content.Intent createManageBlockedNumbersIntent();
     method public java.util.List<android.telecom.ParcelableCallAnalytics> dumpAnalytics();
     method public void enablePhoneAccount(android.telecom.PhoneAccountHandle, boolean);
     method public boolean endCall();
@@ -39134,7 +39338,7 @@
     method public boolean isRinging();
     method public boolean isTtySupported();
     method public boolean isVoiceMailNumber(android.telecom.PhoneAccountHandle, java.lang.String);
-    method public void launchManageBlockedNumbersActivity();
+    method public deprecated void launchManageBlockedNumbersActivity();
     method public void placeCall(android.net.Uri, android.os.Bundle);
     method public void registerPhoneAccount(android.telecom.PhoneAccount);
     method public void showInCallScreen(boolean);
@@ -41320,7 +41524,6 @@
     method public boolean hasNext();
     method public java.util.Iterator<java.lang.String> iterator();
     method public java.lang.String next();
-    method public void remove();
     method public void setString(java.lang.String);
   }
 
@@ -42932,6 +43135,7 @@
     method public int describeContents();
     method public static android.util.LocaleList forLanguageTags(java.lang.String);
     method public java.util.Locale get(int);
+    method public static android.util.LocaleList getAdjustedDefault();
     method public static android.util.LocaleList getDefault();
     method public static android.util.LocaleList getEmptyLocaleList();
     method public java.util.Locale getFirstMatch(java.lang.String[]);
@@ -50333,6 +50537,7 @@
     method public void setChar(int, java.lang.String, char);
     method public void setCharSequence(int, java.lang.String, java.lang.CharSequence);
     method public void setChronometer(int, long, java.lang.String, boolean);
+    method public void setChronometerCountsDown(int, boolean);
     method public void setContentDescription(int, java.lang.CharSequence);
     method public void setDisplayedChild(int, int);
     method public void setDouble(int, java.lang.String, double);
@@ -53579,6 +53784,7 @@
     method public static long doubleToRawLongBits(double);
     method public double doubleValue();
     method public float floatValue();
+    method public static int hashCode(double);
     method public int intValue();
     method public static boolean isInfinite(double);
     method public boolean isInfinite();
@@ -53586,11 +53792,15 @@
     method public boolean isNaN();
     method public static double longBitsToDouble(long);
     method public long longValue();
+    method public static double max(double, double);
+    method public static double min(double, double);
     method public static double parseDouble(java.lang.String) throws java.lang.NumberFormatException;
+    method public static double sum(double, double);
     method public static java.lang.String toHexString(double);
     method public static java.lang.String toString(double);
     method public static java.lang.Double valueOf(java.lang.String) throws java.lang.NumberFormatException;
     method public static java.lang.Double valueOf(double);
+    field public static final int BYTES = 8; // 0x8
     field public static final int MAX_EXPONENT = 1023; // 0x3ff
     field public static final double MAX_VALUE = 1.7976931348623157E308;
     field public static final int MIN_EXPONENT = -1022; // 0xfffffc02
@@ -53753,10 +53963,13 @@
     method public static java.lang.Integer getInteger(java.lang.String);
     method public static java.lang.Integer getInteger(java.lang.String, int);
     method public static java.lang.Integer getInteger(java.lang.String, java.lang.Integer);
+    method public static int hashCode(int);
     method public static int highestOneBit(int);
     method public int intValue();
     method public long longValue();
     method public static int lowestOneBit(int);
+    method public static int max(int, int);
+    method public static int min(int, int);
     method public static int numberOfLeadingZeros(int);
     method public static int numberOfTrailingZeros(int);
     method public static int parseInt(java.lang.String, int) throws java.lang.NumberFormatException;
@@ -53766,6 +53979,7 @@
     method public static int rotateLeft(int, int);
     method public static int rotateRight(int, int);
     method public static int signum(int);
+    method public static int sum(int, int);
     method public static java.lang.String toBinaryString(int);
     method public static java.lang.String toHexString(int);
     method public static java.lang.String toOctalString(int);
@@ -53774,6 +53988,7 @@
     method public static java.lang.Integer valueOf(java.lang.String, int) throws java.lang.NumberFormatException;
     method public static java.lang.Integer valueOf(java.lang.String) throws java.lang.NumberFormatException;
     method public static java.lang.Integer valueOf(int);
+    field public static final int BYTES = 4; // 0x4
     field public static final int MAX_VALUE = 2147483647; // 0x7fffffff
     field public static final int MIN_VALUE = -2147483648; // 0x80000000
     field public static final int SIZE = 32; // 0x20
@@ -53793,7 +54008,9 @@
   }
 
   public abstract interface Iterable {
+    method public default void forEach(java.util.function.Consumer<? super T>);
     method public abstract java.util.Iterator<T> iterator();
+    method public default java.util.Spliterator<T> spliterator();
   }
 
   public class LinkageError extends java.lang.Error {
@@ -53814,10 +54031,13 @@
     method public static java.lang.Long getLong(java.lang.String);
     method public static java.lang.Long getLong(java.lang.String, long);
     method public static java.lang.Long getLong(java.lang.String, java.lang.Long);
+    method public static int hashCode(long);
     method public static long highestOneBit(long);
     method public int intValue();
     method public long longValue();
     method public static long lowestOneBit(long);
+    method public static long max(long, long);
+    method public static long min(long, long);
     method public static int numberOfLeadingZeros(long);
     method public static int numberOfTrailingZeros(long);
     method public static long parseLong(java.lang.String, int) throws java.lang.NumberFormatException;
@@ -53827,6 +54047,7 @@
     method public static long rotateLeft(long, int);
     method public static long rotateRight(long, int);
     method public static int signum(long);
+    method public static long sum(long, long);
     method public static java.lang.String toBinaryString(long);
     method public static java.lang.String toHexString(long);
     method public static java.lang.String toOctalString(long);
@@ -57268,6 +57489,7 @@
 
   public abstract class Provider extends java.util.Properties {
     ctor protected Provider(java.lang.String, double, java.lang.String);
+    method public synchronized void forEach(java.util.function.BiConsumer<? super java.lang.Object, ? super java.lang.Object>);
     method public java.lang.String getInfo();
     method public java.lang.String getName();
     method public synchronized java.security.Provider.Service getService(java.lang.String, java.lang.String);
@@ -60209,6 +60431,7 @@
     method public E removeLast();
     method public boolean removeLastOccurrence(java.lang.Object);
     method public int size();
+    method public java.util.Spliterator<E> spliterator();
   }
 
   public class ArrayList extends java.util.AbstractList implements java.lang.Cloneable java.util.List java.util.RandomAccess java.io.Serializable {
@@ -60217,8 +60440,10 @@
     ctor public ArrayList(java.util.Collection<? extends E>);
     method public java.lang.Object clone();
     method public void ensureCapacity(int);
+    method public void forEach(java.util.function.Consumer<? super E>);
     method public E get(int);
     method public int size();
+    method public java.util.Spliterator<E> spliterator();
     method public void trimToSize();
   }
 
@@ -60319,6 +60544,14 @@
     method public static void sort(java.lang.Object[], int, int);
     method public static void sort(T[], java.util.Comparator<? super T>);
     method public static void sort(T[], int, int, java.util.Comparator<? super T>);
+    method public static java.util.Spliterator<T> spliterator(T[]);
+    method public static java.util.Spliterator<T> spliterator(T[], int, int);
+    method public static java.util.Spliterator.OfInt spliterator(int[]);
+    method public static java.util.Spliterator.OfInt spliterator(int[], int, int);
+    method public static java.util.Spliterator.OfLong spliterator(long[]);
+    method public static java.util.Spliterator.OfLong spliterator(long[], int, int);
+    method public static java.util.Spliterator.OfDouble spliterator(double[]);
+    method public static java.util.Spliterator.OfDouble spliterator(double[], int, int);
     method public static java.lang.String toString(long[]);
     method public static java.lang.String toString(int[]);
     method public static java.lang.String toString(short[]);
@@ -60549,7 +60782,23 @@
 
   public abstract interface Comparator {
     method public abstract int compare(T, T);
+    method public static java.util.Comparator<T> comparing(java.util.function.Function<? super T, ? extends U>, java.util.Comparator<? super U>);
+    method public static java.util.Comparator<T> comparing(java.util.function.Function<? super T, ? extends U>);
+    method public static java.util.Comparator<T> comparingDouble(java.util.function.ToDoubleFunction<? super T>);
+    method public static java.util.Comparator<T> comparingInt(java.util.function.ToIntFunction<? super T>);
+    method public static java.util.Comparator<T> comparingLong(java.util.function.ToLongFunction<? super T>);
     method public abstract boolean equals(java.lang.Object);
+    method public static java.util.Comparator<T> naturalOrder();
+    method public static java.util.Comparator<T> nullsFirst(java.util.Comparator<? super T>);
+    method public static java.util.Comparator<T> nullsLast(java.util.Comparator<? super T>);
+    method public static java.util.Comparator<T> reverseOrder();
+    method public default java.util.Comparator<T> reversed();
+    method public default java.util.Comparator<T> thenComparing(java.util.Comparator<? super T>);
+    method public default java.util.Comparator<T> thenComparing(java.util.function.Function<? super T, ? extends U>, java.util.Comparator<? super U>);
+    method public default java.util.Comparator<T> thenComparing(java.util.function.Function<? super T, ? extends U>);
+    method public default java.util.Comparator<T> thenComparingDouble(java.util.function.ToDoubleFunction<? super T>);
+    method public default java.util.Comparator<T> thenComparingInt(java.util.function.ToIntFunction<? super T>);
+    method public default java.util.Comparator<T> thenComparingLong(java.util.function.ToLongFunction<? super T>);
   }
 
   public class ConcurrentModificationException extends java.lang.RuntimeException {
@@ -60646,6 +60895,17 @@
     method public abstract int size();
   }
 
+  public class DoubleSummaryStatistics implements java.util.function.DoubleConsumer {
+    ctor public DoubleSummaryStatistics();
+    method public void accept(double);
+    method public void combine(java.util.DoubleSummaryStatistics);
+    method public final double getAverage();
+    method public final long getCount();
+    method public final double getMax();
+    method public final double getMin();
+    method public final double getSum();
+  }
+
   public class DuplicateFormatFlagsException extends java.util.IllegalFormatException {
     ctor public DuplicateFormatFlagsException(java.lang.String);
     method public java.lang.String getFlags();
@@ -60780,6 +61040,7 @@
     ctor public HashMap(java.util.Map<? extends K, ? extends V>);
     method public java.lang.Object clone();
     method public java.util.Set<java.util.Map.Entry<K, V>> entrySet();
+    method public void forEach(java.util.function.BiConsumer<? super K, ? super V>);
   }
 
   public class HashSet extends java.util.AbstractSet implements java.lang.Cloneable java.io.Serializable java.util.Set {
@@ -60790,6 +61051,7 @@
     method public java.lang.Object clone();
     method public java.util.Iterator<E> iterator();
     method public int size();
+    method public java.util.Spliterator<E> spliterator();
   }
 
   public class Hashtable extends java.util.Dictionary implements java.lang.Cloneable java.util.Map java.io.Serializable {
@@ -60804,6 +61066,7 @@
     method public boolean containsValue(java.lang.Object);
     method public synchronized java.util.Enumeration<V> elements();
     method public java.util.Set<java.util.Map.Entry<K, V>> entrySet();
+    method public synchronized void forEach(java.util.function.BiConsumer<? super K, ? super V>);
     method public synchronized V get(java.lang.Object);
     method public synchronized boolean isEmpty();
     method public java.util.Set<K> keySet();
@@ -60822,6 +61085,7 @@
     ctor public IdentityHashMap(java.util.Map<? extends K, ? extends V>);
     method public java.lang.Object clone();
     method public java.util.Set<java.util.Map.Entry<K, V>> entrySet();
+    method public void forEach(java.util.function.BiConsumer<? super K, ? super V>);
   }
 
   public class IllegalFormatCodePointException extends java.util.IllegalFormatException {
@@ -60865,15 +61129,27 @@
     ctor public InputMismatchException(java.lang.String);
   }
 
+  public class IntSummaryStatistics implements java.util.function.IntConsumer {
+    ctor public IntSummaryStatistics();
+    method public void accept(int);
+    method public void combine(java.util.IntSummaryStatistics);
+    method public final double getAverage();
+    method public final long getCount();
+    method public final int getMax();
+    method public final int getMin();
+    method public final long getSum();
+  }
+
   public class InvalidPropertiesFormatException extends java.io.IOException {
     ctor public InvalidPropertiesFormatException(java.lang.Throwable);
     ctor public InvalidPropertiesFormatException(java.lang.String);
   }
 
   public abstract interface Iterator {
+    method public default void forEachRemaining(java.util.function.Consumer<? super E>);
     method public abstract boolean hasNext();
     method public abstract E next();
-    method public abstract void remove();
+    method public default void remove();
   }
 
   public class LinkedHashMap extends java.util.HashMap implements java.util.Map {
@@ -60920,6 +61196,7 @@
     method public E removeLast();
     method public boolean removeLastOccurrence(java.lang.Object);
     method public int size();
+    method public java.util.Spliterator<E> spliterator();
   }
 
   public abstract interface List implements java.util.Collection {
@@ -61055,12 +61332,25 @@
     enum_constant public static final java.util.Locale.Category FORMAT;
   }
 
+  public class LongSummaryStatistics implements java.util.function.IntConsumer java.util.function.LongConsumer {
+    ctor public LongSummaryStatistics();
+    method public void accept(int);
+    method public void accept(long);
+    method public void combine(java.util.LongSummaryStatistics);
+    method public final double getAverage();
+    method public final long getCount();
+    method public final long getMax();
+    method public final long getMin();
+    method public final long getSum();
+  }
+
   public abstract interface Map {
     method public abstract void clear();
     method public abstract boolean containsKey(java.lang.Object);
     method public abstract boolean containsValue(java.lang.Object);
     method public abstract java.util.Set<java.util.Map.Entry<K, V>> entrySet();
     method public abstract boolean equals(java.lang.Object);
+    method public default void forEach(java.util.function.BiConsumer<? super K, ? super V>);
     method public abstract V get(java.lang.Object);
     method public abstract int hashCode();
     method public abstract boolean isEmpty();
@@ -61073,6 +61363,8 @@
   }
 
   public static abstract interface Map.Entry {
+    method public static java.util.Comparator<java.util.Map.Entry<K, V>> comparingByKey();
+    method public static java.util.Comparator<java.util.Map.Entry<K, V>> comparingByKey(java.util.Comparator<? super K>);
     method public abstract boolean equals(java.lang.Object);
     method public abstract K getKey();
     method public abstract V getValue();
@@ -61175,9 +61467,83 @@
     method public abstract void update(java.util.Observable, java.lang.Object);
   }
 
+  public final class Optional {
+    method public static java.util.Optional<T> empty();
+    method public java.util.Optional<T> filter(java.util.function.Predicate<? super T>);
+    method public java.util.Optional<U> flatMap(java.util.function.Function<? super T, java.util.Optional<U>>);
+    method public T get();
+    method public void ifPresent(java.util.function.Consumer<? super T>);
+    method public boolean isPresent();
+    method public java.util.Optional<U> map(java.util.function.Function<? super T, ? extends U>);
+    method public static java.util.Optional<T> of(T);
+    method public static java.util.Optional<T> ofNullable(T);
+    method public T orElse(T);
+    method public T orElseGet(java.util.function.Supplier<? extends T>);
+    method public T orElseThrow(java.util.function.Supplier<? extends X>) throws java.lang.Throwable;
+  }
+
+  public final class OptionalDouble {
+    method public static java.util.OptionalDouble empty();
+    method public double getAsDouble();
+    method public void ifPresent(java.util.function.DoubleConsumer);
+    method public boolean isPresent();
+    method public static java.util.OptionalDouble of(double);
+    method public double orElse(double);
+    method public double orElseGet(java.util.function.DoubleSupplier);
+    method public double orElseThrow(java.util.function.Supplier<X>) throws java.lang.Throwable;
+  }
+
+  public final class OptionalInt {
+    method public static java.util.OptionalInt empty();
+    method public int getAsInt();
+    method public void ifPresent(java.util.function.IntConsumer);
+    method public boolean isPresent();
+    method public static java.util.OptionalInt of(int);
+    method public int orElse(int);
+    method public int orElseGet(java.util.function.IntSupplier);
+    method public int orElseThrow(java.util.function.Supplier<X>) throws java.lang.Throwable;
+  }
+
+  public final class OptionalLong {
+    method public static java.util.OptionalLong empty();
+    method public long getAsLong();
+    method public void ifPresent(java.util.function.LongConsumer);
+    method public boolean isPresent();
+    method public static java.util.OptionalLong of(long);
+    method public long orElse(long);
+    method public long orElseGet(java.util.function.LongSupplier);
+    method public long orElseThrow(java.util.function.Supplier<X>) throws java.lang.Throwable;
+  }
+
+  public abstract interface PrimitiveIterator implements java.util.Iterator {
+    method public abstract void forEachRemaining(T_CONS);
+  }
+
+  public static abstract interface PrimitiveIterator.OfDouble implements java.util.PrimitiveIterator {
+    method public default void forEachRemaining(java.util.function.DoubleConsumer);
+    method public default void forEachRemaining(java.util.function.Consumer<? super java.lang.Double>);
+    method public default java.lang.Double next();
+    method public abstract double nextDouble();
+  }
+
+  public static abstract interface PrimitiveIterator.OfInt implements java.util.PrimitiveIterator {
+    method public default void forEachRemaining(java.util.function.IntConsumer);
+    method public default void forEachRemaining(java.util.function.Consumer<? super java.lang.Integer>);
+    method public default java.lang.Integer next();
+    method public abstract int nextInt();
+  }
+
+  public static abstract interface PrimitiveIterator.OfLong implements java.util.PrimitiveIterator {
+    method public default void forEachRemaining(java.util.function.LongConsumer);
+    method public default void forEachRemaining(java.util.function.Consumer<? super java.lang.Long>);
+    method public default java.lang.Long next();
+    method public abstract long nextLong();
+  }
+
   public class PriorityQueue extends java.util.AbstractQueue implements java.io.Serializable {
     ctor public PriorityQueue();
     ctor public PriorityQueue(int);
+    ctor public PriorityQueue(java.util.Comparator<? super E>);
     ctor public PriorityQueue(int, java.util.Comparator<? super E>);
     ctor public PriorityQueue(java.util.Collection<? extends E>);
     ctor public PriorityQueue(java.util.PriorityQueue<? extends E>);
@@ -61188,6 +61554,7 @@
     method public E peek();
     method public E poll();
     method public int size();
+    method public final java.util.Spliterator<E> spliterator();
   }
 
   public class Properties extends java.util.Hashtable {
@@ -61346,7 +61713,6 @@
     method public short nextShort();
     method public short nextShort(int);
     method public int radix();
-    method public void remove();
     method public java.util.Scanner reset();
     method public java.util.Scanner skip(java.util.regex.Pattern);
     method public java.util.Scanner skip(java.lang.String);
@@ -61431,6 +61797,111 @@
     method public abstract java.util.SortedSet<E> tailSet(E);
   }
 
+  public abstract interface Spliterator {
+    method public abstract int characteristics();
+    method public abstract long estimateSize();
+    method public default void forEachRemaining(java.util.function.Consumer<? super T>);
+    method public default java.util.Comparator<? super T> getComparator();
+    method public default long getExactSizeIfKnown();
+    method public default boolean hasCharacteristics(int);
+    method public abstract boolean tryAdvance(java.util.function.Consumer<? super T>);
+    method public abstract java.util.Spliterator<T> trySplit();
+    field public static final int CONCURRENT = 4096; // 0x1000
+    field public static final int DISTINCT = 1; // 0x1
+    field public static final int IMMUTABLE = 1024; // 0x400
+    field public static final int NONNULL = 256; // 0x100
+    field public static final int ORDERED = 16; // 0x10
+    field public static final int SIZED = 64; // 0x40
+    field public static final int SORTED = 4; // 0x4
+    field public static final int SUBSIZED = 16384; // 0x4000
+  }
+
+  public static abstract interface Spliterator.OfDouble implements java.util.Spliterator.OfPrimitive {
+    method public default void forEachRemaining(java.util.function.DoubleConsumer);
+    method public default void forEachRemaining(java.util.function.Consumer<? super java.lang.Double>);
+    method public abstract boolean tryAdvance(java.util.function.DoubleConsumer);
+    method public default boolean tryAdvance(java.util.function.Consumer<? super java.lang.Double>);
+    method public abstract java.util.Spliterator.OfDouble trySplit();
+  }
+
+  public static abstract interface Spliterator.OfInt implements java.util.Spliterator.OfPrimitive {
+    method public default void forEachRemaining(java.util.function.IntConsumer);
+    method public default void forEachRemaining(java.util.function.Consumer<? super java.lang.Integer>);
+    method public abstract boolean tryAdvance(java.util.function.IntConsumer);
+    method public default boolean tryAdvance(java.util.function.Consumer<? super java.lang.Integer>);
+    method public abstract java.util.Spliterator.OfInt trySplit();
+  }
+
+  public static abstract interface Spliterator.OfLong implements java.util.Spliterator.OfPrimitive {
+    method public default void forEachRemaining(java.util.function.LongConsumer);
+    method public default void forEachRemaining(java.util.function.Consumer<? super java.lang.Long>);
+    method public abstract boolean tryAdvance(java.util.function.LongConsumer);
+    method public default boolean tryAdvance(java.util.function.Consumer<? super java.lang.Long>);
+    method public abstract java.util.Spliterator.OfLong trySplit();
+  }
+
+  public static abstract interface Spliterator.OfPrimitive implements java.util.Spliterator {
+    method public default void forEachRemaining(T_CONS);
+    method public abstract boolean tryAdvance(T_CONS);
+    method public abstract T_SPLITR trySplit();
+  }
+
+  public final class Spliterators {
+    method public static java.util.Spliterator.OfDouble emptyDoubleSpliterator();
+    method public static java.util.Spliterator.OfInt emptyIntSpliterator();
+    method public static java.util.Spliterator.OfLong emptyLongSpliterator();
+    method public static java.util.Spliterator<T> emptySpliterator();
+    method public static java.util.Iterator<T> iterator(java.util.Spliterator<? extends T>);
+    method public static java.util.PrimitiveIterator.OfInt iterator(java.util.Spliterator.OfInt);
+    method public static java.util.PrimitiveIterator.OfLong iterator(java.util.Spliterator.OfLong);
+    method public static java.util.PrimitiveIterator.OfDouble iterator(java.util.Spliterator.OfDouble);
+    method public static java.util.Spliterator<T> spliterator(java.lang.Object[], int);
+    method public static java.util.Spliterator<T> spliterator(java.lang.Object[], int, int, int);
+    method public static java.util.Spliterator.OfInt spliterator(int[], int);
+    method public static java.util.Spliterator.OfInt spliterator(int[], int, int, int);
+    method public static java.util.Spliterator.OfLong spliterator(long[], int);
+    method public static java.util.Spliterator.OfLong spliterator(long[], int, int, int);
+    method public static java.util.Spliterator.OfDouble spliterator(double[], int);
+    method public static java.util.Spliterator.OfDouble spliterator(double[], int, int, int);
+    method public static java.util.Spliterator<T> spliterator(java.util.Collection<? extends T>, int);
+    method public static java.util.Spliterator<T> spliterator(java.util.Iterator<? extends T>, long, int);
+    method public static java.util.Spliterator.OfInt spliterator(java.util.PrimitiveIterator.OfInt, long, int);
+    method public static java.util.Spliterator.OfLong spliterator(java.util.PrimitiveIterator.OfLong, long, int);
+    method public static java.util.Spliterator.OfDouble spliterator(java.util.PrimitiveIterator.OfDouble, long, int);
+    method public static java.util.Spliterator<T> spliteratorUnknownSize(java.util.Iterator<? extends T>, int);
+    method public static java.util.Spliterator.OfInt spliteratorUnknownSize(java.util.PrimitiveIterator.OfInt, int);
+    method public static java.util.Spliterator.OfLong spliteratorUnknownSize(java.util.PrimitiveIterator.OfLong, int);
+    method public static java.util.Spliterator.OfDouble spliteratorUnknownSize(java.util.PrimitiveIterator.OfDouble, int);
+  }
+
+  public static abstract class Spliterators.AbstractDoubleSpliterator implements java.util.Spliterator.OfDouble {
+    ctor protected Spliterators.AbstractDoubleSpliterator(long, int);
+    method public int characteristics();
+    method public long estimateSize();
+    method public java.util.Spliterator.OfDouble trySplit();
+  }
+
+  public static abstract class Spliterators.AbstractIntSpliterator implements java.util.Spliterator.OfInt {
+    ctor protected Spliterators.AbstractIntSpliterator(long, int);
+    method public int characteristics();
+    method public long estimateSize();
+    method public java.util.Spliterator.OfInt trySplit();
+  }
+
+  public static abstract class Spliterators.AbstractLongSpliterator implements java.util.Spliterator.OfLong {
+    ctor protected Spliterators.AbstractLongSpliterator(long, int);
+    method public int characteristics();
+    method public long estimateSize();
+    method public java.util.Spliterator.OfLong trySplit();
+  }
+
+  public static abstract class Spliterators.AbstractSpliterator implements java.util.Spliterator {
+    ctor protected Spliterators.AbstractSpliterator(long, int);
+    method public int characteristics();
+    method public long estimateSize();
+    method public java.util.Spliterator<T> trySplit();
+  }
+
   public class Stack extends java.util.Vector {
     ctor public Stack();
     method public boolean empty();
@@ -61440,6 +61911,15 @@
     method public synchronized int search(java.lang.Object);
   }
 
+  public final class StringJoiner {
+    ctor public StringJoiner(java.lang.CharSequence);
+    ctor public StringJoiner(java.lang.CharSequence, java.lang.CharSequence, java.lang.CharSequence);
+    method public java.util.StringJoiner add(java.lang.CharSequence);
+    method public int length();
+    method public java.util.StringJoiner merge(java.util.StringJoiner);
+    method public java.util.StringJoiner setEmptyValue(java.lang.CharSequence);
+  }
+
   public class StringTokenizer implements java.util.Enumeration {
     ctor public StringTokenizer(java.lang.String, java.lang.String, boolean);
     ctor public StringTokenizer(java.lang.String, java.lang.String);
@@ -61522,6 +62002,7 @@
     method public K firstKey();
     method public java.util.Map.Entry<K, V> floorEntry(K);
     method public K floorKey(K);
+    method public void forEach(java.util.function.BiConsumer<? super K, ? super V>);
     method public java.util.NavigableMap<K, V> headMap(K, boolean);
     method public java.util.SortedMap<K, V> headMap(K);
     method public java.util.Map.Entry<K, V> higherEntry(K);
@@ -61560,6 +62041,7 @@
     method public E pollFirst();
     method public E pollLast();
     method public int size();
+    method public java.util.Spliterator<E> spliterator();
     method public java.util.NavigableSet<E> subSet(E, boolean, E, boolean);
     method public java.util.SortedSet<E> subSet(E, E);
     method public java.util.NavigableSet<E> tailSet(E, boolean);
@@ -61604,6 +62086,7 @@
     method public java.util.Enumeration<E> elements();
     method public synchronized void ensureCapacity(int);
     method public synchronized E firstElement();
+    method public synchronized void forEach(java.util.function.Consumer<? super E>);
     method public synchronized E get(int);
     method public synchronized int indexOf(java.lang.Object, int);
     method public synchronized void insertElementAt(E, int);
@@ -61615,6 +62098,7 @@
     method public synchronized void setElementAt(E, int);
     method public synchronized void setSize(int);
     method public synchronized int size();
+    method public java.util.Spliterator<E> spliterator();
     method public synchronized void trimToSize();
     field protected int capacityIncrement;
     field protected int elementCount;
@@ -61627,6 +62111,7 @@
     ctor public WeakHashMap();
     ctor public WeakHashMap(java.util.Map<? extends K, ? extends V>);
     method public java.util.Set<java.util.Map.Entry<K, V>> entrySet();
+    method public void forEach(java.util.function.BiConsumer<? super K, ? super V>);
   }
 
 }
diff --git a/api/system-removed.txt b/api/system-removed.txt
index 7347aa3..79f7297 100644
--- a/api/system-removed.txt
+++ b/api/system-removed.txt
@@ -35,12 +35,20 @@
 
 package android.media {
 
-  public class AudioFormat implements android.os.Parcelable {
+  public final class AudioFormat implements android.os.Parcelable {
     ctor public AudioFormat();
   }
 
 }
 
+package android.media.tv {
+
+  public class TvView extends android.view.ViewGroup {
+    method public void requestUnblockContent(android.media.tv.TvContentRating);
+  }
+
+}
+
 package android.net {
 
   public class SSLCertificateSocketFactory extends javax.net.ssl.SSLSocketFactory {
diff --git a/api/test-current.txt b/api/test-current.txt
index 0b7914b..a7b434c 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -38,6 +38,7 @@
     field public static final java.lang.String BIND_TV_INPUT = "android.permission.BIND_TV_INPUT";
     field public static final java.lang.String BIND_VOICE_INTERACTION = "android.permission.BIND_VOICE_INTERACTION";
     field public static final java.lang.String BIND_VPN_SERVICE = "android.permission.BIND_VPN_SERVICE";
+    field public static final java.lang.String BIND_VR_LISTENER_SERVICE = "android.permission.BIND_VR_LISTENER_SERVICE";
     field public static final java.lang.String BIND_WALLPAPER = "android.permission.BIND_WALLPAPER";
     field public static final java.lang.String BLUETOOTH = "android.permission.BLUETOOTH";
     field public static final java.lang.String BLUETOOTH_ADMIN = "android.permission.BLUETOOTH_ADMIN";
@@ -101,7 +102,6 @@
     field public static final java.lang.String READ_SYNC_SETTINGS = "android.permission.READ_SYNC_SETTINGS";
     field public static final java.lang.String READ_SYNC_STATS = "android.permission.READ_SYNC_STATS";
     field public static final java.lang.String READ_VOICEMAIL = "com.android.voicemail.permission.READ_VOICEMAIL";
-    field public static final java.lang.String READ_WRITE_CONTACT_METADATA = "android.permission.READ_WRITE_CONTACT_METADATA";
     field public static final java.lang.String REBOOT = "android.permission.REBOOT";
     field public static final java.lang.String RECEIVE_BOOT_COMPLETED = "android.permission.RECEIVE_BOOT_COMPLETED";
     field public static final java.lang.String RECEIVE_EMERGENCY_BROADCAST = "android.permission.RECEIVE_EMERGENCY_BROADCAST";
@@ -115,6 +115,7 @@
     field public static final deprecated java.lang.String RESTART_PACKAGES = "android.permission.RESTART_PACKAGES";
     field public static final java.lang.String SEND_RESPOND_VIA_MESSAGE = "android.permission.SEND_RESPOND_VIA_MESSAGE";
     field public static final java.lang.String SEND_SMS = "android.permission.SEND_SMS";
+    field public static final java.lang.String SEND_SMS_NO_CONFIRMATION = "android.permission.SEND_SMS_NO_CONFIRMATION";
     field public static final java.lang.String SET_ALARM = "com.android.alarm.permission.SET_ALARM";
     field public static final java.lang.String SET_ALWAYS_FINISH = "android.permission.SET_ALWAYS_FINISH";
     field public static final java.lang.String SET_ANIMATION_SCALE = "android.permission.SET_ANIMATION_SCALE";
@@ -878,6 +879,7 @@
     field public static final int nextFocusLeft = 16842977; // 0x10100e1
     field public static final int nextFocusRight = 16842978; // 0x10100e2
     field public static final int nextFocusUp = 16842979; // 0x10100e3
+    field public static final int nfcAntennaPositionDrawable = 16844063; // 0x101051f
     field public static final int noHistory = 16843309; // 0x101022d
     field public static final int normalScreens = 16843397; // 0x1010285
     field public static final int notificationTimeout = 16843651; // 0x1010383
@@ -2669,6 +2671,8 @@
     field public static final int GLOBAL_ACTION_TOGGLE_SPLIT_SCREEN = 7; // 0x7
     field public static final java.lang.String SERVICE_INTERFACE = "android.accessibilityservice.AccessibilityService";
     field public static final java.lang.String SERVICE_META_DATA = "android.accessibilityservice";
+    field public static final int SHOW_MODE_AUTO = 0; // 0x0
+    field public static final int SHOW_MODE_HIDDEN = 1; // 0x1
   }
 
   public static abstract class AccessibilityService.GestureResultCallback {
@@ -3603,7 +3607,7 @@
     method public deprecated void setTitleColor(int);
     method public void setVisible(boolean);
     method public final void setVolumeControlStream(int);
-    method public void setVrMode(boolean);
+    method public void setVrModeEnabled(boolean, android.content.ComponentName) throws android.content.pm.PackageManager.NameNotFoundException;
     method public boolean shouldShowRequestPermissionRationale(java.lang.String);
     method public boolean shouldUpRecreateTask(android.content.Intent);
     method public boolean showAssist(android.os.Bundle);
@@ -4127,13 +4131,12 @@
     field public java.lang.String serviceDetails;
   }
 
-  public class AutomaticZenRule implements android.os.Parcelable {
+  public final class AutomaticZenRule implements android.os.Parcelable {
     ctor public AutomaticZenRule(java.lang.String, android.content.ComponentName, android.net.Uri, int, boolean);
     ctor public AutomaticZenRule(android.os.Parcel);
     method public int describeContents();
     method public android.net.Uri getConditionId();
     method public long getCreationTime();
-    method public java.lang.String getId();
     method public int getInterruptionFilter();
     method public java.lang.String getName();
     method public android.content.ComponentName getOwner();
@@ -4908,6 +4911,7 @@
     field public static final int DEFAULT_VIBRATE = 2; // 0x2
     field public static final java.lang.String EXTRA_BACKGROUND_IMAGE_URI = "android.backgroundImageUri";
     field public static final java.lang.String EXTRA_BIG_TEXT = "android.bigText";
+    field public static final java.lang.String EXTRA_CHRONOMETER_COUNTS_DOWN = "android.chronometerCountsDown";
     field public static final java.lang.String EXTRA_COMPACT_ACTIONS = "android.compactActions";
     field public static final java.lang.String EXTRA_INFO_TEXT = "android.infoText";
     field public static final java.lang.String EXTRA_LARGE_ICON = "android.largeIcon";
@@ -5049,16 +5053,17 @@
     method public android.app.Notification.Builder addExtras(android.os.Bundle);
     method public android.app.Notification.Builder addPerson(java.lang.String);
     method public android.app.Notification build();
+    method public android.widget.RemoteViews createBigContentView();
+    method public android.widget.RemoteViews createContentView();
+    method public android.widget.RemoteViews createHeadsUpContentView();
     method public android.app.Notification.Builder extend(android.app.Notification.Extender);
     method public android.os.Bundle getExtras();
     method public deprecated android.app.Notification getNotification();
-    method public android.widget.RemoteViews makeBigContentView();
-    method public android.widget.RemoteViews makeContentView();
-    method public android.widget.RemoteViews makeHeadsUpContentView();
     method public static android.app.Notification.Builder recoverBuilder(android.content.Context, android.app.Notification);
     method public android.app.Notification.Builder setActions(android.app.Notification.Action...);
     method public android.app.Notification.Builder setAutoCancel(boolean);
     method public android.app.Notification.Builder setCategory(java.lang.String);
+    method public android.app.Notification.Builder setChronometerCountsDown(boolean);
     method public android.app.Notification.Builder setColor(int);
     method public deprecated android.app.Notification.Builder setContent(android.widget.RemoteViews);
     method public android.app.Notification.Builder setContentInfo(java.lang.CharSequence);
@@ -5227,14 +5232,14 @@
   }
 
   public class NotificationManager {
-    method public android.app.AutomaticZenRule addAutomaticZenRule(android.app.AutomaticZenRule);
+    method public java.lang.String addAutomaticZenRule(android.app.AutomaticZenRule);
     method public boolean areNotificationsEnabled();
     method public void cancel(int);
     method public void cancel(java.lang.String, int);
     method public void cancelAll();
     method public android.service.notification.StatusBarNotification[] getActiveNotifications();
     method public android.app.AutomaticZenRule getAutomaticZenRule(java.lang.String);
-    method public java.util.List<android.app.AutomaticZenRule> getAutomaticZenRules();
+    method public java.util.Map<java.lang.String, android.app.AutomaticZenRule> getAutomaticZenRules();
     method public final int getCurrentInterruptionFilter();
     method public int getImportance();
     method public android.app.NotificationManager.Policy getNotificationPolicy();
@@ -5244,7 +5249,7 @@
     method public boolean removeAutomaticZenRule(java.lang.String);
     method public final void setInterruptionFilter(int);
     method public void setNotificationPolicy(android.app.NotificationManager.Policy);
-    method public boolean updateAutomaticZenRule(android.app.AutomaticZenRule);
+    method public boolean updateAutomaticZenRule(java.lang.String, android.app.AutomaticZenRule);
     field public static final java.lang.String ACTION_INTERRUPTION_FILTER_CHANGED = "android.app.action.INTERRUPTION_FILTER_CHANGED";
     field public static final java.lang.String ACTION_NOTIFICATION_POLICY_ACCESS_GRANTED_CHANGED = "android.app.action.NOTIFICATION_POLICY_ACCESS_GRANTED_CHANGED";
     field public static final java.lang.String ACTION_NOTIFICATION_POLICY_CHANGED = "android.app.action.NOTIFICATION_POLICY_CHANGED";
@@ -5256,7 +5261,7 @@
   }
 
   public static class NotificationManager.Policy implements android.os.Parcelable {
-    ctor public deprecated NotificationManager.Policy(int, int, int);
+    ctor public NotificationManager.Policy(int, int, int);
     ctor public NotificationManager.Policy(int, int, int, int);
     method public int describeContents();
     method public static java.lang.String priorityCategoriesToString(int);
@@ -5713,6 +5718,7 @@
 
   public class WallpaperManager {
     method public void clear() throws java.io.IOException;
+    method public void clear(int) throws java.io.IOException;
     method public void clearWallpaperOffsets(android.os.IBinder);
     method public void forgetLoadedWallpaper();
     method public android.graphics.drawable.Drawable getBuiltInDrawable();
@@ -5884,7 +5890,7 @@
     method public android.app.admin.SystemUpdatePolicy getSystemUpdatePolicy();
     method public java.util.List<android.os.PersistableBundle> getTrustAgentConfiguration(android.content.ComponentName, android.content.ComponentName);
     method public android.os.Bundle getUserRestrictions(android.content.ComponentName);
-    method public java.lang.String getWifiMacAddress();
+    method public java.lang.String getWifiMacAddress(android.content.ComponentName);
     method public boolean hasCaCertInstalled(android.content.ComponentName, byte[]);
     method public boolean hasGrantedPolicy(android.content.ComponentName, int);
     method public boolean installCaCert(android.content.ComponentName, byte[]);
@@ -6592,7 +6598,7 @@
     field public static final int TAG_SYNC_SEND_FILE = 210004; // 0x33454
   }
 
-  public static class SecurityLog.SecurityEvent implements android.os.Parcelable {
+  public static final class SecurityLog.SecurityEvent implements android.os.Parcelable {
     method public int describeContents();
     method public java.lang.Object getData();
     method public int getTag();
@@ -7336,15 +7342,6 @@
     field public static final int TYPE_SCO = 2; // 0x2
   }
 
-  public class OobData implements android.os.Parcelable {
-    ctor public OobData();
-    method public int describeContents();
-    method public byte[] getSecurityManagerTk();
-    method public void setSecurityManagerTk(byte[]);
-    method public void writeToParcel(android.os.Parcel, int);
-    field public static final android.os.Parcelable.Creator<android.bluetooth.OobData> CREATOR;
-  }
-
 }
 
 package android.bluetooth.le {
@@ -8150,7 +8147,9 @@
     field public static final java.lang.String RESTRICTIONS_SERVICE = "restrictions";
     field public static final java.lang.String SEARCH_SERVICE = "search";
     field public static final java.lang.String SENSOR_SERVICE = "sensor";
+    field public static final java.lang.String SHORTCUT_SERVICE = "shortcut";
     field public static final java.lang.String STORAGE_SERVICE = "storage";
+    field public static final java.lang.String SYSTEM_HEALTH_SERVICE = "systemhealth";
     field public static final java.lang.String TELECOM_SERVICE = "telecom";
     field public static final java.lang.String TELEPHONY_SERVICE = "phone";
     field public static final java.lang.String TELEPHONY_SUBSCRIPTION_SERVICE = "telephony_subscription_service";
@@ -9337,6 +9336,7 @@
     field public int flags;
     field public int largestWidthLimitDp;
     field public java.lang.String manageSpaceActivityName;
+    field public java.lang.String minSdkVersion;
     field public java.lang.String nativeLibraryDir;
     field public java.lang.String permission;
     field public java.lang.String processName;
@@ -9458,13 +9458,19 @@
   public class LauncherApps {
     method public java.util.List<android.content.pm.LauncherActivityInfo> getActivityList(java.lang.String, android.os.UserHandle);
     method public android.content.pm.ApplicationInfo getApplicationInfo(java.lang.String, int, android.os.UserHandle);
+    method public android.os.ParcelFileDescriptor getShortcutIconFd(android.content.pm.ShortcutInfo, android.os.UserHandle);
+    method public int getShortcutIconResId(android.content.pm.ShortcutInfo, android.os.UserHandle);
+    method public java.util.List<android.content.pm.ShortcutInfo> getShortcutInfo(java.lang.String, java.util.List<java.lang.String>, android.os.UserHandle);
+    method public java.util.List<android.content.pm.ShortcutInfo> getShortcuts(android.content.pm.LauncherApps.ShortcutQuery, android.os.UserHandle);
     method public boolean isActivityEnabled(android.content.ComponentName, android.os.UserHandle);
     method public boolean isPackageEnabled(java.lang.String, android.os.UserHandle);
+    method public void pinShortcuts(java.lang.String, java.util.List<java.lang.String>, android.os.UserHandle);
     method public void registerCallback(android.content.pm.LauncherApps.Callback);
     method public void registerCallback(android.content.pm.LauncherApps.Callback, android.os.Handler);
     method public android.content.pm.LauncherActivityInfo resolveActivity(android.content.Intent, android.os.UserHandle);
     method public void startAppDetailsActivity(android.content.ComponentName, android.os.UserHandle, android.graphics.Rect, android.os.Bundle);
     method public void startMainActivity(android.content.ComponentName, android.os.UserHandle, android.graphics.Rect, android.os.Bundle);
+    method public boolean startShortcut(java.lang.String, java.lang.String, android.graphics.Rect, android.os.Bundle, android.os.UserHandle);
     method public void unregisterCallback(android.content.pm.LauncherApps.Callback);
   }
 
@@ -9477,6 +9483,18 @@
     method public void onPackagesSuspended(java.lang.String[], android.os.UserHandle);
     method public abstract void onPackagesUnavailable(java.lang.String[], android.os.UserHandle, boolean);
     method public void onPackagesUnsuspended(java.lang.String[], android.os.UserHandle);
+    method public void onShortcutsChanged(java.lang.String, java.util.List<android.content.pm.ShortcutInfo>, android.os.UserHandle);
+  }
+
+  public static class LauncherApps.ShortcutQuery {
+    ctor public LauncherApps.ShortcutQuery();
+    method public void setActivity(android.content.ComponentName);
+    method public void setChangedSince(long);
+    method public void setPackage(java.lang.String);
+    method public void setQueryFlags(int);
+    field public static final int FLAG_GET_DYNAMIC = 1; // 0x1
+    field public static final int FLAG_GET_KEY_FIELDS_ONLY = 4; // 0x4
+    field public static final int FLAG_GET_PINNED = 2; // 0x2
   }
 
   public class PackageInfo implements android.os.Parcelable {
@@ -9554,6 +9572,7 @@
     method public java.lang.String[] getNames() throws java.io.IOException;
     method public java.io.InputStream openRead(java.lang.String) throws java.io.IOException;
     method public java.io.OutputStream openWrite(java.lang.String, long, long) throws java.io.IOException;
+    method public void removeSplit(java.lang.String) throws java.io.IOException;
     method public void setStagingProgress(float);
   }
 
@@ -9977,6 +9996,59 @@
     field public java.lang.String permission;
   }
 
+  public class ShortcutInfo implements android.os.Parcelable {
+    method public int describeContents();
+    method public android.content.ComponentName getActivityComponent();
+    method public android.os.PersistableBundle getExtras();
+    method public java.lang.String getId();
+    method public android.content.Intent getIntent();
+    method public long getLastChangedTimestamp();
+    method public java.lang.String getPackageName();
+    method public java.lang.String getTitle();
+    method public int getWeight();
+    method public boolean hasIconFile();
+    method public boolean hasIconResource();
+    method public boolean hasKeyFieldsOnly();
+    method public boolean isDynamic();
+    method public boolean isPinned();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final int CLONE_REMOVE_FOR_CREATOR = 1; // 0x1
+    field public static final int CLONE_REMOVE_FOR_LAUNCHER = 3; // 0x3
+    field public static final int CLONE_REMOVE_NON_KEY_INFO = 4; // 0x4
+    field public static final android.os.Parcelable.Creator<android.content.pm.ShortcutInfo> CREATOR;
+    field public static final int FLAG_DYNAMIC = 1; // 0x1
+    field public static final int FLAG_HAS_ICON_FILE = 8; // 0x8
+    field public static final int FLAG_HAS_ICON_RES = 4; // 0x4
+    field public static final int FLAG_KEY_FIELDS_ONLY = 16; // 0x10
+    field public static final int FLAG_PINNED = 2; // 0x2
+  }
+
+  public static class ShortcutInfo.Builder {
+    ctor public ShortcutInfo.Builder(android.content.Context);
+    method public android.content.pm.ShortcutInfo build();
+    method public android.content.pm.ShortcutInfo.Builder setActivityComponent(android.content.ComponentName);
+    method public android.content.pm.ShortcutInfo.Builder setExtras(android.os.PersistableBundle);
+    method public android.content.pm.ShortcutInfo.Builder setIcon(android.graphics.drawable.Icon);
+    method public android.content.pm.ShortcutInfo.Builder setId(java.lang.String);
+    method public android.content.pm.ShortcutInfo.Builder setIntent(android.content.Intent);
+    method public android.content.pm.ShortcutInfo.Builder setTitle(java.lang.String);
+    method public android.content.pm.ShortcutInfo.Builder setWeight(int);
+  }
+
+  public class ShortcutManager {
+    method public boolean addDynamicShortcut(android.content.pm.ShortcutInfo);
+    method public void deleteAllDynamicShortcuts();
+    method public void deleteDynamicShortcut(java.lang.String);
+    method public java.util.List<android.content.pm.ShortcutInfo> getDynamicShortcuts();
+    method public int getIconMaxDimensions();
+    method public int getMaxDynamicShortcutCount();
+    method public java.util.List<android.content.pm.ShortcutInfo> getPinnedShortcuts();
+    method public long getRateLimitResetTime();
+    method public int getRemainingCallCount();
+    method public boolean setDynamicShortcuts(java.util.List<android.content.pm.ShortcutInfo>);
+    method public boolean updateShortcuts(java.util.List<android.content.pm.ShortcutInfo>);
+  }
+
   public class Signature implements android.os.Parcelable {
     ctor public Signature(byte[]);
     ctor public Signature(java.lang.String);
@@ -10482,7 +10554,6 @@
     method public boolean hasNext();
     method public java.util.Iterator<android.database.CursorJoiner.Result> iterator();
     method public android.database.CursorJoiner.Result next();
-    method public void remove();
   }
 
   public static final class CursorJoiner.Result extends java.lang.Enum {
@@ -12853,7 +12924,8 @@
     method public int getGradientType();
     method public int getOpacity();
     method public android.graphics.drawable.GradientDrawable.Orientation getOrientation();
-    method public boolean isUseLevel();
+    method public int getShape();
+    method public boolean getUseLevel();
     method public void setAlpha(int);
     method public void setColor(int);
     method public void setColor(android.content.res.ColorStateList);
@@ -13715,6 +13787,7 @@
 
   public static abstract class CameraCaptureSession.CaptureCallback {
     ctor public CameraCaptureSession.CaptureCallback();
+    method public void onCaptureBufferLost(android.hardware.camera2.CameraCaptureSession, android.hardware.camera2.CaptureRequest, android.view.Surface, long);
     method public void onCaptureCompleted(android.hardware.camera2.CameraCaptureSession, android.hardware.camera2.CaptureRequest, android.hardware.camera2.TotalCaptureResult);
     method public void onCaptureFailed(android.hardware.camera2.CameraCaptureSession, android.hardware.camera2.CaptureRequest, android.hardware.camera2.CaptureFailure);
     method public void onCaptureProgressed(android.hardware.camera2.CameraCaptureSession, android.hardware.camera2.CaptureRequest, android.hardware.camera2.CaptureResult);
@@ -19171,169 +19244,114 @@
   }
 
   public final class GnssClock implements android.os.Parcelable {
+    ctor public GnssClock();
     method public int describeContents();
-    method public double getBiasInNs();
-    method public double getBiasUncertaintyInNs();
-    method public double getDriftInNsPerSec();
-    method public double getDriftUncertaintyInNsPerSec();
-    method public long getFullBiasInNs();
+    method public double getBiasNanos();
+    method public double getBiasUncertaintyNanos();
+    method public double getDriftNanosPerSecond();
+    method public double getDriftUncertaintyNanosPerSecond();
+    method public long getFullBiasNanos();
     method public int getHardwareClockDiscontinuityCount();
-    method public short getLeapSecond();
-    method public long getTimeInNs();
-    method public double getTimeUncertaintyInNs();
-    method public boolean hasBiasInNs();
-    method public boolean hasBiasUncertaintyInNs();
-    method public boolean hasDriftInNsPerSec();
-    method public boolean hasDriftUncertaintyInNsPerSec();
-    method public boolean hasFullBiasInNs();
+    method public int getLeapSecond();
+    method public long getTimeNanos();
+    method public double getTimeUncertaintyNanos();
+    method public boolean hasBiasNanos();
+    method public boolean hasBiasUncertaintyNanos();
+    method public boolean hasDriftNanosPerSecond();
+    method public boolean hasDriftUncertaintyNanosPerSecond();
+    method public boolean hasFullBiasNanos();
     method public boolean hasLeapSecond();
-    method public boolean hasTimeUncertaintyInNs();
+    method public boolean hasTimeUncertaintyNanos();
     method public void reset();
-    method public void resetBiasInNs();
-    method public void resetBiasUncertaintyInNs();
-    method public void resetDriftInNsPerSec();
-    method public void resetDriftUncertaintyInNsPerSec();
-    method public void resetFullBiasInNs();
+    method public void resetBiasNanos();
+    method public void resetBiasUncertaintyNanos();
+    method public void resetDriftNanosPerSecond();
+    method public void resetDriftUncertaintyNanosPerSecond();
+    method public void resetFullBiasNanos();
     method public void resetLeapSecond();
-    method public void resetTimeUncertaintyInNs();
+    method public void resetTimeUncertaintyNanos();
     method public void set(android.location.GnssClock);
-    method public void setBiasInNs(double);
-    method public void setBiasUncertaintyInNs(double);
-    method public void setDriftInNsPerSec(double);
-    method public void setDriftUncertaintyInNsPerSec(double);
-    method public void setFullBiasInNs(long);
+    method public void setBiasNanos(double);
+    method public void setBiasUncertaintyNanos(double);
+    method public void setDriftNanosPerSecond(double);
+    method public void setDriftUncertaintyNanosPerSecond(double);
+    method public void setFullBiasNanos(long);
     method public void setHardwareClockDiscontinuityCount(int);
-    method public void setLeapSecond(short);
-    method public void setTimeInNs(long);
-    method public void setTimeUncertaintyInNs(double);
+    method public void setLeapSecond(int);
+    method public void setTimeNanos(long);
+    method public void setTimeUncertaintyNanos(double);
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.location.GnssClock> CREATOR;
   }
 
   public final class GnssMeasurement implements android.os.Parcelable {
+    ctor public GnssMeasurement();
     method public int describeContents();
-    method public double getAccumulatedDeltaRangeInMeters();
-    method public short getAccumulatedDeltaRangeState();
-    method public double getAccumulatedDeltaRangeUncertaintyInMeters();
-    method public double getAzimuthInDeg();
-    method public double getAzimuthUncertaintyInDeg();
-    method public int getBitNumber();
+    method public double getAccumulatedDeltaRangeMeters();
+    method public int getAccumulatedDeltaRangeState();
+    method public double getAccumulatedDeltaRangeUncertaintyMeters();
     method public long getCarrierCycles();
-    method public float getCarrierFrequencyInHz();
+    method public float getCarrierFrequencyHz();
     method public double getCarrierPhase();
     method public double getCarrierPhaseUncertainty();
-    method public double getCn0InDbHz();
-    method public double getCodePhaseInChips();
-    method public double getCodePhaseUncertaintyInChips();
-    method public byte getConstellationType();
-    method public double getDopplerShiftInHz();
-    method public double getDopplerShiftUncertaintyInHz();
-    method public double getElevationInDeg();
-    method public double getElevationUncertaintyInDeg();
-    method public byte getLossOfLock();
-    method public byte getMultipathIndicator();
-    method public double getPseudorangeInMeters();
-    method public double getPseudorangeRateInMetersPerSec();
-    method public double getPseudorangeRateUncertaintyInMetersPerSec();
-    method public double getPseudorangeUncertaintyInMeters();
-    method public long getReceivedSvTimeInNs();
-    method public long getReceivedSvTimeUncertaintyInNs();
+    method public double getCn0DbHz();
+    method public int getConstellationType();
+    method public int getMultipathIndicator();
+    method public double getPseudorangeRateMetersPerSecond();
+    method public double getPseudorangeRateUncertaintyMetersPerSecond();
+    method public long getReceivedSvTimeNanos();
+    method public long getReceivedSvTimeUncertaintyNanos();
     method public double getSnrInDb();
-    method public short getState();
-    method public short getSvid();
-    method public short getTimeFromLastBitInMs();
-    method public double getTimeOffsetInNs();
-    method public boolean hasAzimuthInDeg();
-    method public boolean hasAzimuthUncertaintyInDeg();
-    method public boolean hasBitNumber();
+    method public int getState();
+    method public int getSvid();
+    method public double getTimeOffsetNanos();
     method public boolean hasCarrierCycles();
-    method public boolean hasCarrierFrequencyInHz();
+    method public boolean hasCarrierFrequencyHz();
     method public boolean hasCarrierPhase();
     method public boolean hasCarrierPhaseUncertainty();
-    method public boolean hasCodePhaseInChips();
-    method public boolean hasCodePhaseUncertaintyInChips();
-    method public boolean hasDopplerShiftInHz();
-    method public boolean hasDopplerShiftUncertaintyInHz();
-    method public boolean hasElevationInDeg();
-    method public boolean hasElevationUncertaintyInDeg();
-    method public boolean hasPseudorangeInMeters();
-    method public boolean hasPseudorangeUncertaintyInMeters();
     method public boolean hasSnrInDb();
-    method public boolean hasTimeFromLastBitInMs();
     method public boolean isPseudorangeRateCorrected();
-    method public boolean isUsedInFix();
     method public void reset();
-    method public void resetAzimuthInDeg();
-    method public void resetAzimuthUncertaintyInDeg();
-    method public void resetBitNumber();
     method public void resetCarrierCycles();
-    method public void resetCarrierFrequencyInHz();
+    method public void resetCarrierFrequencyHz();
     method public void resetCarrierPhase();
     method public void resetCarrierPhaseUncertainty();
-    method public void resetCodePhaseInChips();
-    method public void resetCodePhaseUncertaintyInChips();
-    method public void resetDopplerShiftInHz();
-    method public void resetDopplerShiftUncertaintyInHz();
-    method public void resetElevationInDeg();
-    method public void resetElevationUncertaintyInDeg();
-    method public void resetPseudorangeInMeters();
-    method public void resetPseudorangeUncertaintyInMeters();
     method public void resetSnrInDb();
-    method public void resetTimeFromLastBitInMs();
     method public void set(android.location.GnssMeasurement);
-    method public void setAccumulatedDeltaRangeInMeters(double);
-    method public void setAccumulatedDeltaRangeState(short);
-    method public void setAccumulatedDeltaRangeUncertaintyInMeters(double);
-    method public void setAzimuthInDeg(double);
-    method public void setAzimuthUncertaintyInDeg(double);
-    method public void setBitNumber(int);
+    method public void setAccumulatedDeltaRangeMeters(double);
+    method public void setAccumulatedDeltaRangeState(int);
+    method public void setAccumulatedDeltaRangeUncertaintyMeters(double);
     method public void setCarrierCycles(long);
-    method public void setCarrierFrequencyInHz(float);
+    method public void setCarrierFrequencyHz(float);
     method public void setCarrierPhase(double);
     method public void setCarrierPhaseUncertainty(double);
-    method public void setCn0InDbHz(double);
-    method public void setCodePhaseInChips(double);
-    method public void setCodePhaseUncertaintyInChips(double);
-    method public void setConstellationType(byte);
-    method public void setDopplerShiftInHz(double);
-    method public void setDopplerShiftUncertaintyInHz(double);
-    method public void setElevationInDeg(double);
-    method public void setElevationUncertaintyInDeg(double);
-    method public void setLossOfLock(byte);
-    method public void setMultipathIndicator(byte);
-    method public void setPseudorangeInMeters(double);
-    method public void setPseudorangeRateInMetersPerSec(double);
-    method public void setPseudorangeRateUncertaintyInMetersPerSec(double);
-    method public void setPseudorangeUncertaintyInMeters(double);
-    method public void setReceivedSvTimeInNs(long);
-    method public void setReceivedSvTimeUncertaintyInNs(long);
+    method public void setCn0DbHz(double);
+    method public void setConstellationType(int);
+    method public void setMultipathIndicator(int);
+    method public void setPseudorangeRateCorrected(boolean);
+    method public void setPseudorangeRateMetersPerSecond(double);
+    method public void setPseudorangeRateUncertaintyMetersPerSecond(double);
+    method public void setReceivedSvTimeNanos(long);
+    method public void setReceivedSvTimeUncertaintyNanos(long);
     method public void setSnrInDb(double);
-    method public void setState(short);
-    method public void setSvid(short);
-    method public void setTimeFromLastBitInMs(short);
-    method public void setTimeOffsetInNs(double);
-    method public void setUsedInFix(boolean);
+    method public void setState(int);
+    method public void setSvid(int);
+    method public void setTimeOffsetNanos(double);
     method public void writeToParcel(android.os.Parcel, int);
-    field public static final short ADR_STATE_CYCLE_SLIP = 4; // 0x4
-    field public static final short ADR_STATE_RESET = 2; // 0x2
-    field public static final short ADR_STATE_UNKNOWN = 0; // 0x0
-    field public static final short ADR_STATE_VALID = 1; // 0x1
+    field public static final int ADR_STATE_CYCLE_SLIP = 4; // 0x4
+    field public static final int ADR_STATE_RESET = 2; // 0x2
+    field public static final int ADR_STATE_UNKNOWN = 0; // 0x0
+    field public static final int ADR_STATE_VALID = 1; // 0x1
     field public static final android.os.Parcelable.Creator<android.location.GnssMeasurement> CREATOR;
-    field public static final byte LOSS_OF_LOCK_CYCLE_SLIP = 2; // 0x2
-    field public static final byte LOSS_OF_LOCK_OK = 1; // 0x1
-    field public static final byte LOSS_OF_LOCK_UNKNOWN = 0; // 0x0
-    field public static final byte MULTIPATH_INDICATOR_DETECTED = 1; // 0x1
-    field public static final byte MULTIPATH_INDICATOR_NOT_USED = 2; // 0x2
-    field public static final byte MULTIPATH_INDICATOR_UNKNOWN = 0; // 0x0
-    field public static final short STATE_BIT_SYNC = 2; // 0x2
-    field public static final short STATE_CODE_LOCK = 1; // 0x1
-    field public static final short STATE_MSEC_AMBIGUOUS = 16; // 0x10
-    field public static final short STATE_SUBFRAME_SYNC = 4; // 0x4
-    field public static final short STATE_TOW_DECODED = 8; // 0x8
-    field public static final short STATE_UNKNOWN = 0; // 0x0
-  }
-
-  public static abstract class GnssMeasurement.LossOfLockStatus implements java.lang.annotation.Annotation {
+    field public static final int MULTIPATH_INDICATOR_DETECTED = 1; // 0x1
+    field public static final int MULTIPATH_INDICATOR_NOT_USED = 2; // 0x2
+    field public static final int MULTIPATH_INDICATOR_UNKNOWN = 0; // 0x0
+    field public static final int STATE_BIT_SYNC = 2; // 0x2
+    field public static final int STATE_CODE_LOCK = 1; // 0x1
+    field public static final int STATE_MSEC_AMBIGUOUS = 16; // 0x10
+    field public static final int STATE_SUBFRAME_SYNC = 4; // 0x4
+    field public static final int STATE_TOW_DECODED = 8; // 0x8
+    field public static final int STATE_UNKNOWN = 0; // 0x0
   }
 
   public static abstract class GnssMeasurement.MultipathIndicator implements java.lang.annotation.Annotation {
@@ -19346,7 +19364,7 @@
     method public java.util.Collection<android.location.GnssMeasurement> getMeasurements();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.location.GnssMeasurementsEvent> CREATOR;
-    field public static final int STATUS_GPS_LOCATION_DISABLED = 2; // 0x2
+    field public static final int STATUS_GNSS_LOCATION_DISABLED = 2; // 0x2
     field public static final int STATUS_NOT_SUPPORTED = 0; // 0x0
     field public static final int STATUS_READY = 1; // 0x1
   }
@@ -19361,36 +19379,37 @@
   }
 
   public final class GnssNavigationMessage implements android.os.Parcelable {
+    ctor public GnssNavigationMessage();
     method public int describeContents();
     method public byte[] getData();
-    method public short getMessageId();
-    method public short getStatus();
-    method public short getSubmessageId();
-    method public short getSvid();
-    method public short getType();
+    method public int getMessageId();
+    method public int getStatus();
+    method public int getSubmessageId();
+    method public int getSvid();
+    method public int getType();
     method public void reset();
     method public void set(android.location.GnssNavigationMessage);
     method public void setData(byte[]);
-    method public void setMessageId(short);
-    method public void setStatus(short);
-    method public void setSubmessageId(short);
-    method public void setSvid(short);
-    method public void setType(short);
+    method public void setMessageId(int);
+    method public void setStatus(int);
+    method public void setSubmessageId(int);
+    method public void setSvid(int);
+    method public void setType(int);
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.location.GnssNavigationMessage> CREATOR;
-    field public static final short MESSAGE_TYPE_BDS_D1 = 1281; // 0x501
-    field public static final short MESSAGE_TYPE_BDS_D2 = 1282; // 0x502
-    field public static final short MESSAGE_TYPE_GAL_F = 1538; // 0x602
-    field public static final short MESSAGE_TYPE_GAL_I = 1537; // 0x601
-    field public static final short MESSAGE_TYPE_GLO_L1CA = 769; // 0x301
-    field public static final short MESSAGE_TYPE_GPS_CNAV2 = 260; // 0x104
-    field public static final short MESSAGE_TYPE_GPS_L1CA = 257; // 0x101
-    field public static final short MESSAGE_TYPE_GPS_L2CNAV = 258; // 0x102
-    field public static final short MESSAGE_TYPE_GPS_L5CNAV = 259; // 0x103
-    field public static final short MESSAGE_TYPE_UNKNOWN = 0; // 0x0
-    field public static final short STATUS_PARITY_PASSED = 1; // 0x1
-    field public static final short STATUS_PARITY_REBUILT = 2; // 0x2
-    field public static final short STATUS_UNKNOWN = 0; // 0x0
+    field public static final int STATUS_PARITY_PASSED = 1; // 0x1
+    field public static final int STATUS_PARITY_REBUILT = 2; // 0x2
+    field public static final int STATUS_UNKNOWN = 0; // 0x0
+    field public static final int TYPE_BDS_D1 = 1281; // 0x501
+    field public static final int TYPE_BDS_D2 = 1282; // 0x502
+    field public static final int TYPE_GAL_F = 1538; // 0x602
+    field public static final int TYPE_GAL_I = 1537; // 0x601
+    field public static final int TYPE_GLO_L1CA = 769; // 0x301
+    field public static final int TYPE_GPS_CNAV2 = 260; // 0x104
+    field public static final int TYPE_GPS_L1CA = 257; // 0x101
+    field public static final int TYPE_GPS_L2CNAV = 258; // 0x102
+    field public static final int TYPE_GPS_L5CNAV = 259; // 0x103
+    field public static final int TYPE_UNKNOWN = 0; // 0x0
   }
 
   public static abstract class GnssNavigationMessage.GnssNavigationMessageType implements java.lang.annotation.Annotation {
@@ -19402,7 +19421,7 @@
     method public android.location.GnssNavigationMessage getNavigationMessage();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.location.GnssNavigationMessageEvent> CREATOR;
-    field public static final int STATUS_GPS_LOCATION_DISABLED = 2; // 0x2
+    field public static final int STATUS_GNSS_LOCATION_DISABLED = 2; // 0x2
     field public static final int STATUS_NOT_SUPPORTED = 0; // 0x0
     field public static final int STATUS_READY = 1; // 0x1
   }
@@ -19421,22 +19440,22 @@
   }
 
   public final class GnssStatus {
-    method public float getAzimuth(int);
-    method public byte getConstellationType(int);
-    method public float getElevation(int);
+    method public float getAzimuthDegrees(int);
+    method public float getCn0DbHz(int);
+    method public int getConstellationType(int);
+    method public float getElevationDegrees(int);
     method public int getNumSatellites();
-    method public float getSnr(int);
     method public int getSvid(int);
     method public boolean hasAlmanac(int);
     method public boolean hasEphemeris(int);
     method public boolean usedInFix(int);
-    field public static final byte CONSTELLATION_BEIDOU = 5; // 0x5
-    field public static final byte CONSTELLATION_GALILEO = 6; // 0x6
-    field public static final byte CONSTELLATION_GLONASS = 3; // 0x3
-    field public static final byte CONSTELLATION_GPS = 1; // 0x1
-    field public static final byte CONSTELLATION_QZSS = 4; // 0x4
-    field public static final byte CONSTELLATION_SBAS = 2; // 0x2
-    field public static final byte CONSTELLATION_UNKNOWN = 0; // 0x0
+    field public static final int CONSTELLATION_BEIDOU = 5; // 0x5
+    field public static final int CONSTELLATION_GALILEO = 6; // 0x6
+    field public static final int CONSTELLATION_GLONASS = 3; // 0x3
+    field public static final int CONSTELLATION_GPS = 1; // 0x1
+    field public static final int CONSTELLATION_QZSS = 4; // 0x4
+    field public static final int CONSTELLATION_SBAS = 2; // 0x2
+    field public static final int CONSTELLATION_UNKNOWN = 0; // 0x0
   }
 
   public static abstract class GnssStatus.ConstellationType implements java.lang.annotation.Annotation {
@@ -19552,8 +19571,8 @@
     method public java.util.List<java.lang.String> getProviders(boolean);
     method public java.util.List<java.lang.String> getProviders(android.location.Criteria, boolean);
     method public boolean isProviderEnabled(java.lang.String);
-    method public boolean registerGnssMeasurementCallback(android.location.GnssMeasurementsEvent.Callback);
-    method public boolean registerGnssMeasurementCallback(android.location.GnssMeasurementsEvent.Callback, android.os.Handler);
+    method public boolean registerGnssMeasurementsCallback(android.location.GnssMeasurementsEvent.Callback);
+    method public boolean registerGnssMeasurementsCallback(android.location.GnssMeasurementsEvent.Callback, android.os.Handler);
     method public boolean registerGnssNavigationMessageCallback(android.location.GnssNavigationMessageEvent.Callback);
     method public boolean registerGnssNavigationMessageCallback(android.location.GnssNavigationMessageEvent.Callback, android.os.Handler);
     method public boolean registerGnssStatusCallback(android.location.GnssStatusCallback);
@@ -19578,7 +19597,7 @@
     method public void setTestProviderEnabled(java.lang.String, boolean);
     method public void setTestProviderLocation(java.lang.String, android.location.Location);
     method public void setTestProviderStatus(java.lang.String, int, android.os.Bundle, long);
-    method public void unregisterGnssMeasurementCallback(android.location.GnssMeasurementsEvent.Callback);
+    method public void unregisterGnssMeasurementsCallback(android.location.GnssMeasurementsEvent.Callback);
     method public void unregisterGnssNavigationMessageCallback(android.location.GnssNavigationMessageEvent.Callback);
     method public void unregisterGnssStatusCallback(android.location.GnssStatusCallback);
     field public static final java.lang.String GPS_PROVIDER = "gps";
@@ -19716,7 +19735,7 @@
     field public static final int TYPE_WIRED_HEADSET = 3; // 0x3
   }
 
-  public class AudioFormat implements android.os.Parcelable {
+  public final class AudioFormat implements android.os.Parcelable {
     method public int describeContents();
     method public int getChannelCount();
     method public int getChannelIndexMask();
@@ -19796,7 +19815,7 @@
     method public void adjustVolume(int, int);
     method public void dispatchMediaKeyEvent(android.view.KeyEvent);
     method public int generateAudioSessionId();
-    method public android.media.AudioRecordConfiguration[] getActiveRecordConfigurations();
+    method public android.media.AudioRecordingConfiguration[] getActiveRecordingConfigurations();
     method public android.media.AudioDeviceInfo[] getDevices(int);
     method public int getMode();
     method public java.lang.String getParameters(java.lang.String);
@@ -19942,7 +19961,7 @@
 
   public static abstract class AudioManager.AudioRecordingCallback {
     ctor public AudioManager.AudioRecordingCallback();
-    method public void onRecordConfigChanged();
+    method public void onRecordConfigChanged(android.media.AudioRecordingConfiguration[]);
   }
 
   public static abstract interface AudioManager.OnAudioFocusChangeListener {
@@ -20016,7 +20035,7 @@
     method public abstract void onRoutingChanged(android.media.AudioRecord);
   }
 
-  public class AudioRecordConfiguration implements android.os.Parcelable {
+  public final class AudioRecordingConfiguration implements android.os.Parcelable {
     method public int describeContents();
     method public android.media.AudioDeviceInfo getAudioDevice();
     method public int getClientAudioSessionId();
@@ -20024,12 +20043,13 @@
     method public android.media.AudioFormat getClientFormat();
     method public android.media.AudioFormat getFormat();
     method public void writeToParcel(android.os.Parcel, int);
-    field public static final android.os.Parcelable.Creator<android.media.AudioRecordConfiguration> CREATOR;
+    field public static final android.os.Parcelable.Creator<android.media.AudioRecordingConfiguration> CREATOR;
   }
 
   public abstract interface AudioRouting {
     method public abstract void addOnRoutingListener(android.media.AudioRouting.OnRoutingChangedListener, android.os.Handler);
     method public abstract android.media.AudioDeviceInfo getPreferredDevice();
+    method public abstract android.media.AudioDeviceInfo getRoutedDevice();
     method public abstract void removeOnRoutingListener(android.media.AudioRouting.OnRoutingChangedListener);
     method public abstract boolean setPreferredDevice(android.media.AudioDeviceInfo);
   }
@@ -20231,37 +20251,129 @@
     field public static final int ORIENTATION_TRANSVERSE = 7; // 0x7
     field public static final int ORIENTATION_UNDEFINED = 0; // 0x0
     field public static final java.lang.String TAG_APERTURE = "FNumber";
+    field public static final java.lang.String TAG_APERTURE_VALUE = "ApertureValue";
+    field public static final java.lang.String TAG_ARTIST = "Artist";
+    field public static final java.lang.String TAG_BITS_PER_SAMPLE = "BitsPerSample";
+    field public static final java.lang.String TAG_BRIGHTNESS_VALUE = "BrightnessValue";
+    field public static final java.lang.String TAG_CFA_PATTERN = "CFAPattern";
+    field public static final java.lang.String TAG_COLOR_SPACE = "ColorSpace";
+    field public static final java.lang.String TAG_COMPONENTS_CONFIGURATION = "ComponentsConfiguration";
+    field public static final java.lang.String TAG_COMPRESSED_BITS_PER_PIXEL = "CompressedBitsPerPixel";
+    field public static final java.lang.String TAG_COMPRESSION = "Compression";
+    field public static final java.lang.String TAG_CONTRAST = "Contrast";
+    field public static final java.lang.String TAG_COPYRIGHT = "Copyright";
+    field public static final java.lang.String TAG_CUSTOM_RENDERED = "CustomRendered";
     field public static final java.lang.String TAG_DATETIME = "DateTime";
     field public static final java.lang.String TAG_DATETIME_DIGITIZED = "DateTimeDigitized";
+    field public static final java.lang.String TAG_DATETIME_ORIGINAL = "DateTimeOriginal";
+    field public static final java.lang.String TAG_DEVICE_SETTING_DESCRIPTION = "DeviceSettingDescription";
     field public static final java.lang.String TAG_DIGITAL_ZOOM_RATIO = "DigitalZoomRatio";
+    field public static final java.lang.String TAG_EXIF_VERSION = "ExifVersion";
     field public static final java.lang.String TAG_EXPOSURE_BIAS_VALUE = "ExposureBiasValue";
+    field public static final java.lang.String TAG_EXPOSURE_INDEX = "ExposureIndex";
     field public static final java.lang.String TAG_EXPOSURE_MODE = "ExposureMode";
     field public static final java.lang.String TAG_EXPOSURE_PROGRAM = "ExposureProgram";
     field public static final java.lang.String TAG_EXPOSURE_TIME = "ExposureTime";
+    field public static final java.lang.String TAG_FILE_SOURCE = "FileSource";
     field public static final java.lang.String TAG_FLASH = "Flash";
+    field public static final java.lang.String TAG_FLASHPIX_VERSION = "FlashpixVersion";
+    field public static final java.lang.String TAG_FLASH_ENERGY = "FlashEnergy";
     field public static final java.lang.String TAG_FOCAL_LENGTH = "FocalLength";
+    field public static final java.lang.String TAG_FOCAL_LENGTH_IN_35MM_FILM = "FocalLengthIn35mmFilm";
+    field public static final java.lang.String TAG_FOCAL_PLANE_RESOLUTION_UNIT = "FocalPlaneResolutionUnit";
+    field public static final java.lang.String TAG_FOCAL_PLANE_X_RESOLUTION = "FocalPlaneXResolution";
+    field public static final java.lang.String TAG_FOCAL_PLANE_Y_RESOLUTION = "FocalPlaneYResolution";
+    field public static final java.lang.String TAG_F_NUMBER = "FNumber";
+    field public static final java.lang.String TAG_GAIN_CONTROL = "GainControl";
     field public static final java.lang.String TAG_GPS_ALTITUDE = "GPSAltitude";
     field public static final java.lang.String TAG_GPS_ALTITUDE_REF = "GPSAltitudeRef";
+    field public static final java.lang.String TAG_GPS_AREA_INFORMATION = "GPSAreaInformation";
     field public static final java.lang.String TAG_GPS_DATESTAMP = "GPSDateStamp";
+    field public static final java.lang.String TAG_GPS_DEST_BEARING = "GPSDestBearing";
+    field public static final java.lang.String TAG_GPS_DEST_BEARING_REF = "GPSDestBearingRef";
+    field public static final java.lang.String TAG_GPS_DEST_DISTANCE = "GPSDestDistance";
+    field public static final java.lang.String TAG_GPS_DEST_DISTANCE_REF = "GPSDestDistanceRef";
+    field public static final java.lang.String TAG_GPS_DEST_LATITUDE = "GPSDestLatitude";
+    field public static final java.lang.String TAG_GPS_DEST_LATITUDE_REF = "GPSDestLatitudeRef";
+    field public static final java.lang.String TAG_GPS_DEST_LONGITUDE = "GPSDestLongitude";
+    field public static final java.lang.String TAG_GPS_DEST_LONGITUDE_REF = "GPSDestLongitudeRef";
+    field public static final java.lang.String TAG_GPS_DIFFERENTIAL = "GPSDifferential";
+    field public static final java.lang.String TAG_GPS_DOP = "GPSDOP";
+    field public static final java.lang.String TAG_GPS_IMG_DIRECTION = "GPSImgDirection";
+    field public static final java.lang.String TAG_GPS_IMG_DIRECTION_REF = "GPSImgDirectionRef";
     field public static final java.lang.String TAG_GPS_LATITUDE = "GPSLatitude";
     field public static final java.lang.String TAG_GPS_LATITUDE_REF = "GPSLatitudeRef";
     field public static final java.lang.String TAG_GPS_LONGITUDE = "GPSLongitude";
     field public static final java.lang.String TAG_GPS_LONGITUDE_REF = "GPSLongitudeRef";
+    field public static final java.lang.String TAG_GPS_MAP_DATUM = "GPSMapDatum";
+    field public static final java.lang.String TAG_GPS_MEASURE_MODE = "GPSMeasureMode";
     field public static final java.lang.String TAG_GPS_PROCESSING_METHOD = "GPSProcessingMethod";
+    field public static final java.lang.String TAG_GPS_SATELLITES = "GPSSatellites";
+    field public static final java.lang.String TAG_GPS_SPEED = "GPSSpeed";
+    field public static final java.lang.String TAG_GPS_SPEED_REF = "GPSSpeedRef";
+    field public static final java.lang.String TAG_GPS_STATUS = "GPSStatus";
     field public static final java.lang.String TAG_GPS_TIMESTAMP = "GPSTimeStamp";
+    field public static final java.lang.String TAG_GPS_TRACK = "GPSTrack";
+    field public static final java.lang.String TAG_GPS_TRACK_REF = "GPSTrackRef";
+    field public static final java.lang.String TAG_GPS_VERSION_ID = "GPSVersionID";
+    field public static final java.lang.String TAG_IMAGE_DESCRIPTION = "ImageDescription";
     field public static final java.lang.String TAG_IMAGE_LENGTH = "ImageLength";
+    field public static final java.lang.String TAG_IMAGE_UNIQUE_ID = "ImageUniqueID";
     field public static final java.lang.String TAG_IMAGE_WIDTH = "ImageWidth";
+    field public static final java.lang.String TAG_INTEROPERABILITY_INDEX = "InteroperabilityIndex";
     field public static final java.lang.String TAG_ISO = "ISOSpeedRatings";
+    field public static final java.lang.String TAG_ISO_SPEED_RATINGS = "ISOSpeedRatings";
+    field public static final java.lang.String TAG_JPEG_INTERCHANGE_FORMAT = "JPEGInterchangeFormat";
+    field public static final java.lang.String TAG_JPEG_INTERCHANGE_FORMAT_LENGTH = "JPEGInterchangeFormatLength";
     field public static final java.lang.String TAG_LIGHT_SOURCE = "LightSource";
     field public static final java.lang.String TAG_MAKE = "Make";
+    field public static final java.lang.String TAG_MAKER_NOTE = "MakerNote";
+    field public static final java.lang.String TAG_MAX_APERTURE_VALUE = "MaxApertureValue";
     field public static final java.lang.String TAG_METERING_MODE = "MeteringMode";
     field public static final java.lang.String TAG_MODEL = "Model";
+    field public static final java.lang.String TAG_OECF = "OECF";
     field public static final java.lang.String TAG_ORIENTATION = "Orientation";
+    field public static final java.lang.String TAG_PHOTOMETRIC_INTERPRETATION = "PhotometricInterpretation";
+    field public static final java.lang.String TAG_PIXEL_X_DIMENSION = "PixelXDimension";
+    field public static final java.lang.String TAG_PIXEL_Y_DIMENSION = "PixelYDimension";
+    field public static final java.lang.String TAG_PLANAR_CONFIGURATION = "PlanarConfiguration";
+    field public static final java.lang.String TAG_PRIMARY_CHROMATICITIES = "PrimaryChromaticities";
+    field public static final java.lang.String TAG_REFERENCE_BLACK_WHITE = "ReferenceBlackWhite";
+    field public static final java.lang.String TAG_RELATED_SOUND_FILE = "RelatedSoundFile";
+    field public static final java.lang.String TAG_RESOLUTION_UNIT = "ResolutionUnit";
+    field public static final java.lang.String TAG_ROWS_PER_STRIP = "RowsPerStrip";
+    field public static final java.lang.String TAG_SAMPLES_PER_PIXEL = "SamplesPerPixel";
+    field public static final java.lang.String TAG_SATURATION = "Saturation";
+    field public static final java.lang.String TAG_SCENE_CAPTURE_TYPE = "SceneCaptureType";
+    field public static final java.lang.String TAG_SCENE_TYPE = "SceneType";
+    field public static final java.lang.String TAG_SENSING_METHOD = "SensingMethod";
+    field public static final java.lang.String TAG_SHARPNESS = "Sharpness";
+    field public static final java.lang.String TAG_SHUTTER_SPEED_VALUE = "ShutterSpeedValue";
+    field public static final java.lang.String TAG_SOFTWARE = "Software";
+    field public static final java.lang.String TAG_SPATIAL_FREQUENCY_RESPONSE = "SpatialFrequencyResponse";
+    field public static final java.lang.String TAG_SPECTRAL_SENSITIVITY = "SpectralSensitivity";
+    field public static final java.lang.String TAG_STRIP_BYTE_COUNTS = "StripByteCounts";
+    field public static final java.lang.String TAG_STRIP_OFFSETS = "StripOffsets";
+    field public static final java.lang.String TAG_SUBJECT_AREA = "SubjectArea";
     field public static final java.lang.String TAG_SUBJECT_DISTANCE = "SubjectDistance";
+    field public static final java.lang.String TAG_SUBJECT_DISTANCE_RANGE = "SubjectDistanceRange";
+    field public static final java.lang.String TAG_SUBJECT_LOCATION = "SubjectLocation";
     field public static final java.lang.String TAG_SUBSEC_TIME = "SubSecTime";
     field public static final java.lang.String TAG_SUBSEC_TIME_DIG = "SubSecTimeDigitized";
+    field public static final java.lang.String TAG_SUBSEC_TIME_DIGITIZED = "SubSecTimeDigitized";
     field public static final java.lang.String TAG_SUBSEC_TIME_ORIG = "SubSecTimeOriginal";
+    field public static final java.lang.String TAG_SUBSEC_TIME_ORIGINAL = "SubSecTimeOriginal";
+    field public static final java.lang.String TAG_THUMBNAIL_IMAGE_LENGTH = "ThumbnailImageLength";
+    field public static final java.lang.String TAG_THUMBNAIL_IMAGE_WIDTH = "ThumbnailImageWidth";
+    field public static final java.lang.String TAG_TRANSFER_FUNCTION = "TransferFunction";
+    field public static final java.lang.String TAG_USER_COMMENT = "UserComment";
     field public static final java.lang.String TAG_WHITE_BALANCE = "WhiteBalance";
+    field public static final java.lang.String TAG_WHITE_POINT = "WhitePoint";
+    field public static final java.lang.String TAG_X_RESOLUTION = "XResolution";
+    field public static final java.lang.String TAG_Y_CB_CR_COEFFICIENTS = "YCbCrCoefficients";
+    field public static final java.lang.String TAG_Y_CB_CR_POSITIONING = "YCbCrPositioning";
+    field public static final java.lang.String TAG_Y_CB_CR_SUB_SAMPLING = "YCbCrSubSampling";
+    field public static final java.lang.String TAG_Y_RESOLUTION = "YResolution";
     field public static final int WHITEBALANCE_AUTO = 0; // 0x0
     field public static final int WHITEBALANCE_MANUAL = 1; // 0x1
   }
@@ -20459,6 +20571,7 @@
     field public static final int ERROR_NO_KEY = 1; // 0x1
     field public static final int ERROR_RESOURCE_BUSY = 3; // 0x3
     field public static final int ERROR_SESSION_NOT_OPENED = 5; // 0x5
+    field public static final int ERROR_UNSUPPORTED_OPERATION = 6; // 0x6
   }
 
   public static final class MediaCodec.CryptoInfo {
@@ -20667,6 +20780,7 @@
     field public static final int HEVCMainTierLevel62 = 16777216; // 0x1000000
     field public static final int HEVCProfileMain = 1; // 0x1
     field public static final int HEVCProfileMain10 = 2; // 0x2
+    field public static final int HEVCProfileMain10HDR10 = 4096; // 0x1000
     field public static final int MPEG2LevelH14 = 2; // 0x2
     field public static final int MPEG2LevelHL = 3; // 0x3
     field public static final int MPEG2LevelLL = 0; // 0x0
@@ -20924,6 +21038,7 @@
     method public final void setDataSource(android.content.Context, android.net.Uri, java.util.Map<java.lang.String, java.lang.String>) throws java.io.IOException;
     method public final void setDataSource(java.lang.String, java.util.Map<java.lang.String, java.lang.String>) throws java.io.IOException;
     method public final void setDataSource(java.lang.String) throws java.io.IOException;
+    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 void unselectTrack(int);
@@ -20984,6 +21099,7 @@
     field public static final java.lang.String KEY_DURATION = "durationUs";
     field public static final java.lang.String KEY_FLAC_COMPRESSION_LEVEL = "flac-compression-level";
     field public static final java.lang.String KEY_FRAME_RATE = "frame-rate";
+    field public static final java.lang.String KEY_HDR_STATIC_INFO = "hdr-static-info";
     field public static final java.lang.String KEY_HEIGHT = "height";
     field public static final java.lang.String KEY_INTRA_REFRESH_PERIOD = "intra-refresh-period";
     field public static final java.lang.String KEY_IS_ADTS = "is-adts";
@@ -21008,6 +21124,7 @@
     field public static final java.lang.String KEY_SLICE_HEIGHT = "slice-height";
     field public static final java.lang.String KEY_STRIDE = "stride";
     field public static final java.lang.String KEY_TEMPORAL_LAYERING = "ts-schema";
+    field public static final java.lang.String KEY_TRACK_ID = "track-id";
     field public static final java.lang.String KEY_WIDTH = "width";
     field public static final java.lang.String MIMETYPE_AUDIO_AAC = "audio/mp4a-latm";
     field public static final java.lang.String MIMETYPE_AUDIO_AC3 = "audio/ac3";
@@ -22983,7 +23100,7 @@
   }
 
   public static final class TvInputInfo.Builder {
-    ctor public TvInputInfo.Builder(android.content.Context, java.lang.Class<?>);
+    ctor public TvInputInfo.Builder(android.content.Context, android.content.ComponentName);
     method public android.media.tv.TvInputInfo build() throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
     method public android.media.tv.TvInputInfo.Builder setCanRecord(boolean);
     method public android.media.tv.TvInputInfo.Builder setTunerCount(int);
@@ -23051,7 +23168,7 @@
     ctor public TvInputService.RecordingSession(android.content.Context);
     method public void notifyError(int);
     method public void notifyRecordingStopped(android.net.Uri);
-    method public void notifyTuned();
+    method public void notifyTuned(android.net.Uri);
     method public abstract void onRelease();
     method public abstract void onStartRecording(android.net.Uri);
     method public abstract void onStopRecording();
@@ -23092,6 +23209,7 @@
     method public boolean onTouchEvent(android.view.MotionEvent);
     method public boolean onTrackballEvent(android.view.MotionEvent);
     method public abstract boolean onTune(android.net.Uri);
+    method public boolean onTune(android.net.Uri, android.os.Bundle);
     method public void onUnblockContent(android.media.tv.TvContentRating);
     method public void setOverlayViewEnabled(boolean);
   }
@@ -23110,7 +23228,7 @@
     method public void onDisconnected(java.lang.String);
     method public void onError(int);
     method public void onRecordingStopped(android.net.Uri);
-    method public void onTuned();
+    method public void onTuned(android.net.Uri);
   }
 
   public final class TvTrackInfo implements android.os.Parcelable {
@@ -23165,12 +23283,15 @@
     method public void setOnUnhandledInputEventListener(android.media.tv.TvView.OnUnhandledInputEventListener);
     method public void setStreamVolume(float);
     method public void setTimeShiftPositionCallback(android.media.tv.TvView.TimeShiftPositionCallback);
+    method public void setZOrderMediaOverlay(boolean);
+    method public void setZOrderOnTop(boolean);
     method public void timeShiftPause();
     method public void timeShiftPlay(java.lang.String, android.net.Uri);
     method public void timeShiftResume();
     method public void timeShiftSeekTo(long);
     method public void timeShiftSetPlaybackParams(android.media.PlaybackParams);
     method public void tune(java.lang.String, android.net.Uri);
+    method public void tune(java.lang.String, android.net.Uri, android.os.Bundle);
   }
 
   public static abstract interface TvView.OnUnhandledInputEventListener {
@@ -23530,17 +23651,6 @@
     method public abstract void onNetworkActive();
   }
 
-  public 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 class Credentials {
     ctor public Credentials(int, int, int);
     method public int getGid();
@@ -23548,7 +23658,7 @@
     method public int getUid();
   }
 
-  public class DataUsageRequest implements android.os.Parcelable {
+  public final class DataUsageRequest 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.DataUsageRequest> CREATOR;
@@ -26866,7 +26976,8 @@
     method public static void glGetSynciv(long, int, int, int[], int, int[], int);
     method public static void glGetSynciv(long, int, int, java.nio.IntBuffer, java.nio.IntBuffer);
     method public static void glGetTransformFeedbackVarying(int, int, int, int[], int, int[], int, int[], int, byte[], int);
-    method public static void glGetTransformFeedbackVarying(int, int, int, java.nio.IntBuffer, java.nio.IntBuffer, java.nio.IntBuffer, byte);
+    method public static deprecated void glGetTransformFeedbackVarying(int, int, int, java.nio.IntBuffer, java.nio.IntBuffer, java.nio.IntBuffer, byte);
+    method public static void glGetTransformFeedbackVarying(int, int, int, java.nio.IntBuffer, java.nio.IntBuffer, java.nio.IntBuffer, java.nio.ByteBuffer);
     method public static java.lang.String glGetTransformFeedbackVarying(int, int, int[], int, int[], int);
     method public static java.lang.String glGetTransformFeedbackVarying(int, int, java.nio.IntBuffer, java.nio.IntBuffer);
     method public static int glGetUniformBlockIndex(int, java.lang.String);
@@ -28478,6 +28589,10 @@
     ctor public DeadObjectException(java.lang.String);
   }
 
+  public class DeadSystemException extends android.os.DeadObjectException {
+    ctor public DeadSystemException();
+  }
+
   public final class Debug {
     method public static deprecated void changeDebugPort(int);
     method public static void dumpHprofData(java.lang.String) throws java.io.IOException;
@@ -29125,7 +29240,10 @@
   public class Process {
     ctor public Process();
     method public static final long getElapsedCpuTime();
+    method public static final int[] getExclusiveCores();
     method public static final int getGidForName(java.lang.String);
+    method public static final long getStartElapsedRealtime();
+    method public static final long getStartUptimeMillis();
     method public static final int getThreadPriority(int) throws java.lang.IllegalArgumentException;
     method public static final int getUidForName(java.lang.String);
     method public static final boolean is64Bit();
@@ -29408,6 +29526,147 @@
 
 }
 
+package android.os.health {
+
+  public class HealthStats {
+    method public java.lang.String getDataType();
+    method public long getMeasurement(int);
+    method public int getMeasurementKeyAt(int);
+    method public int getMeasurementKeyCount();
+    method public java.util.Map<java.lang.String, java.lang.Long> getMeasurements(int);
+    method public int getMeasurementsKeyAt(int);
+    method public int getMeasurementsKeyCount();
+    method public java.util.Map<java.lang.String, android.os.health.HealthStats> getStats(int);
+    method public int getStatsKeyAt(int);
+    method public int getStatsKeyCount();
+    method public android.os.health.TimerStat getTimer(int);
+    method public int getTimerCount(int);
+    method public int getTimerKeyAt(int);
+    method public int getTimerKeyCount();
+    method public long getTimerTime(int);
+    method public java.util.Map<java.lang.String, android.os.health.TimerStat> getTimers(int);
+    method public int getTimersKeyAt(int);
+    method public int getTimersKeyCount();
+    method public boolean hasMeasurement(int);
+    method public boolean hasMeasurements(int);
+    method public boolean hasStats(int);
+    method public boolean hasTimer(int);
+    method public boolean hasTimers(int);
+  }
+
+  public final class PackageHealthStats {
+    field public static final int MEASUREMENTS_WAKEUP_ALARMS_COUNT = 40002; // 0x9c42
+    field public static final int STATS_SERVICES = 40001; // 0x9c41
+  }
+
+  public final class PidHealthStats {
+    field public static final int MEASUREMENT_WAKE_NESTING_COUNT = 20001; // 0x4e21
+    field public static final int MEASUREMENT_WAKE_START_MS = 20003; // 0x4e23
+    field public static final int MEASUREMENT_WAKE_SUM_MS = 20002; // 0x4e22
+  }
+
+  public final class ProcessHealthStats {
+    field public static final int MEASUREMENT_ANR_COUNT = 30005; // 0x7535
+    field public static final int MEASUREMENT_CRASHES_COUNT = 30004; // 0x7534
+    field public static final int MEASUREMENT_FOREGROUND_MS = 30006; // 0x7536
+    field public static final int MEASUREMENT_STARTS_COUNT = 30003; // 0x7533
+    field public static final int MEASUREMENT_SYSTEM_TIME_MS = 30002; // 0x7532
+    field public static final int MEASUREMENT_USER_TIME_MS = 30001; // 0x7531
+  }
+
+  public final class ServiceHealthStats {
+    field public static final int MEASUREMENT_LAUNCH_COUNT = 50002; // 0xc352
+    field public static final int MEASUREMENT_START_SERVICE_COUNT = 50001; // 0xc351
+  }
+
+  public class SystemHealthManager {
+    method public static android.os.health.SystemHealthManager from(android.content.Context);
+    method public android.os.health.HealthStats takeMyUidSnapshot();
+    method public android.os.health.HealthStats takeUidSnapshot(int);
+    method public android.os.health.HealthStats[] takeUidSnapshots(int[]);
+  }
+
+  public class TimerStat implements android.os.Parcelable {
+    ctor public TimerStat();
+    ctor public TimerStat(int, long);
+    ctor public TimerStat(android.os.Parcel);
+    method public int describeContents();
+    method public int getCount();
+    method public long getTime();
+    method public void setCount(int);
+    method public void setTime(long);
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.os.health.TimerStat> CREATOR;
+  }
+
+  public final class UidHealthStats {
+    field public static final int MEASUREMENT_BLUETOOTH_IDLE_MS = 10020; // 0x2724
+    field public static final int MEASUREMENT_BLUETOOTH_POWER_MAMS = 10023; // 0x2727
+    field public static final int MEASUREMENT_BLUETOOTH_RX_BYTES = 10052; // 0x2744
+    field public static final int MEASUREMENT_BLUETOOTH_RX_MS = 10021; // 0x2725
+    field public static final int MEASUREMENT_BLUETOOTH_RX_PACKETS = 10058; // 0x274a
+    field public static final int MEASUREMENT_BLUETOOTH_TX_BYTES = 10053; // 0x2745
+    field public static final int MEASUREMENT_BLUETOOTH_TX_MS = 10022; // 0x2726
+    field public static final int MEASUREMENT_BLUETOOTH_TX_PACKETS = 10059; // 0x274b
+    field public static final int MEASUREMENT_BUTTON_USER_ACTIVITY_COUNT = 10046; // 0x273e
+    field public static final int MEASUREMENT_CPU_POWER_MAUS = 10064; // 0x2750
+    field public static final int MEASUREMENT_MOBILE_IDLE_MS = 10024; // 0x2728
+    field public static final int MEASUREMENT_MOBILE_POWER_MAMS = 10027; // 0x272b
+    field public static final int MEASUREMENT_MOBILE_RX_BYTES = 10048; // 0x2740
+    field public static final int MEASUREMENT_MOBILE_RX_MS = 10025; // 0x2729
+    field public static final int MEASUREMENT_MOBILE_RX_PACKETS = 10054; // 0x2746
+    field public static final int MEASUREMENT_MOBILE_TX_BYTES = 10049; // 0x2741
+    field public static final int MEASUREMENT_MOBILE_TX_MS = 10026; // 0x272a
+    field public static final int MEASUREMENT_MOBILE_TX_PACKETS = 10055; // 0x2747
+    field public static final int MEASUREMENT_OTHER_USER_ACTIVITY_COUNT = 10045; // 0x273d
+    field public static final int MEASUREMENT_REALTIME_BATTERY_MS = 10001; // 0x2711
+    field public static final int MEASUREMENT_REALTIME_SCREEN_OFF_BATTERY_MS = 10003; // 0x2713
+    field public static final int MEASUREMENT_SYSTEM_CPU_TIME_US = 10063; // 0x274f
+    field public static final int MEASUREMENT_TOUCH_USER_ACTIVITY_COUNT = 10047; // 0x273f
+    field public static final int MEASUREMENT_UPTIME_BATTERY_MS = 10002; // 0x2712
+    field public static final int MEASUREMENT_UPTIME_SCREEN_OFF_BATTERY_MS = 10004; // 0x2714
+    field public static final int MEASUREMENT_USER_CPU_TIME_US = 10062; // 0x274e
+    field public static final int MEASUREMENT_WIFI_FULL_LOCK_MS = 10029; // 0x272d
+    field public static final int MEASUREMENT_WIFI_IDLE_MS = 10016; // 0x2720
+    field public static final int MEASUREMENT_WIFI_MULTICAST_MS = 10031; // 0x272f
+    field public static final int MEASUREMENT_WIFI_POWER_MAMS = 10019; // 0x2723
+    field public static final int MEASUREMENT_WIFI_RUNNING_MS = 10028; // 0x272c
+    field public static final int MEASUREMENT_WIFI_RX_BYTES = 10050; // 0x2742
+    field public static final int MEASUREMENT_WIFI_RX_MS = 10017; // 0x2721
+    field public static final int MEASUREMENT_WIFI_RX_PACKETS = 10056; // 0x2748
+    field public static final int MEASUREMENT_WIFI_TX_BYTES = 10051; // 0x2743
+    field public static final int MEASUREMENT_WIFI_TX_MS = 10018; // 0x2722
+    field public static final int MEASUREMENT_WIFI_TX_PACKETS = 10057; // 0x2749
+    field public static final int STATS_PACKAGES = 10015; // 0x271f
+    field public static final int STATS_PIDS = 10013; // 0x271d
+    field public static final int STATS_PROCESSES = 10014; // 0x271e
+    field public static final int TIMERS_JOBS = 10010; // 0x271a
+    field public static final int TIMERS_SENSORS = 10012; // 0x271c
+    field public static final int TIMERS_SYNCS = 10009; // 0x2719
+    field public static final int TIMERS_WAKELOCKS_DRAW = 10008; // 0x2718
+    field public static final int TIMERS_WAKELOCKS_FULL = 10005; // 0x2715
+    field public static final int TIMERS_WAKELOCKS_PARTIAL = 10006; // 0x2716
+    field public static final int TIMERS_WAKELOCKS_WINDOW = 10007; // 0x2717
+    field public static final int TIMER_AUDIO = 10032; // 0x2730
+    field public static final int TIMER_BLUETOOTH_SCAN = 10037; // 0x2735
+    field public static final int TIMER_CAMERA = 10035; // 0x2733
+    field public static final int TIMER_FLASHLIGHT = 10034; // 0x2732
+    field public static final int TIMER_FOREGROUND_ACTIVITY = 10036; // 0x2734
+    field public static final int TIMER_GPS_SENSOR = 10011; // 0x271b
+    field public static final int TIMER_MOBILE_RADIO_ACTIVE = 10061; // 0x274d
+    field public static final int TIMER_PROCESS_STATE_BACKGROUND_MS = 10042; // 0x273a
+    field public static final int TIMER_PROCESS_STATE_CACHED_MS = 10043; // 0x273b
+    field public static final int TIMER_PROCESS_STATE_FOREGROUND_MS = 10041; // 0x2739
+    field public static final int TIMER_PROCESS_STATE_FOREGROUND_SERVICE_MS = 10039; // 0x2737
+    field public static final int TIMER_PROCESS_STATE_TOP_MS = 10038; // 0x2736
+    field public static final int TIMER_PROCESS_STATE_TOP_SLEEPING_MS = 10040; // 0x2738
+    field public static final int TIMER_VIBRATOR = 10044; // 0x273c
+    field public static final int TIMER_VIDEO = 10033; // 0x2731
+    field public static final int TIMER_WIFI_SCAN = 10030; // 0x272e
+  }
+
+}
+
 package android.os.storage {
 
   public abstract class OnObbStateChangeListener {
@@ -29432,7 +29691,7 @@
     method public boolean unmountObb(java.lang.String, boolean, android.os.storage.OnObbStateChangeListener);
   }
 
-  public class StorageVolume implements android.os.Parcelable {
+  public final class StorageVolume implements android.os.Parcelable {
     method public android.content.Intent createAccessIntent(java.lang.String);
     method public int describeContents();
     method public java.lang.String getDescription(android.content.Context);
@@ -30268,7 +30527,7 @@
     field public static final java.lang.String COLUMN_ID = "_id";
     field public static final java.lang.String COLUMN_ORIGINAL_NUMBER = "original_number";
     field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/blocked_number";
-    field public static final java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/blocked_numbers";
+    field public static final java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/blocked_number";
     field public static final android.net.Uri CONTENT_URI;
   }
 
@@ -31795,6 +32054,7 @@
 
   public static final class DocumentsContract.Root {
     field public static final java.lang.String COLUMN_AVAILABLE_BYTES = "available_bytes";
+    field public static final java.lang.String COLUMN_CAPACITY_BYTES = "capacity_bytes";
     field public static final java.lang.String COLUMN_DOCUMENT_ID = "document_id";
     field public static final java.lang.String COLUMN_FLAGS = "flags";
     field public static final java.lang.String COLUMN_ICON = "icon";
@@ -32249,6 +32509,7 @@
     field public static final java.lang.String ACTION_VOICE_CONTROL_BATTERY_SAVER_MODE = "android.settings.VOICE_CONTROL_BATTERY_SAVER_MODE";
     field public static final java.lang.String ACTION_VOICE_CONTROL_DO_NOT_DISTURB_MODE = "android.settings.VOICE_CONTROL_DO_NOT_DISTURB_MODE";
     field public static final java.lang.String ACTION_VOICE_INPUT_SETTINGS = "android.settings.VOICE_INPUT_SETTINGS";
+    field public static final java.lang.String ACTION_VR_LISTENER_SETTINGS = "android.settings.VR_LISTENER_SETTINGS";
     field public static final java.lang.String ACTION_WIFI_IP_SETTINGS = "android.settings.WIFI_IP_SETTINGS";
     field public static final java.lang.String ACTION_WIFI_SETTINGS = "android.settings.WIFI_SETTINGS";
     field public static final java.lang.String ACTION_WIRELESS_SETTINGS = "android.settings.WIRELESS_SETTINGS";
@@ -32286,6 +32547,7 @@
     field public static final java.lang.String AUTO_TIME = "auto_time";
     field public static final java.lang.String AUTO_TIME_ZONE = "auto_time_zone";
     field public static final java.lang.String BLUETOOTH_ON = "bluetooth_on";
+    field public static final java.lang.String BOOT_COUNT = "boot_count";
     field public static final java.lang.String CONTACT_METADATA_SYNC = "contact_metadata_sync";
     field public static final android.net.Uri CONTENT_URI;
     field public static final java.lang.String DATA_ROAMING = "data_roaming";
@@ -34319,7 +34581,8 @@
     ctor public CarrierMessagingService();
     method public android.os.IBinder onBind(android.content.Intent);
     method public void onDownloadMms(android.net.Uri, int, android.net.Uri, android.service.carrier.CarrierMessagingService.ResultCallback<java.lang.Integer>);
-    method public void onFilterSms(android.service.carrier.MessagePdu, java.lang.String, int, int, android.service.carrier.CarrierMessagingService.ResultCallback<java.lang.Boolean>);
+    method public deprecated void onFilterSms(android.service.carrier.MessagePdu, java.lang.String, int, int, android.service.carrier.CarrierMessagingService.ResultCallback<java.lang.Boolean>);
+    method public void onReceiveTextSms(android.service.carrier.MessagePdu, java.lang.String, int, int, android.service.carrier.CarrierMessagingService.ResultCallback<java.lang.Integer>);
     method public deprecated void onSendDataSms(byte[], int, java.lang.String, int, android.service.carrier.CarrierMessagingService.ResultCallback<android.service.carrier.CarrierMessagingService.SendSmsResult>);
     method public void onSendDataSms(byte[], int, java.lang.String, int, int, android.service.carrier.CarrierMessagingService.ResultCallback<android.service.carrier.CarrierMessagingService.SendSmsResult>);
     method public void onSendMms(android.net.Uri, int, android.net.Uri, android.service.carrier.CarrierMessagingService.ResultCallback<android.service.carrier.CarrierMessagingService.SendMmsResult>);
@@ -34330,6 +34593,9 @@
     field public static final int DOWNLOAD_STATUS_ERROR = 2; // 0x2
     field public static final int DOWNLOAD_STATUS_OK = 0; // 0x0
     field public static final int DOWNLOAD_STATUS_RETRY_ON_CARRIER_NETWORK = 1; // 0x1
+    field public static final int RECEIVE_OPTIONS_DEFAULT = 0; // 0x0
+    field public static final int RECEIVE_OPTIONS_DROP = 1; // 0x1
+    field public static final int RECEIVE_OPTIONS_SKIP_NOTIFY_WHEN_CREDENTIAL_ENCRYPTED_STORAGE_UNAVAILABLE = 2; // 0x2
     field public static final int SEND_FLAG_REQUEST_DELIVERY_STATUS = 1; // 0x1
     field public static final int SEND_STATUS_ERROR = 2; // 0x2
     field public static final int SEND_STATUS_OK = 0; // 0x0
@@ -34498,8 +34764,9 @@
 package android.service.notification {
 
   public class Condition implements android.os.Parcelable {
-    ctor public Condition(android.net.Uri, java.lang.String, java.lang.String, java.lang.String, int);
+    ctor public Condition(android.net.Uri, java.lang.String, int);
     ctor public Condition(android.net.Uri, java.lang.String, java.lang.String, java.lang.String, int, int, int);
+    ctor public Condition(android.os.Parcel);
     method public android.service.notification.Condition copy();
     method public int describeContents();
     method public static boolean isValidId(android.net.Uri, java.lang.String);
@@ -34530,6 +34797,7 @@
     method public final void notifyConditions(android.service.notification.Condition...);
     method public android.os.IBinder onBind(android.content.Intent);
     method public abstract void onConnected();
+    method public void onRequestConditions(int);
     method public abstract void onSubscribe(android.net.Uri);
     method public abstract void onUnsubscribe(android.net.Uri);
     field public static final java.lang.String EXTRA_RULE_ID = "android.content.automatic.ruleId";
@@ -34561,10 +34829,9 @@
     method public void onNotificationRemoved(android.service.notification.StatusBarNotification, android.service.notification.NotificationListenerService.RankingMap);
     method public final void requestInterruptionFilter(int);
     method public final void requestListenerHints(int);
-    method public static final void requestRebind(android.content.ComponentName) throws android.os.RemoteException;
+    method public static void requestRebind(android.content.ComponentName) throws android.os.RemoteException;
     method public final void requestUnbind() throws android.os.RemoteException;
     method public final void setNotificationsShown(java.lang.String[]);
-    field public static final java.lang.String CATEGORY_VR_NOTIFICATIONS = "android.intent.category.vr.notifications";
     field public static final int HINT_HOST_DISABLE_EFFECTS = 1; // 0x1
     field public static final int INTERRUPTION_FILTER_ALARMS = 4; // 0x4
     field public static final int INTERRUPTION_FILTER_ALL = 1; // 0x1
@@ -34585,10 +34852,11 @@
     method public int getSuppressedVisualEffects();
     method public boolean isAmbient();
     method public boolean matchesInterruptionFilter();
-    field public static final int IMPORTANCE_DEFAULT = 2; // 0x2
-    field public static final int IMPORTANCE_HIGH = 3; // 0x3
-    field public static final int IMPORTANCE_LOW = 1; // 0x1
-    field public static final int IMPORTANCE_MAX = 4; // 0x4
+    field public static final int IMPORTANCE_DEFAULT = 3; // 0x3
+    field public static final int IMPORTANCE_HIGH = 4; // 0x4
+    field public static final int IMPORTANCE_LOW = 2; // 0x2
+    field public static final int IMPORTANCE_MAX = 5; // 0x5
+    field public static final int IMPORTANCE_MIN = 1; // 0x1
     field public static final int IMPORTANCE_NONE = 0; // 0x0
     field public static final int IMPORTANCE_UNSPECIFIED = -1000; // 0xfffffc18
   }
@@ -34858,6 +35126,17 @@
 
 }
 
+package android.service.vr {
+
+  public abstract class VrListenerService extends android.app.Service {
+    ctor public VrListenerService();
+    method public static final boolean isVrModePackageEnabled(android.content.Context, android.content.ComponentName);
+    method public android.os.IBinder onBind(android.content.Intent);
+    field public static final java.lang.String SERVICE_INTERFACE = "android.service.vr.VrListenerService";
+  }
+
+}
+
 package android.service.wallpaper {
 
   public abstract class WallpaperService extends android.app.Service {
@@ -36427,6 +36706,7 @@
   public class TelecomManager {
     method public void addNewIncomingCall(android.telecom.PhoneAccountHandle, android.os.Bundle);
     method public void cancelMissedCallsNotification();
+    method public android.content.Intent createManageBlockedNumbersIntent();
     method public android.net.Uri getAdnUriForPhoneAccount(android.telecom.PhoneAccountHandle);
     method public java.util.List<android.telecom.PhoneAccountHandle> getCallCapablePhoneAccounts();
     method public java.lang.String getDefaultDialerPackage();
@@ -36439,7 +36719,7 @@
     method public boolean handleMmi(java.lang.String, android.telecom.PhoneAccountHandle);
     method public boolean isInCall();
     method public boolean isVoiceMailNumber(android.telecom.PhoneAccountHandle, java.lang.String);
-    method public void launchManageBlockedNumbersActivity();
+    method public deprecated void launchManageBlockedNumbersActivity();
     method public void placeCall(android.net.Uri, android.os.Bundle);
     method public void registerPhoneAccount(android.telecom.PhoneAccount);
     method public void showInCallScreen(boolean);
@@ -38556,7 +38836,6 @@
     method public boolean hasNext();
     method public java.util.Iterator<java.lang.String> iterator();
     method public java.lang.String next();
-    method public void remove();
     method public void setString(java.lang.String);
   }
 
@@ -40168,6 +40447,7 @@
     method public int describeContents();
     method public static android.util.LocaleList forLanguageTags(java.lang.String);
     method public java.util.Locale get(int);
+    method public static android.util.LocaleList getAdjustedDefault();
     method public static android.util.LocaleList getDefault();
     method public static android.util.LocaleList getEmptyLocaleList();
     method public java.util.Locale getFirstMatch(java.lang.String[]);
@@ -47232,6 +47512,7 @@
     method public void setChar(int, java.lang.String, char);
     method public void setCharSequence(int, java.lang.String, java.lang.CharSequence);
     method public void setChronometer(int, long, java.lang.String, boolean);
+    method public void setChronometerCountsDown(int, boolean);
     method public void setContentDescription(int, java.lang.CharSequence);
     method public void setDisplayedChild(int, int);
     method public void setDouble(int, java.lang.String, double);
@@ -50478,6 +50759,7 @@
     method public static long doubleToRawLongBits(double);
     method public double doubleValue();
     method public float floatValue();
+    method public static int hashCode(double);
     method public int intValue();
     method public static boolean isInfinite(double);
     method public boolean isInfinite();
@@ -50485,11 +50767,15 @@
     method public boolean isNaN();
     method public static double longBitsToDouble(long);
     method public long longValue();
+    method public static double max(double, double);
+    method public static double min(double, double);
     method public static double parseDouble(java.lang.String) throws java.lang.NumberFormatException;
+    method public static double sum(double, double);
     method public static java.lang.String toHexString(double);
     method public static java.lang.String toString(double);
     method public static java.lang.Double valueOf(java.lang.String) throws java.lang.NumberFormatException;
     method public static java.lang.Double valueOf(double);
+    field public static final int BYTES = 8; // 0x8
     field public static final int MAX_EXPONENT = 1023; // 0x3ff
     field public static final double MAX_VALUE = 1.7976931348623157E308;
     field public static final int MIN_EXPONENT = -1022; // 0xfffffc02
@@ -50652,10 +50938,13 @@
     method public static java.lang.Integer getInteger(java.lang.String);
     method public static java.lang.Integer getInteger(java.lang.String, int);
     method public static java.lang.Integer getInteger(java.lang.String, java.lang.Integer);
+    method public static int hashCode(int);
     method public static int highestOneBit(int);
     method public int intValue();
     method public long longValue();
     method public static int lowestOneBit(int);
+    method public static int max(int, int);
+    method public static int min(int, int);
     method public static int numberOfLeadingZeros(int);
     method public static int numberOfTrailingZeros(int);
     method public static int parseInt(java.lang.String, int) throws java.lang.NumberFormatException;
@@ -50665,6 +50954,7 @@
     method public static int rotateLeft(int, int);
     method public static int rotateRight(int, int);
     method public static int signum(int);
+    method public static int sum(int, int);
     method public static java.lang.String toBinaryString(int);
     method public static java.lang.String toHexString(int);
     method public static java.lang.String toOctalString(int);
@@ -50673,6 +50963,7 @@
     method public static java.lang.Integer valueOf(java.lang.String, int) throws java.lang.NumberFormatException;
     method public static java.lang.Integer valueOf(java.lang.String) throws java.lang.NumberFormatException;
     method public static java.lang.Integer valueOf(int);
+    field public static final int BYTES = 4; // 0x4
     field public static final int MAX_VALUE = 2147483647; // 0x7fffffff
     field public static final int MIN_VALUE = -2147483648; // 0x80000000
     field public static final int SIZE = 32; // 0x20
@@ -50692,7 +50983,9 @@
   }
 
   public abstract interface Iterable {
+    method public default void forEach(java.util.function.Consumer<? super T>);
     method public abstract java.util.Iterator<T> iterator();
+    method public default java.util.Spliterator<T> spliterator();
   }
 
   public class LinkageError extends java.lang.Error {
@@ -50713,10 +51006,13 @@
     method public static java.lang.Long getLong(java.lang.String);
     method public static java.lang.Long getLong(java.lang.String, long);
     method public static java.lang.Long getLong(java.lang.String, java.lang.Long);
+    method public static int hashCode(long);
     method public static long highestOneBit(long);
     method public int intValue();
     method public long longValue();
     method public static long lowestOneBit(long);
+    method public static long max(long, long);
+    method public static long min(long, long);
     method public static int numberOfLeadingZeros(long);
     method public static int numberOfTrailingZeros(long);
     method public static long parseLong(java.lang.String, int) throws java.lang.NumberFormatException;
@@ -50726,6 +51022,7 @@
     method public static long rotateLeft(long, int);
     method public static long rotateRight(long, int);
     method public static int signum(long);
+    method public static long sum(long, long);
     method public static java.lang.String toBinaryString(long);
     method public static java.lang.String toHexString(long);
     method public static java.lang.String toOctalString(long);
@@ -54167,6 +54464,7 @@
 
   public abstract class Provider extends java.util.Properties {
     ctor protected Provider(java.lang.String, double, java.lang.String);
+    method public synchronized void forEach(java.util.function.BiConsumer<? super java.lang.Object, ? super java.lang.Object>);
     method public java.lang.String getInfo();
     method public java.lang.String getName();
     method public synchronized java.security.Provider.Service getService(java.lang.String, java.lang.String);
@@ -57108,6 +57406,7 @@
     method public E removeLast();
     method public boolean removeLastOccurrence(java.lang.Object);
     method public int size();
+    method public java.util.Spliterator<E> spliterator();
   }
 
   public class ArrayList extends java.util.AbstractList implements java.lang.Cloneable java.util.List java.util.RandomAccess java.io.Serializable {
@@ -57116,8 +57415,10 @@
     ctor public ArrayList(java.util.Collection<? extends E>);
     method public java.lang.Object clone();
     method public void ensureCapacity(int);
+    method public void forEach(java.util.function.Consumer<? super E>);
     method public E get(int);
     method public int size();
+    method public java.util.Spliterator<E> spliterator();
     method public void trimToSize();
   }
 
@@ -57218,6 +57519,14 @@
     method public static void sort(java.lang.Object[], int, int);
     method public static void sort(T[], java.util.Comparator<? super T>);
     method public static void sort(T[], int, int, java.util.Comparator<? super T>);
+    method public static java.util.Spliterator<T> spliterator(T[]);
+    method public static java.util.Spliterator<T> spliterator(T[], int, int);
+    method public static java.util.Spliterator.OfInt spliterator(int[]);
+    method public static java.util.Spliterator.OfInt spliterator(int[], int, int);
+    method public static java.util.Spliterator.OfLong spliterator(long[]);
+    method public static java.util.Spliterator.OfLong spliterator(long[], int, int);
+    method public static java.util.Spliterator.OfDouble spliterator(double[]);
+    method public static java.util.Spliterator.OfDouble spliterator(double[], int, int);
     method public static java.lang.String toString(long[]);
     method public static java.lang.String toString(int[]);
     method public static java.lang.String toString(short[]);
@@ -57448,7 +57757,23 @@
 
   public abstract interface Comparator {
     method public abstract int compare(T, T);
+    method public static java.util.Comparator<T> comparing(java.util.function.Function<? super T, ? extends U>, java.util.Comparator<? super U>);
+    method public static java.util.Comparator<T> comparing(java.util.function.Function<? super T, ? extends U>);
+    method public static java.util.Comparator<T> comparingDouble(java.util.function.ToDoubleFunction<? super T>);
+    method public static java.util.Comparator<T> comparingInt(java.util.function.ToIntFunction<? super T>);
+    method public static java.util.Comparator<T> comparingLong(java.util.function.ToLongFunction<? super T>);
     method public abstract boolean equals(java.lang.Object);
+    method public static java.util.Comparator<T> naturalOrder();
+    method public static java.util.Comparator<T> nullsFirst(java.util.Comparator<? super T>);
+    method public static java.util.Comparator<T> nullsLast(java.util.Comparator<? super T>);
+    method public static java.util.Comparator<T> reverseOrder();
+    method public default java.util.Comparator<T> reversed();
+    method public default java.util.Comparator<T> thenComparing(java.util.Comparator<? super T>);
+    method public default java.util.Comparator<T> thenComparing(java.util.function.Function<? super T, ? extends U>, java.util.Comparator<? super U>);
+    method public default java.util.Comparator<T> thenComparing(java.util.function.Function<? super T, ? extends U>);
+    method public default java.util.Comparator<T> thenComparingDouble(java.util.function.ToDoubleFunction<? super T>);
+    method public default java.util.Comparator<T> thenComparingInt(java.util.function.ToIntFunction<? super T>);
+    method public default java.util.Comparator<T> thenComparingLong(java.util.function.ToLongFunction<? super T>);
   }
 
   public class ConcurrentModificationException extends java.lang.RuntimeException {
@@ -57545,6 +57870,17 @@
     method public abstract int size();
   }
 
+  public class DoubleSummaryStatistics implements java.util.function.DoubleConsumer {
+    ctor public DoubleSummaryStatistics();
+    method public void accept(double);
+    method public void combine(java.util.DoubleSummaryStatistics);
+    method public final double getAverage();
+    method public final long getCount();
+    method public final double getMax();
+    method public final double getMin();
+    method public final double getSum();
+  }
+
   public class DuplicateFormatFlagsException extends java.util.IllegalFormatException {
     ctor public DuplicateFormatFlagsException(java.lang.String);
     method public java.lang.String getFlags();
@@ -57679,6 +58015,7 @@
     ctor public HashMap(java.util.Map<? extends K, ? extends V>);
     method public java.lang.Object clone();
     method public java.util.Set<java.util.Map.Entry<K, V>> entrySet();
+    method public void forEach(java.util.function.BiConsumer<? super K, ? super V>);
   }
 
   public class HashSet extends java.util.AbstractSet implements java.lang.Cloneable java.io.Serializable java.util.Set {
@@ -57689,6 +58026,7 @@
     method public java.lang.Object clone();
     method public java.util.Iterator<E> iterator();
     method public int size();
+    method public java.util.Spliterator<E> spliterator();
   }
 
   public class Hashtable extends java.util.Dictionary implements java.lang.Cloneable java.util.Map java.io.Serializable {
@@ -57703,6 +58041,7 @@
     method public boolean containsValue(java.lang.Object);
     method public synchronized java.util.Enumeration<V> elements();
     method public java.util.Set<java.util.Map.Entry<K, V>> entrySet();
+    method public synchronized void forEach(java.util.function.BiConsumer<? super K, ? super V>);
     method public synchronized V get(java.lang.Object);
     method public synchronized boolean isEmpty();
     method public java.util.Set<K> keySet();
@@ -57721,6 +58060,7 @@
     ctor public IdentityHashMap(java.util.Map<? extends K, ? extends V>);
     method public java.lang.Object clone();
     method public java.util.Set<java.util.Map.Entry<K, V>> entrySet();
+    method public void forEach(java.util.function.BiConsumer<? super K, ? super V>);
   }
 
   public class IllegalFormatCodePointException extends java.util.IllegalFormatException {
@@ -57764,15 +58104,27 @@
     ctor public InputMismatchException(java.lang.String);
   }
 
+  public class IntSummaryStatistics implements java.util.function.IntConsumer {
+    ctor public IntSummaryStatistics();
+    method public void accept(int);
+    method public void combine(java.util.IntSummaryStatistics);
+    method public final double getAverage();
+    method public final long getCount();
+    method public final int getMax();
+    method public final int getMin();
+    method public final long getSum();
+  }
+
   public class InvalidPropertiesFormatException extends java.io.IOException {
     ctor public InvalidPropertiesFormatException(java.lang.Throwable);
     ctor public InvalidPropertiesFormatException(java.lang.String);
   }
 
   public abstract interface Iterator {
+    method public default void forEachRemaining(java.util.function.Consumer<? super E>);
     method public abstract boolean hasNext();
     method public abstract E next();
-    method public abstract void remove();
+    method public default void remove();
   }
 
   public class LinkedHashMap extends java.util.HashMap implements java.util.Map {
@@ -57819,6 +58171,7 @@
     method public E removeLast();
     method public boolean removeLastOccurrence(java.lang.Object);
     method public int size();
+    method public java.util.Spliterator<E> spliterator();
   }
 
   public abstract interface List implements java.util.Collection {
@@ -57954,12 +58307,25 @@
     enum_constant public static final java.util.Locale.Category FORMAT;
   }
 
+  public class LongSummaryStatistics implements java.util.function.IntConsumer java.util.function.LongConsumer {
+    ctor public LongSummaryStatistics();
+    method public void accept(int);
+    method public void accept(long);
+    method public void combine(java.util.LongSummaryStatistics);
+    method public final double getAverage();
+    method public final long getCount();
+    method public final long getMax();
+    method public final long getMin();
+    method public final long getSum();
+  }
+
   public abstract interface Map {
     method public abstract void clear();
     method public abstract boolean containsKey(java.lang.Object);
     method public abstract boolean containsValue(java.lang.Object);
     method public abstract java.util.Set<java.util.Map.Entry<K, V>> entrySet();
     method public abstract boolean equals(java.lang.Object);
+    method public default void forEach(java.util.function.BiConsumer<? super K, ? super V>);
     method public abstract V get(java.lang.Object);
     method public abstract int hashCode();
     method public abstract boolean isEmpty();
@@ -57972,6 +58338,8 @@
   }
 
   public static abstract interface Map.Entry {
+    method public static java.util.Comparator<java.util.Map.Entry<K, V>> comparingByKey();
+    method public static java.util.Comparator<java.util.Map.Entry<K, V>> comparingByKey(java.util.Comparator<? super K>);
     method public abstract boolean equals(java.lang.Object);
     method public abstract K getKey();
     method public abstract V getValue();
@@ -58074,9 +58442,83 @@
     method public abstract void update(java.util.Observable, java.lang.Object);
   }
 
+  public final class Optional {
+    method public static java.util.Optional<T> empty();
+    method public java.util.Optional<T> filter(java.util.function.Predicate<? super T>);
+    method public java.util.Optional<U> flatMap(java.util.function.Function<? super T, java.util.Optional<U>>);
+    method public T get();
+    method public void ifPresent(java.util.function.Consumer<? super T>);
+    method public boolean isPresent();
+    method public java.util.Optional<U> map(java.util.function.Function<? super T, ? extends U>);
+    method public static java.util.Optional<T> of(T);
+    method public static java.util.Optional<T> ofNullable(T);
+    method public T orElse(T);
+    method public T orElseGet(java.util.function.Supplier<? extends T>);
+    method public T orElseThrow(java.util.function.Supplier<? extends X>) throws java.lang.Throwable;
+  }
+
+  public final class OptionalDouble {
+    method public static java.util.OptionalDouble empty();
+    method public double getAsDouble();
+    method public void ifPresent(java.util.function.DoubleConsumer);
+    method public boolean isPresent();
+    method public static java.util.OptionalDouble of(double);
+    method public double orElse(double);
+    method public double orElseGet(java.util.function.DoubleSupplier);
+    method public double orElseThrow(java.util.function.Supplier<X>) throws java.lang.Throwable;
+  }
+
+  public final class OptionalInt {
+    method public static java.util.OptionalInt empty();
+    method public int getAsInt();
+    method public void ifPresent(java.util.function.IntConsumer);
+    method public boolean isPresent();
+    method public static java.util.OptionalInt of(int);
+    method public int orElse(int);
+    method public int orElseGet(java.util.function.IntSupplier);
+    method public int orElseThrow(java.util.function.Supplier<X>) throws java.lang.Throwable;
+  }
+
+  public final class OptionalLong {
+    method public static java.util.OptionalLong empty();
+    method public long getAsLong();
+    method public void ifPresent(java.util.function.LongConsumer);
+    method public boolean isPresent();
+    method public static java.util.OptionalLong of(long);
+    method public long orElse(long);
+    method public long orElseGet(java.util.function.LongSupplier);
+    method public long orElseThrow(java.util.function.Supplier<X>) throws java.lang.Throwable;
+  }
+
+  public abstract interface PrimitiveIterator implements java.util.Iterator {
+    method public abstract void forEachRemaining(T_CONS);
+  }
+
+  public static abstract interface PrimitiveIterator.OfDouble implements java.util.PrimitiveIterator {
+    method public default void forEachRemaining(java.util.function.DoubleConsumer);
+    method public default void forEachRemaining(java.util.function.Consumer<? super java.lang.Double>);
+    method public default java.lang.Double next();
+    method public abstract double nextDouble();
+  }
+
+  public static abstract interface PrimitiveIterator.OfInt implements java.util.PrimitiveIterator {
+    method public default void forEachRemaining(java.util.function.IntConsumer);
+    method public default void forEachRemaining(java.util.function.Consumer<? super java.lang.Integer>);
+    method public default java.lang.Integer next();
+    method public abstract int nextInt();
+  }
+
+  public static abstract interface PrimitiveIterator.OfLong implements java.util.PrimitiveIterator {
+    method public default void forEachRemaining(java.util.function.LongConsumer);
+    method public default void forEachRemaining(java.util.function.Consumer<? super java.lang.Long>);
+    method public default java.lang.Long next();
+    method public abstract long nextLong();
+  }
+
   public class PriorityQueue extends java.util.AbstractQueue implements java.io.Serializable {
     ctor public PriorityQueue();
     ctor public PriorityQueue(int);
+    ctor public PriorityQueue(java.util.Comparator<? super E>);
     ctor public PriorityQueue(int, java.util.Comparator<? super E>);
     ctor public PriorityQueue(java.util.Collection<? extends E>);
     ctor public PriorityQueue(java.util.PriorityQueue<? extends E>);
@@ -58087,6 +58529,7 @@
     method public E peek();
     method public E poll();
     method public int size();
+    method public final java.util.Spliterator<E> spliterator();
   }
 
   public class Properties extends java.util.Hashtable {
@@ -58245,7 +58688,6 @@
     method public short nextShort();
     method public short nextShort(int);
     method public int radix();
-    method public void remove();
     method public java.util.Scanner reset();
     method public java.util.Scanner skip(java.util.regex.Pattern);
     method public java.util.Scanner skip(java.lang.String);
@@ -58330,6 +58772,111 @@
     method public abstract java.util.SortedSet<E> tailSet(E);
   }
 
+  public abstract interface Spliterator {
+    method public abstract int characteristics();
+    method public abstract long estimateSize();
+    method public default void forEachRemaining(java.util.function.Consumer<? super T>);
+    method public default java.util.Comparator<? super T> getComparator();
+    method public default long getExactSizeIfKnown();
+    method public default boolean hasCharacteristics(int);
+    method public abstract boolean tryAdvance(java.util.function.Consumer<? super T>);
+    method public abstract java.util.Spliterator<T> trySplit();
+    field public static final int CONCURRENT = 4096; // 0x1000
+    field public static final int DISTINCT = 1; // 0x1
+    field public static final int IMMUTABLE = 1024; // 0x400
+    field public static final int NONNULL = 256; // 0x100
+    field public static final int ORDERED = 16; // 0x10
+    field public static final int SIZED = 64; // 0x40
+    field public static final int SORTED = 4; // 0x4
+    field public static final int SUBSIZED = 16384; // 0x4000
+  }
+
+  public static abstract interface Spliterator.OfDouble implements java.util.Spliterator.OfPrimitive {
+    method public default void forEachRemaining(java.util.function.DoubleConsumer);
+    method public default void forEachRemaining(java.util.function.Consumer<? super java.lang.Double>);
+    method public abstract boolean tryAdvance(java.util.function.DoubleConsumer);
+    method public default boolean tryAdvance(java.util.function.Consumer<? super java.lang.Double>);
+    method public abstract java.util.Spliterator.OfDouble trySplit();
+  }
+
+  public static abstract interface Spliterator.OfInt implements java.util.Spliterator.OfPrimitive {
+    method public default void forEachRemaining(java.util.function.IntConsumer);
+    method public default void forEachRemaining(java.util.function.Consumer<? super java.lang.Integer>);
+    method public abstract boolean tryAdvance(java.util.function.IntConsumer);
+    method public default boolean tryAdvance(java.util.function.Consumer<? super java.lang.Integer>);
+    method public abstract java.util.Spliterator.OfInt trySplit();
+  }
+
+  public static abstract interface Spliterator.OfLong implements java.util.Spliterator.OfPrimitive {
+    method public default void forEachRemaining(java.util.function.LongConsumer);
+    method public default void forEachRemaining(java.util.function.Consumer<? super java.lang.Long>);
+    method public abstract boolean tryAdvance(java.util.function.LongConsumer);
+    method public default boolean tryAdvance(java.util.function.Consumer<? super java.lang.Long>);
+    method public abstract java.util.Spliterator.OfLong trySplit();
+  }
+
+  public static abstract interface Spliterator.OfPrimitive implements java.util.Spliterator {
+    method public default void forEachRemaining(T_CONS);
+    method public abstract boolean tryAdvance(T_CONS);
+    method public abstract T_SPLITR trySplit();
+  }
+
+  public final class Spliterators {
+    method public static java.util.Spliterator.OfDouble emptyDoubleSpliterator();
+    method public static java.util.Spliterator.OfInt emptyIntSpliterator();
+    method public static java.util.Spliterator.OfLong emptyLongSpliterator();
+    method public static java.util.Spliterator<T> emptySpliterator();
+    method public static java.util.Iterator<T> iterator(java.util.Spliterator<? extends T>);
+    method public static java.util.PrimitiveIterator.OfInt iterator(java.util.Spliterator.OfInt);
+    method public static java.util.PrimitiveIterator.OfLong iterator(java.util.Spliterator.OfLong);
+    method public static java.util.PrimitiveIterator.OfDouble iterator(java.util.Spliterator.OfDouble);
+    method public static java.util.Spliterator<T> spliterator(java.lang.Object[], int);
+    method public static java.util.Spliterator<T> spliterator(java.lang.Object[], int, int, int);
+    method public static java.util.Spliterator.OfInt spliterator(int[], int);
+    method public static java.util.Spliterator.OfInt spliterator(int[], int, int, int);
+    method public static java.util.Spliterator.OfLong spliterator(long[], int);
+    method public static java.util.Spliterator.OfLong spliterator(long[], int, int, int);
+    method public static java.util.Spliterator.OfDouble spliterator(double[], int);
+    method public static java.util.Spliterator.OfDouble spliterator(double[], int, int, int);
+    method public static java.util.Spliterator<T> spliterator(java.util.Collection<? extends T>, int);
+    method public static java.util.Spliterator<T> spliterator(java.util.Iterator<? extends T>, long, int);
+    method public static java.util.Spliterator.OfInt spliterator(java.util.PrimitiveIterator.OfInt, long, int);
+    method public static java.util.Spliterator.OfLong spliterator(java.util.PrimitiveIterator.OfLong, long, int);
+    method public static java.util.Spliterator.OfDouble spliterator(java.util.PrimitiveIterator.OfDouble, long, int);
+    method public static java.util.Spliterator<T> spliteratorUnknownSize(java.util.Iterator<? extends T>, int);
+    method public static java.util.Spliterator.OfInt spliteratorUnknownSize(java.util.PrimitiveIterator.OfInt, int);
+    method public static java.util.Spliterator.OfLong spliteratorUnknownSize(java.util.PrimitiveIterator.OfLong, int);
+    method public static java.util.Spliterator.OfDouble spliteratorUnknownSize(java.util.PrimitiveIterator.OfDouble, int);
+  }
+
+  public static abstract class Spliterators.AbstractDoubleSpliterator implements java.util.Spliterator.OfDouble {
+    ctor protected Spliterators.AbstractDoubleSpliterator(long, int);
+    method public int characteristics();
+    method public long estimateSize();
+    method public java.util.Spliterator.OfDouble trySplit();
+  }
+
+  public static abstract class Spliterators.AbstractIntSpliterator implements java.util.Spliterator.OfInt {
+    ctor protected Spliterators.AbstractIntSpliterator(long, int);
+    method public int characteristics();
+    method public long estimateSize();
+    method public java.util.Spliterator.OfInt trySplit();
+  }
+
+  public static abstract class Spliterators.AbstractLongSpliterator implements java.util.Spliterator.OfLong {
+    ctor protected Spliterators.AbstractLongSpliterator(long, int);
+    method public int characteristics();
+    method public long estimateSize();
+    method public java.util.Spliterator.OfLong trySplit();
+  }
+
+  public static abstract class Spliterators.AbstractSpliterator implements java.util.Spliterator {
+    ctor protected Spliterators.AbstractSpliterator(long, int);
+    method public int characteristics();
+    method public long estimateSize();
+    method public java.util.Spliterator<T> trySplit();
+  }
+
   public class Stack extends java.util.Vector {
     ctor public Stack();
     method public boolean empty();
@@ -58339,6 +58886,15 @@
     method public synchronized int search(java.lang.Object);
   }
 
+  public final class StringJoiner {
+    ctor public StringJoiner(java.lang.CharSequence);
+    ctor public StringJoiner(java.lang.CharSequence, java.lang.CharSequence, java.lang.CharSequence);
+    method public java.util.StringJoiner add(java.lang.CharSequence);
+    method public int length();
+    method public java.util.StringJoiner merge(java.util.StringJoiner);
+    method public java.util.StringJoiner setEmptyValue(java.lang.CharSequence);
+  }
+
   public class StringTokenizer implements java.util.Enumeration {
     ctor public StringTokenizer(java.lang.String, java.lang.String, boolean);
     ctor public StringTokenizer(java.lang.String, java.lang.String);
@@ -58421,6 +58977,7 @@
     method public K firstKey();
     method public java.util.Map.Entry<K, V> floorEntry(K);
     method public K floorKey(K);
+    method public void forEach(java.util.function.BiConsumer<? super K, ? super V>);
     method public java.util.NavigableMap<K, V> headMap(K, boolean);
     method public java.util.SortedMap<K, V> headMap(K);
     method public java.util.Map.Entry<K, V> higherEntry(K);
@@ -58459,6 +59016,7 @@
     method public E pollFirst();
     method public E pollLast();
     method public int size();
+    method public java.util.Spliterator<E> spliterator();
     method public java.util.NavigableSet<E> subSet(E, boolean, E, boolean);
     method public java.util.SortedSet<E> subSet(E, E);
     method public java.util.NavigableSet<E> tailSet(E, boolean);
@@ -58503,6 +59061,7 @@
     method public java.util.Enumeration<E> elements();
     method public synchronized void ensureCapacity(int);
     method public synchronized E firstElement();
+    method public synchronized void forEach(java.util.function.Consumer<? super E>);
     method public synchronized E get(int);
     method public synchronized int indexOf(java.lang.Object, int);
     method public synchronized void insertElementAt(E, int);
@@ -58514,6 +59073,7 @@
     method public synchronized void setElementAt(E, int);
     method public synchronized void setSize(int);
     method public synchronized int size();
+    method public java.util.Spliterator<E> spliterator();
     method public synchronized void trimToSize();
     field protected int capacityIncrement;
     field protected int elementCount;
@@ -58526,6 +59086,7 @@
     ctor public WeakHashMap();
     ctor public WeakHashMap(java.util.Map<? extends K, ? extends V>);
     method public java.util.Set<java.util.Map.Entry<K, V>> entrySet();
+    method public void forEach(java.util.function.BiConsumer<? super K, ? super V>);
   }
 
 }
diff --git a/api/test-removed.txt b/api/test-removed.txt
index 50a24f6..2f55373 100644
--- a/api/test-removed.txt
+++ b/api/test-removed.txt
@@ -37,12 +37,20 @@
 
 package android.media {
 
-  public class AudioFormat implements android.os.Parcelable {
+  public final class AudioFormat implements android.os.Parcelable {
     ctor public AudioFormat();
   }
 
 }
 
+package android.media.tv {
+
+  public class TvView extends android.view.ViewGroup {
+    method public void requestUnblockContent(android.media.tv.TvContentRating);
+  }
+
+}
+
 package android.net {
 
   public class SSLCertificateSocketFactory extends javax.net.ssl.SSLSocketFactory {
@@ -201,14 +209,6 @@
 
 }
 
-package android.service.notification {
-
-  public abstract class ConditionProviderService extends android.app.Service {
-    method public void onRequestConditions(int);
-  }
-
-}
-
 package android.test.mock {
 
   public deprecated class MockPackageManager extends android.content.pm.PackageManager {
diff --git a/cmds/am/src/com/android/commands/am/Am.java b/cmds/am/src/com/android/commands/am/Am.java
index eedb82b..e6c5768 100644
--- a/cmds/am/src/com/android/commands/am/Am.java
+++ b/cmds/am/src/com/android/commands/am/Am.java
@@ -577,7 +577,7 @@
                         return;
                     }
                     List<ResolveInfo> activities = pm.queryIntentActivities(intent, mimeType, 0,
-                            mUserId);
+                            mUserId).getList();
                     if (activities == null || activities.size() <= 0) {
                         System.err.println("Error: Intent does not match any activities: "
                                 + intent);
@@ -606,7 +606,7 @@
                             new File(mProfileFile),
                             ParcelFileDescriptor.MODE_CREATE |
                             ParcelFileDescriptor.MODE_TRUNCATE |
-                            ParcelFileDescriptor.MODE_READ_WRITE);
+                            ParcelFileDescriptor.MODE_WRITE_ONLY);
                 } catch (FileNotFoundException e) {
                     System.err.println("Error: Unable to open file: " + mProfileFile);
                     System.err.println("Consider using a file under /data/local/tmp/");
@@ -903,7 +903,7 @@
             fd = openForSystemServer(file,
                     ParcelFileDescriptor.MODE_CREATE |
                             ParcelFileDescriptor.MODE_TRUNCATE |
-                            ParcelFileDescriptor.MODE_READ_WRITE);
+                            ParcelFileDescriptor.MODE_WRITE_ONLY);
         } catch (FileNotFoundException e) {
             System.err.println("Error: Unable to open file: " + filename);
             System.err.println("Consider using a file under /data/local/tmp/");
@@ -992,7 +992,7 @@
                         new File(profileFile),
                         ParcelFileDescriptor.MODE_CREATE |
                         ParcelFileDescriptor.MODE_TRUNCATE |
-                        ParcelFileDescriptor.MODE_READ_WRITE);
+                        ParcelFileDescriptor.MODE_WRITE_ONLY);
             } catch (FileNotFoundException e) {
                 System.err.println("Error: Unable to open file: " + profileFile);
                 System.err.println("Consider using a file under /data/local/tmp/");
@@ -1052,7 +1052,7 @@
             fd = openForSystemServer(file,
                     ParcelFileDescriptor.MODE_CREATE |
                     ParcelFileDescriptor.MODE_TRUNCATE |
-                    ParcelFileDescriptor.MODE_READ_WRITE);
+                    ParcelFileDescriptor.MODE_WRITE_ONLY);
         } catch (FileNotFoundException e) {
             System.err.println("Error: Unable to open file: " + heapFile);
             System.err.println("Consider using a file under /data/local/tmp/");
@@ -1216,6 +1216,7 @@
 
     class MyActivityController extends IActivityController.Stub {
         final String mGdbPort;
+        final boolean mMonkey;
 
         static final int STATE_NORMAL = 0;
         static final int STATE_CRASHED = 1;
@@ -1242,8 +1243,9 @@
         Thread mGdbThread;
         boolean mGotGdbPrint;
 
-        MyActivityController(String gdbPort) {
+        MyActivityController(String gdbPort, boolean monkey) {
             mGdbPort = gdbPort;
+            mMonkey = monkey;
         }
 
         @Override
@@ -1443,7 +1445,7 @@
             try {
                 printMessageForState();
 
-                mAm.setActivityController(this);
+                mAm.setActivityController(this, mMonkey);
                 mState = STATE_NORMAL;
 
                 InputStreamReader converter = new InputStreamReader(System.in);
@@ -1498,7 +1500,7 @@
             } catch (IOException e) {
                 e.printStackTrace();
             } finally {
-                mAm.setActivityController(null);
+                mAm.setActivityController(null, mMonkey);
             }
         }
     }
@@ -1506,16 +1508,19 @@
     private void runMonitor() throws Exception {
         String opt;
         String gdbPort = null;
+        boolean monkey = false;
         while ((opt=nextOption()) != null) {
             if (opt.equals("--gdb")) {
                 gdbPort = nextArgRequired();
+            } else if (opt.equals("-m")) {
+                monkey = true;
             } else {
                 System.err.println("Error: Unknown option: " + opt);
                 return;
             }
         }
 
-        MyActivityController controller = new MyActivityController(gdbPort);
+        MyActivityController controller = new MyActivityController(gdbPort, monkey);
         controller.run();
     }
 
diff --git a/cmds/app_process/Android.mk b/cmds/app_process/Android.mk
index 51bbb81..3ae9e12 100644
--- a/cmds/app_process/Android.mk
+++ b/cmds/app_process/Android.mk
@@ -20,6 +20,7 @@
     libutils \
     liblog \
     libbinder \
+    libnativeloader \
     libandroid_runtime \
     $(app_process_common_shared_libs) \
 
@@ -52,6 +53,7 @@
     libutils \
     liblog \
     libbinder \
+    libnativeloader \
     libandroid_runtime \
     $(app_process_common_shared_libs) \
 
diff --git a/cmds/app_process/app_main.cpp b/cmds/app_process/app_main.cpp
index 2e02382..8bcbf51 100644
--- a/cmds/app_process/app_main.cpp
+++ b/cmds/app_process/app_main.cpp
@@ -21,6 +21,7 @@
 #include <cutils/properties.h>
 #include <cutils/trace.h>
 #include <android_runtime/AndroidRuntime.h>
+#include <nativeloader/native_loader.h>
 #include <private/android_filesystem_config.h>  // for AID_SYSTEM
 
 namespace android {
@@ -304,6 +305,7 @@
     }
 
     if (zygote) {
+        PreloadPublicNativeLibraries();
         runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
     } else if (className) {
         runtime.start("com.android.internal.os.RuntimeInit", args, zygote);
diff --git a/cmds/bootanimation/BootAnimation.cpp b/cmds/bootanimation/BootAnimation.cpp
index 8f361ce..ea53e59 100644
--- a/cmds/bootanimation/BootAnimation.cpp
+++ b/cmds/bootanimation/BootAnimation.cpp
@@ -68,8 +68,7 @@
 
 // ---------------------------------------------------------------------------
 
-BootAnimation::BootAnimation() : Thread(false), mZip(NULL)
-{
+BootAnimation::BootAnimation() : Thread(false), mZip(NULL), mClockEnabled(true) {
     mSession = new SurfaceComposerClient();
 }
 
@@ -450,6 +449,69 @@
     return true;
 }
 
+// The time glyphs are stored in a single image of height 64 pixels. Each digit is 40 pixels wide,
+// and the colon character is half that at 20 pixels. The glyph order is '0123456789:'.
+// We render 24 hour time.
+void BootAnimation::drawTime(const Texture& clockTex, const int yPos) {
+    static constexpr char TIME_FORMAT[] = "%H:%M";
+    static constexpr int TIME_LENGTH = sizeof(TIME_FORMAT);
+
+    static constexpr int DIGIT_HEIGHT = 64;
+    static constexpr int DIGIT_WIDTH = 40;
+    static constexpr int COLON_WIDTH = DIGIT_WIDTH / 2;
+    static constexpr int TIME_WIDTH = (DIGIT_WIDTH * 4) + COLON_WIDTH;
+
+    if (clockTex.h < DIGIT_HEIGHT || clockTex.w < (10 * DIGIT_WIDTH + COLON_WIDTH)) {
+        ALOGE("Clock texture is too small; abandoning boot animation clock");
+        mClockEnabled = false;
+        return;
+    }
+
+    time_t rawtime;
+    time(&rawtime);
+    struct tm* timeInfo = localtime(&rawtime);
+
+    char timeBuff[TIME_LENGTH];
+    size_t length = strftime(timeBuff, TIME_LENGTH, TIME_FORMAT, timeInfo);
+
+    if (length != TIME_LENGTH - 1) {
+        ALOGE("Couldn't format time; abandoning boot animation clock");
+        mClockEnabled = false;
+        return;
+    }
+
+    glEnable(GL_BLEND);  // Allow us to draw on top of the animation
+    glBindTexture(GL_TEXTURE_2D, clockTex.name);
+
+    int xPos = (mWidth - TIME_WIDTH) / 2;
+    int cropRect[4] = { 0, DIGIT_HEIGHT, DIGIT_WIDTH, -DIGIT_HEIGHT };
+
+    for (int i = 0; i < TIME_LENGTH - 1; i++) {
+        char c = timeBuff[i];
+        int width = DIGIT_WIDTH;
+        int pos = c - '0';  // Position in the character list
+        if (pos < 0 || pos > 10) {
+            continue;
+        }
+        if (c == ':') {
+            width = COLON_WIDTH;
+        }
+
+        // Crop the texture to only the pixels in the current glyph
+        int left = pos * DIGIT_WIDTH;
+        cropRect[0] = left;
+        cropRect[2] = width;
+        glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES, cropRect);
+
+        glDrawTexiOES(xPos, yPos, 0, width, DIGIT_HEIGHT);
+
+        xPos += width;
+    }
+
+    glDisable(GL_BLEND);  // Return to the animation's default behaviour
+    glBindTexture(GL_TEXTURE_2D, 0);
+}
+
 bool BootAnimation::movie()
 {
     String8 desString;
@@ -477,7 +539,12 @@
         if (endl == NULL) break;
         String8 line(s, endl - s);
         const char* l = line.string();
-        int fps, width, height, count, pause;
+        int fps = 0;
+        int width = 0;
+        int height = 0;
+        int count = 0;
+        int pause = 0;
+        int clockPosY = -1;
         char path[ANIM_ENTRY_NAME_MAX];
         char color[7] = "000000"; // default to black if unspecified
 
@@ -487,14 +554,15 @@
             animation.width = width;
             animation.height = height;
             animation.fps = fps;
-        }
-        else if (sscanf(l, " %c %d %d %s #%6s", &pathType, &count, &pause, path, color) >= 4) {
-            // ALOGD("> type=%c, count=%d, pause=%d, path=%s, color=%s", pathType, count, pause, path, color);
+        } else if (sscanf(l, " %c %d %d %s #%6s %d",
+                          &pathType, &count, &pause, path, color, &clockPosY) >= 4) {
+            // ALOGD("> type=%c, count=%d, pause=%d, path=%s, color=%s, clockPosY=%d", pathType, count, pause, path, color, clockPosY);
             Animation::Part part;
             part.playUntilComplete = pathType == 'c';
             part.count = count;
             part.pause = pause;
             part.path = path;
+            part.clockPosY = clockPosY;
             part.audioFile = NULL;
             if (!parseColor(color, part.backgroundColor)) {
                 ALOGE("> invalid color '#%s'", color);
@@ -556,6 +624,8 @@
 
     mZip->endIteration(cookie);
 
+    // Blend required to draw time on top of animation frames.
+    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
     glShadeModel(GL_FLAT);
     glDisable(GL_DITHER);
     glDisable(GL_SCISSOR_TEST);
@@ -569,6 +639,12 @@
     glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
     glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
 
+    bool clockTextureInitialized = false;
+    if (mClockEnabled) {
+        clockTextureInitialized = (initTexture(&mClock, mAssets, "images/clock64.png") == NO_ERROR);
+        mClockEnabled = clockTextureInitialized;
+    }
+
     const int xc = (mWidth - animation.width) / 2;
     const int yc = ((mHeight - animation.height) / 2);
     nsecs_t frameDuration = s2ns(1) / animation.fps;
@@ -629,6 +705,10 @@
                 // which is equivalent to mHeight - (yc + animation.height)
                 glDrawTexiOES(xc, mHeight - (yc + animation.height),
                               0, animation.width, animation.height);
+                if (mClockEnabled && part.clockPosY >= 0) {
+                    drawTime(mClock, part.clockPosY);
+                }
+
                 eglSwapBuffers(mDisplay, mSurface);
 
                 nsecs_t now = systemTime();
@@ -665,6 +745,10 @@
         }
     }
 
+    if (clockTextureInitialized) {
+        glDeleteTextures(1, &mClock.name);
+    }
+
     return false;
 }
 
diff --git a/cmds/bootanimation/BootAnimation.h b/cmds/bootanimation/BootAnimation.h
index f968b25..83e2b38 100644
--- a/cmds/bootanimation/BootAnimation.h
+++ b/cmds/bootanimation/BootAnimation.h
@@ -67,8 +67,10 @@
             }
         };
         struct Part {
-            int count;
-            int pause;
+            int count;  // The number of times this part should repeat, 0 for infinite
+            int pause;  // The number of frames to pause for at the end of this part
+            int clockPosY;  // The y position of the clock, in pixels, from the bottom of the
+                            // display (the clock is centred horizontally). -1 to disable the clock
             String8 path;
             SortedVector<Frame> frames;
             bool playUntilComplete;
@@ -86,6 +88,7 @@
     bool android();
     bool readFile(const char* name, String8& outString);
     bool movie();
+    void drawTime(const Texture& clockTex, const int yPos);
 
     void checkExit();
 
@@ -93,6 +96,7 @@
     sp<AudioPlayer>                 mAudioPlayer;
     AssetManager mAssets;
     Texture     mAndroid[2];
+    Texture     mClock;
     int         mWidth;
     int         mHeight;
     EGLDisplay  mDisplay;
@@ -101,6 +105,7 @@
     sp<SurfaceControl> mFlingerSurfaceControl;
     sp<Surface> mFlingerSurface;
     ZipFileRO   *mZip;
+    bool        mClockEnabled;
 };
 
 // ---------------------------------------------------------------------------
diff --git a/cmds/screencap/screencap.cpp b/cmds/screencap/screencap.cpp
index c469ae4..7bf073b 100644
--- a/cmds/screencap/screencap.cpp
+++ b/cmds/screencap/screencap.cpp
@@ -67,30 +67,6 @@
     }
 }
 
-static status_t vinfoToPixelFormat(const fb_var_screeninfo& vinfo,
-        uint32_t* bytespp, uint32_t* f)
-{
-
-    switch (vinfo.bits_per_pixel) {
-        case 16:
-            *f = PIXEL_FORMAT_RGB_565;
-            *bytespp = 2;
-            break;
-        case 24:
-            *f = PIXEL_FORMAT_RGB_888;
-            *bytespp = 3;
-            break;
-        case 32:
-            // TODO: do better decoding of vinfo here
-            *f = PIXEL_FORMAT_RGBX_8888;
-            *bytespp = 4;
-            break;
-        default:
-            return BAD_VALUE;
-    }
-    return NO_ERROR;
-}
-
 static status_t notifyMediaScanner(const char* fileName) {
     String8 cmd("am broadcast -a android.intent.action.MEDIA_SCANNER_SCAN_FILE -d file://");
     String8 fileUrl("\"");
@@ -147,7 +123,7 @@
             png = true;
         }
     }
-    
+
     if (fd == -1) {
         usage(pname);
         return 1;
@@ -195,28 +171,6 @@
         s = screenshot.getStride();
         f = screenshot.getFormat();
         size = screenshot.getSize();
-    } else {
-        const char* fbpath = "/dev/graphics/fb0";
-        int fb = open(fbpath, O_RDONLY);
-        if (fb >= 0) {
-            struct fb_var_screeninfo vinfo;
-            if (ioctl(fb, FBIOGET_VSCREENINFO, &vinfo) == 0) {
-                uint32_t bytespp;
-                if (vinfoToPixelFormat(vinfo, &bytespp, &f) == NO_ERROR) {
-                    size_t offset = (vinfo.xoffset + vinfo.yoffset*vinfo.xres) * bytespp;
-                    w = vinfo.xres;
-                    h = vinfo.yres;
-                    s = vinfo.xres;
-                    size = w*h*bytespp;
-                    mapsize = offset + size;
-                    mapbase = mmap(0, mapsize, PROT_READ, MAP_PRIVATE, fb, 0);
-                    if (mapbase != MAP_FAILED) {
-                        base = (void const *)((char const *)mapbase + offset);
-                    }
-                }
-            }
-            close(fb);
-        }
     }
 
     if (base != NULL) {
diff --git a/cmds/uiautomator/library/testrunner-src/com/android/uiautomator/core/UiAutomationShellWrapper.java b/cmds/uiautomator/library/testrunner-src/com/android/uiautomator/core/UiAutomationShellWrapper.java
index 1fa9bac..ddeb8e7 100644
--- a/cmds/uiautomator/library/testrunner-src/com/android/uiautomator/core/UiAutomationShellWrapper.java
+++ b/cmds/uiautomator/library/testrunner-src/com/android/uiautomator/core/UiAutomationShellWrapper.java
@@ -50,9 +50,9 @@
         }
         try {
             if (isSet) {
-                am.setActivityController(new DummyActivityController());
+                am.setActivityController(new DummyActivityController(), true);
             } else {
-                am.setActivityController(null);
+                am.setActivityController(null, true);
             }
         } catch (RemoteException e) {
             throw new RuntimeException(e);
diff --git a/core/java/android/accessibilityservice/AccessibilityService.java b/core/java/android/accessibilityservice/AccessibilityService.java
index fb5f5b9..ac3b8e3 100644
--- a/core/java/android/accessibilityservice/AccessibilityService.java
+++ b/core/java/android/accessibilityservice/AccessibilityService.java
@@ -383,13 +383,7 @@
     @Retention(RetentionPolicy.SOURCE)
     @IntDef({SHOW_MODE_AUTO, SHOW_MODE_HIDDEN})
     public @interface SoftKeyboardShowMode {};
-    /**
-     * @hide
-     */
     public static final int SHOW_MODE_AUTO = 0;
-    /**
-     * @hide
-     */
     public static final int SHOW_MODE_HIDDEN = 1;
 
     private int mConnectionId;
@@ -1137,7 +1131,7 @@
         }
 
         /**
-         * Removes all instances of the specified change listener from teh list of magnification
+         * Removes all instances of the specified change listener from the list of magnification
          * change listeners.
          *
          * @param listener the listener to remove, must be non-null
@@ -1216,14 +1210,11 @@
 
         /**
          * Returns the show mode of the soft keyboard. The default show mode is
-         * {@code Settings.Secure.SHOW_MODE_AUTO}, where the soft keyboard is shown when a text
-         * input field is focused. An AccessibilityService can also request the show mode
-         * {@code Settings.Secure.SHOW_MODE_HIDDEN}, where the soft keyboard is never shown.
+         * {@code SHOW_MODE_AUTO}, where the soft keyboard is shown when a text input field is
+         * focused. An AccessibilityService can also request the show mode
+         * {@code SHOW_MODE_HIDDEN}, where the soft keyboard is never shown.
          *
          * @return the current soft keyboard show mode
-         *
-         * @see Settings#Secure#SHOW_MODE_AUTO
-         * @see Settings#Secure#SHOW_MODE_HIDDEN
          */
         @SoftKeyboardShowMode
         public int getShowMode() {
@@ -1239,9 +1230,9 @@
 
         /**
          * Sets the soft keyboard show mode. The default show mode is
-         * {@code Settings.Secure.SHOW_MODE_AUTO}, where the soft keyboard is shown when a text
-         * input field is focused. An AccessibilityService can also request the show mode
-         * {@code Settings.Secure.SHOW_MODE_HIDDEN}, where the soft keyboard is never shown. The
+         * {@code SHOW_MODE_AUTO}, where the soft keyboard is shown when a text input field is
+         * focused. An AccessibilityService can also request the show mode
+         * {@code SHOW_MODE_HIDDEN}, where the soft keyboard is never shown. The
          * The lastto this method will be honored, regardless of any previous calls (including those
          * made by other AccessibilityServices).
          * <p>
@@ -1251,9 +1242,6 @@
          *
          * @param showMode the new show mode for the soft keyboard
          * @return {@code true} on success
-         *
-         * @see Settings#Secure#SHOW_MODE_AUTO
-         * @see Settings#Secure#SHOW_MODE_HIDDEN
          */
         public boolean setShowMode(@SoftKeyboardShowMode int showMode) {
            final IAccessibilityServiceConnection connection =
@@ -1263,9 +1251,13 @@
                try {
                    return connection.setSoftKeyboardShowMode(showMode);
                } catch (RemoteException re) {
-                   Log.w(LOG_TAG, "Falied to set soft keyboard behavior", re);
+                   Log.w(LOG_TAG, "Failed to set soft keyboard behavior", re);
+                   re.rethrowFromSystemServer();
                }
+           } else {
+               throw new RuntimeException("AccessibilityServiceConnection is null");
            }
+
            return false;
         }
 
@@ -1275,9 +1267,9 @@
         public interface OnShowModeChangedListener {
            /**
             * Called when the soft keyboard behavior changes. The default show mode is
-            * {@code Settings.Secure.SHOW_MODE_AUTO}, where the soft keyboard is shown when a text
-            * input field is focused. An AccessibilityService can also request the show mode
-            * {@code Settings.Secure.SHOW_MODE_HIDDEN}, where the soft keyboard is never shown.
+            * {@code SHOW_MODE_AUTO}, where the soft keyboard is shown when a text input field is
+            * focused. An AccessibilityService can also request the show mode
+            * {@code SHOW_MODE_HIDDEN}, where the soft keyboard is never shown.
             *
             * @param controller the soft keyboard controller
             * @param showMode the current soft keyboard show mode
diff --git a/core/java/android/accounts/AccountManager.java b/core/java/android/accounts/AccountManager.java
index 1d9e3bb..e520b40 100644
--- a/core/java/android/accounts/AccountManager.java
+++ b/core/java/android/accounts/AccountManager.java
@@ -353,8 +353,7 @@
         try {
             return mService.getPassword(account);
         } catch (RemoteException e) {
-            // won't ever happen
-            throw new RuntimeException(e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -382,8 +381,7 @@
         try {
             return mService.getUserData(account, key);
         } catch (RemoteException e) {
-            // won't ever happen
-            throw new RuntimeException(e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -402,8 +400,7 @@
         try {
             return mService.getAuthenticatorTypes(UserHandle.getCallingUserId());
         } catch (RemoteException e) {
-            // will never happen
-            throw new RuntimeException(e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -424,8 +421,7 @@
         try {
             return mService.getAuthenticatorTypes(userId);
         } catch (RemoteException e) {
-            // will never happen
-            throw new RuntimeException(e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -449,8 +445,7 @@
         try {
             return mService.getAccounts(null, mContext.getOpPackageName());
         } catch (RemoteException e) {
-            // won't ever happen
-            throw new RuntimeException(e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -475,8 +470,7 @@
         try {
             return mService.getAccountsAsUser(null, userId, mContext.getOpPackageName());
         } catch (RemoteException e) {
-            // won't ever happen
-            throw new RuntimeException(e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -493,8 +487,7 @@
         try {
             return mService.getAccountsForPackage(packageName, uid, mContext.getOpPackageName());
         } catch (RemoteException re) {
-            // won't ever happen
-            throw new RuntimeException(re);
+            throw re.rethrowFromSystemServer();
         }
     }
 
@@ -512,8 +505,7 @@
             return mService.getAccountsByTypeForPackage(type, packageName,
                     mContext.getOpPackageName());
         } catch (RemoteException re) {
-            // won't ever happen
-            throw new RuntimeException(re);
+            throw re.rethrowFromSystemServer();
         }
     }
 
@@ -552,8 +544,7 @@
             return mService.getAccountsAsUser(type, userHandle.getIdentifier(),
                     mContext.getOpPackageName());
         } catch (RemoteException e) {
-            // won't ever happen
-            throw new RuntimeException(e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -572,8 +563,7 @@
         try {
             mService.updateAppPermission(account, authTokenType, uid, value);
         } catch (RemoteException e) {
-            // won't ever happen
-            throw new RuntimeException(e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -742,8 +732,7 @@
         try {
             return mService.addAccountExplicitly(account, password, userdata);
         } catch (RemoteException e) {
-            // Can happen if there was a SecurityException was thrown.
-            throw new RuntimeException(e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -768,7 +757,7 @@
         try {
             return mService.accountAuthenticated(account);
         } catch (RemoteException e) {
-            throw new RuntimeException(e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -836,8 +825,7 @@
         try {
             return mService.getPreviousName(account);
         } catch (RemoteException e) {
-            // will never happen
-            throw new RuntimeException(e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1008,8 +996,7 @@
         try {
             return mService.removeAccountExplicitly(account);
         } catch (RemoteException e) {
-            // May happen if the caller doesn't match the signature of the authenticator.
-            throw new RuntimeException(e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1036,8 +1023,7 @@
                 mService.invalidateAuthToken(accountType, authToken);
             }
         } catch (RemoteException e) {
-            // won't ever happen
-            throw new RuntimeException(e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1068,8 +1054,7 @@
         try {
             return mService.peekAuthToken(account, authTokenType);
         } catch (RemoteException e) {
-            // won't ever happen
-            throw new RuntimeException(e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1098,8 +1083,7 @@
         try {
             mService.setPassword(account, password);
         } catch (RemoteException e) {
-            // won't ever happen
-            throw new RuntimeException(e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1127,8 +1111,7 @@
         try {
             mService.clearPassword(account);
         } catch (RemoteException e) {
-            // won't ever happen
-            throw new RuntimeException(e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1156,8 +1139,7 @@
         try {
             mService.setUserData(account, key, value);
         } catch (RemoteException e) {
-            // Will happen if there is not signature match.
-            throw new RuntimeException(e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1186,8 +1168,7 @@
         try {
             mService.setAuthToken(account, authTokenType, authToken);
         } catch (RemoteException e) {
-            // won't ever happen
-            throw new RuntimeException(e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1588,7 +1569,7 @@
             mService.addSharedAccountsFromParentUser(parentUser.getIdentifier(),
                     user.getIdentifier());
         } catch (RemoteException re) {
-            throw new IllegalStateException(re);
+            throw re.rethrowFromSystemServer();
         }
     }
 
@@ -1641,8 +1622,7 @@
             boolean val = mService.removeSharedAccountAsUser(account, user.getIdentifier());
             return val;
         } catch (RemoteException re) {
-            // won't ever happen
-            throw new RuntimeException(re);
+            throw re.rethrowFromSystemServer();
         }
     }
 
@@ -1655,8 +1635,7 @@
         try {
             return mService.getSharedAccountsAsUser(user.getIdentifier());
         } catch (RemoteException re) {
-            // won't ever happen
-            throw new RuntimeException(re);
+            throw re.rethrowFromSystemServer();
         }
     }
 
@@ -1878,7 +1857,7 @@
         try {
             return mService.someUserHasAccount(account);
         } catch (RemoteException re) {
-            throw new RuntimeException(re);
+            throw re.rethrowFromSystemServer();
         }
     }
 
@@ -2039,8 +2018,7 @@
                     try {
                         doWork();
                     } catch (RemoteException e) {
-                        // this will only happen if the system process is dead, which means
-                        // we will be dying ourselves
+                        throw e.rethrowFromSystemServer();
                     }
                 } else {
                     set(bundle);
diff --git a/core/java/android/animation/AnimatorInflater.java b/core/java/android/animation/AnimatorInflater.java
index 20d71a6..8d03b55 100644
--- a/core/java/android/animation/AnimatorInflater.java
+++ b/core/java/android/animation/AnimatorInflater.java
@@ -108,7 +108,7 @@
             float pathErrorScale) throws NotFoundException {
         final ConfigurationBoundResourceCache<Animator> animatorCache = resources
                 .getAnimatorCache();
-        Animator animator = animatorCache.getInstance(id, theme);
+        Animator animator = animatorCache.getInstance(id, resources, theme);
         if (animator != null) {
             if (DBG_ANIMATOR_INFLATER) {
                 Log.d(TAG, "loaded animator from cache, " + resources.getResourceName(id));
@@ -157,7 +157,7 @@
         final ConfigurationBoundResourceCache<StateListAnimator> cache = resources
                 .getStateListAnimatorCache();
         final Theme theme = context.getTheme();
-        StateListAnimator animator = cache.getInstance(id, theme);
+        StateListAnimator animator = cache.getInstance(id, resources, theme);
         if (animator != null) {
             return animator;
         }
diff --git a/core/java/android/animation/ValueAnimator.java b/core/java/android/animation/ValueAnimator.java
index e721de9..663f297 100644
--- a/core/java/android/animation/ValueAnimator.java
+++ b/core/java/android/animation/ValueAnimator.java
@@ -972,7 +972,14 @@
             // to be consistent with the previous behavior. Otherwise, postpone this until the first
             // frame after the start delay.
             startAnimation();
-            setCurrentFraction(mSeekFraction == -1 ? 0 : mSeekFraction);
+            if (mSeekFraction == -1) {
+                // No seek, start at play time 0. Note that the reason we are not using fraction 0
+                // is because for animations with 0 duration, we want to be consistent with pre-N
+                // behavior: skip to the final value immediately.
+                setCurrentPlayTime(0);
+            } else {
+                setCurrentFraction(mSeekFraction);
+            }
         }
     }
 
@@ -1029,8 +1036,16 @@
 
     @Override
     public void resume() {
-        if (mPaused) {
+        if (Looper.myLooper() == null) {
+            throw new AndroidRuntimeException("Animators may only be resumed from the same " +
+                    "thread that the animator was started on");
+        }
+        if (mPaused && !mResumed) {
             mResumed = true;
+            if (mPauseTime > 0) {
+                AnimationHandler handler = AnimationHandler.getInstance();
+                handler.addAnimationFrameCallback(this, 0);
+            }
         }
         super.resume();
     }
@@ -1235,9 +1250,8 @@
         }
         mLastFrameTime = frameTime;
         if (mPaused) {
-            if (mPauseTime < 0) {
-                mPauseTime = frameTime;
-            }
+            mPauseTime = frameTime;
+            handler.removeCallback(this);
             return;
         } else if (mResumed) {
             mResumed = false;
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 4792dc9..6b67b95 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -41,6 +41,7 @@
 import android.content.IntentSender;
 import android.content.SharedPreferences;
 import android.content.pm.ActivityInfo;
+import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.res.Configuration;
@@ -68,6 +69,7 @@
 import android.os.PersistableBundle;
 import android.os.RemoteException;
 import android.os.StrictMode;
+import android.os.SystemProperties;
 import android.os.UserHandle;
 import android.text.Selection;
 import android.text.SpannableStringBuilder;
@@ -110,6 +112,7 @@
 import android.view.WindowManagerGlobal;
 import android.view.accessibility.AccessibilityEvent;
 import android.widget.AdapterView;
+import android.widget.Toast;
 import android.widget.Toolbar;
 
 import com.android.internal.app.IVoiceInteractor;
@@ -832,6 +835,8 @@
     private boolean mHasCurrentPermissionsRequest;
     private boolean mEatKeyUpEvent;
 
+    private static native String getDlWarning();
+
     /** Return the intent that started this activity. */
     public Intent getIntent() {
         return mIntent;
@@ -1119,34 +1124,6 @@
     }
 
     /**
-     * Attempts to extract the color from a given drawable.
-     *
-     * @return the extracted color or 0 if no color could be extracted.
-     */
-    private int tryExtractColorFromDrawable(Drawable drawable) {
-        if (drawable instanceof ColorDrawable) {
-            return ((ColorDrawable) drawable).getColor();
-        } else if (drawable instanceof InsetDrawable) {
-            return tryExtractColorFromDrawable(((InsetDrawable) drawable).getDrawable());
-        } else if (drawable instanceof ShapeDrawable) {
-            Paint p = ((ShapeDrawable) drawable).getPaint();
-            if (p != null) {
-                return p.getColor();
-            }
-        } else if (drawable instanceof LayerDrawable) {
-            LayerDrawable ld = (LayerDrawable) drawable;
-            int numLayers = ld.getNumberOfLayers();
-            for (int i = 0; i < numLayers; i++) {
-                int color = tryExtractColorFromDrawable(ld.getDrawable(i));
-                if (color != 0) {
-                    return color;
-                }
-            }
-        }
-        return 0;
-    }
-
-    /**
      * Called when activity start-up is complete (after {@link #onStart}
      * and {@link #onRestoreInstanceState} have been called).  Applications will
      * generally not implement this method; it is intended for system
@@ -1168,35 +1145,6 @@
             onTitleChanged(getTitle(), getTitleColor());
         }
 
-        Resources.Theme theme = getTheme();
-        if (theme != null) {
-            // Get the primary color and update the TaskDescription for this activity
-            TypedArray a = theme.obtainStyledAttributes(
-                    com.android.internal.R.styleable.ActivityTaskDescription);
-            if (mTaskDescription.getPrimaryColor() == 0) {
-                int colorPrimary = a.getColor(
-                        com.android.internal.R.styleable.ActivityTaskDescription_colorPrimary, 0);
-                if (colorPrimary != 0 && Color.alpha(colorPrimary) == 0xFF) {
-                    mTaskDescription.setPrimaryColor(colorPrimary);
-                }
-            }
-            if (mTaskDescription.getBackgroundColor() == 0) {
-                int windowBgResourceId = a.getResourceId(
-                        com.android.internal.R.styleable.ActivityTaskDescription_windowBackground,
-                        0);
-                int windowBgFallbackResourceId = a.getResourceId(
-                        com.android.internal.R.styleable.ActivityTaskDescription_windowBackgroundFallback,
-                        0);
-                int colorBg = tryExtractColorFromDrawable(DecorView.getResizingBackgroundDrawable(
-                        this, windowBgResourceId, windowBgFallbackResourceId));
-                if (colorBg != 0 && Color.alpha(colorBg) == 0xFF) {
-                    mTaskDescription.setBackgroundColor(colorBg);
-                }
-            }
-            a.recycle();
-            setTaskDescription(mTaskDescription);
-        }
-
         mCalled = true;
     }
 
@@ -4036,6 +3984,27 @@
             }
             theme.applyStyle(resid, false);
         }
+
+        // Get the primary color and update the TaskDescription for this activity
+        TypedArray a = theme.obtainStyledAttributes(
+                com.android.internal.R.styleable.ActivityTaskDescription);
+        if (mTaskDescription.getPrimaryColor() == 0) {
+            int colorPrimary = a.getColor(
+                    com.android.internal.R.styleable.ActivityTaskDescription_colorPrimary, 0);
+            if (colorPrimary != 0 && Color.alpha(colorPrimary) == 0xFF) {
+                mTaskDescription.setPrimaryColor(colorPrimary);
+            }
+        }
+        // For dev-preview only.
+        if (mTaskDescription.getBackgroundColor() == 0) {
+            int colorBackground = a.getColor(
+                    com.android.internal.R.styleable.ActivityTaskDescription_colorBackground, 0);
+            if (colorBackground != 0 && Color.alpha(colorBackground) == 0xFF) {
+                mTaskDescription.setBackgroundColor(colorBackground);
+            }
+        }
+        a.recycle();
+        setTaskDescription(mTaskDescription);
     }
 
     /**
@@ -6208,14 +6177,24 @@
     /**
      * Enable or disable virtual reality (VR) mode.
      *
-     * <p>VR mode is a hint to Android system services to switch to modes optimized for
-     * high-performance stereoscopic rendering.</p>
+     * <p>VR mode is a hint to Android system services to switch to a mode optimized for
+     * high-performance stereoscopic rendering.  This mode will be enabled while this Activity has
+     * focus.</p>
      *
      * @param enabled {@code true} to enable this mode.
+     * @param requestedComponent the name of the component to use as a
+     *        {@link android.service.vr.VrListenerService} while VR mode is enabled.
+     *
+     * @throws android.content.pm.PackageManager.NameNotFoundException;
      */
-    public void setVrMode(boolean enabled) {
+    public void setVrModeEnabled(boolean enabled, @NonNull ComponentName requestedComponent)
+          throws PackageManager.NameNotFoundException {
         try {
-            ActivityManagerNative.getDefault().setVrMode(mToken, enabled);
+            if (ActivityManagerNative.getDefault().setVrMode(mToken, enabled, requestedComponent)
+                    != 0) {
+                throw new PackageManager.NameNotFoundException(
+                        requestedComponent.flattenToString());
+            }
         } catch (RemoteException e) {
             // pass
         }
@@ -6621,6 +6600,32 @@
         }
         mFragments.dispatchStart();
         mFragments.reportLoaderStart();
+
+        // This property is set for all builds except final release
+        boolean isDlwarningEnabled = SystemProperties.getInt("ro.bionic.ld.warning", 0) == 1;
+        boolean isAppDebuggable =
+                (mApplication.getApplicationInfo().flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0;
+
+        if (isAppDebuggable || isDlwarningEnabled) {
+            String dlwarning = getDlWarning();
+            if (dlwarning != null) {
+                String appName = getApplicationInfo().loadLabel(getPackageManager())
+                        .toString();
+                String warning = "Detected problems with app native libraries\n" +
+                                 "(please consult log for detail):\n" + dlwarning;
+                if (isAppDebuggable) {
+                      new AlertDialog.Builder(this).
+                          setTitle(appName).
+                          setMessage(warning).
+                          setPositiveButton(android.R.string.ok, null).
+                          setCancelable(false).
+                          show();
+                } else {
+                    Toast.makeText(this, appName + "\n" + warning, Toast.LENGTH_LONG).show();
+                }
+            }
+        }
+
         mActivityTransitionState.enterReady(this);
     }
 
@@ -6628,9 +6633,7 @@
         mFragments.noteStateNotSaved();
 
         if (mToken != null && mParent == null) {
-            // We might have view roots that were preserved during a relaunch, we need to start them
-            // again. We don't need to check mStopped, the roots will check if they were actually
-            // stopped.
+            // No need to check mStopped, the roots will check if they were actually stopped.
             WindowManagerGlobal.getInstance().setStoppedState(mToken, false /* stopped */);
         }
 
@@ -6728,7 +6731,7 @@
         onUserLeaveHint();
     }
 
-    final void performStop() {
+    final void performStop(boolean preserveWindow) {
         mDoReportFullyDrawn = false;
         mFragments.doLoaderStop(mChangingConfigurations /*retain*/);
 
@@ -6737,7 +6740,10 @@
                 mWindow.closeAllPanels();
             }
 
-            if (mToken != null && mParent == null) {
+            // If we're preserving the window, don't setStoppedState to true, since we
+            // need the window started immediately again. Stopping the window will
+            // destroys hardware resources and causes flicker.
+            if (!preserveWindow && mToken != null && mParent == null) {
                 WindowManagerGlobal.getInstance().setStoppedState(mToken, true);
             }
 
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index b1927d0..2f6907e 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -577,6 +577,16 @@
         }
 
         /**
+         * Return whether a stackId is a stack containing floating windows. Floating windows
+         * are laid out differently as they are allowed to extend past the display bounds
+         * without overscan insets.
+         */
+        public static boolean tasksAreFloating(int stackId) {
+            return stackId == FREEFORM_WORKSPACE_STACK_ID
+                || stackId == PINNED_STACK_ID;
+        }
+
+        /**
          * Returns true if animation specs should be constructed for app transition that moves
          * the task to the specified stack.
          */
@@ -647,6 +657,16 @@
             return stackId != PINNED_STACK_ID && stackId != FREEFORM_WORKSPACE_STACK_ID
                     && stackId != DOCKED_STACK_ID;
         }
+
+        /**
+         * Returns true if the input stack id should only be present on a device that supports
+         * multi-window mode.
+         * @see android.app.ActivityManager#supportsMultiWindow
+         */
+        public static boolean isMultiWindowStack(int stackId) {
+            return isStaticStack(stackId) || stackId == PINNED_STACK_ID
+                    || stackId == FREEFORM_WORKSPACE_STACK_ID || stackId == DOCKED_STACK_ID;
+        }
     }
 
     /**
@@ -716,8 +736,7 @@
         try {
             return ActivityManagerNative.getDefault().getFrontActivityScreenCompatMode();
         } catch (RemoteException e) {
-            // System dead, we will be dead too soon!
-            return 0;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -726,7 +745,7 @@
         try {
             ActivityManagerNative.getDefault().setFrontActivityScreenCompatMode(mode);
         } catch (RemoteException e) {
-            // System dead, we will be dead too soon!
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -735,8 +754,7 @@
         try {
             return ActivityManagerNative.getDefault().getPackageScreenCompatMode(packageName);
         } catch (RemoteException e) {
-            // System dead, we will be dead too soon!
-            return 0;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -745,7 +763,7 @@
         try {
             ActivityManagerNative.getDefault().setPackageScreenCompatMode(packageName, mode);
         } catch (RemoteException e) {
-            // System dead, we will be dead too soon!
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -754,8 +772,7 @@
         try {
             return ActivityManagerNative.getDefault().getPackageAskScreenCompat(packageName);
         } catch (RemoteException e) {
-            // System dead, we will be dead too soon!
-            return false;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -764,7 +781,7 @@
         try {
             ActivityManagerNative.getDefault().setPackageAskScreenCompat(packageName, ask);
         } catch (RemoteException e) {
-            // System dead, we will be dead too soon!
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -871,6 +888,17 @@
     }
 
     /**
+     * Returns true if the system supports at least one form of multi-window.
+     * E.g. freeform, split-screen, picture-in-picture.
+     * @hide
+     */
+    static public boolean supportsMultiWindow() {
+        return !isLowRamDeviceStatic()
+                && Resources.getSystem().getBoolean(
+                    com.android.internal.R.bool.config_supportsMultiWindow);
+    }
+
+    /**
      * Information you can set and retrieve about the current activity within the recent task list.
      */
     public static class TaskDescription implements Parcelable {
@@ -1049,6 +1077,7 @@
                     return ActivityManagerNative.getDefault().getTaskDescriptionIcon(iconFilename,
                             userId);
                 } catch (RemoteException e) {
+                    throw e.rethrowFromSystemServer();
                 }
             }
             return null;
@@ -1429,8 +1458,7 @@
             return ActivityManagerNative.getDefault().getRecentTasks(maxNum,
                     flags, UserHandle.myUserId());
         } catch (RemoteException e) {
-            // System dead, we will be dead too soon!
-            return null;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1455,8 +1483,7 @@
             return ActivityManagerNative.getDefault().getRecentTasks(maxNum,
                     flags, userId);
         } catch (RemoteException e) {
-            // System dead, we will be dead too soon!
-            return null;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1548,6 +1575,7 @@
                     Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
             dest.writeInt(numActivities);
             dest.writeInt(numRunning);
+            dest.writeInt(isDockable ? 1 : 0);
         }
 
         public void readFromParcel(Parcel source) {
@@ -1563,6 +1591,7 @@
             description = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(source);
             numActivities = source.readInt();
             numRunning = source.readInt();
+            isDockable = source.readInt() != 0;
         }
 
         public static final Creator<RunningTaskInfo> CREATOR = new Creator<RunningTaskInfo>() {
@@ -1591,8 +1620,7 @@
         try {
             appTasks = ActivityManagerNative.getDefault().getAppTasks(mContext.getPackageName());
         } catch (RemoteException e) {
-            // System dead, we will be dead too soon!
-            return null;
+            throw e.rethrowFromSystemServer();
         }
         int numAppTasks = appTasks.size();
         for (int i = 0; i < numAppTasks; i++) {
@@ -1617,7 +1645,7 @@
             try {
                 mAppTaskThumbnailSize = ActivityManagerNative.getDefault().getAppTaskThumbnailSize();
             } catch (RemoteException e) {
-                throw new IllegalStateException("System dead?", e);
+                throw e.rethrowFromSystemServer();
             }
         }
     }
@@ -1683,7 +1711,7 @@
             return ActivityManagerNative.getDefault().addAppTask(activity.getActivityToken(),
                     intent, description, thumbnail);
         } catch (RemoteException e) {
-            throw new IllegalStateException("System dead?", e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1725,8 +1753,7 @@
         try {
             return ActivityManagerNative.getDefault().getTasks(maxNum, 0);
         } catch (RemoteException e) {
-            // System dead, we will be dead too soon!
-            return null;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1742,8 +1769,7 @@
         try {
             return ActivityManagerNative.getDefault().removeTask(taskId);
         } catch (RemoteException e) {
-            // System dead, we will be dead too soon!
-            return false;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1902,8 +1928,7 @@
         try {
             return ActivityManagerNative.getDefault().getTaskThumbnail(id);
         } catch (RemoteException e) {
-            // System dead, we will be dead too soon!
-            return null;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1912,8 +1937,7 @@
         try {
             return ActivityManagerNative.getDefault().isInHomeStack(taskId);
         } catch (RemoteException e) {
-            // System dead, we will be dead too soon!
-            return false;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1962,7 +1986,7 @@
         try {
             ActivityManagerNative.getDefault().moveTaskToFront(taskId, flags, options);
         } catch (RemoteException e) {
-            // System dead, we will be dead too soon!
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -2148,8 +2172,7 @@
             return ActivityManagerNative.getDefault()
                     .getServices(maxNum, 0);
         } catch (RemoteException e) {
-            // System dead, we will be dead too soon!
-            return null;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -2164,8 +2187,7 @@
             return ActivityManagerNative.getDefault()
                     .getRunningServiceControlPanel(service);
         } catch (RemoteException e) {
-            // System dead, we will be dead too soon!
-            return null;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -2269,6 +2291,7 @@
         try {
             ActivityManagerNative.getDefault().getMemoryInfo(outInfo);
         } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -2387,7 +2410,7 @@
             return ActivityManagerNative.getDefault().clearApplicationUserData(packageName,
                     observer, UserHandle.myUserId());
         } catch (RemoteException e) {
-            return false;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -2421,8 +2444,7 @@
             return ActivityManagerNative.getDefault().getGrantedUriPermissions(packageName,
                     UserHandle.myUserId());
         } catch (RemoteException e) {
-            Log.e(TAG, "Couldn't get granted URI permissions for :" + packageName, e);
-            return ParceledListSlice.emptyList();
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -2440,7 +2462,7 @@
             ActivityManagerNative.getDefault().clearGrantedUriPermissions(packageName,
                     UserHandle.myUserId());
         } catch (RemoteException e) {
-            Log.e(TAG, "Couldn't clear granted URI permissions for :" + packageName, e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -2560,7 +2582,7 @@
         try {
             return ActivityManagerNative.getDefault().getProcessesInErrorState();
         } catch (RemoteException e) {
-            return null;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -2874,7 +2896,7 @@
         try {
             return ActivityManagerNative.getDefault().getRunningExternalApplications();
         } catch (RemoteException e) {
-            return null;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -2891,7 +2913,7 @@
             return ActivityManagerNative.getDefault().setProcessMemoryTrimLevel(process, userId,
                     level);
         } catch (RemoteException e) {
-            return false;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -2909,7 +2931,7 @@
         try {
             return ActivityManagerNative.getDefault().getRunningAppProcesses();
         } catch (RemoteException e) {
-            return null;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -2928,7 +2950,7 @@
                     mContext.getOpPackageName());
             return RunningAppProcessInfo.procStateToImportance(procState);
         } catch (RemoteException e) {
-            return RunningAppProcessInfo.IMPORTANCE_GONE;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -2947,6 +2969,7 @@
         try {
             ActivityManagerNative.getDefault().getMyMemoryState(outState);
         } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -2965,7 +2988,7 @@
         try {
             return ActivityManagerNative.getDefault().getProcessMemoryInfo(pids);
         } catch (RemoteException e) {
-            return null;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -2999,6 +3022,7 @@
             ActivityManagerNative.getDefault().killBackgroundProcesses(packageName,
                     UserHandle.myUserId());
         } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -3015,7 +3039,7 @@
             ActivityManagerNative.getDefault().killUid(UserHandle.getAppId(uid),
                     UserHandle.getUserId(uid), reason);
         } catch (RemoteException e) {
-            Log.e(TAG, "Couldn't kill uid:" + uid, e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -3042,6 +3066,7 @@
         try {
             ActivityManagerNative.getDefault().forceStopPackage(packageName, userId);
         } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -3060,8 +3085,8 @@
         try {
             return ActivityManagerNative.getDefault().getDeviceConfigurationInfo();
         } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
         }
-        return null;
     }
 
     /**
@@ -3150,8 +3175,8 @@
         try {
             return ActivityManagerNative.getDefault().isUserAMonkey();
         } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
         }
-        return false;
     }
 
     /**
@@ -3226,10 +3251,8 @@
             return AppGlobals.getPackageManager()
                     .checkUidPermission(permission, uid);
         } catch (RemoteException e) {
-            // Should never happen, but if it does... deny!
-            Slog.e(TAG, "PackageManager is dead?!?", e);
+            throw e.rethrowFromSystemServer();
         }
-        return PackageManager.PERMISSION_DENIED;
     }
 
     /** @hide */
@@ -3238,10 +3261,8 @@
             return AppGlobals.getPackageManager()
                     .checkUidPermission(permission, uid);
         } catch (RemoteException e) {
-            // Should never happen, but if it does... deny!
-            Slog.e(TAG, "PackageManager is dead?!?", e);
+            throw e.rethrowFromSystemServer();
         }
-        return PackageManager.PERMISSION_DENIED;
     }
 
     /**
@@ -3277,7 +3298,7 @@
             return ActivityManagerNative.getDefault().handleIncomingUser(callingPid,
                     callingUid, userId, allowAll, requireFull, name, callerPackage);
         } catch (RemoteException e) {
-            throw new SecurityException("Failed calling activity manager", e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -3292,7 +3313,7 @@
             ui = ActivityManagerNative.getDefault().getCurrentUser();
             return ui != null ? ui.id : 0;
         } catch (RemoteException e) {
-            return 0;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -3304,7 +3325,7 @@
         try {
             return ActivityManagerNative.getDefault().switchUser(userid);
         } catch (RemoteException e) {
-            return false;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -3328,7 +3349,7 @@
         try {
             return ActivityManagerNative.getDefault().isUserRunning(userId, 0);
         } catch (RemoteException e) {
-            return false;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -3338,7 +3359,7 @@
             return ActivityManagerNative.getDefault().isUserRunning(userId,
                     ActivityManager.FLAG_AND_LOCKED);
         } catch (RemoteException e) {
-            return false;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -3348,7 +3369,16 @@
             return ActivityManagerNative.getDefault().isUserRunning(userId,
                     ActivityManager.FLAG_AND_UNLOCKED);
         } catch (RemoteException e) {
-            return false;
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /** {@hide} */
+    public boolean isVrModePackageEnabled(ComponentName component) {
+        try {
+            return ActivityManagerNative.getDefault().isVrModePackageEnabled(component);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -3433,6 +3463,7 @@
             ActivityManagerNative.getDefault().setDumpHeapDebugLimit(null, 0, pssSize,
                     mContext.getPackageName());
         } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -3451,6 +3482,7 @@
         try {
             ActivityManagerNative.getDefault().setDumpHeapDebugLimit(null, 0, 0, null);
         } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -3461,6 +3493,7 @@
         try {
             ActivityManagerNative.getDefault().startLockTaskMode(taskId);
         } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -3471,6 +3504,7 @@
         try {
             ActivityManagerNative.getDefault().stopLockTaskMode();
         } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -3497,7 +3531,7 @@
         try {
             return ActivityManagerNative.getDefault().getLockTaskModeState();
         } catch (RemoteException e) {
-            return ActivityManager.LOCK_TASK_MODE_NONE;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -3520,7 +3554,7 @@
             try {
                 mAppTaskImpl.finishAndRemoveTask();
             } catch (RemoteException e) {
-                Slog.e(TAG, "Invalid AppTask", e);
+                throw e.rethrowFromSystemServer();
             }
         }
 
@@ -3533,8 +3567,7 @@
             try {
                 return mAppTaskImpl.getTaskInfo();
             } catch (RemoteException e) {
-                Slog.e(TAG, "Invalid AppTask", e);
-                return null;
+                throw e.rethrowFromSystemServer();
             }
         }
 
@@ -3548,7 +3581,7 @@
             try {
                 mAppTaskImpl.moveToFront();
             } catch (RemoteException e) {
-                Slog.e(TAG, "Invalid AppTask", e);
+                throw e.rethrowFromSystemServer();
             }
         }
 
@@ -3590,7 +3623,7 @@
             try {
                 mAppTaskImpl.setExcludeFromRecents(exclude);
             } catch (RemoteException e) {
-                Slog.e(TAG, "Invalid AppTask", e);
+                throw e.rethrowFromSystemServer();
             }
         }
     }
diff --git a/core/java/android/app/ActivityManagerInternal.java b/core/java/android/app/ActivityManagerInternal.java
index 4fa654f..7310d67 100644
--- a/core/java/android/app/ActivityManagerInternal.java
+++ b/core/java/android/app/ActivityManagerInternal.java
@@ -29,6 +29,31 @@
  * @hide Only for use within the system server.
  */
 public abstract class ActivityManagerInternal {
+
+    /**
+     * Type for {@link #notifyAppTransitionStarting}: The transition was started because we had
+     * the surface saved.
+     */
+    public static final int APP_TRANSITION_SAVED_SURFACE = 0;
+
+    /**
+     * Type for {@link #notifyAppTransitionStarting}: The transition was started because we drew
+     * the starting window.
+     */
+    public static final int APP_TRANSITION_STARTING_WINDOW = 1;
+
+    /**
+     * Type for {@link #notifyAppTransitionStarting}: The transition was started because we all
+     * app windows were drawn
+     */
+    public static final int APP_TRANSITION_WINDOWS_DRAWN = 2;
+
+    /**
+     * Type for {@link #notifyAppTransitionStarting}: The transition was started because of a
+     * timeout.
+     */
+    public static final int APP_TRANSITION_TIMEOUT = 3;
+
     // Called by the power manager.
     public abstract void onWakefulnessChanged(int wakefulness);
 
@@ -48,6 +73,7 @@
      * with underlying activities.
      */
     public static abstract class SleepToken {
+
         /**
          * Releases the sleep token.
          */
@@ -56,6 +82,7 @@
 
     /**
      * Returns home activity for the specified user.
+     *
      * @param userId ID of the user or {@link android.os.UserHandle#USER_ALL}
      */
     public abstract ComponentName getHomeActivityForUser(int userId);
@@ -72,4 +99,19 @@
     public abstract void onLocalVoiceInteractionStarted(IBinder callingActivity,
             IVoiceInteractionSession mSession,
             IVoiceInteractor mInteractor);
+
+    /**
+     * Callback for window manager to let activity manager know that the starting window has been
+     * drawn
+     */
+    public abstract void notifyStartingWindowDrawn();
+
+    /**
+     * Callback for window manager to let activity manager know that we are finally starting the
+     * app transition;
+     *
+     * @param reason The reason why the app transition started. Must be one of the APP_TRANSITION_*
+     *               values.
+     */
+    public abstract void notifyAppTransitionStarting(int reason);
 }
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index bb36a3e..8b62ef9 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -792,8 +792,9 @@
             if (hasBounds) {
                 bounds = Rect.CREATOR.createFromParcel(data);
             }
-            moveTaskToDockedStack(taskId, createMode, toTop, animate, bounds);
+            boolean res = moveTaskToDockedStack(taskId, createMode, toTop, animate, bounds);
             reply.writeNoException();
+            reply.writeInt(res ? 1 : 0);
             return true;
         }
 
@@ -822,7 +823,27 @@
             reply.writeNoException();
             return true;
         }
-
+        case RESIZE_PINNED_STACK_TRANSACTION: {
+            data.enforceInterface(IActivityManager.descriptor);
+            final boolean hasBounds = data.readInt() != 0;
+            Rect bounds = null;
+            if (hasBounds) {
+                bounds = Rect.CREATOR.createFromParcel(data);
+            }
+            final boolean hasTempPinnedTaskBounds = data.readInt() != 0;
+            Rect tempPinnedTaskBounds = null;
+            if (hasTempPinnedTaskBounds) {
+                tempPinnedTaskBounds = Rect.CREATOR.createFromParcel(data);
+            }
+            resizePinnedStack(bounds, tempPinnedTaskBounds);
+            return true;
+        }
+        case SWAP_DOCKED_AND_FULLSCREEN_STACK: {
+            data.enforceInterface(IActivityManager.descriptor);
+            swapDockedAndFullscreenStack();
+            reply.writeNoException();
+            return true;
+        }
         case RESIZE_DOCKED_STACK_TRANSACTION: {
             data.enforceInterface(IActivityManager.descriptor);
             final boolean hasBounds = data.readInt() != 0;
@@ -1527,7 +1548,8 @@
             data.enforceInterface(IActivityManager.descriptor);
             IActivityController watcher = IActivityController.Stub.asInterface(
                     data.readStrongBinder());
-            setActivityController(watcher);
+            boolean imAMonkey = data.readInt() != 0;
+            setActivityController(watcher, imAMonkey);
             reply.writeNoException();
             return true;
         }
@@ -1540,6 +1562,14 @@
             return true;
         }
 
+        case GET_MEMORY_TRIM_LEVEL_TRANSACTION: {
+            data.enforceInterface(IActivityManager.descriptor);
+            int level = getMemoryTrimLevel();
+            reply.writeNoException();
+            reply.writeInt(level);
+            return true;
+        }
+
         case ENTER_SAFE_MODE_TRANSACTION: {
             data.enforceInterface(IActivityManager.descriptor);
             enterSafeMode();
@@ -2878,8 +2908,18 @@
             data.enforceInterface(IActivityManager.descriptor);
             final IBinder token = data.readStrongBinder();
             final boolean enable = data.readInt() == 1;
-            setVrMode(token, enable);
+            final ComponentName packageName = ComponentName.CREATOR.createFromParcel(data);
+            int res = setVrMode(token, enable, packageName);
             reply.writeNoException();
+            reply.writeInt(res);
+            return true;
+        }
+        case IS_VR_PACKAGE_ENABLED_TRANSACTION: {
+            data.enforceInterface(IActivityManager.descriptor);
+            final ComponentName packageName = ComponentName.CREATOR.createFromParcel(data);
+            boolean res = isVrModePackageEnabled(packageName);
+            reply.writeNoException();
+            reply.writeInt(res ? 1 : 0);
             return true;
         }
         case IS_APP_FOREGROUND_TRANSACTION: {
@@ -3800,7 +3840,7 @@
         reply.recycle();
     }
     @Override
-    public void moveTaskToDockedStack(int taskId, int createMode, boolean toTop, boolean animate,
+    public boolean moveTaskToDockedStack(int taskId, int createMode, boolean toTop, boolean animate,
             Rect initialBounds) throws RemoteException
     {
         Parcel data = Parcel.obtain();
@@ -3818,8 +3858,10 @@
         }
         mRemote.transact(MOVE_TASK_TO_DOCKED_STACK_TRANSACTION, data, reply, 0);
         reply.readException();
+        boolean res = reply.readInt() > 0;
         data.recycle();
         reply.recycle();
+        return res;
     }
     @Override
     public boolean moveTopActivityToPinnedStack(int stackId, Rect r)
@@ -3859,6 +3901,17 @@
         reply.recycle();
     }
     @Override
+    public void swapDockedAndFullscreenStack() throws RemoteException
+    {
+        Parcel data = Parcel.obtain();
+        Parcel reply = Parcel.obtain();
+        data.writeInterfaceToken(IActivityManager.descriptor);
+        mRemote.transact(SWAP_DOCKED_AND_FULLSCREEN_STACK, data, reply, 0);
+        reply.readException();
+        data.recycle();
+        reply.recycle();
+    }
+    @Override
     public void resizeDockedStack(Rect dockedBounds, Rect tempDockedTaskBounds,
             Rect tempDockedTaskInsetBounds,
             Rect tempOtherTaskBounds, Rect tempOtherTaskInsetBounds)
@@ -3902,6 +3955,31 @@
         data.recycle();
         reply.recycle();
     }
+
+    @Override
+    public void resizePinnedStack(Rect pinnedBounds, Rect tempPinnedTaskBounds) throws RemoteException
+    {
+        Parcel data = Parcel.obtain();
+        Parcel reply = Parcel.obtain();
+        data.writeInterfaceToken(IActivityManager.descriptor);
+        if (pinnedBounds != null) {
+            data.writeInt(1);
+            pinnedBounds.writeToParcel(data, 0);
+        } else {
+            data.writeInt(0);
+        }
+        if (tempPinnedTaskBounds != null) {
+            data.writeInt(1);
+            tempPinnedTaskBounds.writeToParcel(data, 0);
+        } else {
+            data.writeInt(0);
+        }
+        mRemote.transact(RESIZE_PINNED_STACK_TRANSACTION, data, reply, 0);
+        reply.readException();
+        data.recycle();
+        reply.recycle();
+    }
+
     @Override
     public void positionTaskInStack(int taskId, int stackId, int position) throws RemoteException
     {
@@ -4852,12 +4930,14 @@
         data.recycle();
         reply.recycle();
     }
-    public void setActivityController(IActivityController watcher) throws RemoteException
+    public void setActivityController(IActivityController watcher, boolean imAMonkey)
+            throws RemoteException
     {
         Parcel data = Parcel.obtain();
         Parcel reply = Parcel.obtain();
         data.writeInterfaceToken(IActivityManager.descriptor);
         data.writeStrongBinder(watcher != null ? watcher.asBinder() : null);
+        data.writeInt(imAMonkey ? 1 : 0);
         mRemote.transact(SET_ACTIVITY_CONTROLLER_TRANSACTION, data, reply, 0);
         reply.readException();
         data.recycle();
@@ -4874,6 +4954,18 @@
         data.recycle();
         reply.recycle();
     }
+    public int getMemoryTrimLevel() throws RemoteException
+    {
+        Parcel data = Parcel.obtain();
+        Parcel reply = Parcel.obtain();
+        data.writeInterfaceToken(IActivityManager.descriptor);
+        mRemote.transact(GET_MEMORY_TRIM_LEVEL_TRANSACTION, data, reply, 0);
+        reply.readException();
+        int level = reply.readInt();
+        data.recycle();
+        reply.recycle();
+        return level;
+    }
     public void enterSafeMode() throws RemoteException {
         Parcel data = Parcel.obtain();
         data.writeInterfaceToken(IActivityManager.descriptor);
@@ -6182,16 +6274,34 @@
         return res;
     }
 
-    public void setVrMode(IBinder token, boolean enabled) throws RemoteException {
+    public int setVrMode(IBinder token, boolean enabled, ComponentName packageName)
+            throws RemoteException {
         Parcel data = Parcel.obtain();
         Parcel reply = Parcel.obtain();
         data.writeInterfaceToken(IActivityManager.descriptor);
         data.writeStrongBinder(token);
         data.writeInt(enabled ? 1 : 0);
+        packageName.writeToParcel(data, 0);
         mRemote.transact(SET_VR_MODE_TRANSACTION, data, reply, 0);
         reply.readException();
+        int res = reply.readInt();
         data.recycle();
         reply.recycle();
+        return res;
+    }
+
+    public boolean isVrModePackageEnabled(ComponentName packageName)
+            throws RemoteException {
+        Parcel data = Parcel.obtain();
+        Parcel reply = Parcel.obtain();
+        data.writeInterfaceToken(IActivityManager.descriptor);
+        packageName.writeToParcel(data, 0);
+        mRemote.transact(IS_VR_PACKAGE_ENABLED_TRANSACTION, data, reply, 0);
+        reply.readException();
+        int res = reply.readInt();
+        data.recycle();
+        reply.recycle();
+        return res == 1;
     }
 
     @Override
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index e0e41f1..060ac5e 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -75,6 +75,7 @@
 import android.os.SystemClock;
 import android.os.SystemProperties;
 import android.os.Trace;
+import android.os.TransactionTooLargeException;
 import android.os.UserHandle;
 import android.provider.Settings;
 import android.security.NetworkSecurityPolicy;
@@ -112,6 +113,7 @@
 import com.android.internal.os.RuntimeInit;
 import com.android.internal.os.SamplingProfilerIntegration;
 import com.android.internal.os.SomeArgs;
+import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.FastPrintWriter;
 import com.android.org.conscrypt.OpenSSLSocketImpl;
 import com.android.org.conscrypt.TrustedCertificateStore;
@@ -174,6 +176,7 @@
     private static final int SQLITE_MEM_RELEASED_EVENT_LOG_TAG = 75003;
     private static final int LOG_AM_ON_PAUSE_CALLED = 30021;
     private static final int LOG_AM_ON_RESUME_CALLED = 30022;
+    private static final int LOG_AM_ON_STOP_CALLED = 30049;
 
     /** Type for IActivityManager.serviceDoneExecuting: anonymous operation */
     public static final int SERVICE_DONE_EXECUTING_ANON = 0;
@@ -191,7 +194,7 @@
 
     private ContextImpl mSystemContext;
 
-    static IPackageManager sPackageManager;
+    static volatile IPackageManager sPackageManager;
 
     final ApplicationThread mAppThread = new ApplicationThread();
     final Looper mLooper = Looper.myLooper();
@@ -216,7 +219,7 @@
     // set of instantiated backup agents, keyed by package name
     final ArrayMap<String, BackupAgent> mBackupAgents = new ArrayMap<String, BackupAgent>();
     /** Reference to singleton {@link ActivityThread} */
-    private static ActivityThread sCurrentActivityThread;
+    private static volatile ActivityThread sCurrentActivityThread;
     Instrumentation mInstrumentation;
     String mInstrumentationPackageName = null;
     String mInstrumentationAppDir = null;
@@ -294,7 +297,7 @@
     final GcIdler mGcIdler = new GcIdler();
     boolean mGcIdlerScheduled = false;
 
-    static Handler sMainThreadHandler;  // set once in main()
+    static volatile Handler sMainThreadHandler;  // set once in main()
 
     Bundle mCoreSettings = null;
 
@@ -977,18 +980,19 @@
 
         @Override
         public void dumpMemInfo(FileDescriptor fd, Debug.MemoryInfo mem, boolean checkin,
-                boolean dumpFullInfo, boolean dumpDalvik, boolean dumpSummaryOnly, String[] args) {
+                boolean dumpFullInfo, boolean dumpDalvik, boolean dumpSummaryOnly,
+                boolean dumpUnreachable, String[] args) {
             FileOutputStream fout = new FileOutputStream(fd);
             PrintWriter pw = new FastPrintWriter(fout);
             try {
-                dumpMemInfo(pw, mem, checkin, dumpFullInfo, dumpDalvik, dumpSummaryOnly);
+                dumpMemInfo(pw, mem, checkin, dumpFullInfo, dumpDalvik, dumpSummaryOnly, dumpUnreachable);
             } finally {
                 pw.flush();
             }
         }
 
         private void dumpMemInfo(PrintWriter pw, Debug.MemoryInfo memInfo, boolean checkin,
-                boolean dumpFullInfo, boolean dumpDalvik, boolean dumpSummaryOnly) {
+                boolean dumpFullInfo, boolean dumpDalvik, boolean dumpSummaryOnly, boolean dumpUnreachable) {
             long nativeMax = Debug.getNativeHeapSize() / 1024;
             long nativeAllocated = Debug.getNativeHeapAllocatedSize() / 1024;
             long nativeFree = Debug.getNativeHeapFreeSize() / 1024;
@@ -1102,6 +1106,16 @@
                 pw.println(" Asset Allocations");
                 pw.print(assetAlloc);
             }
+
+            // Unreachable native memory
+            if (dumpUnreachable) {
+                boolean showContents = ((mBoundApplication != null)
+                    && ((mBoundApplication.appInfo.flags&ApplicationInfo.FLAG_DEBUGGABLE) != 0))
+                    || android.os.Build.IS_DEBUGGABLE;
+                pw.println(" ");
+                pw.println(" Unreachable memory");
+                pw.print(Debug.getUnreachableMemory(100, showContents));
+            }
         }
 
         @Override
@@ -1395,7 +1409,7 @@
 
                     r.packageInfo = getPackageInfoNoCheck(
                             r.activityInfo.applicationInfo, r.compatInfo);
-                    handleLaunchActivity(r, null);
+                    handleLaunchActivity(r, null, "LAUNCH_ACTIVITY");
                     Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                 } break;
                 case RELAUNCH_ACTIVITY: {
@@ -1446,7 +1460,7 @@
                     Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityResume");
                     SomeArgs args = (SomeArgs) msg.obj;
                     handleResumeActivity((IBinder) args.arg1, true, args.argi1 != 0, true,
-                            args.argi3);
+                            args.argi3, "RESUME_ACTIVITY");
                     Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                     break;
                 case SEND_RESULT:
@@ -1693,7 +1707,7 @@
                             am.activityIdle(a.token, a.createdConfig, stopProfiling);
                             a.createdConfig = null;
                         } catch (RemoteException ex) {
-                            // Ignore
+                            throw ex.rethrowFromSystemServer();
                         }
                     }
                     prev = a;
@@ -1775,14 +1789,13 @@
     }
 
     /**
-     * Creates the top level resources for the given package.
+     * Creates the top level resources for the given package. Will return an existing
+     * Resources if one has already been created.
      */
     Resources getTopLevelResources(String resDir, String[] splitResDirs, String[] overlayDirs,
-            String[] libDirs, int displayId, Configuration overrideConfiguration,
-            LoadedApk pkgInfo) {
-        return mResourcesManager.getTopLevelResources(resDir, splitResDirs, overlayDirs, libDirs,
-                displayId, overrideConfiguration, pkgInfo.getCompatibilityInfo(),
-                pkgInfo.getClassLoader());
+            String[] libDirs, int displayId, LoadedApk pkgInfo) {
+        return mResourcesManager.getResources(null, resDir, splitResDirs, overlayDirs, libDirs,
+                displayId, null, pkgInfo.getCompatibilityInfo(), pkgInfo.getClassLoader());
     }
 
     final Handler getHandler() {
@@ -1833,7 +1846,7 @@
                             | PackageManager.MATCH_DEBUG_TRIAGED_MISSING,
                     userId);
         } catch (RemoteException e) {
-            // Ignore
+            throw e.rethrowFromSystemServer();
         }
 
         if (ai != null) {
@@ -2592,10 +2605,11 @@
         try {
             displayId = ActivityManagerNative.getDefault().getActivityDisplayId(r.token);
         } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
         }
 
         ContextImpl appContext = ContextImpl.createActivityContext(
-                this, r.packageInfo, displayId, r.overrideConfig);
+                this, r.packageInfo, r.token, displayId, r.overrideConfig);
         appContext.setOuterContext(activity);
         Context baseContext = appContext;
 
@@ -2618,7 +2632,7 @@
         return baseContext;
     }
 
-    private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent) {
+    private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent, String reason) {
         // If we are getting ready to gc after going to the background, well
         // we are back active so skip it.
         unscheduleGcIdler();
@@ -2645,7 +2659,7 @@
             reportSizeConfigurations(r);
             Bundle oldState = r.state;
             handleResumeActivity(r.token, false, r.isForward,
-                    !r.activity.mFinished && !r.startsNotResumed, r.lastProcessedSeq);
+                    !r.activity.mFinished && !r.startsNotResumed, r.lastProcessedSeq, reason);
 
             if (!r.activity.mFinished && r.startsNotResumed) {
                 // The activity manager actually wants this one to start out
@@ -2660,6 +2674,8 @@
                 try {
                     r.activity.mCalled = false;
                     mInstrumentation.callActivityOnPause(r.activity);
+                    EventLog.writeEvent(LOG_AM_ON_PAUSE_CALLED, UserHandle.myUserId(),
+                            r.activity.getComponentName().getClassName(), reason);
                     // We need to keep around the original state, in case
                     // we need to be created again.  But we only do this
                     // for pre-Honeycomb apps, which always save their state
@@ -2697,7 +2713,7 @@
                     .finishActivity(r.token, Activity.RESULT_CANCELED, null,
                             Activity.DONT_FINISH_TASK_WITH_ACTIVITY);
             } catch (RemoteException ex) {
-                // Ignore
+                throw ex.rethrowFromSystemServer();
             }
         }
     }
@@ -2726,6 +2742,7 @@
             ActivityManagerNative.getDefault().reportSizeConfigurations(r.token,
                     horizontal.copyKeys(), vertical.copyKeys(), smallest.copyKeys());
         } catch (RemoteException ex) {
+            throw ex.rethrowFromSystemServer();
         }
 
     }
@@ -2802,6 +2819,7 @@
         try {
             mgr.reportAssistContextExtras(cmd.requestToken, data, structure, content, referrer);
         } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -2838,6 +2856,7 @@
         try {
             ActivityManagerNative.getDefault().backgroundResourcesReleased(token);
         } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -2992,8 +3011,7 @@
                 return;
             }
         } catch (RemoteException e) {
-            Slog.e(TAG, "Can't reach package manager", e);
-            return;
+            throw e.rethrowFromSystemServer();
         }
 
         // no longer idle; we have backup work to do
@@ -3054,7 +3072,7 @@
             try {
                 ActivityManagerNative.getDefault().backupAgentCreated(packageName, binder);
             } catch (RemoteException e) {
-                // nothing to do.
+                throw e.rethrowFromSystemServer();
             }
         } catch (Exception e) {
             throw new RuntimeException("Unable to create BackupAgent "
@@ -3116,7 +3134,7 @@
                 ActivityManagerNative.getDefault().serviceDoneExecuting(
                         data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
             } catch (RemoteException e) {
-                // nothing to do.
+                throw e.rethrowFromSystemServer();
             }
         } catch (Exception e) {
             if (!mInstrumentation.onException(service, e)) {
@@ -3147,6 +3165,7 @@
                     }
                     ensureJitEnabled();
                 } catch (RemoteException ex) {
+                    throw ex.rethrowFromSystemServer();
                 }
             } catch (Exception e) {
                 if (!mInstrumentation.onException(s, e)) {
@@ -3174,6 +3193,7 @@
                                 data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
                     }
                 } catch (RemoteException ex) {
+                    throw ex.rethrowFromSystemServer();
                 }
             } catch (Exception e) {
                 if (!mInstrumentation.onException(s, e)) {
@@ -3255,7 +3275,7 @@
                     ActivityManagerNative.getDefault().serviceDoneExecuting(
                             data.token, SERVICE_DONE_EXECUTING_START, data.startId, res);
                 } catch (RemoteException e) {
-                    // nothing to do.
+                    throw e.rethrowFromSystemServer();
                 }
                 ensureJitEnabled();
             } catch (Exception e) {
@@ -3286,9 +3306,7 @@
                     ActivityManagerNative.getDefault().serviceDoneExecuting(
                             token, SERVICE_DONE_EXECUTING_STOP, 0, 0);
                 } catch (RemoteException e) {
-                    // nothing to do.
-                    Slog.i(TAG, "handleStopService: unable to execute serviceDoneExecuting for "
-                            + token, e);
+                    throw e.rethrowFromSystemServer();
                 }
             } catch (Exception e) {
                 if (!mInstrumentation.onException(s, e)) {
@@ -3305,7 +3323,7 @@
     }
 
     public final ActivityClientRecord performResumeActivity(IBinder token,
-            boolean clearHide) {
+            boolean clearHide, String reason) {
         ActivityClientRecord r = mActivities.get(token);
         if (localLOGV) Slog.v(TAG, "Performing resume of " + r
                 + " finished=" + r.activity.mFinished);
@@ -3327,8 +3345,20 @@
                 }
                 r.activity.performResume();
 
-                EventLog.writeEvent(LOG_AM_ON_RESUME_CALLED,
-                        UserHandle.myUserId(), r.activity.getComponentName().getClassName());
+                // If there is a pending local relaunch that was requested when the activity was
+                // paused, it will put the activity into paused state when it finally happens.
+                // Since the activity resumed before being relaunched, we don't want that to happen,
+                // so we need to clear the request to relaunch paused.
+                for (int i = mRelaunchingActivities.size() - 1; i >= 0; i--) {
+                    final ActivityClientRecord relaunching = mRelaunchingActivities.get(i);
+                    if (relaunching.token == r.token
+                            && relaunching.onlyLocalRequest && relaunching.startsNotResumed) {
+                        relaunching.startsNotResumed = false;
+                    }
+                }
+
+                EventLog.writeEvent(LOG_AM_ON_RESUME_CALLED, UserHandle.myUserId(),
+                        r.activity.getComponentName().getClassName(), reason);
 
                 r.paused = false;
                 r.stopped = false;
@@ -3364,7 +3394,7 @@
     }
 
     final void handleResumeActivity(IBinder token,
-            boolean clearHide, boolean isForward, boolean reallyResume, int seq) {
+            boolean clearHide, boolean isForward, boolean reallyResume, int seq, String reason) {
         ActivityClientRecord r = mActivities.get(token);
         if (!checkAndUpdateLifecycleSeq(seq, r, "resumeActivity")) {
             return;
@@ -3376,7 +3406,7 @@
         mSomeActivitiesChanged = true;
 
         // TODO Push resumeArgs into the activity for consideration
-        r = performResumeActivity(token, clearHide);
+        r = performResumeActivity(token, clearHide, reason);
 
         if (r != null) {
             final Activity a = r.activity;
@@ -3398,6 +3428,7 @@
                     willBeVisible = ActivityManagerNative.getDefault().willActivityBeVisible(
                             a.getActivityToken());
                 } catch (RemoteException e) {
+                    throw e.rethrowFromSystemServer();
                 }
             }
             if (r.window == null && !a.mFinished && willBeVisible) {
@@ -3435,14 +3466,9 @@
             if (!r.activity.mFinished && willBeVisible
                     && r.activity.mDecor != null && !r.hideForNow) {
                 if (r.newConfig != null) {
-                    r.tmpConfig.setTo(r.newConfig);
-                    if (r.overrideConfig != null) {
-                        r.tmpConfig.updateFrom(r.overrideConfig);
-                    }
+                    performConfigurationChangedForActivity(r, r.newConfig, REPORT_TO_ACTIVITY);
                     if (DEBUG_CONFIGURATION) Slog.v(TAG, "Resuming activity "
-                            + r.activityInfo.name + " with newConfig " + r.tmpConfig);
-                    performConfigurationChanged(r.activity, r.tmpConfig, REPORT_TO_ACTIVITY);
-                    freeTextLayoutCachesIfNeeded(r.activity.mCurrentConfig.diff(r.tmpConfig));
+                            + r.activityInfo.name + " with newConfig " + r.activity.mCurrentConfig);
                     r.newConfig = null;
                 }
                 if (localLOGV) Slog.v(TAG, "Resuming " + r + " with isForward="
@@ -3481,6 +3507,7 @@
                 try {
                     ActivityManagerNative.getDefault().activityResumed(token);
                 } catch (RemoteException ex) {
+                    throw ex.rethrowFromSystemServer();
                 }
             }
 
@@ -3492,6 +3519,7 @@
                     .finishActivity(token, Activity.RESULT_CANCELED, null,
                             Activity.DONT_FINISH_TASK_WITH_ACTIVITY);
             } catch (RemoteException ex) {
+                throw ex.rethrowFromSystemServer();
             }
         }
     }
@@ -3555,6 +3583,7 @@
     private void handlePauseActivity(IBinder token, boolean finished,
             boolean userLeaving, int configChanges, boolean dontReport, int seq) {
         ActivityClientRecord r = mActivities.get(token);
+        if (DEBUG_ORDER) Slog.d(TAG, "handlePauseActivity " + r + ", seq: " + seq);
         if (!checkAndUpdateLifecycleSeq(seq, r, "pauseActivity")) {
             return;
         }
@@ -3565,7 +3594,7 @@
             }
 
             r.activity.mConfigChangeFlags |= configChanges;
-            performPauseActivity(token, finished, r.isPreHoneycomb());
+            performPauseActivity(token, finished, r.isPreHoneycomb(), "handlePauseActivity");
 
             // Make sure any pending writes are now committed.
             if (r.isPreHoneycomb()) {
@@ -3577,6 +3606,7 @@
                 try {
                     ActivityManagerNative.getDefault().activityPaused(token);
                 } catch (RemoteException ex) {
+                    throw ex.rethrowFromSystemServer();
                 }
             }
             mSomeActivitiesChanged = true;
@@ -3588,13 +3618,13 @@
     }
 
     final Bundle performPauseActivity(IBinder token, boolean finished,
-            boolean saveState) {
+            boolean saveState, String reason) {
         ActivityClientRecord r = mActivities.get(token);
-        return r != null ? performPauseActivity(r, finished, saveState) : null;
+        return r != null ? performPauseActivity(r, finished, saveState, reason) : null;
     }
 
     final Bundle performPauseActivity(ActivityClientRecord r, boolean finished,
-            boolean saveState) {
+            boolean saveState, String reason) {
         if (r.paused) {
             if (r.activity.mFinished) {
                 // If we are finishing, we won't call onResume() in certain cases.
@@ -3619,7 +3649,7 @@
             r.activity.mCalled = false;
             mInstrumentation.callActivityOnPause(r.activity);
             EventLog.writeEvent(LOG_AM_ON_PAUSE_CALLED, UserHandle.myUserId(),
-                    r.activity.getComponentName().getClassName());
+                    r.activity.getComponentName().getClassName(), reason);
             if (!r.activity.mCalled) {
                 throw new SuperNotCalledException(
                     "Activity " + r.intent.getComponent().toShortString() +
@@ -3652,9 +3682,9 @@
         return !r.activity.mFinished && saveState ? r.state : null;
     }
 
-    final void performStopActivity(IBinder token, boolean saveState) {
+    final void performStopActivity(IBinder token, boolean saveState, String reason) {
         ActivityClientRecord r = mActivities.get(token);
-        performStopActivityInner(r, null, false, saveState);
+        performStopActivityInner(r, null, false, saveState, reason);
     }
 
     private static class StopInfo implements Runnable {
@@ -3670,6 +3700,12 @@
                 ActivityManagerNative.getDefault().activityStopped(
                     activity.token, state, persistentState, description);
             } catch (RemoteException ex) {
+                if (ex instanceof TransactionTooLargeException
+                        && activity.packageInfo.getTargetSdkVersion() < Build.VERSION_CODES.N) {
+                    Log.e(TAG, "App sent too much data in instance state, so it was ignored", ex);
+                    return;
+                }
+                throw ex.rethrowFromSystemServer();
             }
         }
     }
@@ -3705,7 +3741,7 @@
      * the activity's UI visibillity changes.
      */
     private void performStopActivityInner(ActivityClientRecord r,
-            StopInfo info, boolean keepShown, boolean saveState) {
+            StopInfo info, boolean keepShown, boolean saveState, String reason) {
         if (localLOGV) Slog.v(TAG, "Performing stop of " + r);
         if (r != null) {
             if (!keepShown && r.stopped) {
@@ -3747,7 +3783,7 @@
             if (!keepShown) {
                 try {
                     // Now we are idle.
-                    r.activity.performStop();
+                    r.activity.performStop(false /*preserveWindow*/);
                 } catch (Exception e) {
                     if (!mInstrumentation.onException(r.activity, e)) {
                         throw new RuntimeException(
@@ -3757,6 +3793,8 @@
                     }
                 }
                 r.stopped = true;
+                EventLog.writeEvent(LOG_AM_ON_STOP_CALLED, UserHandle.myUserId(),
+                        r.activity.getComponentName().getClassName(), reason);
             }
 
             r.paused = true;
@@ -3775,14 +3813,10 @@
                     }
                 }
                 if (r.newConfig != null) {
-                    r.tmpConfig.setTo(r.newConfig);
-                    if (r.overrideConfig != null) {
-                        r.tmpConfig.updateFrom(r.overrideConfig);
-                    }
+                    performConfigurationChangedForActivity(r, r.newConfig, REPORT_TO_ACTIVITY);
                     if (DEBUG_CONFIGURATION) Slog.v(TAG, "Updating activity vis "
-                            + r.activityInfo.name + " with new config " + r.tmpConfig);
-                    performConfigurationChanged(r.activity, r.tmpConfig, REPORT_TO_ACTIVITY);
-                    freeTextLayoutCachesIfNeeded(r.activity.mCurrentConfig.diff(r.tmpConfig));
+                            + r.activityInfo.name + " with new config "
+                            + r.activity.mCurrentConfig);
                     r.newConfig = null;
                 }
             } else {
@@ -3803,7 +3837,7 @@
         r.activity.mConfigChangeFlags |= configChanges;
 
         StopInfo info = new StopInfo();
-        performStopActivityInner(r, info, show, true);
+        performStopActivityInner(r, info, show, true, "handleStopActivity");
 
         if (localLOGV) Slog.v(
             TAG, "Finishing stop of " + r + ": show=" + show
@@ -3859,7 +3893,7 @@
         }
 
         if (!show && !r.stopped) {
-            performStopActivityInner(r, null, show, false);
+            performStopActivityInner(r, null, show, false, "handleWindowVisibility");
         } else if (show && r.stopped) {
             // If we are getting ready to gc after going to the background, well
             // we are back active so skip it.
@@ -3888,7 +3922,7 @@
             if (!r.stopped && !r.isPreHoneycomb()) {
                 try {
                     // Now we are idle.
-                    r.activity.performStop();
+                    r.activity.performStop(false /*preserveWindow*/);
                 } catch (Exception e) {
                     if (!mInstrumentation.onException(r.activity, e)) {
                         throw new RuntimeException(
@@ -3898,6 +3932,8 @@
                     }
                 }
                 r.stopped = true;
+                EventLog.writeEvent(LOG_AM_ON_STOP_CALLED, UserHandle.myUserId(),
+                        r.activity.getComponentName().getClassName(), "sleeping");
             }
 
             // Make sure any pending writes are now committed.
@@ -3909,6 +3945,7 @@
             try {
                 ActivityManagerNative.getDefault().activitySlept(r.token);
             } catch (RemoteException ex) {
+                throw ex.rethrowFromSystemServer();
             }
         } else {
             if (r.stopped && r.activity.mVisibleFromServer) {
@@ -4038,7 +4075,7 @@
                     r.activity.mCalled = false;
                     mInstrumentation.callActivityOnPause(r.activity);
                     EventLog.writeEvent(LOG_AM_ON_PAUSE_CALLED, UserHandle.myUserId(),
-                            r.activity.getComponentName().getClassName());
+                            r.activity.getComponentName().getClassName(), "destroy");
                     if (!r.activity.mCalled) {
                         throw new SuperNotCalledException(
                             "Activity " + safeToComponentShortString(r.intent)
@@ -4058,7 +4095,7 @@
             }
             if (!r.stopped) {
                 try {
-                    r.activity.performStop();
+                    r.activity.performStop(r.mPreserveWindow);
                 } catch (SuperNotCalledException e) {
                     throw e;
                 } catch (Exception e) {
@@ -4070,6 +4107,8 @@
                     }
                 }
                 r.stopped = true;
+                EventLog.writeEvent(LOG_AM_ON_STOP_CALLED, UserHandle.myUserId(),
+                        r.activity.getComponentName().getClassName(), "destroy");
             }
             if (getNonConfigInstance) {
                 try {
@@ -4175,7 +4214,7 @@
             try {
                 ActivityManagerNative.getDefault().activityDestroyed(token);
             } catch (RemoteException ex) {
-                // If the system process has died, it's game over for everyone.
+                throw ex.rethrowFromSystemServer();
             }
         }
         mSomeActivitiesChanged = true;
@@ -4194,6 +4233,7 @@
         synchronized (mResourcesManager) {
             for (int i=0; i<mRelaunchingActivities.size(); i++) {
                 ActivityClientRecord r = mRelaunchingActivities.get(i);
+                if (DEBUG_ORDER) Slog.d(TAG, "requestRelaunchActivity: " + this + ", trying: " + r);
                 if (r.token == token) {
                     target = r;
                     if (pendingResults != null) {
@@ -4216,7 +4256,7 @@
                         try {
                             ActivityManagerNative.getDefault().activityRelaunched(token);
                         } catch (RemoteException e) {
-                            e.printStackTrace();
+                            throw e.rethrowFromSystemServer();
                         }
                     }
                     break;
@@ -4224,14 +4264,19 @@
             }
 
             if (target == null) {
+                if (DEBUG_ORDER) Slog.d(TAG, "requestRelaunchActivity: target is null, fromServer:"
+                        + fromServer);
                 target = new ActivityClientRecord();
                 target.token = token;
                 target.pendingResults = pendingResults;
                 target.pendingIntents = pendingNewIntents;
                 target.mPreserveWindow = preserveWindow;
                 if (!fromServer) {
-                    ActivityClientRecord existing = mActivities.get(token);
+                    final ActivityClientRecord existing = mActivities.get(token);
+                    if (DEBUG_ORDER) Slog.d(TAG, "requestRelaunchActivity: " + existing);
                     if (existing != null) {
+                        if (DEBUG_ORDER) Slog.d(TAG, "requestRelaunchActivity: paused= "
+                                + existing.paused);;
                         target.startsNotResumed = existing.paused;
                         target.overrideConfig = existing.overrideConfig;
                     }
@@ -4254,8 +4299,8 @@
             target.pendingConfigChanges |= configChanges;
             target.relaunchSeq = getLifecycleSeq();
         }
-        if (DEBUG_ORDER) Slog.d(TAG, "relaunchActivity " + ActivityThread.this
-                + " operation received seq: " + target.relaunchSeq);
+        if (DEBUG_ORDER) Slog.d(TAG, "relaunchActivity " + ActivityThread.this + ", target "
+                + target + " operation received seq: " + target.relaunchSeq);
     }
 
     private void handleRelaunchActivity(ActivityClientRecord tmp) {
@@ -4337,7 +4382,7 @@
                 try {
                     ActivityManagerNative.getDefault().activityRelaunched(tmp.token);
                 } catch (RemoteException e) {
-                    // If the system process has died, it's game over for everyone.
+                    throw e.rethrowFromSystemServer();
                 }
             }
             return;
@@ -4363,13 +4408,13 @@
                 WindowManagerGlobal.getWindowSession().prepareToReplaceChildren(r.token);
             }
         } catch (RemoteException e) {
-            // If the system process has died, it's game over for everyone.
+            throw e.rethrowFromSystemServer();
         }
 
 
         // Need to ensure state is saved.
         if (!r.paused) {
-            performPauseActivity(r.token, false, r.isPreHoneycomb());
+            performPauseActivity(r.token, false, r.isPreHoneycomb(), "handleRelaunchActivity");
         }
         if (r.state == null && !r.stopped && !r.isPreHoneycomb()) {
             callCallActivityOnSaveInstanceState(r);
@@ -4399,7 +4444,7 @@
         r.startsNotResumed = tmp.startsNotResumed;
         r.overrideConfig = tmp.overrideConfig;
 
-        handleLaunchActivity(r, currentIntent);
+        handleLaunchActivity(r, currentIntent, "handleRelaunchActivity");
 
         if (!tmp.onlyLocalRequest) {
             try {
@@ -4408,7 +4453,7 @@
                     r.window.reportActivityRelaunched();
                 }
             } catch (RemoteException e) {
-                // If the system process has died, it's game over for everyone.
+                throw e.rethrowFromSystemServer();
             }
         }
     }
@@ -4476,8 +4521,44 @@
         return callbacks;
     }
 
-    private static void performConfigurationChanged(ComponentCallbacks2 cb, Configuration config,
-            boolean reportToActivity) {
+    /**
+     * Updates the configuration for an Activity. The ActivityClientRecord's
+     * {@link ActivityClientRecord#overrideConfig} is used to compute the final Configuration for
+     * that Activity. {@link ActivityClientRecord#tmpConfig} is used as a temporary for delivering
+     * the updated Configuration.
+     * @param r ActivityClientRecord representing the Activity.
+     * @param newBaseConfig The new configuration to use. This may be augmented with
+     *                      {@link ActivityClientRecord#overrideConfig}.
+     * @param reportToActivity true if the change should be reported to the Activity's callback.
+     */
+    private void performConfigurationChangedForActivity(ActivityClientRecord r,
+                                                        Configuration newBaseConfig,
+                                                        boolean reportToActivity) {
+        r.tmpConfig.setTo(newBaseConfig);
+        if (r.overrideConfig != null) {
+            r.tmpConfig.updateFrom(r.overrideConfig);
+        }
+        performConfigurationChanged(r.activity, r.token, r.tmpConfig, r.overrideConfig,
+                reportToActivity);
+        freeTextLayoutCachesIfNeeded(r.activity.mCurrentConfig.diff(r.tmpConfig));
+    }
+
+    /**
+     * Decides whether to update an Activity's configuration and whether to tell the
+     * Activity/Component about it.
+     * @param cb The component callback to notify of configuration change.
+     * @param activityToken The Activity binder token for which this configuration change happened.
+     *                      If the change is global, this is null.
+     * @param newConfig The new configuration.
+     * @param overrideConfig The override config that differentiates the Activity's configuration
+     *                       from the base global configuration.
+     * @param reportToActivity Notify the Activity of the change.
+     */
+    private void performConfigurationChanged(ComponentCallbacks2 cb,
+                                             IBinder activityToken,
+                                             Configuration newConfig,
+                                             Configuration overrideConfig,
+                                             boolean reportToActivity) {
         // Only for Activity objects, check that they actually call up to their
         // superclass implementation.  ComponentCallbacks2 is an interface, so
         // we check the runtime type and act accordingly.
@@ -4494,7 +4575,7 @@
             // If the new config is the same as the config this Activity
             // is already running with then don't bother calling
             // onConfigurationChanged
-            int diff = activity.mCurrentConfig.diff(config);
+            int diff = activity.mCurrentConfig.diff(newConfig);
             if (diff != 0) {
                 // If this activity doesn't handle any of the config changes then don't bother
                 // calling onConfigurationChanged as we're going to destroy it.
@@ -4509,21 +4590,31 @@
             }
         }
 
-        if (DEBUG_CONFIGURATION) Slog.v(TAG, "Config callback " + cb
-                + ": shouldChangeConfig=" + shouldChangeConfig);
+        if (DEBUG_CONFIGURATION) {
+            Slog.v(TAG, "Config callback " + cb + ": shouldChangeConfig=" + shouldChangeConfig);
+        }
+
         if (shouldChangeConfig) {
+            if (activityToken != null) {
+                // We only update an Activity's configuration if this is not a global
+                // configuration change. This must also be done before the callback,
+                // or else we violate the contract that the new resources are available
+                // in {@link ComponentCallbacks2#onConfigurationChanged(Configuration)}.
+                mResourcesManager.updateResourcesForActivity(activityToken, overrideConfig);
+            }
+
             if (reportToActivity) {
-                cb.onConfigurationChanged(config);
+                cb.onConfigurationChanged(newConfig);
             }
 
             if (activity != null) {
                 if (reportToActivity && !activity.mCalled) {
                     throw new SuperNotCalledException(
                             "Activity " + activity.getLocalClassName() +
-                        " did not call through to super.onConfigurationChanged()");
+                            " did not call through to super.onConfigurationChanged()");
                 }
                 activity.mConfigChangeFlags = 0;
-                activity.mCurrentConfig = new Configuration(config);
+                activity.mCurrentConfig = new Configuration(newConfig);
             }
         }
     }
@@ -4540,7 +4631,8 @@
             mCompatConfiguration = new Configuration();
         }
         mCompatConfiguration.setTo(mConfiguration);
-        if (mResourcesManager.applyCompatConfiguration(displayDensity, mCompatConfiguration)) {
+        if (mResourcesManager.applyCompatConfigurationLocked(displayDensity,
+                mCompatConfiguration)) {
             config = mCompatConfiguration;
         }
         return config;
@@ -4592,7 +4684,8 @@
         if (callbacks != null) {
             final int N = callbacks.size();
             for (int i=0; i<N; i++) {
-                performConfigurationChanged(callbacks.get(i), config, REPORT_TO_ACTIVITY);
+                performConfigurationChanged(callbacks.get(i), null, config, null,
+                        REPORT_TO_ACTIVITY);
             }
         }
     }
@@ -4618,15 +4711,8 @@
         if (DEBUG_CONFIGURATION) Slog.v(TAG, "Handle activity config changed: "
                 + r.activityInfo.name + ", with callback=" + reportToActivity);
 
-        r.tmpConfig.setTo(mCompatConfiguration);
-        if (data.overrideConfig != null) {
-            r.overrideConfig = data.overrideConfig;
-            r.tmpConfig.updateFrom(data.overrideConfig);
-        }
-        performConfigurationChanged(r.activity, r.tmpConfig, reportToActivity);
-
-        freeTextLayoutCachesIfNeeded(r.activity.mCurrentConfig.diff(mCompatConfiguration));
-
+        r.overrideConfig = data.overrideConfig;
+        performConfigurationChangedForActivity(r, mCompatConfiguration, reportToActivity);
         mSomeActivitiesChanged = true;
     }
 
@@ -4688,34 +4774,93 @@
         try {
             ActivityManagerNative.getDefault().dumpHeapFinished(dhd.path);
         } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
         }
     }
 
     final void handleDispatchPackageBroadcast(int cmd, String[] packages) {
         boolean hasPkgInfo = false;
-        if (packages != null) {
-            synchronized (mResourcesManager) {
-                for (int i=packages.length-1; i>=0; i--) {
-                    //Slog.i(TAG, "Cleaning old package: " + packages[i]);
-                    if (!hasPkgInfo) {
-                        WeakReference<LoadedApk> ref;
-                        ref = mPackages.get(packages[i]);
-                        if (ref != null && ref.get() != null) {
+        switch (cmd) {
+            case IApplicationThread.PACKAGE_REMOVED:
+            case IApplicationThread.PACKAGE_REMOVED_DONT_KILL:
+            {
+                final boolean killApp = cmd == IApplicationThread.PACKAGE_REMOVED;
+                if (packages == null) {
+                    break;
+                }
+                synchronized (mResourcesManager) {
+                    for (int i = packages.length - 1; i >= 0; i--) {
+                        if (!hasPkgInfo) {
+                            WeakReference<LoadedApk> ref = mPackages.get(packages[i]);
+                            if (ref != null && ref.get() != null) {
+                                hasPkgInfo = true;
+                            } else {
+                                ref = mResourcePackages.get(packages[i]);
+                                if (ref != null && ref.get() != null) {
+                                    hasPkgInfo = true;
+                                }
+                            }
+                        }
+                        if (killApp) {
+                            mPackages.remove(packages[i]);
+                            mResourcePackages.remove(packages[i]);
+                        }
+                    }
+                }
+                break;
+            }
+            case IApplicationThread.PACKAGE_REPLACED:
+            {
+                if (packages == null) {
+                    break;
+                }
+                synchronized (mResourcesManager) {
+                    for (int i = packages.length - 1; i >= 0; i--) {
+                        WeakReference<LoadedApk> ref = mPackages.get(packages[i]);
+                        LoadedApk pkgInfo = ref != null ? ref.get() : null;
+                        if (pkgInfo != null) {
                             hasPkgInfo = true;
                         } else {
                             ref = mResourcePackages.get(packages[i]);
-                            if (ref != null && ref.get() != null) {
+                            pkgInfo = ref != null ? ref.get() : null;
+                            if (pkgInfo != null) {
                                 hasPkgInfo = true;
                             }
                         }
+                        // If the package is being replaced, yet it still has a valid
+                        // LoadedApk object, the package was updated with _DONT_KILL.
+                        // Adjust it's internal references to the application info and
+                        // resources.
+                        if (pkgInfo != null) {
+                            try {
+                                final String packageName = packages[i];
+                                final ApplicationInfo aInfo =
+                                        sPackageManager.getApplicationInfo(
+                                                packageName,
+                                                0 /*flags*/,
+                                                UserHandle.myUserId());
+
+                                if (mActivities.size() > 0) {
+                                    for (ActivityClientRecord ar : mActivities.values()) {
+                                        if (ar.activityInfo.applicationInfo.packageName
+                                                .equals(packageName)) {
+                                            ar.activityInfo.applicationInfo = aInfo;
+                                            ar.packageInfo = pkgInfo;
+                                        }
+                                    }
+                                }
+                                final List<String> oldPaths =
+                                        sPackageManager.getPreviousCodePaths(packageName);
+                                pkgInfo.updateApplicationInfo(aInfo, oldPaths);
+                            } catch (RemoteException e) {
+                            }
+                        }
                     }
-                    mPackages.remove(packages[i]);
-                    mResourcePackages.remove(packages[i]);
                 }
+                break;
             }
         }
-        ApplicationPackageManager.handlePackageBroadcast(cmd, packages,
-                hasPkgInfo);
+        ApplicationPackageManager.handlePackageBroadcast(cmd, packages, hasPkgInfo);
     }
 
     final void handleLowMemory() {
@@ -4770,14 +4915,15 @@
                 RenderScriptCacheDir.setupDiskCache(cacheDir);
             }
         } catch (RemoteException e) {
-            // Ignore
+            throw e.rethrowFromSystemServer();
         }
     }
 
     // Keep in sync with installd (frameworks/native/cmds/installd/commands.cpp).
     private static File getPrimaryProfileFile(String packageName) {
-         return new File("/data/misc/profiles/cur/" + UserHandle.myUserId() +
-              "/" + packageName + "/primary.prof");
+        File profileDir = Environment.getDataProfilesDePackageDirectory(
+                UserHandle.myUserId(), packageName);
+        return new File(profileDir, "primary.prof");
     }
 
     private static void setupJitProfileSupport(LoadedApk loadedApk, File cacheDir) {
@@ -4808,11 +4954,15 @@
                 Os.fchmod(fd, permissions);
                 Os.fchown(fd, appInfo.uid, appInfo.uid);
             } catch (ErrnoException e) {
-                Log.v(TAG, "Unable to create jit profile file " + profileFile, e);
+                Log.v(TAG, "Unable to create jit profile file "
+                        + profileFile + ": " + e.getMessage());
                 try {
                     Os.unlink(profileFile.getAbsolutePath());
                 } catch (ErrnoException unlinkErr) {
-                    Log.v(TAG, "Unable to unlink jit profile file " + profileFile, unlinkErr);
+                    if (unlinkErr.errno != OsConstants.ENOENT) {
+                        Log.v(TAG, "Unable to unlink jit profile file "
+                                + profileFile + ": " + unlinkErr.getMessage());
+                    }
                 }
                 return;
             } finally {
@@ -4820,8 +4970,17 @@
             }
         }
 
+        final File foreignDexProfilesFile =
+                Environment.getDataProfilesDeForeignDexDirectory(UserHandle.myUserId());
+        String foreignDexProfilesPath = null;
+        if (!foreignDexProfilesFile.exists()) {
+            Log.v(TAG, "ForeignDexProfilesPath does not exists:" +
+                    foreignDexProfilesFile.getPath());
+        } else {
+            foreignDexProfilesPath = foreignDexProfilesFile.getAbsolutePath();
+        }
         VMRuntime.registerAppInfo(profileFile.getAbsolutePath(), appInfo.dataDir,
-                codePaths.toArray(new String[codePaths.size()]));
+                codePaths.toArray(new String[codePaths.size()]), foreignDexProfilesPath);
     }
 
     private void updateDefaultDensity() {
@@ -4839,6 +4998,9 @@
             DdmVmInternal.enableRecentAllocations(true);
         }
 
+        // Note when this process has started.
+        Process.setStartTimes(SystemClock.elapsedRealtime(), SystemClock.uptimeMillis());
+
         mBoundApplication = data;
         mConfiguration = new Configuration(data.config);
         mCompatConfiguration = new Configuration(data.config);
@@ -4887,21 +5049,25 @@
          */
         TimeZone.setDefault(null);
 
-        /*
-         * Initialize the default locales in this process for the reasons we set the time zone.
-         *
-         * We do this through ResourcesManager, since we need to do locale negotiation.
-         */
-        mResourcesManager.setDefaultLocalesLocked(data.config.getLocales());
+        synchronized (mResourcesManager) {
+            /*
+             * Initialize the default locales in this process for the reasons we set the time zone.
+             *
+             * We do this through ResourcesManager, since we need to do locale negotiation.
+             */
+            mResourcesManager.setDefaultLocalesLocked(data.config.getLocales());
 
-        /*
-         * Update the system configuration since its preloaded and might not
-         * reflect configuration changes. The configuration object passed
-         * in AppBindData can be safely assumed to be up to date
-         */
-        mResourcesManager.applyConfigurationToResourcesLocked(data.config, data.compatInfo);
-        mCurDefaultDisplayDpi = data.config.densityDpi;
-        applyCompatConfiguration(mCurDefaultDisplayDpi);
+            /*
+             * Update the system configuration since its preloaded and might not
+             * reflect configuration changes. The configuration object passed
+             * in AppBindData can be safely assumed to be up to date
+             */
+            mResourcesManager.applyConfigurationToResourcesLocked(data.config, data.compatInfo);
+            mCurDefaultDisplayDpi = data.config.densityDpi;
+
+            // This calls mResourcesManager so keep it within the synchronized block.
+            applyCompatConfiguration(mCurDefaultDisplayDpi);
+        }
 
         data.info = getPackageInfoNoCheck(data.appInfo, data.compatInfo);
 
@@ -4962,6 +5128,7 @@
                 try {
                     mgr.showWaitingForDebugger(mAppThread, true);
                 } catch (RemoteException ex) {
+                    throw ex.rethrowFromSystemServer();
                 }
 
                 Debug.waitForDebugger();
@@ -4969,6 +5136,7 @@
                 try {
                     mgr.showWaitingForDebugger(mAppThread, false);
                 } catch (RemoteException ex) {
+                    throw ex.rethrowFromSystemServer();
                 }
 
             } else {
@@ -4996,7 +5164,9 @@
             try {
                 final ProxyInfo proxyInfo = service.getProxyForNetwork(null);
                 Proxy.setHttpProxySystemProperty(proxyInfo);
-            } catch (RemoteException e) {}
+            } catch (RemoteException e) {
+                throw e.rethrowFromSystemServer();
+            }
         }
 
         // Instrumentation info affects the class loader, so load it before
@@ -5115,9 +5285,8 @@
             // don't bring up providers in restricted mode; they may depend on the
             // app's custom Application class
             if (!data.restrictedBackupMode) {
-                List<ProviderInfo> providers = data.providers;
-                if (providers != null) {
-                    installContentProviders(app, providers);
+                if (!ArrayUtils.isEmpty(data.providers)) {
+                    installContentProviders(app, data.providers);
                     // For process that contains content providers, we want to
                     // ensure that the JIT is enabled "at some point".
                     mH.sendEmptyMessageDelayed(H.ENABLE_JIT, 10*1000);
@@ -5160,6 +5329,7 @@
         try {
             am.finishInstrumentation(mAppThread, resultCode, results);
         } catch (RemoteException ex) {
+            throw ex.rethrowFromSystemServer();
         }
     }
 
@@ -5189,6 +5359,7 @@
             ActivityManagerNative.getDefault().publishContentProviders(
                 getApplicationThread(), results);
         } catch (RemoteException ex) {
+            throw ex.rethrowFromSystemServer();
         }
     }
 
@@ -5210,6 +5381,7 @@
             holder = ActivityManagerNative.getDefault().getContentProvider(
                     getApplicationThread(), auth, userId, stable);
         } catch (RemoteException ex) {
+            throw ex.rethrowFromSystemServer();
         }
         if (holder == null) {
             Slog.e(TAG, "Failed to find provider info for " + auth);
@@ -5497,6 +5669,7 @@
                     ActivityManagerNative.getDefault()
                             .appNotRespondingViaProvider(prc.holder.connection);
                 } catch (RemoteException e) {
+                    throw e.rethrowFromSystemServer();
                 }
             }
         }
@@ -5676,7 +5849,7 @@
             try {
                 mgr.attachApplication(mAppThread);
             } catch (RemoteException ex) {
-                // Ignore
+                throw ex.rethrowFromSystemServer();
             }
             // Watch for getting close to heap limit.
             BinderInternal.addGcWatcher(new Runnable() {
@@ -5695,6 +5868,7 @@
                         try {
                             mgr.releaseSomeActivities(mAppThread);
                         } catch (RemoteException e) {
+                            throw e.rethrowFromSystemServer();
                         }
                     }
                 }
diff --git a/core/java/android/app/AlarmManager.java b/core/java/android/app/AlarmManager.java
index b569416..b08142a 100644
--- a/core/java/android/app/AlarmManager.java
+++ b/core/java/android/app/AlarmManager.java
@@ -201,6 +201,7 @@
             try {
                 mService.remove(null, this);
             } catch (RemoteException ex) {
+                throw ex.rethrowFromSystemServer();
             }
 
             synchronized (AlarmManager.class) {
@@ -656,6 +657,7 @@
             mService.set(mPackageName, type, triggerAtMillis, windowMillis, intervalMillis, flags,
                     operation, recipientWrapper, listenerTag, workSource, alarmClock);
         } catch (RemoteException ex) {
+            throw ex.rethrowFromSystemServer();
         }
     }
 
@@ -886,6 +888,7 @@
         try {
             mService.remove(operation, null);
         } catch (RemoteException ex) {
+            throw ex.rethrowFromSystemServer();
         }
     }
 
@@ -926,6 +929,7 @@
         try {
             mService.setTime(millis);
         } catch (RemoteException ex) {
+            throw ex.rethrowFromSystemServer();
         }
     }
 
@@ -965,6 +969,7 @@
         try {
             mService.setTimeZone(timeZone);
         } catch (RemoteException ex) {
+            throw ex.rethrowFromSystemServer();
         }
     }
 
@@ -973,18 +978,23 @@
         try {
             return mService.getNextWakeFromIdleTime();
         } catch (RemoteException ex) {
-            return Long.MAX_VALUE;
+            throw ex.rethrowFromSystemServer();
         }
     }
 
     /**
      * Gets information about the next alarm clock currently scheduled.
      *
-     * The alarm clocks considered are those scheduled by {@link #setAlarmClock}
-     * from any package of the calling user.
+     * The alarm clocks considered are those scheduled by any application
+     * using the {@link #setAlarmClock} method.
+     *
+     * @return An {@link AlarmClockInfo} object describing the next upcoming alarm
+     *   clock event that will occur.  If there are no alarm clock events currently
+     *   scheduled, this method will return {@code null}.
      *
      * @see #setAlarmClock
      * @see AlarmClockInfo
+     * @see #ACTION_NEXT_ALARM_CLOCK_CHANGED
      */
     public AlarmClockInfo getNextAlarmClock() {
         return getNextAlarmClock(UserHandle.myUserId());
@@ -993,11 +1003,16 @@
     /**
      * Gets information about the next alarm clock currently scheduled.
      *
-     * The alarm clocks considered are those scheduled by {@link #setAlarmClock}
-     * from any package of the given {@parm userId}.
+     * The alarm clocks considered are those scheduled by any application
+     * using the {@link #setAlarmClock} method within the given user.
+     *
+     * @return An {@link AlarmClockInfo} object describing the next upcoming alarm
+     *   clock event that will occur within the given user.  If there are no alarm clock
+     *   events currently scheduled in that user, this method will return {@code null}.
      *
      * @see #setAlarmClock
      * @see AlarmClockInfo
+     * @see #ACTION_NEXT_ALARM_CLOCK_CHANGED
      *
      * @hide
      */
@@ -1005,12 +1020,12 @@
         try {
             return mService.getNextAlarmClock(userId);
         } catch (RemoteException ex) {
-            return null;
+            throw ex.rethrowFromSystemServer();
         }
     }
 
     /**
-     * An immutable description of an alarm clock.
+     * An immutable description of a scheduled "alarm clock" event.
      *
      * @see AlarmManager#setAlarmClock
      * @see AlarmManager#getNextAlarmClock
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index 93452fd..82c4c51 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -704,8 +704,8 @@
      * (and system ui) to bypass the user restriction when active.
      */
     private static boolean[] sOpAllowSystemRestrictionBypass = new boolean[] {
-            false, //COARSE_LOCATION
-            false, //FINE_LOCATION
+            true, //COARSE_LOCATION
+            true, //FINE_LOCATION
             false, //GPS
             false, //VIBRATE
             false, //READ_CONTACTS
@@ -1236,8 +1236,8 @@
         try {
             return mService.getPackagesForOps(ops);
         } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
         }
-        return null;
     }
 
     /**
@@ -1252,8 +1252,8 @@
         try {
             return mService.getOpsForPackage(uid, packageName, ops);
         } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
         }
-        return null;
     }
 
     /** @hide */
@@ -1261,6 +1261,7 @@
         try {
             mService.setUidMode(code, uid, mode);
         } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1269,6 +1270,7 @@
         try {
             mService.setUserRestriction(code, restricted, token, mContext.getUserId());
         } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1277,6 +1279,7 @@
         try {
             mService.setMode(code, uid, packageName, mode);
         } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1297,6 +1300,7 @@
             final int uid = Binder.getCallingUid();
             mService.setAudioRestriction(code, usage, uid, mode, exceptionPackages);
         } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1305,6 +1309,7 @@
         try {
             mService.resetAllModes(UserHandle.myUserId(), null);
         } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1361,6 +1366,7 @@
             try {
                 mService.startWatchingMode(op, packageName, cb);
             } catch (RemoteException e) {
+                throw e.rethrowFromSystemServer();
             }
         }
     }
@@ -1376,6 +1382,7 @@
                 try {
                     mService.stopWatchingMode(cb);
                 } catch (RemoteException e) {
+                    throw e.rethrowFromSystemServer();
                 }
             }
         }
@@ -1540,8 +1547,8 @@
             }
             return mode;
         } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
         }
-        return MODE_IGNORED;
     }
 
     /**
@@ -1553,8 +1560,8 @@
         try {
             return mService.checkOperation(op, uid, packageName);
         } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
         }
-        return MODE_ERRORED;
     }
 
     /**
@@ -1570,7 +1577,7 @@
                         "Package " + packageName + " does not belong to " + uid);
             }
         } catch (RemoteException e) {
-            throw new SecurityException("Unable to verify package ownership", e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1586,8 +1593,8 @@
             }
             return mode;
         } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
         }
-        return MODE_IGNORED;
     }
 
     /**
@@ -1599,8 +1606,8 @@
         try {
             return mService.checkAudioOperation(op, stream, uid, packageName);
         } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
         }
-        return MODE_ERRORED;
     }
 
     /**
@@ -1626,8 +1633,8 @@
             }
             return mode;
         } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
         }
-        return MODE_IGNORED;
     }
 
     /**
@@ -1669,8 +1676,8 @@
             return mService.noteProxyOperation(op, mContext.getOpPackageName(),
                     Binder.getCallingUid(), proxiedPackageName);
         } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
         }
-        return MODE_ERRORED;
     }
 
     /**
@@ -1682,8 +1689,8 @@
         try {
             return mService.noteOperation(op, uid, packageName);
         } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
         }
-        return MODE_ERRORED;
     }
 
     /** @hide */
@@ -1700,7 +1707,7 @@
             try {
                 sToken = service.getToken(new Binder());
             } catch (RemoteException e) {
-                // System is dead, whatevs.
+                throw e.rethrowFromSystemServer();
             }
             return sToken;
         }
@@ -1731,8 +1738,8 @@
             }
             return mode;
         } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
         }
-        return MODE_IGNORED;
     }
 
     /**
@@ -1744,8 +1751,8 @@
         try {
             return mService.startOperation(getToken(mService), op, uid, packageName);
         } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
         }
-        return MODE_ERRORED;
     }
 
     /** @hide */
@@ -1764,6 +1771,7 @@
         try {
             mService.finishOperation(getToken(mService), op, uid, packageName);
         } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
         }
     }
 
diff --git a/core/java/android/app/ApplicationLoaders.java b/core/java/android/app/ApplicationLoaders.java
index 7d0d1b4..0fc097e 100644
--- a/core/java/android/app/ApplicationLoaders.java
+++ b/core/java/android/app/ApplicationLoaders.java
@@ -20,16 +20,14 @@
 import android.util.ArrayMap;
 import dalvik.system.PathClassLoader;
 
-class ApplicationLoaders
-{
-    public static ApplicationLoaders getDefault()
-    {
+class ApplicationLoaders {
+    public static ApplicationLoaders getDefault() {
         return gApplicationLoaders;
     }
 
-    public ClassLoader getClassLoader(String zip, boolean isBundled, String librarySearchPath,
-                                      String libraryPermittedPath, ClassLoader parent)
-    {
+    public ClassLoader getClassLoader(String zip, int targetSdkVersion, boolean isBundled,
+                                      String librarySearchPath, String libraryPermittedPath,
+                                      ClassLoader parent) {
         /*
          * This is the parent we use if they pass "null" in.  In theory
          * this should be the "system" class loader; in practice we
@@ -55,11 +53,22 @@
                 }
     
                 Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, zip);
+
                 PathClassLoader pathClassloader =
-                    new PathClassLoader(zip, isBundled, librarySearchPath,
-                                        libraryPermittedPath, parent);
+                    new PathClassLoader(zip, librarySearchPath, parent);
+
+                String errorMessage = createClassloaderNamespace(pathClassloader,
+                                                                 targetSdkVersion,
+                                                                 librarySearchPath,
+                                                                 libraryPermittedPath,
+                                                                 isBundled);
                 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
 
+                if (errorMessage != null) {
+                    throw new UnsatisfiedLinkError("Unable to create namespace for the classloader " +
+                                                   pathClassloader + ": " + errorMessage);
+                }
+
                 mLoaders.put(zip, pathClassloader);
                 return pathClassloader;
             }
@@ -71,6 +80,24 @@
         }
     }
 
+    private static native String createClassloaderNamespace(ClassLoader classLoader,
+                                                            int targetSdkVersion,
+                                                            String librarySearchPath,
+                                                            String libraryPermittedPath,
+                                                            boolean isShared);
+
+    /**
+     * Adds a new path the classpath of the given loader.
+     * @throws IllegalStateException if the provided class loader is not a {@link PathClassLoader}.
+     */
+    void addPath(ClassLoader classLoader, String dexPath) {
+        if (!(classLoader instanceof PathClassLoader)) {
+            throw new IllegalStateException("class loader is not a PathClassLoader");
+        }
+        final PathClassLoader baseDexClassLoader = (PathClassLoader) classLoader;
+        baseDexClassLoader.addDexPath(dexPath);
+    }
+
     private final ArrayMap<String, ClassLoader> mLoaders = new ArrayMap<String, ClassLoader>();
 
     private static final ApplicationLoaders gApplicationLoaders
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index 91eabcc..ca05091 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -30,7 +30,6 @@
 import android.content.pm.ActivityInfo;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.ComponentInfo;
-import android.content.pm.ContainerEncryptionParams;
 import android.content.pm.EphemeralApplicationInfo;
 import android.content.pm.FeatureInfo;
 import android.content.pm.IOnPermissionsChangeListener;
@@ -54,7 +53,6 @@
 import android.content.pm.ResolveInfo;
 import android.content.pm.ServiceInfo;
 import android.content.pm.UserInfo;
-import android.content.pm.VerificationParams;
 import android.content.pm.VerifierDeviceIdentity;
 import android.content.res.Resources;
 import android.content.res.XmlResourceParser;
@@ -143,7 +141,7 @@
                 return pi;
             }
         } catch (RemoteException e) {
-            throw new RuntimeException("Package manager has died", e);
+            throw e.rethrowFromSystemServer();
         }
 
         throw new NameNotFoundException(packageName);
@@ -154,7 +152,7 @@
         try {
             return mPM.currentToCanonicalPackageNames(names);
         } catch (RemoteException e) {
-            throw new RuntimeException("Package manager has died", e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -163,7 +161,7 @@
         try {
             return mPM.canonicalToCurrentPackageNames(names);
         } catch (RemoteException e) {
-            throw new RuntimeException("Package manager has died", e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -227,7 +225,7 @@
                 return gids;
             }
         } catch (RemoteException e) {
-            throw new RuntimeException("Package manager has died", e);
+            throw e.rethrowFromSystemServer();
         }
 
         throw new NameNotFoundException(packageName);
@@ -252,7 +250,7 @@
                 return uid;
             }
         } catch (RemoteException e) {
-            throw new RuntimeException("Package manager has died", e);
+            throw e.rethrowFromSystemServer();
         }
 
         throw new NameNotFoundException(packageName);
@@ -267,7 +265,7 @@
                 return pi;
             }
         } catch (RemoteException e) {
-            throw new RuntimeException("Package manager has died", e);
+            throw e.rethrowFromSystemServer();
         }
 
         throw new NameNotFoundException(name);
@@ -277,12 +275,12 @@
     public List<PermissionInfo> queryPermissionsByGroup(String group, int flags)
             throws NameNotFoundException {
         try {
-            List<PermissionInfo> pi = mPM.queryPermissionsByGroup(group, flags);
+            List<PermissionInfo> pi = mPM.queryPermissionsByGroup(group, flags).getList();
             if (pi != null) {
                 return pi;
             }
         } catch (RemoteException e) {
-            throw new RuntimeException("Package manager has died", e);
+            throw e.rethrowFromSystemServer();
         }
 
         throw new NameNotFoundException(group);
@@ -297,7 +295,7 @@
                 return pgi;
             }
         } catch (RemoteException e) {
-            throw new RuntimeException("Package manager has died", e);
+            throw e.rethrowFromSystemServer();
         }
 
         throw new NameNotFoundException(name);
@@ -306,9 +304,9 @@
     @Override
     public List<PermissionGroupInfo> getAllPermissionGroups(int flags) {
         try {
-            return mPM.getAllPermissionGroups(flags);
+            return mPM.getAllPermissionGroups(flags).getList();
         } catch (RemoteException e) {
-            throw new RuntimeException("Package manager has died", e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -330,7 +328,7 @@
                 return maybeAdjustApplicationInfo(ai);
             }
         } catch (RemoteException e) {
-            throw new RuntimeException("Package manager has died", e);
+            throw e.rethrowFromSystemServer();
         }
 
         throw new NameNotFoundException(packageName);
@@ -370,7 +368,7 @@
                 return ai;
             }
         } catch (RemoteException e) {
-            throw new RuntimeException("Package manager has died", e);
+            throw e.rethrowFromSystemServer();
         }
 
         throw new NameNotFoundException(className.toString());
@@ -385,7 +383,7 @@
                 return ai;
             }
         } catch (RemoteException e) {
-            throw new RuntimeException("Package manager has died", e);
+            throw e.rethrowFromSystemServer();
         }
 
         throw new NameNotFoundException(className.toString());
@@ -400,7 +398,7 @@
                 return si;
             }
         } catch (RemoteException e) {
-            throw new RuntimeException("Package manager has died", e);
+            throw e.rethrowFromSystemServer();
         }
 
         throw new NameNotFoundException(className.toString());
@@ -415,7 +413,7 @@
                 return pi;
             }
         } catch (RemoteException e) {
-            throw new RuntimeException("Package manager has died", e);
+            throw e.rethrowFromSystemServer();
         }
 
         throw new NameNotFoundException(className.toString());
@@ -426,7 +424,7 @@
         try {
             return mPM.getSystemSharedLibraryNames();
         } catch (RemoteException e) {
-            throw new RuntimeException("Package manager has died", e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -436,16 +434,21 @@
         try {
             return mPM.getServicesSystemSharedLibraryPackageName();
         } catch (RemoteException e) {
-            throw new RuntimeException("Package manager has died", e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
     @Override
     public FeatureInfo[] getSystemAvailableFeatures() {
         try {
-            return mPM.getSystemAvailableFeatures();
+            final List<FeatureInfo> list = mPM.getSystemAvailableFeatures().getList();
+            final FeatureInfo[] res = new FeatureInfo[list.size()];
+            for (int i = 0; i < res.length; i++) {
+                res[i] = list.get(i);
+            }
+            return res;
         } catch (RemoteException e) {
-            throw new RuntimeException("Package manager has died", e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -459,7 +462,7 @@
         try {
             return mPM.hasSystemFeature(name, version);
         } catch (RemoteException e) {
-            throw new RuntimeException("Package manager has died", e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -468,7 +471,7 @@
         try {
             return mPM.checkPermission(permName, pkgName, mContext.getUserId());
         } catch (RemoteException e) {
-            throw new RuntimeException("Package manager has died", e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -477,7 +480,7 @@
         try {
             return mPM.isPermissionRevokedByPolicy(permName, pkgName, mContext.getUserId());
         } catch (RemoteException e) {
-            throw new RuntimeException("Package manager has died", e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -491,7 +494,7 @@
                 try {
                     mPermissionsControllerPackageName = mPM.getPermissionControllerPackageName();
                 } catch (RemoteException e) {
-                    throw new RuntimeException("Package manager has died", e);
+                    throw e.rethrowFromSystemServer();
                 }
             }
             return mPermissionsControllerPackageName;
@@ -503,7 +506,7 @@
         try {
             return mPM.addPermission(info);
         } catch (RemoteException e) {
-            throw new RuntimeException("Package manager has died", e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -512,7 +515,7 @@
         try {
             return mPM.addPermissionAsync(info);
         } catch (RemoteException e) {
-            throw new RuntimeException("Package manager has died", e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -521,7 +524,7 @@
         try {
             mPM.removePermission(name);
         } catch (RemoteException e) {
-            throw new RuntimeException("Package manager has died", e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -531,7 +534,7 @@
         try {
             mPM.grantRuntimePermission(packageName, permissionName, user.getIdentifier());
         } catch (RemoteException e) {
-            throw new RuntimeException("Package manager has died", e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -541,7 +544,7 @@
         try {
             mPM.revokeRuntimePermission(packageName, permissionName, user.getIdentifier());
         } catch (RemoteException e) {
-            throw new RuntimeException("Package manager has died", e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -550,7 +553,7 @@
         try {
             return mPM.getPermissionFlags(permissionName, packageName, user.getIdentifier());
         } catch (RemoteException e) {
-            throw new RuntimeException("Package manager has died", e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -561,7 +564,7 @@
             mPM.updatePermissionFlags(permissionName, packageName, flagMask,
                     flagValues, user.getIdentifier());
         } catch (RemoteException e) {
-            throw new RuntimeException("Package manager has died", e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -571,7 +574,7 @@
             return mPM.shouldShowRequestPermissionRationale(permission,
                     mContext.getPackageName(), mContext.getUserId());
         } catch (RemoteException e) {
-            throw new RuntimeException("Package manager has died", e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -580,7 +583,7 @@
         try {
             return mPM.checkSignatures(pkg1, pkg2);
         } catch (RemoteException e) {
-            throw new RuntimeException("Package manager has died", e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -589,7 +592,7 @@
         try {
             return mPM.checkUidSignatures(uid1, uid2);
         } catch (RemoteException e) {
-            throw new RuntimeException("Package manager has died", e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -598,7 +601,7 @@
         try {
             return mPM.getPackagesForUid(uid);
         } catch (RemoteException e) {
-            throw new RuntimeException("Package manager has died", e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -607,7 +610,7 @@
         try {
             return mPM.getNameForUid(uid);
         } catch (RemoteException e) {
-            throw new RuntimeException("Package manager has died", e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -620,7 +623,7 @@
                 return uid;
             }
         } catch (RemoteException e) {
-            throw new RuntimeException("Package manager has died", e);
+            throw e.rethrowFromSystemServer();
         }
         throw new NameNotFoundException("No shared userid for user:"+sharedUserName);
     }
@@ -638,7 +641,7 @@
             ParceledListSlice<PackageInfo> slice = mPM.getInstalledPackages(flags, userId);
             return slice.getList();
         } catch (RemoteException e) {
-            throw new RuntimeException("Package manager has died", e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -652,7 +655,7 @@
                     permissions, flags, userId);
             return slice.getList();
         } catch (RemoteException e) {
-            throw new RuntimeException("Package manager has died", e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -664,7 +667,7 @@
             ParceledListSlice<ApplicationInfo> slice = mPM.getInstalledApplications(flags, userId);
             return slice.getList();
         } catch (RemoteException e) {
-            throw new RuntimeException("Package manager has died", e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -680,7 +683,7 @@
             }
             return Collections.emptyList();
         } catch (RemoteException e) {
-            throw new RuntimeException("Package manager has died", e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -695,7 +698,7 @@
             }
             return null;
         } catch (RemoteException e) {
-            throw new RuntimeException("Package manager has died", e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -705,9 +708,8 @@
             return mPM.isEphemeralApplication(
                     mContext.getPackageName(), mContext.getUserId());
         } catch (RemoteException e) {
-            Log.e(TAG, "System server is dead", e);
+            throw e.rethrowFromSystemServer();
         }
-        return false;
     }
 
     @Override
@@ -724,11 +726,12 @@
                     mContext.getPackageName(), mContext.getUserId());
             if (cookie != null) {
                 return cookie;
+            } else {
+                return EmptyArray.BYTE;
             }
         } catch (RemoteException e) {
-            Log.e(TAG, "System server is dead", e);
+            throw e.rethrowFromSystemServer();
         }
-        return EmptyArray.BYTE;
     }
 
     @Override
@@ -737,9 +740,8 @@
             return mPM.setEphemeralApplicationCookie(
                     mContext.getPackageName(), cookie, mContext.getUserId());
         } catch (RemoteException e) {
-            Log.e(TAG, "System server is dead", e);
+            throw e.rethrowFromSystemServer();
         }
-        return false;
     }
 
     @Override
@@ -756,7 +758,7 @@
                 flags,
                 userId);
         } catch (RemoteException e) {
-            throw new RuntimeException("Package manager has died", e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -775,9 +777,9 @@
                 intent,
                 intent.resolveTypeIfNeeded(mContext.getContentResolver()),
                 flags,
-                userId);
+                userId).getList();
         } catch (RemoteException e) {
-            throw new RuntimeException("Package manager has died", e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -805,11 +807,12 @@
         }
 
         try {
-            return mPM.queryIntentActivityOptions(caller, specifics,
-                                                  specificTypes, intent, intent.resolveTypeIfNeeded(resolver),
-                                                  flags, mContext.getUserId());
+            return mPM
+                    .queryIntentActivityOptions(caller, specifics, specificTypes, intent,
+                            intent.resolveTypeIfNeeded(resolver), flags, mContext.getUserId())
+                    .getList();
         } catch (RemoteException e) {
-            throw new RuntimeException("Package manager has died", e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -823,9 +826,9 @@
                 intent,
                 intent.resolveTypeIfNeeded(mContext.getContentResolver()),
                 flags,
-                userId);
+                userId).getList();
         } catch (RemoteException e) {
-            throw new RuntimeException("Package manager has died", e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -843,7 +846,7 @@
                 flags,
                 mContext.getUserId());
         } catch (RemoteException e) {
-            throw new RuntimeException("Package manager has died", e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -854,9 +857,9 @@
                 intent,
                 intent.resolveTypeIfNeeded(mContext.getContentResolver()),
                 flags,
-                userId);
+                userId).getList();
         } catch (RemoteException e) {
-            throw new RuntimeException("Package manager has died", e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -870,9 +873,10 @@
             Intent intent, int flags, int userId) {
         try {
             return mPM.queryIntentContentProviders(intent,
-                    intent.resolveTypeIfNeeded(mContext.getContentResolver()), flags, userId);
+                    intent.resolveTypeIfNeeded(mContext.getContentResolver()), flags, userId)
+                    .getList();
         } catch (RemoteException e) {
-            throw new RuntimeException("Package manager has died", e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -892,7 +896,7 @@
         try {
             return mPM.resolveContentProvider(name, flags, userId);
         } catch (RemoteException e) {
-            throw new RuntimeException("Package manager has died", e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -904,7 +908,7 @@
                     = mPM.queryContentProviders(processName, uid, flags);
             return slice != null ? slice.getList() : null;
         } catch (RemoteException e) {
-            throw new RuntimeException("Package manager has died", e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -919,7 +923,7 @@
                 return ii;
             }
         } catch (RemoteException e) {
-            throw new RuntimeException("Package manager has died", e);
+            throw e.rethrowFromSystemServer();
         }
 
         throw new NameNotFoundException(className.toString());
@@ -929,9 +933,9 @@
     public List<InstrumentationInfo> queryInstrumentation(
         String targetPackage, int flags) {
         try {
-            return mPM.queryInstrumentation(targetPackage, flags);
+            return mPM.queryInstrumentation(targetPackage, flags).getList();
         } catch (RemoteException e) {
-            throw new RuntimeException("Package manager has died", e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1096,6 +1100,14 @@
     }
 
     @Override
+    public Drawable getManagedUserBadgedDrawable(Drawable drawable, Rect badgeLocation,
+            int badgeDensity) {
+        Drawable badgeDrawable = getDrawableForDensity(
+            com.android.internal.R.drawable.ic_corp_badge, badgeDensity);
+        return getBadgedDrawable(drawable, badgeDrawable, badgeLocation, true);
+    }
+
+    @Override
     public Drawable getUserBadgedIcon(Drawable icon, UserHandle user) {
         final int badgeResId = getBadgeResIdForUser(user.getIdentifier());
         if (badgeResId == 0) {
@@ -1117,24 +1129,27 @@
 
     @Override
     public Drawable getUserBadgeForDensity(UserHandle user, int density) {
-        return getManagedProfileIconForDensity(user, density,
-                com.android.internal.R.drawable.ic_corp_badge);
+        return getManagedProfileIconForDensity(user, com.android.internal.R.drawable.ic_corp_badge,
+                density);
     }
 
     @Override
     public Drawable getUserBadgeForDensityNoBackground(UserHandle user, int density) {
-        return getManagedProfileIconForDensity(user, density,
-                com.android.internal.R.drawable.ic_corp_badge_no_background);
+        return getManagedProfileIconForDensity(user,
+                com.android.internal.R.drawable.ic_corp_badge_no_background, density);
     }
 
-    private Drawable getManagedProfileIconForDensity(UserHandle user, int density,
-            int drawableId) {
+    private Drawable getDrawableForDensity(int drawableId, int density) {
+        if (density <= 0) {
+            density = mContext.getResources().getDisplayMetrics().densityDpi;
+        }
+        return Resources.getSystem().getDrawableForDensity(drawableId, density);
+    }
+
+    private Drawable getManagedProfileIconForDensity(UserHandle user, int drawableId, int density) {
         UserInfo userInfo = getUserIfProfile(user.getIdentifier());
         if (userInfo != null && userInfo.isManagedProfile()) {
-            if (density <= 0) {
-                density = mContext.getResources().getDisplayMetrics().densityDpi;
-            }
-            return Resources.getSystem().getDrawableForDensity(drawableId, density);
+            return getDrawableForDensity(drawableId, density);
         }
         return null;
     }
@@ -1167,7 +1182,7 @@
                 sameUid ? app.sourceDir : app.publicSourceDir,
                 sameUid ? app.splitSourceDirs : app.splitPublicSourceDirs,
                 app.resourceDirs, app.sharedLibraryFiles, Display.DEFAULT_DISPLAY,
-                null, mContext.mPackageInfo);
+                mContext.mPackageInfo);
         if (r != null) {
             return r;
         }
@@ -1198,7 +1213,7 @@
                 return getResourcesForApplication(ai);
             }
         } catch (RemoteException e) {
-            throw new RuntimeException("Package manager has died", e);
+            throw e.rethrowFromSystemServer();
         }
         throw new NameNotFoundException("Package " + appPackageName + " doesn't exist");
     }
@@ -1213,7 +1228,7 @@
             }
             return mCachedSafeMode != 0;
         } catch (RemoteException e) {
-            throw new RuntimeException("Package manager has died", e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1229,7 +1244,7 @@
                 mPM.addOnPermissionsChangeListener(delegate);
                 mPermissionListeners.put(listener, delegate);
             } catch (RemoteException e) {
-                throw new RuntimeException("Package manager has died", e);
+                throw e.rethrowFromSystemServer();
             }
         }
     }
@@ -1243,7 +1258,7 @@
                     mPM.removeOnPermissionsChangeListener(delegate);
                     mPermissionListeners.remove(listener);
                 } catch (RemoteException e) {
-                    throw new RuntimeException("Package manager has died", e);
+                    throw e.rethrowFromSystemServer();
                 }
             }
         }
@@ -1470,81 +1485,29 @@
     @Override
     public void installPackage(Uri packageURI, IPackageInstallObserver observer, int flags,
                                String installerPackageName) {
-        final VerificationParams verificationParams = new VerificationParams(null, null,
-                null, VerificationParams.NO_UID);
         installCommon(packageURI, new LegacyPackageInstallObserver(observer), flags,
-                installerPackageName, verificationParams, null, mContext.getUserId());
-    }
-
-    @Override
-    public void installPackageWithVerification(Uri packageURI, IPackageInstallObserver observer,
-            int flags, String installerPackageName, Uri verificationURI,
-            ContainerEncryptionParams encryptionParams) {
-        final VerificationParams verificationParams = new VerificationParams(verificationURI, null,
-                null, VerificationParams.NO_UID);
-        installCommon(packageURI, new LegacyPackageInstallObserver(observer), flags,
-                installerPackageName, verificationParams, encryptionParams, mContext.getUserId());
-    }
-
-    @Override
-    public void installPackageWithVerificationAndEncryption(Uri packageURI,
-            IPackageInstallObserver observer, int flags, String installerPackageName,
-            VerificationParams verificationParams, ContainerEncryptionParams encryptionParams) {
-        installCommon(packageURI, new LegacyPackageInstallObserver(observer), flags,
-                installerPackageName, verificationParams, encryptionParams, mContext.getUserId());
+                installerPackageName, mContext.getUserId());
     }
 
     @Override
     public void installPackage(Uri packageURI, PackageInstallObserver observer,
             int flags, String installerPackageName) {
-        installPackageAsUser(packageURI, observer, flags, installerPackageName,
-                mContext.getUserId());
-    }
-
-    @Override
-    public void installPackageAsUser(Uri packageURI, PackageInstallObserver observer, int flags,
-               String installerPackageName, int userId) {
-        final VerificationParams verificationParams = new VerificationParams(null, null,
-                null, VerificationParams.NO_UID);
-        installCommon(packageURI, observer, flags, installerPackageName, verificationParams, null,
-                userId);
-    }
-
-    @Override
-    public void installPackageWithVerification(Uri packageURI,
-            PackageInstallObserver observer, int flags, String installerPackageName,
-            Uri verificationURI,
-            ContainerEncryptionParams encryptionParams) {
-        final VerificationParams verificationParams = new VerificationParams(verificationURI, null,
-                null, VerificationParams.NO_UID);
-        installCommon(packageURI, observer, flags, installerPackageName, verificationParams,
-                encryptionParams, mContext.getUserId());
-    }
-
-    @Override
-    public void installPackageWithVerificationAndEncryption(Uri packageURI,
-            PackageInstallObserver observer, int flags, String installerPackageName,
-            VerificationParams verificationParams, ContainerEncryptionParams encryptionParams) {
-        installCommon(packageURI, observer, flags, installerPackageName, verificationParams,
-                encryptionParams, mContext.getUserId());
+        installCommon(packageURI, observer, flags, installerPackageName, mContext.getUserId());
     }
 
     private void installCommon(Uri packageURI,
             PackageInstallObserver observer, int flags, String installerPackageName,
-            VerificationParams verificationParams, ContainerEncryptionParams encryptionParams,
             int userId) {
         if (!"file".equals(packageURI.getScheme())) {
             throw new UnsupportedOperationException("Only file:// URIs are supported");
         }
-        if (encryptionParams != null) {
-            throw new UnsupportedOperationException("ContainerEncryptionParams not supported");
-        }
 
         final String originPath = packageURI.getPath();
         try {
             mPM.installPackageAsUser(originPath, observer.getBinder(), flags, installerPackageName,
-                    verificationParams, null, userId);
-        } catch (RemoteException ignored) {
+                    userId);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1563,8 +1526,7 @@
             }
             return res;
         } catch (RemoteException e) {
-            // Should never happen!
-            throw new NameNotFoundException("Package " + packageName + " doesn't exist");
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1573,7 +1535,7 @@
         try {
             mPM.verifyPendingInstall(id, response);
         } catch (RemoteException e) {
-            // Should never happen!
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1583,16 +1545,16 @@
         try {
             mPM.extendVerificationTimeout(id, verificationCodeAtTimeout, millisecondsToDelay);
         } catch (RemoteException e) {
-            // Should never happen!
+            throw e.rethrowFromSystemServer();
         }
     }
 
     @Override
-    public void verifyIntentFilter(int id, int verificationCode, List<String> outFailedDomains) {
+    public void verifyIntentFilter(int id, int verificationCode, List<String> failedDomains) {
         try {
-            mPM.verifyIntentFilter(id, verificationCode, outFailedDomains);
+            mPM.verifyIntentFilter(id, verificationCode, failedDomains);
         } catch (RemoteException e) {
-            // Should never happen!
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1601,8 +1563,7 @@
         try {
             return mPM.getIntentVerificationStatus(packageName, userId);
         } catch (RemoteException e) {
-            // Should never happen!
-            return PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1611,28 +1572,25 @@
         try {
             return mPM.updateIntentVerificationStatus(packageName, status, userId);
         } catch (RemoteException e) {
-            // Should never happen!
-            return false;
+            throw e.rethrowFromSystemServer();
         }
     }
 
     @Override
     public List<IntentFilterVerificationInfo> getIntentFilterVerifications(String packageName) {
         try {
-            return mPM.getIntentFilterVerifications(packageName);
+            return mPM.getIntentFilterVerifications(packageName).getList();
         } catch (RemoteException e) {
-            // Should never happen!
-            return null;
+            throw e.rethrowFromSystemServer();
         }
     }
 
     @Override
     public List<IntentFilter> getAllIntentFilters(String packageName) {
         try {
-            return mPM.getAllIntentFilters(packageName);
+            return mPM.getAllIntentFilters(packageName).getList();
         } catch (RemoteException e) {
-            // Should never happen!
-            return null;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1641,8 +1599,7 @@
         try {
             return mPM.getDefaultBrowserPackageName(userId);
         } catch (RemoteException e) {
-            // Should never happen!
-            return null;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1651,8 +1608,7 @@
         try {
             return mPM.setDefaultBrowserPackageName(packageName, userId);
         } catch (RemoteException e) {
-            // Should never happen!
-            return false;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1662,7 +1618,7 @@
         try {
             mPM.setInstallerPackageName(targetPackage, installerPackageName);
         } catch (RemoteException e) {
-            // Should never happen!
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1671,9 +1627,8 @@
         try {
             return mPM.getInstallerPackageName(packageName);
         } catch (RemoteException e) {
-            // Should never happen!
+            throw e.rethrowFromSystemServer();
         }
-        return null;
     }
 
     @Override
@@ -1681,7 +1636,7 @@
         try {
             return mPM.getMoveStatus(moveId);
         } catch (RemoteException e) {
-            throw e.rethrowAsRuntimeException();
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1693,7 +1648,7 @@
             try {
                 mPM.registerMoveCallback(delegate);
             } catch (RemoteException e) {
-                throw e.rethrowAsRuntimeException();
+                throw e.rethrowFromSystemServer();
             }
             mDelegates.add(delegate);
         }
@@ -1708,7 +1663,7 @@
                     try {
                         mPM.unregisterMoveCallback(delegate);
                     } catch (RemoteException e) {
-                        throw e.rethrowAsRuntimeException();
+                        throw e.rethrowFromSystemServer();
                     }
                     i.remove();
                 }
@@ -1730,7 +1685,7 @@
 
             return mPM.movePackage(packageName, volumeUuid);
         } catch (RemoteException e) {
-            throw e.rethrowAsRuntimeException();
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1796,7 +1751,7 @@
                 return false;
             }
         } catch (RemoteException e) {
-            throw new RuntimeException("Package manager has died", e);
+            throw e.rethrowFromSystemServer();
         }
 
         // Otherwise we can move to any private volume
@@ -1817,7 +1772,7 @@
 
             return mPM.movePrimaryStorage(volumeUuid);
         } catch (RemoteException e) {
-            throw e.rethrowAsRuntimeException();
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1874,7 +1829,7 @@
         try {
             mPM.deletePackageAsUser(packageName, observer, userId, flags);
         } catch (RemoteException e) {
-            // Should never happen!
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1884,7 +1839,7 @@
         try {
             mPM.clearApplicationUserData(packageName, observer, mContext.getUserId());
         } catch (RemoteException e) {
-            // Should never happen!
+            throw e.rethrowFromSystemServer();
         }
     }
     @Override
@@ -1893,7 +1848,7 @@
         try {
             mPM.deleteApplicationCacheFiles(packageName, observer);
         } catch (RemoteException e) {
-            // Should never happen!
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1903,7 +1858,7 @@
         try {
             mPM.freeStorageAndNotify(volumeUuid, idealStorageSize, observer);
         } catch (RemoteException e) {
-            // Should never happen!
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1912,7 +1867,7 @@
         try {
             mPM.freeStorage(volumeUuid, freeStorageSize, pi);
         } catch (RemoteException e) {
-            // Should never happen!
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1922,9 +1877,8 @@
         try {
             return mPM.setPackagesSuspendedAsUser(packageNames, suspended, userId);
         } catch (RemoteException e) {
-            // Should never happen!
+            throw e.rethrowFromSystemServer();
         }
-        return packageNames;
     }
 
     @Override
@@ -1932,9 +1886,8 @@
         try {
             return mPM.isPackageSuspendedForUser(packageName, userId);
         } catch (RemoteException e) {
-            // Should never happen!
+            throw e.rethrowFromSystemServer();
         }
-        return false;
     }
 
     @Override
@@ -1943,35 +1896,24 @@
         try {
             mPM.getPackageSizeInfo(packageName, userHandle, observer);
         } catch (RemoteException e) {
-            // Should never happen!
+            throw e.rethrowFromSystemServer();
         }
     }
+
     @Override
     public void addPackageToPreferred(String packageName) {
-        try {
-            mPM.addPackageToPreferred(packageName);
-        } catch (RemoteException e) {
-            // Should never happen!
-        }
+        Log.w(TAG, "addPackageToPreferred() is a no-op");
     }
 
     @Override
     public void removePackageFromPreferred(String packageName) {
-        try {
-            mPM.removePackageFromPreferred(packageName);
-        } catch (RemoteException e) {
-            // Should never happen!
-        }
+        Log.w(TAG, "removePackageFromPreferred() is a no-op");
     }
 
     @Override
     public List<PackageInfo> getPreferredPackages(int flags) {
-        try {
-            return mPM.getPreferredPackages(flags);
-        } catch (RemoteException e) {
-            // Should never happen!
-        }
-        return new ArrayList<PackageInfo>();
+        Log.w(TAG, "getPreferredPackages() is a no-op");
+        return Collections.emptyList();
     }
 
     @Override
@@ -1980,7 +1922,7 @@
         try {
             mPM.addPreferredActivity(filter, match, set, activity, mContext.getUserId());
         } catch (RemoteException e) {
-            // Should never happen!
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1990,7 +1932,7 @@
         try {
             mPM.addPreferredActivity(filter, match, set, activity, userId);
         } catch (RemoteException e) {
-            // Should never happen!
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -2000,7 +1942,7 @@
         try {
             mPM.replacePreferredActivity(filter, match, set, activity, mContext.getUserId());
         } catch (RemoteException e) {
-            // Should never happen!
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -2011,7 +1953,7 @@
         try {
             mPM.replacePreferredActivity(filter, match, set, activity, userId);
         } catch (RemoteException e) {
-            // Should never happen!
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -2020,7 +1962,7 @@
         try {
             mPM.clearPackagePreferredActivities(packageName);
         } catch (RemoteException e) {
-            // Should never happen!
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -2030,9 +1972,8 @@
         try {
             return mPM.getPreferredActivities(outFilters, outActivities, packageName);
         } catch (RemoteException e) {
-            // Should never happen!
+            throw e.rethrowFromSystemServer();
         }
-        return 0;
     }
 
     @Override
@@ -2040,9 +1981,8 @@
         try {
             return mPM.getHomeActivities(outActivities);
         } catch (RemoteException e) {
-            // Should never happen!
+            throw e.rethrowFromSystemServer();
         }
-        return null;
     }
 
     @Override
@@ -2051,7 +1991,7 @@
         try {
             mPM.setComponentEnabledSetting(componentName, newState, flags, mContext.getUserId());
         } catch (RemoteException e) {
-            // Should never happen!
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -2060,9 +2000,8 @@
         try {
             return mPM.getComponentEnabledSetting(componentName, mContext.getUserId());
         } catch (RemoteException e) {
-            // Should never happen!
+            throw e.rethrowFromSystemServer();
         }
-        return PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
     }
 
     @Override
@@ -2072,7 +2011,7 @@
             mPM.setApplicationEnabledSetting(packageName, newState, flags,
                     mContext.getUserId(), mContext.getOpPackageName());
         } catch (RemoteException e) {
-            // Should never happen!
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -2081,9 +2020,8 @@
         try {
             return mPM.getApplicationEnabledSetting(packageName, mContext.getUserId());
         } catch (RemoteException e) {
-            // Should never happen!
+            throw e.rethrowFromSystemServer();
         }
-        return PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
     }
 
     @Override
@@ -2092,20 +2030,18 @@
         try {
             return mPM.setApplicationHiddenSettingAsUser(packageName, hidden,
                     user.getIdentifier());
-        } catch (RemoteException re) {
-            // Should never happen!
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
         }
-        return false;
     }
 
     @Override
     public boolean getApplicationHiddenSettingAsUser(String packageName, UserHandle user) {
         try {
             return mPM.getApplicationHiddenSettingAsUser(packageName, user.getIdentifier());
-        } catch (RemoteException re) {
-            // Should never happen!
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
         }
-        return false;
     }
 
     /** @hide */
@@ -2113,26 +2049,22 @@
     public KeySet getKeySetByAlias(String packageName, String alias) {
         Preconditions.checkNotNull(packageName);
         Preconditions.checkNotNull(alias);
-        KeySet ks;
         try {
-            ks = mPM.getKeySetByAlias(packageName, alias);
+            return mPM.getKeySetByAlias(packageName, alias);
         } catch (RemoteException e) {
-            return null;
+            throw e.rethrowFromSystemServer();
         }
-        return ks;
     }
 
     /** @hide */
     @Override
     public KeySet getSigningKeySet(String packageName) {
         Preconditions.checkNotNull(packageName);
-        KeySet ks;
         try {
-            ks = mPM.getSigningKeySet(packageName);
+            return mPM.getSigningKeySet(packageName);
         } catch (RemoteException e) {
-            return null;
+            throw e.rethrowFromSystemServer();
         }
-        return ks;
     }
 
     /** @hide */
@@ -2143,7 +2075,7 @@
         try {
             return mPM.isPackageSignedByKeySet(packageName, ks);
         } catch (RemoteException e) {
-            return false;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -2155,7 +2087,7 @@
         try {
             return mPM.isPackageSignedByKeySetExactly(packageName, ks);
         } catch (RemoteException e) {
-            return false;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -2167,9 +2099,8 @@
         try {
             return mPM.getVerifierDeviceIdentity();
         } catch (RemoteException e) {
-            // Should never happen!
+            throw e.rethrowFromSystemServer();
         }
-        return null;
     }
 
     /**
@@ -2180,7 +2111,7 @@
         try {
             return mPM.isUpgrade();
         } catch (RemoteException e) {
-            return false;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -2192,7 +2123,7 @@
                     mInstaller = new PackageInstaller(mContext, this, mPM.getPackageInstaller(),
                             mContext.getPackageName(), mContext.getUserId());
                 } catch (RemoteException e) {
-                    throw e.rethrowAsRuntimeException();
+                    throw e.rethrowFromSystemServer();
                 }
             }
             return mInstaller;
@@ -2204,7 +2135,7 @@
         try {
             return mPM.isPackageAvailable(packageName, mContext.getUserId());
         } catch (RemoteException e) {
-            throw e.rethrowAsRuntimeException();
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -2218,7 +2149,7 @@
             mPM.addCrossProfileIntentFilter(filter, mContext.getOpPackageName(),
                     sourceUserId, targetUserId, flags);
         } catch (RemoteException e) {
-            // Should never happen!
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -2230,7 +2161,7 @@
         try {
             mPM.clearCrossProfileIntentFilters(sourceUserId, mContext.getOpPackageName());
         } catch (RemoteException e) {
-            // Should never happen!
+            throw e.rethrowFromSystemServer();
         }
     }
 
diff --git a/core/java/android/app/ApplicationThreadNative.java b/core/java/android/app/ApplicationThreadNative.java
index 59ecc03..744ddf7 100644
--- a/core/java/android/app/ApplicationThreadNative.java
+++ b/core/java/android/app/ApplicationThreadNative.java
@@ -548,11 +548,12 @@
             boolean dumpInfo = data.readInt() != 0;
             boolean dumpDalvik = data.readInt() != 0;
             boolean dumpSummaryOnly = data.readInt() != 0;
+            boolean dumpUnreachable = data.readInt() != 0;
             String[] args = data.readStringArray();
             if (fd != null) {
                 try {
                     dumpMemInfo(fd.getFileDescriptor(), mi, checkin, dumpInfo,
-                            dumpDalvik, dumpSummaryOnly, args);
+                            dumpDalvik, dumpSummaryOnly, dumpUnreachable, args);
                 } finally {
                     try {
                         fd.close();
@@ -1328,7 +1329,8 @@
     }
 
     public void dumpMemInfo(FileDescriptor fd, Debug.MemoryInfo mem, boolean checkin,
-            boolean dumpInfo, boolean dumpDalvik, boolean dumpSummaryOnly, String[] args) throws RemoteException {
+            boolean dumpInfo, boolean dumpDalvik, boolean dumpSummaryOnly,
+            boolean dumpUnreachable, String[] args) throws RemoteException {
         Parcel data = Parcel.obtain();
         Parcel reply = Parcel.obtain();
         data.writeInterfaceToken(IApplicationThread.descriptor);
@@ -1338,6 +1340,7 @@
         data.writeInt(dumpInfo ? 1 : 0);
         data.writeInt(dumpDalvik ? 1 : 0);
         data.writeInt(dumpSummaryOnly ? 1 : 0);
+        data.writeInt(dumpUnreachable ? 1 : 0);
         data.writeStringArray(args);
         mRemote.transact(DUMP_MEM_INFO_TRANSACTION, data, reply, 0);
         reply.readException();
diff --git a/core/java/android/app/AutomaticZenRule.java b/core/java/android/app/AutomaticZenRule.java
index e5fa02b..cd4ace6 100644
--- a/core/java/android/app/AutomaticZenRule.java
+++ b/core/java/android/app/AutomaticZenRule.java
@@ -16,6 +16,7 @@
 
 package android.app;
 
+import android.app.NotificationManager.InterruptionFilter;
 import android.content.ComponentName;
 import android.net.Uri;
 import android.os.Parcel;
@@ -26,14 +27,13 @@
 /**
  * Rule instance information for zen mode.
  */
-public class AutomaticZenRule implements Parcelable {
+public final class AutomaticZenRule implements Parcelable {
 
     private boolean enabled = false;
     private String name;
-    private int interruptionFilter;
+    private @InterruptionFilter int interruptionFilter;
     private Uri conditionId;
     private ComponentName owner;
-    private String id;
     private long creationTime;
 
     /**
@@ -42,7 +42,7 @@
      * @param name The name of the rule.
      * @param owner The Condition Provider service that owns this rule.
      * @param conditionId A representation of the state that should cause the Condition Provider
-     *                    service to apply the interruption filter.
+     *                    service to apply the given interruption filter.
      * @param interruptionFilter The interruption filter defines which notifications are allowed to
      *                           interrupt the user (e.g. via sound &amp; vibration) while this rule
      *                           is active.
@@ -62,9 +62,8 @@
      * @hide
      */
     public AutomaticZenRule(String name, ComponentName owner, Uri conditionId,
-            int interruptionFilter, boolean enabled, String id, long creationTime) {
+            int interruptionFilter, boolean enabled, long creationTime) {
         this(name, owner, conditionId, interruptionFilter, enabled);
-        this.id = id;
         this.creationTime = creationTime;
     }
 
@@ -76,9 +75,6 @@
         interruptionFilter = source.readInt();
         conditionId = source.readParcelable(null);
         owner = source.readParcelable(null);
-        if (source.readInt() == 1) {
-            id = source.readString();
-        }
         creationTime = source.readLong();
     }
 
@@ -118,20 +114,13 @@
     }
 
     /**
-     * Returns the wall time in milliseconds when this rule was created, if known.
+     * Returns the time this rule was created, represented as milliseconds since the epoch.
      */
     public long getCreationTime() {
       return creationTime;
     }
 
     /**
-     * Returns the unique identifier for this rule.
-     */
-    public String getId() {
-      return id;
-    }
-
-    /**
      * Sets the representation of the state that causes this rule to become active.
      */
     public void setConditionId(Uri conditionId) {
@@ -140,9 +129,9 @@
 
     /**
      * Sets the interruption filter that is applied when this rule is active.
-     * @param interruptionFilter One of the INTERRUPTION_FILTER_ constants in NotificationManager.
+     * @param interruptionFilter The do not disturb mode to enter when this rule is active.
      */
-    public void setInterruptionFilter(int interruptionFilter) {
+    public void setInterruptionFilter(@InterruptionFilter int interruptionFilter) {
         this.interruptionFilter = interruptionFilter;
     }
 
@@ -177,12 +166,6 @@
         dest.writeInt(interruptionFilter);
         dest.writeParcelable(conditionId, 0);
         dest.writeParcelable(owner, 0);
-        if (id != null) {
-            dest.writeInt(1);
-            dest.writeString(id);
-        } else {
-            dest.writeInt(0);
-        }
         dest.writeLong(creationTime);
     }
 
@@ -194,7 +177,6 @@
                 .append(",interruptionFilter=").append(interruptionFilter)
                 .append(",conditionId=").append(conditionId)
                 .append(",owner=").append(owner)
-                .append(",id=").append(id)
                 .append(",creationTime=").append(creationTime)
                 .append(']').toString();
     }
@@ -209,13 +191,12 @@
                 && other.interruptionFilter == interruptionFilter
                 && Objects.equals(other.conditionId, conditionId)
                 && Objects.equals(other.owner, owner)
-                && Objects.equals(other.id, id)
                 && other.creationTime == creationTime;
     }
 
     @Override
     public int hashCode() {
-        return Objects.hash(enabled, name, interruptionFilter, conditionId, owner, id, creationTime);
+        return Objects.hash(enabled, name, interruptionFilter, conditionId, owner, creationTime);
     }
 
     public static final Parcelable.Creator<AutomaticZenRule> CREATOR
diff --git a/core/java/android/app/BackStackRecord.java b/core/java/android/app/BackStackRecord.java
index 4b0dfc7..3a51aff 100644
--- a/core/java/android/app/BackStackRecord.java
+++ b/core/java/android/app/BackStackRecord.java
@@ -16,8 +16,6 @@
 
 package android.app;
 
-import com.android.internal.util.FastPrintWriter;
-
 import android.graphics.Rect;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -33,6 +31,8 @@
 import android.view.ViewGroup;
 import android.view.ViewTreeObserver;
 
+import com.android.internal.util.FastPrintWriter;
+
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 import java.util.ArrayList;
@@ -717,10 +717,12 @@
 
         bumpBackStackNesting(1);
 
-        SparseArray<Fragment> firstOutFragments = new SparseArray<Fragment>();
-        SparseArray<Fragment> lastInFragments = new SparseArray<Fragment>();
-        calculateFragments(firstOutFragments, lastInFragments);
-        beginTransition(firstOutFragments, lastInFragments, false);
+        if (mManager.mCurState >= Fragment.CREATED) {
+            SparseArray<Fragment> firstOutFragments = new SparseArray<Fragment>();
+            SparseArray<Fragment> lastInFragments = new SparseArray<Fragment>();
+            calculateFragments(firstOutFragments, lastInFragments);
+            beginTransition(firstOutFragments, lastInFragments, false);
+        }
 
         Op op = mHead;
         while (op != null) {
@@ -842,6 +844,14 @@
                     firstOutFragments.remove(containerId);
                 }
             }
+            /**
+             * Ensure that fragments that are entering are at least at the CREATED state
+             * so that they may load Transitions using TransitionInflater.
+             */
+            if (fragment.mState < Fragment.CREATED && mManager.mCurState >= Fragment.CREATED) {
+                mManager.makeActive(fragment);
+                mManager.moveToState(fragment, Fragment.CREATED, 0, 0, false);
+            }
         }
     }
 
@@ -986,7 +996,6 @@
      */
     private TransitionState beginTransition(SparseArray<Fragment> firstOutFragments,
             SparseArray<Fragment> lastInFragments, boolean isBack) {
-        ensureFragmentsAreInitialized(lastInFragments);
         TransitionState state = new TransitionState();
 
         // Adding a non-existent target view makes sure that the transitions don't target
@@ -1012,21 +1021,6 @@
         return state;
     }
 
-    /**
-     * Ensure that fragments that are entering are at least at the CREATED state
-     * so that they may load Transitions using TransitionInflater.
-     */
-    private void ensureFragmentsAreInitialized(SparseArray<Fragment> lastInFragments) {
-        final int count = lastInFragments.size();
-        for (int i = 0; i < count; i++) {
-            final Fragment fragment = lastInFragments.valueAt(i);
-            if (fragment.mState < Fragment.CREATED) {
-                mManager.makeActive(fragment);
-                mManager.moveToState(fragment, Fragment.CREATED, 0, 0, false);
-            }
-        }
-    }
-
     private static Transition cloneTransition(Transition transition) {
         if (transition != null) {
             transition = transition.clone();
@@ -1663,12 +1657,14 @@
             pw.flush();
         }
 
-        if (state == null) {
-            if (firstOutFragments.size() != 0 || lastInFragments.size() != 0) {
-                state = beginTransition(firstOutFragments, lastInFragments, true);
+        if (mManager.mCurState >= Fragment.CREATED) {
+            if (state == null) {
+                if (firstOutFragments.size() != 0 || lastInFragments.size() != 0) {
+                    state = beginTransition(firstOutFragments, lastInFragments, true);
+                }
+            } else if (!doStateMove) {
+                setNameOverrides(state, mSharedElementTargetNames, mSharedElementSourceNames);
             }
-        } else if (!doStateMove) {
-            setNameOverrides(state, mSharedElementTargetNames, mSharedElementSourceNames);
         }
 
         bumpBackStackNesting(-1);
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index 8884949..32ace14 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -396,9 +396,11 @@
 
     /**
      * Try our best to migrate all files from source to target that match
-     * requested prefix. Return false if we have any trouble migrating.
+     * requested prefix.
+     *
+     * @return the number of files moved, or -1 if there was trouble.
      */
-    private static boolean migrateFiles(File sourceDir, File targetDir, final String prefix) {
+    private static int migrateFiles(File sourceDir, File targetDir, final String prefix) {
         final File[] sourceFiles = FileUtils.listFilesOrEmpty(sourceDir, new FilenameFilter() {
             @Override
             public boolean accept(File dir, String name) {
@@ -406,7 +408,7 @@
             }
         });
 
-        boolean res = true;
+        int res = 0;
         for (File sourceFile : sourceFiles) {
             final File targetFile = new File(targetDir, sourceFile.getName());
             Log.d(TAG, "Migrating " + sourceFile + " to " + targetFile);
@@ -416,9 +418,12 @@
                 if (!sourceFile.delete()) {
                     throw new IOException("Failed to clean up " + sourceFile);
                 }
+                if (res != -1) {
+                    res++;
+                }
             } catch (IOException e) {
                 Log.w(TAG, "Failed to migrate " + sourceFile + ": " + e);
-                res = false;
+                res = -1;
             }
         }
         return res;
@@ -430,12 +435,17 @@
             final File source = sourceContext.getSharedPreferencesPath(name);
             final File target = getSharedPreferencesPath(name);
 
-            // Evict any in-memory caches for either location
-            final ArrayMap<File, SharedPreferencesImpl> cache = getSharedPreferencesCacheLocked();
-            cache.remove(source);
-            cache.remove(target);
-
-            return migrateFiles(source.getParentFile(), target.getParentFile(), source.getName());
+            final int res = migrateFiles(source.getParentFile(), target.getParentFile(),
+                    source.getName());
+            if (res > 0) {
+                // We moved at least one file, so evict any in-memory caches for
+                // either location
+                final ArrayMap<File, SharedPreferencesImpl> cache =
+                        getSharedPreferencesCacheLocked();
+                cache.remove(source);
+                cache.remove(target);
+            }
+            return res != -1;
         }
     }
 
@@ -675,7 +685,8 @@
         synchronized (ContextImpl.class) {
             final File source = sourceContext.getDatabasePath(name);
             final File target = getDatabasePath(name);
-            return migrateFiles(source.getParentFile(), target.getParentFile(), source.getName());
+            return migrateFiles(source.getParentFile(), target.getParentFile(),
+                    source.getName()) != -1;
         }
     }
 
@@ -813,7 +824,7 @@
                 null, null, 0, Intent.FLAG_ACTIVITY_NEW_TASK, null, options,
                 user.getIdentifier());
         } catch (RemoteException e) {
-            throw new RuntimeException("Failure from system", e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -878,7 +889,7 @@
             }
             Instrumentation.checkStartActivityResult(result, null);
         } catch (RemoteException e) {
-            throw new RuntimeException("Failure from system", e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -893,7 +904,7 @@
                     Activity.RESULT_OK, null, null, null, AppOpsManager.OP_NONE, null, false, false,
                     getUserId());
         } catch (RemoteException e) {
-            throw new RuntimeException("Failure from system", e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -910,7 +921,7 @@
                     Activity.RESULT_OK, null, null, receiverPermissions, AppOpsManager.OP_NONE,
                     null, false, false, getUserId());
         } catch (RemoteException e) {
-            throw new RuntimeException("Failure from system", e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -925,7 +936,7 @@
                     Activity.RESULT_OK, null, null, receiverPermissions, AppOpsManager.OP_NONE,
                     null, false, false, getUserId());
         } catch (RemoteException e) {
-            throw new RuntimeException("Failure from system", e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -942,7 +953,7 @@
                     Activity.RESULT_OK, null, null, receiverPermissions, AppOpsManager.OP_NONE,
                     options, false, false, getUserId());
         } catch (RemoteException e) {
-            throw new RuntimeException("Failure from system", e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -959,7 +970,7 @@
                     Activity.RESULT_OK, null, null, receiverPermissions, appOp, null, false, false,
                     getUserId());
         } catch (RemoteException e) {
-            throw new RuntimeException("Failure from system", e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -976,7 +987,7 @@
                     Activity.RESULT_OK, null, null, receiverPermissions, AppOpsManager.OP_NONE,
                     null, true, false, getUserId());
         } catch (RemoteException e) {
-            throw new RuntimeException("Failure from system", e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1039,7 +1050,7 @@
                 initialCode, initialData, initialExtras, receiverPermissions, appOp,
                     options, true, false, getUserId());
         } catch (RemoteException e) {
-            throw new RuntimeException("Failure from system", e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1052,7 +1063,7 @@
                     intent, resolvedType, null, Activity.RESULT_OK, null, null, null,
                     AppOpsManager.OP_NONE, null, false, false, user.getIdentifier());
         } catch (RemoteException e) {
-            throw new RuntimeException("Failure from system", e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1075,7 +1086,7 @@
                     Activity.RESULT_OK, null, null, receiverPermissions, appOp, null, false, false,
                     user.getIdentifier());
         } catch (RemoteException e) {
-            throw new RuntimeException("Failure from system", e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1126,7 +1137,7 @@
                 initialCode, initialData, initialExtras, receiverPermissions,
                     appOp, options, true, false, user.getIdentifier());
         } catch (RemoteException e) {
-            throw new RuntimeException("Failure from system", e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1142,7 +1153,7 @@
                 Activity.RESULT_OK, null, null, null, AppOpsManager.OP_NONE, null, false, true,
                 getUserId());
         } catch (RemoteException e) {
-            throw new RuntimeException("Failure from system", e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1178,7 +1189,7 @@
                 initialCode, initialData, initialExtras, null,
                     AppOpsManager.OP_NONE, null, true, true, getUserId());
         } catch (RemoteException e) {
-            throw new RuntimeException("Failure from system", e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1195,7 +1206,7 @@
             ActivityManagerNative.getDefault().unbroadcastIntent(
                     mMainThread.getApplicationThread(), intent, getUserId());
         } catch (RemoteException e) {
-            throw new RuntimeException("Failure from system", e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1210,7 +1221,7 @@
                 Activity.RESULT_OK, null, null, null, AppOpsManager.OP_NONE, null, false, true,
                     user.getIdentifier());
         } catch (RemoteException e) {
-            throw new RuntimeException("Failure from system", e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1225,7 +1236,7 @@
                 Activity.RESULT_OK, null, null, null, AppOpsManager.OP_NONE, options, false, true,
                 user.getIdentifier());
         } catch (RemoteException e) {
-            throw new RuntimeException("Failure from system", e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1260,7 +1271,7 @@
                 initialCode, initialData, initialExtras, null,
                     AppOpsManager.OP_NONE, null, true, true, user.getIdentifier());
         } catch (RemoteException e) {
-            throw new RuntimeException("Failure from system", e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1277,7 +1288,7 @@
             ActivityManagerNative.getDefault().unbroadcastIntent(
                     mMainThread.getApplicationThread(), intent, user.getIdentifier());
         } catch (RemoteException e) {
-            throw new RuntimeException("Failure from system", e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1325,7 +1336,7 @@
                     mMainThread.getApplicationThread(), mBasePackageName,
                     rd, filter, broadcastPermission, userId);
         } catch (RemoteException e) {
-            return null;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1337,6 +1348,7 @@
             try {
                 ActivityManagerNative.getDefault().unregisterReceiver(rd);
             } catch (RemoteException e) {
+                throw e.rethrowFromSystemServer();
             }
         } else {
             throw new RuntimeException("Not supported in system context");
@@ -1393,7 +1405,7 @@
             }
             return cn;
         } catch (RemoteException e) {
-            throw new RuntimeException("Failure from system", e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1415,7 +1427,7 @@
             }
             return res != 0;
         } catch (RemoteException e) {
-            throw new RuntimeException("Failure from system", e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1474,7 +1486,7 @@
             }
             return res != 0;
         } catch (RemoteException e) {
-            throw new RuntimeException("Failure from system", e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1489,6 +1501,7 @@
             try {
                 ActivityManagerNative.getDefault().unbindService(sd);
             } catch (RemoteException e) {
+                throw e.rethrowFromSystemServer();
             }
         } else {
             throw new RuntimeException("Not supported in system context");
@@ -1506,7 +1519,7 @@
                     className, profileFile, 0, arguments, null, null, getUserId(),
                     null /* ABI override */);
         } catch (RemoteException e) {
-            throw new RuntimeException("Failure from system", e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1530,7 +1543,7 @@
             return ActivityManagerNative.getDefault().checkPermission(
                     permission, pid, uid);
         } catch (RemoteException e) {
-            return PackageManager.PERMISSION_DENIED;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1545,7 +1558,7 @@
             return ActivityManagerNative.getDefault().checkPermissionWithToken(
                     permission, pid, uid, callerToken);
         } catch (RemoteException e) {
-            return PackageManager.PERMISSION_DENIED;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1631,6 +1644,7 @@
                     mMainThread.getApplicationThread(), toPackage,
                     ContentProvider.getUriWithoutUserId(uri), modeFlags, resolveUserId(uri));
         } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1641,6 +1655,7 @@
                     mMainThread.getApplicationThread(),
                     ContentProvider.getUriWithoutUserId(uri), modeFlags, resolveUserId(uri));
         } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1651,7 +1666,7 @@
                     ContentProvider.getUriWithoutUserId(uri), pid, uid, modeFlags,
                     resolveUserId(uri), null);
         } catch (RemoteException e) {
-            return PackageManager.PERMISSION_DENIED;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1663,7 +1678,7 @@
                     ContentProvider.getUriWithoutUserId(uri), pid, uid, modeFlags,
                     resolveUserId(uri), callerToken);
         } catch (RemoteException e) {
-            return PackageManager.PERMISSION_DENIED;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1979,9 +1994,10 @@
     }
 
     static ContextImpl createActivityContext(ActivityThread mainThread,
-            LoadedApk packageInfo, int displayId, Configuration overrideConfiguration) {
+            LoadedApk packageInfo, IBinder activityToken, int displayId,
+            Configuration overrideConfiguration) {
         if (packageInfo == null) throw new IllegalArgumentException("packageInfo");
-        return new ContextImpl(null, mainThread, packageInfo, null, null, 0,
+        return new ContextImpl(null, mainThread, packageInfo, activityToken, null, 0,
                 null, overrideConfiguration, displayId);
     }
 
@@ -2039,10 +2055,16 @@
                     || overrideConfiguration != null
                     || (compatInfo != null && compatInfo.applicationScale
                             != resources.getCompatibilityInfo().applicationScale)) {
-                resources = mResourcesManager.getTopLevelResources(packageInfo.getResDir(),
-                        packageInfo.getSplitResDirs(), packageInfo.getOverlayDirs(),
-                        packageInfo.getApplicationInfo().sharedLibraryFiles, displayId,
-                        overrideConfiguration, compatInfo, packageInfo.getClassLoader());
+                resources = mResourcesManager.getResources(
+                        activityToken,
+                        packageInfo.getResDir(),
+                        packageInfo.getSplitResDirs(),
+                        packageInfo.getOverlayDirs(),
+                        packageInfo.getApplicationInfo().sharedLibraryFiles,
+                        displayId,
+                        overrideConfiguration,
+                        compatInfo,
+                        packageInfo.getClassLoader());
             }
         }
         mResources = resources;
diff --git a/core/java/android/app/DatePickerDialog.java b/core/java/android/app/DatePickerDialog.java
index bbf1607..83dc506 100644
--- a/core/java/android/app/DatePickerDialog.java
+++ b/core/java/android/app/DatePickerDialog.java
@@ -125,9 +125,8 @@
             @Nullable OnDateSetListener listener, int year, int month, int dayOfMonth) {
         this(context, themeResId);
 
-        mDateSetListener = listener;
-
         mDatePicker.updateDate(year, month, dayOfMonth);
+        mDateSetListener = listener;
     }
 
     static @StyleRes int resolveDialogTheme(@NonNull Context context, @StyleRes int themeResId) {
diff --git a/core/java/android/app/Fragment.java b/core/java/android/app/Fragment.java
index aafb3c6..6870bbf 100644
--- a/core/java/android/app/Fragment.java
+++ b/core/java/android/app/Fragment.java
@@ -2509,6 +2509,7 @@
             throw new SuperNotCalledException("Fragment " + this
                     + " did not call through to super.onDestroy()");
         }
+        mChildFragmentManager = null;
     }
 
     private static Transition loadTransition(Context context, TypedArray typedArray,
diff --git a/core/java/android/app/FragmentManager.java b/core/java/android/app/FragmentManager.java
index 78a054b..0631943 100644
--- a/core/java/android/app/FragmentManager.java
+++ b/core/java/android/app/FragmentManager.java
@@ -1525,7 +1525,7 @@
             throw new IllegalStateException("Must be called from main thread of fragment host");
         }
 
-        if (allowStateLoss) {
+        if (!allowStateLoss) {
             checkStateLoss();
         }
 
@@ -1625,7 +1625,9 @@
             final BackStackRecord bss = mBackStack.remove(last);
             SparseArray<Fragment> firstOutFragments = new SparseArray<Fragment>();
             SparseArray<Fragment> lastInFragments = new SparseArray<Fragment>();
-            bss.calculateBackFragments(firstOutFragments, lastInFragments);
+            if (mCurState >= Fragment.CREATED) {
+                bss.calculateBackFragments(firstOutFragments, lastInFragments);
+            }
             bss.popFromBackStack(true, null, firstOutFragments, lastInFragments);
             reportBackStackChanged();
         } else {
@@ -1672,8 +1674,10 @@
             final int LAST = states.size()-1;
             SparseArray<Fragment> firstOutFragments = new SparseArray<Fragment>();
             SparseArray<Fragment> lastInFragments = new SparseArray<Fragment>();
-            for (int i=0; i<=LAST; i++) {
-                states.get(i).calculateBackFragments(firstOutFragments, lastInFragments);
+            if (mCurState >= Fragment.CREATED) {
+                for (int i = 0; i <= LAST; i++) {
+                    states.get(i).calculateBackFragments(firstOutFragments, lastInFragments);
+                }
             }
             BackStackRecord.TransitionState state = null;
             for (int i=0; i<=LAST; i++) {
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index e4d6835..cdbf598 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -33,6 +33,7 @@
 import android.content.pm.ApplicationInfo;
 import android.content.pm.ConfigurationInfo;
 import android.content.pm.IPackageDataObserver;
+import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.pm.ParceledListSlice;
 import android.content.pm.ProviderInfo;
 import android.content.pm.UserInfo;
@@ -143,13 +144,19 @@
     public boolean moveActivityTaskToBack(IBinder token, boolean nonRoot) throws RemoteException;
     public void moveTaskBackwards(int task) throws RemoteException;
     public void moveTaskToStack(int taskId, int stackId, boolean toTop) throws RemoteException;
-    public void moveTaskToDockedStack(int taskId, int createMode, boolean toTop, boolean animate,
+    public boolean moveTaskToDockedStack(int taskId, int createMode, boolean toTop, boolean animate,
             Rect initialBounds) throws RemoteException;
     public boolean moveTopActivityToPinnedStack(int stackId, Rect bounds) throws RemoteException;
     public void resizeStack(int stackId, Rect bounds, boolean allowResizeInDockedMode,
             boolean preserveWindows, boolean animate) throws RemoteException;
 
     /**
+     * Moves all tasks from the docked stack in the fullscreen stack and puts the top task of the
+     * fullscreen stack into the docked stack.
+     */
+    public void swapDockedAndFullscreenStack() throws RemoteException;
+
+    /**
      * Resizes the docked stack, and all other stacks as the result of the dock stack bounds change.
      *
      * @param dockedBounds The bounds for the docked stack.
@@ -171,6 +178,16 @@
     public void resizeDockedStack(Rect dockedBounds, Rect tempDockedTaskBounds,
             Rect tempDockedTaskInsetBounds,
             Rect tempOtherTaskBounds, Rect tempOtherTaskInsetBounds) throws RemoteException;
+    /**
+     * Resizes the pinned stack.
+     *
+     * @param pinnedBounds The bounds for the pinned stack.
+     * @param tempPinnedTaskBounds The temporary bounds for the tasks in the pinned stack, which
+     *                             might be different from the stack bounds to allow more
+     *                             flexibility while resizing, or {@code null} if they should be the
+     *                             same as the stack bounds.
+     */
+    public void resizePinnedStack(Rect pinnedBounds, Rect tempPinnedTaskBounds) throws RemoteException;
     public void positionTaskInStack(int taskId, int stackId, int position) throws RemoteException;
     public List<StackInfo> getAllStackInfos() throws RemoteException;
     public StackInfo getStackInfo(int stackId) throws RemoteException;
@@ -305,9 +322,10 @@
         String packageName, boolean waitForDebugger, boolean persistent)
         throws RemoteException;
     public void setAlwaysFinish(boolean enabled) throws RemoteException;
-    public void setActivityController(IActivityController watcher)
+    public void setActivityController(IActivityController watcher, boolean imAMonkey)
         throws RemoteException;
     public void setLenientBackgroundCheck(boolean enabled) throws RemoteException;
+    public int getMemoryTrimLevel() throws RemoteException;
 
     public void enterSafeMode() throws RemoteException;
 
@@ -588,7 +606,10 @@
 
     public void enterPictureInPicture(IBinder token) throws RemoteException;
 
-    public void setVrMode(IBinder token, boolean enabled) throws RemoteException;
+    public int setVrMode(IBinder token, boolean enabled, ComponentName packageName)
+            throws RemoteException;
+
+    public boolean isVrModePackageEnabled(ComponentName packageName) throws RemoteException;
 
     public boolean isAppForeground(int uid) throws RemoteException;
 
@@ -980,4 +1001,8 @@
     int NOTIFY_PINNED_STACK_ANIMATION_ENDED_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 366;
     int REMOVE_STACK = IBinder.FIRST_CALL_TRANSACTION + 367;
     int SET_LENIENT_BACKGROUND_CHECK_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+368;
+    int GET_MEMORY_TRIM_LEVEL_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+369;
+    int RESIZE_PINNED_STACK_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 370;
+    int IS_VR_PACKAGE_ENABLED_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 371;
+    int SWAP_DOCKED_AND_FULLSCREEN_STACK = IBinder.FIRST_CALL_TRANSACTION + 372;
 }
diff --git a/core/java/android/app/IApplicationThread.java b/core/java/android/app/IApplicationThread.java
index b55da88..628bde0 100644
--- a/core/java/android/app/IApplicationThread.java
+++ b/core/java/android/app/IApplicationThread.java
@@ -123,8 +123,13 @@
     void dumpHeap(boolean managed, String path, ParcelFileDescriptor fd)
             throws RemoteException;
     void setSchedulingGroup(int group) throws RemoteException;
+    // the package has been removed, clean up internal references
     static final int PACKAGE_REMOVED = 0;
     static final int EXTERNAL_STORAGE_UNAVAILABLE = 1;
+    // the package is being modified in-place, don't kill it and retain references to it
+    static final int PACKAGE_REMOVED_DONT_KILL = 2;
+    // a previously removed package was replaced with a new version [eg. upgrade, split added, ...]
+    static final int PACKAGE_REPLACED = 3;
     void dispatchPackageBroadcast(int cmd, String[] packages) throws RemoteException;
     void scheduleCrash(String msg) throws RemoteException;
     void dumpActivity(FileDescriptor fd, IBinder servicetoken, String prefix, String[] args)
@@ -133,7 +138,8 @@
     void updatePackageCompatibilityInfo(String pkg, CompatibilityInfo info) throws RemoteException;
     void scheduleTrimMemory(int level) throws RemoteException;
     void dumpMemInfo(FileDescriptor fd, Debug.MemoryInfo mem, boolean checkin, boolean dumpInfo,
-            boolean dumpDalvik, boolean dumpSummaryOnly, String[] args) throws RemoteException;
+            boolean dumpDalvik, boolean dumpSummaryOnly, boolean dumpUnreachable,
+            String[] args) throws RemoteException;
     void dumpGfxInfo(FileDescriptor fd, String[] args) throws RemoteException;
     void dumpDbInfo(FileDescriptor fd, String[] args) throws RemoteException;
     void unstableProviderDied(IBinder provider) throws RemoteException;
diff --git a/core/java/android/app/INotificationManager.aidl b/core/java/android/app/INotificationManager.aidl
index 8be00aa..7a69c62 100644
--- a/core/java/android/app/INotificationManager.aidl
+++ b/core/java/android/app/INotificationManager.aidl
@@ -80,7 +80,7 @@
     void setOnNotificationPostedTrimFromListener(in INotificationListener token, int trim);
     void setInterruptionFilter(String pkg, int interruptionFilter);
 
-    void setImportanceFromAssistant(in INotificationListener token, String key, int importance, CharSequence explanation);
+    void setImportanceFromRankerService(in INotificationListener token, String key, int importance, CharSequence explanation);
 
     ComponentName getEffectsSuppressor();
     boolean matchesCallFilter(in Bundle extras);
@@ -97,9 +97,9 @@
     boolean isNotificationPolicyAccessGrantedForPackage(String pkg);
     void setNotificationPolicyAccessGranted(String pkg, boolean granted);
     AutomaticZenRule getAutomaticZenRule(String id);
-    List<AutomaticZenRule> getAutomaticZenRules();
-    AutomaticZenRule addAutomaticZenRule(in AutomaticZenRule automaticZenRule);
-    boolean updateAutomaticZenRule(in AutomaticZenRule automaticZenRule);
+    List<ZenModeConfig.ZenRule> getZenRules();
+    String addAutomaticZenRule(in AutomaticZenRule automaticZenRule);
+    boolean updateAutomaticZenRule(String id, in AutomaticZenRule automaticZenRule);
     boolean removeAutomaticZenRule(String id);
     boolean removeAutomaticZenRules(String packageName);
     int getRuleInstanceCount(in ComponentName owner);
diff --git a/core/java/android/app/LoadedApk.java b/core/java/android/app/LoadedApk.java
index 837ceb6..b8fc323 100644
--- a/core/java/android/app/LoadedApk.java
+++ b/core/java/android/app/LoadedApk.java
@@ -58,6 +58,7 @@
 import java.net.URL;
 import java.util.List;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collections;
 import java.util.Enumeration;
 import java.util.Objects;
@@ -83,24 +84,25 @@
     private static final String TAG = "LoadedApk";
 
     private final ActivityThread mActivityThread;
-    private ApplicationInfo mApplicationInfo;
     final String mPackageName;
-    private final String mAppDir;
-    private final String mResDir;
-    private final String[] mSplitAppDirs;
-    private final String[] mSplitResDirs;
-    private final String[] mOverlayDirs;
-    private final String[] mSharedLibraries;
-    private final String mDataDir;
-    private final String mLibDir;
-    private final File mDataDirFile;
-    private final File mDeviceEncryptedDataDirFile;
-    private final File mCredentialEncryptedDataDirFile;
+    private ApplicationInfo mApplicationInfo;
+    private String mAppDir;
+    private String mResDir;
+    private String[] mSplitAppDirs;
+    private String[] mSplitResDirs;
+    private String[] mOverlayDirs;
+    private String[] mSharedLibraries;
+    private String mDataDir;
+    private String mLibDir;
+    private File mDataDirFile;
+    private File mDeviceEncryptedDataDirFile;
+    private File mCredentialEncryptedDataDirFile;
     private final ClassLoader mBaseClassLoader;
     private final boolean mSecurityViolation;
     private final boolean mIncludeCode;
     private final boolean mRegisterPackage;
     private final DisplayAdjustments mDisplayAdjustments = new DisplayAdjustments();
+    /** WARNING: This may change. Don't hold external references to it. */
     Resources mResources;
     private ClassLoader mClassLoader;
     private Application mApplication;
@@ -129,23 +131,10 @@
     public LoadedApk(ActivityThread activityThread, ApplicationInfo aInfo,
             CompatibilityInfo compatInfo, ClassLoader baseLoader,
             boolean securityViolation, boolean includeCode, boolean registerPackage) {
-        final int myUid = Process.myUid();
-        aInfo = adjustNativeLibraryPaths(aInfo);
 
         mActivityThread = activityThread;
-        mApplicationInfo = aInfo;
+        setApplicationInfo(aInfo);
         mPackageName = aInfo.packageName;
-        mAppDir = aInfo.sourceDir;
-        mResDir = aInfo.uid == myUid ? aInfo.sourceDir : aInfo.publicSourceDir;
-        mSplitAppDirs = aInfo.splitSourceDirs;
-        mSplitResDirs = aInfo.uid == myUid ? aInfo.splitSourceDirs : aInfo.splitPublicSourceDirs;
-        mOverlayDirs = aInfo.resourceDirs;
-        mSharedLibraries = aInfo.sharedLibraryFiles;
-        mDataDir = aInfo.dataDir;
-        mDataDirFile = FileUtils.newFileOrNull(mDataDir);
-        mDeviceEncryptedDataDirFile = FileUtils.newFileOrNull(aInfo.deviceEncryptedDataDir);
-        mCredentialEncryptedDataDirFile = FileUtils.newFileOrNull(aInfo.credentialEncryptedDataDir);
-        mLibDir = aInfo.nativeLibraryDir;
         mBaseClassLoader = baseLoader;
         mSecurityViolation = securityViolation;
         mIncludeCode = includeCode;
@@ -225,6 +214,10 @@
         return mApplicationInfo;
     }
 
+    public int getTargetSdkVersion() {
+        return mApplicationInfo.targetSdkVersion;
+    }
+
     public boolean isSecurityViolation() {
         return mSecurityViolation;
     }
@@ -252,7 +245,7 @@
             ai = ActivityThread.getPackageManager().getApplicationInfo(packageName,
                     PackageManager.GET_SHARED_LIBRARY_FILES, UserHandle.myUserId());
         } catch (RemoteException e) {
-            throw new AssertionError(e);
+            throw e.rethrowFromSystemServer();
         }
 
         if (ai == null) {
@@ -262,129 +255,189 @@
         return ai.sharedLibraryFiles;
     }
 
-    public ClassLoader getClassLoader() {
-        synchronized (this) {
-            if (mClassLoader != null) {
-                return mClassLoader;
-            }
+    public void updateApplicationInfo(ApplicationInfo aInfo, List<String> oldPaths) {
+        setApplicationInfo(aInfo);
 
-            if (mPackageName.equals("android")) {
-                if (mBaseClassLoader == null) {
-                    mClassLoader = ClassLoader.getSystemClassLoader();
-                } else {
-                    mClassLoader = mBaseClassLoader;
+        final List<String> newPaths = new ArrayList<>();
+        makePaths(mActivityThread, aInfo, newPaths, null /*libPaths*/);
+        final List<String> addedPaths = new ArrayList<>(newPaths.size());
+
+        if (oldPaths != null) {
+            for (String path : newPaths) {
+                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));
+                    if (apkName.equals(oldApkName)) {
+                        match = true;
+                        break;
+                    }
                 }
-                return mClassLoader;
+                if (!match) {
+                    addedPaths.add(path);
+                }
+            }
+        } else {
+            addedPaths.addAll(newPaths);
+        }
+        synchronized (this) {
+            mClassLoader = createOrUpdateClassLoaderLocked(addedPaths);
+            if (mResources != null) {
+                mResources = mActivityThread.getTopLevelResources(mResDir, mSplitResDirs,
+                        mOverlayDirs, mApplicationInfo.sharedLibraryFiles, Display.DEFAULT_DISPLAY,
+                        this);
+            }
+        }
+    }
+
+    private void setApplicationInfo(ApplicationInfo aInfo) {
+        final int myUid = Process.myUid();
+        aInfo = adjustNativeLibraryPaths(aInfo);
+        mApplicationInfo = aInfo;
+        mAppDir = aInfo.sourceDir;
+        mResDir = aInfo.uid == myUid ? aInfo.sourceDir : aInfo.publicSourceDir;
+        mSplitAppDirs = aInfo.splitSourceDirs;
+        mSplitResDirs = aInfo.uid == myUid ? aInfo.splitSourceDirs : aInfo.splitPublicSourceDirs;
+        mOverlayDirs = aInfo.resourceDirs;
+        mSharedLibraries = aInfo.sharedLibraryFiles;
+        mDataDir = aInfo.dataDir;
+        mLibDir = aInfo.nativeLibraryDir;
+        mDataDirFile = FileUtils.newFileOrNull(aInfo.dataDir);
+        mDeviceEncryptedDataDirFile = FileUtils.newFileOrNull(aInfo.deviceEncryptedDataDir);
+        mCredentialEncryptedDataDirFile = FileUtils.newFileOrNull(aInfo.credentialEncryptedDataDir);
+    }
+
+    public static void makePaths(ActivityThread activityThread, ApplicationInfo aInfo,
+            List<String> outZipPaths, List<String> outLibPaths) {
+        final String appDir = aInfo.sourceDir;
+        final String[] splitAppDirs = aInfo.splitSourceDirs;
+        final String libDir = aInfo.nativeLibraryDir;
+        final String[] sharedLibraries = aInfo.sharedLibraryFiles;
+
+        outZipPaths.clear();
+        outZipPaths.add(appDir);
+        if (splitAppDirs != null) {
+            Collections.addAll(outZipPaths, splitAppDirs);
+        }
+
+        if (outLibPaths != null) {
+            outLibPaths.clear();
+        }
+
+        /*
+         * The following is a bit of a hack to inject
+         * instrumentation into the system: If the app
+         * being started matches one of the instrumentation names,
+         * then we combine both the "instrumentation" and
+         * "instrumented" app into the path, along with the
+         * concatenation of both apps' shared library lists.
+         */
+
+        String instrumentationPackageName = activityThread.mInstrumentationPackageName;
+        String instrumentationAppDir = activityThread.mInstrumentationAppDir;
+        String[] instrumentationSplitAppDirs = activityThread.mInstrumentationSplitAppDirs;
+        String instrumentationLibDir = activityThread.mInstrumentationLibDir;
+
+        String instrumentedAppDir = activityThread.mInstrumentedAppDir;
+        String[] instrumentedSplitAppDirs = activityThread.mInstrumentedSplitAppDirs;
+        String instrumentedLibDir = activityThread.mInstrumentedLibDir;
+        String[] instrumentationLibs = null;
+
+        if (appDir.equals(instrumentationAppDir)
+                || appDir.equals(instrumentedAppDir)) {
+            outZipPaths.clear();
+            outZipPaths.add(instrumentationAppDir);
+            if (instrumentationSplitAppDirs != null) {
+                Collections.addAll(outZipPaths, instrumentationSplitAppDirs);
+            }
+            outZipPaths.add(instrumentedAppDir);
+            if (instrumentedSplitAppDirs != null) {
+                Collections.addAll(outZipPaths, instrumentedSplitAppDirs);
             }
 
+            if (outLibPaths != null) {
+                outLibPaths.add(instrumentationLibDir);
+                outLibPaths.add(instrumentedLibDir);
+            }
+
+            if (!instrumentedAppDir.equals(instrumentationAppDir)) {
+                instrumentationLibs = getLibrariesFor(instrumentationPackageName);
+            }
+        }
+
+        if (outLibPaths != null) {
+            if (outLibPaths.isEmpty()) {
+                outLibPaths.add(libDir);
+            }
+
+            // Add path to libraries in apk for current abi. Do this now because more entries
+            // will be added to zipPaths that shouldn't be part of the library path.
+            if (aInfo.primaryCpuAbi != null) {
+                for (String apk : outZipPaths) {
+                    outLibPaths.add(apk + "!/lib/" + aInfo.primaryCpuAbi);
+                }
+            }
+
+            if (aInfo.isSystemApp() && !aInfo.isUpdatedSystemApp()) {
+                // Add path to system libraries to libPaths;
+                // Access to system libs should be limited
+                // to bundled applications; this is why updated
+                // system apps are not included.
+                outLibPaths.add(System.getProperty("java.library.path"));
+            }
+        }
+
+        if (sharedLibraries != null) {
+            for (String lib : sharedLibraries) {
+                if (!outZipPaths.contains(lib)) {
+                    outZipPaths.add(0, lib);
+                }
+            }
+        }
+
+        if (instrumentationLibs != null) {
+            for (String lib : instrumentationLibs) {
+                if (!outZipPaths.contains(lib)) {
+                    outZipPaths.add(0, lib);
+                }
+            }
+        }
+
+        final String zip = TextUtils.join(File.pathSeparator, outZipPaths);
+    }
+
+    private ClassLoader createOrUpdateClassLoaderLocked(List<String> addedPaths) {
+        final ClassLoader classLoader;
+        if (mIncludeCode && !mPackageName.equals("android")) {
             // Avoid the binder call when the package is the current application package.
             // The activity manager will perform ensure that dexopt is performed before
             // spinning up the process.
             if (!Objects.equals(mPackageName, ActivityThread.currentPackageName())) {
-                final String isa = VMRuntime.getRuntime().vmInstructionSet();
+                VMRuntime.getRuntime().vmInstructionSet();
                 try {
                     ActivityThread.getPackageManager().notifyPackageUse(mPackageName);
                 } catch (RemoteException re) {
-                    // Ignored.
+                    throw re.rethrowFromSystemServer();
                 }
             }
 
             final List<String> zipPaths = new ArrayList<>();
-            final List<String> apkPaths = new ArrayList<>();
             final List<String> libPaths = new ArrayList<>();
 
             if (mRegisterPackage) {
                 try {
                     ActivityManagerNative.getDefault().addPackageDependency(mPackageName);
                 } catch (RemoteException e) {
+                    throw e.rethrowFromSystemServer();
                 }
             }
 
-            zipPaths.add(mAppDir);
-            if (mSplitAppDirs != null) {
-                Collections.addAll(zipPaths, mSplitAppDirs);
-            }
-
-            libPaths.add(mLibDir);
-
-            /*
-             * The following is a bit of a hack to inject
-             * instrumentation into the system: If the app
-             * being started matches one of the instrumentation names,
-             * then we combine both the "instrumentation" and
-             * "instrumented" app into the path, along with the
-             * concatenation of both apps' shared library lists.
-             */
-
-            String instrumentationPackageName = mActivityThread.mInstrumentationPackageName;
-            String instrumentationAppDir = mActivityThread.mInstrumentationAppDir;
-            String[] instrumentationSplitAppDirs = mActivityThread.mInstrumentationSplitAppDirs;
-            String instrumentationLibDir = mActivityThread.mInstrumentationLibDir;
-
-            String instrumentedAppDir = mActivityThread.mInstrumentedAppDir;
-            String[] instrumentedSplitAppDirs = mActivityThread.mInstrumentedSplitAppDirs;
-            String instrumentedLibDir = mActivityThread.mInstrumentedLibDir;
-            String[] instrumentationLibs = null;
-
-            if (mAppDir.equals(instrumentationAppDir)
-                    || mAppDir.equals(instrumentedAppDir)) {
-                zipPaths.clear();
-                zipPaths.add(instrumentationAppDir);
-                if (instrumentationSplitAppDirs != null) {
-                    Collections.addAll(zipPaths, instrumentationSplitAppDirs);
-                }
-                zipPaths.add(instrumentedAppDir);
-                if (instrumentedSplitAppDirs != null) {
-                    Collections.addAll(zipPaths, instrumentedSplitAppDirs);
-                }
-
-                libPaths.clear();
-                libPaths.add(instrumentationLibDir);
-                libPaths.add(instrumentedLibDir);
-
-                if (!instrumentedAppDir.equals(instrumentationAppDir)) {
-                    instrumentationLibs = getLibrariesFor(instrumentationPackageName);
-                }
-            }
-
-            apkPaths.addAll(zipPaths);
-
-            if (mSharedLibraries != null) {
-                for (String lib : mSharedLibraries) {
-                    if (!zipPaths.contains(lib)) {
-                        zipPaths.add(0, lib);
-                    }
-                }
-            }
-
-            if (instrumentationLibs != null) {
-                for (String lib : instrumentationLibs) {
-                    if (!zipPaths.contains(lib)) {
-                        zipPaths.add(0, lib);
-                    }
-                }
-            }
-
-            final String zip = mIncludeCode ? TextUtils.join(File.pathSeparator, zipPaths) : "";
-
-            // Add path to libraries in apk for current abi
-            if (mApplicationInfo.primaryCpuAbi != null) {
-                for (String apk : apkPaths) {
-                  libPaths.add(apk + "!/lib/" + mApplicationInfo.primaryCpuAbi);
-                }
-            }
-
+            makePaths(mActivityThread, mApplicationInfo, zipPaths, libPaths);
+            final String zip = TextUtils.join(File.pathSeparator, zipPaths);
+            final boolean isBundledApp = mApplicationInfo.isSystemApp()
+                    && !mApplicationInfo.isUpdatedSystemApp();
             String libraryPermittedPath = mDataDir;
-            boolean isBundledApp = false;
-
-            if (mApplicationInfo.isSystemApp()) {
-                isBundledApp = true;
-                // Add path to system libraries to libPaths;
-                // Access to system libs should be limited
-                // to bundled applications; this is why updated
-                // system apps are not included.
-                libPaths.add(System.getProperty("java.library.path"));
-
+            if (isBundledApp) {
                 // This is necessary to grant bundled apps access to
                 // libraries located in subdirectories of /system/lib
                 libraryPermittedPath += File.pathSeparator +
@@ -409,14 +462,42 @@
                 Slog.v(ActivityThread.TAG, "Class path: " + zip +
                         ", JNI path: " + librarySearchPath);
 
-            // Temporarily disable logging of disk reads on the Looper thread
-            // as this is early and necessary.
-            StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads();
+            if (mClassLoader == null) {
+                // Temporarily disable logging of disk reads on the Looper thread
+                // as this is early and necessary.
+                StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads();
 
-            mClassLoader = ApplicationLoaders.getDefault().getClassLoader(zip, isBundledApp,
-                    librarySearchPath, libraryPermittedPath, mBaseClassLoader);
+                classLoader = ApplicationLoaders.getDefault().getClassLoader(zip,
+                        mApplicationInfo.targetSdkVersion, isBundledApp, librarySearchPath,
+                        libraryPermittedPath, mBaseClassLoader);
 
-            StrictMode.setThreadPolicy(oldPolicy);
+                StrictMode.setThreadPolicy(oldPolicy);
+            } else if (addedPaths != null && addedPaths.size() > 0) {
+                final String add = TextUtils.join(File.pathSeparator, addedPaths);
+                ApplicationLoaders.getDefault().addPath(mClassLoader, add);
+                classLoader = mClassLoader;
+            } else {
+                classLoader = mClassLoader;
+            }
+        } else {
+            if (mClassLoader == null) {
+                if (mBaseClassLoader == null) {
+                    classLoader = ClassLoader.getSystemClassLoader();
+                } else {
+                    classLoader = mBaseClassLoader;
+                }
+            } else {
+                classLoader = mClassLoader;
+            }
+        }
+        return classLoader;
+    }
+
+    public ClassLoader getClassLoader() {
+        synchronized (this) {
+            if (mClassLoader == null) {
+                mClassLoader = createOrUpdateClassLoaderLocked(null /*addedPaths*/);
+            }
             return mClassLoader;
         }
     }
@@ -451,8 +532,7 @@
             pi = pm.getPackageInfo(mPackageName, PackageManager.MATCH_DEBUG_TRIAGED_MISSING,
                     UserHandle.myUserId());
         } catch (RemoteException e) {
-            throw new IllegalStateException("Unable to get package info for "
-                    + mPackageName + "; is system dying?", e);
+            throw e.rethrowFromSystemServer();
         }
         if (pi == null) {
             throw new IllegalStateException("Unable to get package info for "
@@ -588,7 +668,7 @@
     public Resources getResources(ActivityThread mainThread) {
         if (mResources == null) {
             mResources = mainThread.getTopLevelResources(mResDir, mSplitResDirs, mOverlayDirs,
-                    mApplicationInfo.sharedLibraryFiles, Display.DEFAULT_DISPLAY, null, this);
+                    mApplicationInfo.sharedLibraryFiles, Display.DEFAULT_DISPLAY, this);
         }
         return mResources;
     }
@@ -709,7 +789,7 @@
                         ActivityManagerNative.getDefault().unregisterReceiver(
                                 rd.getIIntentReceiver());
                     } catch (RemoteException e) {
-                        // system crashed, nothing we can do
+                        throw e.rethrowFromSystemServer();
                     }
                 }
             }
@@ -735,7 +815,7 @@
                         ActivityManagerNative.getDefault().unbindService(
                                 sd.getIServiceConnection());
                     } catch (RemoteException e) {
-                        // system crashed, nothing we can do
+                        throw e.rethrowFromSystemServer();
                     }
                     sd.doForget();
                 }
@@ -860,7 +940,7 @@
                         }
                         mgr.finishReceiver(this, resultCode, data, extras, false, intent.getFlags());
                     } catch (RemoteException e) {
-                        Slog.w(ActivityThread.TAG, "Couldn't finish broadcast to unregistered receiver");
+                        throw e.rethrowFromSystemServer();
                     }
                 }
             }
@@ -1098,7 +1178,6 @@
 
         private RuntimeException mUnbindLocation;
 
-        private boolean mDied;
         private boolean mForgotten;
 
         private static class ConnectionInfo {
@@ -1197,7 +1276,6 @@
             ServiceDispatcher.ConnectionInfo old;
 
             synchronized (this) {
-                mDied = true;
                 old = mActiveConnections.remove(name);
                 if (old == null || old.binder != service) {
                     // Death for someone different than who we last
@@ -1232,7 +1310,6 @@
 
                 if (service != null) {
                     // A new service is being connected... set it all up.
-                    mDied = false;
                     info = new ConnectionInfo();
                     info.binder = service;
                     info.deathMonitor = new DeathMonitor(name, service);
diff --git a/core/java/android/app/LocalActivityManager.java b/core/java/android/app/LocalActivityManager.java
index 873e337..2a1e3c2 100644
--- a/core/java/android/app/LocalActivityManager.java
+++ b/core/java/android/app/LocalActivityManager.java
@@ -144,7 +144,7 @@
             
             if (desiredState == RESUMED) {
                 if (localLOGV) Log.v(TAG, r.id + ": resuming");
-                mActivityThread.performResumeActivity(r, true);
+                mActivityThread.performResumeActivity(r, true, "moveToState-INITIALIZING");
                 r.curState = RESUMED;
             }
             
@@ -167,7 +167,7 @@
                 if (desiredState == RESUMED) {
                     if (localLOGV) Log.v(TAG, r.id + ": restarting and resuming");
                     mActivityThread.performRestartActivity(r);
-                    mActivityThread.performResumeActivity(r, true);
+                    mActivityThread.performResumeActivity(r, true, "moveToState-CREATED");
                     r.curState = RESUMED;
                 }
                 return;
@@ -176,13 +176,13 @@
                 if (desiredState == RESUMED) {
                     // Need to resume it...
                     if (localLOGV) Log.v(TAG, r.id + ": resuming");
-                    mActivityThread.performResumeActivity(r, true);
+                    mActivityThread.performResumeActivity(r, true, "moveToState-STARTED");
                     r.instanceState = null;
                     r.curState = RESUMED;
                 }
                 if (desiredState == CREATED) {
                     if (localLOGV) Log.v(TAG, r.id + ": stopping");
-                    mActivityThread.performStopActivity(r, false);
+                    mActivityThread.performStopActivity(r, false, "moveToState-STARTED");
                     r.curState = CREATED;
                 }
                 return;
@@ -197,7 +197,7 @@
                     if (localLOGV) Log.v(TAG, r.id + ": pausing");
                     performPause(r, mFinishing);
                     if (localLOGV) Log.v(TAG, r.id + ": stopping");
-                    mActivityThread.performStopActivity(r, false);
+                    mActivityThread.performStopActivity(r, false, "moveToState-RESUMED");
                     r.curState = CREATED;
                 }
                 return;
@@ -205,9 +205,9 @@
     }
     
     private void performPause(LocalActivityRecord r, boolean finishing) {
-        boolean needState = r.instanceState == null;
-        Bundle instanceState = mActivityThread.performPauseActivity(r,
-                finishing, needState);
+        final boolean needState = r.instanceState == null;
+        final Bundle instanceState = mActivityThread.performPauseActivity(
+                r, finishing, needState, "performPause");
         if (needState) {
             r.instanceState = instanceState;
         }
diff --git a/core/java/android/app/MediaRouteButton.java b/core/java/android/app/MediaRouteButton.java
index 181c907..70a5e15 100644
--- a/core/java/android/app/MediaRouteButton.java
+++ b/core/java/android/app/MediaRouteButton.java
@@ -19,6 +19,7 @@
 import com.android.internal.R;
 import com.android.internal.app.MediaRouteDialogPresenter;
 
+import android.annotation.NonNull;
 import android.content.Context;
 import android.content.ContextWrapper;
 import android.content.res.TypedArray;
@@ -279,7 +280,7 @@
     }
 
     @Override
-    protected boolean verifyDrawable(Drawable who) {
+    protected boolean verifyDrawable(@NonNull Drawable who) {
         return super.verifyDrawable(who) || who == mRemoteIndicator;
     }
 
diff --git a/core/java/android/app/NativeActivity.java b/core/java/android/app/NativeActivity.java
index 3c7f48b..b6e0467 100644
--- a/core/java/android/app/NativeActivity.java
+++ b/core/java/android/app/NativeActivity.java
@@ -95,8 +95,7 @@
     
     private native long loadNativeCode(String path, String funcname, MessageQueue queue,
             String internalDataPath, String obbPath, String externalDataPath, int sdkVersion,
-            AssetManager assetMgr, byte[] savedState, ClassLoader classLoader, String libraryPath,
-            String isolationPath);
+            AssetManager assetMgr, byte[] savedState, ClassLoader classLoader, String libraryPath);
     private native String getDlError();
     private native void unloadNativeCode(long handle);
     private native void onStartNative(long handle);
@@ -177,8 +176,7 @@
                 getAbsolutePath(getFilesDir()), getAbsolutePath(getObbDir()),
                 getAbsolutePath(getExternalFilesDir(null)),
                 Build.VERSION.SDK_INT, getAssets(), nativeSavedState,
-                classLoader, classLoader.getLdLibraryPath(),
-                classLoader.getLibraryPermittedPath());
+                classLoader, classLoader.getLdLibraryPath());
 
         if (mNativeHandle == 0) {
             throw new UnsatisfiedLinkError(
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 402c112..88c8964 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -21,7 +21,6 @@
 import android.annotation.IntDef;
 import android.annotation.SdkConstant;
 import android.annotation.SdkConstant.SdkConstantType;
-import android.annotation.SystemApi;
 import android.content.Context;
 import android.content.Intent;
 import android.content.pm.ApplicationInfo;
@@ -44,7 +43,13 @@
 import android.os.Parcelable;
 import android.os.SystemClock;
 import android.os.UserHandle;
+import android.text.SpannableStringBuilder;
+import android.text.Spanned;
 import android.text.TextUtils;
+import android.text.style.AbsoluteSizeSpan;
+import android.text.style.CharacterStyle;
+import android.text.style.RelativeSizeSpan;
+import android.text.style.TextAppearanceSpan;
 import android.util.Log;
 import android.util.SparseArray;
 import android.util.TypedValue;
@@ -65,7 +70,6 @@
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.List;
-import java.util.Objects;
 import java.util.Set;
 
 /**
@@ -823,6 +827,12 @@
     public static final String EXTRA_SHOW_CHRONOMETER = "android.showChronometer";
 
     /**
+     * {@link #extras} key: whether the chronometer set on the notification should count down
+     * instead of counting up. Is only relevant if key {@link #EXTRA_SHOW_CHRONOMETER} is present.
+     */
+    public static final String EXTRA_CHRONOMETER_COUNTS_DOWN = "android.chronometerCountsDown";
+
+    /**
      * {@link #extras} key: whether {@link #when} should be shown,
      * as supplied to {@link Builder#setShowWhen(boolean)}.
      */
@@ -1645,8 +1655,39 @@
                     + " instance is a custom Parcelable and not allowed in Notification");
             return cs.toString();
         }
+        return removeTextSizeSpans(cs);
+    }
 
-        return cs;
+    private static CharSequence removeTextSizeSpans(CharSequence charSequence) {
+        if (charSequence instanceof Spanned) {
+            Spanned ss = (Spanned) charSequence;
+            Object[] spans = ss.getSpans(0, ss.length(), Object.class);
+            SpannableStringBuilder builder = new SpannableStringBuilder(ss.toString());
+            for (Object span : spans) {
+                Object resultSpan = span;
+                if (resultSpan instanceof CharacterStyle) {
+                    resultSpan = ((CharacterStyle) span).getUnderlying();
+                }
+                if (resultSpan instanceof TextAppearanceSpan) {
+                    TextAppearanceSpan originalSpan = (TextAppearanceSpan) resultSpan;
+                    resultSpan = new TextAppearanceSpan(
+                            originalSpan.getFamily(),
+                            originalSpan.getTextStyle(),
+                            -1,
+                            originalSpan.getTextColor(),
+                            originalSpan.getLinkTextColor());
+                } else if (resultSpan instanceof RelativeSizeSpan
+                        || resultSpan instanceof AbsoluteSizeSpan) {
+                    continue;
+                } else {
+                    resultSpan = span;
+                }
+                builder.setSpan(resultSpan, ss.getSpanStart(span), ss.getSpanEnd(span),
+                        ss.getSpanFlags(span));
+            }
+            return builder;
+        }
+        return charSequence;
     }
 
     public int describeContents() {
@@ -2158,8 +2199,12 @@
          *
          * Useful when showing an elapsed time (like an ongoing phone call).
          *
+         * The counter can also be set to count down to <code>when</code> when using
+         * {@link #setChronometerCountsDown(boolean)}.
+         *
          * @see android.widget.Chronometer
          * @see Notification#when
+         * @see #setChronometerCountsDown(boolean)
          */
         public Builder setUsesChronometer(boolean b) {
             mN.extras.putBoolean(EXTRA_SHOW_CHRONOMETER, b);
@@ -2167,6 +2212,19 @@
         }
 
         /**
+         * Sets the Chronometer to count down instead of counting up.
+         *
+         * <p>This is only relevant if {@link #setUsesChronometer(boolean)} has been set to true.
+         * If it isn't set the chronometer will count up.
+         *
+         * @see #setUsesChronometer(boolean)
+         */
+        public Builder setChronometerCountsDown(boolean countsDown) {
+            mN.extras.putBoolean(EXTRA_CHRONOMETER_COUNTS_DOWN, countsDown);
+            return this;
+        }
+
+        /**
          * Set the small icon resource, which will be used to represent the notification in the
          * status bar.
          *
@@ -2942,7 +3000,6 @@
             contentView.setViewVisibility(R.id.chronometer, View.GONE);
             contentView.setViewVisibility(R.id.header_sub_text, View.GONE);
             contentView.setViewVisibility(R.id.header_content_info, View.GONE);
-            contentView.setViewVisibility(R.id.number_of_children, View.GONE);
             contentView.setViewVisibility(R.id.sub_text_divider, View.GONE);
             contentView.setViewVisibility(R.id.content_info_divider, View.GONE);
             contentView.setViewVisibility(R.id.time_divider, View.GONE);
@@ -3043,7 +3100,6 @@
 
         private void bindNotificationHeader(RemoteViews contentView) {
             bindSmallIcon(contentView);
-            bindChildCountColor(contentView);
             bindHeaderAppName(contentView);
             bindHeaderSubText(contentView);
             bindContentInfo(contentView);
@@ -3052,10 +3108,6 @@
             bindProfileBadge(contentView);
         }
 
-        private void bindChildCountColor(RemoteViews contentView) {
-            contentView.setTextColor(R.id.number_of_children, resolveColor());
-        }
-
         private void bindContentInfo(RemoteViews contentView) {
             boolean visible = false;
             if (mN.extras.getCharSequence(EXTRA_INFO_TEXT) != null) {
@@ -3097,6 +3149,8 @@
                     contentView.setLong(R.id.chronometer, "setBase",
                             mN.when + (SystemClock.elapsedRealtime() - System.currentTimeMillis()));
                     contentView.setBoolean(R.id.chronometer, "setStarted", true);
+                    boolean countsDown = mN.extras.getBoolean(EXTRA_CHRONOMETER_COUNTS_DOWN);
+                    contentView.setChronometerCountsDown(R.id.chronometer, countsDown);
                 } else {
                     contentView.setViewVisibility(R.id.time, View.VISIBLE);
                     contentView.setLong(R.id.time, "setTime", mN.when);
@@ -3233,7 +3287,7 @@
          *   2. Style's proposed content view
          *   3. Standard template view
          */
-        public RemoteViews makeContentView() {
+        public RemoteViews createContentView() {
             if (mN.contentView != null && (mStyle == null || !mStyle.displayCustomViewInline())) {
                 return mN.contentView;
             } else if (mStyle != null) {
@@ -3248,7 +3302,7 @@
         /**
          * Construct a RemoteViews for the final big notification layout.
          */
-        public RemoteViews makeBigContentView() {
+        public RemoteViews createBigContentView() {
             RemoteViews result = null;
             if (mN.bigContentView != null
                     && (mStyle == null || !mStyle.displayCustomViewInline())) {
@@ -3291,7 +3345,7 @@
         /**
          * Construct a RemoteViews for the final heads-up notification layout.
          */
-        public RemoteViews makeHeadsUpContentView() {
+        public RemoteViews createHeadsUpContentView() {
             if (mN.headsUpContentView != null
                     && (mStyle == null ||  !mStyle.displayCustomViewInline())) {
                 return mN.headsUpContentView;
@@ -3304,7 +3358,6 @@
                 return null;
             }
 
-
             return applyStandardTemplateWithActions(getBigBaseLayoutResource());
         }
 
@@ -3316,7 +3369,7 @@
         public RemoteViews makePublicContentView() {
             if (mN.publicVersion != null) {
                 final Builder builder = recoverBuilder(mContext, mN.publicVersion);
-                return builder.makeContentView();
+                return builder.createContentView();
             }
             Bundle savedBundle = mN.extras;
             Style style = mStyle;
@@ -3328,6 +3381,8 @@
                     savedBundle.getBoolean(EXTRA_SHOW_WHEN));
             publicExtras.putBoolean(EXTRA_SHOW_CHRONOMETER,
                     savedBundle.getBoolean(EXTRA_SHOW_CHRONOMETER));
+            publicExtras.putBoolean(EXTRA_CHRONOMETER_COUNTS_DOWN,
+                    savedBundle.getBoolean(EXTRA_CHRONOMETER_COUNTS_DOWN));
             publicExtras.putCharSequence(EXTRA_TITLE,
                     mContext.getString(R.string.notification_hidden_text));
             mN.extras = publicExtras;
@@ -3437,6 +3492,11 @@
             return mN;
         }
 
+        /**
+         * Creates a Builder from an existing notification so further changes can be made.
+         * @param context The context for your application / activity.
+         * @param n The notification to create a Builder from.
+         */
         public static Notification.Builder recoverBuilder(Context context, Notification n) {
             // Re-create notification context so we can access app resources.
             ApplicationInfo applicationInfo = n.extras.getParcelable(
@@ -3496,21 +3556,22 @@
                 mStyle.buildStyled(mN);
             }
 
-            if (mContext.getApplicationInfo().targetSdkVersion < Build.VERSION_CODES.N) {
+            if (mContext.getApplicationInfo().targetSdkVersion < Build.VERSION_CODES.N
+                    && (mStyle == null || !mStyle.displayCustomViewInline())) {
                 if (mN.contentView == null) {
-                    mN.contentView = makeContentView();
+                    mN.contentView = createContentView();
                     mN.extras.putInt(EXTRA_REBUILD_CONTENT_VIEW_ACTION_COUNT,
                             mN.contentView.getSequenceNumber());
                 }
                 if (mN.bigContentView == null) {
-                    mN.bigContentView = makeBigContentView();
+                    mN.bigContentView = createBigContentView();
                     if (mN.bigContentView != null) {
                         mN.extras.putInt(EXTRA_REBUILD_BIG_CONTENT_VIEW_ACTION_COUNT,
                                 mN.bigContentView.getSequenceNumber());
                     }
                 }
                 if (mN.headsUpContentView == null) {
-                    mN.headsUpContentView = makeHeadsUpContentView();
+                    mN.headsUpContentView = createHeadsUpContentView();
                     if (mN.headsUpContentView != null) {
                         mN.extras.putInt(EXTRA_REBUILD_HEADS_UP_CONTENT_VIEW_ACTION_COUNT,
                                 mN.headsUpContentView.getSequenceNumber());
@@ -3536,37 +3597,53 @@
         }
 
         /**
+         * Removes RemoteViews that were created for compatibility from {@param n}, if they did not
+         * change.
+         *
+         * @return {@param n}, if no stripping is needed, otherwise a stripped clone of {@param n}.
+         *
          * @hide
          */
-        public static void stripForDelivery(Notification n) {
+        public static Notification maybeCloneStrippedForDelivery(Notification n) {
             String templateClass = n.extras.getString(EXTRA_TEMPLATE);
-            if (TextUtils.isEmpty(templateClass)) {
-                return;
-            }
+
             // Only strip views for known Styles because we won't know how to
             // re-create them otherwise.
-            if (getNotificationStyleClass(templateClass) == null) {
-                return;
+            if (!TextUtils.isEmpty(templateClass)
+                    && getNotificationStyleClass(templateClass) == null) {
+                return n;
             }
-            // Get rid of unmodified BuilderRemoteViews.
-            if (n.contentView instanceof BuilderRemoteViews &&
+
+            // Only strip unmodified BuilderRemoteViews.
+            boolean stripContentView = n.contentView instanceof BuilderRemoteViews &&
                     n.extras.getInt(EXTRA_REBUILD_CONTENT_VIEW_ACTION_COUNT, -1) ==
-                            n.contentView.getSequenceNumber()) {
-                n.contentView = null;
-                n.extras.remove(EXTRA_REBUILD_CONTENT_VIEW_ACTION_COUNT);
-            }
-            if (n.bigContentView instanceof BuilderRemoteViews &&
+                            n.contentView.getSequenceNumber();
+            boolean stripBigContentView = n.bigContentView instanceof BuilderRemoteViews &&
                     n.extras.getInt(EXTRA_REBUILD_BIG_CONTENT_VIEW_ACTION_COUNT, -1) ==
-                            n.bigContentView.getSequenceNumber()) {
-                n.bigContentView = null;
-                n.extras.remove(EXTRA_REBUILD_BIG_CONTENT_VIEW_ACTION_COUNT);
-            }
-            if (n.headsUpContentView instanceof BuilderRemoteViews &&
+                            n.bigContentView.getSequenceNumber();
+            boolean stripHeadsUpContentView = n.headsUpContentView instanceof BuilderRemoteViews &&
                     n.extras.getInt(EXTRA_REBUILD_HEADS_UP_CONTENT_VIEW_ACTION_COUNT, -1) ==
-                            n.headsUpContentView.getSequenceNumber()) {
-                n.headsUpContentView = null;
-                n.extras.remove(EXTRA_REBUILD_HEADS_UP_CONTENT_VIEW_ACTION_COUNT);
+                            n.headsUpContentView.getSequenceNumber();
+
+            // Nothing to do here, no need to clone.
+            if (!stripContentView && !stripBigContentView && !stripHeadsUpContentView) {
+                return n;
             }
+
+            Notification clone = n.clone();
+            if (stripContentView) {
+                clone.contentView = null;
+                clone.extras.remove(EXTRA_REBUILD_CONTENT_VIEW_ACTION_COUNT);
+            }
+            if (stripBigContentView) {
+                clone.bigContentView = null;
+                clone.extras.remove(EXTRA_REBUILD_BIG_CONTENT_VIEW_ACTION_COUNT);
+            }
+            if (stripHeadsUpContentView) {
+                clone.headsUpContentView = null;
+                clone.extras.remove(EXTRA_REBUILD_HEADS_UP_CONTENT_VIEW_ACTION_COUNT);
+            }
+            return clone;
         }
 
         private int getBaseLayoutResource() {
@@ -4145,7 +4222,8 @@
             int i=0;
             final float density = mBuilder.mContext.getResources().getDisplayMetrics().density;
             int topPadding = (int) (5 * density);
-            int bottomPadding = (int) (13 * density);
+            int bottomPadding = mBuilder.mContext.getResources().getDimensionPixelSize(
+                    com.android.internal.R.dimen.notification_content_margin_bottom);
             boolean first = true;
             while (i < mTexts.size() && i < rowIds.length) {
                 CharSequence str = mTexts.get(i);
@@ -4510,6 +4588,11 @@
         private void buildIntoRemoteViewContent(RemoteViews remoteViews,
                 RemoteViews customContent) {
             remoteViews.removeAllViews(R.id.notification_main_column);
+            // Need to clone customContent before adding, because otherwise it can no longer be
+            // parceled independently of remoteViews.
+            if (customContent != null) {
+                customContent = customContent.clone();
+            }
             remoteViews.addView(R.id.notification_main_column, customContent);
             // also update the end margin if there is an image
             int endMargin = mBuilder.mContext.getResources().getDimensionPixelSize(
@@ -4614,6 +4697,11 @@
         private RemoteViews buildIntoRemoteView(RemoteViews remoteViews, int id,
                 RemoteViews customContent) {
             remoteViews.removeAllViews(id);
+            // Need to clone customContent before adding, because otherwise it can no longer be
+            // parceled independently of remoteViews.
+            if (customContent != null) {
+                customContent = customContent.clone();
+            }
             remoteViews.addView(id, customContent);
             return remoteViews;
         }
diff --git a/core/java/android/app/NotificationManager.java b/core/java/android/app/NotificationManager.java
index 324a0ab..10aa7eb 100644
--- a/core/java/android/app/NotificationManager.java
+++ b/core/java/android/app/NotificationManager.java
@@ -18,6 +18,7 @@
 
 import com.android.internal.util.Preconditions;
 
+import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SdkConstant;
@@ -45,8 +46,14 @@
 import android.util.ArraySet;
 import android.util.Log;
 
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
 import java.util.Objects;
 import java.util.List;
+import java.util.Set;
 
 /**
  * Class to notify the user of events that happen.  This is how you tell
@@ -138,6 +145,12 @@
     public static final String ACTION_INTERRUPTION_FILTER_CHANGED_INTERNAL
             = "android.app.action.INTERRUPTION_FILTER_CHANGED_INTERNAL";
 
+    /** @hide */
+    @IntDef({INTERRUPTION_FILTER_NONE, INTERRUPTION_FILTER_PRIORITY, INTERRUPTION_FILTER_ALARMS,
+            INTERRUPTION_FILTER_ALL, INTERRUPTION_FILTER_UNKNOWN})
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface InterruptionFilter {}
+
     /**
      * {@link #getCurrentInterruptionFilter() Interruption filter} constant -
      *     Normal interruption filter.
@@ -245,8 +258,7 @@
             }
         }
         if (localLOGV) Log.v(TAG, pkg + ": notify(" + id + ", " + notification + ")");
-        final Notification copy = notification.clone();
-        Builder.stripForDelivery(copy);
+        final Notification copy = Builder.maybeCloneStrippedForDelivery(notification);
         try {
             service.enqueueNotificationWithTag(pkg, mContext.getOpPackageName(), tag, id,
                     copy, idOut, user.getIdentifier());
@@ -254,6 +266,7 @@
                 Log.w(TAG, "notify: id corrupted: sent " + id + ", got back " + idOut[0]);
             }
         } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -294,6 +307,7 @@
         try {
             service.cancelNotificationWithTag(pkg, tag, id, user.getIdentifier());
         } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -309,6 +323,7 @@
         try {
             service.cancelAllNotifications(pkg, UserHandle.myUserId());
         } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -320,7 +335,7 @@
         try {
             return service.getEffectsSuppressor();
         } catch (RemoteException e) {
-            return null;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -332,7 +347,7 @@
         try {
             return service.matchesCallFilter(extras);
         } catch (RemoteException e) {
-            return false;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -344,7 +359,7 @@
         try {
             return service.isSystemConditionProviderEnabled(path);
         } catch (RemoteException e) {
-            return false;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -356,6 +371,7 @@
         try {
             service.setZenMode(mode, conditionId, reason);
         } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -367,8 +383,8 @@
         try {
             return service.getZenMode();
         } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
         }
-        return Global.ZEN_MODE_OFF;
     }
 
     /**
@@ -379,8 +395,8 @@
         try {
             return service.getZenModeConfig();
         } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
         }
-        return null;
     }
 
     /**
@@ -391,31 +407,38 @@
         try {
             return service.getRuleInstanceCount(owner);
         } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
         }
-        return 0;
     }
 
     /**
      * Returns AutomaticZenRules owned by the caller.
      *
      * <p>
-     * Only available if policy access is granted to this package.
+     * Throws a SecurityException if policy access is granted to this package.
      * See {@link #isNotificationPolicyAccessGranted}.
      */
-    public List<AutomaticZenRule> getAutomaticZenRules() {
+    public Map<String, AutomaticZenRule> getAutomaticZenRules() {
         INotificationManager service = getService();
         try {
-            return service.getAutomaticZenRules();
+            List<ZenModeConfig.ZenRule> rules = service.getZenRules();
+            Map<String, AutomaticZenRule> ruleMap = new HashMap<>();
+            for (ZenModeConfig.ZenRule rule : rules) {
+                ruleMap.put(rule.id, new AutomaticZenRule(rule.name, rule.component,
+                        rule.conditionId, zenModeToInterruptionFilter(rule.zenMode), rule.enabled,
+                        rule.creationTime));
+            }
+            return ruleMap;
         } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
         }
-        return null;
     }
 
     /**
      * Returns the AutomaticZenRule with the given id, if it exists and the caller has access.
      *
      * <p>
-     * Only available if policy access is granted to this package.
+     * Throws a SecurityException if policy access is granted to this package.
      * See {@link #isNotificationPolicyAccessGranted}.
      *
      * <p>
@@ -427,56 +450,56 @@
         try {
             return service.getAutomaticZenRule(id);
         } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
         }
-        return null;
     }
 
     /**
      * Creates the given zen rule.
      *
      * <p>
-     * Only available if policy access is granted to this package.
+     * Throws a SecurityException if policy access is granted to this package.
      * See {@link #isNotificationPolicyAccessGranted}.
      *
      * @param automaticZenRule the rule to create.
-     * @return A fully populated {@link AutomaticZenRule} if the rule was persisted successfully,
-     * null otherwise.
+     * @return The id of the newly created rule; null if the rule could not be created.
      */
-    public AutomaticZenRule addAutomaticZenRule(AutomaticZenRule automaticZenRule) {
+    public String addAutomaticZenRule(AutomaticZenRule automaticZenRule) {
         INotificationManager service = getService();
         try {
             return service.addAutomaticZenRule(automaticZenRule);
         } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
         }
-        return null;
     }
 
     /**
      * Updates the given zen rule.
      *
      * <p>
-     * Only available if policy access is granted to this package.
+     * Throws a SecurityException if policy access is granted to this package.
      * See {@link #isNotificationPolicyAccessGranted}.
      *
      * <p>
      * Callers can only update rules that they own. See {@link AutomaticZenRule#getOwner}.
+     * @param id The id of the rule to update
      * @param automaticZenRule the rule to update. 
      * @return Whether the rule was successfully updated.
      */
-    public boolean updateAutomaticZenRule(AutomaticZenRule automaticZenRule) {
+    public boolean updateAutomaticZenRule(String id, AutomaticZenRule automaticZenRule) {
         INotificationManager service = getService();
         try {
-            return service.updateAutomaticZenRule(automaticZenRule);
+            return service.updateAutomaticZenRule(id, automaticZenRule);
         } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
         }
-        return false;
     }
 
     /**
      * Deletes the automatic zen rule with the given id.
      *
      * <p>
-     * Only available if policy access is granted to this package.
+     * Throws a SecurityException if policy access is granted to this package.
      * See {@link #isNotificationPolicyAccessGranted}.
      *
      * <p>
@@ -489,8 +512,8 @@
         try {
             return service.removeAutomaticZenRule(id);
         } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
         }
-        return false;
     }
 
     /**
@@ -503,26 +526,32 @@
         try {
             return service.removeAutomaticZenRules(packageName);
         } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
         }
-        return false;
     }
 
-    public int getImportance() {
+    /**
+     * Returns the user specified importance for notifications from the calling package.
+     */
+    public @NotificationListenerService.Ranking.Importance int getImportance() {
         INotificationManager service = getService();
         try {
             return service.getPackageImportance(mContext.getPackageName());
         } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
         }
-        return NotificationListenerService.Ranking.IMPORTANCE_UNSPECIFIED;
     }
 
+    /**
+     * Returns whether notifications from the calling package are blocked.
+     */
     public boolean areNotificationsEnabled() {
         INotificationManager service = getService();
         try {
             return service.areNotificationsEnabled(mContext.getPackageName());
         } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
         }
-        return false;
     }
 
     /**
@@ -544,8 +573,8 @@
         try {
             return service.isNotificationPolicyAccessGranted(mContext.getOpPackageName());
         } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
         }
-        return false;
     }
 
     /** @hide */
@@ -554,8 +583,8 @@
         try {
             return service.isNotificationPolicyAccessGrantedForPackage(pkg);
         } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
         }
-        return false;
     }
 
     /**
@@ -570,8 +599,8 @@
         try {
             return service.getNotificationPolicy(mContext.getOpPackageName());
         } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
         }
-        return null;
     }
 
     /**
@@ -589,6 +618,7 @@
         try {
             service.setNotificationPolicy(mContext.getOpPackageName(), policy);
         } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -598,6 +628,7 @@
         try {
             service.setNotificationPolicyAccessGranted(pkg, granted);
         } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -614,8 +645,9 @@
                 return rt;
             }
         } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
         }
-        return new ArraySet<String>();
+        return new ArraySet<>();
     }
 
     private Context mContext;
@@ -628,7 +660,7 @@
 
     /**
      * Notification policy configuration.  Represents user-preferences for notification
-     * filtering and prioritization.
+     * filtering.
      */
     public static class Policy implements android.os.Parcelable {
         /** Reminder notifications are prioritized. */
@@ -673,13 +705,13 @@
          */
         public static final int SUPPRESSED_EFFECTS_UNSET = -1;
         /**
-         * Whether notification suppressed by DND should not interruption visually when the screen
-         * is off.
+         * Whether notifications suppressed by DND should not interrupt visually (e.g. with
+         * notification lights or by turning the screen on) when the screen is off.
          */
         public static final int SUPPRESSED_EFFECT_SCREEN_OFF = 1 << 0;
         /**
-         * Whether notification suppressed by DND should not interruption visually when the screen
-         * is on.
+         * Whether notifications suppressed by DND should not interrupt visually when the screen
+         * is on (e.g. by peeking onto the screen).
          */
         public static final int SUPPRESSED_EFFECT_SCREEN_ON = 1 << 1;
 
@@ -694,13 +726,27 @@
          */
         public final int suppressedVisualEffects;
 
-
-        @Deprecated
+        /**
+         * Constructs a policy for Do Not Disturb priority mode behavior.
+         *
+         * @param priorityCategories bitmask of categories of notifications that can bypass DND.
+         * @param priorityCallSenders which callers can bypass DND.
+         * @param priorityMessageSenders which message senders can bypass DND.
+         */
         public Policy(int priorityCategories, int priorityCallSenders, int priorityMessageSenders) {
             this(priorityCategories, priorityCallSenders, priorityMessageSenders,
                     SUPPRESSED_EFFECTS_UNSET);
         }
 
+        /**
+         * Constructs a policy for Do Not Disturb priority mode behavior.
+         *
+         * @param priorityCategories bitmask of categories of notifications that can bypass DND.
+         * @param priorityCallSenders which callers can bypass DND.
+         * @param priorityMessageSenders which message senders can bypass DND.
+         * @param suppressedVisualEffects which visual interruptions should be suppressed from
+         *                                notifications that are filtered by DND.
+         */
         public Policy(int priorityCategories, int priorityCallSenders, int priorityMessageSenders,
                 int suppressedVisualEffects) {
             this.priorityCategories = priorityCategories;
@@ -831,7 +877,6 @@
                 return new Policy[size];
             }
         };
-
     }
 
     /**
@@ -856,9 +901,8 @@
             final List<StatusBarNotification> list = parceledList.getList();
             return list.toArray(new StatusBarNotification[list.size()]);
         } catch (RemoteException e) {
-            Log.e(TAG, "Unable to talk to notification manager. Woe!", e);
+            throw e.rethrowFromSystemServer();
         }
-        return new StatusBarNotification[0];
     }
 
     /**
@@ -874,14 +918,13 @@
      * Only available if policy access is granted to this package.
      * See {@link #isNotificationPolicyAccessGranted}.
      */
-    public final int getCurrentInterruptionFilter() {
+    public final @InterruptionFilter int getCurrentInterruptionFilter() {
         final INotificationManager service = getService();
         try {
             return zenModeToInterruptionFilter(service.getZenMode());
         } catch (RemoteException e) {
-            Log.e(TAG, "Unable to talk to notification manager. Woe!", e);
+            throw e.rethrowFromSystemServer();
         }
-        return INTERRUPTION_FILTER_UNKNOWN;
     }
 
     /**
@@ -902,7 +945,7 @@
         try {
             service.setInterruptionFilter(mContext.getOpPackageName(), interruptionFilter);
         } catch (RemoteException e) {
-            Log.e(TAG, "Unable to talk to notification manager. Woe!", e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
diff --git a/core/java/android/app/ResourcesManager.java b/core/java/android/app/ResourcesManager.java
index 94e584e..54d813d 100644
--- a/core/java/android/app/ResourcesManager.java
+++ b/core/java/android/app/ResourcesManager.java
@@ -18,13 +18,17 @@
 
 import static android.app.ActivityThread.DEBUG_CONFIGURATION;
 
+import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.content.pm.ActivityInfo;
 import android.content.res.AssetManager;
 import android.content.res.CompatibilityInfo;
 import android.content.res.Configuration;
 import android.content.res.Resources;
+import android.content.res.ResourcesImpl;
 import android.content.res.ResourcesKey;
 import android.hardware.display.DisplayManagerGlobal;
+import android.os.IBinder;
 import android.util.ArrayMap;
 import android.util.DisplayMetrics;
 import android.util.LocaleList;
@@ -33,11 +37,16 @@
 import android.util.Slog;
 import android.view.Display;
 import android.view.DisplayAdjustments;
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.ArrayUtils;
 
 import java.lang.ref.WeakReference;
+import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.HashSet;
-import java.util.List;
+import java.util.Objects;
+import java.util.WeakHashMap;
+import java.util.function.Predicate;
 
 /** @hide */
 public class ResourcesManager {
@@ -45,18 +54,56 @@
     private static final boolean DEBUG = false;
 
     private static ResourcesManager sResourcesManager;
-    private final ArrayMap<ResourcesKey, WeakReference<Resources>> mActiveResources =
-            new ArrayMap<>();
-    private final ArrayMap<Pair<Integer, DisplayAdjustments>, WeakReference<Display>> mDisplays =
-            new ArrayMap<>();
+
+    /**
+     * Predicate that returns true if a WeakReference is gc'ed.
+     */
+    private static final Predicate<WeakReference<Resources>> sEmptyReferencePredicate =
+            new Predicate<WeakReference<Resources>>() {
+                @Override
+                public boolean test(WeakReference<Resources> weakRef) {
+                    return weakRef == null || weakRef.get() == null;
+                }
+            };
 
     private String[] mSystemLocales = {};
-    private final HashSet<String> mNonSystemLocales = new HashSet<String>();
+    private final HashSet<String> mNonSystemLocales = new HashSet<>();
     private boolean mHasNonSystemLocales = false;
 
-    CompatibilityInfo mResCompatibilityInfo;
+    /**
+     * The global compatibility settings.
+     */
+    private CompatibilityInfo mResCompatibilityInfo;
 
-    Configuration mResConfiguration;
+    /**
+     * The global configuration upon which all Resources are based. Multi-window Resources
+     * apply their overrides to this configuration.
+     */
+    private final Configuration mResConfiguration = new Configuration();
+
+    /**
+     * A mapping of ResourceImpls and their configurations. These are heavy weight objects
+     * which should be reused as much as possible.
+     */
+    private final ArrayMap<ResourcesKey, WeakReference<ResourcesImpl>> mResourceImpls =
+            new ArrayMap<>();
+
+    /**
+     * A list of Resource references that can be reused.
+     */
+    private final ArrayList<WeakReference<Resources>> mResourceReferences = new ArrayList<>();
+
+    /**
+     * Each Activity may have only one Resources object.
+     */
+    private final WeakHashMap<IBinder, WeakReference<Resources>> mActivityResourceReferences =
+            new WeakHashMap<>();
+
+    /**
+     * A cache of DisplayId to DisplayAdjustments.
+     */
+    private final ArrayMap<Pair<Integer, DisplayAdjustments>, WeakReference<Display>> mDisplays =
+            new ArrayMap<>();
 
     public static ResourcesManager getInstance() {
         synchronized (ResourcesManager.class) {
@@ -75,7 +122,11 @@
         return getDisplayMetricsLocked(Display.DEFAULT_DISPLAY);
     }
 
-    DisplayMetrics getDisplayMetricsLocked(int displayId) {
+    /**
+     * Protected so that tests can override and returns something a fixed value.
+     */
+    @VisibleForTesting
+    protected DisplayMetrics getDisplayMetricsLocked(int displayId) {
         DisplayMetrics dm = new DisplayMetrics();
         final Display display =
                 getAdjustedDisplay(displayId, DisplayAdjustments.DEFAULT_DISPLAY_ADJUSTMENTS);
@@ -87,12 +138,12 @@
         return dm;
     }
 
-    final void applyNonDefaultDisplayMetricsToConfigurationLocked(
-            DisplayMetrics dm, Configuration config) {
+    private static void applyNonDefaultDisplayMetricsToConfiguration(
+            @NonNull DisplayMetrics dm, @NonNull Configuration config) {
         config.touchscreen = Configuration.TOUCHSCREEN_NOTOUCH;
         config.densityDpi = dm.densityDpi;
-        config.screenWidthDp = (int)(dm.widthPixels / dm.density);
-        config.screenHeightDp = (int)(dm.heightPixels / dm.density);
+        config.screenWidthDp = (int) (dm.widthPixels / dm.density);
+        config.screenHeightDp = (int) (dm.heightPixels / dm.density);
         int sl = Configuration.resetScreenLayout(config.screenLayout);
         if (dm.widthPixels > dm.heightPixels) {
             config.orientation = Configuration.ORIENTATION_LANDSCAPE;
@@ -109,8 +160,8 @@
         config.compatSmallestScreenWidthDp = config.smallestScreenWidthDp;
     }
 
-    public boolean applyCompatConfiguration(int displayDensity,
-            Configuration compatConfiguration) {
+    public boolean applyCompatConfigurationLocked(int displayDensity,
+            @NonNull Configuration compatConfiguration) {
         if (mResCompatibilityInfo != null && !mResCompatibilityInfo.supportsScreen()) {
             mResCompatibilityInfo.applyToConfiguration(displayDensity, compatConfiguration);
             return true;
@@ -125,7 +176,8 @@
      * @param displayId display Id.
      * @param displayAdjustments display adjustments.
      */
-    public Display getAdjustedDisplay(final int displayId, DisplayAdjustments displayAdjustments) {
+    public Display getAdjustedDisplay(final int displayId,
+            @Nullable DisplayAdjustments displayAdjustments) {
         final DisplayAdjustments displayAdjustmentsCopy = (displayAdjustments != null)
                 ? new DisplayAdjustments(displayAdjustments) : new DisplayAdjustments();
         final Pair<Integer, DisplayAdjustments> key =
@@ -152,76 +204,42 @@
     }
 
     /**
-     * Creates the top level Resources for applications with the given compatibility info.
+     * Creates an AssetManager from the paths within the ResourcesKey.
      *
-     * @param resDir the resource directory.
-     * @param splitResDirs split resource directories.
-     * @param overlayDirs the resource overlay directories.
-     * @param libDirs the shared library resource dirs this app references.
-     * @param displayId display Id.
-     * @param overrideConfiguration override configurations.
-     * @param compatInfo the compatibility info. Must not be null.
-     * @param classLoader the class loader for the resource package
-     */
-    Resources getTopLevelResources(String resDir, String[] splitResDirs,
-            String[] overlayDirs, String[] libDirs, int displayId,
-            Configuration overrideConfiguration, CompatibilityInfo compatInfo,
-            ClassLoader classLoader) {
-        final float scale = compatInfo.applicationScale;
-        Configuration overrideConfigCopy = (overrideConfiguration != null)
-                ? new Configuration(overrideConfiguration) : null;
-        ResourcesKey key = new ResourcesKey(resDir, displayId, overrideConfigCopy, scale);
-        Resources r;
-        final boolean findSystemLocales;
-        final boolean hasNonSystemLocales;
-        synchronized (this) {
-            // Resources is app scale dependent.
-            if (DEBUG) Slog.w(TAG, "getTopLevelResources: " + resDir + " / " + scale);
-
-            WeakReference<Resources> wr = mActiveResources.get(key);
-            r = wr != null ? wr.get() : null;
-            //if (r != null) Log.i(TAG, "isUpToDate " + resDir + ": " + r.getAssets().isUpToDate());
-            if (r != null && r.getAssets().isUpToDate()) {
-                if (DEBUG) Slog.w(TAG, "Returning cached resources " + r + " " + resDir
-                        + ": appScale=" + r.getCompatibilityInfo().applicationScale
-                        + " key=" + key + " overrideConfig=" + overrideConfiguration);
-                return r;
-            }
-            findSystemLocales = (mSystemLocales.length == 0);
-            hasNonSystemLocales = mHasNonSystemLocales;
-        }
-
-        //if (r != null) {
-        //    Log.w(TAG, "Throwing away out-of-date resources!!!! "
-        //            + r + " " + resDir);
-        //}
-
+     * This can be overridden in tests so as to avoid creating a real AssetManager with
+     * real APK paths.
+     * @param key The key containing the resource paths to add to the AssetManager.
+     * @return a new AssetManager.
+    */
+    @VisibleForTesting
+    protected AssetManager createAssetManager(@NonNull final ResourcesKey key) {
         AssetManager assets = new AssetManager();
+
         // resDir can be null if the 'android' package is creating a new Resources object.
         // This is fine, since each AssetManager automatically loads the 'android' package
         // already.
-        if (resDir != null) {
-            if (assets.addAssetPath(resDir) == 0) {
+        if (key.mResDir != null) {
+            if (assets.addAssetPath(key.mResDir) == 0) {
                 return null;
             }
         }
 
-        if (splitResDirs != null) {
-            for (String splitResDir : splitResDirs) {
+        if (key.mSplitResDirs != null) {
+            for (final String splitResDir : key.mSplitResDirs) {
                 if (assets.addAssetPath(splitResDir) == 0) {
                     return null;
                 }
             }
         }
 
-        if (overlayDirs != null) {
-            for (String idmapPath : overlayDirs) {
+        if (key.mOverlayDirs != null) {
+            for (final String idmapPath : key.mOverlayDirs) {
                 assets.addOverlayPath(idmapPath);
             }
         }
 
-        if (libDirs != null) {
-            for (String libDir : libDirs) {
+        if (key.mLibDirs != null) {
+            for (final String libDir : key.mLibDirs) {
                 if (libDir.endsWith(".apk")) {
                     // Avoid opening files we know do not have resources,
                     // like code-only .jar files.
@@ -232,16 +250,17 @@
                 }
             }
         }
+        return assets;
+    }
 
-        //Log.i(TAG, "Resource: key=" + key + ", display metrics=" + metrics);
-        DisplayMetrics dm = getDisplayMetricsLocked(displayId);
+    private Configuration generateConfig(@NonNull ResourcesKey key, @NonNull DisplayMetrics dm) {
         Configuration config;
-        final boolean isDefaultDisplay = (displayId == Display.DEFAULT_DISPLAY);
+        final boolean isDefaultDisplay = (key.mDisplayId == Display.DEFAULT_DISPLAY);
         final boolean hasOverrideConfig = key.hasOverrideConfiguration();
         if (!isDefaultDisplay || hasOverrideConfig) {
             config = new Configuration(getConfiguration());
             if (!isDefaultDisplay) {
-                applyNonDefaultDisplayMetricsToConfigurationLocked(dm, config);
+                applyNonDefaultDisplayMetricsToConfiguration(dm, config);
             }
             if (hasOverrideConfig) {
                 config.updateFrom(key.mOverrideConfiguration);
@@ -250,15 +269,212 @@
         } else {
             config = getConfiguration();
         }
-        r = new Resources(assets, dm, config, compatInfo, classLoader);
-        if (DEBUG) Slog.i(TAG, "Created app resources " + resDir + " " + r + ": "
-                + r.getConfiguration() + " appScale=" + r.getCompatibilityInfo().applicationScale);
+        return config;
+    }
 
-        final String[] systemLocales = (
-                findSystemLocales ?
-                AssetManager.getSystem().getLocales() :
-                null);
-        final String[] nonSystemLocales = assets.getNonSystemLocales();
+
+    private ResourcesImpl createResourcesImpl(@NonNull ResourcesKey key) {
+        AssetManager assets = createAssetManager(key);
+        DisplayMetrics dm = getDisplayMetricsLocked(key.mDisplayId);
+        Configuration config = generateConfig(key, dm);
+        ResourcesImpl impl = new ResourcesImpl(assets, dm, config, key.mCompatInfo);
+        if (DEBUG) {
+            Slog.d(TAG, "- creating impl=" + impl + " with key: " + key);
+        }
+        return impl;
+    }
+
+    /**
+     * Finds a cached ResourcesImpl object that matches the given ResourcesKey.
+     *
+     * @param key The key to match.
+     * @return a ResourcesImpl if the key matches a cache entry, null otherwise.
+     */
+    private ResourcesImpl findResourcesImplForKey(@NonNull ResourcesKey key) {
+        WeakReference<ResourcesImpl> weakImplRef = mResourceImpls.get(key);
+        ResourcesImpl impl = weakImplRef != null ? weakImplRef.get() : null;
+        if (impl != null && impl.getAssets().isUpToDate()) {
+            return impl;
+        }
+        return null;
+    }
+
+    /**
+     * Find the ResourcesKey that this ResourcesImpl object is associated with.
+     * @return the ResourcesKey or null if none was found.
+     */
+    private ResourcesKey findKeyForResourceImpl(@NonNull ResourcesImpl resourceImpl) {
+        final int refCount = mResourceImpls.size();
+        for (int i = 0; i < refCount; i++) {
+            WeakReference<ResourcesImpl> weakImplRef = mResourceImpls.valueAt(i);
+            ResourcesImpl impl = weakImplRef != null ? weakImplRef.get() : null;
+            if (impl != null && resourceImpl == impl) {
+                return mResourceImpls.keyAt(i);
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Gets an existing Resources object tied to this Activity, or creates one if it doesn't exist
+     * or the class loader is different.
+     */
+    private Resources getOrCreateResourcesForActivityLocked(@NonNull IBinder activityToken,
+            @NonNull ClassLoader classLoader, @NonNull ResourcesImpl impl) {
+        // This is a request tied to an Activity, meaning we will need to update all
+        // Activity related Resources to match this configuration.
+        WeakReference<Resources> weakResourceRef = mActivityResourceReferences.get(activityToken);
+        Resources resources = weakResourceRef != null ? weakResourceRef.get() : null;
+        if (resources == null || !Objects.equals(resources.getClassLoader(), classLoader)) {
+            resources = new Resources(classLoader);
+            mActivityResourceReferences.put(activityToken, new WeakReference<>(resources));
+            if (DEBUG) {
+                Slog.d(TAG, "- creating new ref=" + resources);
+            }
+        } else {
+            if (DEBUG) {
+                Slog.d(TAG, "- using existing ref=" + resources);
+            }
+        }
+
+        if (resources.getImpl() != impl) {
+            if (DEBUG) {
+                Slog.d(TAG, "- setting ref=" + resources + " with impl=" + impl);
+            }
+
+            // Setting an impl is expensive because we update all ThemeImpl references.
+            // too.
+            resources.setImpl(impl);
+        }
+        return resources;
+    }
+
+    /**
+     * Gets an existing Resources object if the class loader and ResourcesImpl are the same,
+     * otherwise creates a new Resources object.
+     */
+    private Resources getOrCreateResourcesLocked(@NonNull ClassLoader classLoader,
+            @NonNull ResourcesImpl impl) {
+        // Find an existing Resources that has this ResourcesImpl set.
+        final int refCount = mResourceReferences.size();
+        for (int i = 0; i < refCount; i++) {
+            WeakReference<Resources> weakResourceRef = mResourceReferences.get(i);
+            Resources resources = weakResourceRef != null ? weakResourceRef.get() : null;
+            if (resources != null &&
+                    Objects.equals(resources.getClassLoader(), classLoader) &&
+                    resources.getImpl() == impl) {
+                if (DEBUG) {
+                    Slog.d(TAG, "- using existing ref=" + resources);
+                }
+                return resources;
+            }
+        }
+
+        // Create a new Resources reference and use the existing ResourcesImpl object.
+        Resources resources = new Resources(classLoader);
+        resources.setImpl(impl);
+        mResourceReferences.add(new WeakReference<>(resources));
+        if (DEBUG) {
+            Slog.d(TAG, "- creating new ref=" + resources);
+            Slog.d(TAG, "- setting ref=" + resources + " with impl=" + impl);
+        }
+        return resources;
+    }
+
+    /**
+     * Gets or creates a new Resources object associated with the IBinder token. References returned
+     * by this method live as long as the Activity, meaning they can be cached and used by the
+     * Activity even after a configuration change. If any other parameter is changed
+     * (resDir, splitResDirs, overrideConfig) for a given Activity, the same Resources object
+     * is updated and handed back to the caller. However, changing the class loader will result in a
+     * new Resources object.
+     * <p/>
+     * If activityToken is null, a cached Resources object will be returned if it matches the
+     * input parameters. Otherwise a new Resources object that satisfies these parameters is
+     * returned.
+     *
+     * @param activityToken Represents an Activity. If null, global resources are assumed.
+     * @param resDir The base resource path. Can be null (only framework resources will be loaded).
+     * @param splitResDirs An array of split resource paths. Can be null.
+     * @param overlayDirs An array of overlay paths. Can be null.
+     * @param libDirs An array of resource library paths. Can be null.
+     * @param displayId The ID of the display for which to create the resources.
+     * @param overrideConfig The configuration to apply on top of the base configuration. Can be
+     * null. Mostly used with Activities that are in multi-window which may override width and
+     * height properties from the base config.
+     * @param compatInfo The compatibility settings to use. Cannot be null. A default to use is
+     * {@link CompatibilityInfo#DEFAULT_COMPATIBILITY_INFO}.
+     * @param classLoader The class loader to use when inflating Resources. If null, the
+     * {@link ClassLoader#getSystemClassLoader()} is used.
+     * @return a Resources object from which to access resources.
+     */
+    public Resources getResources(@Nullable IBinder activityToken,
+            @Nullable String resDir,
+            @Nullable String[] splitResDirs,
+            @Nullable String[] overlayDirs,
+            @Nullable String[] libDirs,
+            int displayId,
+            @Nullable Configuration overrideConfig,
+            @NonNull CompatibilityInfo compatInfo,
+            @Nullable ClassLoader classLoader) {
+        final ResourcesKey key = new ResourcesKey(
+                resDir,
+                splitResDirs,
+                overlayDirs,
+                libDirs,
+                displayId,
+                overrideConfig != null ? new Configuration(overrideConfig) : null, // Copy
+                compatInfo);
+
+        classLoader = classLoader != null ? classLoader : ClassLoader.getSystemClassLoader();
+
+        final boolean findSystemLocales;
+        final boolean hasNonSystemLocales;
+        synchronized (this) {
+            findSystemLocales = (mSystemLocales.length == 0);
+            hasNonSystemLocales = mHasNonSystemLocales;
+
+            if (DEBUG) {
+                Throwable here = new Throwable();
+                here.fillInStackTrace();
+                Slog.w(TAG, "!! Get resources for activity=" + activityToken + " key=" + key, here);
+            }
+
+            if (activityToken != null) {
+                ResourcesImpl resourcesImpl = findResourcesImplForKey(key);
+                if (resourcesImpl != null) {
+                    if (DEBUG) {
+                        Slog.d(TAG, "- using existing impl=" + resourcesImpl);
+                    }
+                    return getOrCreateResourcesForActivityLocked(activityToken, classLoader,
+                            resourcesImpl);
+                }
+
+                // We will create the ResourcesImpl object outside of holding this lock.
+
+            } else {
+                // Clean up any dead references so they don't pile up.
+                ArrayUtils.unstableRemoveIf(mResourceReferences, sEmptyReferencePredicate);
+
+                // Not tied to an Activity, find a shared Resources that has the right ResourcesImpl
+                ResourcesImpl resourcesImpl = findResourcesImplForKey(key);
+                if (resourcesImpl != null) {
+                    if (DEBUG) {
+                        Slog.d(TAG, "- using existing impl=" + resourcesImpl);
+                    }
+                    return getOrCreateResourcesLocked(classLoader, resourcesImpl);
+                }
+
+                // We will create the ResourcesImpl object outside of holding this lock.
+            }
+        }
+
+        // If we're here, we didn't find a suitable ResourcesImpl to use, so create one now.
+        ResourcesImpl resourcesImpl = createResourcesImpl(key);
+
+        final String[] systemLocales = findSystemLocales
+                ? AssetManager.getSystem().getLocales() : null;
+        final String[] nonSystemLocales = resourcesImpl.getAssets().getNonSystemLocales();
         // Avoid checking for non-pseudo-locales if we already know there were some from a previous
         // Resources. The default value (for when hasNonSystemLocales is true) doesn't matter,
         // since mHasNonSystemLocales will also be true, and thus isPseudoLocalesOnly would not be
@@ -267,28 +483,75 @@
                 LocaleList.isPseudoLocalesOnly(nonSystemLocales);
 
         synchronized (this) {
-            WeakReference<Resources> wr = mActiveResources.get(key);
-            Resources existing = wr != null ? wr.get() : null;
-            if (existing != null && existing.getAssets().isUpToDate()) {
-                // Someone else already created the resources while we were
-                // unlocked; go ahead and use theirs.
-                r.getAssets().close();
-                return existing;
-            }
-
-            // XXX need to remove entries when weak references go away
-            mActiveResources.put(key, new WeakReference<>(r));
             if (mSystemLocales.length == 0) {
                 mSystemLocales = systemLocales;
             }
             mNonSystemLocales.addAll(Arrays.asList(nonSystemLocales));
             mHasNonSystemLocales = mHasNonSystemLocales || !isPseudoLocalesOnly;
-            if (DEBUG) Slog.v(TAG, "mActiveResources.size()=" + mActiveResources.size());
-            return r;
+
+            ResourcesImpl existingResourcesImpl = findResourcesImplForKey(key);
+            if (existingResourcesImpl != null) {
+                if (DEBUG) {
+                    Slog.d(TAG, "- got beat! existing impl=" + existingResourcesImpl
+                            + " new impl=" + resourcesImpl);
+                }
+                resourcesImpl.getAssets().close();
+                resourcesImpl = existingResourcesImpl;
+            } else {
+                // Add this ResourcesImpl to the cache.
+                mResourceImpls.put(key, new WeakReference<>(resourcesImpl));
+            }
+
+            final Resources resources;
+            if (activityToken != null) {
+                resources = getOrCreateResourcesForActivityLocked(activityToken, classLoader,
+                        resourcesImpl);
+            } else {
+                resources = getOrCreateResourcesLocked(classLoader, resourcesImpl);
+            }
+            return resources;
         }
     }
 
-    /* package */ void setDefaultLocalesLocked(LocaleList locales) {
+    /**
+     * Updates an Activity's Resources object with overrideConfig. The Resources object
+     * that was previously returned by
+     * {@link #getResources(IBinder, String, String[], String[], String[], int, Configuration,
+     * CompatibilityInfo, ClassLoader)} is
+     * still valid and will have the updated configuration.
+     * @param activityToken The Activity token.
+     * @param overrideConfig The configuration override to update.
+     */
+    public void updateResourcesForActivity(@NonNull IBinder activityToken,
+            @Nullable Configuration overrideConfig) {
+        final ClassLoader classLoader;
+        final ResourcesKey oldKey;
+        synchronized (this) {
+            // Extract the ResourcesKey that was last used to create the Resources for this
+            // activity.
+            WeakReference<Resources> weakResRef = mActivityResourceReferences.get(activityToken);
+            final Resources resources = weakResRef != null ? weakResRef.get() : null;
+            if (resources == null) {
+                Slog.e(TAG, "can't update resources for uncached activity " + activityToken);
+                return;
+            }
+
+            classLoader = resources.getClassLoader();
+            oldKey = findKeyForResourceImpl(resources.getImpl());
+            if (oldKey == null) {
+                Slog.e(TAG, "can't find ResourcesKey for resources impl=" + resources.getImpl());
+                return;
+            }
+        }
+
+        // Update the Resources object with the new override config and all of the existing
+        // settings.
+        getResources(activityToken, oldKey.mResDir, oldKey.mSplitResDirs, oldKey.mOverlayDirs,
+                oldKey.mLibDirs, oldKey.mDisplayId, overrideConfig, oldKey.mCompatInfo,
+                classLoader);
+    }
+
+    /* package */ void setDefaultLocalesLocked(@NonNull LocaleList locales) {
         final int bestLocale;
         if (mHasNonSystemLocales) {
             bestLocale = locales.getFirstMatchIndexWithEnglishSupported(mNonSystemLocales);
@@ -302,11 +565,8 @@
         LocaleList.setDefault(locales, bestLocale);
     }
 
-    final boolean applyConfigurationToResourcesLocked(Configuration config,
-            CompatibilityInfo compat) {
-        if (mResConfiguration == null) {
-            mResConfiguration = new Configuration();
-        }
+    public final boolean applyConfigurationToResourcesLocked(@NonNull Configuration config,
+                                                             @Nullable CompatibilityInfo compat) {
         if (!mResConfiguration.isOtherSeqNewer(config) && compat == null) {
             if (DEBUG || DEBUG_CONFIGURATION) Slog.v(TAG, "Skipping new config: curSeq="
                     + mResConfiguration.seq + ", newSeq=" + config.seq);
@@ -353,9 +613,9 @@
 
         Configuration tmpConfig = null;
 
-        for (int i = mActiveResources.size() - 1; i >= 0; i--) {
-            ResourcesKey key = mActiveResources.keyAt(i);
-            Resources r = mActiveResources.valueAt(i).get();
+        for (int i = mResourceImpls.size() - 1; i >= 0; i--) {
+            ResourcesKey key = mResourceImpls.keyAt(i);
+            ResourcesImpl r = mResourceImpls.valueAt(i).get();
             if (r != null) {
                 if (DEBUG || DEBUG_CONFIGURATION) Slog.v(TAG, "Changing resources "
                         + r + " config to: " + localeAdjustedConfig);
@@ -370,7 +630,7 @@
                     tmpConfig.setTo(localeAdjustedConfig);
                     if (!isDefaultDisplay) {
                         dm = getDisplayMetricsLocked(displayId);
-                        applyNonDefaultDisplayMetricsToConfigurationLocked(dm, tmpConfig);
+                        applyNonDefaultDisplayMetricsToConfiguration(dm, tmpConfig);
                     }
                     if (hasOverrideConfiguration) {
                         tmpConfig.updateFrom(key.mOverrideConfiguration);
@@ -383,11 +643,10 @@
                 //        + " " + r + ": " + r.getConfiguration());
             } else {
                 //Slog.i(TAG, "Removing old resources " + v.getKey());
-                mActiveResources.removeAt(i);
+                mResourceImpls.removeAt(i);
             }
         }
 
         return changes != 0;
     }
-
-}
+}
\ No newline at end of file
diff --git a/core/java/android/app/SearchManager.java b/core/java/android/app/SearchManager.java
index 9e32164..ac4abf5 100644
--- a/core/java/android/app/SearchManager.java
+++ b/core/java/android/app/SearchManager.java
@@ -686,8 +686,7 @@
         try {
             return mService.getGlobalSearchActivities();
         } catch (RemoteException ex) {
-            Log.e(TAG, "getGlobalSearchActivities() failed: " + ex);
-            return null;
+            throw ex.rethrowFromSystemServer();
         }
     }
 
@@ -698,8 +697,7 @@
         try {
             return mService.getGlobalSearchActivity();
         } catch (RemoteException ex) {
-            Log.e(TAG, "getGlobalSearchActivity() failed: " + ex);
-            return null;
+            throw ex.rethrowFromSystemServer();
         }
     }
 
@@ -716,8 +714,7 @@
         try {
             return mService.getWebSearchActivity();
         } catch (RemoteException ex) {
-            Log.e(TAG, "getWebSearchActivity() failed: " + ex);
-            return null;
+            throw ex.rethrowFromSystemServer();
         }
     }
 
@@ -850,8 +847,7 @@
         try {
             return mService.getSearchableInfo(componentName);
         } catch (RemoteException ex) {
-            Log.e(TAG, "getSearchableInfo() failed: " + ex);
-            return null;
+            throw ex.rethrowFromSystemServer();
         }
     }
 
@@ -935,8 +931,7 @@
         try {
             return mService.getSearchablesInGlobalSearch();
         } catch (RemoteException e) {
-            Log.e(TAG, "getSearchablesInGlobalSearch() failed: " + e);
-            return null;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -958,8 +953,7 @@
             }
             return intent;
         } catch (RemoteException re) {
-            Log.e(TAG, "getAssistIntent() failed: " + re);
-            return null;
+            throw re.rethrowFromSystemServer();
         }
     }
 
@@ -977,7 +971,7 @@
             }
             mService.launchAssist(args);
         } catch (RemoteException re) {
-            Log.e(TAG, "launchAssist() failed: " + re);
+            throw re.rethrowFromSystemServer();
         }
     }
 
@@ -995,8 +989,7 @@
             }
             return mService.launchLegacyAssist(hint, userHandle, args);
         } catch (RemoteException re) {
-            Log.e(TAG, "launchAssist() failed: " + re);
-            return false;
+            throw re.rethrowFromSystemServer();
         }
     }
 }
diff --git a/core/java/android/app/StatusBarManager.java b/core/java/android/app/StatusBarManager.java
index b899116..e57a9b5 100644
--- a/core/java/android/app/StatusBarManager.java
+++ b/core/java/android/app/StatusBarManager.java
@@ -123,8 +123,7 @@
                 svc.disable(what, mToken, mContext.getPackageName());
             }
         } catch (RemoteException ex) {
-            // system process is dead anyway.
-            throw new RuntimeException(ex);
+            throw ex.rethrowFromSystemServer();
         }
     }
 
@@ -141,8 +140,7 @@
                 svc.disable2(what, mToken, mContext.getPackageName());
             }
         } catch (RemoteException ex) {
-            // system process is dead anyway.
-            throw new RuntimeException(ex);
+            throw ex.rethrowFromSystemServer();
         }
     }
 
@@ -156,8 +154,7 @@
                 svc.expandNotificationsPanel();
             }
         } catch (RemoteException ex) {
-            // system process is dead anyway.
-            throw new RuntimeException(ex);
+            throw ex.rethrowFromSystemServer();
         }
     }
     
@@ -171,8 +168,7 @@
                 svc.collapsePanels();
             }
         } catch (RemoteException ex) {
-            // system process is dead anyway.
-            throw new RuntimeException(ex);
+            throw ex.rethrowFromSystemServer();
         }
     }
 
@@ -193,8 +189,7 @@
                 svc.expandSettingsPanel(subPanel);
             }
         } catch (RemoteException ex) {
-            // system process is dead anyway.
-            throw new RuntimeException(ex);
+            throw ex.rethrowFromSystemServer();
         }
     }
 
@@ -206,8 +201,7 @@
                     contentDescription);
             }
         } catch (RemoteException ex) {
-            // system process is dead anyway.
-            throw new RuntimeException(ex);
+            throw ex.rethrowFromSystemServer();
         }
     }
 
@@ -218,8 +212,7 @@
                 svc.removeIcon(slot);
             }
         } catch (RemoteException ex) {
-            // system process is dead anyway.
-            throw new RuntimeException(ex);
+            throw ex.rethrowFromSystemServer();
         }
     }
 
@@ -230,8 +223,7 @@
                 svc.setIconVisibility(slot, visible);
             }
         } catch (RemoteException ex) {
-            // system process is dead anyway.
-            throw new RuntimeException(ex);
+            throw ex.rethrowFromSystemServer();
         }
     }
 
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index 307c3eb..6c0b69c 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -37,7 +37,9 @@
 import android.content.IRestrictionsManager;
 import android.content.RestrictionsManager;
 import android.content.pm.ILauncherApps;
+import android.content.pm.IShortcutService;
 import android.content.pm.LauncherApps;
+import android.content.pm.ShortcutManager;
 import android.content.res.Resources;
 import android.hardware.ConsumerIrManager;
 import android.hardware.ISerialManager;
@@ -101,6 +103,7 @@
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.os.Vibrator;
+import android.os.health.SystemHealthManager;
 import android.os.storage.StorageManager;
 import android.print.IPrintManager;
 import android.print.PrintManager;
@@ -226,7 +229,7 @@
         SYSTEM_SERVICE_NAMES.put(android.text.ClipboardManager.class, Context.CLIPBOARD_SERVICE);
 
         registerService(Context.CONNECTIVITY_SERVICE, ConnectivityManager.class,
-                new StaticOuterContextServiceFetcher<ConnectivityManager>() {
+                new StaticApplicationContextServiceFetcher<ConnectivityManager>() {
             @Override
             public ConnectivityManager createService(Context context) {
                 IBinder b = ServiceManager.getService(Context.CONNECTIVITY_SERVICE);
@@ -271,9 +274,9 @@
             }});
 
         registerService(Context.DROPBOX_SERVICE, DropBoxManager.class,
-                new StaticServiceFetcher<DropBoxManager>() {
+                new CachedServiceFetcher<DropBoxManager>() {
             @Override
-            public DropBoxManager createService() {
+            public DropBoxManager createService(ContextImpl ctx) {
                 IBinder b = ServiceManager.getService(Context.DROPBOX_SERVICE);
                 IDropBoxManagerService service = IDropBoxManagerService.Stub.asInterface(b);
                 if (service == null) {
@@ -283,7 +286,7 @@
                     // DROPBOX_SERVICE is registered.
                     return null;
                 }
-                return new DropBoxManager(service);
+                return new DropBoxManager(ctx, service);
             }});
 
         registerService(Context.INPUT_SERVICE, InputManager.class,
@@ -745,9 +748,23 @@
             @Override
             public SoundTriggerManager createService(ContextImpl ctx) {
                 IBinder b = ServiceManager.getService(Context.SOUND_TRIGGER_SERVICE);
-                Log.i(TAG, "Creating new instance of SoundTriggerManager object.");
                 return new SoundTriggerManager(ctx, ISoundTriggerService.Stub.asInterface(b));
             }});
+
+        registerService(Context.SHORTCUT_SERVICE, ShortcutManager.class,
+                new CachedServiceFetcher<ShortcutManager>() {
+            @Override
+            public ShortcutManager createService(ContextImpl ctx) {
+                IBinder b = ServiceManager.getService(Context.SHORTCUT_SERVICE);
+                return new ShortcutManager(ctx, IShortcutService.Stub.asInterface(b));
+            }});
+
+        registerService(Context.SYSTEM_HEALTH_SERVICE, SystemHealthManager.class,
+                new CachedServiceFetcher<SystemHealthManager>() {
+            @Override
+            public SystemHealthManager createService(ContextImpl ctx) {
+                return new SystemHealthManager();
+            }});
     }
 
     /**
@@ -840,22 +857,21 @@
     }
 
     /**
-     * Like StaticServiceFetcher, creates only one instance of the service per process, but when
-     * creating the service for the first time, passes it the outer context of the creating
-     * component.
+     * Like StaticServiceFetcher, creates only one instance of the service per application, but when
+     * creating the service for the first time, passes it the application context of the creating
+     * application.
      *
-     * TODO: Is this safe in the case where multiple applications share the same process?
      * TODO: Delete this once its only user (ConnectivityManager) is known to work well in the
      * case where multiple application components each have their own ConnectivityManager object.
      */
-    static abstract class StaticOuterContextServiceFetcher<T> implements ServiceFetcher<T> {
+    static abstract class StaticApplicationContextServiceFetcher<T> implements ServiceFetcher<T> {
         private T mCachedInstance;
 
         @Override
         public final T getService(ContextImpl ctx) {
-            synchronized (StaticOuterContextServiceFetcher.this) {
+            synchronized (StaticApplicationContextServiceFetcher.this) {
                 if (mCachedInstance == null) {
-                    mCachedInstance = createService(ctx.getOuterContext());
+                    mCachedInstance = createService(ctx.getApplicationContext());
                 }
                 return mCachedInstance;
             }
diff --git a/core/java/android/app/UiModeManager.java b/core/java/android/app/UiModeManager.java
index 56b4249..69e8df8 100644
--- a/core/java/android/app/UiModeManager.java
+++ b/core/java/android/app/UiModeManager.java
@@ -17,6 +17,7 @@
 package android.app;
 
 import android.annotation.IntDef;
+import android.annotation.TestApi;
 import android.content.Context;
 import android.content.res.Configuration;
 import android.os.RemoteException;
@@ -158,7 +159,7 @@
             try {
                 mService.enableCarMode(flags);
             } catch (RemoteException e) {
-                Log.e(TAG, "disableCarMode: RemoteException", e);
+                throw e.rethrowFromSystemServer();
             }
         }
     }
@@ -181,7 +182,7 @@
             try {
                 mService.disableCarMode(flags);
             } catch (RemoteException e) {
-                Log.e(TAG, "disableCarMode: RemoteException", e);
+                throw e.rethrowFromSystemServer();
             }
         }
     }
@@ -200,7 +201,7 @@
             try {
                 return mService.getCurrentModeType();
             } catch (RemoteException e) {
-                Log.e(TAG, "getCurrentModeType: RemoteException", e);
+                throw e.rethrowFromSystemServer();
             }
         }
         return Configuration.UI_MODE_TYPE_NORMAL;
@@ -233,7 +234,7 @@
             try {
                 mService.setNightMode(mode);
             } catch (RemoteException e) {
-                Log.e(TAG, "setNightMode: RemoteException", e);
+                throw e.rethrowFromSystemServer();
             }
         }
     }
@@ -257,7 +258,7 @@
             try {
                 return mService.getNightMode();
             } catch (RemoteException e) {
-                Log.e(TAG, "getNightMode: RemoteException", e);
+                throw e.rethrowFromSystemServer();
             }
         }
         return -1;
@@ -266,13 +267,15 @@
     /**
      * @return If UI mode is locked or not. When UI mode is locked, calls to change UI mode
      *         like {@link #enableCarMode(int)} will silently fail.
+     * @hide
      */
+    @TestApi
     public boolean isUiModeLocked() {
         if (mService != null) {
             try {
                 return mService.isUiModeLocked();
             } catch (RemoteException e) {
-                Log.e(TAG, "isUiModeLocked: RemoteException", e);
+                throw e.rethrowFromSystemServer();
             }
         }
         return true;
@@ -286,13 +289,15 @@
      * mode will fail silently.
      *
      * @return {@code true} if night mode is locked or {@code false} otherwise
+     * @hide
      */
+    @TestApi
     public boolean isNightModeLocked() {
         if (mService != null) {
             try {
                 return mService.isNightModeLocked();
             } catch (RemoteException e) {
-                Log.e(TAG, "isNightModeLocked: RemoteException", e);
+                throw e.rethrowFromSystemServer();
             }
         }
         return true;
diff --git a/core/java/android/app/WallpaperManager.java b/core/java/android/app/WallpaperManager.java
index c3512ec..2d06dcc 100644
--- a/core/java/android/app/WallpaperManager.java
+++ b/core/java/android/app/WallpaperManager.java
@@ -49,7 +49,6 @@
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.SystemProperties;
-import android.os.UserHandle;
 import android.text.TextUtils;
 import android.util.Log;
 import android.view.WindowManagerGlobal;
@@ -263,7 +262,8 @@
 
     static class Globals extends IWallpaperManagerCallback.Stub {
         private IWallpaperManager mService;
-        private Bitmap mWallpaper;
+        private Bitmap mCachedWallpaper;
+        private int mCachedWallpaperUserId;
         private Bitmap mDefaultWallpaper;
 
         Globals(Looper looper) {
@@ -293,36 +293,37 @@
                             return null;
                         }
                     } catch (RemoteException e) {
-                        // Ignore
+                        throw e.rethrowFromSystemServer();
                     }
                 }
-                if (mWallpaper != null) {
-                    return mWallpaper;
+                if (mCachedWallpaper != null && mCachedWallpaperUserId == userId) {
+                    return mCachedWallpaper;
                 }
-                if (mDefaultWallpaper != null) {
-                    return mDefaultWallpaper;
-                }
-                mWallpaper = null;
+                mCachedWallpaper = null;
+                mCachedWallpaperUserId = 0;
                 try {
-                    mWallpaper = getCurrentWallpaperLocked(userId);
+                    mCachedWallpaper = getCurrentWallpaperLocked(userId);
+                    mCachedWallpaperUserId = userId;
                 } catch (OutOfMemoryError e) {
                     Log.w(TAG, "No memory load current wallpaper", e);
                 }
-                if (returnDefault) {
-                    if (mWallpaper == null) {
-                        mDefaultWallpaper = getDefaultWallpaperLocked(context);
-                        return mDefaultWallpaper;
-                    } else {
-                        mDefaultWallpaper = null;
-                    }
+                if (mCachedWallpaper != null) {
+                    return mCachedWallpaper;
                 }
-                return mWallpaper;
+                if (returnDefault) {
+                    if (mDefaultWallpaper == null) {
+                        mDefaultWallpaper = getDefaultWallpaperLocked(context);
+                    }
+                    return mDefaultWallpaper;
+                }
+                return null;
             }
         }
 
         public void forgetLoadedWallpaper() {
             synchronized (this) {
-                mWallpaper = null;
+                mCachedWallpaper = null;
+                mCachedWallpaperUserId = 0;
                 mDefaultWallpaper = null;
             }
         }
@@ -349,7 +350,7 @@
                     }
                 }
             } catch (RemoteException e) {
-                // Ignore
+                throw e.rethrowFromSystemServer();
             }
             return null;
         }
@@ -691,7 +692,7 @@
                 Bundle outParams = new Bundle();
                 return sGlobals.mService.getWallpaper(null, which, outParams, userId);
             } catch (RemoteException e) {
-                return null;
+                throw e.rethrowFromSystemServer();
             }
         }
     }
@@ -720,7 +721,7 @@
                 return sGlobals.mService.getWallpaperInfo();
             }
         } catch (RemoteException e) {
-            return null;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -767,7 +768,9 @@
         }
 
         // fallback crop activity
-        cropAndSetWallpaperIntent.setPackage("com.android.wallpapercropper");
+        final String cropperPackage = mContext.getString(
+                com.android.internal.R.string.config_wallpaperCropperPackage);
+        cropAndSetWallpaperIntent.setPackage(cropperPackage);
         List<ResolveInfo> cropAppList = packageManager.queryIntentActivities(
                 cropAndSetWallpaperIntent, 0);
         if (cropAppList.size() > 0) {
@@ -842,7 +845,7 @@
                 }
             }
         } catch (RemoteException e) {
-            // Ignore
+            throw e.rethrowFromSystemServer();
         }
         return result.getInt(EXTRA_NEW_WALLPAPER_ID, 0);
     }
@@ -948,7 +951,7 @@
                 }
             }
         } catch (RemoteException e) {
-            // Ignore
+            throw e.rethrowFromSystemServer();
         }
         return result.getInt(EXTRA_NEW_WALLPAPER_ID, 0);
     }
@@ -1065,7 +1068,7 @@
                 }
             }
         } catch (RemoteException e) {
-            // Ignore
+            throw e.rethrowFromSystemServer();
         }
 
         return result.getInt(EXTRA_NEW_WALLPAPER_ID, 0);
@@ -1086,7 +1089,7 @@
             String name = "res:" + resources.getResourceName(resid);
             return sGlobals.mService.hasNamedWallpaper(name);
         } catch (RemoteException e) {
-            return false;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1112,8 +1115,7 @@
         try {
             return sGlobals.mService.getWidthHint();
         } catch (RemoteException e) {
-            // Shouldn't happen!
-            return 0;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1139,8 +1141,7 @@
         try {
             return sGlobals.mService.getHeightHint();
         } catch (RemoteException e) {
-            // Shouldn't happen!
-            return 0;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1201,7 +1202,7 @@
                         mContext.getOpPackageName());
             }
         } catch (RemoteException e) {
-            // Ignore
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1222,7 +1223,7 @@
                 sGlobals.mService.setDisplayPadding(padding, mContext.getOpPackageName());
             }
         } catch (RemoteException e) {
-            // Ignore
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1243,7 +1244,7 @@
                     windowToken, x, y);
             //Log.v(TAG, "...app returning after sending display offset!");
         } catch (RemoteException e) {
-            // Ignore.
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1272,7 +1273,7 @@
         try {
             sGlobals.mService.clearWallpaper(mContext.getOpPackageName(), which, userId);
         } catch (RemoteException e) {
-            // Ignore
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1294,9 +1295,8 @@
             sGlobals.mService.setWallpaperComponentChecked(name, mContext.getOpPackageName());
             return true;
         } catch (RemoteException e) {
-            // Ignore
+            throw e.rethrowFromSystemServer();
         }
-        return false;
     }
 
     /**
@@ -1319,7 +1319,7 @@
                     windowToken, xOffset, yOffset, mWallpaperXStep, mWallpaperYStep);
             //Log.v(TAG, "...app returning after sending offsets!");
         } catch (RemoteException e) {
-            // Ignore.
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1357,7 +1357,7 @@
                     windowToken, action, x, y, z, extras, false);
             //Log.v(TAG, "...app returning after sending offsets!");
         } catch (RemoteException e) {
-            // Ignore.
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1373,7 +1373,7 @@
             try {
                 return sGlobals.mService.isWallpaperSupported(mContext.getOpPackageName());
             } catch (RemoteException e) {
-                // Ignore
+                throw e.rethrowFromSystemServer();
             }
         }
         return false;
@@ -1393,7 +1393,7 @@
             try {
                 return sGlobals.mService.isWallpaperSettingAllowed(mContext.getOpPackageName());
             } catch (RemoteException e) {
-                // Ignore
+                throw e.rethrowFromSystemServer();
             }
         }
         return false;
@@ -1414,7 +1414,7 @@
             WindowManagerGlobal.getWindowSession().setWallpaperPosition(
                     windowToken, -1, -1, -1, -1);
         } catch (RemoteException e) {
-            // Ignore.
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1434,6 +1434,25 @@
     }
 
     /**
+     * Remove one or more currently set wallpapers, reverting to the system default
+     * display for each one.  If {@link #FLAG_SET_SYSTEM} is set in the {@code which}
+     * parameter, the intent {@link Intent#ACTION_WALLPAPER_CHANGED} will be broadcast
+     * upon success.
+     *
+     * @param which A bitwise combination of {@link #FLAG_SET_SYSTEM} or
+     *   {@link #FLAG_SET_LOCK}
+     * @throws IOException If an error occurs reverting to the built-in wallpaper.
+     */
+    public void clear(int which) throws IOException {
+        if ((which & FLAG_SET_SYSTEM) != 0) {
+            clear();
+        }
+        if ((which & FLAG_SET_LOCK) != 0) {
+            clearWallpaper(FLAG_SET_LOCK, mContext.getUserId());
+        }
+    }
+
+    /**
      * Open stream representing the default static image wallpaper.
      *
      * @hide
@@ -1495,9 +1514,8 @@
         try {
             return sGlobals.mService.setLockWallpaperCallback(callback);
         } catch (RemoteException e) {
-            Log.e(TAG, "Unable to contact wallpaper service");
+            throw e.rethrowFromSystemServer();
         }
-        return false;
     }
 
     // Private completion callback for setWallpaper() synchronization
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 74fe13a..53a6351 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -100,9 +100,6 @@
     private final IDevicePolicyManager mService;
     private final boolean mParentInstance;
 
-    private static final String REMOTE_EXCEPTION_MESSAGE =
-            "Failed to talk with device policy manager service";
-
     private DevicePolicyManager(Context context, boolean parentInstance) {
         this(context,
                 IDevicePolicyManager.Stub.asInterface(
@@ -347,6 +344,68 @@
             = "android.app.action.PROVISION_FINALIZATION";
 
     /**
+     * Action: Bugreport sharing with device owner has been accepted by the user.
+     *
+     * @hide
+     */
+    public static final String ACTION_BUGREPORT_SHARING_ACCEPTED =
+            "com.android.server.action.BUGREPORT_SHARING_ACCEPTED";
+
+    /**
+     * Action: Bugreport sharing with device owner has been declined by the user.
+     *
+     * @hide
+     */
+    public static final String ACTION_BUGREPORT_SHARING_DECLINED =
+            "com.android.server.action.BUGREPORT_SHARING_DECLINED";
+
+    /**
+     * Action: Bugreport has been collected and is dispatched to {@link DevicePolicyManagerService}.
+     *
+     * @hide
+     */
+    public static final String ACTION_REMOTE_BUGREPORT_DISPATCH =
+            "android.intent.action.REMOTE_BUGREPORT_DISPATCH";
+
+    /**
+     * Extra for shared bugreport's SHA-256 hash.
+     *
+     * @hide
+     */
+    public static final String EXTRA_REMOTE_BUGREPORT_HASH =
+            "android.intent.extra.REMOTE_BUGREPORT_HASH";
+
+    /**
+     * Extra for remote bugreport notification shown type.
+     *
+     * @hide
+     */
+    public static final String EXTRA_BUGREPORT_NOTIFICATION_TYPE =
+            "android.app.extra.bugreport_notification_type";
+
+    /**
+     * Notification type for a started remote bugreport flow.
+     *
+     * @hide
+     */
+    public static final int NOTIFICATION_BUGREPORT_STARTED = 1;
+
+    /**
+     * Notification type for a bugreport that has already been accepted to be shared, but is still
+     * being taken.
+     *
+     * @hide
+     */
+    public static final int NOTIFICATION_BUGREPORT_ACCEPTED_NOT_FINISHED = 2;
+
+    /**
+     * Notification type for a bugreport that has been taken and can be shared or declined.
+     *
+     * @hide
+     */
+    public static final int NOTIFICATION_BUGREPORT_FINISHED_NOT_ACCEPTED = 3;
+
+    /**
      * A {@link android.os.Parcelable} extra of type {@link android.os.PersistableBundle} that
      * allows a mobile device management application or NFC programmer application which starts
      * managed provisioning to pass data to the management application instance after provisioning.
@@ -989,7 +1048,7 @@
             try {
                 return mService.isAdminActive(admin, userId);
             } catch (RemoteException e) {
-                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+                throw e.rethrowFromSystemServer();
             }
         }
         return false;
@@ -1004,7 +1063,7 @@
             try {
                 return mService.isRemovingAdmin(admin, userId);
             } catch (RemoteException e) {
-                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+                throw e.rethrowFromSystemServer();
             }
         }
         return false;
@@ -1029,7 +1088,7 @@
             try {
                 return mService.getActiveAdmins(userId);
             } catch (RemoteException e) {
-                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+                throw e.rethrowFromSystemServer();
             }
         }
         return null;
@@ -1054,7 +1113,7 @@
             try {
                 return mService.packageHasActiveAdmins(packageName, userId);
             } catch (RemoteException e) {
-                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+                throw e.rethrowFromSystemServer();
             }
         }
         return false;
@@ -1074,7 +1133,7 @@
             try {
                 mService.removeActiveAdmin(admin, myUserId());
             } catch (RemoteException e) {
-                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+                throw e.rethrowFromSystemServer();
             }
         }
     }
@@ -1093,7 +1152,7 @@
             try {
                 return mService.hasGrantedPolicy(admin, usesPolicy, myUserId());
             } catch (RemoteException e) {
-                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+                throw e.rethrowFromSystemServer();
             }
         }
         return false;
@@ -1109,7 +1168,7 @@
             try {
                 return mService.isSeparateProfileChallengeAllowed(userHandle);
             } catch (RemoteException e) {
-                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+                throw e.rethrowFromSystemServer();
             }
         }
         return false;
@@ -1227,7 +1286,7 @@
             try {
                 mService.setPasswordQuality(admin, quality, mParentInstance);
             } catch (RemoteException e) {
-                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+                throw e.rethrowFromSystemServer();
             }
         }
     }
@@ -1254,7 +1313,7 @@
             try {
                 return mService.getPasswordQuality(admin, userHandle, mParentInstance);
             } catch (RemoteException e) {
-                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+                throw e.rethrowFromSystemServer();
             }
         }
         return PASSWORD_QUALITY_UNSPECIFIED;
@@ -1291,7 +1350,7 @@
             try {
                 mService.setPasswordMinimumLength(admin, length, mParentInstance);
             } catch (RemoteException e) {
-                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+                throw e.rethrowFromSystemServer();
             }
         }
     }
@@ -1319,7 +1378,7 @@
             try {
                 return mService.getPasswordMinimumLength(admin, userHandle, mParentInstance);
             } catch (RemoteException e) {
-                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+                throw e.rethrowFromSystemServer();
             }
         }
         return 0;
@@ -1357,7 +1416,7 @@
             try {
                 mService.setPasswordMinimumUpperCase(admin, length, mParentInstance);
             } catch (RemoteException e) {
-                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+                throw e.rethrowFromSystemServer();
             }
         }
     }
@@ -1391,7 +1450,7 @@
             try {
                 return mService.getPasswordMinimumUpperCase(admin, userHandle, mParentInstance);
             } catch (RemoteException e) {
-                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+                throw e.rethrowFromSystemServer();
             }
         }
         return 0;
@@ -1429,7 +1488,7 @@
             try {
                 mService.setPasswordMinimumLowerCase(admin, length, mParentInstance);
             } catch (RemoteException e) {
-                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+                throw e.rethrowFromSystemServer();
             }
         }
     }
@@ -1463,7 +1522,7 @@
             try {
                 return mService.getPasswordMinimumLowerCase(admin, userHandle, mParentInstance);
             } catch (RemoteException e) {
-                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+                throw e.rethrowFromSystemServer();
             }
         }
         return 0;
@@ -1500,7 +1559,7 @@
             try {
                 mService.setPasswordMinimumLetters(admin, length, mParentInstance);
             } catch (RemoteException e) {
-                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+                throw e.rethrowFromSystemServer();
             }
         }
     }
@@ -1533,7 +1592,7 @@
             try {
                 return mService.getPasswordMinimumLetters(admin, userHandle, mParentInstance);
             } catch (RemoteException e) {
-                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+                throw e.rethrowFromSystemServer();
             }
         }
         return 0;
@@ -1570,7 +1629,7 @@
             try {
                 mService.setPasswordMinimumNumeric(admin, length, mParentInstance);
             } catch (RemoteException e) {
-                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+                throw e.rethrowFromSystemServer();
             }
         }
     }
@@ -1603,7 +1662,7 @@
             try {
                 return mService.getPasswordMinimumNumeric(admin, userHandle, mParentInstance);
             } catch (RemoteException e) {
-                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+                throw e.rethrowFromSystemServer();
             }
         }
         return 0;
@@ -1640,7 +1699,7 @@
             try {
                 mService.setPasswordMinimumSymbols(admin, length, mParentInstance);
             } catch (RemoteException e) {
-                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+                throw e.rethrowFromSystemServer();
             }
         }
     }
@@ -1672,7 +1731,7 @@
             try {
                 return mService.getPasswordMinimumSymbols(admin, userHandle, mParentInstance);
             } catch (RemoteException e) {
-                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+                throw e.rethrowFromSystemServer();
             }
         }
         return 0;
@@ -1709,7 +1768,7 @@
             try {
                 mService.setPasswordMinimumNonLetter(admin, length, mParentInstance);
             } catch (RemoteException e) {
-                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+                throw e.rethrowFromSystemServer();
             }
         }
     }
@@ -1742,7 +1801,7 @@
             try {
                 return mService.getPasswordMinimumNonLetter(admin, userHandle, mParentInstance);
             } catch (RemoteException e) {
-                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+                throw e.rethrowFromSystemServer();
             }
         }
         return 0;
@@ -1780,7 +1839,7 @@
             try {
                 mService.setPasswordHistoryLength(admin, length, mParentInstance);
             } catch (RemoteException e) {
-                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+                throw e.rethrowFromSystemServer();
             }
         }
     }
@@ -1816,7 +1875,7 @@
             try {
                 mService.setPasswordExpirationTimeout(admin, timeout, mParentInstance);
             } catch (RemoteException e) {
-                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+                throw e.rethrowFromSystemServer();
             }
         }
     }
@@ -1840,7 +1899,7 @@
             try {
                 return mService.getPasswordExpirationTimeout(admin, myUserId(), mParentInstance);
             } catch (RemoteException e) {
-                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+                throw e.rethrowFromSystemServer();
             }
         }
         return 0;
@@ -1864,7 +1923,7 @@
             try {
                 return mService.getPasswordExpiration(admin, myUserId(), mParentInstance);
             } catch (RemoteException e) {
-                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+                throw e.rethrowFromSystemServer();
             }
         }
         return 0;
@@ -1893,7 +1952,7 @@
             try {
                 return mService.getPasswordHistoryLength(admin, userHandle, mParentInstance);
             } catch (RemoteException e) {
-                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+                throw e.rethrowFromSystemServer();
             }
         }
         return 0;
@@ -1931,7 +1990,7 @@
             try {
                 return mService.isActivePasswordSufficient(myUserId(), mParentInstance);
             } catch (RemoteException e) {
-                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+                throw e.rethrowFromSystemServer();
             }
         }
         return false;
@@ -1951,7 +2010,7 @@
             try {
                 return mService.isProfileActivePasswordSufficientForParent(userHandle);
             } catch (RemoteException e) {
-                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+                throw e.rethrowFromSystemServer();
             }
         }
         return false;
@@ -1988,7 +2047,7 @@
             try {
                 return mService.getCurrentFailedPasswordAttempts(userHandle, mParentInstance);
             } catch (RemoteException e) {
-                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+                throw e.rethrowFromSystemServer();
             }
         }
         return -1;
@@ -2005,7 +2064,7 @@
             try {
                 return mService.getDoNotAskCredentialsOnBoot();
             } catch (RemoteException e) {
-                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+                throw e.rethrowFromSystemServer();
             }
         }
         return false;
@@ -2039,7 +2098,7 @@
             try {
                 mService.setMaximumFailedPasswordsForWipe(admin, num, mParentInstance);
             } catch (RemoteException e) {
-                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+                throw e.rethrowFromSystemServer();
             }
         }
     }
@@ -2068,7 +2127,7 @@
                 return mService.getMaximumFailedPasswordsForWipe(
                         admin, userHandle, mParentInstance);
             } catch (RemoteException e) {
-                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+                throw e.rethrowFromSystemServer();
             }
         }
         return 0;
@@ -2087,7 +2146,7 @@
                 return mService.getProfileWithMinimumFailedPasswordsForWipe(
                         userHandle, mParentInstance);
             } catch (RemoteException e) {
-                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+                throw e.rethrowFromSystemServer();
             }
         }
         return UserHandle.USER_NULL;
@@ -2155,7 +2214,7 @@
             try {
                 return mService.resetPassword(password, flags);
             } catch (RemoteException e) {
-                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+                throw e.rethrowFromSystemServer();
             }
         }
         return false;
@@ -2183,7 +2242,7 @@
             try {
                 mService.setMaximumTimeToLock(admin, timeMs, mParentInstance);
             } catch (RemoteException e) {
-                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+                throw e.rethrowFromSystemServer();
             }
         }
     }
@@ -2212,7 +2271,7 @@
             try {
                 return mService.getMaximumTimeToLock(admin, userHandle, mParentInstance);
             } catch (RemoteException e) {
-                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+                throw e.rethrowFromSystemServer();
             }
         }
         return 0;
@@ -2235,7 +2294,7 @@
             try {
                 mService.lockNow(mParentInstance);
             } catch (RemoteException e) {
-                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+                throw e.rethrowFromSystemServer();
             }
         }
     }
@@ -2272,7 +2331,7 @@
             try {
                 mService.wipeData(flags);
             } catch (RemoteException e) {
-                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+                throw e.rethrowFromSystemServer();
             }
         }
     }
@@ -2342,7 +2401,7 @@
                 }
                 return mService.setGlobalProxy(admin, hostSpec, exclSpec);
             } catch (RemoteException e) {
-                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+                throw e.rethrowFromSystemServer();
             }
         }
         return null;
@@ -2370,7 +2429,7 @@
             try {
                 mService.setRecommendedGlobalProxy(admin, proxyInfo);
             } catch (RemoteException e) {
-                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+                throw e.rethrowFromSystemServer();
             }
         }
     }
@@ -2386,7 +2445,7 @@
             try {
                 return mService.getGlobalProxyAdmin(myUserId());
             } catch (RemoteException e) {
-                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+                throw e.rethrowFromSystemServer();
             }
         }
         return null;
@@ -2515,7 +2574,7 @@
             try {
                 return mService.setStorageEncryption(admin, encrypt);
             } catch (RemoteException e) {
-                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+                throw e.rethrowFromSystemServer();
             }
         }
         return ENCRYPTION_STATUS_UNSUPPORTED;
@@ -2535,7 +2594,7 @@
             try {
                 return mService.getStorageEncryption(admin, myUserId());
             } catch (RemoteException e) {
-                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+                throw e.rethrowFromSystemServer();
             }
         }
         return false;
@@ -2570,7 +2629,7 @@
             try {
                 return mService.getStorageEncryptionStatus(userHandle);
             } catch (RemoteException e) {
-                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+                throw e.rethrowFromSystemServer();
             }
         }
         return ENCRYPTION_STATUS_UNSUPPORTED;
@@ -2591,7 +2650,7 @@
             try {
                 return mService.installCaCert(admin, certBuffer);
             } catch (RemoteException e) {
-                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+                throw e.rethrowFromSystemServer();
             }
         }
         return false;
@@ -2612,7 +2671,7 @@
             } catch (CertificateException e) {
                 Log.w(TAG, "Unable to parse certificate", e);
             } catch (RemoteException e) {
-                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+                throw e.rethrowFromSystemServer();
             }
         }
     }
@@ -2640,7 +2699,7 @@
                     }
                 }
             } catch (RemoteException re) {
-                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
+                throw re.rethrowFromSystemServer();
             }
         }
         return certs;
@@ -2659,7 +2718,7 @@
                 mService.uninstallCaCerts(admin, new TrustedCertificateStore().userAliases()
                         .toArray(new String[0]));
             } catch (RemoteException re) {
-                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
+                throw re.rethrowFromSystemServer();
             }
         }
     }
@@ -2677,7 +2736,7 @@
                 mService.enforceCanManageCaCerts(admin);
                 return getCaCertAlias(certBuffer) != null;
             } catch (RemoteException re) {
-                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
+                throw re.rethrowFromSystemServer();
             } catch (CertificateException ce) {
                 Log.w(TAG, "Could not parse certificate", ce);
             }
@@ -2715,18 +2774,19 @@
      * certificate and corresponding private key. All apps within the profile will be able to access
      * the certificate and use the private key, given direct user approval.
      *
-     * <p>The caller of this API may grant itself access to the credential immediately, without user
-     * approval. It is a best practice not to request this unless strictly necessary since it opens
-     * up additional security vulnerabilities.
+     * <p>The caller of this API may grant itself access to the certificate and private key
+     * immediately, without user approval. It is a best practice not to request this unless strictly
+     * necessary since it opens up additional security vulnerabilities.
      *
      * @param admin Which {@link DeviceAdminReceiver} this request is associated with, or
-     *            {@code null} if calling from a delegated certificate installer.
+     *        {@code null} if calling from a delegated certificate installer.
      * @param privKey The private key to install.
      * @param cert The certificate to install.
      * @param alias The private key alias under which to install the certificate. If a certificate
-     * with that alias already exists, it will be overwritten.
+     *        with that alias already exists, it will be overwritten.
      * @param requestAccess {@code true} to request that the calling app be granted access to the
-     * credentials immediately. Otherwise, access to the credentials will be gated by user approval.
+     *        credentials immediately. Otherwise, access to the credentials will be gated by user
+     *        approval.
      * @return {@code true} if the keys were installed, {@code false} otherwise.
      */
     public boolean installKeyPair(@Nullable ComponentName admin, @NonNull PrivateKey privKey,
@@ -2737,7 +2797,7 @@
                     .getKeySpec(privKey, PKCS8EncodedKeySpec.class).getEncoded();
             return mService.installKeyPair(admin, pkcs8Key, pemCert, alias, requestAccess);
         } catch (RemoteException e) {
-            Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+            throw e.rethrowFromSystemServer();
         } catch (NoSuchAlgorithmException | InvalidKeySpecException e) {
             Log.w(TAG, "Failed to obtain private key material", e);
         } catch (CertificateException | IOException e) {
@@ -2747,21 +2807,20 @@
     }
 
     /**
-     * Called by a device or profile owner, or delegated certificate installer, to remove all user
-     * credentials installed under a given alias.
+     * Called by a device or profile owner, or delegated certificate installer, to remove a
+     * certificate and private key pair installed under a given alias.
      *
      * @param admin Which {@link DeviceAdminReceiver} this request is associated with, or
-     *            {@code null} if calling from a delegated certificate installer.
+     *        {@code null} if calling from a delegated certificate installer.
      * @param alias The private key alias under which the certificate is installed.
-     * @return {@code true} if the keys were both removed, {@code false} otherwise.
+     * @return {@code true} if the private key alias no longer exists, {@code false} otherwise.
      */
     public boolean removeKeyPair(@Nullable ComponentName admin, @NonNull String alias) {
         try {
             return mService.removeKeyPair(admin, alias);
         } catch (RemoteException e) {
-            Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+            throw e.rethrowFromSystemServer();
         }
-        return false;
     }
 
     /**
@@ -2800,7 +2859,7 @@
             try {
                 mService.setCertInstallerPackage(admin, installerPackage);
             } catch (RemoteException e) {
-                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+                throw e.rethrowFromSystemServer();
             }
         }
     }
@@ -2818,7 +2877,7 @@
             try {
                 return mService.getCertInstallerPackage(admin);
             } catch (RemoteException e) {
-                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+                throw e.rethrowFromSystemServer();
             }
         }
         return null;
@@ -2845,7 +2904,7 @@
             try {
                 return mService.setAlwaysOnVpnPackage(admin, vpnPackage);
             } catch (RemoteException e) {
-                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+                throw e.rethrowFromSystemServer();
             }
         }
         return false;
@@ -2865,7 +2924,7 @@
             try {
                 return mService.getAlwaysOnVpnPackage(admin);
             } catch (RemoteException e) {
-                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+                throw e.rethrowFromSystemServer();
             }
         }
         return null;
@@ -2890,7 +2949,7 @@
             try {
                 mService.setCameraDisabled(admin, disabled);
             } catch (RemoteException e) {
-                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+                throw e.rethrowFromSystemServer();
             }
         }
     }
@@ -2911,7 +2970,7 @@
             try {
                 return mService.getCameraDisabled(admin, userHandle);
             } catch (RemoteException e) {
-                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+                throw e.rethrowFromSystemServer();
             }
         }
         return false;
@@ -2921,7 +2980,7 @@
      * Called by a device owner to request a bugreport.
      *
      * <p>There must be only one user on the device, managed by the device owner.
-     * Otherwise a security exception will be thrown.
+     * Otherwise a {@link SecurityException} will be thrown.
      *
      * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
      * @return {@code true} if the bugreport collection started successfully, or {@code false}
@@ -2933,7 +2992,7 @@
             try {
                 return mService.requestBugreport(admin);
             } catch (RemoteException e) {
-                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+                throw e.rethrowFromSystemServer();
             }
         }
         return false;
@@ -2970,7 +3029,7 @@
             try {
                 mService.setScreenCaptureDisabled(admin, disabled);
             } catch (RemoteException e) {
-                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+                throw e.rethrowFromSystemServer();
             }
         }
     }
@@ -2991,7 +3050,7 @@
             try {
                 return mService.getScreenCaptureDisabled(admin, userHandle);
             } catch (RemoteException e) {
-                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+                throw e.rethrowFromSystemServer();
             }
         }
         return false;
@@ -3014,7 +3073,7 @@
             try {
                 mService.setAutoTimeRequired(admin, required);
             } catch (RemoteException e) {
-                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+                throw e.rethrowFromSystemServer();
             }
         }
     }
@@ -3027,7 +3086,7 @@
             try {
                 return mService.getAutoTimeRequired();
             } catch (RemoteException e) {
-                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+                throw e.rethrowFromSystemServer();
             }
         }
         return false;
@@ -3052,7 +3111,7 @@
             try {
                 mService.setForceEphemeralUsers(admin, forceEphemeralUsers);
             } catch (RemoteException e) {
-                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+                throw e.rethrowFromSystemServer();
             }
         }
     }
@@ -3066,7 +3125,7 @@
             try {
                 return mService.getForceEphemeralUsers(admin);
             } catch (RemoteException e) {
-                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+                throw e.rethrowFromSystemServer();
             }
         }
         return false;
@@ -3115,7 +3174,7 @@
             try {
                 mService.setKeyguardDisabledFeatures(admin, which, mParentInstance);
             } catch (RemoteException e) {
-                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+                throw e.rethrowFromSystemServer();
             }
         }
     }
@@ -3144,7 +3203,7 @@
             try {
                 return mService.getKeyguardDisabledFeatures(admin, userHandle, mParentInstance);
             } catch (RemoteException e) {
-                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+                throw e.rethrowFromSystemServer();
             }
         }
         return KEYGUARD_DISABLE_FEATURES_NONE;
@@ -3159,7 +3218,7 @@
             try {
                 mService.setActiveAdmin(policyReceiver, refreshing, userHandle);
             } catch (RemoteException e) {
-                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+                throw e.rethrowFromSystemServer();
             }
         }
     }
@@ -3179,7 +3238,7 @@
             try {
                 mService.getRemoveWarning(admin, result, myUserId());
             } catch (RemoteException e) {
-                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+                throw e.rethrowFromSystemServer();
             }
         }
     }
@@ -3194,7 +3253,7 @@
                 mService.setActivePasswordState(quality, length, letters, uppercase, lowercase,
                         numbers, symbols, nonletter, userHandle);
             } catch (RemoteException e) {
-                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+                throw e.rethrowFromSystemServer();
             }
         }
     }
@@ -3207,7 +3266,7 @@
             try {
                 mService.reportFailedPasswordAttempt(userHandle);
             } catch (RemoteException e) {
-                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+                throw e.rethrowFromSystemServer();
             }
         }
     }
@@ -3220,7 +3279,7 @@
             try {
                 mService.reportSuccessfulPasswordAttempt(userHandle);
             } catch (RemoteException e) {
-                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+                throw e.rethrowFromSystemServer();
             }
         }
     }
@@ -3233,7 +3292,7 @@
             try {
                 mService.reportFailedFingerprintAttempt(userHandle);
             } catch (RemoteException e) {
-                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+                throw e.rethrowFromSystemServer();
             }
         }
     }
@@ -3246,7 +3305,7 @@
             try {
                 mService.reportSuccessfulFingerprintAttempt(userHandle);
             } catch (RemoteException e) {
-                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+                throw e.rethrowFromSystemServer();
             }
         }
     }
@@ -3260,7 +3319,7 @@
             try {
                 mService.reportKeyguardDismissed(userHandle);
             } catch (RemoteException e) {
-                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+                throw e.rethrowFromSystemServer();
             }
         }
     }
@@ -3274,7 +3333,7 @@
             try {
                 mService.reportKeyguardSecured(userHandle);
             } catch (RemoteException e) {
-                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+                throw e.rethrowFromSystemServer();
             }
         }
     }
@@ -3327,7 +3386,7 @@
             try {
                 return mService.setDeviceOwner(who, ownerName, userId);
             } catch (RemoteException re) {
-                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
+                throw re.rethrowFromSystemServer();
             }
         }
         return false;
@@ -3409,7 +3468,7 @@
             try {
                 return mService.getDeviceOwnerComponent(callingUserOnly);
             } catch (RemoteException re) {
-                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
+                throw re.rethrowFromSystemServer();
             }
         }
         return null;
@@ -3428,7 +3487,7 @@
             try {
                 return mService.getDeviceOwnerUserId();
             } catch (RemoteException re) {
-                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
+                throw re.rethrowFromSystemServer();
             }
         }
         return UserHandle.USER_NULL;
@@ -3448,7 +3507,7 @@
             try {
                 mService.clearDeviceOwner(packageName);
             } catch (RemoteException re) {
-                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
+                throw re.rethrowFromSystemServer();
             }
         }
     }
@@ -3491,7 +3550,7 @@
             try {
                 return mService.getDeviceOwnerName();
             } catch (RemoteException re) {
-                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
+                throw re.rethrowFromSystemServer();
             }
         }
         return null;
@@ -3544,7 +3603,7 @@
                 mService.setActiveAdmin(admin, false, myUserId);
                 return mService.setProfileOwner(admin, ownerName, myUserId);
             } catch (RemoteException re) {
-                throw new IllegalArgumentException("Couldn't set profile owner.", re);
+                throw re.rethrowFromSystemServer();
             }
         }
         return false;
@@ -3564,7 +3623,7 @@
             try {
                 mService.clearProfileOwner(admin);
             } catch (RemoteException re) {
-                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
+                throw re.rethrowFromSystemServer();
             }
         }
     }
@@ -3578,7 +3637,7 @@
             try {
                 return mService.hasUserSetupCompleted();
             } catch (RemoteException re) {
-                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
+                throw re.rethrowFromSystemServer();
             }
         }
         return true;
@@ -3609,8 +3668,7 @@
                 }
                 return mService.setProfileOwner(admin, ownerName, userHandle);
             } catch (RemoteException re) {
-                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
-                throw new IllegalArgumentException("Couldn't set profile owner.", re);
+                throw re.rethrowFromSystemServer();
             }
         }
         return false;
@@ -3638,7 +3696,7 @@
             try {
                 return mService.setDeviceOwnerLockScreenInfo(admin, info);
             } catch (RemoteException re) {
-                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
+                throw re.rethrowFromSystemServer();
             }
         }
         return false;
@@ -3652,7 +3710,7 @@
             try {
                 return mService.getDeviceOwnerLockScreenInfo();
             } catch (RemoteException re) {
-                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
+                throw re.rethrowFromSystemServer();
             }
         }
         return null;
@@ -3665,7 +3723,9 @@
      * be hidden, it will not show up in recents, will not be able to show toasts or dialogs
      * or ring the device.
      *
-     * <p>The package must already be installed.
+     * <p>The package must already be installed. If the package is uninstalled while suspended
+     * the package will no longer be suspended. The admin can block this by using
+     * {@link #setUninstallBlocked}.
      *
      * @param admin The name of the admin component to check.
      * @param packageNames The package names to suspend or unsuspend.
@@ -3680,7 +3740,7 @@
             try {
                 return mService.setPackagesSuspended(admin, packageNames, suspended);
             } catch (RemoteException re) {
-                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
+                throw re.rethrowFromSystemServer();
             }
         }
         return packageNames;
@@ -3699,7 +3759,7 @@
             try {
                 return mService.getPackageSuspended(admin, packageName);
             } catch (RemoteException e) {
-                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+                throw e.rethrowFromSystemServer();
             }
         }
         return false;
@@ -3718,7 +3778,7 @@
             try {
                 mService.setProfileEnabled(admin);
             } catch (RemoteException e) {
-                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+                throw e.rethrowFromSystemServer();
             }
         }
     }
@@ -3739,7 +3799,7 @@
             try {
                 mService.setProfileName(admin, profileName);
             } catch (RemoteException e) {
-                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+                throw e.rethrowFromSystemServer();
             }
         }
     }
@@ -3759,7 +3819,7 @@
                 return profileOwner != null
                         && profileOwner.getPackageName().equals(packageName);
             } catch (RemoteException re) {
-                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
+                throw re.rethrowFromSystemServer();
             }
         }
         return false;
@@ -3785,9 +3845,7 @@
             try {
                 return mService.getProfileOwner(userId);
             } catch (RemoteException re) {
-                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
-                throw new IllegalArgumentException(
-                        "Requested profile owner for invalid userId", re);
+                throw re.rethrowFromSystemServer();
             }
         }
         return null;
@@ -3804,9 +3862,7 @@
             try {
                 return mService.getProfileOwnerName(Process.myUserHandle().getIdentifier());
             } catch (RemoteException re) {
-                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
-                throw new IllegalArgumentException(
-                        "Requested profile owner for invalid userId", re);
+                throw re.rethrowFromSystemServer();
             }
         }
         return null;
@@ -3825,9 +3881,7 @@
             try {
                 return mService.getProfileOwnerName(userId);
             } catch (RemoteException re) {
-                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
-                throw new IllegalArgumentException(
-                        "Requested profile owner for invalid userId", re);
+                throw re.rethrowFromSystemServer();
             }
         }
         return null;
@@ -3856,7 +3910,7 @@
             try {
                 mService.addPersistentPreferredActivity(admin, filter, activity);
             } catch (RemoteException e) {
-                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+                throw e.rethrowFromSystemServer();
             }
         }
     }
@@ -3877,7 +3931,7 @@
             try {
                 mService.clearPackagePersistentPreferredActivities(admin, packageName);
             } catch (RemoteException e) {
-                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+                throw e.rethrowFromSystemServer();
             }
         }
     }
@@ -3903,7 +3957,7 @@
             try {
                 mService.setApplicationRestrictionsManagingPackage(admin, packageName);
             } catch (RemoteException e) {
-                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+                throw e.rethrowFromSystemServer();
             }
         }
     }
@@ -3921,7 +3975,7 @@
             try {
                 return mService.getApplicationRestrictionsManagingPackage(admin);
             } catch (RemoteException e) {
-                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+                throw e.rethrowFromSystemServer();
             }
         }
         return null;
@@ -3937,7 +3991,7 @@
             try {
                 return mService.isCallerApplicationRestrictionsManagingPackage();
             } catch (RemoteException e) {
-                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+                throw e.rethrowFromSystemServer();
             }
         }
         return false;
@@ -3982,7 +4036,7 @@
             try {
                 mService.setApplicationRestrictions(admin, packageName, settings);
             } catch (RemoteException e) {
-                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+                throw e.rethrowFromSystemServer();
             }
         }
     }
@@ -4012,7 +4066,7 @@
             try {
                 mService.setTrustAgentConfiguration(admin, target, configuration);
             } catch (RemoteException e) {
-                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+                throw e.rethrowFromSystemServer();
             }
         }
     }
@@ -4043,7 +4097,7 @@
             try {
                 return mService.getTrustAgentConfiguration(admin, agent, userHandle);
             } catch (RemoteException e) {
-                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+                throw e.rethrowFromSystemServer();
             }
         }
         return new ArrayList<PersistableBundle>(); // empty list
@@ -4064,7 +4118,7 @@
             try {
                 mService.setCrossProfileCallerIdDisabled(admin, disabled);
             } catch (RemoteException e) {
-                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+                throw e.rethrowFromSystemServer();
             }
         }
     }
@@ -4083,7 +4137,7 @@
             try {
                 return mService.getCrossProfileCallerIdDisabled(admin);
             } catch (RemoteException e) {
-                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+                throw e.rethrowFromSystemServer();
             }
         }
         return false;
@@ -4100,7 +4154,7 @@
             try {
                 return mService.getCrossProfileCallerIdDisabledForUser(userHandle.getIdentifier());
             } catch (RemoteException e) {
-                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+                throw e.rethrowFromSystemServer();
             }
         }
         return false;
@@ -4122,7 +4176,7 @@
             try {
                 mService.setCrossProfileContactsSearchDisabled(admin, disabled);
             } catch (RemoteException e) {
-                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+                throw e.rethrowFromSystemServer();
             }
         }
     }
@@ -4141,7 +4195,7 @@
             try {
                 return mService.getCrossProfileContactsSearchDisabled(admin);
             } catch (RemoteException e) {
-                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+                throw e.rethrowFromSystemServer();
             }
         }
         return false;
@@ -4160,7 +4214,7 @@
                 return mService
                         .getCrossProfileContactsSearchDisabledForUser(userHandle.getIdentifier());
             } catch (RemoteException e) {
-                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+                throw e.rethrowFromSystemServer();
             }
         }
         return false;
@@ -4178,7 +4232,7 @@
                 mService.startManagedQuickContact(actualLookupKey, actualContactId,
                         isContactIdIgnored, directoryId, originalIntent);
             } catch (RemoteException e) {
-                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+                throw e.rethrowFromSystemServer();
             }
         }
     }
@@ -4212,7 +4266,7 @@
             try {
                 mService.setBluetoothContactSharingDisabled(admin, disabled);
             } catch (RemoteException e) {
-                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+                throw e.rethrowFromSystemServer();
             }
         }
     }
@@ -4234,7 +4288,7 @@
             try {
                 return mService.getBluetoothContactSharingDisabled(admin);
             } catch (RemoteException e) {
-                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+                throw e.rethrowFromSystemServer();
             }
         }
         return true;
@@ -4254,7 +4308,7 @@
                 return mService.getBluetoothContactSharingDisabledForUser(userHandle
                         .getIdentifier());
             } catch (RemoteException e) {
-                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+                throw e.rethrowFromSystemServer();
             }
         }
         return true;
@@ -4276,7 +4330,7 @@
             try {
                 mService.addCrossProfileIntentFilter(admin, filter, flags);
             } catch (RemoteException e) {
-                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+                throw e.rethrowFromSystemServer();
             }
         }
     }
@@ -4292,7 +4346,7 @@
             try {
                 mService.clearCrossProfileIntentFilters(admin);
             } catch (RemoteException e) {
-                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+                throw e.rethrowFromSystemServer();
             }
         }
     }
@@ -4324,7 +4378,7 @@
             try {
                 return mService.setPermittedAccessibilityServices(admin, packageNames);
             } catch (RemoteException e) {
-                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+                throw e.rethrowFromSystemServer();
             }
         }
         return false;
@@ -4344,7 +4398,7 @@
             try {
                 return mService.getPermittedAccessibilityServices(admin);
             } catch (RemoteException e) {
-                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+                throw e.rethrowFromSystemServer();
             }
         }
         return null;
@@ -4367,7 +4421,7 @@
                 return mService.isAccessibilityServicePermittedByAdmin(admin, packageName,
                         userHandle);
             } catch (RemoteException e) {
-                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+                throw e.rethrowFromSystemServer();
             }
         }
         return false;
@@ -4391,7 +4445,7 @@
             try {
                 return mService.getPermittedAccessibilityServicesForUser(userId);
             } catch (RemoteException e) {
-                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+                throw e.rethrowFromSystemServer();
             }
         }
         return null;
@@ -4425,7 +4479,7 @@
             try {
                 return mService.setPermittedInputMethods(admin, packageNames);
             } catch (RemoteException e) {
-                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+                throw e.rethrowFromSystemServer();
             }
         }
         return false;
@@ -4446,7 +4500,7 @@
             try {
                 return mService.getPermittedInputMethods(admin);
             } catch (RemoteException e) {
-                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+                throw e.rethrowFromSystemServer();
             }
         }
         return null;
@@ -4468,7 +4522,7 @@
             try {
                 return mService.isInputMethodPermittedByAdmin(admin, packageName, userHandle);
             } catch (RemoteException e) {
-                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+                throw e.rethrowFromSystemServer();
             }
         }
         return false;
@@ -4491,7 +4545,7 @@
             try {
                 return mService.getPermittedInputMethodsForCurrentUser();
             } catch (RemoteException e) {
-                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+                throw e.rethrowFromSystemServer();
             }
         }
         return null;
@@ -4511,7 +4565,7 @@
             try {
                 return mService.getKeepUninstalledPackages(admin);
             } catch (RemoteException e) {
-                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+                throw e.rethrowFromSystemServer();
             }
         }
         return null;
@@ -4534,7 +4588,7 @@
             try {
                 mService.setKeepUninstalledPackages(admin, packageNames);
             } catch (RemoteException e) {
-                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+                throw e.rethrowFromSystemServer();
             }
         }
     }
@@ -4639,9 +4693,8 @@
         try {
             return mService.createAndManageUser(admin, name, profileOwner, adminExtras, flags);
         } catch (RemoteException re) {
-            Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
+            throw re.rethrowFromSystemServer();
         }
-        return null;
     }
 
     /**
@@ -4656,8 +4709,7 @@
         try {
             return mService.removeUser(admin, userHandle);
         } catch (RemoteException re) {
-            Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
-            return false;
+            throw re.rethrowFromSystemServer();
         }
     }
 
@@ -4674,8 +4726,7 @@
         try {
             return mService.switchUser(admin, userHandle);
         } catch (RemoteException re) {
-            Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
-            return false;
+            throw re.rethrowFromSystemServer();
         }
     }
 
@@ -4701,7 +4752,7 @@
             try {
                 return mService.getApplicationRestrictions(admin, packageName);
             } catch (RemoteException e) {
-                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+                throw e.rethrowFromSystemServer();
             }
         }
         return null;
@@ -4723,7 +4774,7 @@
             try {
                 mService.setUserRestriction(admin, key, true);
             } catch (RemoteException e) {
-                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+                throw e.rethrowFromSystemServer();
             }
         }
     }
@@ -4744,7 +4795,7 @@
             try {
                 mService.setUserRestriction(admin, key, false);
             } catch (RemoteException e) {
-                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+                throw e.rethrowFromSystemServer();
             }
         }
     }
@@ -4771,7 +4822,7 @@
             try {
                 ret = mService.getUserRestrictions(admin, userHandle);
             } catch (RemoteException e) {
-                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+                throw e.rethrowFromSystemServer();
             }
         }
         return ret == null ? new Bundle() : ret;
@@ -4793,7 +4844,7 @@
             try {
                 return mService.setApplicationHidden(admin, packageName, hidden);
             } catch (RemoteException e) {
-                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+                throw e.rethrowFromSystemServer();
             }
         }
         return false;
@@ -4811,7 +4862,7 @@
             try {
                 return mService.isApplicationHidden(admin, packageName);
             } catch (RemoteException e) {
-                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+                throw e.rethrowFromSystemServer();
             }
         }
         return false;
@@ -4829,7 +4880,7 @@
             try {
                 mService.enableSystemApp(admin, packageName);
             } catch (RemoteException e) {
-                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+                throw e.rethrowFromSystemServer();
             }
         }
     }
@@ -4848,7 +4899,7 @@
             try {
                 return mService.enableSystemAppWithIntent(admin, intent);
             } catch (RemoteException e) {
-                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+                throw e.rethrowFromSystemServer();
             }
         }
         return 0;
@@ -4879,7 +4930,7 @@
             try {
                 mService.setAccountManagementDisabled(admin, accountType, disabled);
             } catch (RemoteException e) {
-                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+                throw e.rethrowFromSystemServer();
             }
         }
     }
@@ -4907,7 +4958,7 @@
             try {
                 return mService.getAccountTypesWithManagementDisabledAsUser(userId);
             } catch (RemoteException e) {
-                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+                throw e.rethrowFromSystemServer();
             }
         }
 
@@ -4938,7 +4989,7 @@
             try {
                 mService.setLockTaskPackages(admin, packages);
             } catch (RemoteException e) {
-                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+                throw e.rethrowFromSystemServer();
             }
         }
     }
@@ -4954,7 +5005,7 @@
             try {
                 return mService.getLockTaskPackages(admin);
             } catch (RemoteException e) {
-                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+                throw e.rethrowFromSystemServer();
             }
         }
         return null;
@@ -4970,7 +5021,7 @@
             try {
                 return mService.isLockTaskPermitted(pkg);
             } catch (RemoteException e) {
-                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+                throw e.rethrowFromSystemServer();
             }
         }
         return false;
@@ -5017,7 +5068,7 @@
             try {
                 mService.setGlobalSetting(admin, setting, value);
             } catch (RemoteException e) {
-                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+                throw e.rethrowFromSystemServer();
             }
         }
     }
@@ -5045,7 +5096,7 @@
             try {
                 mService.setSecureSetting(admin, setting, value);
             } catch (RemoteException e) {
-                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+                throw e.rethrowFromSystemServer();
             }
         }
     }
@@ -5066,7 +5117,7 @@
             try {
                 mService.setRestrictionsProvider(admin, provider);
             } catch (RemoteException re) {
-                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
+                throw re.rethrowFromSystemServer();
             }
         }
     }
@@ -5082,7 +5133,7 @@
             try {
                 mService.setMasterVolumeMuted(admin, on);
             } catch (RemoteException re) {
-                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
+                throw re.rethrowFromSystemServer();
             }
         }
     }
@@ -5098,7 +5149,7 @@
             try {
                 return mService.isMasterVolumeMuted(admin);
             } catch (RemoteException re) {
-                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
+                throw re.rethrowFromSystemServer();
             }
         }
         return false;
@@ -5118,7 +5169,7 @@
             try {
                 mService.setUninstallBlocked(admin, packageName, uninstallBlocked);
             } catch (RemoteException re) {
-                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
+                throw re.rethrowFromSystemServer();
             }
         }
     }
@@ -5142,7 +5193,7 @@
             try {
                 return mService.isUninstallBlocked(admin, packageName);
             } catch (RemoteException re) {
-                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
+                throw re.rethrowFromSystemServer();
             }
         }
         return false;
@@ -5170,7 +5221,7 @@
             try {
                 return mService.addCrossProfileWidgetProvider(admin, packageName);
             } catch (RemoteException re) {
-                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
+                throw re.rethrowFromSystemServer();
             }
         }
         return false;
@@ -5198,7 +5249,7 @@
             try {
                 return mService.removeCrossProfileWidgetProvider(admin, packageName);
             } catch (RemoteException re) {
-                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
+                throw re.rethrowFromSystemServer();
             }
         }
         return false;
@@ -5222,7 +5273,7 @@
                     return providers;
                 }
             } catch (RemoteException re) {
-                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
+                throw re.rethrowFromSystemServer();
             }
         }
         return Collections.emptyList();
@@ -5238,7 +5289,7 @@
         try {
             mService.setUserIcon(admin, icon);
         } catch (RemoteException re) {
-            Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
+            throw re.rethrowFromSystemServer();
         }
     }
 
@@ -5258,7 +5309,7 @@
             try {
                 mService.setSystemUpdatePolicy(admin, policy);
             } catch (RemoteException re) {
-                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
+                throw re.rethrowFromSystemServer();
             }
         }
     }
@@ -5273,7 +5324,7 @@
             try {
                 return mService.getSystemUpdatePolicy();
             } catch (RemoteException re) {
-                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
+                throw re.rethrowFromSystemServer();
             }
         }
         return null;
@@ -5297,8 +5348,7 @@
         try {
             return mService.setKeyguardDisabled(admin, disabled);
         } catch (RemoteException re) {
-            Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
-            return false;
+            throw re.rethrowFromSystemServer();
         }
     }
 
@@ -5317,8 +5367,7 @@
         try {
             return mService.setStatusBarDisabled(admin, disabled);
         } catch (RemoteException re) {
-            Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
-            return false;
+            throw re.rethrowFromSystemServer();
         }
     }
 
@@ -5337,7 +5386,7 @@
             try {
                 mService.notifyPendingSystemUpdate(updateReceivedTime);
             } catch (RemoteException re) {
-                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
+                throw re.rethrowFromSystemServer();
             }
         }
     }
@@ -5363,7 +5412,7 @@
         try {
             mService.setPermissionPolicy(admin, policy);
         } catch (RemoteException re) {
-            Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
+            throw re.rethrowFromSystemServer();
         }
     }
 
@@ -5377,7 +5426,7 @@
         try {
             return mService.getPermissionPolicy(admin);
         } catch (RemoteException re) {
-            return PERMISSION_POLICY_PROMPT;
+            throw re.rethrowFromSystemServer();
         }
     }
 
@@ -5414,8 +5463,7 @@
         try {
             return mService.setPermissionGrantState(admin, packageName, permission, grantState);
         } catch (RemoteException re) {
-            Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
-            return false;
+            throw re.rethrowFromSystemServer();
         }
     }
 
@@ -5441,8 +5489,7 @@
         try {
             return mService.getPermissionGrantState(admin, packageName, permission);
         } catch (RemoteException re) {
-            Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
-            return PERMISSION_GRANT_STATE_DEFAULT;
+            throw re.rethrowFromSystemServer();
         }
     }
 
@@ -5460,8 +5507,7 @@
         try {
             return mService.isProvisioningAllowed(action);
         } catch (RemoteException re) {
-            Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
-            return false;
+            throw re.rethrowFromSystemServer();
         }
     }
 
@@ -5477,8 +5523,7 @@
         try {
             return mService.isManagedProfile(admin);
         } catch (RemoteException re) {
-            Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
-            return false;
+            throw re.rethrowFromSystemServer();
         }
     }
 
@@ -5493,25 +5538,24 @@
         try {
             return mService.isSystemOnlyUser(admin);
         } catch (RemoteException re) {
-            Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
-            return false;
+            throw re.rethrowFromSystemServer();
         }
     }
 
     /**
      * Called by device owner to get the MAC address of the Wi-Fi device.
      *
+     * @param admin Which device owner this request is associated with.
      * @return the MAC address of the Wi-Fi device, or null when the information is not
      * available. (For example, Wi-Fi hasn't been enabled, or the device doesn't support Wi-Fi.)
      *
      * <p>The address will be in the {@code XX:XX:XX:XX:XX:XX} format.
      */
-    public String getWifiMacAddress() {
+    public String getWifiMacAddress(@NonNull ComponentName admin) {
         try {
-            return mService.getWifiMacAddress();
+            return mService.getWifiMacAddress(admin);
         } catch (RemoteException re) {
-            Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
-            return null;
+            throw re.rethrowFromSystemServer();
         }
     }
 
@@ -5522,7 +5566,7 @@
         try {
             mService.reboot(admin);
         } catch (RemoteException re) {
-            Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
+            throw re.rethrowFromSystemServer();
         }
     }
 
@@ -5552,7 +5596,7 @@
             try {
                 mService.setShortSupportMessage(admin, message);
             } catch (RemoteException e) {
-                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+                throw e.rethrowFromSystemServer();
             }
         }
     }
@@ -5569,7 +5613,7 @@
             try {
                 return mService.getShortSupportMessage(admin);
             } catch (RemoteException e) {
-                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+                throw e.rethrowFromSystemServer();
             }
         }
         return null;
@@ -5595,7 +5639,7 @@
             try {
                 mService.setLongSupportMessage(admin, message);
             } catch (RemoteException e) {
-                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+                throw e.rethrowFromSystemServer();
             }
         }
     }
@@ -5612,7 +5656,7 @@
             try {
                 return mService.getLongSupportMessage(admin);
             } catch (RemoteException e) {
-                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+                throw e.rethrowFromSystemServer();
             }
         }
         return null;
@@ -5632,7 +5676,7 @@
             try {
                 return mService.getShortSupportMessageForUser(admin, userHandle);
             } catch (RemoteException e) {
-                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+                throw e.rethrowFromSystemServer();
             }
         }
         return null;
@@ -5653,7 +5697,7 @@
             try {
                 return mService.getLongSupportMessageForUser(admin, userHandle);
             } catch (RemoteException e) {
-                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+                throw e.rethrowFromSystemServer();
             }
         }
         return null;
@@ -5674,8 +5718,7 @@
             }
             return new DevicePolicyManager(mContext, true);
         } catch (RemoteException e) {
-            Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
-            return null;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -5686,6 +5729,9 @@
      * <p> Device logs contain various information intended for security auditing purposes.
      * See {@link SecurityEvent} for details.
      *
+     * <p>There must be only one user on the device, managed by the device owner.
+     * Otherwise a {@link SecurityException} will be thrown.
+     *
      * @param admin Which device owner this request is associated with.
      * @param enabled whether device logging should be enabled or not.
      * @see #retrieveDeviceLogs
@@ -5694,13 +5740,16 @@
         try {
             mService.setDeviceLoggingEnabled(admin, enabled);
         } catch (RemoteException re) {
-            Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
+            throw re.rethrowFromSystemServer();
         }
     }
 
     /**
      * Return whether device logging is enabled or not by the device owner.
      *
+     * <p>Can only be called by the device owner, otherwise a {@link SecurityException} will be
+     * thrown.
+     *
      * @param admin Which device owner this request is associated with.
      * @return {@code true} if device logging is enabled by device owner, {@code false} otherwise.
      */
@@ -5708,8 +5757,7 @@
         try {
             return mService.getDeviceLoggingEnabled(admin);
         } catch (RemoteException re) {
-            Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
-            return false;
+            throw re.rethrowFromSystemServer();
         }
     }
 
@@ -5720,6 +5768,9 @@
      * <p> Access to the logs is rate limited and it will only return new logs after the device
      * owner has been notified via {@link DeviceAdminReceiver#onSecurityLogsAvailable}.
      *
+     * <p>There must be only one user on the device, managed by the device owner.
+     * Otherwise a {@link SecurityException} will be thrown.
+     *
      * @param admin Which device owner this request is associated with.
      * @return the new batch of device logs which is a list of {@link SecurityEvent},
      * or {@code null} if rate limitation is exceeded or if logging is currently disabled.
@@ -5734,8 +5785,7 @@
                 return null;
             }
         } catch (RemoteException re) {
-            Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
-            return null;
+            throw re.rethrowFromSystemServer();
         }
     }
 
@@ -5764,6 +5814,9 @@
      * result, this API is provided as best-effort and the returned logs may contain corrupted data.
      * </strong>
      *
+     * <p>There must be only one user on the device, managed by the device owner.
+     * Otherwise a {@link SecurityException} will be thrown.
+     *
      * @param admin Which device owner this request is associated with.
      * @return Device logs from before the latest reboot of the system.
      */
@@ -5772,8 +5825,7 @@
             ParceledListSlice<SecurityEvent> list = mService.retrievePreviousDeviceLogs(admin);
             return list.getList();
         } catch (RemoteException re) {
-            Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
-            return Collections.<SecurityEvent>emptyList();
+            throw re.rethrowFromSystemServer();
         }
     }
 
@@ -5792,7 +5844,7 @@
         try {
             mService.setOrganizationColor(admin, color);
         } catch (RemoteException re) {
-            Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
+            throw re.rethrowFromSystemServer();
         }
     }
 
@@ -5811,7 +5863,7 @@
         try {
             mService.setOrganizationColorForUser(color, userId);
         } catch (RemoteException re) {
-            Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
+            throw re.rethrowFromSystemServer();
         }
     }
 
@@ -5826,8 +5878,7 @@
         try {
             return mService.getOrganizationColor(admin);
         } catch (RemoteException re) {
-            Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
-            return 0;
+            throw re.rethrowFromSystemServer();
         }
     }
 
@@ -5842,8 +5893,7 @@
         try {
             return mService.getOrganizationColorForUser(userHandle);
         } catch (RemoteException re) {
-            Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
-            return 0;
+            throw re.rethrowFromSystemServer();
         }
     }
 
@@ -5862,7 +5912,7 @@
         try {
             mService.setOrganizationName(admin, title);
         } catch (RemoteException re) {
-            Log.w(TAG, REMOTE_EXCEPTION_MESSAGE);
+            throw re.rethrowFromSystemServer();
         }
     }
 
@@ -5877,8 +5927,7 @@
         try {
             return mService.getOrganizationName(admin);
         } catch (RemoteException re) {
-            Log.w(TAG, REMOTE_EXCEPTION_MESSAGE);
-            return null;
+            throw re.rethrowFromSystemServer();
         }
     }
 
@@ -5894,8 +5943,7 @@
         try {
             return mService.getOrganizationNameForUser(userHandle);
         } catch (RemoteException re) {
-            Log.w(TAG, REMOTE_EXCEPTION_MESSAGE);
-            return null;
+            throw re.rethrowFromSystemServer();
         }
     }
 
@@ -5911,7 +5959,7 @@
             try {
                 return mService.getUserProvisioningState();
             } catch (RemoteException e) {
-                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+                throw e.rethrowFromSystemServer();
             }
         }
         return STATE_USER_UNMANAGED;
@@ -5929,7 +5977,7 @@
             try {
                 mService.setUserProvisioningState(state, userHandle);
             } catch (RemoteException e) {
-                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+                throw e.rethrowFromSystemServer();
             }
         }
     }
@@ -5956,7 +6004,7 @@
         try {
             mService.setAffiliationIds(admin, new ArrayList<String>(ids));
         } catch (RemoteException e) {
-            Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -5971,8 +6019,7 @@
         try {
             return mService != null && mService.isAffiliatedUser();
         } catch (RemoteException e) {
-            Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
-            return false;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -5987,8 +6034,7 @@
         try {
             return mService.isUninstallInQueue(packageName);
         } catch (RemoteException re) {
-            Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
-            return false;
+            throw re.rethrowFromSystemServer();
         }
     }
 
@@ -6000,7 +6046,7 @@
         try {
             mService.uninstallPackageWithActiveAdmins(packageName);
         } catch (RemoteException re) {
-            Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
+            throw re.rethrowFromSystemServer();
         }
     }
 }
diff --git a/core/java/android/app/admin/DevicePolicyManagerInternal.java b/core/java/android/app/admin/DevicePolicyManagerInternal.java
index 0a0d77d..61b40d4 100644
--- a/core/java/android/app/admin/DevicePolicyManagerInternal.java
+++ b/core/java/android/app/admin/DevicePolicyManagerInternal.java
@@ -16,6 +16,8 @@
 
 package android.app.admin;
 
+import android.os.UserHandle;
+
 import java.util.List;
 
 /**
@@ -69,4 +71,13 @@
      * @return true if the uid is an active admin with the given policy.
      */
     public abstract boolean isActiveAdminWithPolicy(int uid, int reqPolicy);
+
+    /**
+     * Checks if a given package has a device or a profile owner for the given user.
+     * </br><em>Does <b>not</b> support negative userIds like {@link UserHandle#USER_ALL}</em>
+     * @param packageName The package to check
+     * @param userId the userId to check for.
+     * @return true if package has a device or profile owner, false otherwise.
+     */
+    public abstract boolean hasDeviceOwnerOrProfileOwner(String packageName, int userId);
 }
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index b7a16aa..dc73e26 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -262,7 +262,7 @@
     List<String> getKeepUninstalledPackages(in ComponentName admin);
     boolean isManagedProfile(in ComponentName admin);
     boolean isSystemOnlyUser(in ComponentName admin);
-    String getWifiMacAddress();
+    String getWifiMacAddress(in ComponentName admin);
     void reboot(in ComponentName admin);
 
     void setShortSupportMessage(in ComponentName admin, in String message);
diff --git a/core/java/android/app/job/JobInfo.java b/core/java/android/app/job/JobInfo.java
index 4cbaf6c..039c9d7 100644
--- a/core/java/android/app/job/JobInfo.java
+++ b/core/java/android/app/job/JobInfo.java
@@ -102,12 +102,19 @@
     public static final int PRIORITY_SYNC_INITIALIZATION = 20;
 
     /**
-     * Value of {@link #getPriority} for the current foreground app (overrides the supplied
+     * Value of {@link #getPriority} for a foreground app (overrides the supplied
      * JobInfo priority if it is smaller).
      * @hide
      */
     public static final int PRIORITY_FOREGROUND_APP = 30;
 
+    /**
+     * Value of {@link #getPriority} for the current top app (overrides the supplied
+     * JobInfo priority if it is smaller).
+     * @hide
+     */
+    public static final int PRIORITY_TOP_APP = 40;
+
     private final int jobId;
     private final PersistableBundle extras;
     private final ComponentName service;
diff --git a/core/java/android/app/trust/TrustManager.java b/core/java/android/app/trust/TrustManager.java
index 999d826..0f5cb6f 100644
--- a/core/java/android/app/trust/TrustManager.java
+++ b/core/java/android/app/trust/TrustManager.java
@@ -16,8 +16,6 @@
 
 package android.app.trust;
 
-import com.android.internal.widget.LockPatternUtils;
-
 import android.Manifest;
 import android.annotation.RequiresPermission;
 import android.os.Handler;
@@ -26,7 +24,8 @@
 import android.os.Message;
 import android.os.RemoteException;
 import android.util.ArrayMap;
-import android.util.Log;
+
+import com.android.internal.widget.LockPatternUtils;
 
 /**
  * See {@link com.android.server.trust.TrustManagerService}
@@ -62,7 +61,7 @@
         try {
             mService.setDeviceLockedForUser(userId, locked);
         } catch (RemoteException e) {
-            onError(e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -77,7 +76,7 @@
         try {
             mService.reportUnlockAttempt(successful, userId);
         } catch (RemoteException e) {
-            onError(e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -90,7 +89,7 @@
         try {
             mService.reportEnabledTrustAgentsChanged(userId);
         } catch (RemoteException e) {
-            onError(e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -103,7 +102,7 @@
         try {
             mService.reportKeyguardShowingChanged();
         } catch (RemoteException e) {
-            onError(e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -134,7 +133,7 @@
             mService.registerTrustListener(iTrustListener);
             mTrustListeners.put(trustListener, iTrustListener);
         } catch (RemoteException e) {
-            onError(e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -149,7 +148,7 @@
             try {
                 mService.unregisterTrustListener(iTrustListener);
             } catch (RemoteException e) {
-                onError(e);
+                throw e.rethrowFromSystemServer();
             }
         }
     }
@@ -163,16 +162,10 @@
         try {
             return mService.isTrustUsuallyManaged(userId);
         } catch (RemoteException e) {
-            return false;
+            throw e.rethrowFromSystemServer();
         }
     }
 
-
-
-    private void onError(Exception e) {
-        Log.e(TAG, "Error while calling TrustManagerService", e);
-    }
-
     private final Handler mHandler = new Handler(Looper.getMainLooper()) {
         @Override
         public void handleMessage(Message msg) {
diff --git a/core/java/android/appwidget/AppWidgetManager.java b/core/java/android/appwidget/AppWidgetManager.java
index 278c9d6..9f654c2 100644
--- a/core/java/android/appwidget/AppWidgetManager.java
+++ b/core/java/android/appwidget/AppWidgetManager.java
@@ -472,9 +472,8 @@
         }
         try {
             mService.updateAppWidgetIds(mPackageName, appWidgetIds, views);
-        }
-        catch (RemoteException e) {
-            throw new RuntimeException("system server dead?", e);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -495,9 +494,8 @@
         }
         try {
             mService.updateAppWidgetOptions(mPackageName, appWidgetId, options);
-        }
-        catch (RemoteException e) {
-            throw new RuntimeException("system server dead?", e);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -518,9 +516,8 @@
         }
         try {
             return mService.getAppWidgetOptions(mPackageName, appWidgetId);
-        }
-        catch (RemoteException e) {
-            throw new RuntimeException("system server dead?", e);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -581,7 +578,7 @@
         try {
             mService.partiallyUpdateAppWidgetIds(mPackageName, appWidgetIds, views);
         } catch (RemoteException e) {
-            throw new RuntimeException("system server dead?", e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -635,9 +632,8 @@
         }
         try {
             mService.updateAppWidgetProvider(provider, views);
-        }
-        catch (RemoteException e) {
-            throw new RuntimeException("system server dead?", e);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -654,9 +650,8 @@
         }
         try {
             mService.notifyAppWidgetViewDataChanged(mPackageName, appWidgetIds, viewId);
-        }
-        catch (RemoteException e) {
-            throw new RuntimeException("system server dead?", e);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -764,9 +759,8 @@
                 convertSizesToPixels(info);
             }
             return providers.getList();
-        }
-        catch (RemoteException e) {
-            throw new RuntimeException("system server dead?", e);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -787,9 +781,8 @@
                 convertSizesToPixels(info);
             }
             return info;
-        }
-        catch (RemoteException e) {
-            throw new RuntimeException("system server dead?", e);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -918,9 +911,8 @@
         }
         try {
             return mService.hasBindAppWidgetPermission(packageName, userId);
-        }
-        catch (RemoteException e) {
-            throw new RuntimeException("system server dead?", e);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -939,9 +931,8 @@
         }
         try {
             return mService.hasBindAppWidgetPermission(packageName, UserHandle.myUserId());
-        }
-        catch (RemoteException e) {
-            throw new RuntimeException("system server dead?", e);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -979,9 +970,8 @@
         }
         try {
             mService.setBindAppWidgetPermission(packageName, userId, permission);
-        }
-        catch (RemoteException e) {
-            throw new RuntimeException("system server dead?", e);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1005,9 +995,8 @@
         }
         try {
             mService.bindRemoteViewsService(packageName, appWidgetId, intent, connection);
-        }
-        catch (RemoteException e) {
-            throw new RuntimeException("system server dead?", e);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1029,9 +1018,8 @@
         }
         try {
             mService.unbindRemoteViewsService(packageName, appWidgetId, intent);
-        }
-        catch (RemoteException e) {
-            throw new RuntimeException("system server dead?", e);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1048,9 +1036,8 @@
         }
         try {
             return mService.getAppWidgetIds(provider);
-        }
-        catch (RemoteException e) {
-            throw new RuntimeException("system server dead?", e);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1063,8 +1050,8 @@
         }
         try {
             return mService.isBoundWidgetPackage(packageName, userId);
-        } catch (RemoteException re) {
-            throw new RuntimeException("system server dead?", re);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1076,9 +1063,8 @@
         try {
             return mService.bindAppWidgetId(mPackageName, appWidgetId,
                     profileId, provider, options);
-        }
-        catch (RemoteException e) {
-            throw new RuntimeException("system server dead?", e);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
         }
     }
 
diff --git a/core/java/android/auditing/SecurityLog.java b/core/java/android/auditing/SecurityLog.java
index 829685b..13823a2 100644
--- a/core/java/android/auditing/SecurityLog.java
+++ b/core/java/android/auditing/SecurityLog.java
@@ -116,7 +116,7 @@
     /**
      * A class representing a security event log entry.
      */
-    public static class SecurityEvent implements Parcelable {
+    public static final class SecurityEvent implements Parcelable {
         private Event mEvent;
 
         /** @hide */
diff --git a/core/java/android/bluetooth/OobData.java b/core/java/android/bluetooth/OobData.java
index 01f72ef..70d47ee 100644
--- a/core/java/android/bluetooth/OobData.java
+++ b/core/java/android/bluetooth/OobData.java
@@ -23,6 +23,7 @@
 
 /**
  * Out Of Band Data for Bluetooth device.
+ * @hide
  */
 public class OobData implements Parcelable {
     private byte[] securityManagerTk;
diff --git a/core/java/android/content/ClipboardManager.java b/core/java/android/content/ClipboardManager.java
index e67da2b..1266f73 100644
--- a/core/java/android/content/ClipboardManager.java
+++ b/core/java/android/content/ClipboardManager.java
@@ -122,6 +122,7 @@
             }
             getService().setPrimaryClip(clip, mContext.getOpPackageName());
         } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -132,7 +133,7 @@
         try {
             return getService().getPrimaryClip(mContext.getOpPackageName());
         } catch (RemoteException e) {
-            return null;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -144,7 +145,7 @@
         try {
             return getService().getPrimaryClipDescription(mContext.getOpPackageName());
         } catch (RemoteException e) {
-            return null;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -155,7 +156,7 @@
         try {
             return getService().hasPrimaryClip(mContext.getOpPackageName());
         } catch (RemoteException e) {
-            return false;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -166,6 +167,7 @@
                     getService().addPrimaryClipChangedListener(
                             mPrimaryClipChangedServiceListener, mContext.getOpPackageName());
                 } catch (RemoteException e) {
+                    throw e.rethrowFromSystemServer();
                 }
             }
             mPrimaryClipChangedListeners.add(what);
@@ -180,6 +182,7 @@
                     getService().removePrimaryClipChangedListener(
                             mPrimaryClipChangedServiceListener);
                 } catch (RemoteException e) {
+                    throw e.rethrowFromSystemServer();
                 }
             }
         }
@@ -213,7 +216,7 @@
         try {
             return getService().hasClipboardText(mContext.getOpPackageName());
         } catch (RemoteException e) {
-            return false;
+            throw e.rethrowFromSystemServer();
         }
     }
 
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index b935b25..825dd5b 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -2680,6 +2680,7 @@
             RADIO_SERVICE,
             HARDWARE_PROPERTIES_SERVICE,
             //@hide: SOUND_TRIGGER_SERVICE,
+            SHORTCUT_SERVICE,
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface ServiceName {}
@@ -3576,6 +3577,23 @@
     public static final String HARDWARE_PROPERTIES_SERVICE = "hardwareproperties";
 
     /**
+     * TODO Javadoc
+     *
+     * @see #getSystemService
+     * @see android.content.pm.ShortcutManager
+     */
+    public static final String SHORTCUT_SERVICE = "shortcut";
+
+    /**
+     * Use with {@link #getSystemService} to retrieve a
+     * {@link android.os.health.SystemHealthManager} for accessing system health (battery, power,
+     * memory, etc) metrics.
+     *
+     * @see #getSystemService
+     */
+    public static final String SYSTEM_HEALTH_SERVICE = "systemhealth";
+
+    /**
      * Determine whether the given permission is allowed for a particular
      * process and user ID running in the system.
      *
diff --git a/core/java/android/content/RestrictionsManager.java b/core/java/android/content/RestrictionsManager.java
index a7744e7..6893067 100644
--- a/core/java/android/content/RestrictionsManager.java
+++ b/core/java/android/content/RestrictionsManager.java
@@ -422,7 +422,7 @@
                 return mService.getApplicationRestrictions(mContext.getPackageName());
             }
         } catch (RemoteException re) {
-            Log.w(TAG, "Couldn't reach service");
+            throw re.rethrowFromSystemServer();
         }
         return null;
     }
@@ -439,7 +439,7 @@
                 return mService.hasRestrictionsProvider();
             }
         } catch (RemoteException re) {
-            Log.w(TAG, "Couldn't reach service");
+            throw re.rethrowFromSystemServer();
         }
         return false;
     }
@@ -477,7 +477,7 @@
                         request);
             }
         } catch (RemoteException re) {
-            Log.w(TAG, "Couldn't reach service");
+            throw re.rethrowFromSystemServer();
         }
     }
 
@@ -487,7 +487,7 @@
                 return mService.createLocalApprovalIntent();
             }
         } catch (RemoteException re) {
-            Log.w(TAG, "Couldn't reach service");
+            throw re.rethrowFromSystemServer();
         }
         return null;
     }
@@ -519,7 +519,7 @@
                 mService.notifyPermissionResponse(packageName, response);
             }
         } catch (RemoteException re) {
-            Log.w(TAG, "Couldn't reach service");
+            throw re.rethrowFromSystemServer();
         }
     }
 
diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java
index ad174f6..58d75f7 100644
--- a/core/java/android/content/pm/ApplicationInfo.java
+++ b/core/java/android/content/pm/ApplicationInfo.java
@@ -707,6 +707,12 @@
     public int uid;
     
     /**
+     * The minimum SDK version this application can run on. It will not run
+     * on earlier versions.
+     */
+    public String minSdkVersion;
+
+    /**
      * The minimum SDK version this application targets.  It may run on earlier
      * versions, but it knows how to work with any new behavior added at this
      * version.  Will be {@link android.os.Build.VERSION_CODES#CUR_DEVELOPMENT}
@@ -790,7 +796,9 @@
                 pw.println(prefix + "sharedLibraryFiles=" + Arrays.toString(sharedLibraryFiles));
             }
         }
-        pw.println(prefix + "enabled=" + enabled + " targetSdkVersion=" + targetSdkVersion
+        pw.println(prefix + "enabled=" + enabled
+                + " minSdkVersion=" + minSdkVersion
+                + " targetSdkVersion=" + targetSdkVersion
                 + " versionCode=" + versionCode);
         if ((flags&DUMP_FLAG_DETAILS) != 0) {
             if (manageSpaceActivityName != null) {
@@ -884,6 +892,7 @@
         deviceEncryptedDataDir = orig.deviceEncryptedDataDir;
         credentialEncryptedDataDir = orig.credentialEncryptedDataDir;
         uid = orig.uid;
+        minSdkVersion = orig.minSdkVersion;
         targetSdkVersion = orig.targetSdkVersion;
         versionCode = orig.versionCode;
         enabled = orig.enabled;
@@ -938,6 +947,7 @@
         dest.writeString(deviceEncryptedDataDir);
         dest.writeString(credentialEncryptedDataDir);
         dest.writeInt(uid);
+        dest.writeString(minSdkVersion);
         dest.writeInt(targetSdkVersion);
         dest.writeInt(versionCode);
         dest.writeInt(enabled ? 1 : 0);
@@ -992,6 +1002,7 @@
         deviceEncryptedDataDir = source.readString();
         credentialEncryptedDataDir = source.readString();
         uid = source.readInt();
+        minSdkVersion = source.readString();
         targetSdkVersion = source.readInt();
         versionCode = source.readInt();
         enabled = source.readInt() != 0;
diff --git a/core/java/android/content/pm/AppsQueryHelper.java b/core/java/android/content/pm/AppsQueryHelper.java
index e542589..4c01b27 100644
--- a/core/java/android/content/pm/AppsQueryHelper.java
+++ b/core/java/android/content/pm/AppsQueryHelper.java
@@ -171,7 +171,7 @@
             return mPackageManager.getInstalledApplications(PackageManager.GET_UNINSTALLED_PACKAGES
                     | PackageManager.GET_DISABLED_COMPONENTS, userId).getList();
         } catch (RemoteException e) {
-            throw new IllegalStateException("Package manager has died", e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -181,9 +181,9 @@
             return mPackageManager.queryIntentActivities(intent, null,
                     PackageManager.GET_DISABLED_COMPONENTS
                             | PackageManager.GET_UNINSTALLED_PACKAGES,
-                    userId);
+                    userId).getList();
         } catch (RemoteException e) {
-            throw new IllegalStateException("Package manager has died", e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -192,9 +192,9 @@
         try {
             return mPackageManager.queryIntentServices(intent, null,
                     PackageManager.GET_META_DATA
-                            | PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS, userId);
+                            | PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS, userId).getList();
         } catch (RemoteException e) {
-            throw new IllegalStateException("Package manager has died", e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -205,8 +205,7 @@
             return mPackageManager.getPackagesHoldingPermissions(new String[]{perm}, 0,
                     userId).getList();
         } catch (RemoteException e) {
-            throw new IllegalStateException("Package manager has died", e);
+            throw e.rethrowFromSystemServer();
         }
     }
-
 }
diff --git a/core/java/android/content/pm/ContainerEncryptionParams.java b/core/java/android/content/pm/ContainerEncryptionParams.java
deleted file mode 100644
index ab3aa27..0000000
--- a/core/java/android/content/pm/ContainerEncryptionParams.java
+++ /dev/null
@@ -1,384 +0,0 @@
-/*
- * 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.content.pm;
-
-import android.annotation.SystemApi;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.text.TextUtils;
-import android.util.Slog;
-
-import java.security.InvalidAlgorithmParameterException;
-import java.security.spec.AlgorithmParameterSpec;
-import java.util.Arrays;
-
-import javax.crypto.SecretKey;
-import javax.crypto.spec.IvParameterSpec;
-
-/**
- * Represents encryption parameters used to read a container.
- *
- * @deprecated encrypted containers are legacy.
- * @hide
- */
-@SystemApi
-@Deprecated
-public class ContainerEncryptionParams implements Parcelable {
-    protected static final String TAG = "ContainerEncryptionParams";
-
-    /** What we print out first when toString() is called. */
-    private static final String TO_STRING_PREFIX = "ContainerEncryptionParams{";
-
-    /**
-     * Parameter type for parceling that indicates the next parameters are
-     * IvParameters.
-     */
-    private static final int ENC_PARAMS_IV_PARAMETERS = 1;
-
-    /** Parameter type for paceling that indicates there are no MAC parameters. */
-    private static final int MAC_PARAMS_NONE = 1;
-
-    /** The encryption algorithm used. */
-    private final String mEncryptionAlgorithm;
-
-    /** The parameter spec to be used for encryption. */
-    private final IvParameterSpec mEncryptionSpec;
-
-    /** Secret key to be used for decryption. */
-    private final SecretKey mEncryptionKey;
-
-    /** Algorithm name for the MAC to be used. */
-    private final String mMacAlgorithm;
-
-    /** The parameter spec to be used for the MAC tag authentication. */
-    private final AlgorithmParameterSpec mMacSpec;
-
-    /** Secret key to be used for MAC tag authentication. */
-    private final SecretKey mMacKey;
-
-    /** MAC tag authenticating the data in the container. */
-    private final byte[] mMacTag;
-
-    /** Offset into file where authenticated (e.g., MAC protected) data begins. */
-    private final long mAuthenticatedDataStart;
-
-    /** Offset into file where encrypted data begins. */
-    private final long mEncryptedDataStart;
-
-    /**
-     * Offset into file for the end of encrypted data (and, by extension,
-     * authenticated data) in file.
-     */
-    private final long mDataEnd;
-
-    public ContainerEncryptionParams(String encryptionAlgorithm,
-            AlgorithmParameterSpec encryptionSpec, SecretKey encryptionKey)
-            throws InvalidAlgorithmParameterException {
-        this(encryptionAlgorithm, encryptionSpec, encryptionKey, null, null, null, null, -1, -1,
-                -1);
-    }
-
-    /**
-     * Creates container encryption specifications for installing from encrypted
-     * containers.
-     *
-     * @param encryptionAlgorithm encryption algorithm to use; format matches
-     *            JCE
-     * @param encryptionSpec algorithm parameter specification
-     * @param encryptionKey key used for decryption
-     * @param macAlgorithm MAC algorithm to use; format matches JCE
-     * @param macSpec algorithm parameters specification, may be {@code null}
-     * @param macKey key used for authentication (i.e., for the MAC tag)
-     * @param macTag message authentication code (MAC) tag for the authenticated
-     *            data
-     * @param authenticatedDataStart offset of start of authenticated data in
-     *            stream
-     * @param encryptedDataStart offset of start of encrypted data in stream
-     * @param dataEnd offset of the end of both the authenticated and encrypted
-     *            data
-     * @throws InvalidAlgorithmParameterException
-     */
-    public ContainerEncryptionParams(String encryptionAlgorithm,
-            AlgorithmParameterSpec encryptionSpec, SecretKey encryptionKey, String macAlgorithm,
-            AlgorithmParameterSpec macSpec, SecretKey macKey, byte[] macTag,
-            long authenticatedDataStart, long encryptedDataStart, long dataEnd)
-            throws InvalidAlgorithmParameterException {
-        if (TextUtils.isEmpty(encryptionAlgorithm)) {
-            throw new NullPointerException("algorithm == null");
-        } else if (encryptionSpec == null) {
-            throw new NullPointerException("encryptionSpec == null");
-        } else if (encryptionKey == null) {
-            throw new NullPointerException("encryptionKey == null");
-        }
-
-        if (!TextUtils.isEmpty(macAlgorithm)) {
-            if (macKey == null) {
-                throw new NullPointerException("macKey == null");
-            }
-        }
-
-        if (!(encryptionSpec instanceof IvParameterSpec)) {
-            throw new InvalidAlgorithmParameterException(
-                    "Unknown parameter spec class; must be IvParameters");
-        }
-
-        mEncryptionAlgorithm = encryptionAlgorithm;
-        mEncryptionSpec = (IvParameterSpec) encryptionSpec;
-        mEncryptionKey = encryptionKey;
-
-        mMacAlgorithm = macAlgorithm;
-        mMacSpec = macSpec;
-        mMacKey = macKey;
-        mMacTag = macTag;
-
-        mAuthenticatedDataStart = authenticatedDataStart;
-        mEncryptedDataStart = encryptedDataStart;
-        mDataEnd = dataEnd;
-    }
-
-    public String getEncryptionAlgorithm() {
-        return mEncryptionAlgorithm;
-    }
-
-    public AlgorithmParameterSpec getEncryptionSpec() {
-        return mEncryptionSpec;
-    }
-
-    public SecretKey getEncryptionKey() {
-        return mEncryptionKey;
-    }
-
-    public String getMacAlgorithm() {
-        return mMacAlgorithm;
-    }
-
-    public AlgorithmParameterSpec getMacSpec() {
-        return mMacSpec;
-    }
-
-    public SecretKey getMacKey() {
-        return mMacKey;
-    }
-
-    public byte[] getMacTag() {
-        return mMacTag;
-    }
-
-    public long getAuthenticatedDataStart() {
-        return mAuthenticatedDataStart;
-    }
-
-    public long getEncryptedDataStart() {
-        return mEncryptedDataStart;
-    }
-
-    public long getDataEnd() {
-        return mDataEnd;
-    }
-
-    @Override
-    public int describeContents() {
-        return 0;
-    }
-
-    @Override
-    public boolean equals(Object o) {
-        if (this == o) {
-            return true;
-        }
-
-        if (!(o instanceof ContainerEncryptionParams)) {
-            return false;
-        }
-
-        final ContainerEncryptionParams other = (ContainerEncryptionParams) o;
-
-        // Primitive comparison
-        if ((mAuthenticatedDataStart != other.mAuthenticatedDataStart)
-                || (mEncryptedDataStart != other.mEncryptedDataStart)
-                || (mDataEnd != other.mDataEnd)) {
-            return false;
-        }
-
-        // String comparison
-        if (!mEncryptionAlgorithm.equals(other.mEncryptionAlgorithm)
-                || !mMacAlgorithm.equals(other.mMacAlgorithm)) {
-            return false;
-        }
-
-        // Object comparison
-        if (!isSecretKeyEqual(mEncryptionKey, other.mEncryptionKey)
-                || !isSecretKeyEqual(mMacKey, other.mMacKey)) {
-            return false;
-        }
-
-        if (!Arrays.equals(mEncryptionSpec.getIV(), other.mEncryptionSpec.getIV())
-                || !Arrays.equals(mMacTag, other.mMacTag) || (mMacSpec != other.mMacSpec)) {
-            return false;
-        }
-
-        return true;
-    }
-
-    private static final boolean isSecretKeyEqual(SecretKey key1, SecretKey key2) {
-        final String keyFormat = key1.getFormat();
-        final String otherKeyFormat = key2.getFormat();
-
-        if (keyFormat == null) {
-            if (keyFormat != otherKeyFormat) {
-                return false;
-            }
-
-            if (key1.getEncoded() != key2.getEncoded()) {
-                return false;
-            }
-        } else {
-            if (!keyFormat.equals(key2.getFormat())) {
-                return false;
-            }
-
-            if (!Arrays.equals(key1.getEncoded(), key2.getEncoded())) {
-                return false;
-            }
-        }
-
-        return true;
-    }
-
-    @Override
-    public int hashCode() {
-        int hash = 3;
-
-        hash += 5 * mEncryptionAlgorithm.hashCode();
-        hash += 7 * Arrays.hashCode(mEncryptionSpec.getIV());
-        hash += 11 * mEncryptionKey.hashCode();
-        hash += 13 * mMacAlgorithm.hashCode();
-        hash += 17 * mMacKey.hashCode();
-        hash += 19 * Arrays.hashCode(mMacTag);
-        hash += 23 * mAuthenticatedDataStart;
-        hash += 29 * mEncryptedDataStart;
-        hash += 31 * mDataEnd;
-
-        return hash;
-    }
-
-    @Override
-    public String toString() {
-        final StringBuilder sb = new StringBuilder(TO_STRING_PREFIX);
-
-        sb.append("mEncryptionAlgorithm=\"");
-        sb.append(mEncryptionAlgorithm);
-        sb.append("\",");
-        sb.append("mEncryptionSpec=");
-        sb.append(mEncryptionSpec.toString());
-        sb.append("mEncryptionKey=");
-        sb.append(mEncryptionKey.toString());
-
-        sb.append("mMacAlgorithm=\"");
-        sb.append(mMacAlgorithm);
-        sb.append("\",");
-        sb.append("mMacSpec=");
-        sb.append(mMacSpec.toString());
-        sb.append("mMacKey=");
-        sb.append(mMacKey.toString());
-
-        sb.append(",mAuthenticatedDataStart=");
-        sb.append(mAuthenticatedDataStart);
-        sb.append(",mEncryptedDataStart=");
-        sb.append(mEncryptedDataStart);
-        sb.append(",mDataEnd=");
-        sb.append(mDataEnd);
-        sb.append('}');
-
-        return sb.toString();
-    }
-
-    @Override
-    public void writeToParcel(Parcel dest, int flags) {
-        dest.writeString(mEncryptionAlgorithm);
-        dest.writeInt(ENC_PARAMS_IV_PARAMETERS);
-        dest.writeByteArray(mEncryptionSpec.getIV());
-        dest.writeSerializable(mEncryptionKey);
-
-        dest.writeString(mMacAlgorithm);
-        dest.writeInt(MAC_PARAMS_NONE);
-        dest.writeByteArray(new byte[0]);
-        dest.writeSerializable(mMacKey);
-
-        dest.writeByteArray(mMacTag);
-
-        dest.writeLong(mAuthenticatedDataStart);
-        dest.writeLong(mEncryptedDataStart);
-        dest.writeLong(mDataEnd);
-    }
-
-    private ContainerEncryptionParams(Parcel source) throws InvalidAlgorithmParameterException {
-        mEncryptionAlgorithm = source.readString();
-        final int encParamType = source.readInt();
-        final byte[] encParamsEncoded = source.createByteArray();
-        mEncryptionKey = (SecretKey) source.readSerializable();
-
-        mMacAlgorithm = source.readString();
-        final int macParamType = source.readInt();
-        source.createByteArray(); // byte[] macParamsEncoded
-        mMacKey = (SecretKey) source.readSerializable();
-
-        mMacTag = source.createByteArray();
-
-        mAuthenticatedDataStart = source.readLong();
-        mEncryptedDataStart = source.readLong();
-        mDataEnd = source.readLong();
-
-        switch (encParamType) {
-            case ENC_PARAMS_IV_PARAMETERS:
-                mEncryptionSpec = new IvParameterSpec(encParamsEncoded);
-                break;
-            default:
-                throw new InvalidAlgorithmParameterException("Unknown parameter type "
-                        + encParamType);
-        }
-
-        switch (macParamType) {
-            case MAC_PARAMS_NONE:
-                mMacSpec = null;
-                break;
-            default:
-                throw new InvalidAlgorithmParameterException("Unknown parameter type "
-                        + macParamType);
-        }
-
-        if (mEncryptionKey == null) {
-            throw new NullPointerException("encryptionKey == null");
-        }
-    }
-
-    public static final Parcelable.Creator<ContainerEncryptionParams> CREATOR =
-            new Parcelable.Creator<ContainerEncryptionParams>() {
-        public ContainerEncryptionParams createFromParcel(Parcel source) {
-            try {
-                return new ContainerEncryptionParams(source);
-            } catch (InvalidAlgorithmParameterException e) {
-                Slog.e(TAG, "Invalid algorithm parameters specified", e);
-                return null;
-            }
-        }
-
-        public ContainerEncryptionParams[] newArray(int size) {
-            return new ContainerEncryptionParams[size];
-        }
-    };
-}
\ 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 cc266c5..b1d3f20 100644
--- a/core/java/android/content/pm/ILauncherApps.aidl
+++ b/core/java/android/content/pm/ILauncherApps.aidl
@@ -22,9 +22,12 @@
 import android.content.pm.IOnAppsChangedListener;
 import android.content.pm.ParceledListSlice;
 import android.content.pm.ResolveInfo;
+import android.content.pm.ShortcutInfo;
 import android.graphics.Rect;
 import android.os.Bundle;
 import android.os.UserHandle;
+import android.os.ParcelFileDescriptor;
+
 import java.util.List;
 
 /**
@@ -42,4 +45,17 @@
     boolean isPackageEnabled(String packageName, in UserHandle user);
     boolean isActivityEnabled(in ComponentName component, in UserHandle user);
     ApplicationInfo getApplicationInfo(String packageName, int flags, in UserHandle user);
+
+    ParceledListSlice getShortcuts(String callingPackage, long changedSince, String packageName,
+            in ComponentName componentName, int flags, in UserHandle user);
+    ParceledListSlice getShortcutInfo(String callingPackage, String packageName, in List<String> ids,
+            in UserHandle user);
+    void pinShortcuts(String callingPackage, String packageName, in List<String> shortcutIds,
+            in UserHandle user);
+    boolean startShortcut(String callingPackage, String packageName, String id,
+            in Rect sourceBounds, in Bundle startActivityOptions, in UserHandle user);
+
+    int getShortcutIconResId(String callingPackage, in ShortcutInfo shortcut, in UserHandle user);
+    ParcelFileDescriptor getShortcutIconFd(String callingPackage, in ShortcutInfo shortcut,
+            in UserHandle user);
 }
diff --git a/core/java/android/content/pm/IOnAppsChangedListener.aidl b/core/java/android/content/pm/IOnAppsChangedListener.aidl
index 1303696..e6525af 100644
--- a/core/java/android/content/pm/IOnAppsChangedListener.aidl
+++ b/core/java/android/content/pm/IOnAppsChangedListener.aidl
@@ -16,6 +16,7 @@
 
 package android.content.pm;
 
+import android.content.pm.ParceledListSlice;
 import android.os.UserHandle;
 
 /**
@@ -29,4 +30,5 @@
     void onPackagesUnavailable(in UserHandle user, in String[] packageNames, boolean replacing);
     void onPackagesSuspended(in UserHandle user, in String[] packageNames);
     void onPackagesUnsuspended(in UserHandle user, in String[] packageNames);
+    void onShortcutChanged(in UserHandle user, String packageName, in ParceledListSlice shortcuts);
 }
diff --git a/core/java/android/content/pm/IPackageInstallerSession.aidl b/core/java/android/content/pm/IPackageInstallerSession.aidl
index aee3ba7..2a3fac3 100644
--- a/core/java/android/content/pm/IPackageInstallerSession.aidl
+++ b/core/java/android/content/pm/IPackageInstallerSession.aidl
@@ -29,6 +29,8 @@
     ParcelFileDescriptor openWrite(String name, long offsetBytes, long lengthBytes);
     ParcelFileDescriptor openRead(String name);
 
+    void removeSplit(String splitName);
+
     void close();
     void commit(in IntentSender statusReceiver);
     void abandon();
diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl
index d6b674c..c684447 100644
--- a/core/java/android/content/pm/IPackageManager.aidl
+++ b/core/java/android/content/pm/IPackageManager.aidl
@@ -46,7 +46,6 @@
 import android.content.pm.ResolveInfo;
 import android.content.pm.ServiceInfo;
 import android.content.pm.UserInfo;
-import android.content.pm.VerificationParams;
 import android.content.pm.VerifierDeviceIdentity;
 import android.graphics.Bitmap;
 import android.net.Uri;
@@ -72,11 +71,11 @@
 
     PermissionInfo getPermissionInfo(String name, int flags);
 
-    List<PermissionInfo> queryPermissionsByGroup(String group, int flags);
+    ParceledListSlice queryPermissionsByGroup(String group, int flags);
 
     PermissionGroupInfo getPermissionGroupInfo(String name, int flags);
 
-    List<PermissionGroupInfo> getAllPermissionGroups(int flags);
+    ParceledListSlice getAllPermissionGroups(int flags);
 
     ApplicationInfo getApplicationInfo(String packageName, int flags ,int userId);
 
@@ -121,6 +120,8 @@
 
     int checkUidSignatures(int uid1, int uid2);
 
+    List<String> getAllPackages();
+
     String[] getPackagesForUid(int uid);
 
     String getNameForUid(int uid);
@@ -139,24 +140,24 @@
 
     boolean canForwardTo(in Intent intent, String resolvedType, int sourceUserId, int targetUserId);
 
-    List<ResolveInfo> queryIntentActivities(in Intent intent,
+    ParceledListSlice queryIntentActivities(in Intent intent,
             String resolvedType, int flags, int userId);
 
-    List<ResolveInfo> queryIntentActivityOptions(
+    ParceledListSlice queryIntentActivityOptions(
             in ComponentName caller, in Intent[] specifics,
             in String[] specificTypes, in Intent intent,
             String resolvedType, int flags, int userId);
 
-    List<ResolveInfo> queryIntentReceivers(in Intent intent,
+    ParceledListSlice queryIntentReceivers(in Intent intent,
             String resolvedType, int flags, int userId);
 
     ResolveInfo resolveService(in Intent intent,
             String resolvedType, int flags, int userId);
 
-    List<ResolveInfo> queryIntentServices(in Intent intent,
+    ParceledListSlice queryIntentServices(in Intent intent,
             String resolvedType, int flags, int userId);
 
-    List<ResolveInfo> queryIntentContentProviders(in Intent intent,
+    ParceledListSlice queryIntentContentProviders(in Intent intent,
             String resolvedType, int flags, int userId);
 
     /**
@@ -190,7 +191,7 @@
      * @return A List&lt;applicationInfo> containing one entry for each persistent
      *         application.
      */
-    List<ApplicationInfo> getPersistentApplications(int flags);
+    ParceledListSlice getPersistentApplications(int flags);
 
     ProviderInfo resolveContentProvider(String name, int flags, int userId);
 
@@ -211,22 +212,14 @@
     InstrumentationInfo getInstrumentationInfo(
             in ComponentName className, int flags);
 
-    List<InstrumentationInfo> queryInstrumentation(
+    ParceledListSlice queryInstrumentation(
             String targetPackage, int flags);
 
-    void installPackage(in String originPath,
-            in IPackageInstallObserver2 observer,
-            int flags,
-            in String installerPackageName,
-            in VerificationParams verificationParams,
-            in String packageAbiOverride);
-
+    /** @deprecated Use PackageInstaller instead */
     void installPackageAsUser(in String originPath,
             in IPackageInstallObserver2 observer,
             int flags,
             in String installerPackageName,
-            in VerificationParams verificationParams,
-            in String packageAbiOverride,
             int userId);
 
     void finishPackageInstall(int token);
@@ -249,12 +242,6 @@
 
     String getInstallerPackageName(in String packageName);
 
-    void addPackageToPreferred(String packageName);
-
-    void removePackageFromPreferred(String packageName);
-
-    List<PackageInfo> getPreferredPackages(int flags);
-
     void resetApplicationPreferences(int userId);
 
     ResolveInfo getLastChosenActivity(in Intent intent,
@@ -395,6 +382,13 @@
      */
     void clearApplicationUserData(in String packageName, IPackageDataObserver observer, int userId);
 
+    /**
+     * Clear the profile data of an application.
+     * @param packageName The package name of the application whose profile data
+     * need to be deleted
+     */
+    void clearApplicationProfileData(in String packageName);
+
    /**
      * Get package statistics including the code, data and cache size for
      * an already installed package
@@ -415,7 +409,7 @@
      * Get a list of features that are available on the
      * system.
      */
-    FeatureInfo[] getSystemAvailableFeatures();
+    ParceledListSlice getSystemAvailableFeatures();
 
     boolean hasSystemFeature(String name, int version);
 
@@ -489,8 +483,8 @@
     void verifyIntentFilter(int id, int verificationCode, in List<String> failedDomains);
     int getIntentVerificationStatus(String packageName, int userId);
     boolean updateIntentVerificationStatus(String packageName, int status, int userId);
-    List<IntentFilterVerificationInfo> getIntentFilterVerifications(String packageName);
-    List<IntentFilter> getAllIntentFilters(String packageName);
+    ParceledListSlice getIntentFilterVerifications(String packageName);
+    ParceledListSlice getAllIntentFilters(String packageName);
 
     boolean setDefaultBrowserPackageName(String packageName, int userId);
     String getDefaultBrowserPackageName(int userId);
@@ -539,4 +533,7 @@
     String getServicesSystemSharedLibraryPackageName();
 
     boolean isPackageDeviceAdminOnAnyUser(String packageName);
+
+    List<String> getPreviousCodePaths(in String packageName);
+
 }
diff --git a/core/java/android/content/pm/IShortcutService.aidl b/core/java/android/content/pm/IShortcutService.aidl
new file mode 100644
index 0000000..8f9dcfc
--- /dev/null
+++ b/core/java/android/content/pm/IShortcutService.aidl
@@ -0,0 +1,50 @@
+/*
+ * 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.pm.ParceledListSlice;
+import android.content.pm.ShortcutInfo;
+
+/**
+ * {@hide}
+ */
+interface IShortcutService {
+
+    boolean setDynamicShortcuts(String packageName, in ParceledListSlice shortcutInfoList,
+            int userId);
+
+    ParceledListSlice getDynamicShortcuts(String packageName, int userId);
+
+    boolean addDynamicShortcut(String packageName, in ShortcutInfo shortcutInfo, int userId);
+
+    void deleteDynamicShortcut(String packageName, in String shortcutId, int userId);
+
+    void deleteAllDynamicShortcuts(String packageName, int userId);
+
+    ParceledListSlice getPinnedShortcuts(String packageName, int userId);
+
+    boolean updateShortcuts(String packageName, in ParceledListSlice shortcuts, int userId);
+
+    int getMaxDynamicShortcutCount(String packageName, int userId);
+
+    int getRemainingCallCount(String packageName, int userId);
+
+    long getRateLimitResetTime(String packageName, int userId);
+
+    int getIconMaxDimensions(String packageName, int userId);
+
+    void resetThrottling(); // system only API for developer opsions
+}
\ No newline at end of file
diff --git a/core/java/android/content/pm/LauncherApps.java b/core/java/android/content/pm/LauncherApps.java
index 8c7d327..a6a732e 100644
--- a/core/java/android/content/pm/LauncherApps.java
+++ b/core/java/android/content/pm/LauncherApps.java
@@ -16,23 +16,29 @@
 
 package android.content.pm;
 
+import android.Manifest.permission;
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.RequiresPermission;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
-import android.content.pm.ILauncherApps;
-import android.content.pm.IOnAppsChangedListener;
 import android.content.pm.PackageManager.ApplicationInfoFlags;
-import android.content.pm.PackageManager.NameNotFoundException;
 import android.graphics.Rect;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.Looper;
 import android.os.Message;
+import android.os.Parcel;
+import android.os.ParcelFileDescriptor;
 import android.os.RemoteException;
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.util.Log;
 
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
@@ -148,6 +154,92 @@
          */
         public void onPackagesUnsuspended(String[] packageNames, UserHandle user) {
         }
+
+        /**
+         * Indicates that one or more shortcuts (which may be dynamic and/or pinned)
+         * have been added, updated or removed.
+         *
+         * @param packageName The name of the package that has the shortcuts.
+         * @param shortcuts all shortcuts from the package (dynamic and/or pinned).
+         * @param user The UserHandle of the profile that generated the change.
+         */
+        public void onShortcutsChanged(@NonNull String packageName,
+                @NonNull List<ShortcutInfo> shortcuts, @NonNull UserHandle user) {
+        }
+    }
+
+    /**
+     * Represents a query passed to {@link #getShortcuts(ShortcutQuery, UserHandle)}.
+     */
+    public static class ShortcutQuery {
+        /**
+         * Include dynamic shortcuts in the result.
+         */
+        public static final int FLAG_GET_DYNAMIC = 1 << 0;
+
+        /**
+         * Include pinned shortcuts in the result.
+         */
+        public static final int FLAG_GET_PINNED = 1 << 1;
+
+        /**
+         * Requests "key" fields only.  See {@link ShortcutInfo#hasKeyFieldsOnly()} for which
+         * fields are available.
+         */
+        public static final int FLAG_GET_KEY_FIELDS_ONLY = 1 << 2;
+
+        /** @hide */
+        @IntDef(flag = true,
+                value = {
+                        FLAG_GET_DYNAMIC,
+                        FLAG_GET_PINNED,
+                        FLAG_GET_KEY_FIELDS_ONLY,
+                })
+        @Retention(RetentionPolicy.SOURCE)
+        public @interface QueryFlags {}
+
+        long mChangedSince;
+
+        @Nullable
+        String mPackage;
+
+        @Nullable
+        ComponentName mActivity;
+
+        @QueryFlags
+        int mQueryFlags;
+
+        public ShortcutQuery() {
+        }
+
+        /**
+         * If non-zero, returns only shortcuts that have been added or updated since the timestamp,
+         * which is a milliseconds since the Epoch.
+         */
+        public void setChangedSince(long changedSince) {
+            mChangedSince = changedSince;
+        }
+
+        /**
+         * If non-null, returns only shortcuts from the package.
+         */
+        public void setPackage(@Nullable String packageName) {
+            mPackage = packageName;
+        }
+
+        /**
+         * If non-null, returns only shortcuts associated with the activity.
+         */
+        public void setActivity(@Nullable ComponentName activity) {
+            mActivity = activity;
+        }
+
+        /**
+         * Set query options.
+         */
+        public void setQueryFlags(@QueryFlags int queryFlags) {
+            mQueryFlags = queryFlags;
+        }
     }
 
     /** @hide */
@@ -171,7 +263,7 @@
         try {
             activities = mService.getLauncherActivities(packageName, user);
         } catch (RemoteException re) {
-            throw new RuntimeException("Failed to call LauncherAppsService", re);
+            throw re.rethrowFromSystemServer();
         }
         if (activities == null) {
             return Collections.EMPTY_LIST;
@@ -208,7 +300,7 @@
                 return info;
             }
         } catch (RemoteException re) {
-            throw new RuntimeException("Failed to call LauncherAppsService", re);
+            throw re.rethrowFromSystemServer();
         }
         return null;
     }
@@ -229,7 +321,7 @@
         try {
             mService.startActivityAsUser(component, sourceBounds, opts, user);
         } catch (RemoteException re) {
-            // Oops!
+            throw re.rethrowFromSystemServer();
         }
     }
 
@@ -247,7 +339,7 @@
         try {
             mService.showAppDetailsAsUser(component, sourceBounds, opts, user);
         } catch (RemoteException re) {
-            // Oops!
+            throw re.rethrowFromSystemServer();
         }
     }
 
@@ -263,7 +355,7 @@
         try {
             return mService.isPackageEnabled(packageName, user);
         } catch (RemoteException re) {
-            throw new RuntimeException("Failed to call LauncherAppsService", re);
+            throw re.rethrowFromSystemServer();
         }
     }
 
@@ -282,7 +374,7 @@
         try {
             return mService.getApplicationInfo(packageName, flags, user);
         } catch (RemoteException re) {
-            throw new RuntimeException("Failed to call LauncherAppsService", re);
+            throw re.rethrowFromSystemServer();
         }
     }
 
@@ -298,10 +390,140 @@
         try {
             return mService.isActivityEnabled(component, user);
         } catch (RemoteException re) {
-            throw new RuntimeException("Failed to call LauncherAppsService", re);
+            throw re.rethrowFromSystemServer();
         }
     }
 
+    /**
+     * Returns the IDs of {@link ShortcutInfo}s that match {@code query}.
+     *
+     * <p>Callers mut have the {@link permission#BIND_APPWIDGET} permission.
+     *
+     * @param query result includes shortcuts matching this query.
+     * @param user The UserHandle of the profile.
+     *
+     * @return the IDs of {@link ShortcutInfo}s that match the query.
+     */
+    @RequiresPermission(permission.BIND_APPWIDGET)
+    @Nullable
+    public List<ShortcutInfo> getShortcuts(@NonNull ShortcutQuery query,
+            @NonNull UserHandle user) {
+        try {
+            return mService.getShortcuts(mContext.getPackageName(),
+                    query.mChangedSince, query.mPackage, query.mActivity, query.mQueryFlags, user)
+                    .getList();
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Returns {@link ShortcutInfo}s with the given IDs from a package.
+     *
+     * <p>Callers mut have the {@link permission#BIND_APPWIDGET} permission.
+     *
+     * @param packageName The target package.
+     * @param ids IDs of the shortcuts to retrieve.
+     * @param user The UserHandle of the profile.
+     *
+     * @return list of {@link ShortcutInfo} associated with the package.
+     */
+    @RequiresPermission(permission.BIND_APPWIDGET)
+    @Nullable
+    public List<ShortcutInfo> getShortcutInfo(@NonNull String packageName,
+            @NonNull List<String> ids, @NonNull UserHandle user) {
+        try {
+            return mService.getShortcutInfo(mContext.getPackageName(), packageName, ids, user)
+                    .getList();
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+
+    /**
+     * Pin shortcuts on a package.
+     *
+     * <p>This API is <b>NOT</b> cumulative; this will replace all pinned shortcuts for the package.
+     * However, different launchers may have different set of pinned shortcuts.
+     *
+     * <p>Callers must have the {@link permission#BIND_APPWIDGET} permission.
+     *
+     * @param packageName The target package name.
+     * @param shortcutIds The IDs of the shortcut to be pinned.
+     * @param user The UserHandle of the profile.
+     */
+    @RequiresPermission(permission.BIND_APPWIDGET)
+    public void pinShortcuts(@NonNull String packageName, @NonNull List<String> shortcutIds,
+            @NonNull UserHandle user) {
+        try {
+            mService.pinShortcuts(mContext.getPackageName(), packageName, shortcutIds, user);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Return the icon resource ID, if {@code shortcut} has one
+     * (i.e. when {@link ShortcutInfo#hasIconResource()} returns {@code true}).
+     *
+     * <p>Callers mut have the {@link permission#BIND_APPWIDGET} permission.
+     *
+     * @param shortcut The target shortcut.
+     * @param user The UserHandle of the profile.
+     */
+    @RequiresPermission(permission.BIND_APPWIDGET)
+    public int getShortcutIconResId(@NonNull ShortcutInfo shortcut, @NonNull UserHandle user) {
+        try {
+            return mService.getShortcutIconResId(mContext.getPackageName(), shortcut, user);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Return the icon as {@link ParcelFileDescriptor}, when it's stored as a file
+     * (i.e. when {@link ShortcutInfo#hasIconFile()} returns {@code true}).
+     *
+     * <p>Callers mut have the {@link permission#BIND_APPWIDGET} permission.
+     *
+     * @param shortcut The target shortcut.
+     * @param user The UserHandle of the profile.
+     */
+    @RequiresPermission(permission.BIND_APPWIDGET)
+    public ParcelFileDescriptor getShortcutIconFd(
+            @NonNull ShortcutInfo shortcut, @NonNull UserHandle user) {
+        try {
+            return mService.getShortcutIconFd(mContext.getPackageName(), shortcut, user);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Launches a shortcut.
+     *
+     * <p>Callers mut have the {@link permission#BIND_APPWIDGET} permission.
+     *
+     * @param packageName The target shortcut package name.
+     * @param shortcutId The target shortcut ID.
+     * @param sourceBounds The Rect containing the source bounds of the clicked icon.
+     * @param startActivityOptions Options to pass to startActivity.
+     * @param user The UserHandle of the profile.
+     * @return {@code false} when the shortcut is no longer valid (e.g. the creator application
+     *   has been uninstalled). {@code true} when the shortcut is still valid.
+     */
+    @RequiresPermission(permission.BIND_APPWIDGET)
+    public boolean startShortcut(@NonNull String packageName, @NonNull String shortcutId,
+            @Nullable Rect sourceBounds, @Nullable Bundle startActivityOptions,
+            @NonNull UserHandle user) {
+        try {
+            return mService.startShortcut(mContext.getPackageName(), packageName, shortcutId,
+                    sourceBounds, startActivityOptions, user);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
 
     /**
      * Registers a callback for changes to packages in current and managed profiles.
@@ -327,6 +549,7 @@
                     try {
                         mService.addOnAppsChangedListener(mAppsChangedListener);
                     } catch (RemoteException re) {
+                        throw re.rethrowFromSystemServer();
                     }
                 }
             }
@@ -346,6 +569,7 @@
                 try {
                     mService.removeOnAppsChangedListener(mAppsChangedListener);
                 } catch (RemoteException re) {
+                    throw re.rethrowFromSystemServer();
                 }
             }
         }
@@ -472,6 +696,20 @@
                 }
             }
         }
+
+        @Override
+        public void onShortcutChanged(UserHandle user, String packageName,
+                ParceledListSlice shortcuts) {
+            if (DEBUG) {
+                Log.d(TAG, "onShortcutChanged " + user.getIdentifier() + "," + packageName);
+            }
+            final List<ShortcutInfo> list = shortcuts.getList();
+            synchronized (LauncherApps.this) {
+                for (CallbackMessageHandler callback : mCallbacks) {
+                    callback.postOnShortcutChanged(packageName, user, list);
+                }
+            }
+        }
     };
 
     private static class CallbackMessageHandler extends Handler {
@@ -482,6 +720,7 @@
         private static final int MSG_UNAVAILABLE = 5;
         private static final int MSG_SUSPENDED = 6;
         private static final int MSG_UNSUSPENDED = 7;
+        private static final int MSG_SHORTCUT_CHANGED = 8;
 
         private LauncherApps.Callback mCallback;
 
@@ -490,6 +729,7 @@
             String packageName;
             boolean replacing;
             UserHandle user;
+            List<ShortcutInfo> shortcuts;
         }
 
         public CallbackMessageHandler(Looper looper, LauncherApps.Callback callback) {
@@ -525,6 +765,9 @@
                 case MSG_UNSUSPENDED:
                     mCallback.onPackagesUnsuspended(info.packageNames, info.user);
                     break;
+                case MSG_SHORTCUT_CHANGED:
+                    mCallback.onShortcutsChanged(info.packageName, info.shortcuts, info.user);
+                    break;
             }
         }
 
@@ -580,5 +823,14 @@
             info.user = user;
             obtainMessage(MSG_UNSUSPENDED, info).sendToTarget();
         }
+
+        public void postOnShortcutChanged(String packageName, UserHandle user,
+                List<ShortcutInfo> shortcuts) {
+            CallbackInfo info = new CallbackInfo();
+            info.packageName = packageName;
+            info.user = user;
+            info.shortcuts = shortcuts;
+            obtainMessage(MSG_SHORTCUT_CHANGED, info).sendToTarget();
+        }
     }
 }
diff --git a/core/java/android/content/pm/PackageInstaller.java b/core/java/android/content/pm/PackageInstaller.java
index 3283005..0f5ec91 100644
--- a/core/java/android/content/pm/PackageInstaller.java
+++ b/core/java/android/content/pm/PackageInstaller.java
@@ -301,7 +301,7 @@
             ExceptionUtils.maybeUnwrapIOException(e);
             throw e;
         } catch (RemoteException e) {
-            throw e.rethrowAsRuntimeException();
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -321,7 +321,7 @@
             ExceptionUtils.maybeUnwrapIOException(e);
             throw e;
         } catch (RemoteException e) {
-            throw e.rethrowAsRuntimeException();
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -337,7 +337,7 @@
         try {
             mInstaller.updateSessionAppIcon(sessionId, appIcon);
         } catch (RemoteException e) {
-            throw e.rethrowAsRuntimeException();
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -353,7 +353,7 @@
             final String val = (appLabel != null) ? appLabel.toString() : null;
             mInstaller.updateSessionAppLabel(sessionId, val);
         } catch (RemoteException e) {
-            throw e.rethrowAsRuntimeException();
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -370,7 +370,7 @@
         try {
             mInstaller.abandonSession(sessionId);
         } catch (RemoteException e) {
-            throw e.rethrowAsRuntimeException();
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -385,7 +385,7 @@
         try {
             return mInstaller.getSessionInfo(sessionId);
         } catch (RemoteException e) {
-            throw e.rethrowAsRuntimeException();
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -403,7 +403,7 @@
         try {
             return mInstaller.getAllSessions(mUserId).getList();
         } catch (RemoteException e) {
-            throw e.rethrowAsRuntimeException();
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -414,7 +414,7 @@
         try {
             return mInstaller.getMySessions(mInstallerPackageName, mUserId).getList();
         } catch (RemoteException e) {
-            throw e.rethrowAsRuntimeException();
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -427,7 +427,7 @@
         try {
             mInstaller.uninstall(packageName, mInstallerPackageName, 0, statusReceiver, mUserId);
         } catch (RemoteException e) {
-            throw e.rethrowAsRuntimeException();
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -436,7 +436,7 @@
         try {
             mInstaller.setPermissionsResult(sessionId, accepted);
         } catch (RemoteException e) {
-            throw e.rethrowAsRuntimeException();
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -611,7 +611,7 @@
             try {
                 mInstaller.registerCallback(delegate, mUserId);
             } catch (RemoteException e) {
-                throw e.rethrowAsRuntimeException();
+                throw e.rethrowFromSystemServer();
             }
             mDelegates.add(delegate);
         }
@@ -634,7 +634,7 @@
                     try {
                         mInstaller.unregisterCallback(delegate);
                     } catch (RemoteException e) {
-                        throw e.rethrowAsRuntimeException();
+                        throw e.rethrowFromSystemServer();
                     }
                     i.remove();
                 }
@@ -681,7 +681,7 @@
             try {
                 mSession.setClientProgress(progress);
             } catch (RemoteException e) {
-                throw e.rethrowAsRuntimeException();
+                throw e.rethrowFromSystemServer();
             }
         }
 
@@ -690,7 +690,7 @@
             try {
                 mSession.addClientProgress(progress);
             } catch (RemoteException e) {
-                throw e.rethrowAsRuntimeException();
+                throw e.rethrowFromSystemServer();
             }
         }
 
@@ -734,7 +734,7 @@
                 ExceptionUtils.maybeUnwrapIOException(e);
                 throw e;
             } catch (RemoteException e) {
-                throw e.rethrowAsRuntimeException();
+                throw e.rethrowFromSystemServer();
             }
         }
 
@@ -767,7 +767,7 @@
                 ExceptionUtils.maybeUnwrapIOException(e);
                 throw e;
             } catch (RemoteException e) {
-                throw e.rethrowAsRuntimeException();
+                throw e.rethrowFromSystemServer();
             }
         }
 
@@ -790,7 +790,28 @@
                 ExceptionUtils.maybeUnwrapIOException(e);
                 throw e;
             } catch (RemoteException e) {
-                throw e.rethrowAsRuntimeException();
+                throw e.rethrowFromSystemServer();
+            }
+        }
+
+        /**
+         * Removes a split.
+         * <p>
+         * Split removals occur prior to adding new APKs. If upgrading a feature
+         * split, it is not expected nor desirable to remove the split prior to
+         * upgrading.
+         * <p>
+         * When split removal is bundled with new APKs, the packageName must be
+         * identical.
+         */
+        public void removeSplit(@NonNull String splitName) throws IOException {
+            try {
+                mSession.removeSplit(splitName);
+            } catch (RuntimeException e) {
+                ExceptionUtils.maybeUnwrapIOException(e);
+                throw e;
+            } catch (RemoteException e) {
+                throw e.rethrowFromSystemServer();
             }
         }
 
@@ -810,7 +831,7 @@
             try {
                 mSession.commit(statusReceiver);
             } catch (RemoteException e) {
-                throw e.rethrowAsRuntimeException();
+                throw e.rethrowFromSystemServer();
             }
         }
 
@@ -823,7 +844,7 @@
             try {
                 mSession.close();
             } catch (RemoteException e) {
-                throw e.rethrowAsRuntimeException();
+                throw e.rethrowFromSystemServer();
             }
         }
 
@@ -837,7 +858,7 @@
             try {
                 mSession.abandon();
             } catch (RemoteException e) {
-                throw e.rethrowAsRuntimeException();
+                throw e.rethrowFromSystemServer();
             }
         }
     }
@@ -979,8 +1000,8 @@
         }
 
         /**
-         * Optionally set the URI where this package was downloaded from. Used for
-         * verification purposes.
+         * Optionally set the URI where this package was downloaded from. This is
+         * informational and may be used as a signal for anti-malware purposes.
          *
          * @see Intent#EXTRA_ORIGINATING_URI
          */
@@ -989,7 +1010,8 @@
         }
 
         /**
-         * Sets the UID that initiated package installation. Used for verification purposes.
+         * Sets the UID that initiated package installation. This is informational
+         * and may be used as a signal for anti-malware purposes.
          *
          * @see PackageManager#EXTRA_VERIFICATION_INSTALLER_UID
          */
@@ -998,8 +1020,8 @@
         }
 
         /**
-         * Optionally set the URI that referred you to install this package. Used
-         * for verification purposes.
+         * Optionally set the URI that referred you to install this package. This is
+         * informational and may be used as a signal for anti-malware purposes.
          *
          * @see Intent#EXTRA_REFERRER
          */
@@ -1031,6 +1053,12 @@
         }
 
         /** {@hide} */
+        @SystemApi
+        public void setInstallFlagsDowngrade() {
+            installFlags |= PackageManager.INSTALL_ALLOW_DOWNGRADE;
+        }
+
+        /** {@hide} */
         public void setInstallFlagsExternal() {
             installFlags |= PackageManager.INSTALL_EXTERNAL;
             installFlags &= ~PackageManager.INSTALL_INTERNAL;
@@ -1042,6 +1070,11 @@
         }
 
         /** {@hide} */
+        public void setInstallFlagsDontKillApp() {
+            installFlags |= PackageManager.INSTALL_DONT_KILL_APP;
+        }
+
+        /** {@hide} */
         public void dump(IndentingPrintWriter pw) {
             pw.printPair("mode", mode);
             pw.printHexPair("installFlags", installFlags);
diff --git a/core/java/android/content/pm/PackageItemInfo.java b/core/java/android/content/pm/PackageItemInfo.java
index 4df83036..edd888b 100644
--- a/core/java/android/content/pm/PackageItemInfo.java
+++ b/core/java/android/content/pm/PackageItemInfo.java
@@ -16,12 +16,16 @@
 
 package android.content.pm;
 
+import android.annotation.NonNull;
+import android.annotation.SystemApi;
 import android.content.res.XmlResourceParser;
 
 import android.graphics.drawable.Drawable;
 import android.os.Bundle;
 import android.os.Parcel;
 import android.os.UserHandle;
+import android.text.BidiFormatter;
+import android.text.TextPaint;
 import android.text.TextUtils;
 import android.util.Printer;
 
@@ -38,6 +42,8 @@
  * in the implementation of Parcelable in subclasses.
  */
 public class PackageItemInfo {
+    private static final float MAX_LABEL_SIZE_PX = 500f;
+
     /**
      * Public name of this item. From the "android:name" attribute.
      */
@@ -140,6 +146,56 @@
     }
 
     /**
+     * Same as {@link #loadLabel(PackageManager)} with the addition that
+     * the returned label is safe for being presented in the UI since it
+     * will not contain new lines and the length will be limited to a
+     * reasonable amount. This prevents a malicious party to influence UI
+     * layout via the app label misleading the user into performing a
+     * detrimental for them action. If the label is too long it will be
+     * truncated and ellipsized at the end.
+     *
+     * @param pm A PackageManager from which the label can be loaded; usually
+     * the PackageManager from which you originally retrieved this item
+     * @return Returns a CharSequence containing the item's label. If the
+     * item does not have a label, its name is returned.
+     *
+     * @hide
+     */
+    @SystemApi
+    public @NonNull CharSequence loadSafeLabel(@NonNull PackageManager pm) {
+        // loadLabel() always returns non-null
+        CharSequence label = loadLabel(pm);
+
+        // If the label contains new line characters it may push the UI
+        // down to hide a part of it. Labels shouldn't have new line
+        // characters, so just truncate at the first time one is seen.
+        String labelStr = label.toString();
+        final int labelLength = labelStr.length();
+        int offset = 0;
+        while (offset < labelLength) {
+            final int codePoint = labelStr.codePointAt(offset);
+            final int type = Character.getType(codePoint);
+            if (type == Character.LINE_SEPARATOR
+                    || type == Character.CONTROL
+                    || type == Character.PARAGRAPH_SEPARATOR) {
+                labelStr = labelStr.substring(0, offset);
+                break;
+            }
+            offset += Character.charCount(codePoint);
+        }
+
+        if (labelStr.isEmpty()) {
+            return labelStr;
+        }
+
+        TextPaint paint = new TextPaint();
+        paint.setTextSize(42);
+
+        return TextUtils.ellipsize(labelStr, paint, MAX_LABEL_SIZE_PX,
+                TextUtils.TruncateAt.END);
+    }
+
+    /**
      * Retrieve the current graphical icon associated with this item.  This
      * will call back on the given PackageManager to load the icon from
      * the application.
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 4dd8155..e1e8a07 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -538,6 +538,7 @@
             INSTALL_FORCE_VOLUME_UUID,
             INSTALL_FORCE_PERMISSION_PROMPT,
             INSTALL_EPHEMERAL,
+            INSTALL_DONT_KILL_APP,
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface InstallFlags {}
@@ -640,6 +641,15 @@
     public static final int INSTALL_EPHEMERAL = 0x00000800;
 
     /**
+     * Flag parameter for {@link #installPackage} to indicate that this package contains
+     * a feature split to an existing application and the existing application should not
+     * be killed during the installation process.
+     *
+     * @hide
+     */
+    public static final int INSTALL_DONT_KILL_APP = 0x00001000;
+
+    /**
      * Flag parameter for
      * {@link #setComponentEnabledSetting(android.content.ComponentName, int, int)} to indicate
      * that you don't want to kill the app containing the component.  Be careful when you set this
@@ -1088,6 +1098,7 @@
             DELETE_KEEP_DATA,
             DELETE_ALL_USERS,
             DELETE_SYSTEM_APP,
+            DELETE_DONT_KILL_APP,
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface DeleteFlags {}
@@ -1120,6 +1131,15 @@
     public static final int DELETE_SYSTEM_APP = 0x00000004;
 
     /**
+     * Flag parameter for {@link #deletePackage} to indicate that, if you are calling
+     * uninstall on a package that is replaced to provide new feature splits, the
+     * existing application should not be killed during the removal process.
+     *
+     * @hide
+     */
+    public static final int DELETE_DONT_KILL_APP = 0x00000008;
+
+    /**
      * Return code for when package deletion succeeds. This is passed to the
      * {@link IPackageDeleteObserver} if the system succeeded in deleting the
      * package.
@@ -1292,6 +1312,7 @@
      *
      * @hide
      */
+    @SystemApi
     public static final int INTENT_FILTER_VERIFICATION_SUCCESS = 1;
 
     /**
@@ -1301,6 +1322,7 @@
      *
      * @hide
      */
+    @SystemApi
     public static final int INTENT_FILTER_VERIFICATION_FAILURE = -1;
 
     /**
@@ -1574,9 +1596,9 @@
 
     /**
      * Feature for {@link #getSystemAvailableFeatures} and
-     * {@link #hasSystemFeature}: If this feature is supported, the Vulkan native API will enumerate
-     * at least one {@code VkPhysicalDevice}, and the feature version will indicate what
-     * level of optional hardware features limits it supports.
+     * {@link #hasSystemFeature(String, int)}: If this feature is supported, the Vulkan native API
+     * will enumerate at least one {@code VkPhysicalDevice}, and the feature version will indicate
+     * what level of optional hardware features limits it supports.
      * <p>
      * Level 0 includes the base Vulkan requirements as well as:
      * <ul><li>{@code VkPhysicalDeviceFeatures::textureCompressionETC2}</li></ul>
@@ -1601,7 +1623,7 @@
 
     /**
      * Feature for {@link #getSystemAvailableFeatures} and
-     * {@link #hasSystemFeature}: The version of this feature indicates the highest
+     * {@link #hasSystemFeature(String, int)}: The version of this feature indicates the highest
      * {@code VkPhysicalDeviceProperties::apiVersion} supported by the physical devices that support
      * the hardware level indicated by {@link #FEATURE_VULKAN_HARDWARE_LEVEL}. The feature version
      * uses the same encoding as Vulkan version numbers:
@@ -4339,6 +4361,32 @@
             throws NameNotFoundException;
 
     /**
+     * Returns a managed-user-style badged copy of the given drawable allowing the user to
+     * distinguish it from the original drawable.
+     * The caller can specify the location in the bounds of the drawable to be
+     * badged where the badge should be applied as well as the density of the
+     * badge to be used.
+     * <p>
+     * If the original drawable is a BitmapDrawable and the backing bitmap is
+     * mutable as per {@link android.graphics.Bitmap#isMutable()}, the badging
+     * is performed in place and the original drawable is returned.
+     * </p>
+     *
+     * @param drawable The drawable to badge.
+     * @param badgeLocation Where in the bounds of the badged drawable to place
+     *         the badge. If it's {@code null}, the badge is applied on top of the entire
+     *         drawable being badged.
+     * @param badgeDensity The optional desired density for the badge as per
+     *         {@link android.util.DisplayMetrics#densityDpi}. If it's not positive,
+     *         the density of the display is used.
+     * @return A drawable that combines the original drawable and a badge as
+     *         determined by the system.
+     * @hide
+     */
+    public abstract Drawable getManagedUserBadgedDrawable(Drawable drawable, Rect badgeLocation,
+        int badgeDensity);
+
+    /**
      * If the target user is a managed profile of the calling user or if the
      * target user is the caller and is itself a managed profile, then this
      * returns a badged copy of the given icon to be able to distinguish it from
@@ -4367,17 +4415,17 @@
      * badge to be used.
      * <p>
      * If the original drawable is a BitmapDrawable and the backing bitmap is
-     * mutable as per {@link android.graphics.Bitmap#isMutable()}, the bading
+     * mutable as per {@link android.graphics.Bitmap#isMutable()}, the badging
      * is performed in place and the original drawable is returned.
      * </p>
      *
      * @param drawable The drawable to badge.
      * @param user The target user.
      * @param badgeLocation Where in the bounds of the badged drawable to place
-     *         the badge. If not provided, the badge is applied on top of the entire
+     *         the badge. If it's {@code null}, the badge is applied on top of the entire
      *         drawable being badged.
      * @param badgeDensity The optional desired density for the badge as per
-     *         {@link android.util.DisplayMetrics#densityDpi}. If not provided,
+     *         {@link android.util.DisplayMetrics#densityDpi}. If it's not positive,
      *         the density of the display is used.
      * @return A drawable that combines the original drawable and a badge as
      *         determined by the system.
@@ -4598,60 +4646,20 @@
      */
     @Deprecated
     public abstract void installPackage(
-            Uri packageURI, IPackageInstallObserver observer, @InstallFlags int flags,
+            Uri packageURI,
+            IPackageInstallObserver observer,
+            @InstallFlags int flags,
             String installerPackageName);
-
     /**
      * @deprecated replaced by {@link PackageInstaller}
      * @hide
      */
     @Deprecated
-    public abstract void installPackageWithVerification(Uri packageURI,
-            IPackageInstallObserver observer, @InstallFlags int flags, String installerPackageName,
-            Uri verificationURI, ContainerEncryptionParams encryptionParams);
-
-    /**
-     * @deprecated replaced by {@link PackageInstaller}
-     * @hide
-     */
-    @Deprecated
-    public abstract void installPackageWithVerificationAndEncryption(Uri packageURI,
-            IPackageInstallObserver observer, @InstallFlags int flags, String installerPackageName,
-            VerificationParams verificationParams, ContainerEncryptionParams encryptionParams);
-
-    /**
-     * @deprecated replaced by {@link PackageInstaller}
-     * @hide
-     */
-    @Deprecated
-    public abstract void installPackage(Uri packageURI, PackageInstallObserver observer,
-            @InstallFlags int flags, String installerPackageName);
-
-    /**
-     * @deprecated replaced by {@link PackageInstaller}
-     * @hide
-     */
-    @Deprecated
-    public abstract void installPackageAsUser(Uri packageURI, PackageInstallObserver observer,
-            @InstallFlags int flags, String installerPackageName, @UserIdInt int userId);
-
-    /**
-     * @deprecated replaced by {@link PackageInstaller}
-     * @hide
-     */
-    @Deprecated
-    public abstract void installPackageWithVerification(Uri packageURI,
-            PackageInstallObserver observer, @InstallFlags int flags, String installerPackageName,
-            Uri verificationURI, ContainerEncryptionParams encryptionParams);
-
-    /**
-     * @deprecated replaced by {@link PackageInstaller}
-     * @hide
-     */
-    @Deprecated
-    public abstract void installPackageWithVerificationAndEncryption(Uri packageURI,
-            PackageInstallObserver observer, @InstallFlags int flags, String installerPackageName,
-            VerificationParams verificationParams, ContainerEncryptionParams encryptionParams);
+    public abstract void installPackage(
+            Uri packageURI,
+            PackageInstallObserver observer,
+            @InstallFlags int flags,
+            String installerPackageName);
 
     /**
      * If there is already an application with the given package name installed
@@ -4725,8 +4733,8 @@
 
     /**
      * Allows a package listening to the
-     * {@link Intent#ACTION_INTENT_FILTER_NEEDS_VERIFICATION intent filter verification
-     * broadcast} to respond to the package manager. The response must include
+     * {@link Intent#ACTION_INTENT_FILTER_NEEDS_VERIFICATION} intent filter verification
+     * broadcast to respond to the package manager. The response must include
      * the {@code verificationCode} which is one of
      * {@link PackageManager#INTENT_FILTER_VERIFICATION_SUCCESS} or
      * {@link PackageManager#INTENT_FILTER_VERIFICATION_FAILURE}.
@@ -4735,7 +4743,7 @@
      *            {@link PackageManager#EXTRA_VERIFICATION_ID} Intent extra.
      * @param verificationCode either {@link PackageManager#INTENT_FILTER_VERIFICATION_SUCCESS}
      *            or {@link PackageManager#INTENT_FILTER_VERIFICATION_FAILURE}.
-     * @param outFailedDomains a list of failed domains if the verificationCode is
+     * @param failedDomains a list of failed domains if the verificationCode is
      *            {@link PackageManager#INTENT_FILTER_VERIFICATION_FAILURE}, otherwise null;
      * @throws SecurityException if the caller does not have the
      *            INTENT_FILTER_VERIFICATION_AGENT permission.
@@ -4744,7 +4752,7 @@
      */
     @SystemApi
     public abstract void verifyIntentFilter(int verificationId, int verificationCode,
-            List<String> outFailedDomains);
+            List<String> failedDomains);
 
     /**
      * Get the status of a Domain Verification Result for an IntentFilter. This is
@@ -5359,6 +5367,9 @@
      * will be hidden, the application will not show up in recents, will not be able to show
      * toasts or dialogs or ring the device.
      *
+     * <p>The package must already be installed. If the package is uninstalled while suspended
+     * the package will no longer be suspended.
+     *
      * @param packageNames The names of the packages to set the suspended status.
      * @param suspended If set to {@code true} than the packages will be suspended, if set to
      * {@code false} the packages will be unsuspended.
diff --git a/core/java/android/content/pm/PackageManagerInternal.java b/core/java/android/content/pm/PackageManagerInternal.java
index 7fe7f84..89f2fc4 100644
--- a/core/java/android/content/pm/PackageManagerInternal.java
+++ b/core/java/android/content/pm/PackageManagerInternal.java
@@ -16,6 +16,8 @@
 
 package android.content.pm;
 
+import android.content.pm.PackageManager.NameNotFoundException;
+
 import java.util.List;
 
 /**
@@ -125,4 +127,17 @@
      * @return True a permissions review is required.
      */
     public abstract boolean isPermissionsReviewRequired(String packageName, int userId);
+
+    /**
+     * Gets all of the information we know about a particular package.
+     *
+     * @param packageName The package name to find.
+     * @param userId The user under which to check.
+     *
+     * @return An {@link ApplicationInfo} containing information about the
+     *         package.
+     * @throws NameNotFoundException if a package with the given name cannot be
+     *             found on the system.
+     */
+    public abstract ApplicationInfo getApplicationInfo(String packageName, int userId);
 }
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index ce6ddfd..7d7be9a 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -121,6 +121,10 @@
 
     private static final int MAX_PACKAGES_PER_APK = 5;
 
+    public static final int APK_SIGNING_UNKNOWN = 0;
+    public static final int APK_SIGNING_V1 = 1;
+    public static final int APK_SIGNING_V2 = 2;
+
     // TODO: switch outError users to PackageParserException
     // TODO: refactor "codePath" to "apkPath"
 
@@ -1058,12 +1062,24 @@
         return pkg;
     }
 
+    public static int getApkSigningVersion(Package pkg) {
+        try {
+            if (ApkSignatureSchemeV2Verifier.hasSignature(pkg.baseCodePath)) {
+                return APK_SIGNING_V2;
+            }
+            return APK_SIGNING_V1;
+        } catch (IOException e) {
+        }
+        return APK_SIGNING_UNKNOWN;
+    }
+
     /**
      * Collect certificates from all the APKs described in the given package,
      * populating {@link Package#mSignatures}. Also asserts that all APK
      * contents are signed correctly and consistently.
      */
-    public static void collectCertificates(Package pkg, int parseFlags) throws PackageParserException {
+    public static void collectCertificates(Package pkg, int parseFlags)
+            throws PackageParserException {
         collectCertificatesInternal(pkg, parseFlags);
         final int childCount = (pkg.childPackages != null) ? pkg.childPackages.size() : 0;
         for (int i = 0; i < childCount; i++) {
@@ -1074,7 +1090,8 @@
         }
     }
 
-    private static void collectCertificatesInternal(Package pkg, int parseFlags) throws PackageParserException {
+    private static void collectCertificatesInternal(Package pkg, int parseFlags)
+            throws PackageParserException {
         pkg.mCertificates = null;
         pkg.mSignatures = null;
         pkg.mSigningKeys = null;
@@ -1507,6 +1524,7 @@
         childPkg.baseRevisionCode = parentPkg.baseRevisionCode;
         childPkg.mVersionName = parentPkg.mVersionName;
         childPkg.applicationInfo.targetSdkVersion = parentPkg.applicationInfo.targetSdkVersion;
+        childPkg.applicationInfo.minSdkVersion = parentPkg.applicationInfo.minSdkVersion;
 
         childPkg = parseBaseApkCommon(childPkg, CHILD_PACKAGE_TAGS, res, parser, flags, outError);
         if (childPkg == null) {
@@ -1837,10 +1855,16 @@
                             com.android.internal.R.styleable.AndroidManifestUsesSdk_targetSdkVersion);
                     if (val != null) {
                         if (val.type == TypedValue.TYPE_STRING && val.string != null) {
-                            targetCode = minCode = val.string.toString();
+                            targetCode = val.string.toString();
+                            if (minCode == null) {
+                                minCode = targetCode;
+                            }
                         } else {
                             // If it's not a string, it's an integer.
                             targetVers = val.data;
+                            if (minVers == 0) {
+                                minVers = targetVers;
+                            }
                         }
                     }
 
@@ -1866,11 +1890,14 @@
                             mParseError = PackageManager.INSTALL_FAILED_OLDER_SDK;
                             return null;
                         }
+                        pkg.applicationInfo.minSdkVersion = minCode;
                     } else if (minVers > SDK_VERSION) {
                         outError[0] = "Requires newer sdk version #" + minVers
                                 + " (current version is #" + SDK_VERSION + ")";
                         mParseError = PackageManager.INSTALL_FAILED_OLDER_SDK;
                         return null;
+                    } else {
+                        pkg.applicationInfo.minSdkVersion = Integer.toString(minVers);
                     }
 
                     if (targetCode != null) {
@@ -4690,9 +4717,6 @@
         // preferred up order.
         public int mPreferredOrder = 0;
 
-        // For use by package manager to keep track of where it needs to do dexopt.
-        public final ArraySet<String> mDexOptPerformed = new ArraySet<>(4);
-
         // For use by package manager to keep track of when a package was last used.
         public long mLastPackageUsageTimeInMills;
 
diff --git a/core/java/android/hardware/CameraInfo.aidl b/core/java/android/content/pm/ShortcutInfo.aidl
similarity index 82%
copy from core/java/android/hardware/CameraInfo.aidl
copy to core/java/android/content/pm/ShortcutInfo.aidl
index e21e694..08e1873 100644
--- a/core/java/android/hardware/CameraInfo.aidl
+++ b/core/java/android/content/pm/ShortcutInfo.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2013 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.
@@ -13,8 +13,6 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+package android.content.pm;
 
-package android.hardware;
-
-/** @hide */
-parcelable CameraInfo;
+parcelable ShortcutInfo;
diff --git a/core/java/android/content/pm/ShortcutInfo.java b/core/java/android/content/pm/ShortcutInfo.java
new file mode 100644
index 0000000..e41136c
--- /dev/null
+++ b/core/java/android/content/pm/ShortcutInfo.java
@@ -0,0 +1,766 @@
+/*
+ * 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.IntDef;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.ComponentName;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.Intent;
+import android.graphics.drawable.Icon;
+import android.os.Bundle;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.os.PersistableBundle;
+import android.os.UserHandle;
+
+import com.android.internal.util.Preconditions;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * TODO Enhance javadoc
+ *
+ * Represents a shortcut form an application.
+ *
+ * Notes...
+ * - If an {@link Icon} is of a resource, then we'll just persist the package name and resource ID.
+ *
+ *   Otherwise, the bitmap will be fetched when it's registered to ShortcutManager, then *shrunk*
+ *   if necessary, and persisted.
+ *
+ *   We will disallow byte[] icons, because they can easily go over binder size limit.
+ *
+ * TODO Move save/load to this class
+ */
+public class ShortcutInfo implements Parcelable {
+    /* @hide */
+    public static final int FLAG_DYNAMIC = 1 << 0;
+
+    /* @hide */
+    public static final int FLAG_PINNED = 1 << 1;
+
+    /* @hide */
+    public static final int FLAG_HAS_ICON_RES = 1 << 2;
+
+    /* @hide */
+    public static final int FLAG_HAS_ICON_FILE = 1 << 3;
+
+    /* @hide */
+    public static final int FLAG_KEY_FIELDS_ONLY = 1 << 4;
+
+    /** @hide */
+    @IntDef(flag = true,
+            value = {
+            FLAG_DYNAMIC,
+            FLAG_PINNED,
+            FLAG_HAS_ICON_RES,
+            FLAG_HAS_ICON_FILE,
+            FLAG_KEY_FIELDS_ONLY,
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface ShortcutFlags {}
+
+    // Cloning options.
+
+    /* @hide */
+    private static final int CLONE_REMOVE_ICON = 1 << 0;
+
+    /* @hide */
+    private static final int CLONE_REMOVE_INTENT = 1 << 1;
+
+    /* @hide */
+    public static final int CLONE_REMOVE_NON_KEY_INFO = 1 << 2;
+
+    /* @hide */
+    public static final int CLONE_REMOVE_FOR_CREATOR = CLONE_REMOVE_ICON;
+
+    /* @hide */
+    public static final int CLONE_REMOVE_FOR_LAUNCHER = CLONE_REMOVE_ICON | CLONE_REMOVE_INTENT;
+
+    /** @hide */
+    @IntDef(flag = true,
+            value = {
+                    CLONE_REMOVE_ICON,
+                    CLONE_REMOVE_INTENT,
+                    CLONE_REMOVE_NON_KEY_INFO,
+                    CLONE_REMOVE_FOR_CREATOR,
+                    CLONE_REMOVE_FOR_LAUNCHER
+            })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface CloneFlags {}
+
+    private final String mId;
+
+    @NonNull
+    private final String mPackageName;
+
+    @Nullable
+    private ComponentName mActivityComponent;
+
+    @Nullable
+    private Icon mIcon;
+
+    @NonNull
+    private String mTitle;
+
+    /**
+     * Intent *with extras removed*.
+     */
+    @NonNull
+    private Intent mIntent;
+
+    /**
+     * Extras for the intent.
+     */
+    @NonNull
+    private PersistableBundle mIntentPersistableExtras;
+
+    private int mWeight;
+
+    @Nullable
+    private PersistableBundle mExtras;
+
+    private long mLastChangedTimestamp;
+
+    // Internal use only.
+    @ShortcutFlags
+    private int mFlags;
+
+    // Internal use only.
+    private int mIconResourceId;
+
+    // Internal use only.
+    @Nullable
+    private String mBitmapPath;
+
+    private ShortcutInfo(Builder b) {
+        mId = Preconditions.checkStringNotEmpty(b.mId, "Shortcut ID must be provided");
+
+        // Note we can't do other null checks here because SM.updateShortcuts() takes partial
+        // information.
+        mPackageName = b.mContext.getPackageName();
+        mActivityComponent = b.mActivityComponent;
+        mIcon = b.mIcon;
+        mTitle = b.mTitle;
+        mIntent = b.mIntent;
+        if (mIntent != null) {
+            final Bundle intentExtras = mIntent.getExtras();
+            if (intentExtras != null) {
+                mIntent.replaceExtras((Bundle) null);
+                mIntentPersistableExtras = new PersistableBundle(intentExtras);
+            }
+        }
+        mWeight = b.mWeight;
+        mExtras = b.mExtras;
+        updateTimestamp();
+    }
+
+    /**
+     * Throws if any of the mandatory fields is not set.
+     *
+     * @hide
+     */
+    public void enforceMandatoryFields() {
+        Preconditions.checkStringNotEmpty(mTitle, "Shortcut title must be provided");
+        Preconditions.checkNotNull(mIntent, "Shortcut Intent must be provided");
+    }
+
+    /**
+     * Copy constructor.
+     */
+    private ShortcutInfo(ShortcutInfo source, @CloneFlags int cloneFlags) {
+        mId = source.mId;
+        mPackageName = source.mPackageName;
+        mFlags = source.mFlags;
+        mLastChangedTimestamp = source.mLastChangedTimestamp;
+
+        if ((cloneFlags & CLONE_REMOVE_NON_KEY_INFO) == 0) {
+            mActivityComponent = source.mActivityComponent;
+
+            if ((cloneFlags & CLONE_REMOVE_ICON) == 0) {
+                mIcon = source.mIcon;
+                mBitmapPath = source.mBitmapPath;
+            }
+
+            mTitle = source.mTitle;
+            if ((cloneFlags & CLONE_REMOVE_INTENT) == 0) {
+                mIntent = source.mIntent;
+                mIntentPersistableExtras = source.mIntentPersistableExtras;
+            }
+            mWeight = source.mWeight;
+            mExtras = source.mExtras;
+            mIconResourceId = source.mIconResourceId;
+        } else {
+            // Set this bit.
+            mFlags |= FLAG_KEY_FIELDS_ONLY;
+        }
+    }
+
+    /**
+     * Copy a {@link ShortcutInfo}, optionally removing fields.
+     * @hide
+     */
+    public ShortcutInfo clone(@CloneFlags int cloneFlags) {
+        return new ShortcutInfo(this, cloneFlags);
+    }
+
+    /**
+     * Copy non-null/zero fields from another {@link ShortcutInfo}.  Only "public" information
+     * will be overwritten.  The timestamp will be updated.
+     *
+     * - Flags will not change
+     * - mBitmapPath will not change
+     * - Current time will be set to timestamp
+     *
+     * @hide
+     */
+    public void copyNonNullFieldsFrom(ShortcutInfo source) {
+        Preconditions.checkState(mId.equals(source.mId), "ID must match");
+        Preconditions.checkState(mPackageName.equals(source.mPackageName),
+                "Package name must match");
+
+        if (source.mActivityComponent != null) {
+            mActivityComponent = source.mActivityComponent;
+        }
+
+        if (source.mIcon != null) {
+            mIcon = source.mIcon;
+        }
+        if (source.mTitle != null) {
+            mTitle = source.mTitle;
+        }
+        if (source.mIntent != null) {
+            mIntent = source.mIntent;
+            mIntentPersistableExtras = source.mIntentPersistableExtras;
+        }
+        if (source.mWeight != 0) {
+            mWeight = source.mWeight;
+        }
+        if (source.mExtras != null) {
+            mExtras = source.mExtras;
+        }
+
+        updateTimestamp();
+    }
+
+    /**
+     * @hide
+     */
+    public static Icon validateIcon(Icon icon) {
+        switch (icon.getType()) {
+            case Icon.TYPE_RESOURCE:
+            case Icon.TYPE_BITMAP:
+                break; // OK
+            case Icon.TYPE_URI:
+                if (ContentResolver.SCHEME_CONTENT.equals(icon.getUri().getScheme())) {
+                    break;
+                }
+                // Note "file:" is not supported, because depending on the path, system server
+                // cannot access it. // TODO Revisit "file:" icon support
+
+                // fall through
+            default:
+                throw getInvalidIconException();
+        }
+        if (icon.hasTint()) {
+            // TODO support it
+            throw new IllegalArgumentException("Icons with tints are not supported");
+        }
+
+        return icon;
+    }
+
+    /** @hide */
+    public static IllegalArgumentException getInvalidIconException() {
+        return new IllegalArgumentException("Unsupported icon type:"
+                +" only bitmap, resource and content URI are supported");
+    }
+
+    /**
+     * Builder class for {@link ShortcutInfo} objects.
+     */
+    public static class Builder {
+        private final Context mContext;
+
+        private String mId;
+
+        private ComponentName mActivityComponent;
+
+        private Icon mIcon;
+
+        private String mTitle;
+
+        private Intent mIntent;
+
+        private int mWeight;
+
+        private PersistableBundle mExtras;
+
+        /** Constructor. */
+        public Builder(Context context) {
+            mContext = context;
+        }
+
+        /**
+         * Sets the ID of the shortcut.  This is a mandatory field.
+         */
+        @NonNull
+        public Builder setId(@NonNull String id) {
+            mId = Preconditions.checkStringNotEmpty(id, "id");
+            return this;
+        }
+
+        /**
+         * Optionally sets the target activity.  If it's not set, and if the caller application
+         * has multiple launcher icons, this shortcut will be shown on all those icons.
+         * If it's set, this shortcut will be only shown on this activity.
+         */
+        @NonNull
+        public Builder setActivityComponent(@NonNull ComponentName activityComponent) {
+            mActivityComponent = Preconditions.checkNotNull(activityComponent, "activityComponent");
+            return this;
+        }
+
+        /**
+         * Optionally sets an icon.
+         *
+         * <ul>
+         *     <li>Tints are not supported.
+         *     <li>Bitmaps, resources and "content:" URIs are supported.
+         *     <li>"content:" URI will be fetched when a shortcut is registered to
+         *         {@link ShortcutManager}.  Changing the content from the same URI later will
+         *         not be reflected to launcher icons.
+         * </ul>
+         *
+         * <p>For performance reasons, icons will <b>NOT</b> be available on instances
+         * returned by {@link ShortcutManager} or {@link LauncherApps}.  Launcher applications
+         * need to use {@link LauncherApps#getShortcutIconFd(ShortcutInfo, UserHandle)}
+         * and {@link LauncherApps#getShortcutIconResId(ShortcutInfo, UserHandle)}.
+         */
+        @NonNull
+        public Builder setIcon(Icon icon) {
+            mIcon = validateIcon(icon);
+            return this;
+        }
+
+        /**
+         * Sets the title of a shortcut.  This is a mandatory field.
+         */
+        @NonNull
+        public Builder setTitle(@NonNull String title) {
+            mTitle = Preconditions.checkStringNotEmpty(title, "title");
+            return this;
+        }
+
+        /**
+         * Sets the intent of a shortcut.  This is a mandatory field.  The extras must only contain
+         * persistable information.  (See {@link PersistableBundle}).
+         */
+        @NonNull
+        public Builder setIntent(@NonNull Intent intent) {
+            mIntent = Preconditions.checkNotNull(intent, "intent");
+            return this;
+        }
+
+        /**
+         * Optionally sets the weight of a shortcut, which will be used by the launcher for sorting.
+         * The larger the weight, the more "important" a shortcut is.
+         */
+        @NonNull
+        public Builder setWeight(int weight) {
+            mWeight = weight;
+            return this;
+        }
+
+        /**
+         * Optional values that applications can set.  Applications can store any meta-data of
+         * shortcuts in this, and retrieve later from {@link ShortcutInfo#getExtras()}.
+         */
+        @NonNull
+        public Builder setExtras(@NonNull PersistableBundle extras) {
+            mExtras = extras;
+            return this;
+        }
+
+        /**
+         * Creates a {@link ShortcutInfo} instance.
+         */
+        @NonNull
+        public ShortcutInfo build() {
+            return new ShortcutInfo(this);
+        }
+    }
+
+    /**
+     * Return the ID of the shortcut.
+     */
+    @NonNull
+    public String getId() {
+        return mId;
+    }
+
+    /**
+     * Return the package name of the creator application.
+     */
+    @NonNull
+    public String getPackageName() {
+        return mPackageName;
+    }
+
+    /**
+     * Return the target activity, which may be null, in which case the shortcut is not associated
+     * with a specific activity.
+     */
+    @Nullable
+    public ComponentName getActivityComponent() {
+        return mActivityComponent;
+    }
+
+    /**
+     * Icon.
+     *
+     * For performance reasons, this will <b>NOT</b> be available when an instance is returned
+     * by {@link ShortcutManager} or {@link LauncherApps}.  A launcher application needs to use
+     * other APIs in LauncherApps to fetch the bitmap.
+     *
+     * @hide
+     */
+    @Nullable
+    public Icon getIcon() {
+        return mIcon;
+    }
+
+    /**
+     * Return the shortcut title.
+     *
+     * <p>All shortcuts must have a non-empty title, but this method will return null when
+     * {@link #hasKeyFieldsOnly()} is true.
+     */
+    @Nullable
+    public String getTitle() {
+        return mTitle;
+    }
+
+    /**
+     * Return the intent.
+     *
+     * <p>All shortcuts must have an intent, but this method will return null when
+     * {@link #hasKeyFieldsOnly()} is true.
+     */
+    @Nullable
+    public Intent getIntent() {
+        if (mIntent == null) {
+            return null;
+        }
+        final Intent intent = new Intent(mIntent);
+        intent.replaceExtras(
+                mIntentPersistableExtras != null ? new Bundle(mIntentPersistableExtras) : null);
+        return intent;
+    }
+
+    /**
+     * Return "raw" intent, which is the original intent without the extras.
+     * @hide
+     */
+    @Nullable
+    public Intent getIntentNoExtras() {
+        return mIntent;
+    }
+
+    /**
+     * The extras in the intent.  We convert extras into {@link PersistableBundle} so we can
+     * persist them.
+     * @hide
+     */
+    @Nullable
+    public PersistableBundle getIntentPersistableExtras() {
+        return mIntentPersistableExtras;
+    }
+
+    /**
+     * Return the weight of a shortcut, which will be used by Launcher for sorting.
+     * The larger the weight, the more "important" a shortcut is.
+     */
+    public int getWeight() {
+        return mWeight;
+    }
+
+    /**
+     * Optional values that application can set.
+     */
+    @Nullable
+    public PersistableBundle getExtras() {
+        return mExtras;
+    }
+
+    /**
+     * Last time when any of the fields was updated.
+     */
+    public long getLastChangedTimestamp() {
+        return mLastChangedTimestamp;
+    }
+
+    /** @hide */
+    @ShortcutFlags
+    public int getFlags() {
+        return mFlags;
+    }
+
+    /** @hide*/
+    public void setFlags(@ShortcutFlags int flags) {
+        mFlags = flags;
+    }
+
+    /** @hide*/
+    public void addFlags(@ShortcutFlags int flags) {
+        mFlags |= flags;
+    }
+
+    /** @hide*/
+    public void clearFlags(@ShortcutFlags int flags) {
+        mFlags &= ~flags;
+    }
+
+    /** @hide*/
+    public boolean hasFlags(@ShortcutFlags int flags) {
+        return (mFlags & flags) == flags;
+    }
+
+    /** Return whether a shortcut is dynamic. */
+    public boolean isDynamic() {
+        return hasFlags(FLAG_DYNAMIC);
+    }
+
+    /** Return whether a shortcut is pinned. */
+    public boolean isPinned() {
+        return hasFlags(FLAG_PINNED);
+    }
+
+    /**
+     * Return whether a shortcut's icon is a resource in the owning package.
+     *
+     * @see LauncherApps#getShortcutIconResId(ShortcutInfo, UserHandle)
+     */
+    public boolean hasIconResource() {
+        return hasFlags(FLAG_HAS_ICON_RES);
+    }
+
+    /**
+     * Return whether a shortcut's icon is stored as a file.
+     *
+     * @see LauncherApps#getShortcutIconFd(ShortcutInfo, UserHandle)
+     */
+    public boolean hasIconFile() {
+        return hasFlags(FLAG_HAS_ICON_FILE);
+    }
+
+    /**
+     * Return whether a shortcut only contains "key" information only or not.  If true, only the
+     * following fields are available.
+     * <ul>
+     *     <li>{@link #getId()}
+     *     <li>{@link #getPackageName()}
+     *     <li>{@link #getLastChangedTimestamp()}
+     *     <li>{@link #isDynamic()}
+     *     <li>{@link #isPinned()}
+     *     <li>{@link #hasIconResource()}
+     *     <li>{@link #hasIconFile()}
+     * </ul>
+     */
+    public boolean hasKeyFieldsOnly() {
+        return hasFlags(FLAG_KEY_FIELDS_ONLY);
+    }
+
+    /** @hide */
+    public void updateTimestamp() {
+        mLastChangedTimestamp = System.currentTimeMillis();
+    }
+
+    /** @hide */
+    // VisibleForTesting
+    public void setTimestamp(long value) {
+        mLastChangedTimestamp = value;
+    }
+
+    /** @hide */
+    public void clearIcon() {
+        mIcon = null;
+    }
+
+    /** @hide */
+    public void setIconResourceId(int iconResourceId) {
+        mIconResourceId = iconResourceId;
+    }
+
+    /** @hide */
+    public int getIconResourceId() {
+        return mIconResourceId;
+    }
+
+    /** @hide */
+    public String getBitmapPath() {
+        return mBitmapPath;
+    }
+
+    /** @hide */
+    public void setBitmapPath(String bitmapPath) {
+        mBitmapPath = bitmapPath;
+    }
+
+    private ShortcutInfo(Parcel source) {
+        final ClassLoader cl = getClass().getClassLoader();
+
+        mId = source.readString();
+        mPackageName = source.readString();
+        mActivityComponent = source.readParcelable(cl);
+        mIcon = source.readParcelable(cl);
+        mTitle = source.readString();
+        mIntent = source.readParcelable(cl);
+        mIntentPersistableExtras = source.readParcelable(cl);
+        mWeight = source.readInt();
+        mExtras = source.readParcelable(cl);
+        mLastChangedTimestamp = source.readLong();
+        mFlags = source.readInt();
+        mIconResourceId = source.readInt();
+        mBitmapPath = source.readString();
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeString(mId);
+        dest.writeString(mPackageName);
+        dest.writeParcelable(mActivityComponent, flags);
+        dest.writeParcelable(mIcon, flags);
+        dest.writeString(mTitle);
+        dest.writeParcelable(mIntent, flags);
+        dest.writeParcelable(mIntentPersistableExtras, flags);
+        dest.writeInt(mWeight);
+        dest.writeParcelable(mExtras, flags);
+        dest.writeLong(mLastChangedTimestamp);
+        dest.writeInt(mFlags);
+        dest.writeInt(mIconResourceId);
+        dest.writeString(mBitmapPath);
+    }
+
+    public static final Creator<ShortcutInfo> CREATOR =
+            new Creator<ShortcutInfo>() {
+                public ShortcutInfo createFromParcel(Parcel source) {
+                    return new ShortcutInfo(source);
+                }
+                public ShortcutInfo[] newArray(int size) {
+                    return new ShortcutInfo[size];
+                }
+            };
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    /**
+     * Return a string representation, intended for logging.  Some fields will be retracted.
+     */
+    @Override
+    public String toString() {
+        return toStringInner(/* secure =*/ true, /* includeInternalData =*/ false);
+    }
+
+    /** @hide */
+    public String toInsecureString() {
+        return toStringInner(/* secure =*/ false, /* includeInternalData =*/ true);
+    }
+
+    private String toStringInner(boolean secure, boolean includeInternalData) {
+        final StringBuilder sb = new StringBuilder();
+        sb.append("ShortcutInfo {");
+
+        sb.append("id=");
+        sb.append(secure ? "***" : mId);
+
+        sb.append(", packageName=");
+        sb.append(mPackageName);
+
+        if (isDynamic()) {
+            sb.append(", dynamic");
+        }
+        if (isPinned()) {
+            sb.append(", pinned");
+        }
+
+        sb.append(", activity=");
+        sb.append(mActivityComponent);
+
+        sb.append(", title=");
+        sb.append(secure ? "***" : mTitle);
+
+        sb.append(", icon=");
+        sb.append(mIcon);
+
+        sb.append(", weight=");
+        sb.append(mWeight);
+
+        sb.append(", timestamp=");
+        sb.append(mLastChangedTimestamp);
+
+        sb.append(", intent=");
+        sb.append(mIntent);
+
+        sb.append(", intentExtras=");
+        sb.append(secure ? "***" : mIntentPersistableExtras);
+
+        sb.append(", extras=");
+        sb.append(mExtras);
+
+        sb.append(", flags=");
+        sb.append(mFlags);
+
+        if (includeInternalData) {
+
+            sb.append(", iconRes=");
+            sb.append(mIconResourceId);
+
+            sb.append(", bitmapPath=");
+            sb.append(mBitmapPath);
+        }
+
+        sb.append("}");
+        return sb.toString();
+    }
+
+    /** @hide */
+    public ShortcutInfo(String id, String packageName, ComponentName activityComponent,
+            Icon icon, String title, Intent intent, PersistableBundle intentPersistableExtras,
+            int weight, PersistableBundle extras, long lastChangedTimestamp,
+            int flags, int iconResId, String bitmapPath) {
+        mId = id;
+        mPackageName = packageName;
+        mActivityComponent = activityComponent;
+        mIcon = icon;
+        mTitle = title;
+        mIntent = intent;
+        mIntentPersistableExtras = intentPersistableExtras;
+        mWeight = weight;
+        mExtras = extras;
+        mLastChangedTimestamp = lastChangedTimestamp;
+        mFlags = flags;
+        mIconResourceId = iconResId;
+        mBitmapPath = bitmapPath;
+    }
+}
diff --git a/core/java/android/content/pm/ShortcutManager.java b/core/java/android/content/pm/ShortcutManager.java
new file mode 100644
index 0000000..b247f65
--- /dev/null
+++ b/core/java/android/content/pm/ShortcutManager.java
@@ -0,0 +1,258 @@
+/*
+ * 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.content.Context;
+import android.os.RemoteException;
+import android.os.UserHandle;
+import android.util.Log;
+
+import com.android.internal.annotations.VisibleForTesting;
+
+import java.util.List;
+
+/**
+ * TODO Enhance javadoc
+ *
+ * {@link ShortcutManager} manages shortcuts created by applications.
+ *
+ * <h3>Dynamic shortcuts and pinned shortcuts</h3>
+ *
+ * An application can publish shortcuts with {@link #setDynamicShortcuts(List)} and
+ * {@link #addDynamicShortcut(ShortcutInfo)}.  There can be at most
+ * {@link #getMaxDynamicShortcutCount()} number of dynamic shortcuts at a time from the same
+ * application.
+ * A dynamic shortcut can be deleted with {@link #deleteDynamicShortcut(String)}, and apps
+ * can also use {@link #deleteAllDynamicShortcuts()} to delete all dynamic shortcuts.
+ *
+ * <p>The shortcuts that are currently published by the above APIs are called "dynamic", because
+ * they can be removed by the creator application at any time.  The user may "pin" dynamic shortcuts
+ * on Launcher to make "pinned" shortcuts.  Pinned shortcuts <b>cannot</b> be removed by the creator
+ * app.  An application can obtain all pinned shortcuts from itself with
+ * {@link #getPinnedShortcuts()}.  Applications should keep the pinned shortcut information
+ * up-to-date using {@link #updateShortcuts(List)}.
+ *
+ * <p>The number of pinned shortcuts does not affect the number of dynamic shortcuts that can be
+ * published by an application at a time.
+ * No matter how many pinned shortcuts that Launcher has for an application, the
+ * application can still always publish {@link #getMaxDynamicShortcutCount()} number of dynamic
+ * shortcuts.
+ *
+ * <h3>Shortcut IDs</h3>
+ *
+ * Each shortcut must have an ID, which must be unique within each application.  When a shortcut is
+ * published, existing shortcuts with the same ID will be updated.  Note this may include a
+ * pinned shortcut.
+ *
+ * <h3>Rate limiting</h3>
+ *
+ * Calls to {@link #setDynamicShortcuts(List)}, {@link #addDynamicShortcut(ShortcutInfo)},
+ * and {@link #updateShortcuts(List)} will be
+ * rate-limited.  An application can call these methods at most
+ * {@link #getRemainingCallCount()} times until the rate-limiting counter is reset,
+ * which happens at a certain time every day.
+ *
+ * <p>An applications can use {@link #getRateLimitResetTime()} to get the next reset time.
+ *
+ * <h3>Backup and Restore</h3>
+ *
+ * Shortcuts will be backed up and restored across devices.  This means all information, including
+ * IDs, must be meaningful on a different device.
+ *
+ * TODO: Define a Broadcast to let apps update shortcuts on a restored device.
+ *
+ * <h3>APIs for launcher</h3>
+ *
+ * Launcher applications should use {@link LauncherApps} to get shortcuts that are published from
+ * applications.  Launcher applications can also pin shortcuts with
+ * {@link LauncherApps#pinShortcuts(String, List, UserHandle)}.
+ */
+public class ShortcutManager {
+    private static final String TAG = "ShortcutManager";
+
+    private final Context mContext;
+    private final IShortcutService mService;
+
+    /**
+     * @hide
+     */
+    public ShortcutManager(Context context, IShortcutService service) {
+        mContext = context;
+        mService = service;
+    }
+
+    /**
+     * Publish a list of shortcuts.  All existing dynamic shortcuts from the caller application
+     * will be replaced.
+     *
+     * <p>This API will be rate-limited.
+     *
+     * @return {@code true} if the call has succeeded. {@code false} if the call is rate-limited.
+     *
+     * @throws IllegalArgumentException if {@code shortcutInfoList} contains more than
+     * {@link #getMaxDynamicShortcutCount()} shortcuts.
+     */
+    public boolean setDynamicShortcuts(@NonNull List<ShortcutInfo> shortcutInfoList) {
+        try {
+            return mService.setDynamicShortcuts(mContext.getPackageName(),
+                    new ParceledListSlice(shortcutInfoList), injectMyUserId());
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Return all dynamic shortcuts from the caller application.  The number of result items
+     * will not exceed the value returned by {@link #getMaxDynamicShortcutCount()}.
+     */
+    @NonNull
+    public List<ShortcutInfo> getDynamicShortcuts() {
+        try {
+            return mService.getDynamicShortcuts(mContext.getPackageName(), injectMyUserId())
+                    .getList();
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Publish a single dynamic shortcut.  If there's already dynamic or pinned shortcuts with
+     * the same ID, they will all be updated.
+     *
+     * <p>This API will be rate-limited.
+     *
+     * @return {@code true} if the call has succeeded. {@code false} if the call is rate-limited.
+     *
+     * @throws IllegalArgumentException if the caller application has already published the
+     * max number of dynamic shortcuts.
+     */
+    public boolean addDynamicShortcut(@NonNull ShortcutInfo shortcutInfo) {
+        try {
+            return mService.addDynamicShortcut(
+                    mContext.getPackageName(), shortcutInfo, injectMyUserId());
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Delete a single dynamic shortcut by ID.
+     */
+    public void deleteDynamicShortcut(@NonNull String shortcutId) {
+        try {
+            mService.deleteDynamicShortcut(mContext.getPackageName(), shortcutId, injectMyUserId());
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Delete all dynamic shortcuts from the caller application.
+     */
+    public void deleteAllDynamicShortcuts() {
+        try {
+            mService.deleteAllDynamicShortcuts(mContext.getPackageName(), injectMyUserId());
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Return all pinned shortcuts from the caller application.
+     */
+    @NonNull
+    public List<ShortcutInfo> getPinnedShortcuts() {
+        try {
+            return mService.getPinnedShortcuts(mContext.getPackageName(), injectMyUserId())
+                    .getList();
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Update all existing shortcuts with the same IDs.  Shortcuts may be pinned and/or dynamic.
+     *
+     * <p>This API will be rate-limited.
+     *
+     * @return {@code true} if the call has succeeded. {@code false} if the call is rate-limited.
+     */
+    public boolean updateShortcuts(List<ShortcutInfo> shortcutInfoList) {
+        try {
+            return mService.updateShortcuts(mContext.getPackageName(),
+                    new ParceledListSlice(shortcutInfoList), injectMyUserId());
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Return the max number of dynamic shortcuts that each application can have at a time.
+     */
+    public int getMaxDynamicShortcutCount() {
+        try {
+            return mService.getMaxDynamicShortcutCount(mContext.getPackageName(), injectMyUserId());
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Return the number of times the caller application can call the rate-limited APIs
+     * before the rate limit counter is reset.
+     *
+     * @see #getRateLimitResetTime()
+     */
+    public int getRemainingCallCount() {
+        try {
+            return mService.getRemainingCallCount(mContext.getPackageName(), injectMyUserId());
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Return when the rate limit count will be reset next time, in milliseconds since the epoch.
+     *
+     * @see #getRemainingCallCount()
+     * @see System#currentTimeMillis()
+     */
+    public long getRateLimitResetTime() {
+        try {
+            return mService.getRateLimitResetTime(mContext.getPackageName(), injectMyUserId());
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Return the max width and height for icons, in pixels.
+     */
+    public int getIconMaxDimensions() {
+        try {
+            return mService.getIconMaxDimensions(mContext.getPackageName(), injectMyUserId());
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /** @hide injection point */
+    @VisibleForTesting
+    protected int injectMyUserId() {
+        return UserHandle.myUserId();
+    }
+}
diff --git a/core/java/android/content/pm/ShortcutServiceInternal.java b/core/java/android/content/pm/ShortcutServiceInternal.java
new file mode 100644
index 0000000..918c763
--- /dev/null
+++ b/core/java/android/content/pm/ShortcutServiceInternal.java
@@ -0,0 +1,66 @@
+/*
+ * 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.annotation.UserIdInt;
+import android.content.ComponentName;
+import android.content.Intent;
+import android.content.pm.LauncherApps.ShortcutQuery;
+import android.os.ParcelFileDescriptor;
+import android.os.UserHandle;
+
+import java.util.List;
+
+/**
+ * Entry points used by {@link LauncherApps}.
+ *
+ * <p>No permission / argument checks will be performed inside.
+ * Callers must check the calling app permission and the calling package name.
+ * @hide
+ */
+public abstract class ShortcutServiceInternal {
+    public interface ShortcutChangeListener {
+        void onShortcutChanged(@NonNull String packageName,
+                @NonNull List<ShortcutInfo> shortcuts, @UserIdInt int userId);
+    }
+
+    public abstract List<ShortcutInfo>
+            getShortcuts(@NonNull String callingPackage, long changedSince,
+            @Nullable String packageName, @Nullable ComponentName componentName,
+            @ShortcutQuery.QueryFlags int flags,
+            int userId);
+
+    public abstract List<ShortcutInfo>
+            getShortcutInfo(@NonNull String callingPackage,
+            @NonNull String packageName, @Nullable List<String> ids, int userId);
+
+    public abstract void pinShortcuts(@NonNull String callingPackage, @NonNull String packageName,
+            @NonNull List<String> shortcutIds, int userId);
+
+    public abstract Intent createShortcutIntent(@NonNull String callingPackage,
+            @NonNull String packageName, @NonNull String shortcutId, int userId);
+
+    public abstract void addListener(@NonNull ShortcutChangeListener listener);
+
+    public abstract int getShortcutIconResId(@NonNull String callingPackage,
+            @NonNull ShortcutInfo shortcut, int userId);
+
+    public abstract ParcelFileDescriptor getShortcutIconFd(@NonNull String callingPackage,
+            @NonNull ShortcutInfo shortcut, int userId);
+}
diff --git a/core/java/android/content/res/ConfigurationBoundResourceCache.java b/core/java/android/content/res/ConfigurationBoundResourceCache.java
index fecda87..40d2a82 100644
--- a/core/java/android/content/res/ConfigurationBoundResourceCache.java
+++ b/core/java/android/content/res/ConfigurationBoundResourceCache.java
@@ -23,29 +23,19 @@
  * @hide For internal use only.
  */
 public class ConfigurationBoundResourceCache<T> extends ThemedResourceCache<ConstantState<T>> {
-    private final Resources mResources;
-
-    /**
-     * Creates a cache for the given Resources instance.
-     *
-     * @param resources the resources to use when creating new instances
-     */
-    public ConfigurationBoundResourceCache(Resources resources) {
-        mResources = resources;
-    }
-
     /**
      * If the resource is cached, creates and returns a new instance of it.
      *
      * @param key a key that uniquely identifies the drawable resource
+     * @param resources a Resources object from which to create new instances.
      * @param theme the theme where the resource will be used
      * @return a new instance of the resource, or {@code null} if not in
      *         the cache
      */
-    public T getInstance(long key, Resources.Theme theme) {
+    public T getInstance(long key, Resources resources, Resources.Theme theme) {
         final ConstantState<T> entry = get(key, theme);
         if (entry != null) {
-            return entry.newInstance(mResources, theme);
+            return entry.newInstance(resources, theme);
         }
 
         return null;
diff --git a/core/java/android/content/res/DrawableCache.java b/core/java/android/content/res/DrawableCache.java
index ba00134..7b27fac 100644
--- a/core/java/android/content/res/DrawableCache.java
+++ b/core/java/android/content/res/DrawableCache.java
@@ -22,29 +22,19 @@
  * Class which can be used to cache Drawable resources against a theme.
  */
 class DrawableCache extends ThemedResourceCache<Drawable.ConstantState> {
-    private final Resources mResources;
-
-    /**
-     * Creates a cache for the given Resources instance.
-     *
-     * @param resources the resources to use when creating new instances
-     */
-    public DrawableCache(Resources resources) {
-        mResources = resources;
-    }
-
     /**
      * If the resource is cached, creates and returns a new instance of it.
      *
      * @param key a key that uniquely identifies the drawable resource
+     * @param resources a Resources object from which to create new instances.
      * @param theme the theme where the resource will be used
      * @return a new instance of the resource, or {@code null} if not in
      *         the cache
      */
-    public Drawable getInstance(long key, Resources.Theme theme) {
+    public Drawable getInstance(long key, Resources resources, Resources.Theme theme) {
         final Drawable.ConstantState entry = get(key, theme);
         if (entry != null) {
-            return entry.newDrawable(mResources, theme);
+            return entry.newDrawable(resources, theme);
         }
 
         return null;
diff --git a/core/java/android/content/res/GradientColor.java b/core/java/android/content/res/GradientColor.java
index 98ef2ea..cc46cbd 100644
--- a/core/java/android/content/res/GradientColor.java
+++ b/core/java/android/content/res/GradientColor.java
@@ -17,6 +17,7 @@
 package android.content.res;
 
 import android.annotation.ColorInt;
+import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.content.res.Resources.Theme;
@@ -37,13 +38,48 @@
 import android.util.Xml;
 
 import java.io.IOException;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 
-
+/**
+ * Lets you define a gradient color, which is used inside
+ * {@link android.graphics.drawable.VectorDrawable}.
+ *
+ * {@link android.content.res.GradientColor}s are created from XML resource files defined in the
+ * "color" subdirectory directory of an application's resource directory.  The XML file contains
+ * a single "gradient" element with a number of attributes and elements inside.  For example:
+ * <pre>
+ * &lt;gradient xmlns:android="http://schemas.android.com/apk/res/android"&gt;
+ *   &lt;android:startColor="?android:attr/colorPrimary"/&gt;
+ *   &lt;android:endColor="?android:attr/colorControlActivated"/&gt;
+ *   &lt;.../&gt;
+ *   &lt;android:type="linear"/&gt;
+ * &lt;/gradient&gt;
+ * </pre>
+ *
+ * This can describe either a {@link android.graphics.LinearGradient},
+ * {@link android.graphics.RadialGradient}, or {@link android.graphics.SweepGradient}.
+ *
+ * Note that different attributes are relevant for different types of gradient.
+ * For example, android:gradientRadius is only applied to RadialGradient.
+ * androd:centerX and android:centerY are only applied to SweepGradient or RadialGradient.
+ * android:startX, android:startY, android:endX and android:endY are only applied to LinearGradient.
+ *
+ * Also note if any color "item" element is defined, then startColor, centerColor and endColor will
+ * be ignored.
+ */
 public class GradientColor extends ComplexColor {
     private static final String TAG = "GradientColor";
 
     private static final boolean DBG_GRADIENT = false;
 
+    @IntDef({TILE_MODE_CLAMP, TILE_MODE_REPEAT, TILE_MODE_MIRROR})
+    @Retention(RetentionPolicy.SOURCE)
+    private @interface GradientTileMode {}
+    private static final int TILE_MODE_CLAMP = 0;
+    private static final int TILE_MODE_REPEAT = 1;
+    private static final int TILE_MODE_MIRROR = 2;
+
     /** Lazily-created factory for this GradientColor. */
     private GradientColorFactory mFactory;
 
@@ -54,7 +90,8 @@
     // all the XML information.
     private Shader mShader = null;
 
-    // Below are the attributes at the root element <gradient>
+    // Below are the attributes at the root element <gradient>.
+    // NOTE: they need to be copied in the copy constructor!
     private int mGradientType = GradientDrawable.LINEAR_GRADIENT;
 
     private float mCenterX = 0f;
@@ -70,6 +107,8 @@
     private int mEndColor = 0;
     private boolean mHasCenterColor = false;
 
+    private int mTileMode = 0; // Clamp mode.
+
     private float mGradientRadius = 0f;
 
     // Below are the attributes for the <item> element.
@@ -100,6 +139,7 @@
             mEndColor = copy.mEndColor;
             mHasCenterColor = copy.mHasCenterColor;
             mGradientRadius = copy.mGradientRadius;
+            mTileMode = copy.mTileMode;
 
             if (copy.mItemColors != null) {
                 mItemColors = copy.mItemColors.clone();
@@ -117,6 +157,20 @@
         }
     }
 
+    // Set the default to clamp mode.
+    private static Shader.TileMode parseTileMode(@GradientTileMode int tileMode) {
+        switch (tileMode) {
+            case TILE_MODE_CLAMP:
+                return Shader.TileMode.CLAMP;
+            case TILE_MODE_REPEAT:
+                return Shader.TileMode.REPEAT;
+            case TILE_MODE_MIRROR:
+                return Shader.TileMode.MIRROR;
+            default:
+                return Shader.TileMode.CLAMP;
+        }
+    }
+
     /**
      * Update the root level's attributes, either for inflate or applyTheme.
      */
@@ -150,6 +204,9 @@
         mEndColor = a.getColor(
                 R.styleable.GradientColor_endColor, mEndColor);
 
+        mTileMode = a.getInt(
+                R.styleable.GradientColor_tileMode, mTileMode);
+
         if (DBG_GRADIENT) {
             Log.v(TAG, "hasCenterColor is " + mHasCenterColor);
             if (mHasCenterColor) {
@@ -157,6 +214,7 @@
             }
             Log.v(TAG, "startColor: " + mStartColor);
             Log.v(TAG, "endColor: " + mEndColor);
+            Log.v(TAG, "tileMode: " + mTileMode);
         }
 
         mGradientRadius = a.getFloat(R.styleable.GradientColor_gradientRadius,
@@ -406,11 +464,11 @@
 
         if (mGradientType == GradientDrawable.LINEAR_GRADIENT) {
             mShader = new LinearGradient(mStartX, mStartY, mEndX, mEndY, tempColors, tempOffsets,
-                    Shader.TileMode.CLAMP);
+                    parseTileMode(mTileMode));
         } else {
             if (mGradientType == GradientDrawable.RADIAL_GRADIENT) {
                 mShader = new RadialGradient(mCenterX, mCenterY, mGradientRadius, tempColors,
-                        tempOffsets, Shader.TileMode.CLAMP);
+                        tempOffsets, parseTileMode(mTileMode));
             } else {
                 mShader = new SweepGradient(mCenterX, mCenterY, tempColors, tempOffsets);
             }
diff --git a/core/java/android/content/res/Resources.java b/core/java/android/content/res/Resources.java
index a9150e8..fb706fc 100644
--- a/core/java/android/content/res/Resources.java
+++ b/core/java/android/content/res/Resources.java
@@ -40,26 +40,21 @@
 import android.annotation.XmlRes;
 import android.content.pm.ActivityInfo;
 import android.graphics.Movie;
-import android.graphics.drawable.ColorDrawable;
 import android.graphics.drawable.Drawable;
 import android.graphics.drawable.Drawable.ConstantState;
 import android.graphics.drawable.DrawableInflater;
-import android.icu.text.PluralRules;
 import android.os.Build;
 import android.os.Bundle;
-import android.os.Trace;
 import android.util.AttributeSet;
 import android.util.DisplayMetrics;
-import android.util.LocaleList;
 import android.util.Log;
 import android.util.LongSparseArray;
 import android.util.Pools.SynchronizedPool;
-import android.util.Slog;
 import android.util.TypedValue;
-import android.util.Xml;
 import android.view.ViewDebug;
 import android.view.ViewHierarchyEncoder;
 
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.GrowingArrayUtils;
 import com.android.internal.util.XmlUtils;
 
@@ -68,7 +63,8 @@
 
 import java.io.IOException;
 import java.io.InputStream;
-import java.util.Locale;
+import java.lang.ref.WeakReference;
+import java.util.ArrayList;
 
 /**
  * Class for accessing an application's resources.  This sits on top of the
@@ -98,48 +94,15 @@
 public class Resources {
     static final String TAG = "Resources";
 
-    private static final boolean DEBUG_LOAD = false;
-    private static final boolean DEBUG_CONFIG = false;
-    private static final boolean TRACE_FOR_PRELOAD = false;
-    private static final boolean TRACE_FOR_MISS_PRELOAD = false;
-
-    private static final int LAYOUT_DIR_CONFIG = ActivityInfo.activityInfoConfigToNative(
-            ActivityInfo.CONFIG_LAYOUT_DIRECTION);
-
-    private static final int ID_OTHER = 0x01000004;
-
     private static final Object sSync = new Object();
 
-    // Information about preloaded resources.  Note that they are not
-    // protected by a lock, because while preloading in zygote we are all
-    // single-threaded, and after that these are immutable.
-    private static final LongSparseArray<ConstantState>[] sPreloadedDrawables;
-    private static final LongSparseArray<ConstantState> sPreloadedColorDrawables
-            = new LongSparseArray<>();
-    private static final LongSparseArray<android.content.res.ConstantState<ComplexColor>>
-            sPreloadedComplexColors = new LongSparseArray<>();
-
-    // Pool of TypedArrays targeted to this Resources object.
-    final SynchronizedPool<TypedArray> mTypedArrayPool = new SynchronizedPool<>(5);
-
     // Used by BridgeResources in layoutlib
     static Resources mSystem = null;
 
-    private static boolean sPreloaded;
+    private ResourcesImpl mResourcesImpl;
 
-    /** Lock object used to protect access to caches and configuration. */
-    private final Object mAccessLock = new Object();
-
-    // These are protected by mAccessLock.
-    private final Configuration mTmpConfig = new Configuration();
-    private final DrawableCache mDrawableCache = new DrawableCache(this);
-    private final DrawableCache mColorDrawableCache = new DrawableCache(this);
-    private final ConfigurationBoundResourceCache<ComplexColor> mComplexColorCache =
-            new ConfigurationBoundResourceCache<>(this);
-    private final ConfigurationBoundResourceCache<Animator> mAnimatorCache =
-            new ConfigurationBoundResourceCache<>(this);
-    private final ConfigurationBoundResourceCache<StateListAnimator> mStateListAnimatorCache =
-            new ConfigurationBoundResourceCache<>(this);
+    // Pool of TypedArrays targeted to this Resources object.
+    final SynchronizedPool<TypedArray> mTypedArrayPool = new SynchronizedPool<>(5);
 
     /** Used to inflate drawable objects from XML. */
     private DrawableInflater mDrawableInflater;
@@ -150,28 +113,14 @@
     /** Single-item pool used to minimize TypedValue allocations. */
     private TypedValue mTmpValue = new TypedValue();
 
-    private boolean mPreloading;
-
-    // Cyclical cache used for recently-accessed XML files.
-    private int mLastCachedXmlBlockIndex = -1;
-    private final String[] mCachedXmlBlockFiles = new String[4];
-    private final XmlBlock[] mCachedXmlBlocks = new XmlBlock[4];
-
-    final AssetManager mAssets;
     final ClassLoader mClassLoader;
-    final DisplayMetrics mMetrics = new DisplayMetrics();
 
-    private final Configuration mConfiguration = new Configuration();
-
-    private PluralRules mPluralRule;
-
-    private CompatibilityInfo mCompatibilityInfo = CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO;
-
-    static {
-        sPreloadedDrawables = new LongSparseArray[2];
-        sPreloadedDrawables[0] = new LongSparseArray<>();
-        sPreloadedDrawables[1] = new LongSparseArray<>();
-    }
+    /**
+     * WeakReferences to Themes that were constructed from this Resources object.
+     * We keep track of these in case our underlying implementation is changed, in which case
+     * the Themes must also get updated ThemeImpls.
+     */
+    private final ArrayList<WeakReference<Theme>> mThemeRefs = new ArrayList<>();
 
     /**
      * Returns the most appropriate default theme for the specified target SDK version.
@@ -214,32 +163,20 @@
     }
 
     /**
-     * @return the inflater used to create drawable objects
-     * @hide Pending API finalization.
+     * Return a global shared Resources object that provides access to only
+     * system resources (no application resources), and is not configured for
+     * the current screen (can not use dimension units, does not change based
+     * on orientation, etc).
      */
-    public final DrawableInflater getDrawableInflater() {
-        if (mDrawableInflater == null) {
-            mDrawableInflater = new DrawableInflater(this, mClassLoader);
+    public static Resources getSystem() {
+        synchronized (sSync) {
+            Resources ret = mSystem;
+            if (ret == null) {
+                ret = new Resources();
+                mSystem = ret;
+            }
+            return ret;
         }
-        return mDrawableInflater;
-    }
-
-    /**
-     * Used by AnimatorInflater.
-     *
-     * @hide
-     */
-    public ConfigurationBoundResourceCache<Animator> getAnimatorCache() {
-        return mAnimatorCache;
-    }
-
-    /**
-     * Used by AnimatorInflater.
-     *
-     * @hide
-     */
-    public ConfigurationBoundResourceCache<StateListAnimator> getStateListAnimatorCache() {
-        return mStateListAnimatorCache;
     }
 
     /**
@@ -270,51 +207,105 @@
      *               selecting/computing resource values (optional).
      */
     public Resources(AssetManager assets, DisplayMetrics metrics, Configuration config) {
-        this(assets, metrics, config, CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO, null);
+        this(null);
+        mResourcesImpl = new ResourcesImpl(assets, metrics, config,
+                CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO);
     }
 
     /**
      * Creates a new Resources object with CompatibilityInfo.
      *
-     * @param assets Previously created AssetManager.
-     * @param metrics Current display metrics to consider when
-     *                selecting/computing resource values.
-     * @param config Desired device configuration to consider when
-     *               selecting/computing resource values (optional).
-     * @param compatInfo this resource's compatibility info. Must not be null.
      * @param classLoader class loader for the package used to load custom
      *                    resource classes, may be {@code null} to use system
      *                    class loader
      * @hide
      */
-    public Resources(AssetManager assets, DisplayMetrics metrics, Configuration config,
-            CompatibilityInfo compatInfo, @Nullable ClassLoader classLoader) {
-        mAssets = assets;
+    public Resources(@Nullable ClassLoader classLoader) {
         mClassLoader = classLoader == null ? ClassLoader.getSystemClassLoader() : classLoader;
-        mMetrics.setToDefaults();
-        if (compatInfo != null) {
-            mCompatibilityInfo = compatInfo;
-        }
-        updateConfiguration(config, metrics);
-        assets.ensureStringBlocks();
     }
 
     /**
-     * Return a global shared Resources object that provides access to only
-     * system resources (no application resources), and is not configured for
-     * the current screen (can not use dimension units, does not change based
-     * on orientation, etc).
+     * Only for creating the System resources.
      */
-    public static Resources getSystem() {
-        synchronized (sSync) {
-            Resources ret = mSystem;
-            if (ret == null) {
-                ret = new Resources();
-                mSystem = ret;
-            }
+    private Resources() {
+        this(null);
 
-            return ret;
+        final DisplayMetrics metrics = new DisplayMetrics();
+        metrics.setToDefaults();
+
+        final Configuration config = new Configuration();
+        config.setToDefaults();
+
+        mResourcesImpl = new ResourcesImpl(AssetManager.getSystem(), metrics, config,
+                CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO);
+    }
+
+    /**
+     * Set the underlying implementation (containing all the resources and caches)
+     * and updates all Theme references to new implementations as well.
+     * @hide
+     */
+    public void setImpl(ResourcesImpl impl) {
+        if (impl == mResourcesImpl) {
+            return;
         }
+
+        mResourcesImpl = impl;
+
+        // Create new ThemeImpls that are identical to the ones we have.
+        synchronized (mThemeRefs) {
+            final int count = mThemeRefs.size();
+            for (int i = 0; i < count; i++) {
+                WeakReference<Theme> weakThemeRef = mThemeRefs.get(i);
+                Theme theme = weakThemeRef != null ? weakThemeRef.get() : null;
+                if (theme != null) {
+                    theme.setImpl(mResourcesImpl.newThemeImpl(theme.getKey()));
+                }
+            }
+        }
+    }
+
+    /**
+     * @hide
+     */
+    public ResourcesImpl getImpl() {
+        return mResourcesImpl;
+    }
+
+    /**
+     * @hide
+     */
+    public ClassLoader getClassLoader() {
+        return mClassLoader;
+    }
+
+    /**
+     * @return the inflater used to create drawable objects
+     * @hide Pending API finalization.
+     */
+    public final DrawableInflater getDrawableInflater() {
+        if (mDrawableInflater == null) {
+            mDrawableInflater = new DrawableInflater(this, mClassLoader);
+        }
+        return mDrawableInflater;
+    }
+
+    /**
+     * Used by AnimatorInflater.
+     *
+     * @hide
+     */
+    public ConfigurationBoundResourceCache<Animator> getAnimatorCache() {
+        return mResourcesImpl.getAnimatorCache();
+    }
+
+    /**
+     * Used by AnimatorInflater.
+     *
+     * @hide
+     */
+    public ConfigurationBoundResourceCache<StateListAnimator> getStateListAnimatorCache() {
+        return mResourcesImpl.getStateListAnimatorCache();
     }
 
     /**
@@ -332,8 +323,8 @@
      * @return CharSequence The string data associated with the resource, plus
      *         possibly styled text information.
      */
-    public CharSequence getText(@StringRes int id) throws NotFoundException {
-        CharSequence res = mAssets.getResourceText(id);
+    @NonNull public CharSequence getText(@StringRes int id) throws NotFoundException {
+        CharSequence res = mResourcesImpl.getAssets().getResourceText(id);
         if (res != null) {
             return res;
         }
@@ -361,41 +352,10 @@
      * @return CharSequence The string data associated with the resource, plus
      *         possibly styled text information.
      */
+    @NonNull
     public CharSequence getQuantityText(@PluralsRes int id, int quantity)
             throws NotFoundException {
-        PluralRules rule = getPluralRule();
-        CharSequence res = mAssets.getResourceBagText(id,
-                attrForQuantityCode(rule.select(quantity)));
-        if (res != null) {
-            return res;
-        }
-        res = mAssets.getResourceBagText(id, ID_OTHER);
-        if (res != null) {
-            return res;
-        }
-        throw new NotFoundException("Plural resource ID #0x" + Integer.toHexString(id)
-                + " quantity=" + quantity
-                + " item=" + rule.select(quantity));
-    }
-
-    private PluralRules getPluralRule() {
-        synchronized (sSync) {
-            if (mPluralRule == null) {
-                mPluralRule = PluralRules.forLocale(mConfiguration.getLocales().get(0));
-            }
-            return mPluralRule;
-        }
-    }
-
-    private static int attrForQuantityCode(String quantityCode) {
-        switch (quantityCode) {
-            case PluralRules.KEYWORD_ZERO: return 0x01000005;
-            case PluralRules.KEYWORD_ONE:  return 0x01000006;
-            case PluralRules.KEYWORD_TWO:  return 0x01000007;
-            case PluralRules.KEYWORD_FEW:  return 0x01000008;
-            case PluralRules.KEYWORD_MANY: return 0x01000009;
-            default:                     return ID_OTHER;
-        }
+        return mResourcesImpl.getQuantityText(id, quantity);
     }
 
     /**
@@ -414,12 +374,7 @@
      */
     @NonNull
     public String getString(@StringRes int id) throws NotFoundException {
-        final CharSequence res = getText(id);
-        if (res != null) {
-            return res.toString();
-        }
-        throw new NotFoundException("String resource ID #0x"
-                                    + Integer.toHexString(id));
+        return getText(id).toString();
     }
 
 
@@ -444,7 +399,8 @@
     @NonNull
     public String getString(@StringRes int id, Object... formatArgs) throws NotFoundException {
         final String raw = getString(id);
-        return String.format(mConfiguration.getLocales().get(0), raw, formatArgs);
+        return String.format(mResourcesImpl.getConfiguration().getLocales().get(0), raw,
+                formatArgs);
     }
 
     /**
@@ -472,10 +428,12 @@
      * @return String The string data associated with the resource,
      * stripped of styled text information.
      */
+    @NonNull
     public String getQuantityString(@PluralsRes int id, int quantity, Object... formatArgs)
             throws NotFoundException {
         String raw = getQuantityText(id, quantity).toString();
-        return String.format(mConfiguration.getLocales().get(0), raw, formatArgs);
+        return String.format(mResourcesImpl.getConfiguration().getLocales().get(0), raw,
+                formatArgs);
     }
 
     /**
@@ -498,8 +456,8 @@
      * @return String The string data associated with the resource,
      * stripped of styled text information.
      */
-    public String getQuantityString(@PluralsRes int id, int quantity)
-            throws NotFoundException {
+    @NonNull
+    public String getQuantityString(@PluralsRes int id, int quantity) throws NotFoundException {
         return getQuantityText(id, quantity).toString();
     }
 
@@ -518,7 +476,7 @@
      *         possibly styled text information, or def if id is 0 or not found.
      */
     public CharSequence getText(@StringRes int id, CharSequence def) {
-        CharSequence res = id != 0 ? mAssets.getResourceText(id) : null;
+        CharSequence res = id != 0 ? mResourcesImpl.getAssets().getResourceText(id) : null;
         return res != null ? res : def;
     }
 
@@ -533,13 +491,13 @@
      *
      * @return The styled text array associated with the resource.
      */
+    @NonNull
     public CharSequence[] getTextArray(@ArrayRes int id) throws NotFoundException {
-        CharSequence[] res = mAssets.getResourceTextArray(id);
+        CharSequence[] res = mResourcesImpl.getAssets().getResourceTextArray(id);
         if (res != null) {
             return res;
         }
-        throw new NotFoundException("Text array resource ID #0x"
-                                    + Integer.toHexString(id));
+        throw new NotFoundException("Text array resource ID #0x" + Integer.toHexString(id));
     }
 
     /**
@@ -553,14 +511,14 @@
      *
      * @return The string array associated with the resource.
      */
+    @NonNull
     public String[] getStringArray(@ArrayRes int id)
             throws NotFoundException {
-        String[] res = mAssets.getResourceStringArray(id);
+        String[] res = mResourcesImpl.getAssets().getResourceStringArray(id);
         if (res != null) {
             return res;
         }
-        throw new NotFoundException("String array resource ID #0x"
-                                    + Integer.toHexString(id));
+        throw new NotFoundException("String array resource ID #0x" + Integer.toHexString(id));
     }
 
     /**
@@ -574,13 +532,13 @@
      *
      * @return The int array associated with the resource.
      */
+    @NonNull
     public int[] getIntArray(@ArrayRes int id) throws NotFoundException {
-        int[] res = mAssets.getArrayIntResource(id);
+        int[] res = mResourcesImpl.getAssets().getArrayIntResource(id);
         if (res != null) {
             return res;
         }
-        throw new NotFoundException("Int array resource ID #0x"
-                                    + Integer.toHexString(id));
+        throw new NotFoundException("Int array resource ID #0x" + Integer.toHexString(id));
     }
 
     /**
@@ -596,16 +554,16 @@
      * Be sure to call {@link TypedArray#recycle() TypedArray.recycle()}
      * when done with it.
      */
-    public TypedArray obtainTypedArray(@ArrayRes int id)
-            throws NotFoundException {
-        int len = mAssets.getArraySize(id);
+    @NonNull
+    public TypedArray obtainTypedArray(@ArrayRes int id) throws NotFoundException {
+        final ResourcesImpl impl = mResourcesImpl;
+        int len = impl.getAssets().getArraySize(id);
         if (len < 0) {
-            throw new NotFoundException("Array resource ID #0x"
-                                        + Integer.toHexString(id));
+            throw new NotFoundException("Array resource ID #0x" + Integer.toHexString(id));
         }
         
         TypedArray array = TypedArray.obtain(this, len);
-        array.mLength = mAssets.retrieveArray(id, array.mData);
+        array.mLength = impl.getAssets().retrieveArray(id, array.mData);
         array.mIndices[0] = 0;
         
         return array;
@@ -629,10 +587,12 @@
      * @see #getDimensionPixelSize
      */
     public float getDimension(@DimenRes int id) throws NotFoundException {
-        final TypedValue value = obtainTempTypedValue(id);
+        final TypedValue value = obtainTempTypedValue();
         try {
+            final ResourcesImpl impl = mResourcesImpl;
+            impl.getValue(id, value, true);
             if (value.type == TypedValue.TYPE_DIMENSION) {
-                return TypedValue.complexToDimension(value.data, mMetrics);
+                return TypedValue.complexToDimension(value.data, impl.getDisplayMetrics());
             }
             throw new NotFoundException("Resource ID #0x" + Integer.toHexString(id)
                     + " type #0x" + Integer.toHexString(value.type) + " is not valid");
@@ -661,10 +621,13 @@
      * @see #getDimensionPixelSize
      */
     public int getDimensionPixelOffset(@DimenRes int id) throws NotFoundException {
-        final TypedValue value = obtainTempTypedValue(id);
+        final TypedValue value = obtainTempTypedValue();
         try {
+            final ResourcesImpl impl = mResourcesImpl;
+            impl.getValue(id, value, true);
             if (value.type == TypedValue.TYPE_DIMENSION) {
-                return TypedValue.complexToDimensionPixelOffset(value.data, mMetrics);
+                return TypedValue.complexToDimensionPixelOffset(value.data,
+                        impl.getDisplayMetrics());
             }
             throw new NotFoundException("Resource ID #0x" + Integer.toHexString(id)
                     + " type #0x" + Integer.toHexString(value.type) + " is not valid");
@@ -694,10 +657,12 @@
      * @see #getDimensionPixelOffset
      */
     public int getDimensionPixelSize(@DimenRes int id) throws NotFoundException {
-        final TypedValue value = obtainTempTypedValue(id);
+        final TypedValue value = obtainTempTypedValue();
         try {
+            final ResourcesImpl impl = mResourcesImpl;
+            impl.getValue(id, value, true);
             if (value.type == TypedValue.TYPE_DIMENSION) {
-                return TypedValue.complexToDimensionPixelSize(value.data, mMetrics);
+                return TypedValue.complexToDimensionPixelSize(value.data, impl.getDisplayMetrics());
             }
             throw new NotFoundException("Resource ID #0x" + Integer.toHexString(id)
                     + " type #0x" + Integer.toHexString(value.type) + " is not valid");
@@ -724,8 +689,9 @@
      * @throws NotFoundException Throws NotFoundException if the given ID does not exist.
      */
     public float getFraction(@FractionRes int id, int base, int pbase) {
-        final TypedValue value = obtainTempTypedValue(id);
+        final TypedValue value = obtainTempTypedValue();
         try {
+            mResourcesImpl.getValue(id, value, true);
             if (value.type == TypedValue.TYPE_FRACTION) {
                 return TypedValue.complexToFraction(value.data, base, pbase);
             }
@@ -795,9 +761,11 @@
      */
     public Drawable getDrawable(@DrawableRes int id, @Nullable Theme theme)
             throws NotFoundException {
-        final TypedValue value = obtainTempTypedValue(id);
+        final TypedValue value = obtainTempTypedValue();
         try {
-            return loadDrawable(value, id, theme);
+            final ResourcesImpl impl = mResourcesImpl;
+            impl.getValue(id, value, true);
+            return impl.loadDrawable(this, value, id, theme, true);
         } finally {
             releaseTempTypedValue(value);
         }
@@ -850,14 +818,16 @@
      *             not exist.
      */
     public Drawable getDrawableForDensity(@DrawableRes int id, int density, @Nullable Theme theme) {
-        final TypedValue value = obtainTempTypedValue(id);
+        final TypedValue value = obtainTempTypedValue();
         try {
-            getValueForDensity(id, density, value, true);
+            final ResourcesImpl impl = mResourcesImpl;
+            impl.getValueForDensity(id, density, value, true);
 
             // If the drawable's XML lives in our current density qualifier,
             // it's okay to use a scaled version from the cache. Otherwise, we
             // need to actually load the drawable from XML.
-            final boolean useCache = value.density == mMetrics.densityDpi;
+            final DisplayMetrics metrics = impl.getDisplayMetrics();
+            final boolean useCache = value.density == metrics.densityDpi;
 
             /*
              * Pretend the requested density is actually the display density. If
@@ -868,18 +838,23 @@
              */
             if (value.density > 0 && value.density != TypedValue.DENSITY_NONE) {
                 if (value.density == density) {
-                    value.density = mMetrics.densityDpi;
+                    value.density = metrics.densityDpi;
                 } else {
-                    value.density = (value.density * mMetrics.densityDpi) / density;
+                    value.density = (value.density * metrics.densityDpi) / density;
                 }
             }
-
-            return loadDrawable(value, id, theme, useCache);
+            return impl.loadDrawable(this, value, id, theme, useCache);
         } finally {
             releaseTempTypedValue(value);
         }
     }
 
+    @NonNull
+    Drawable loadDrawable(@NonNull TypedValue value, int id, @Nullable Theme theme)
+            throws NotFoundException {
+        return mResourcesImpl.loadDrawable(this, value, id, theme, true);
+    }
+
     /**
      * Return a movie object associated with the particular resource ID.
      * @param id The desired resource identifier, as generated by the aapt
@@ -889,13 +864,12 @@
      * 
      */
     public Movie getMovie(@RawRes int id) throws NotFoundException {
-        InputStream is = openRawResource(id);
-        Movie movie = Movie.decodeStream(is);
+        final InputStream is = openRawResource(id);
+        final Movie movie = Movie.decodeStream(is);
         try {
             is.close();
-        }
-        catch (java.io.IOException e) {
-            // don't care, since the return value is valid
+        } catch (IOException e) {
+            // No one cares.
         }
         return movie;
     }
@@ -939,8 +913,10 @@
      */
     @ColorInt
     public int getColor(@ColorRes int id, @Nullable Theme theme) throws NotFoundException {
-        final TypedValue value = obtainTempTypedValue(id);
+        final TypedValue value = obtainTempTypedValue();
         try {
+            final ResourcesImpl impl = mResourcesImpl;
+            impl.getValue(id, value, true);
             if (value.type >= TypedValue.TYPE_FIRST_INT
                     && value.type <= TypedValue.TYPE_LAST_INT) {
                 return value.data;
@@ -949,7 +925,7 @@
                         + " type #0x" + Integer.toHexString(value.type) + " is not valid");
             }
 
-            final ColorStateList csl = loadColorStateList(value, id, theme);
+            final ColorStateList csl = impl.loadColorStateList(this, value, id, theme);
             return csl.getDefaultColor();
         } finally {
             releaseTempTypedValue(value);
@@ -1007,14 +983,27 @@
     @Nullable
     public ColorStateList getColorStateList(@ColorRes int id, @Nullable Theme theme)
             throws NotFoundException {
-        final TypedValue value = obtainTempTypedValue(id);
+        final TypedValue value = obtainTempTypedValue();
         try {
-            return loadColorStateList(value, id, theme);
+            final ResourcesImpl impl = mResourcesImpl;
+            impl.getValue(id, value, true);
+            return impl.loadColorStateList(this, value, id, theme);
         } finally {
             releaseTempTypedValue(value);
         }
     }
 
+    @Nullable
+    ColorStateList loadColorStateList(@NonNull TypedValue value, int id, @Nullable Theme theme)
+            throws NotFoundException {
+        return mResourcesImpl.loadColorStateList(this, value, id, theme);
+    }
+
+    @Nullable
+    public ComplexColor loadComplexColor(@NonNull TypedValue value, int id, @Nullable Theme theme) {
+        return mResourcesImpl.loadComplexColor(this, value, id, theme);
+    }
+
     /**
      * Return a boolean associated with a particular resource ID.  This can be
      * used with any integral resource value, and will return true if it is
@@ -1029,8 +1018,9 @@
      * @return Returns the boolean value contained in the resource.
      */
     public boolean getBoolean(@BoolRes int id) throws NotFoundException {
-        final TypedValue value = obtainTempTypedValue(id);
+        final TypedValue value = obtainTempTypedValue();
         try {
+            mResourcesImpl.getValue(id, value, true);
             if (value.type >= TypedValue.TYPE_FIRST_INT
                     && value.type <= TypedValue.TYPE_LAST_INT) {
                 return value.data != 0;
@@ -1054,8 +1044,9 @@
      * @return Returns the integer value contained in the resource.
      */
     public int getInteger(@IntegerRes int id) throws NotFoundException {
-        final TypedValue value = obtainTempTypedValue(id);
+        final TypedValue value = obtainTempTypedValue();
         try {
+            mResourcesImpl.getValue(id, value, true);
             if (value.type >= TypedValue.TYPE_FIRST_INT
                     && value.type <= TypedValue.TYPE_LAST_INT) {
                 return value.data;
@@ -1081,8 +1072,9 @@
      * @hide Pending API council approval.
      */
     public float getFloat(int id) {
-        final TypedValue value = obtainTempTypedValue(id);
+        final TypedValue value = obtainTempTypedValue();
         try {
+            mResourcesImpl.getValue(id, value, true);
             if (value.type == TypedValue.TYPE_FLOAT) {
                 return value.getFloat();
             }
@@ -1190,20 +1182,6 @@
     }
 
     /**
-     * Returns a TypedValue populated with data for the specified resource ID
-     * that's suitable for temporary use. The obtained TypedValue should be
-     * released using {@link #releaseTempTypedValue(TypedValue)}.
-     *
-     * @param id the resource ID for which data should be obtained
-     * @return a populated typed value suitable for temporary use
-     */
-    private TypedValue obtainTempTypedValue(@AnyRes int id) {
-        final TypedValue value = obtainTempTypedValue();
-        getValue(id, value, true);
-        return value;
-    }
-
-    /**
      * Returns a TypedValue suitable for temporary use. The obtained TypedValue
      * should be released using {@link #releaseTempTypedValue(TypedValue)}.
      *
@@ -1252,17 +1230,7 @@
      */
     public InputStream openRawResource(@RawRes int id, TypedValue value)
             throws NotFoundException {
-        getValue(id, value, true);
-
-        try {
-            return mAssets.openNonAsset(value.assetCookie, value.string.toString(),
-                    AssetManager.ACCESS_STREAMING);
-        } catch (Exception e) {
-            NotFoundException rnf = new NotFoundException("File " + value.string.toString() +
-                    " from drawable resource ID #0x" + Integer.toHexString(id));
-            rnf.initCause(e);
-            throw rnf;
-        }
+        return mResourcesImpl.openRawResource(id, value);
     }
 
     /**
@@ -1288,12 +1256,9 @@
      */
     public AssetFileDescriptor openRawResourceFd(@RawRes int id)
             throws NotFoundException {
-        final TypedValue value = obtainTempTypedValue(id);
+        final TypedValue value = obtainTempTypedValue();
         try {
-            return mAssets.openNonAssetFd(value.assetCookie, value.string.toString());
-        } catch (Exception e) {
-            throw new NotFoundException("File " + value.string.toString() + " from drawable "
-                    + "resource ID #0x" + Integer.toHexString(id), e);
+            return mResourcesImpl.openRawResourceFd(id, value);
         } finally {
             releaseTempTypedValue(value);
         }
@@ -1316,12 +1281,7 @@
      */
     public void getValue(@AnyRes int id, TypedValue outValue, boolean resolveRefs)
             throws NotFoundException {
-        boolean found = mAssets.getResourceValue(id, 0, outValue, resolveRefs);
-        if (found) {
-            return;
-        }
-        throw new NotFoundException("Resource ID #0x"
-                                    + Integer.toHexString(id));
+        mResourcesImpl.getValue(id, outValue, resolveRefs);
     }
 
     /**
@@ -1339,11 +1299,7 @@
      */
     public void getValueForDensity(@AnyRes int id, int density, TypedValue outValue,
             boolean resolveRefs) throws NotFoundException {
-        boolean found = mAssets.getResourceValue(id, density, outValue, resolveRefs);
-        if (found) {
-            return;
-        }
-        throw new NotFoundException("Resource ID #0x" + Integer.toHexString(id));
+        mResourcesImpl.getValueForDensity(id, density, outValue, resolveRefs);
     }
 
     /**
@@ -1368,12 +1324,7 @@
      */
     public void getValue(String name, TypedValue outValue, boolean resolveRefs)
             throws NotFoundException {
-        int id = getIdentifier(name, "string", null);
-        if (id != 0) {
-            getValue(id, outValue, resolveRefs);
-            return;
-        }
-        throw new NotFoundException("String resource name " + name);
+        mResourcesImpl.getValue(name, outValue, resolveRefs);
     }
 
     /**
@@ -1392,6 +1343,15 @@
      * retrieve XML attributes with style and theme information applied.
      */
     public final class Theme {
+        private ResourcesImpl.ThemeImpl mThemeImpl;
+
+        private Theme() {
+        }
+
+        void setImpl(ResourcesImpl.ThemeImpl impl) {
+            mThemeImpl = impl;
+        }
+
         /**
          * Place new attribute values into the theme.  The style resource
          * specified by <var>resid</var> will be retrieved from this Theme's
@@ -1410,12 +1370,7 @@
          *              if not already defined in the theme.
          */
         public void applyStyle(int resId, boolean force) {
-            synchronized (mKey) {
-                AssetManager.applyThemeStyle(mTheme, resId, force);
-
-                mThemeResId = resId;
-                mKey.append(resId, force);
-            }
+            mThemeImpl.applyStyle(resId, force);
         }
 
         /**
@@ -1428,14 +1383,7 @@
          * @param other The existing Theme to copy from.
          */
         public void setTo(Theme other) {
-            synchronized (mKey) {
-                synchronized (other.mKey) {
-                    AssetManager.copyTheme(mTheme, other.mTheme);
-
-                    mThemeResId = other.mThemeResId;
-                    mKey.setTo(other.getKey());
-                }
-            }
+            mThemeImpl.setTo(other.mThemeImpl);
         }
 
         /**
@@ -1458,13 +1406,7 @@
          * @see #obtainStyledAttributes(AttributeSet, int[], int, int)
          */
         public TypedArray obtainStyledAttributes(@StyleableRes int[] attrs) {
-            synchronized (mKey) {
-                final int len = attrs.length;
-                final TypedArray array = TypedArray.obtain(Resources.this, len);
-                array.mTheme = this;
-                AssetManager.applyStyle(mTheme, 0, 0, 0, attrs, array.mData, array.mIndices);
-                return array;
-            }
+            return mThemeImpl.obtainStyledAttributes(this, null, attrs, 0, 0);
         }
 
         /**
@@ -1489,13 +1431,7 @@
          */
         public TypedArray obtainStyledAttributes(@StyleRes int resId, @StyleableRes int[] attrs)
                 throws NotFoundException {
-            synchronized (mKey) {
-                final int len = attrs.length;
-                final TypedArray array = TypedArray.obtain(Resources.this, len);
-                array.mTheme = this;
-                AssetManager.applyStyle(mTheme, 0, resId, 0, attrs, array.mData, array.mIndices);
-                return array;
-            }
+            return mThemeImpl.obtainStyledAttributes(this, null, attrs, 0, resId);
         }
 
         /**
@@ -1548,23 +1484,7 @@
          */
         public TypedArray obtainStyledAttributes(AttributeSet set,
                 @StyleableRes int[] attrs, @AttrRes int defStyleAttr, @StyleRes int defStyleRes) {
-            synchronized (mKey) {
-                final int len = attrs.length;
-                final TypedArray array = TypedArray.obtain(Resources.this, len);
-
-                // XXX note that for now we only work with compiled XML files.
-                // To support generic XML files we will need to manually parse
-                // out the attributes from the XML file (applying type information
-                // contained in the resources and such).
-                final XmlBlock.Parser parser = (XmlBlock.Parser) set;
-                AssetManager.applyStyle(mTheme, defStyleAttr, defStyleRes,
-                        parser != null ? parser.mParseState : 0,
-                        attrs, array.mData, array.mIndices);
-                array.mTheme = this;
-                array.mXml = parser;
-
-                return array;
-            }
+            return mThemeImpl.obtainStyledAttributes(this, set, attrs, defStyleAttr, defStyleRes);
         }
 
         /**
@@ -1583,20 +1503,7 @@
          */
         @NonNull
         public TypedArray resolveAttributes(@NonNull int[] values, @NonNull int[] attrs) {
-            synchronized (mKey) {
-                final int len = attrs.length;
-                if (values == null || len != values.length) {
-                    throw new IllegalArgumentException(
-                            "Base attribute values must the same length as attrs");
-                }
-
-                final TypedArray array = TypedArray.obtain(Resources.this, len);
-                AssetManager.resolveAttrs(mTheme, 0, 0, values, attrs, array.mData, array.mIndices);
-                array.mTheme = this;
-                array.mXml = null;
-
-                return array;
-            }
+            return mThemeImpl.resolveAttributes(this, values, attrs);
         }
 
         /**
@@ -1617,9 +1524,7 @@
          *         <var>outValue</var> is valid, else false.
          */
         public boolean resolveAttribute(int resid, TypedValue outValue, boolean resolveRefs) {
-            synchronized (mKey) {
-                return mAssets.getThemeValue(mTheme, resid, outValue, resolveRefs);
-            }
+            return mThemeImpl.resolveAttribute(resid, outValue, resolveRefs);
         }
 
         /**
@@ -1629,7 +1534,7 @@
          * @hide
          */
         public int[] getAllAttributes() {
-            return mAssets.getStyleAttributes(getAppliedStyleResId());
+            return mThemeImpl.getAllAttributes();
         }
 
         /**
@@ -1665,11 +1570,7 @@
          * @see ActivityInfo
          */
         public int getChangingConfigurations() {
-            synchronized (mKey) {
-                final int nativeChangingConfig =
-                        AssetManager.getThemeChangingConfigurations(mTheme);
-                return ActivityInfo.activityInfoConfigNativeToJava(nativeChangingConfig);
-            }
+            return mThemeImpl.getChangingConfigurations();
         }
 
         /**
@@ -1680,43 +1581,23 @@
          * @param prefix Text to prefix each line printed.
          */
         public void dump(int priority, String tag, String prefix) {
-            synchronized (mKey) {
-                AssetManager.dumpTheme(mTheme, priority, tag, prefix);
-            }
+            mThemeImpl.dump(priority, tag, prefix);
         }
 
-        @Override
-        protected void finalize() throws Throwable {
-            super.finalize();
-            mAssets.releaseTheme(mTheme);
-        }
-
-        /*package*/ Theme() {
-            mAssets = Resources.this.mAssets;
-            mTheme = mAssets.createTheme();
-        }
-
-        /** Unique key for the series of styles applied to this theme. */
-        private final ThemeKey mKey = new ThemeKey();
-
-        @SuppressWarnings("hiding")
-        private final AssetManager mAssets;
-        private final long mTheme;
-
-        /** Resource identifier for the theme. */
-        private int mThemeResId = 0;
-
         // Needed by layoutlib.
         /*package*/ long getNativeTheme() {
-            return mTheme;
+            return mThemeImpl.getNativeTheme();
         }
 
         /*package*/ int getAppliedStyleResId() {
-            return mThemeResId;
+            return mThemeImpl.getAppliedStyleResId();
         }
 
-        /*package*/ ThemeKey getKey() {
-            return mKey;
+        /**
+         * @hide
+         */
+        public ThemeKey getKey() {
+            return mThemeImpl.getKey();
         }
 
         private String getResourceNameFromHexString(String hexString) {
@@ -1724,7 +1605,7 @@
         }
 
         /**
-         * Parses {@link #mKey} and returns a String array that holds pairs of
+         * Parses {@link #getKey()} and returns a String array that holds pairs of
          * adjacent Theme data: resource name followed by whether or not it was
          * forced, as specified by {@link #applyStyle(int, boolean)}.
          *
@@ -1732,21 +1613,7 @@
          */
         @ViewDebug.ExportedProperty(category = "theme", hasAdjacentMapping = true)
         public String[] getTheme() {
-            synchronized (mKey) {
-                final int N = mKey.mCount;
-                final String[] themes = new String[N * 2];
-                for (int i = 0, j = N - 1; i < themes.length; i += 2, --j) {
-                    final int resId = mKey.mResId[j];
-                    final boolean forced = mKey.mForce[j];
-                    try {
-                        themes[i] = getResourceName(resId);
-                    } catch (NotFoundException e) {
-                        themes[i] = Integer.toHexString(i);
-                    }
-                    themes[i + 1] = forced ? "forced" : "not forced";
-                }
-                return themes;
-            }
+            return mThemeImpl.getTheme();
         }
 
         /** @hide */
@@ -1767,16 +1634,7 @@
          * @hide
          */
         public void rebase() {
-            synchronized (mKey) {
-                AssetManager.clearTheme(mTheme);
-
-                // Reapply the same styles in the same order.
-                for (int i = 0; i < mKey.mCount; i++) {
-                    final int resId = mKey.mResId[i];
-                    final boolean force = mKey.mForce[i];
-                    AssetManager.applyThemeStyle(mTheme, resId, force);
-                }
-            }
+            mThemeImpl.rebase();
         }
     }
 
@@ -1865,7 +1723,10 @@
      * @return Theme The newly created Theme container.
      */
     public final Theme newTheme() {
-        return new Theme();
+        Theme theme = new Theme();
+        theme.setImpl(mResourcesImpl.newThemeImpl());
+        mThemeRefs.add(new WeakReference<>(theme));
+        return theme;
     }
 
     /**
@@ -1889,7 +1750,7 @@
         // out the attributes from the XML file (applying type information
         // contained in the resources and such).
         XmlBlock.Parser parser = (XmlBlock.Parser)set;
-        mAssets.retrieveAttributes(parser.mParseState, attrs,
+        mResourcesImpl.getAssets().retrieveAttributes(parser.mParseState, attrs,
                 array.mData, array.mIndices);
 
         array.mXml = parser;
@@ -1900,151 +1761,16 @@
     /**
      * Store the newly updated configuration.
      */
-    public void updateConfiguration(Configuration config,
-            DisplayMetrics metrics) {
+    public void updateConfiguration(Configuration config, DisplayMetrics metrics) {
         updateConfiguration(config, metrics, null);
     }
 
     /**
      * @hide
      */
-    public void updateConfiguration(Configuration config,
-            DisplayMetrics metrics, CompatibilityInfo compat) {
-        synchronized (mAccessLock) {
-            if (false) {
-                Slog.i(TAG, "**** Updating config of " + this + ": old config is "
-                        + mConfiguration + " old compat is " + mCompatibilityInfo);
-                Slog.i(TAG, "**** Updating config of " + this + ": new config is "
-                        + config + " new compat is " + compat);
-            }
-            if (compat != null) {
-                mCompatibilityInfo = compat;
-            }
-            if (metrics != null) {
-                mMetrics.setTo(metrics);
-            }
-            // NOTE: We should re-arrange this code to create a Display
-            // with the CompatibilityInfo that is used everywhere we deal
-            // with the display in relation to this app, rather than
-            // doing the conversion here.  This impl should be okay because
-            // we make sure to return a compatible display in the places
-            // where there are public APIs to retrieve the display...  but
-            // it would be cleaner and more maintainble to just be
-            // consistently dealing with a compatible display everywhere in
-            // the framework.
-            mCompatibilityInfo.applyToDisplayMetrics(mMetrics);
-
-            final int configChanges = calcConfigChanges(config);
-
-            LocaleList locales = mConfiguration.getLocales();
-            if (locales.isEmpty()) {
-                locales = LocaleList.getAdjustedDefault();
-                mConfiguration.setLocales(locales);
-            }
-            if (mConfiguration.densityDpi != Configuration.DENSITY_DPI_UNDEFINED) {
-                mMetrics.densityDpi = mConfiguration.densityDpi;
-                mMetrics.density = mConfiguration.densityDpi * DisplayMetrics.DENSITY_DEFAULT_SCALE;
-            }
-            mMetrics.scaledDensity = mMetrics.density * mConfiguration.fontScale;
-
-            final int width, height;
-            if (mMetrics.widthPixels >= mMetrics.heightPixels) {
-                width = mMetrics.widthPixels;
-                height = mMetrics.heightPixels;
-            } else {
-                //noinspection SuspiciousNameCombination
-                width = mMetrics.heightPixels;
-                //noinspection SuspiciousNameCombination
-                height = mMetrics.widthPixels;
-            }
-
-            final int keyboardHidden;
-            if (mConfiguration.keyboardHidden == Configuration.KEYBOARDHIDDEN_NO
-                    && mConfiguration.hardKeyboardHidden == Configuration.HARDKEYBOARDHIDDEN_YES) {
-                keyboardHidden = Configuration.KEYBOARDHIDDEN_SOFT;
-            } else {
-                keyboardHidden = mConfiguration.keyboardHidden;
-            }
-
-            mAssets.setConfiguration(mConfiguration.mcc, mConfiguration.mnc,
-                    adjustLanguageTag(locales.get(0).toLanguageTag()),
-                    mConfiguration.orientation,
-                    mConfiguration.touchscreen,
-                    mConfiguration.densityDpi, mConfiguration.keyboard,
-                    keyboardHidden, mConfiguration.navigation, width, height,
-                    mConfiguration.smallestScreenWidthDp,
-                    mConfiguration.screenWidthDp, mConfiguration.screenHeightDp,
-                    mConfiguration.screenLayout, mConfiguration.uiMode,
-                    Build.VERSION.RESOURCES_SDK_INT);
-
-            if (DEBUG_CONFIG) {
-                Slog.i(TAG, "**** Updating config of " + this + ": final config is "
-                        + mConfiguration + " final compat is " + mCompatibilityInfo);
-            }
-
-            mDrawableCache.onConfigurationChange(configChanges);
-            mColorDrawableCache.onConfigurationChange(configChanges);
-            mComplexColorCache.onConfigurationChange(configChanges);
-            mAnimatorCache.onConfigurationChange(configChanges);
-            mStateListAnimatorCache.onConfigurationChange(configChanges);
-
-            flushLayoutCache();
-        }
-        synchronized (sSync) {
-            if (mPluralRule != null) {
-                mPluralRule = PluralRules.forLocale(mConfiguration.getLocales().get(0));
-            }
-        }
-    }
-
-    /**
-     * Called by ConfigurationBoundResourceCacheTest via reflection.
-     */
-    private int calcConfigChanges(Configuration config) {
-        int configChanges = 0xfffffff;
-        if (config != null) {
-            mTmpConfig.setTo(config);
-            int density = config.densityDpi;
-            if (density == Configuration.DENSITY_DPI_UNDEFINED) {
-                density = mMetrics.noncompatDensityDpi;
-            }
-
-            mCompatibilityInfo.applyToConfiguration(density, mTmpConfig);
-
-            if (mTmpConfig.getLocales().isEmpty()) {
-                mTmpConfig.setLocales(LocaleList.getDefault());
-            }
-            configChanges = mConfiguration.updateFrom(mTmpConfig);
-            configChanges = ActivityInfo.activityInfoConfigToNative(configChanges);
-        }
-        return configChanges;
-    }
-
-    /**
-     * {@code Locale.toLanguageTag} will transform the obsolete (and deprecated)
-     * language codes "in", "ji" and "iw" to "id", "yi" and "he" respectively.
-     *
-     * All released versions of android prior to "L" used the deprecated language
-     * tags, so we will need to support them for backwards compatibility.
-     *
-     * Note that this conversion needs to take place *after* the call to
-     * {@code toLanguageTag} because that will convert all the deprecated codes to
-     * the new ones, even if they're set manually.
-     */
-    private static String adjustLanguageTag(String languageTag) {
-        final int separator = languageTag.indexOf('-');
-        final String language;
-        final String remainder;
-
-        if (separator == -1) {
-            language = languageTag;
-            remainder = "";
-        } else {
-            language = languageTag.substring(0, separator);
-            remainder = languageTag.substring(separator);
-        }
-
-        return Locale.adjustLanguageCode(language) + remainder;
+    public void updateConfiguration(Configuration config, DisplayMetrics metrics,
+                                    CompatibilityInfo compat) {
+        mResourcesImpl.updateConfiguration(config, metrics, compat);
     }
 
     /**
@@ -2069,9 +1795,7 @@
      * @return The resource's current display metrics. 
      */
     public DisplayMetrics getDisplayMetrics() {
-        if (DEBUG_CONFIG) Slog.v(TAG, "Returning DisplayMetrics: " + mMetrics.widthPixels
-                + "x" + mMetrics.heightPixels + " " + mMetrics.density);
-        return mMetrics;
+        return mResourcesImpl.getDisplayMetrics();
     }
 
     /**
@@ -2081,13 +1805,13 @@
      * @return The resource's current configuration. 
      */
     public Configuration getConfiguration() {
-        return mConfiguration;
+        return mResourcesImpl.getConfiguration();
     }
 
     /** @hide */
     public Configuration[] getSizeConfigurations() {
-        return mAssets.getSizeConfigurations();
-    };
+        return mResourcesImpl.getSizeConfigurations();
+    }
 
     /**
      * Return the compatibility mode information for the application.
@@ -2097,17 +1821,17 @@
      * @hide
      */
     public CompatibilityInfo getCompatibilityInfo() {
-        return mCompatibilityInfo;
+        return mResourcesImpl.getCompatibilityInfo();
     }
 
     /**
      * This is just for testing.
      * @hide
      */
+    @VisibleForTesting
     public void setCompatibilityInfo(CompatibilityInfo ci) {
         if (ci != null) {
-            mCompatibilityInfo = ci;
-            updateConfiguration(mConfiguration, mMetrics);
+            mResourcesImpl.updateConfiguration(null, null, ci);
         }
     }
     
@@ -2132,15 +1856,7 @@
      *         resource was found.  (0 is not a valid resource ID.)
      */
     public int getIdentifier(String name, String defType, String defPackage) {
-        if (name == null) {
-            throw new NullPointerException("name is null");
-        }
-        try {
-            return Integer.parseInt(name);
-        } catch (Exception e) {
-            // Ignore
-        }
-        return mAssets.getResourceIdentifier(name, defType, defPackage);
+        return mResourcesImpl.getIdentifier(name, defType, defPackage);
     }
 
     /**
@@ -2167,10 +1883,7 @@
      * @see #getResourceEntryName
      */
     public String getResourceName(@AnyRes int resid) throws NotFoundException {
-        String str = mAssets.getResourceName(resid);
-        if (str != null) return str;
-        throw new NotFoundException("Unable to find resource ID #0x"
-                + Integer.toHexString(resid));
+        return mResourcesImpl.getResourceName(resid);
     }
     
     /**
@@ -2186,10 +1899,7 @@
      * @see #getResourceName
      */
     public String getResourcePackageName(@AnyRes int resid) throws NotFoundException {
-        String str = mAssets.getResourcePackageName(resid);
-        if (str != null) return str;
-        throw new NotFoundException("Unable to find resource ID #0x"
-                + Integer.toHexString(resid));
+        return mResourcesImpl.getResourcePackageName(resid);
     }
     
     /**
@@ -2205,10 +1915,7 @@
      * @see #getResourceName
      */
     public String getResourceTypeName(@AnyRes int resid) throws NotFoundException {
-        String str = mAssets.getResourceTypeName(resid);
-        if (str != null) return str;
-        throw new NotFoundException("Unable to find resource ID #0x"
-                + Integer.toHexString(resid));
+        return mResourcesImpl.getResourceTypeName(resid);
     }
     
     /**
@@ -2224,10 +1931,7 @@
      * @see #getResourceName
      */
     public String getResourceEntryName(@AnyRes int resid) throws NotFoundException {
-        String str = mAssets.getResourceEntryName(resid);
-        if (str != null) return str;
-        throw new NotFoundException("Unable to find resource ID #0x"
-                + Integer.toHexString(resid));
+        return mResourcesImpl.getResourceEntryName(resid);
     }
     
     /**
@@ -2330,7 +2034,7 @@
      * Retrieve underlying AssetManager storage for these resources.
      */
     public final AssetManager getAssets() {
-        return mAssets;
+        return mResourcesImpl.getAssets();
     }
 
     /**
@@ -2339,19 +2043,7 @@
      * tools.
      */
     public final void flushLayoutCache() {
-        final String[] cachedXmlBlockFiles = mCachedXmlBlockFiles;
-        final XmlBlock[] cachedXmlBlocks = mCachedXmlBlocks;
-        synchronized (cachedXmlBlockFiles) {
-            final int num = cachedXmlBlockFiles.length;
-            for (int i = 0; i < num; i++) {
-                final XmlBlock oldBlock = cachedXmlBlocks[i];
-                if (oldBlock != null) {
-                    oldBlock.close();
-                }
-                cachedXmlBlockFiles[i] = null;
-                cachedXmlBlocks[i] = null;
-            }
-        }
+        mResourcesImpl.flushLayoutCache();
     }
 
     /**
@@ -2360,15 +2052,7 @@
      * {@hide}
      */
     public final void startPreloading() {
-        synchronized (sSync) {
-            if (sPreloaded) {
-                throw new IllegalStateException("Resources already preloaded");
-            }
-            sPreloaded = true;
-            mPreloading = true;
-            mConfiguration.densityDpi = DisplayMetrics.DENSITY_DEVICE;
-            updateConfiguration(null, null);
-        }
+        mResourcesImpl.startPreloading();
     }
     
     /**
@@ -2376,441 +2060,14 @@
      * to normal Resources operation.
      */
     public final void finishPreloading() {
-        if (mPreloading) {
-            mPreloading = false;
-            flushLayoutCache();
-        }
+        mResourcesImpl.finishPreloading();
     }
 
     /**
      * @hide
      */
     public LongSparseArray<ConstantState> getPreloadedDrawables() {
-        return sPreloadedDrawables[0];
-    }
-
-    private boolean verifyPreloadConfig(int changingConfigurations, int allowVarying,
-            int resourceId, String name) {
-        // We allow preloading of resources even if they vary by font scale (which
-        // doesn't impact resource selection) or density (which we handle specially by
-        // simply turning off all preloading), as well as any other configs specified
-        // by the caller.
-        if (((changingConfigurations&~(ActivityInfo.CONFIG_FONT_SCALE |
-                ActivityInfo.CONFIG_DENSITY)) & ~allowVarying) != 0) {
-            String resName;
-            try {
-                resName = getResourceName(resourceId);
-            } catch (NotFoundException e) {
-                resName = "?";
-            }
-            // This should never happen in production, so we should log a
-            // warning even if we're not debugging.
-            Log.w(TAG, "Preloaded " + name + " resource #0x"
-                    + Integer.toHexString(resourceId)
-                    + " (" + resName + ") that varies with configuration!!");
-            return false;
-        }
-        if (TRACE_FOR_PRELOAD) {
-            String resName;
-            try {
-                resName = getResourceName(resourceId);
-            } catch (NotFoundException e) {
-                resName = "?";
-            }
-            Log.w(TAG, "Preloading " + name + " resource #0x"
-                    + Integer.toHexString(resourceId)
-                    + " (" + resName + ")");
-        }
-        return true;
-    }
-
-    @Nullable
-    Drawable loadDrawable(TypedValue value, int id, Theme theme) throws NotFoundException {
-        return loadDrawable(value, id, theme, true);
-    }
-
-    @Nullable
-    Drawable loadDrawable(TypedValue value, int id, Theme theme, boolean useCache)
-            throws NotFoundException {
-        try {
-            if (TRACE_FOR_PRELOAD) {
-                // Log only framework resources
-                if ((id >>> 24) == 0x1) {
-                    final String name = getResourceName(id);
-                    if (name != null) {
-                        Log.d("PreloadDrawable", name);
-                    }
-                }
-            }
-
-            final boolean isColorDrawable;
-            final DrawableCache caches;
-            final long key;
-            if (value.type >= TypedValue.TYPE_FIRST_COLOR_INT
-                    && value.type <= TypedValue.TYPE_LAST_COLOR_INT) {
-                isColorDrawable = true;
-                caches = mColorDrawableCache;
-                key = value.data;
-            } else {
-                isColorDrawable = false;
-                caches = mDrawableCache;
-                key = (((long) value.assetCookie) << 32) | value.data;
-            }
-
-            // First, check whether we have a cached version of this drawable
-            // that was inflated against the specified theme. Skip the cache if
-            // we're currently preloading or we're not using the cache.
-            if (!mPreloading && useCache) {
-                final Drawable cachedDrawable = caches.getInstance(key, theme);
-                if (cachedDrawable != null) {
-                    return cachedDrawable;
-                }
-            }
-
-            // Next, check preloaded drawables. Preloaded drawables may contain
-            // unresolved theme attributes.
-            final ConstantState cs;
-            if (isColorDrawable) {
-                cs = sPreloadedColorDrawables.get(key);
-            } else {
-                cs = sPreloadedDrawables[mConfiguration.getLayoutDirection()].get(key);
-            }
-
-            Drawable dr;
-            if (cs != null) {
-                dr = cs.newDrawable(this);
-            } else if (isColorDrawable) {
-                dr = new ColorDrawable(value.data);
-            } else {
-                dr = loadDrawableForCookie(value, id, null);
-            }
-
-            // Determine if the drawable has unresolved theme attributes. If it
-            // does, we'll need to apply a theme and store it in a theme-specific
-            // cache.
-            final boolean canApplyTheme = dr != null && dr.canApplyTheme();
-            if (canApplyTheme && theme != null) {
-                dr = dr.mutate();
-                dr.applyTheme(theme);
-                dr.clearMutated();
-            }
-
-            // If we were able to obtain a drawable, store it in the appropriate
-            // cache: preload, not themed, null theme, or theme-specific. Don't
-            // pollute the cache with drawables loaded from a foreign density.
-            if (dr != null && useCache) {
-                dr.setChangingConfigurations(value.changingConfigurations);
-                cacheDrawable(value, isColorDrawable, caches, theme, canApplyTheme, key, dr);
-            }
-
-            return dr;
-        } catch (Exception e) {
-            String name;
-            try {
-                name = getResourceName(id);
-            } catch (NotFoundException e2) {
-                name = "(missing name)";
-            }
-
-            // The target drawable might fail to load for any number of
-            // reasons, but we always want to include the resource name.
-            // Since the client already expects this method to throw a
-            // NotFoundException, just throw one of those.
-            final NotFoundException nfe = new NotFoundException("Drawable " + name
-                    + " with resource ID #0x" + Integer.toHexString(id), e);
-            nfe.setStackTrace(new StackTraceElement[0]);
-            throw nfe;
-        }
-    }
-
-    private void cacheDrawable(TypedValue value, boolean isColorDrawable, DrawableCache caches,
-            Theme theme, boolean usesTheme, long key, Drawable dr) {
-        final ConstantState cs = dr.getConstantState();
-        if (cs == null) {
-            return;
-        }
-
-        if (mPreloading) {
-            final int changingConfigs = cs.getChangingConfigurations();
-            if (isColorDrawable) {
-                if (verifyPreloadConfig(changingConfigs, 0, value.resourceId, "drawable")) {
-                    sPreloadedColorDrawables.put(key, cs);
-                }
-            } else {
-                if (verifyPreloadConfig(
-                        changingConfigs, LAYOUT_DIR_CONFIG, value.resourceId, "drawable")) {
-                    if ((changingConfigs & LAYOUT_DIR_CONFIG) == 0) {
-                        // If this resource does not vary based on layout direction,
-                        // we can put it in all of the preload maps.
-                        sPreloadedDrawables[0].put(key, cs);
-                        sPreloadedDrawables[1].put(key, cs);
-                    } else {
-                        // Otherwise, only in the layout dir we loaded it for.
-                        sPreloadedDrawables[mConfiguration.getLayoutDirection()].put(key, cs);
-                    }
-                }
-            }
-        } else {
-            synchronized (mAccessLock) {
-                caches.put(key, theme, cs, usesTheme);
-            }
-        }
-    }
-
-    /**
-     * Loads a drawable from XML or resources stream.
-     */
-    private Drawable loadDrawableForCookie(TypedValue value, int id, Theme theme) {
-        if (value.string == null) {
-            throw new NotFoundException("Resource \"" + getResourceName(id) + "\" ("
-                    + Integer.toHexString(id) + ") is not a Drawable (color or path): " + value);
-        }
-
-        final String file = value.string.toString();
-
-        if (TRACE_FOR_MISS_PRELOAD) {
-            // Log only framework resources
-            if ((id >>> 24) == 0x1) {
-                final String name = getResourceName(id);
-                if (name != null) {
-                    Log.d(TAG, "Loading framework drawable #" + Integer.toHexString(id)
-                            + ": " + name + " at " + file);
-                }
-            }
-        }
-
-        if (DEBUG_LOAD) {
-            Log.v(TAG, "Loading drawable for cookie " + value.assetCookie + ": " + file);
-        }
-
-        final Drawable dr;
-
-        Trace.traceBegin(Trace.TRACE_TAG_RESOURCES, file);
-        try {
-            if (file.endsWith(".xml")) {
-                final XmlResourceParser rp = loadXmlResourceParser(
-                        file, id, value.assetCookie, "drawable");
-                dr = Drawable.createFromXml(this, rp, theme);
-                rp.close();
-            } else {
-                final InputStream is = mAssets.openNonAsset(
-                        value.assetCookie, file, AssetManager.ACCESS_STREAMING);
-                dr = Drawable.createFromResourceStream(this, value, is, file, null);
-                is.close();
-            }
-        } catch (Exception e) {
-            Trace.traceEnd(Trace.TRACE_TAG_RESOURCES);
-            final NotFoundException rnf = new NotFoundException(
-                    "File " + file + " from drawable resource ID #0x" + Integer.toHexString(id));
-            rnf.initCause(e);
-            throw rnf;
-        }
-        Trace.traceEnd(Trace.TRACE_TAG_RESOURCES);
-
-        return dr;
-    }
-
-    /**
-     * Given the value and id, we can get the XML filename as in value.data, based on that, we
-     * first try to load CSL from the cache. If not found, try to get from the constant state.
-     * Last, parse the XML and generate the CSL.
-     */
-    private ComplexColor loadComplexColorFromName(Theme theme, TypedValue value, int id) {
-        final long key = (((long) value.assetCookie) << 32) | value.data;
-        final ConfigurationBoundResourceCache<ComplexColor> cache = mComplexColorCache;
-        ComplexColor complexColor = cache.getInstance(key, theme);
-        if (complexColor != null) {
-            return complexColor;
-        }
-
-        final android.content.res.ConstantState<ComplexColor> factory =
-                sPreloadedComplexColors.get(key);
-
-        if (factory != null) {
-            complexColor = factory.newInstance(this, theme);
-        }
-        if (complexColor == null) {
-            complexColor = loadComplexColorForCookie(value, id, theme);
-        }
-
-        if (complexColor != null) {
-            if (mPreloading) {
-                if (verifyPreloadConfig(value.changingConfigurations, 0, value.resourceId,
-                        "color")) {
-                    sPreloadedComplexColors.put(key, complexColor.getConstantState());
-                }
-            } else {
-                cache.put(key, theme, complexColor.getConstantState());
-            }
-        }
-        return complexColor;
-    }
-
-    @Nullable
-    public ComplexColor loadComplexColor(@NonNull TypedValue value, int id, Theme theme) {
-        if (TRACE_FOR_PRELOAD) {
-            // Log only framework resources
-            if ((id >>> 24) == 0x1) {
-                final String name = getResourceName(id);
-                if (name != null) android.util.Log.d("loadComplexColor", name);
-            }
-        }
-
-        final long key = (((long) value.assetCookie) << 32) | value.data;
-
-        // Handle inline color definitions.
-        if (value.type >= TypedValue.TYPE_FIRST_COLOR_INT
-                && value.type <= TypedValue.TYPE_LAST_COLOR_INT) {
-            return getColorStateListFromInt(value, key);
-        }
-
-        final String file = value.string.toString();
-
-        ComplexColor complexColor;
-        if (file.endsWith(".xml")) {
-            try {
-                complexColor = loadComplexColorFromName(theme, value, id);
-            } catch (Exception e) {
-                final NotFoundException rnf = new NotFoundException(
-                        "File " + file + " from complex color resource ID #0x"
-                                + Integer.toHexString(id));
-                rnf.initCause(e);
-                throw rnf;
-            }
-        } else {
-            throw new NotFoundException(
-                    "File " + file + " from drawable resource ID #0x"
-                            + Integer.toHexString(id) + ": .xml extension required");
-        }
-
-        return complexColor;
-    }
-
-    @Nullable
-    ColorStateList loadColorStateList(TypedValue value, int id, Theme theme)
-            throws NotFoundException {
-        if (TRACE_FOR_PRELOAD) {
-            // Log only framework resources
-            if ((id >>> 24) == 0x1) {
-                final String name = getResourceName(id);
-                if (name != null) android.util.Log.d("PreloadColorStateList", name);
-            }
-        }
-
-        final long key = (((long) value.assetCookie) << 32) | value.data;
-
-        // Handle inline color definitions.
-        if (value.type >= TypedValue.TYPE_FIRST_COLOR_INT
-                && value.type <= TypedValue.TYPE_LAST_COLOR_INT) {
-            return getColorStateListFromInt(value, key);
-        }
-
-        ComplexColor complexColor = loadComplexColorFromName(theme, value, id);
-        if (complexColor != null && complexColor instanceof ColorStateList) {
-            return (ColorStateList) complexColor;
-        }
-
-        throw new NotFoundException(
-                "Can't find ColorStateList from drawable resource ID #0x"
-                        + Integer.toHexString(id));
-    }
-
-    @NonNull
-    private ColorStateList getColorStateListFromInt(@NonNull  TypedValue value, long key) {
-        ColorStateList csl;
-        final android.content.res.ConstantState<ComplexColor> factory =
-                sPreloadedComplexColors.get(key);
-        if (factory != null) {
-            return (ColorStateList) factory.newInstance();
-        }
-
-        csl = ColorStateList.valueOf(value.data);
-
-        if (mPreloading) {
-            if (verifyPreloadConfig(value.changingConfigurations, 0, value.resourceId,
-                    "color")) {
-                sPreloadedComplexColors.put(key, csl.getConstantState());
-            }
-        }
-
-        return csl;
-    }
-
-    /**
-     * Load a ComplexColor based on the XML file content. The result can be a GradientColor or
-     * ColorStateList. Note that pure color will be wrapped into a ColorStateList.
-     *
-     * We deferred the parser creation to this function b/c we need to differentiate b/t gradient
-     * and selector tag.
-     *
-     * @return a ComplexColor (GradientColor or ColorStateList) based on the XML file content.
-     */
-    @Nullable
-    private ComplexColor loadComplexColorForCookie(TypedValue value, int id, Theme theme) {
-        if (value.string == null) {
-            throw new UnsupportedOperationException(
-                    "Can't convert to ComplexColor: type=0x" + value.type);
-        }
-
-        final String file = value.string.toString();
-
-        if (TRACE_FOR_MISS_PRELOAD) {
-            // Log only framework resources
-            if ((id >>> 24) == 0x1) {
-                final String name = getResourceName(id);
-                if (name != null) {
-                    Log.d(TAG, "Loading framework ComplexColor #" + Integer.toHexString(id)
-                            + ": " + name + " at " + file);
-                }
-            }
-        }
-
-        if (DEBUG_LOAD) {
-            Log.v(TAG, "Loading ComplexColor for cookie " + value.assetCookie + ": " + file);
-        }
-
-        ComplexColor complexColor = null;
-
-        Trace.traceBegin(Trace.TRACE_TAG_RESOURCES, file);
-        if (file.endsWith(".xml")) {
-            try {
-                final XmlResourceParser parser = loadXmlResourceParser(
-                        file, id, value.assetCookie, "ComplexColor");
-
-                final AttributeSet attrs = Xml.asAttributeSet(parser);
-                int type;
-                while ((type = parser.next()) != XmlPullParser.START_TAG
-                        && type != XmlPullParser.END_DOCUMENT) {
-                    // Seek parser to start tag.
-                }
-                if (type != XmlPullParser.START_TAG) {
-                    throw new XmlPullParserException("No start tag found");
-                }
-
-                final String name = parser.getName();
-                if (name.equals("gradient")) {
-                    complexColor = GradientColor.createFromXmlInner(this, parser, attrs, theme);
-                } else if (name.equals("selector")) {
-                    complexColor = ColorStateList.createFromXmlInner(this, parser, attrs, theme);
-                }
-                parser.close();
-            } catch (Exception e) {
-                Trace.traceEnd(Trace.TRACE_TAG_RESOURCES);
-                final NotFoundException rnf = new NotFoundException(
-                        "File " + file + " from ComplexColor resource ID #0x"
-                                + Integer.toHexString(id));
-                rnf.initCause(e);
-                throw rnf;
-            }
-        } else {
-            Trace.traceEnd(Trace.TRACE_TAG_RESOURCES);
-            throw new NotFoundException(
-                    "File " + file + " from drawable resource ID #0x"
-                            + Integer.toHexString(id) + ": .xml extension required");
-        }
-        Trace.traceEnd(Trace.TRACE_TAG_RESOURCES);
-
-        return complexColor;
+        return mResourcesImpl.getPreloadedDrawables();
     }
 
     /**
@@ -2824,10 +2081,12 @@
     @NonNull
     XmlResourceParser loadXmlResourceParser(@AnyRes int id, @NonNull String type)
             throws NotFoundException {
-        final TypedValue value = obtainTempTypedValue(id);
+        final TypedValue value = obtainTempTypedValue();
         try {
+            final ResourcesImpl impl = mResourcesImpl;
+            impl.getValue(id, value, true);
             if (value.type == TypedValue.TYPE_STRING) {
-                return loadXmlResourceParser(value.string.toString(), id,
+                return impl.loadXmlResourceParser(value.string.toString(), id,
                         value.assetCookie, type);
             }
             throw new NotFoundException("Resource ID #0x" + Integer.toHexString(id)
@@ -2848,47 +2107,18 @@
      * @throws NotFoundException if the file could not be loaded
      */
     @NonNull
-    XmlResourceParser loadXmlResourceParser(@NonNull String file, @AnyRes int id,
-            int assetCookie, @NonNull String type) throws NotFoundException {
-        if (id != 0) {
-            try {
-                final String[] cachedXmlBlockFiles = mCachedXmlBlockFiles;
-                final XmlBlock[] cachedXmlBlocks = mCachedXmlBlocks;
-                synchronized (cachedXmlBlockFiles) {
-                    // First see if this block is in our cache.
-                    final int num = cachedXmlBlockFiles.length;
-                    for (int i = 0; i < num; i++) {
-                        if (cachedXmlBlockFiles[i] != null
-                                && cachedXmlBlockFiles[i].equals(file)) {
-                            return cachedXmlBlocks[i].newParser();
-                        }
-                    }
+    XmlResourceParser loadXmlResourceParser(String file, int id, int assetCookie,
+                                            String type) throws NotFoundException {
+        return mResourcesImpl.loadXmlResourceParser(file, id, assetCookie, type);
+    }
 
-                    // Not in the cache, create a new block and put it at
-                    // the next slot in the cache.
-                    final XmlBlock block = mAssets.openXmlBlockAsset(assetCookie, file);
-                    if (block != null) {
-                        final int pos = (mLastCachedXmlBlockIndex + 1) % num;
-                        mLastCachedXmlBlockIndex = pos;
-                        final XmlBlock oldBlock = cachedXmlBlocks[pos];
-                        if (oldBlock != null) {
-                            oldBlock.close();
-                        }
-                        cachedXmlBlockFiles[pos] = file;
-                        cachedXmlBlocks[pos] = block;
-                        return block.newParser();
-                    }
-                }
-            } catch (Exception e) {
-                final NotFoundException rnf = new NotFoundException("File " + file
-                        + " from xml type " + type + " resource ID #0x" + Integer.toHexString(id));
-                rnf.initCause(e);
-                throw rnf;
-            }
-        }
-
-        throw new NotFoundException("File " + file + " from xml type " + type + " resource ID #0x"
-                + Integer.toHexString(id));
+    /**
+     * Called by ConfigurationBoundResourceCacheTest.
+     * @hide
+     */
+    @VisibleForTesting
+    public int calcConfigChanges(Configuration config) {
+        return mResourcesImpl.calcConfigChanges(config);
     }
 
     /**
@@ -2904,16 +2134,4 @@
         }
         return theme.obtainStyledAttributes(set, attrs, 0, 0);
     }
-
-    private Resources() {
-        mAssets = AssetManager.getSystem();
-        mClassLoader = ClassLoader.getSystemClassLoader();
-        // NOTE: Intentionally leaving this uninitialized (all values set
-        // to zero), so that anyone who tries to do something that requires
-        // metrics will get a very wrong value.
-        mConfiguration.setToDefaults();
-        mMetrics.setToDefaults();
-        updateConfiguration(null, null);
-        mAssets.ensureStringBlocks();
-    }
 }
diff --git a/core/java/android/content/res/ResourcesImpl.java b/core/java/android/content/res/ResourcesImpl.java
new file mode 100644
index 0000000..0858cb8
--- /dev/null
+++ b/core/java/android/content/res/ResourcesImpl.java
@@ -0,0 +1,1157 @@
+/*
+ * 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.res;
+
+import android.animation.Animator;
+import android.animation.StateListAnimator;
+import android.annotation.AnyRes;
+import android.annotation.AttrRes;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.PluralsRes;
+import android.annotation.RawRes;
+import android.annotation.StyleRes;
+import android.annotation.StyleableRes;
+import android.content.pm.ActivityInfo;
+import android.content.res.Resources.NotFoundException;
+import android.graphics.drawable.ColorDrawable;
+import android.graphics.drawable.Drawable;
+import android.icu.text.PluralRules;
+import android.os.Build;
+import android.os.Trace;
+import android.util.AttributeSet;
+import android.util.DisplayMetrics;
+import android.util.LocaleList;
+import android.util.Log;
+import android.util.LongSparseArray;
+import android.util.Slog;
+import android.util.TypedValue;
+import android.util.Xml;
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.InputStream;
+import java.util.Arrays;
+import java.util.Locale;
+
+/**
+ * The implementation of Resource access. This class contains the AssetManager and all caches
+ * associated with it.
+ *
+ * {@link Resources} is just a thing wrapper around this class. When a configuration change
+ * occurs, clients can retain the same {@link Resources} reference because the underlying
+ * {@link ResourcesImpl} object will be updated or re-created.
+ *
+ * @hide
+ */
+public class ResourcesImpl {
+    static final String TAG = "Resources";
+
+    private static final boolean DEBUG_LOAD = false;
+    private static final boolean DEBUG_CONFIG = false;
+    private static final boolean TRACE_FOR_PRELOAD = false;
+    private static final boolean TRACE_FOR_MISS_PRELOAD = false;
+
+    private static final int LAYOUT_DIR_CONFIG = ActivityInfo.activityInfoConfigToNative(
+            ActivityInfo.CONFIG_LAYOUT_DIRECTION);
+
+    private static final int ID_OTHER = 0x01000004;
+
+    private static final Object sSync = new Object();
+
+    private static boolean sPreloaded;
+    private boolean mPreloading;
+
+    // Information about preloaded resources.  Note that they are not
+    // protected by a lock, because while preloading in zygote we are all
+    // single-threaded, and after that these are immutable.
+    private static final LongSparseArray<Drawable.ConstantState>[] sPreloadedDrawables;
+    private static final LongSparseArray<Drawable.ConstantState> sPreloadedColorDrawables
+            = new LongSparseArray<>();
+    private static final LongSparseArray<android.content.res.ConstantState<ComplexColor>>
+            sPreloadedComplexColors = new LongSparseArray<>();
+
+    /** Lock object used to protect access to caches and configuration. */
+    private final Object mAccessLock = new Object();
+
+    // These are protected by mAccessLock.
+    private final Configuration mTmpConfig = new Configuration();
+    private final DrawableCache mDrawableCache = new DrawableCache();
+    private final DrawableCache mColorDrawableCache = new DrawableCache();
+    private final ConfigurationBoundResourceCache<ComplexColor> mComplexColorCache =
+            new ConfigurationBoundResourceCache<>();
+    private final ConfigurationBoundResourceCache<Animator> mAnimatorCache =
+            new ConfigurationBoundResourceCache<>();
+    private final ConfigurationBoundResourceCache<StateListAnimator> mStateListAnimatorCache =
+            new ConfigurationBoundResourceCache<>();
+
+    /** Size of the cyclical cache used to map XML files to blocks. */
+    private static final int XML_BLOCK_CACHE_SIZE = 4;
+
+    // Cyclical cache used for recently-accessed XML files.
+    private int mLastCachedXmlBlockIndex = -1;
+    private final int[] mCachedXmlBlockCookies = new int[XML_BLOCK_CACHE_SIZE];
+    private final String[] mCachedXmlBlockFiles = new String[XML_BLOCK_CACHE_SIZE];
+    private final XmlBlock[] mCachedXmlBlocks = new XmlBlock[XML_BLOCK_CACHE_SIZE];
+
+
+    final AssetManager mAssets;
+    final DisplayMetrics mMetrics = new DisplayMetrics();
+
+    private PluralRules mPluralRule;
+
+    private final Configuration mConfiguration = new Configuration();
+    private CompatibilityInfo mCompatibilityInfo = CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO;
+
+    static {
+        sPreloadedDrawables = new LongSparseArray[2];
+        sPreloadedDrawables[0] = new LongSparseArray<>();
+        sPreloadedDrawables[1] = new LongSparseArray<>();
+    }
+
+    /**
+     * Creates a new ResourcesImpl object with CompatibilityInfo.
+     *
+     * @param assets Previously created AssetManager.
+     * @param metrics Current display metrics to consider when
+     *                selecting/computing resource values.
+     * @param config Desired device configuration to consider when
+     *               selecting/computing resource values (optional).
+     * @param compatInfo this resource's compatibility info. Must not be null.
+     */
+    public ResourcesImpl(AssetManager assets, DisplayMetrics metrics, Configuration config,
+            CompatibilityInfo compatInfo) {
+        mAssets = assets;
+        mMetrics.setToDefaults();
+        updateConfiguration(config, metrics, compatInfo);
+        mAssets.ensureStringBlocks();
+    }
+
+    public AssetManager getAssets() {
+        return mAssets;
+    }
+
+    DisplayMetrics getDisplayMetrics() {
+        if (DEBUG_CONFIG) Slog.v(TAG, "Returning DisplayMetrics: " + mMetrics.widthPixels
+                + "x" + mMetrics.heightPixels + " " + mMetrics.density);
+        return mMetrics;
+    }
+
+    Configuration getConfiguration() {
+        return mConfiguration;
+    }
+
+    Configuration[] getSizeConfigurations() {
+        return mAssets.getSizeConfigurations();
+    }
+
+    CompatibilityInfo getCompatibilityInfo() {
+        return mCompatibilityInfo;
+    }
+
+    private PluralRules getPluralRule() {
+        synchronized (sSync) {
+            if (mPluralRule == null) {
+                mPluralRule = PluralRules.forLocale(mConfiguration.getLocales().get(0));
+            }
+            return mPluralRule;
+        }
+    }
+
+    void getValue(@AnyRes int id, TypedValue outValue, boolean resolveRefs)
+            throws NotFoundException {
+        boolean found = mAssets.getResourceValue(id, 0, outValue, resolveRefs);
+        if (found) {
+            return;
+        }
+        throw new NotFoundException("Resource ID #0x" + Integer.toHexString(id));
+    }
+
+    void getValueForDensity(@AnyRes int id, int density, TypedValue outValue,
+            boolean resolveRefs) throws NotFoundException {
+        boolean found = mAssets.getResourceValue(id, density, outValue, resolveRefs);
+        if (found) {
+            return;
+        }
+        throw new NotFoundException("Resource ID #0x" + Integer.toHexString(id));
+    }
+
+    void getValue(String name, TypedValue outValue, boolean resolveRefs)
+            throws NotFoundException {
+        int id = getIdentifier(name, "string", null);
+        if (id != 0) {
+            getValue(id, outValue, resolveRefs);
+            return;
+        }
+        throw new NotFoundException("String resource name " + name);
+    }
+
+    int getIdentifier(String name, String defType, String defPackage) {
+        if (name == null) {
+            throw new NullPointerException("name is null");
+        }
+        try {
+            return Integer.parseInt(name);
+        } catch (Exception e) {
+            // Ignore
+        }
+        return mAssets.getResourceIdentifier(name, defType, defPackage);
+    }
+
+    @NonNull
+    String getResourceName(@AnyRes int resid) throws NotFoundException {
+        String str = mAssets.getResourceName(resid);
+        if (str != null) return str;
+        throw new NotFoundException("Unable to find resource ID #0x"
+                + Integer.toHexString(resid));
+    }
+
+    @NonNull
+    String getResourcePackageName(@AnyRes int resid) throws NotFoundException {
+        String str = mAssets.getResourcePackageName(resid);
+        if (str != null) return str;
+        throw new NotFoundException("Unable to find resource ID #0x"
+                + Integer.toHexString(resid));
+    }
+
+    @NonNull
+    String getResourceTypeName(@AnyRes int resid) throws NotFoundException {
+        String str = mAssets.getResourceTypeName(resid);
+        if (str != null) return str;
+        throw new NotFoundException("Unable to find resource ID #0x"
+                + Integer.toHexString(resid));
+    }
+
+    @NonNull
+    String getResourceEntryName(@AnyRes int resid) throws NotFoundException {
+        String str = mAssets.getResourceEntryName(resid);
+        if (str != null) return str;
+        throw new NotFoundException("Unable to find resource ID #0x"
+                + Integer.toHexString(resid));
+    }
+
+    @NonNull
+    CharSequence getQuantityText(@PluralsRes int id, int quantity) throws NotFoundException {
+        PluralRules rule = getPluralRule();
+        CharSequence res = mAssets.getResourceBagText(id,
+                attrForQuantityCode(rule.select(quantity)));
+        if (res != null) {
+            return res;
+        }
+        res = mAssets.getResourceBagText(id, ID_OTHER);
+        if (res != null) {
+            return res;
+        }
+        throw new NotFoundException("Plural resource ID #0x" + Integer.toHexString(id)
+                + " quantity=" + quantity
+                + " item=" + rule.select(quantity));
+    }
+
+    private static int attrForQuantityCode(String quantityCode) {
+        switch (quantityCode) {
+            case PluralRules.KEYWORD_ZERO: return 0x01000005;
+            case PluralRules.KEYWORD_ONE:  return 0x01000006;
+            case PluralRules.KEYWORD_TWO:  return 0x01000007;
+            case PluralRules.KEYWORD_FEW:  return 0x01000008;
+            case PluralRules.KEYWORD_MANY: return 0x01000009;
+            default:                       return ID_OTHER;
+        }
+    }
+
+    @NonNull
+    AssetFileDescriptor openRawResourceFd(@RawRes int id, TypedValue tempValue)
+            throws NotFoundException {
+        getValue(id, tempValue, true);
+        try {
+            return mAssets.openNonAssetFd(tempValue.assetCookie, tempValue.string.toString());
+        } catch (Exception e) {
+            throw new NotFoundException("File " + tempValue.string.toString() + " from drawable "
+                    + "resource ID #0x" + Integer.toHexString(id), e);
+        }
+    }
+
+    @NonNull
+    InputStream openRawResource(@RawRes int id, TypedValue value) throws NotFoundException {
+        getValue(id, value, true);
+        try {
+            return mAssets.openNonAsset(value.assetCookie, value.string.toString(),
+                    AssetManager.ACCESS_STREAMING);
+        } catch (Exception e) {
+            NotFoundException rnf = new NotFoundException("File " + value.string.toString() +
+                    " from drawable resource ID #0x" + Integer.toHexString(id));
+            rnf.initCause(e);
+            throw rnf;
+        }
+    }
+
+    ConfigurationBoundResourceCache<Animator> getAnimatorCache() {
+        return mAnimatorCache;
+    }
+
+    ConfigurationBoundResourceCache<StateListAnimator> getStateListAnimatorCache() {
+        return mStateListAnimatorCache;
+    }
+
+    public void updateConfiguration(Configuration config, DisplayMetrics metrics,
+                                    CompatibilityInfo compat) {
+        synchronized (mAccessLock) {
+            if (false) {
+                Slog.i(TAG, "**** Updating config of " + this + ": old config is "
+                        + mConfiguration + " old compat is " + mCompatibilityInfo);
+                Slog.i(TAG, "**** Updating config of " + this + ": new config is "
+                        + config + " new compat is " + compat);
+            }
+            if (compat != null) {
+                mCompatibilityInfo = compat;
+            }
+            if (metrics != null) {
+                mMetrics.setTo(metrics);
+            }
+            // NOTE: We should re-arrange this code to create a Display
+            // with the CompatibilityInfo that is used everywhere we deal
+            // with the display in relation to this app, rather than
+            // doing the conversion here.  This impl should be okay because
+            // we make sure to return a compatible display in the places
+            // where there are public APIs to retrieve the display...  but
+            // it would be cleaner and more maintainble to just be
+            // consistently dealing with a compatible display everywhere in
+            // the framework.
+            mCompatibilityInfo.applyToDisplayMetrics(mMetrics);
+
+            final int configChanges = calcConfigChanges(config);
+
+            LocaleList locales = mConfiguration.getLocales();
+            if (locales.isEmpty()) {
+                locales = LocaleList.getAdjustedDefault();
+                mConfiguration.setLocales(locales);
+            }
+            if (mConfiguration.densityDpi != Configuration.DENSITY_DPI_UNDEFINED) {
+                mMetrics.densityDpi = mConfiguration.densityDpi;
+                mMetrics.density = mConfiguration.densityDpi * DisplayMetrics.DENSITY_DEFAULT_SCALE;
+            }
+            mMetrics.scaledDensity = mMetrics.density * mConfiguration.fontScale;
+
+            final int width, height;
+            if (mMetrics.widthPixels >= mMetrics.heightPixels) {
+                width = mMetrics.widthPixels;
+                height = mMetrics.heightPixels;
+            } else {
+                //noinspection SuspiciousNameCombination
+                width = mMetrics.heightPixels;
+                //noinspection SuspiciousNameCombination
+                height = mMetrics.widthPixels;
+            }
+
+            final int keyboardHidden;
+            if (mConfiguration.keyboardHidden == Configuration.KEYBOARDHIDDEN_NO
+                    && mConfiguration.hardKeyboardHidden == Configuration.HARDKEYBOARDHIDDEN_YES) {
+                keyboardHidden = Configuration.KEYBOARDHIDDEN_SOFT;
+            } else {
+                keyboardHidden = mConfiguration.keyboardHidden;
+            }
+
+            mAssets.setConfiguration(mConfiguration.mcc, mConfiguration.mnc,
+                    adjustLanguageTag(locales.get(0).toLanguageTag()),
+                    mConfiguration.orientation,
+                    mConfiguration.touchscreen,
+                    mConfiguration.densityDpi, mConfiguration.keyboard,
+                    keyboardHidden, mConfiguration.navigation, width, height,
+                    mConfiguration.smallestScreenWidthDp,
+                    mConfiguration.screenWidthDp, mConfiguration.screenHeightDp,
+                    mConfiguration.screenLayout, mConfiguration.uiMode,
+                    Build.VERSION.RESOURCES_SDK_INT);
+
+            if (DEBUG_CONFIG) {
+                Slog.i(TAG, "**** Updating config of " + this + ": final config is "
+                        + mConfiguration + " final compat is " + mCompatibilityInfo);
+            }
+
+            mDrawableCache.onConfigurationChange(configChanges);
+            mColorDrawableCache.onConfigurationChange(configChanges);
+            mComplexColorCache.onConfigurationChange(configChanges);
+            mAnimatorCache.onConfigurationChange(configChanges);
+            mStateListAnimatorCache.onConfigurationChange(configChanges);
+
+            flushLayoutCache();
+        }
+        synchronized (sSync) {
+            if (mPluralRule != null) {
+                mPluralRule = PluralRules.forLocale(mConfiguration.getLocales().get(0));
+            }
+        }
+    }
+
+    /**
+     * Called by ConfigurationBoundResourceCacheTest.
+     */
+    public int calcConfigChanges(Configuration config) {
+        int configChanges = 0xfffffff;
+        if (config != null) {
+            mTmpConfig.setTo(config);
+            int density = config.densityDpi;
+            if (density == Configuration.DENSITY_DPI_UNDEFINED) {
+                density = mMetrics.noncompatDensityDpi;
+            }
+
+            mCompatibilityInfo.applyToConfiguration(density, mTmpConfig);
+
+            if (mTmpConfig.getLocales().isEmpty()) {
+                mTmpConfig.setLocales(LocaleList.getDefault());
+            }
+            configChanges = mConfiguration.updateFrom(mTmpConfig);
+            configChanges = ActivityInfo.activityInfoConfigToNative(configChanges);
+        }
+        return configChanges;
+    }
+
+    /**
+     * {@code Locale.toLanguageTag} will transform the obsolete (and deprecated)
+     * language codes "in", "ji" and "iw" to "id", "yi" and "he" respectively.
+     *
+     * All released versions of android prior to "L" used the deprecated language
+     * tags, so we will need to support them for backwards compatibility.
+     *
+     * Note that this conversion needs to take place *after* the call to
+     * {@code toLanguageTag} because that will convert all the deprecated codes to
+     * the new ones, even if they're set manually.
+     */
+    private static String adjustLanguageTag(String languageTag) {
+        final int separator = languageTag.indexOf('-');
+        final String language;
+        final String remainder;
+
+        if (separator == -1) {
+            language = languageTag;
+            remainder = "";
+        } else {
+            language = languageTag.substring(0, separator);
+            remainder = languageTag.substring(separator);
+        }
+
+        return Locale.adjustLanguageCode(language) + remainder;
+    }
+
+    /**
+     * Call this to remove all cached loaded layout resources from the
+     * Resources object.  Only intended for use with performance testing
+     * tools.
+     */
+    public void flushLayoutCache() {
+        synchronized (mCachedXmlBlocks) {
+            Arrays.fill(mCachedXmlBlockCookies, 0);
+            Arrays.fill(mCachedXmlBlockFiles, null);
+
+            final XmlBlock[] cachedXmlBlocks = mCachedXmlBlocks;
+            for (int i = 0; i < XML_BLOCK_CACHE_SIZE; i++) {
+                final XmlBlock oldBlock = cachedXmlBlocks[i];
+                if (oldBlock != null) {
+                    oldBlock.close();
+                }
+            }
+            Arrays.fill(cachedXmlBlocks, null);
+        }
+    }
+
+    @Nullable
+    Drawable loadDrawable(Resources wrapper, TypedValue value, int id, Resources.Theme theme,
+            boolean useCache) throws NotFoundException {
+        try {
+            if (TRACE_FOR_PRELOAD) {
+                // Log only framework resources
+                if ((id >>> 24) == 0x1) {
+                    final String name = getResourceName(id);
+                    if (name != null) {
+                        Log.d("PreloadDrawable", name);
+                    }
+                }
+            }
+
+            final boolean isColorDrawable;
+            final DrawableCache caches;
+            final long key;
+            if (value.type >= TypedValue.TYPE_FIRST_COLOR_INT
+                    && value.type <= TypedValue.TYPE_LAST_COLOR_INT) {
+                isColorDrawable = true;
+                caches = mColorDrawableCache;
+                key = value.data;
+            } else {
+                isColorDrawable = false;
+                caches = mDrawableCache;
+                key = (((long) value.assetCookie) << 32) | value.data;
+            }
+
+            // First, check whether we have a cached version of this drawable
+            // that was inflated against the specified theme. Skip the cache if
+            // we're currently preloading or we're not using the cache.
+            if (!mPreloading && useCache) {
+                final Drawable cachedDrawable = caches.getInstance(key, wrapper, theme);
+                if (cachedDrawable != null) {
+                    return cachedDrawable;
+                }
+            }
+
+            // Next, check preloaded drawables. Preloaded drawables may contain
+            // unresolved theme attributes.
+            final Drawable.ConstantState cs;
+            if (isColorDrawable) {
+                cs = sPreloadedColorDrawables.get(key);
+            } else {
+                cs = sPreloadedDrawables[mConfiguration.getLayoutDirection()].get(key);
+            }
+
+            Drawable dr;
+            if (cs != null) {
+                dr = cs.newDrawable(wrapper);
+            } else if (isColorDrawable) {
+                dr = new ColorDrawable(value.data);
+            } else {
+                dr = loadDrawableForCookie(wrapper, value, id, null);
+            }
+
+            // Determine if the drawable has unresolved theme attributes. If it
+            // does, we'll need to apply a theme and store it in a theme-specific
+            // cache.
+            final boolean canApplyTheme = dr != null && dr.canApplyTheme();
+            if (canApplyTheme && theme != null) {
+                dr = dr.mutate();
+                dr.applyTheme(theme);
+                dr.clearMutated();
+            }
+
+            // If we were able to obtain a drawable, store it in the appropriate
+            // cache: preload, not themed, null theme, or theme-specific. Don't
+            // pollute the cache with drawables loaded from a foreign density.
+            if (dr != null && useCache) {
+                dr.setChangingConfigurations(value.changingConfigurations);
+                cacheDrawable(value, isColorDrawable, caches, theme, canApplyTheme, key, dr);
+            }
+
+            return dr;
+        } catch (Exception e) {
+            String name;
+            try {
+                name = getResourceName(id);
+            } catch (NotFoundException e2) {
+                name = "(missing name)";
+            }
+
+            // The target drawable might fail to load for any number of
+            // reasons, but we always want to include the resource name.
+            // Since the client already expects this method to throw a
+            // NotFoundException, just throw one of those.
+            final NotFoundException nfe = new NotFoundException("Drawable " + name
+                    + " with resource ID #0x" + Integer.toHexString(id), e);
+            nfe.setStackTrace(new StackTraceElement[0]);
+            throw nfe;
+        }
+    }
+
+    private void cacheDrawable(TypedValue value, boolean isColorDrawable, DrawableCache caches,
+            Resources.Theme theme, boolean usesTheme, long key, Drawable dr) {
+        final Drawable.ConstantState cs = dr.getConstantState();
+        if (cs == null) {
+            return;
+        }
+
+        if (mPreloading) {
+            final int changingConfigs = cs.getChangingConfigurations();
+            if (isColorDrawable) {
+                if (verifyPreloadConfig(changingConfigs, 0, value.resourceId, "drawable")) {
+                    sPreloadedColorDrawables.put(key, cs);
+                }
+            } else {
+                if (verifyPreloadConfig(
+                        changingConfigs, LAYOUT_DIR_CONFIG, value.resourceId, "drawable")) {
+                    if ((changingConfigs & LAYOUT_DIR_CONFIG) == 0) {
+                        // If this resource does not vary based on layout direction,
+                        // we can put it in all of the preload maps.
+                        sPreloadedDrawables[0].put(key, cs);
+                        sPreloadedDrawables[1].put(key, cs);
+                    } else {
+                        // Otherwise, only in the layout dir we loaded it for.
+                        sPreloadedDrawables[mConfiguration.getLayoutDirection()].put(key, cs);
+                    }
+                }
+            }
+        } else {
+            synchronized (mAccessLock) {
+                caches.put(key, theme, cs, usesTheme);
+            }
+        }
+    }
+
+    private boolean verifyPreloadConfig(int changingConfigurations, int allowVarying,
+            int resourceId, String name) {
+        // We allow preloading of resources even if they vary by font scale (which
+        // doesn't impact resource selection) or density (which we handle specially by
+        // simply turning off all preloading), as well as any other configs specified
+        // by the caller.
+        if (((changingConfigurations&~(ActivityInfo.CONFIG_FONT_SCALE |
+                ActivityInfo.CONFIG_DENSITY)) & ~allowVarying) != 0) {
+            String resName;
+            try {
+                resName = getResourceName(resourceId);
+            } catch (NotFoundException e) {
+                resName = "?";
+            }
+            // This should never happen in production, so we should log a
+            // warning even if we're not debugging.
+            Log.w(TAG, "Preloaded " + name + " resource #0x"
+                    + Integer.toHexString(resourceId)
+                    + " (" + resName + ") that varies with configuration!!");
+            return false;
+        }
+        if (TRACE_FOR_PRELOAD) {
+            String resName;
+            try {
+                resName = getResourceName(resourceId);
+            } catch (NotFoundException e) {
+                resName = "?";
+            }
+            Log.w(TAG, "Preloading " + name + " resource #0x"
+                    + Integer.toHexString(resourceId)
+                    + " (" + resName + ")");
+        }
+        return true;
+    }
+
+    /**
+     * Loads a drawable from XML or resources stream.
+     */
+    private Drawable loadDrawableForCookie(Resources wrapper, TypedValue value, int id,
+            Resources.Theme theme) {
+        if (value.string == null) {
+            throw new NotFoundException("Resource \"" + getResourceName(id) + "\" ("
+                    + Integer.toHexString(id) + ") is not a Drawable (color or path): " + value);
+        }
+
+        final String file = value.string.toString();
+
+        if (TRACE_FOR_MISS_PRELOAD) {
+            // Log only framework resources
+            if ((id >>> 24) == 0x1) {
+                final String name = getResourceName(id);
+                if (name != null) {
+                    Log.d(TAG, "Loading framework drawable #" + Integer.toHexString(id)
+                            + ": " + name + " at " + file);
+                }
+            }
+        }
+
+        if (DEBUG_LOAD) {
+            Log.v(TAG, "Loading drawable for cookie " + value.assetCookie + ": " + file);
+        }
+
+        final Drawable dr;
+
+        Trace.traceBegin(Trace.TRACE_TAG_RESOURCES, file);
+        try {
+            if (file.endsWith(".xml")) {
+                final XmlResourceParser rp = loadXmlResourceParser(
+                        file, id, value.assetCookie, "drawable");
+                dr = Drawable.createFromXml(wrapper, rp, theme);
+                rp.close();
+            } else {
+                final InputStream is = mAssets.openNonAsset(
+                        value.assetCookie, file, AssetManager.ACCESS_STREAMING);
+                dr = Drawable.createFromResourceStream(wrapper, value, is, file, null);
+                is.close();
+            }
+        } catch (Exception e) {
+            Trace.traceEnd(Trace.TRACE_TAG_RESOURCES);
+            final NotFoundException rnf = new NotFoundException(
+                    "File " + file + " from drawable resource ID #0x" + Integer.toHexString(id));
+            rnf.initCause(e);
+            throw rnf;
+        }
+        Trace.traceEnd(Trace.TRACE_TAG_RESOURCES);
+
+        return dr;
+    }
+
+    /**
+     * Given the value and id, we can get the XML filename as in value.data, based on that, we
+     * first try to load CSL from the cache. If not found, try to get from the constant state.
+     * Last, parse the XML and generate the CSL.
+     */
+    private ComplexColor loadComplexColorFromName(Resources wrapper, Resources.Theme theme,
+            TypedValue value, int id) {
+        final long key = (((long) value.assetCookie) << 32) | value.data;
+        final ConfigurationBoundResourceCache<ComplexColor> cache = mComplexColorCache;
+        ComplexColor complexColor = cache.getInstance(key, wrapper, theme);
+        if (complexColor != null) {
+            return complexColor;
+        }
+
+        final android.content.res.ConstantState<ComplexColor> factory =
+                sPreloadedComplexColors.get(key);
+
+        if (factory != null) {
+            complexColor = factory.newInstance(wrapper, theme);
+        }
+        if (complexColor == null) {
+            complexColor = loadComplexColorForCookie(wrapper, value, id, theme);
+        }
+
+        if (complexColor != null) {
+            if (mPreloading) {
+                if (verifyPreloadConfig(value.changingConfigurations, 0, value.resourceId,
+                        "color")) {
+                    sPreloadedComplexColors.put(key, complexColor.getConstantState());
+                }
+            } else {
+                cache.put(key, theme, complexColor.getConstantState());
+            }
+        }
+        return complexColor;
+    }
+
+    @Nullable
+    ComplexColor loadComplexColor(Resources wrapper, @NonNull TypedValue value, int id,
+            Resources.Theme theme) {
+        if (TRACE_FOR_PRELOAD) {
+            // Log only framework resources
+            if ((id >>> 24) == 0x1) {
+                final String name = getResourceName(id);
+                if (name != null) android.util.Log.d("loadComplexColor", name);
+            }
+        }
+
+        final long key = (((long) value.assetCookie) << 32) | value.data;
+
+        // Handle inline color definitions.
+        if (value.type >= TypedValue.TYPE_FIRST_COLOR_INT
+                && value.type <= TypedValue.TYPE_LAST_COLOR_INT) {
+            return getColorStateListFromInt(value, key);
+        }
+
+        final String file = value.string.toString();
+
+        ComplexColor complexColor;
+        if (file.endsWith(".xml")) {
+            try {
+                complexColor = loadComplexColorFromName(wrapper, theme, value, id);
+            } catch (Exception e) {
+                final NotFoundException rnf = new NotFoundException(
+                        "File " + file + " from complex color resource ID #0x"
+                                + Integer.toHexString(id));
+                rnf.initCause(e);
+                throw rnf;
+            }
+        } else {
+            throw new NotFoundException(
+                    "File " + file + " from drawable resource ID #0x"
+                            + Integer.toHexString(id) + ": .xml extension required");
+        }
+
+        return complexColor;
+    }
+
+    @Nullable
+    ColorStateList loadColorStateList(Resources wrapper, TypedValue value, int id,
+            Resources.Theme theme)
+            throws NotFoundException {
+        if (TRACE_FOR_PRELOAD) {
+            // Log only framework resources
+            if ((id >>> 24) == 0x1) {
+                final String name = getResourceName(id);
+                if (name != null) android.util.Log.d("PreloadColorStateList", name);
+            }
+        }
+
+        final long key = (((long) value.assetCookie) << 32) | value.data;
+
+        // Handle inline color definitions.
+        if (value.type >= TypedValue.TYPE_FIRST_COLOR_INT
+                && value.type <= TypedValue.TYPE_LAST_COLOR_INT) {
+            return getColorStateListFromInt(value, key);
+        }
+
+        ComplexColor complexColor = loadComplexColorFromName(wrapper, theme, value, id);
+        if (complexColor != null && complexColor instanceof ColorStateList) {
+            return (ColorStateList) complexColor;
+        }
+
+        throw new NotFoundException(
+                "Can't find ColorStateList from drawable resource ID #0x"
+                        + Integer.toHexString(id));
+    }
+
+    @NonNull
+    private ColorStateList getColorStateListFromInt(@NonNull TypedValue value, long key) {
+        ColorStateList csl;
+        final android.content.res.ConstantState<ComplexColor> factory =
+                sPreloadedComplexColors.get(key);
+        if (factory != null) {
+            return (ColorStateList) factory.newInstance();
+        }
+
+        csl = ColorStateList.valueOf(value.data);
+
+        if (mPreloading) {
+            if (verifyPreloadConfig(value.changingConfigurations, 0, value.resourceId,
+                    "color")) {
+                sPreloadedComplexColors.put(key, csl.getConstantState());
+            }
+        }
+
+        return csl;
+    }
+
+    /**
+     * Load a ComplexColor based on the XML file content. The result can be a GradientColor or
+     * ColorStateList. Note that pure color will be wrapped into a ColorStateList.
+     *
+     * We deferred the parser creation to this function b/c we need to differentiate b/t gradient
+     * and selector tag.
+     *
+     * @return a ComplexColor (GradientColor or ColorStateList) based on the XML file content.
+     */
+    @Nullable
+    private ComplexColor loadComplexColorForCookie(Resources wrapper, TypedValue value, int id,
+            Resources.Theme theme) {
+        if (value.string == null) {
+            throw new UnsupportedOperationException(
+                    "Can't convert to ComplexColor: type=0x" + value.type);
+        }
+
+        final String file = value.string.toString();
+
+        if (TRACE_FOR_MISS_PRELOAD) {
+            // Log only framework resources
+            if ((id >>> 24) == 0x1) {
+                final String name = getResourceName(id);
+                if (name != null) {
+                    Log.d(TAG, "Loading framework ComplexColor #" + Integer.toHexString(id)
+                            + ": " + name + " at " + file);
+                }
+            }
+        }
+
+        if (DEBUG_LOAD) {
+            Log.v(TAG, "Loading ComplexColor for cookie " + value.assetCookie + ": " + file);
+        }
+
+        ComplexColor complexColor = null;
+
+        Trace.traceBegin(Trace.TRACE_TAG_RESOURCES, file);
+        if (file.endsWith(".xml")) {
+            try {
+                final XmlResourceParser parser = loadXmlResourceParser(
+                        file, id, value.assetCookie, "ComplexColor");
+
+                final AttributeSet attrs = Xml.asAttributeSet(parser);
+                int type;
+                while ((type = parser.next()) != XmlPullParser.START_TAG
+                        && type != XmlPullParser.END_DOCUMENT) {
+                    // Seek parser to start tag.
+                }
+                if (type != XmlPullParser.START_TAG) {
+                    throw new XmlPullParserException("No start tag found");
+                }
+
+                final String name = parser.getName();
+                if (name.equals("gradient")) {
+                    complexColor = GradientColor.createFromXmlInner(wrapper, parser, attrs, theme);
+                } else if (name.equals("selector")) {
+                    complexColor = ColorStateList.createFromXmlInner(wrapper, parser, attrs, theme);
+                }
+                parser.close();
+            } catch (Exception e) {
+                Trace.traceEnd(Trace.TRACE_TAG_RESOURCES);
+                final NotFoundException rnf = new NotFoundException(
+                        "File " + file + " from ComplexColor resource ID #0x"
+                                + Integer.toHexString(id));
+                rnf.initCause(e);
+                throw rnf;
+            }
+        } else {
+            Trace.traceEnd(Trace.TRACE_TAG_RESOURCES);
+            throw new NotFoundException(
+                    "File " + file + " from drawable resource ID #0x"
+                            + Integer.toHexString(id) + ": .xml extension required");
+        }
+        Trace.traceEnd(Trace.TRACE_TAG_RESOURCES);
+
+        return complexColor;
+    }
+
+    /**
+     * Loads an XML parser for the specified file.
+     *
+     * @param file the path for the XML file to parse
+     * @param id the resource identifier for the file
+     * @param assetCookie the asset cookie for the file
+     * @param type the type of resource (used for logging)
+     * @return a parser for the specified XML file
+     * @throws NotFoundException if the file could not be loaded
+     */
+    @NonNull
+    XmlResourceParser loadXmlResourceParser(@NonNull String file, @AnyRes int id, int assetCookie,
+            @NonNull String type)
+            throws NotFoundException {
+        if (id != 0) {
+            try {
+                synchronized (mCachedXmlBlocks) {
+                    final int[] cachedXmlBlockCookies = mCachedXmlBlockCookies;
+                    final String[] cachedXmlBlockFiles = mCachedXmlBlockFiles;
+                    final XmlBlock[] cachedXmlBlocks = mCachedXmlBlocks;
+                    // First see if this block is in our cache.
+                    final int num = cachedXmlBlockFiles.length;
+                    for (int i = 0; i < num; i++) {
+                        if (cachedXmlBlockCookies[i] == assetCookie && cachedXmlBlockFiles[i] != null
+                                && cachedXmlBlockFiles[i].equals(file)) {
+                            return cachedXmlBlocks[i].newParser();
+                        }
+                    }
+
+                    // Not in the cache, create a new block and put it at
+                    // the next slot in the cache.
+                    final XmlBlock block = mAssets.openXmlBlockAsset(assetCookie, file);
+                    if (block != null) {
+                        final int pos = (mLastCachedXmlBlockIndex + 1) % num;
+                        mLastCachedXmlBlockIndex = pos;
+                        final XmlBlock oldBlock = cachedXmlBlocks[pos];
+                        if (oldBlock != null) {
+                            oldBlock.close();
+                        }
+                        cachedXmlBlockCookies[pos] = assetCookie;
+                        cachedXmlBlockFiles[pos] = file;
+                        cachedXmlBlocks[pos] = block;
+                        return block.newParser();
+                    }
+                }
+            } catch (Exception e) {
+                final NotFoundException rnf = new NotFoundException("File " + file
+                        + " from xml type " + type + " resource ID #0x" + Integer.toHexString(id));
+                rnf.initCause(e);
+                throw rnf;
+            }
+        }
+
+        throw new NotFoundException("File " + file + " from xml type " + type + " resource ID #0x"
+                + Integer.toHexString(id));
+    }
+
+    /**
+     * Start preloading of resource data using this Resources object.  Only
+     * for use by the zygote process for loading common system resources.
+     * {@hide}
+     */
+    public final void startPreloading() {
+        synchronized (sSync) {
+            if (sPreloaded) {
+                throw new IllegalStateException("Resources already preloaded");
+            }
+            sPreloaded = true;
+            mPreloading = true;
+            mConfiguration.densityDpi = DisplayMetrics.DENSITY_DEVICE;
+            updateConfiguration(null, null, null);
+        }
+    }
+
+    /**
+     * Called by zygote when it is done preloading resources, to change back
+     * to normal Resources operation.
+     */
+    void finishPreloading() {
+        if (mPreloading) {
+            mPreloading = false;
+            flushLayoutCache();
+        }
+    }
+
+    LongSparseArray<Drawable.ConstantState> getPreloadedDrawables() {
+        return sPreloadedDrawables[0];
+    }
+
+    ThemeImpl newThemeImpl() {
+        return new ThemeImpl();
+    }
+
+    /**
+     * Creates a new ThemeImpl which is already set to the given Resources.ThemeKey.
+     */
+    ThemeImpl newThemeImpl(Resources.ThemeKey key) {
+        ThemeImpl impl = new ThemeImpl();
+        impl.mKey.setTo(key);
+        impl.rebase();
+        return impl;
+    }
+
+    public class ThemeImpl {
+        /**
+         * Unique key for the series of styles applied to this theme.
+         */
+        private final Resources.ThemeKey mKey = new Resources.ThemeKey();
+
+        @SuppressWarnings("hiding")
+        private final AssetManager mAssets;
+        private final long mTheme;
+
+        /**
+         * Resource identifier for the theme.
+         */
+        private int mThemeResId = 0;
+
+        /*package*/ ThemeImpl() {
+            mAssets = ResourcesImpl.this.mAssets;
+            mTheme = mAssets.createTheme();
+        }
+
+        @Override
+        protected void finalize() throws Throwable {
+            super.finalize();
+            mAssets.releaseTheme(mTheme);
+        }
+
+        /*package*/ Resources.ThemeKey getKey() {
+            return mKey;
+        }
+
+        /*package*/ long getNativeTheme() {
+            return mTheme;
+        }
+
+        /*package*/ int getAppliedStyleResId() {
+            return mThemeResId;
+        }
+
+        void applyStyle(int resId, boolean force) {
+            synchronized (mKey) {
+                AssetManager.applyThemeStyle(mTheme, resId, force);
+
+                mThemeResId = resId;
+                mKey.append(resId, force);
+            }
+        }
+
+        void setTo(ThemeImpl other) {
+            synchronized (mKey) {
+                synchronized (other.mKey) {
+                    AssetManager.copyTheme(mTheme, other.mTheme);
+
+                    mThemeResId = other.mThemeResId;
+                    mKey.setTo(other.getKey());
+                }
+            }
+        }
+
+        @NonNull
+        TypedArray obtainStyledAttributes(@NonNull Resources.Theme wrapper,
+                AttributeSet set,
+                @StyleableRes int[] attrs,
+                @AttrRes int defStyleAttr,
+                @StyleRes int defStyleRes) {
+            synchronized (mKey) {
+                final int len = attrs.length;
+                final TypedArray array = TypedArray.obtain(wrapper.getResources(), len);
+
+                // XXX note that for now we only work with compiled XML files.
+                // To support generic XML files we will need to manually parse
+                // out the attributes from the XML file (applying type information
+                // contained in the resources and such).
+                final XmlBlock.Parser parser = (XmlBlock.Parser) set;
+                AssetManager.applyStyle(mTheme, defStyleAttr, defStyleRes,
+                        parser != null ? parser.mParseState : 0,
+                        attrs, array.mData, array.mIndices);
+                array.mTheme = wrapper;
+                array.mXml = parser;
+
+                return array;
+            }
+        }
+
+        @NonNull
+        TypedArray resolveAttributes(@NonNull Resources.Theme wrapper,
+                @NonNull int[] values,
+                @NonNull int[] attrs) {
+            synchronized (mKey) {
+                final int len = attrs.length;
+                if (values == null || len != values.length) {
+                    throw new IllegalArgumentException(
+                            "Base attribute values must the same length as attrs");
+                }
+
+                final TypedArray array = TypedArray.obtain(wrapper.getResources(), len);
+                AssetManager.resolveAttrs(mTheme, 0, 0, values, attrs, array.mData, array.mIndices);
+                array.mTheme = wrapper;
+                array.mXml = null;
+                return array;
+            }
+        }
+
+        boolean resolveAttribute(int resid, TypedValue outValue, boolean resolveRefs) {
+            synchronized (mKey) {
+                return mAssets.getThemeValue(mTheme, resid, outValue, resolveRefs);
+            }
+        }
+
+        int[] getAllAttributes() {
+            return mAssets.getStyleAttributes(getAppliedStyleResId());
+        }
+
+        int getChangingConfigurations() {
+            synchronized (mKey) {
+                final int nativeChangingConfig =
+                        AssetManager.getThemeChangingConfigurations(mTheme);
+                return ActivityInfo.activityInfoConfigNativeToJava(nativeChangingConfig);
+            }
+        }
+
+        public void dump(int priority, String tag, String prefix) {
+            synchronized (mKey) {
+                AssetManager.dumpTheme(mTheme, priority, tag, prefix);
+            }
+        }
+
+        String[] getTheme() {
+            synchronized (mKey) {
+                final int N = mKey.mCount;
+                final String[] themes = new String[N * 2];
+                for (int i = 0, j = N - 1; i < themes.length; i += 2, --j) {
+                    final int resId = mKey.mResId[j];
+                    final boolean forced = mKey.mForce[j];
+                    try {
+                        themes[i] = getResourceName(resId);
+                    } catch (NotFoundException e) {
+                        themes[i] = Integer.toHexString(i);
+                    }
+                    themes[i + 1] = forced ? "forced" : "not forced";
+                }
+                return themes;
+            }
+        }
+
+        /**
+         * Rebases the theme against the parent Resource object's current
+         * configuration by re-applying the styles passed to
+         * {@link #applyStyle(int, boolean)}.
+         */
+        void rebase() {
+            synchronized (mKey) {
+                AssetManager.clearTheme(mTheme);
+
+                // Reapply the same styles in the same order.
+                for (int i = 0; i < mKey.mCount; i++) {
+                    final int resId = mKey.mResId[i];
+                    final boolean force = mKey.mForce[i];
+                    AssetManager.applyThemeStyle(mTheme, resId, force);
+                }
+            }
+        }
+    }
+}
diff --git a/core/java/android/content/res/ResourcesKey.java b/core/java/android/content/res/ResourcesKey.java
index 2620571..e894492 100644
--- a/core/java/android/content/res/ResourcesKey.java
+++ b/core/java/android/content/res/ResourcesKey.java
@@ -17,32 +17,59 @@
 package android.content.res;
 
 import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.text.TextUtils;
 
+import java.util.Arrays;
 import java.util.Objects;
 
 /** @hide */
 public final class ResourcesKey {
-    private final String mResDir;
-    private final float mScale;
-    private final int mHash;
+    @Nullable
+    public final String mResDir;
+
+    @Nullable
+    public final String[] mSplitResDirs;
+
+    @Nullable
+    public final String[] mOverlayDirs;
+
+    @Nullable
+    public final String[] mLibDirs;
 
     public final int mDisplayId;
+
     @NonNull
     public final Configuration mOverrideConfiguration;
 
-    public ResourcesKey(String resDir, int displayId, Configuration overrideConfiguration,
-            float scale) {
+    @NonNull
+    public final CompatibilityInfo mCompatInfo;
+
+    private final int mHash;
+
+    public ResourcesKey(@Nullable String resDir,
+                        @Nullable String[] splitResDirs,
+                        @Nullable String[] overlayDirs,
+                        @Nullable String[] libDirs,
+                        int displayId,
+                        @Nullable Configuration overrideConfig,
+                        @Nullable CompatibilityInfo compatInfo) {
         mResDir = resDir;
+        mSplitResDirs = splitResDirs;
+        mOverlayDirs = overlayDirs;
+        mLibDirs = libDirs;
         mDisplayId = displayId;
-        mOverrideConfiguration = overrideConfiguration != null
-                ? overrideConfiguration : Configuration.EMPTY;
-        mScale = scale;
+        mOverrideConfiguration = overrideConfig != null ? overrideConfig : Configuration.EMPTY;
+        mCompatInfo = compatInfo != null ? compatInfo : CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO;
 
         int hash = 17;
-        hash = 31 * hash + (mResDir == null ? 0 : mResDir.hashCode());
+        hash = 31 * hash + Objects.hashCode(mResDir);
+        hash = 31 * hash + Arrays.hashCode(mSplitResDirs);
+        hash = 31 * hash + Arrays.hashCode(mOverlayDirs);
+        hash = 31 * hash + Arrays.hashCode(mLibDirs);
         hash = 31 * hash + mDisplayId;
-        hash = 31 * hash + mOverrideConfiguration.hashCode();
-        hash = 31 * hash + Float.floatToIntBits(mScale);
+        hash = 31 * hash + Objects.hashCode(mOverrideConfiguration);
+        hash = 31 * hash + Objects.hashCode(mCompatInfo);
         mHash = hash;
     }
 
@@ -60,18 +87,32 @@
         if (!(obj instanceof ResourcesKey)) {
             return false;
         }
+
         ResourcesKey peer = (ResourcesKey) obj;
+        if (mHash != peer.mHash) {
+            // If the hashes don't match, the objects can't match.
+            return false;
+        }
 
         if (!Objects.equals(mResDir, peer.mResDir)) {
             return false;
         }
+        if (!Arrays.equals(mSplitResDirs, peer.mSplitResDirs)) {
+            return false;
+        }
+        if (!Arrays.equals(mOverlayDirs, peer.mOverlayDirs)) {
+            return false;
+        }
+        if (!Arrays.equals(mLibDirs, peer.mLibDirs)) {
+            return false;
+        }
         if (mDisplayId != peer.mDisplayId) {
             return false;
         }
-        if (!mOverrideConfiguration.equals(peer.mOverrideConfiguration)) {
+        if (!Objects.equals(mOverrideConfiguration, peer.mOverrideConfiguration)) {
             return false;
         }
-        if (mScale != peer.mScale) {
+        if (!Objects.equals(mCompatInfo, peer.mCompatInfo)) {
             return false;
         }
         return true;
@@ -79,6 +120,29 @@
 
     @Override
     public String toString() {
-        return Integer.toHexString(mHash);
+        StringBuilder builder = new StringBuilder().append("ResourcesKey{");
+        builder.append(" mHash=").append(Integer.toHexString(mHash));
+        builder.append(" mResDir=").append(mResDir);
+        builder.append(" mSplitDirs=[");
+        if (mSplitResDirs != null) {
+            builder.append(TextUtils.join(",", mSplitResDirs));
+        }
+        builder.append("]");
+        builder.append(" mOverlayDirs=[");
+        if (mOverlayDirs != null) {
+            builder.append(TextUtils.join(",", mOverlayDirs));
+        }
+        builder.append("]");
+        builder.append(" mLibDirs=[");
+        if (mLibDirs != null) {
+            builder.append(TextUtils.join(",", mLibDirs));
+        }
+        builder.append("]");
+        builder.append(" mDisplayId=").append(mDisplayId);
+        builder.append(" mOverrideConfig=").append(Configuration.resourceQualifierString(
+                mOverrideConfiguration));
+        builder.append(" mCompatInfo=").append(mCompatInfo);
+        builder.append("}");
+        return builder.toString();
     }
 }
diff --git a/core/java/android/content/res/TypedArray.java b/core/java/android/content/res/TypedArray.java
index da49b64..022bdfb 100644
--- a/core/java/android/content/res/TypedArray.java
+++ b/core/java/android/content/res/TypedArray.java
@@ -1206,8 +1206,8 @@
 
     /*package*/ TypedArray(Resources resources, int[] data, int[] indices, int len) {
         mResources = resources;
-        mMetrics = mResources.mMetrics;
-        mAssets = mResources.mAssets;
+        mMetrics = mResources.getDisplayMetrics();
+        mAssets = mResources.getAssets();
         mData = data;
         mIndices = indices;
         mLength = len;
diff --git a/core/java/android/hardware/ConsumerIrManager.java b/core/java/android/hardware/ConsumerIrManager.java
index 6d29212..9fa1c3f 100644
--- a/core/java/android/hardware/ConsumerIrManager.java
+++ b/core/java/android/hardware/ConsumerIrManager.java
@@ -60,8 +60,8 @@
         try {
             return mService.hasIrEmitter();
         } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
         }
-        return false;
     }
 
     /**
@@ -84,7 +84,7 @@
         try {
             mService.transmit(mPackageName, carrierFrequency, pattern);
         } catch (RemoteException e) {
-            Log.w(TAG, "failed to transmit.", e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -149,8 +149,7 @@
             }
             return range;
         } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
         }
-        return null;
     }
-
 }
diff --git a/core/java/android/hardware/ICamera.aidl b/core/java/android/hardware/ICamera.aidl
deleted file mode 100644
index d4f64f8..0000000
--- a/core/java/android/hardware/ICamera.aidl
+++ /dev/null
@@ -1,26 +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 android.hardware;
-
-/** @hide */
-interface ICamera
-{
-    /**
-     * Keep up-to-date with frameworks/av/include/camera/ICamera.h
-     */
-    void disconnect();
-}
diff --git a/core/java/android/hardware/ICameraClient.aidl b/core/java/android/hardware/ICameraClient.aidl
deleted file mode 100644
index d7877b4..0000000
--- a/core/java/android/hardware/ICameraClient.aidl
+++ /dev/null
@@ -1,26 +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 android.hardware;
-
-/** @hide */
-interface ICameraClient
-{
-    /**
-     * Keep up-to-date with frameworks/av/include/camera/ICameraClient.h
-     */
-    // TODO: consider implementing this.
-}
diff --git a/core/java/android/hardware/ICameraService.aidl b/core/java/android/hardware/ICameraService.aidl
deleted file mode 100644
index 0b165cd..0000000
--- a/core/java/android/hardware/ICameraService.aidl
+++ /dev/null
@@ -1,89 +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 android.hardware;
-
-import android.hardware.ICamera;
-import android.hardware.ICameraClient;
-import android.hardware.camera2.ICameraDeviceUser;
-import android.hardware.camera2.ICameraDeviceCallbacks;
-import android.hardware.camera2.impl.CameraMetadataNative;
-import android.hardware.camera2.utils.BinderHolder;
-import android.hardware.ICameraServiceListener;
-import android.hardware.CameraInfo;
-
-/**
- * Binder interface for the native camera service running in mediaserver.
- *
- * @hide
- */
-interface ICameraService
-{
-    /**
-     * Keep up-to-date with frameworks/av/include/camera/ICameraService.h
-     */
-    int getNumberOfCameras(int type);
-
-    // rest of 'int' return values in this file are actually status_t
-
-    int getCameraInfo(int cameraId, out CameraInfo info);
-
-    int connect(ICameraClient client, int cameraId,
-                    String opPackageName,
-                    int clientUid,
-                    // Container for an ICamera object
-                    out BinderHolder device);
-
-    int connectDevice(ICameraDeviceCallbacks callbacks, int cameraId,
-                              String opPackageName,
-                              int clientUid,
-                              // Container for an ICameraDeviceUser object
-                              out BinderHolder device);
-
-    int addListener(ICameraServiceListener listener);
-    int removeListener(ICameraServiceListener listener);
-
-    int getCameraCharacteristics(int cameraId, out CameraMetadataNative info);
-
-    /**
-     * The java stubs for this method are not intended to be used.  Please use
-     * the native stub in frameworks/av/include/camera/ICameraService.h instead.
-     * The BinderHolder output is being used as a placeholder, and will not be
-     * well-formatted in the generated java method.
-     */
-    int getCameraVendorTagDescriptor(out BinderHolder desc);
-
-    // Writes the camera1 parameters into a single-element array.
-    int getLegacyParameters(int cameraId, out String[] parameters);
-    // Determines if a particular API version is supported; see ICameraService.h for version defines
-    int supportsCameraApi(int cameraId, int apiVersion);
-
-    int connectLegacy(ICameraClient client, int cameraId,
-                    int halVersion,
-                    String opPackageName,
-                    int clientUid,
-                    // Container for an ICamera object
-                    out BinderHolder device);
-
-    int setTorchMode(String CameraId, boolean enabled, IBinder clientBinder);
-
-    /**
-     * Notify the camera service of a system event.  Should only be called from system_server.
-     *
-     * Callers require the android.permission.CAMERA_SEND_SYSTEM_EVENTS permission.
-     */
-    oneway void notifySystemEvent(int eventId, in int[] args);
-}
diff --git a/core/java/android/hardware/ICameraServiceProxy.aidl b/core/java/android/hardware/ICameraServiceProxy.aidl
deleted file mode 100644
index 0e654d5..0000000
--- a/core/java/android/hardware/ICameraServiceProxy.aidl
+++ /dev/null
@@ -1,37 +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.hardware;
-
-/**
- * Binder interface for the camera service proxy running in system_server.
- *
- * Keep in sync with frameworks/av/include/camera/ICameraServiceProxy.h
- *
- * @hide
- */
-interface ICameraServiceProxy
-{
-    /**
-     * Ping the service proxy to update the valid users for the camera service.
-     */
-    oneway void pingForUserUpdate();
-
-    /**
-     * Update the status of a camera device
-     */
-     oneway void notifyCameraState(String cameraId, int newCameraState);
-}
diff --git a/core/java/android/hardware/SensorEventListener.java b/core/java/android/hardware/SensorEventListener.java
index 0d859fb..0c059ba 100644
--- a/core/java/android/hardware/SensorEventListener.java
+++ b/core/java/android/hardware/SensorEventListener.java
@@ -18,28 +18,33 @@
 
 /**
  * Used for receiving notifications from the SensorManager when
- * sensor values have changed.
+ * there is new sensor data.
  */
 public interface SensorEventListener {
 
     /**
-     * Called when sensor values have changed.
+     * Called when there is a new sensor event.  Note that "on changed"
+     * is somewhat of a misnomer, as this will also be called if we have a
+     * new reading from a sensor with the exact same sensor values (but a
+     * newer timestamp).
+     *
      * <p>See {@link android.hardware.SensorManager SensorManager}
      * for details on possible sensor types.
      * <p>See also {@link android.hardware.SensorEvent SensorEvent}.
-     * 
+     *
      * <p><b>NOTE:</b> The application doesn't own the
      * {@link android.hardware.SensorEvent event}
      * object passed as a parameter and therefore cannot hold on to it.
      * The object may be part of an internal pool and may be reused by
      * the framework.
      *
-     * @param event the {@link android.hardware.SensorEvent SensorEvent}. 
+     * @param event the {@link android.hardware.SensorEvent SensorEvent}.
      */
     public void onSensorChanged(SensorEvent event);
 
     /**
-     * Called when the accuracy of the registered sensor has changed.
+     * Called when the accuracy of the registered sensor has changed.  Unlike
+     * onSensorChanged(), this is only called when this accuracy value changes.
      *
      * <p>See the SENSOR_STATUS_* constants in
      * {@link android.hardware.SensorManager SensorManager} for details.
diff --git a/core/java/android/hardware/SensorManager.java b/core/java/android/hardware/SensorManager.java
index f0b17c30..5684aa5 100644
--- a/core/java/android/hardware/SensorManager.java
+++ b/core/java/android/hardware/SensorManager.java
@@ -46,7 +46,7 @@
  * is an example of a trigger sensor.
  * </p>
  * <pre class="prettyprint">
- * public class SensorActivity extends Activity, implements SensorEventListener {
+ * public class SensorActivity extends Activity implements SensorEventListener {
  *     private final SensorManager mSensorManager;
  *     private final Sensor mAccelerometer;
  *
diff --git a/core/java/android/hardware/SerialManager.java b/core/java/android/hardware/SerialManager.java
index e0680bf22..83f7649 100644
--- a/core/java/android/hardware/SerialManager.java
+++ b/core/java/android/hardware/SerialManager.java
@@ -14,13 +14,11 @@
  * limitations under the License.
  */
 
-
 package android.hardware;
 
 import android.content.Context;
 import android.os.ParcelFileDescriptor;
 import android.os.RemoteException;
-import android.util.Log;
 
 import java.io.IOException;
 
@@ -50,8 +48,7 @@
         try {
             return mService.getSerialPorts();
         } catch (RemoteException e) {
-            Log.e(TAG, "RemoteException in getSerialPorts", e);
-            return null;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -77,8 +74,7 @@
                 throw new IOException("Could not open serial port " + name);
             }
         } catch (RemoteException e) {
-            Log.e(TAG, "exception in UsbManager.openDevice", e);
+            throw e.rethrowFromSystemServer();
         }
-        return null;
     }
 }
diff --git a/core/java/android/hardware/camera2/CameraAccessException.java b/core/java/android/hardware/camera2/CameraAccessException.java
index 933ce0d..f9b659c 100644
--- a/core/java/android/hardware/camera2/CameraAccessException.java
+++ b/core/java/android/hardware/camera2/CameraAccessException.java
@@ -114,12 +114,12 @@
     }
 
     public CameraAccessException(@AccessError int problem, String message) {
-        super(message);
+        super(getCombinedMessage(problem, message));
         mReason = problem;
     }
 
     public CameraAccessException(@AccessError int problem, String message, Throwable cause) {
-        super(message, cause);
+        super(getCombinedMessage(problem, message), cause);
         mReason = problem;
     }
 
@@ -151,4 +151,37 @@
         }
         return null;
     }
+
+    private static String getCombinedMessage(@AccessError int problem, String message) {
+        String problemString = getProblemString(problem);
+        return String.format("%s (%d): %s", problemString, problem, message);
+    }
+
+    private static String getProblemString(int problem) {
+        String problemString;
+        switch (problem) {
+            case CAMERA_IN_USE:
+                problemString = "CAMERA_IN_USE";
+                break;
+            case MAX_CAMERAS_IN_USE:
+                problemString = "MAX_CAMERAS_IN_USE";
+                break;
+            case CAMERA_DISCONNECTED:
+                problemString = "CAMERA_DISCONNECTED";
+                break;
+            case CAMERA_DISABLED:
+                problemString = "CAMERA_DISABLED";
+                break;
+            case CAMERA_ERROR:
+                problemString = "CAMERA_ERROR";
+                break;
+            case CAMERA_DEPRECATED_HAL:
+                problemString = "CAMERA_DEPRECATED_HAL";
+                break;
+            default:
+                problemString = "<UNKNOWN ERROR>";
+        }
+        return problemString;
+    }
+
 }
diff --git a/core/java/android/hardware/camera2/CameraCaptureSession.java b/core/java/android/hardware/camera2/CameraCaptureSession.java
index 8724a96..38279a4 100644
--- a/core/java/android/hardware/camera2/CameraCaptureSession.java
+++ b/core/java/android/hardware/camera2/CameraCaptureSession.java
@@ -990,6 +990,30 @@
                 int sequenceId) {
             // default empty implementation
         }
+
+        /**
+         * <p>This method is called if a single buffer for a capture could not be sent to its
+         * destination surface.</p>
+         *
+         * <p>If the whole capture failed, then {@link #onCaptureFailed} will be called instead. If
+         * some but not all buffers were captured but the result metadata will not be available,
+         * then onCaptureFailed will be invoked with {@link CaptureFailure#wasImageCaptured}
+         * returning true, along with one or more calls to {@link #onCaptureBufferLost} for the
+         * failed outputs.</p>
+         *
+         * @param session
+         *            The session returned by {@link CameraDevice#createCaptureSession}
+         * @param request
+         *            The request that was given to the CameraDevice
+         * @param target
+         *            The target Surface that the buffer will not be produced for
+         * @param frameNumber
+         *            The frame number for the request
+         */
+        public void onCaptureBufferLost(@NonNull CameraCaptureSession session,
+                @NonNull CaptureRequest request, @NonNull Surface target, long frameNumber) {
+            // default empty implementation
+        }
     }
 
     /**
diff --git a/core/java/android/hardware/camera2/CameraManager.java b/core/java/android/hardware/camera2/CameraManager.java
index 51796eb..04e64af 100644
--- a/core/java/android/hardware/camera2/CameraManager.java
+++ b/core/java/android/hardware/camera2/CameraManager.java
@@ -26,15 +26,14 @@
 import android.hardware.camera2.impl.CameraMetadataNative;
 import android.hardware.camera2.legacy.CameraDeviceUserShim;
 import android.hardware.camera2.legacy.LegacyMetadataMapper;
-import android.hardware.camera2.utils.CameraServiceBinderDecorator;
-import android.hardware.camera2.utils.CameraRuntimeException;
-import android.hardware.camera2.utils.BinderHolder;
 import android.os.IBinder;
 import android.os.Binder;
+import android.os.DeadObjectException;
 import android.os.Handler;
 import android.os.Looper;
 import android.os.RemoteException;
 import android.os.ServiceManager;
+import android.os.ServiceSpecificException;
 import android.util.Log;
 import android.util.ArrayMap;
 
@@ -240,25 +239,19 @@
                 if (!supportsCamera2ApiLocked(cameraId)) {
                     // Legacy backwards compatibility path; build static info from the camera
                     // parameters
-                    String[] outParameters = new String[1];
+                    String parameters = cameraService.getLegacyParameters(id);
 
-                    cameraService.getLegacyParameters(id, /*out*/outParameters);
-                    String parameters = outParameters[0];
-
-                    CameraInfo info = new CameraInfo();
-                    cameraService.getCameraInfo(id, /*out*/info);
+                    CameraInfo info = cameraService.getCameraInfo(id);
 
                     characteristics = LegacyMetadataMapper.createCharacteristics(parameters, info);
                 } else {
                     // Normal path: Get the camera characteristics directly from the camera service
-                    CameraMetadataNative info = new CameraMetadataNative();
-
-                    cameraService.getCameraCharacteristics(id, info);
+                    CameraMetadataNative info = cameraService.getCameraCharacteristics(id);
 
                     characteristics = new CameraCharacteristics(info);
                 }
-            } catch (CameraRuntimeException e) {
-                throw e.asChecked();
+            } catch (ServiceSpecificException e) {
+                throwAsPublicException(e);
             } catch (RemoteException e) {
                 // Camera service died - act as if the camera was disconnected
                 throw new CameraAccessException(CameraAccessException.CAMERA_DISCONNECTED,
@@ -292,85 +285,85 @@
             throws CameraAccessException {
         CameraCharacteristics characteristics = getCameraCharacteristics(cameraId);
         CameraDevice device = null;
-        try {
 
-            synchronized (mLock) {
+        synchronized (mLock) {
 
-                ICameraDeviceUser cameraUser = null;
+            ICameraDeviceUser cameraUser = null;
 
-                android.hardware.camera2.impl.CameraDeviceImpl deviceImpl =
-                        new android.hardware.camera2.impl.CameraDeviceImpl(
-                                cameraId,
-                                callback,
-                                handler,
-                                characteristics);
+            android.hardware.camera2.impl.CameraDeviceImpl deviceImpl =
+                    new android.hardware.camera2.impl.CameraDeviceImpl(
+                        cameraId,
+                        callback,
+                        handler,
+                        characteristics);
 
-                BinderHolder holder = new BinderHolder();
+            ICameraDeviceCallbacks callbacks = deviceImpl.getCallbacks();
 
-                ICameraDeviceCallbacks callbacks = deviceImpl.getCallbacks();
-                int id = Integer.parseInt(cameraId);
-                try {
-                    if (supportsCamera2ApiLocked(cameraId)) {
-                        // Use cameraservice's cameradeviceclient implementation for HAL3.2+ devices
-                        ICameraService cameraService = CameraManagerGlobal.get().getCameraService();
-                        if (cameraService == null) {
-                            throw new CameraRuntimeException(
-                                CameraAccessException.CAMERA_DISCONNECTED,
-                                "Camera service is currently unavailable");
-                        }
-                        cameraService.connectDevice(callbacks, id,
-                                mContext.getOpPackageName(), USE_CALLING_UID, holder);
-                        cameraUser = ICameraDeviceUser.Stub.asInterface(holder.getBinder());
-                    } else {
-                        // Use legacy camera implementation for HAL1 devices
-                        Log.i(TAG, "Using legacy camera HAL.");
-                        cameraUser = CameraDeviceUserShim.connectBinderShim(callbacks, id);
-                    }
-                } catch (CameraRuntimeException e) {
-                    if (e.getReason() == CameraAccessException.CAMERA_DEPRECATED_HAL) {
-                        throw new AssertionError("Should've gone down the shim path");
-                    } else if (e.getReason() == CameraAccessException.CAMERA_IN_USE ||
-                            e.getReason() == CameraAccessException.MAX_CAMERAS_IN_USE ||
-                            e.getReason() == CameraAccessException.CAMERA_DISABLED ||
-                            e.getReason() == CameraAccessException.CAMERA_DISCONNECTED ||
-                            e.getReason() == CameraAccessException.CAMERA_ERROR) {
-                        // Received one of the known connection errors
-                        // The remote camera device cannot be connected to, so
-                        // set the local camera to the startup error state
-                        deviceImpl.setRemoteFailure(e);
-
-                        if (e.getReason() == CameraAccessException.CAMERA_DISABLED ||
-                                e.getReason() == CameraAccessException.CAMERA_DISCONNECTED ||
-                                e.getReason() == CameraAccessException.CAMERA_IN_USE) {
-                            // Per API docs, these failures call onError and throw
-                            throw e.asChecked();
-                        }
-                    } else {
-                        // Unexpected failure - rethrow
-                        throw e;
-                    }
-                } catch (RemoteException e) {
-                    // Camera service died - act as if it's a CAMERA_DISCONNECTED case
-                    CameraRuntimeException ce = new CameraRuntimeException(
-                        CameraAccessException.CAMERA_DISCONNECTED,
-                        "Camera service is currently unavailable", e);
-                    deviceImpl.setRemoteFailure(ce);
-                    throw ce.asChecked();
-                }
-
-                // TODO: factor out callback to be non-nested, then move setter to constructor
-                // For now, calling setRemoteDevice will fire initial
-                // onOpened/onUnconfigured callbacks.
-                deviceImpl.setRemoteDevice(cameraUser);
-                device = deviceImpl;
+            int id;
+            try {
+                id = Integer.parseInt(cameraId);
+            } catch (NumberFormatException e) {
+                throw new IllegalArgumentException("Expected cameraId to be numeric, but it was: "
+                        + cameraId);
             }
 
-        } catch (NumberFormatException e) {
-            throw new IllegalArgumentException("Expected cameraId to be numeric, but it was: "
-                    + cameraId);
-        } catch (CameraRuntimeException e) {
-            throw e.asChecked();
+            try {
+                if (supportsCamera2ApiLocked(cameraId)) {
+                    // Use cameraservice's cameradeviceclient implementation for HAL3.2+ devices
+                    ICameraService cameraService = CameraManagerGlobal.get().getCameraService();
+                    if (cameraService == null) {
+                        throw new ServiceSpecificException(
+                            ICameraService.ERROR_DISCONNECTED,
+                            "Camera service is currently unavailable");
+                    }
+                    cameraUser = cameraService.connectDevice(callbacks, id,
+                            mContext.getOpPackageName(), USE_CALLING_UID);
+                } else {
+                    // Use legacy camera implementation for HAL1 devices
+                    Log.i(TAG, "Using legacy camera HAL.");
+                    cameraUser = CameraDeviceUserShim.connectBinderShim(callbacks, id);
+                }
+            } catch (ServiceSpecificException e) {
+                if (e.errorCode == ICameraService.ERROR_DEPRECATED_HAL) {
+                    throw new AssertionError("Should've gone down the shim path");
+                } else if (e.errorCode == ICameraService.ERROR_CAMERA_IN_USE ||
+                        e.errorCode == ICameraService.ERROR_MAX_CAMERAS_IN_USE ||
+                        e.errorCode == ICameraService.ERROR_DISABLED ||
+                        e.errorCode == ICameraService.ERROR_DISCONNECTED ||
+                        e.errorCode == ICameraService.ERROR_INVALID_OPERATION) {
+                    // Received one of the known connection errors
+                    // The remote camera device cannot be connected to, so
+                    // set the local camera to the startup error state
+                    deviceImpl.setRemoteFailure(e);
+
+                    if (e.errorCode == ICameraService.ERROR_DISABLED ||
+                            e.errorCode == ICameraService.ERROR_DISCONNECTED ||
+                            e.errorCode == ICameraService.ERROR_CAMERA_IN_USE) {
+                        // Per API docs, these failures call onError and throw
+                        throwAsPublicException(e);
+                    }
+                } else {
+                    // Unexpected failure - rethrow
+                    throwAsPublicException(e);
+                }
+            } catch (RemoteException e) {
+                // Camera service died - act as if it's a CAMERA_DISCONNECTED case
+                ServiceSpecificException sse = new ServiceSpecificException(
+                    ICameraService.ERROR_DISCONNECTED,
+                    "Camera service is currently unavailable");
+                deviceImpl.setRemoteFailure(sse);
+                throwAsPublicException(sse);
+            }
+
+            // TODO: factor out callback to be non-nested, then move setter to constructor
+            // For now, calling setRemoteDevice will fire initial
+            // onOpened/onUnconfigured callbacks.
+            // This function call may post onDisconnected and throw CAMERA_DISCONNECTED if
+            // cameraUser dies during setup.
+            deviceImpl.setRemoteDevice(cameraUser);
+            device = deviceImpl;
         }
+
         return device;
     }
 
@@ -602,6 +595,56 @@
     }
 
     /**
+     * Convert ServiceSpecificExceptions and Binder RemoteExceptions from camera binder interfaces
+     * into the correct public exceptions.
+     *
+     * @hide
+     */
+    public static void throwAsPublicException(Throwable t) throws CameraAccessException {
+        if (t instanceof ServiceSpecificException) {
+            ServiceSpecificException e = (ServiceSpecificException) t;
+            int reason = CameraAccessException.CAMERA_ERROR;
+            switch(e.errorCode) {
+                case ICameraService.ERROR_DISCONNECTED:
+                    reason = CameraAccessException.CAMERA_DISCONNECTED;
+                    break;
+                case ICameraService.ERROR_DISABLED:
+                    reason = CameraAccessException.CAMERA_DISABLED;
+                    break;
+                case ICameraService.ERROR_CAMERA_IN_USE:
+                    reason = CameraAccessException.CAMERA_IN_USE;
+                    break;
+                case ICameraService.ERROR_MAX_CAMERAS_IN_USE:
+                    reason = CameraAccessException.MAX_CAMERAS_IN_USE;
+                    break;
+                case ICameraService.ERROR_DEPRECATED_HAL:
+                    reason = CameraAccessException.CAMERA_DEPRECATED_HAL;
+                    break;
+                case ICameraService.ERROR_ILLEGAL_ARGUMENT:
+                case ICameraService.ERROR_ALREADY_EXISTS:
+                    throw new IllegalArgumentException(e.getMessage(), e);
+                case ICameraService.ERROR_PERMISSION_DENIED:
+                    throw new SecurityException(e.getMessage(), e);
+                case ICameraService.ERROR_TIMED_OUT:
+                case ICameraService.ERROR_INVALID_OPERATION:
+                default:
+                    reason = CameraAccessException.CAMERA_ERROR;
+            }
+            throw new CameraAccessException(reason, e.getMessage(), e);
+        } else if (t instanceof DeadObjectException) {
+            throw new CameraAccessException(CameraAccessException.CAMERA_DISCONNECTED,
+                    "Camera service has died unexpectedly",
+                    t);
+        } else if (t instanceof RemoteException) {
+            throw new UnsupportedOperationException("An unknown RemoteException was thrown" +
+                    " which should never happen.", t);
+        } else if (t instanceof RuntimeException) {
+            RuntimeException e = (RuntimeException) t;
+            throw e;
+        }
+    }
+
+    /**
      * Return or create the list of currently connected camera devices.
      *
      * <p>In case of errors connecting to the camera service, will return an empty list.</p>
@@ -619,34 +662,32 @@
 
             try {
                 numCameras = cameraService.getNumberOfCameras(CAMERA_TYPE_ALL);
-            } catch(CameraRuntimeException e) {
-                throw e.asChecked();
+            } catch(ServiceSpecificException e) {
+                throwAsPublicException(e);
             } catch (RemoteException e) {
                 // camera service just died - if no camera service, then no devices
                 return deviceIdList;
             }
 
-            CameraMetadataNative info = new CameraMetadataNative();
             for (int i = 0; i < numCameras; ++i) {
                 // Non-removable cameras use integers starting at 0 for their
                 // identifiers
                 boolean isDeviceSupported = false;
                 try {
-                    cameraService.getCameraCharacteristics(i, info);
+                    CameraMetadataNative info = cameraService.getCameraCharacteristics(i);
                     if (!info.isEmpty()) {
                         isDeviceSupported = true;
                     } else {
                         throw new AssertionError("Expected to get non-empty characteristics");
                     }
-                } catch(IllegalArgumentException  e) {
-                    // Got a BAD_VALUE from service, meaning that this
-                    // device is not supported.
-                } catch(CameraRuntimeException e) {
+                } catch(ServiceSpecificException e) {
                     // DISCONNECTED means that the HAL reported an low-level error getting the
-                    // device info; skip listing the device.  Other errors,
+                    // device info; ILLEGAL_ARGUMENT means that this devices is not supported.
+                    // Skip listing the device.  Other errors,
                     // propagate exception onward
-                    if (e.getReason() != CameraAccessException.CAMERA_DISCONNECTED) {
-                        throw e.asChecked();
+                    if (e.errorCode != ICameraService.ERROR_DISCONNECTED ||
+                            e.errorCode != ICameraService.ERROR_ILLEGAL_ARGUMENT) {
+                        throwAsPublicException(e);
                     }
                 } catch(RemoteException e) {
                     // Camera service died - no devices to list
@@ -699,17 +740,7 @@
             // If no camera service, no support
             if (cameraService == null) return false;
 
-            int res = cameraService.supportsCameraApi(id, apiVersion);
-
-            if (res != CameraServiceBinderDecorator.NO_ERROR) {
-                throw new AssertionError("Unexpected value " + res);
-            }
-            return true;
-        } catch (CameraRuntimeException e) {
-            if (e.getReason() != CameraAccessException.CAMERA_DEPRECATED_HAL) {
-                throw e;
-            }
-            // API level is not supported
+            return cameraService.supportsCameraApi(id, apiVersion);
         } catch (RemoteException e) {
             // Camera service is now down, no support for any API level
         }
@@ -737,21 +768,6 @@
          */
         private static final String CAMERA_SERVICE_BINDER_NAME = "media.camera";
 
-        // Keep up-to-date with ICameraServiceListener.h
-
-        // Device physically unplugged
-        public static final int STATUS_NOT_PRESENT = 0;
-        // Device physically has been plugged in
-        // and the camera can be used exclusively
-        public static final int STATUS_PRESENT = 1;
-        // Device physically has been plugged in
-        // but it will not be connect-able until enumeration is complete
-        public static final int STATUS_ENUMERATING = 2;
-        // Camera is in use by another app and cannot be used exclusively
-        public static final int STATUS_NOT_AVAILABLE = 0x80000000;
-
-        // End enums shared with ICameraServiceListener.h
-
         // Camera ID -> Status map
         private final ArrayMap<String, Integer> mDeviceStatus = new ArrayMap<String, Integer>();
 
@@ -759,17 +775,6 @@
         private final ArrayMap<AvailabilityCallback, Handler> mCallbackMap =
             new ArrayMap<AvailabilityCallback, Handler>();
 
-        // Keep up-to-date with ICameraServiceListener.h
-
-        // torch mode has become not available to set via setTorchMode().
-        public static final int TORCH_STATUS_NOT_AVAILABLE = 0;
-        // torch mode is off and available to be turned on via setTorchMode().
-        public static final int TORCH_STATUS_AVAILABLE_OFF = 1;
-        // torch mode is on and available to be turned off via setTorchMode().
-        public static final int TORCH_STATUS_AVAILABLE_ON = 2;
-
-        // End enums shared with ICameraServiceListener.h
-
         // torch client binder to set the torch mode with.
         private Binder mTorchClientBinder = new Binder();
 
@@ -839,29 +844,20 @@
                 return;
             }
 
-            ICameraService cameraServiceRaw = ICameraService.Stub.asInterface(cameraServiceBinder);
-
-            /**
-             * Wrap the camera service in a decorator which automatically translates return codes
-             * into exceptions.
-             */
-            ICameraService cameraService =
-                CameraServiceBinderDecorator.newInstance(cameraServiceRaw);
+            ICameraService cameraService = ICameraService.Stub.asInterface(cameraServiceBinder);
 
             try {
-                CameraServiceBinderDecorator.throwOnError(
-                        CameraMetadataNative.nativeSetupGlobalVendorTagDescriptor());
-            } catch (CameraRuntimeException e) {
-                handleRecoverableSetupErrors(e, "Failed to set up vendor tags");
+                CameraMetadataNative.setupGlobalVendorTagDescriptor();
+            } catch (ServiceSpecificException e) {
+                handleRecoverableSetupErrors(e);
             }
 
             try {
                 cameraService.addListener(this);
                 mCameraService = cameraService;
-            } catch(CameraRuntimeException e) {
+            } catch(ServiceSpecificException e) {
                 // Unexpected failure
-                throw new IllegalStateException("Failed to register a camera service listener",
-                        e.asChecked());
+                throw new IllegalStateException("Failed to register a camera service listener", e);
             } catch (RemoteException e) {
                 // Camera service is now down, leave mCameraService as null
             }
@@ -881,16 +877,9 @@
                 }
 
                 try {
-                    int status = cameraService.setTorchMode(cameraId, enabled, mTorchClientBinder);
-                } catch(CameraRuntimeException e) {
-                    int problem = e.getReason();
-                    switch (problem) {
-                        case CameraAccessException.CAMERA_ERROR:
-                            throw new IllegalArgumentException(
-                                    "the camera device doesn't have a flash unit.");
-                        default:
-                            throw e.asChecked();
-                    }
+                    cameraService.setTorchMode(cameraId, enabled, mTorchClientBinder);
+                } catch(ServiceSpecificException e) {
+                    throwAsPublicException(e);
                 } catch (RemoteException e) {
                     throw new CameraAccessException(CameraAccessException.CAMERA_DISCONNECTED,
                             "Camera service is currently unavailable");
@@ -898,21 +887,19 @@
             }
         }
 
-        private void handleRecoverableSetupErrors(CameraRuntimeException e, String msg) {
-            int problem = e.getReason();
-            switch (problem) {
-                case CameraAccessException.CAMERA_DISCONNECTED:
-                    String errorMsg = CameraAccessException.getDefaultMessage(problem);
-                    Log.w(TAG, msg + ": " + errorMsg);
+        private void handleRecoverableSetupErrors(ServiceSpecificException e) {
+            switch (e.errorCode) {
+                case ICameraService.ERROR_DISCONNECTED:
+                    Log.w(TAG, e.getMessage());
                     break;
                 default:
-                    throw new IllegalStateException(msg, e.asChecked());
+                    throw new IllegalStateException(e);
             }
         }
 
         private boolean isAvailable(int status) {
             switch (status) {
-                case STATUS_PRESENT:
+                case ICameraServiceListener.STATUS_PRESENT:
                     return true;
                 default:
                     return false;
@@ -921,10 +908,10 @@
 
         private boolean validStatus(int status) {
             switch (status) {
-                case STATUS_NOT_PRESENT:
-                case STATUS_PRESENT:
-                case STATUS_ENUMERATING:
-                case STATUS_NOT_AVAILABLE:
+                case ICameraServiceListener.STATUS_NOT_PRESENT:
+                case ICameraServiceListener.STATUS_PRESENT:
+                case ICameraServiceListener.STATUS_ENUMERATING:
+                case ICameraServiceListener.STATUS_NOT_AVAILABLE:
                     return true;
                 default:
                     return false;
@@ -933,9 +920,9 @@
 
         private boolean validTorchStatus(int status) {
             switch (status) {
-                case TORCH_STATUS_NOT_AVAILABLE:
-                case TORCH_STATUS_AVAILABLE_ON:
-                case TORCH_STATUS_AVAILABLE_OFF:
+                case ICameraServiceListener.TORCH_STATUS_NOT_AVAILABLE:
+                case ICameraServiceListener.TORCH_STATUS_AVAILABLE_ON:
+                case ICameraServiceListener.TORCH_STATUS_AVAILABLE_OFF:
                     return true;
                 default:
                     return false;
@@ -966,14 +953,14 @@
         private void postSingleTorchUpdate(final TorchCallback callback, final Handler handler,
                 final String id, final int status) {
             switch(status) {
-                case TORCH_STATUS_AVAILABLE_ON:
-                case TORCH_STATUS_AVAILABLE_OFF:
+                case ICameraServiceListener.TORCH_STATUS_AVAILABLE_ON:
+                case ICameraServiceListener.TORCH_STATUS_AVAILABLE_OFF:
                     handler.post(
                             new Runnable() {
                                 @Override
                                 public void run() {
                                     callback.onTorchModeChanged(id, status ==
-                                            TORCH_STATUS_AVAILABLE_ON);
+                                            ICameraServiceListener.TORCH_STATUS_AVAILABLE_ON);
                                 }
                             });
                     break;
@@ -1220,11 +1207,12 @@
                 // and torch statuses will be updated.
                 for (int i = 0; i < mDeviceStatus.size(); i++) {
                     String cameraId = mDeviceStatus.keyAt(i);
-                    onStatusChangedLocked(STATUS_NOT_PRESENT, cameraId);
+                    onStatusChangedLocked(ICameraServiceListener.STATUS_NOT_PRESENT, cameraId);
                 }
                 for (int i = 0; i < mTorchStatus.size(); i++) {
                     String cameraId = mTorchStatus.keyAt(i);
-                    onTorchStatusChangedLocked(TORCH_STATUS_NOT_AVAILABLE, cameraId);
+                    onTorchStatusChangedLocked(ICameraServiceListener.TORCH_STATUS_NOT_AVAILABLE,
+                            cameraId);
                 }
 
                 scheduleCameraServiceReconnectionLocked();
diff --git a/core/java/android/hardware/camera2/CameraMetadata.java b/core/java/android/hardware/camera2/CameraMetadata.java
index d58ad22..4add962 100644
--- a/core/java/android/hardware/camera2/CameraMetadata.java
+++ b/core/java/android/hardware/camera2/CameraMetadata.java
@@ -2070,6 +2070,24 @@
      */
     public static final int CONTROL_SCENE_MODE_FACE_PRIORITY_LOW_LIGHT = 19;
 
+    /**
+     * <p>Scene mode values within the range of
+     * <code>[DEVICE_CUSTOM_START, DEVICE_CUSTOM_END]</code> are reserved for device specific
+     * customized scene modes.</p>
+     * @see CaptureRequest#CONTROL_SCENE_MODE
+     * @hide
+     */
+    public static final int CONTROL_SCENE_MODE_DEVICE_CUSTOM_START = 100;
+
+    /**
+     * <p>Scene mode values within the range of
+     * <code>[DEVICE_CUSTOM_START, DEVICE_CUSTOM_END]</code> are reserved for device specific
+     * customized scene modes.</p>
+     * @see CaptureRequest#CONTROL_SCENE_MODE
+     * @hide
+     */
+    public static final int CONTROL_SCENE_MODE_DEVICE_CUSTOM_END = 127;
+
     //
     // Enumeration values for CaptureRequest#CONTROL_VIDEO_STABILIZATION_MODE
     //
diff --git a/core/java/android/hardware/camera2/CaptureRequest.aidl b/core/java/android/hardware/camera2/CaptureRequest.aidl
deleted file mode 100644
index 0b7d5ba..0000000
--- a/core/java/android/hardware/camera2/CaptureRequest.aidl
+++ /dev/null
@@ -1,20 +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 android.hardware.camera2;
-
-/** @hide */
-parcelable CaptureRequest;
diff --git a/core/java/android/hardware/camera2/DngCreator.java b/core/java/android/hardware/camera2/DngCreator.java
index 57a080b..9478dc0 100644
--- a/core/java/android/hardware/camera2/DngCreator.java
+++ b/core/java/android/hardware/camera2/DngCreator.java
@@ -137,6 +137,11 @@
             throw new IllegalArgumentException("Orientation " + orientation +
                     " is not a valid EXIF orientation value");
         }
+        // ExifInterface and TIFF/EP spec differ on definition of
+        // "Unknown" orientation; other values map directly
+        if (orientation == ExifInterface.ORIENTATION_UNDEFINED) {
+            orientation = TAG_ORIENTATION_UNKNOWN;
+        }
         nativeSetOrientation(orientation);
         return this;
     }
@@ -443,7 +448,7 @@
     private static final String GPS_LONG_REF_WEST = "W";
 
     private static final String GPS_DATE_FORMAT_STR = "yyyy:MM:dd";
-    private static final String TIFF_DATETIME_FORMAT = "yyyy:MM:dd kk:mm:ss";
+    private static final String TIFF_DATETIME_FORMAT = "yyyy:MM:dd HH:mm:ss";
     private static final DateFormat sExifGPSDateStamp = new SimpleDateFormat(GPS_DATE_FORMAT_STR);
     private static final DateFormat sDateTimeStampFormat =
             new SimpleDateFormat(TIFF_DATETIME_FORMAT);
@@ -458,6 +463,9 @@
     private static final int DEFAULT_PIXEL_STRIDE = 2; // bytes per sample
     private static final int BYTES_PER_RGB_PIX = 3; // byts per pixel
 
+    // TIFF tag values needed to map between public API and TIFF spec
+    private static final int TAG_ORIENTATION_UNKNOWN = 9;
+
     /**
      * Offset, rowStride, and pixelStride are given in bytes.  Height and width are given in pixels.
      */
diff --git a/core/java/android/hardware/camera2/ICameraDeviceCallbacks.aidl b/core/java/android/hardware/camera2/ICameraDeviceCallbacks.aidl
deleted file mode 100644
index 151c918..0000000
--- a/core/java/android/hardware/camera2/ICameraDeviceCallbacks.aidl
+++ /dev/null
@@ -1,35 +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 android.hardware.camera2;
-
-import android.hardware.camera2.impl.CameraMetadataNative;
-import android.hardware.camera2.impl.CaptureResultExtras;
-
-/** @hide */
-interface ICameraDeviceCallbacks
-{
-    /**
-     * Keep up-to-date with frameworks/av/include/camera/camera2/ICameraDeviceCallbacks.h
-     */
-
-    oneway void onDeviceError(int errorCode, in CaptureResultExtras resultExtras);
-    oneway void onDeviceIdle();
-    oneway void onCaptureStarted(in CaptureResultExtras resultExtras, long timestamp);
-    oneway void onResultReceived(in CameraMetadataNative result,
-                                 in CaptureResultExtras resultExtras);
-    oneway void onPrepared(int streamId);
-}
diff --git a/core/java/android/hardware/camera2/ICameraDeviceUser.aidl b/core/java/android/hardware/camera2/ICameraDeviceUser.aidl
deleted file mode 100644
index c9c9abc..0000000
--- a/core/java/android/hardware/camera2/ICameraDeviceUser.aidl
+++ /dev/null
@@ -1,107 +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 android.hardware.camera2;
-
-import android.hardware.camera2.CaptureRequest;
-import android.hardware.camera2.impl.CameraMetadataNative;
-import android.hardware.camera2.params.OutputConfiguration;
-import android.hardware.camera2.utils.LongParcelable;
-import android.view.Surface;
-
-/** @hide */
-interface ICameraDeviceUser
-{
-    /**
-     * Keep up-to-date with frameworks/av/include/camera/camera2/ICameraDeviceUser.h and
-     * frameworks/base/core/java/android/hardware/camera2/legacy/CameraDeviceUserShim.java
-     */
-    void disconnect();
-
-    // ints here are status_t
-
-    // non-negative value is the requestId. negative value is status_t
-    int submitRequest(in CaptureRequest request, boolean streaming,
-                      out LongParcelable lastFrameNumber);
-
-    int submitRequestList(in List<CaptureRequest> requestList, boolean streaming,
-                          out LongParcelable lastFrameNumber);
-
-    int cancelRequest(int requestId, out LongParcelable lastFrameNumber);
-
-    /**
-     * Begin the device configuration.
-     *
-     * <p>
-     * beginConfigure must be called before any call to deleteStream, createStream,
-     * or endConfigure.  It is not valid to call this when the device is not idle.
-     * <p>
-     */
-    int beginConfigure();
-
-    /**
-     * End the device configuration.
-     *
-     * <p>
-     * endConfigure must be called after stream configuration is complete (i.e. after
-     * a call to beginConfigure and subsequent createStream/deleteStream calls).  This
-     * must be called before any requests can be submitted.
-     * <p>
-     */
-    int endConfigure(boolean isConstrainedHighSpeed);
-
-    int deleteStream(int streamId);
-
-    // non-negative value is the stream ID. negative value is status_t
-    int createStream(in OutputConfiguration outputConfiguration);
-
-    /**
-     * Create an input stream
-     *
-     * <p>Create an input stream of width, height, and format</p>
-     *
-     * @param width Width of the input buffers
-     * @param height Height of the input buffers
-     * @param format Format of the input buffers. One of HAL_PIXEL_FORMAT_*.
-     *
-     * @return stream ID if it's a non-negative value. status_t if it's a negative value.
-     */
-    int createInputStream(int width, int height, int format);
-
-    /**
-     * Get the surface of the input stream.
-     *
-     * <p>It's valid to call this method only after a stream configuration is completed
-     * successfully and the stream configuration includes a input stream.</p>
-     *
-     * @param surface An output argument for the surface of the input stream buffer queue.
-     */
-    int getInputSurface(out Surface surface);
-
-    int createDefaultRequest(int templateId, out CameraMetadataNative request);
-
-    int getCameraInfo(out CameraMetadataNative info);
-
-    int waitUntilIdle();
-
-    int flush(out LongParcelable lastFrameNumber);
-
-    int prepare(int streamId);
-
-    int tearDown(int streamId);
-
-    int prepare2(int maxCount, int streamId);
-}
diff --git a/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java b/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
index 3aba0d1..d84a6fc 100644
--- a/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
+++ b/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
@@ -33,14 +33,14 @@
 import android.hardware.camera2.params.OutputConfiguration;
 import android.hardware.camera2.params.ReprocessFormatsMap;
 import android.hardware.camera2.params.StreamConfigurationMap;
-import android.hardware.camera2.utils.CameraBinderDecorator;
-import android.hardware.camera2.utils.CameraRuntimeException;
-import android.hardware.camera2.utils.LongParcelable;
+import android.hardware.camera2.utils.SubmitInfo;
 import android.hardware.camera2.utils.SurfaceUtils;
+import android.hardware.ICameraService;
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.Looper;
 import android.os.RemoteException;
+import android.os.ServiceSpecificException;
 import android.util.Log;
 import android.util.Range;
 import android.util.Size;
@@ -63,14 +63,15 @@
 /**
  * HAL2.1+ implementation of CameraDevice. Use CameraManager#open to instantiate
  */
-public class CameraDeviceImpl extends CameraDevice {
+public class CameraDeviceImpl extends CameraDevice
+        implements IBinder.DeathRecipient {
     private final String TAG;
     private final boolean DEBUG = false;
 
     private static final int REQUEST_ID_NONE = -1;
 
     // TODO: guard every function with if (!mRemoteDevice) check (if it was closed)
-    private ICameraDeviceUser mRemoteDevice;
+    private ICameraDeviceUserWrapper mRemoteDevice;
 
     // Lock to synchronize cross-thread access to device public interface
     final Object mInterfaceLock = new Object(); // access from this class and Session only!
@@ -261,13 +262,34 @@
         return mCallbacks;
     }
 
-    public void setRemoteDevice(ICameraDeviceUser remoteDevice) {
+    /**
+     * Set remote device, which triggers initial onOpened/onUnconfigured callbacks
+     *
+     * <p>This function may post onDisconnected and throw CAMERA_DISCONNECTED if remoteDevice dies
+     * during setup.</p>
+     *
+     */
+    public void setRemoteDevice(ICameraDeviceUser remoteDevice) throws CameraAccessException {
         synchronized(mInterfaceLock) {
             // TODO: Move from decorator to direct binder-mediated exceptions
             // If setRemoteFailure already called, do nothing
             if (mInError) return;
 
-            mRemoteDevice = CameraBinderDecorator.newInstance(remoteDevice);
+            mRemoteDevice = new ICameraDeviceUserWrapper(remoteDevice);
+
+            IBinder remoteDeviceBinder = remoteDevice.asBinder();
+            // For legacy camera device, remoteDevice is in the same process, and
+            // asBinder returns NULL.
+            if (remoteDeviceBinder != null) {
+                try {
+                    remoteDeviceBinder.linkToDeath(this, /*flag*/ 0);
+                } catch (RemoteException e) {
+                    CameraDeviceImpl.this.mDeviceHandler.post(mCallOnDisconnected);
+
+                    throw new CameraAccessException(CameraAccessException.CAMERA_DISCONNECTED,
+                            "The camera device has encountered a serious error");
+                }
+            }
 
             mDeviceHandler.post(mCallOnOpened);
             mDeviceHandler.post(mCallOnUnconfigured);
@@ -280,28 +302,29 @@
      * <p>This places the camera device in the error state and informs the callback.
      * Use in place of setRemoteDevice() when startup fails.</p>
      */
-    public void setRemoteFailure(final CameraRuntimeException failure) {
+    public void setRemoteFailure(final ServiceSpecificException failure) {
         int failureCode = StateCallback.ERROR_CAMERA_DEVICE;
         boolean failureIsError = true;
 
-        switch (failure.getReason()) {
-            case CameraAccessException.CAMERA_IN_USE:
+        switch (failure.errorCode) {
+            case ICameraService.ERROR_CAMERA_IN_USE:
                 failureCode = StateCallback.ERROR_CAMERA_IN_USE;
                 break;
-            case CameraAccessException.MAX_CAMERAS_IN_USE:
+            case ICameraService.ERROR_MAX_CAMERAS_IN_USE:
                 failureCode = StateCallback.ERROR_MAX_CAMERAS_IN_USE;
                 break;
-            case CameraAccessException.CAMERA_DISABLED:
+            case ICameraService.ERROR_DISABLED:
                 failureCode = StateCallback.ERROR_CAMERA_DISABLED;
                 break;
-            case CameraAccessException.CAMERA_DISCONNECTED:
+            case ICameraService.ERROR_DISCONNECTED:
                 failureIsError = false;
                 break;
-            case CameraAccessException.CAMERA_ERROR:
+            case ICameraService.ERROR_INVALID_OPERATION:
                 failureCode = StateCallback.ERROR_CAMERA_DEVICE;
                 break;
             default:
-                Log.wtf(TAG, "Unknown failure in opening camera device: " + failure.getReason());
+                Log.e(TAG, "Unexpected failure in opening camera device: " + failure.errorCode +
+                        failure.getMessage());
                 break;
         }
         final int code = failureCode;
@@ -430,27 +453,20 @@
                     }
                 }
 
-                try {
-                    mRemoteDevice.endConfigure(isConstrainedHighSpeed);
-                }
-                catch (IllegalArgumentException e) {
-                    // OK. camera service can reject stream config if it's not supported by HAL
-                    // This is only the result of a programmer misusing the camera2 api.
-                    Log.w(TAG, "Stream configuration failed");
-                    return false;
-                }
+                mRemoteDevice.endConfigure(isConstrainedHighSpeed);
 
                 success = true;
-            } catch (CameraRuntimeException e) {
-                if (e.getReason() == CAMERA_IN_USE) {
-                    throw new IllegalStateException("The camera is currently busy." +
-                            " You must wait until the previous operation completes.");
-                }
-
-                throw e.asChecked();
-            } catch (RemoteException e) {
-                // impossible
+            } catch (IllegalArgumentException e) {
+                // OK. camera service can reject stream config if it's not supported by HAL
+                // This is only the result of a programmer misusing the camera2 api.
+                Log.w(TAG, "Stream configuration failed due to: " + e.getMessage());
                 return false;
+            } catch (CameraAccessException e) {
+                if (e.getReason() == CameraAccessException.CAMERA_IN_USE) {
+                    throw new IllegalStateException("The camera is currently busy." +
+                            " You must wait until the previous operation completes.", e);
+                }
+                throw e;
             } finally {
                 if (success && outputs.size() > 0) {
                     mDeviceHandler.post(mCallOnIdle);
@@ -594,12 +610,7 @@
                 configureSuccess = configureStreamsChecked(inputConfig, outputConfigurations,
                         isConstrainedHighSpeed);
                 if (configureSuccess == true && inputConfig != null) {
-                    input = new Surface();
-                    try {
-                        mRemoteDevice.getInputSurface(/*out*/input);
-                    } catch (CameraRuntimeException e) {
-                        e.asChecked();
-                    }
+                    input = mRemoteDevice.getInputSurface();
                 }
             } catch (CameraAccessException e) {
                 configureSuccess = false;
@@ -608,9 +619,6 @@
                 if (DEBUG) {
                     Log.v(TAG, "createCaptureSession - failed with exception ", e);
                 }
-            } catch (RemoteException e) {
-                // impossible
-                return;
             }
 
             List<Surface> outSurfaces = new ArrayList<>(outputConfigurations.size());
@@ -655,16 +663,9 @@
         synchronized(mInterfaceLock) {
             checkIfCameraClosedOrInError();
 
-            CameraMetadataNative templatedRequest = new CameraMetadataNative();
+            CameraMetadataNative templatedRequest = null;
 
-            try {
-                mRemoteDevice.createDefaultRequest(templateType, /*out*/templatedRequest);
-            } catch (CameraRuntimeException e) {
-                throw e.asChecked();
-            } catch (RemoteException e) {
-                // impossible
-                return null;
-            }
+            templatedRequest = mRemoteDevice.createDefaultRequest(templateType);
 
             CaptureRequest.Builder builder = new CaptureRequest.Builder(
                     templatedRequest, /*reprocess*/false, CameraCaptureSession.SESSION_ID_NONE);
@@ -701,14 +702,8 @@
             if (streamId == -1) {
                 throw new IllegalArgumentException("Surface is not part of this session");
             }
-            try {
-                mRemoteDevice.prepare(streamId);
-            } catch (CameraRuntimeException e) {
-                throw e.asChecked();
-            } catch (RemoteException e) {
-                // impossible
-                return;
-            }
+
+            mRemoteDevice.prepare(streamId);
         }
     }
 
@@ -728,14 +723,8 @@
             if (streamId == -1) {
                 throw new IllegalArgumentException("Surface is not part of this session");
             }
-            try {
-                mRemoteDevice.prepare2(maxCount, streamId);
-            } catch (CameraRuntimeException e) {
-                throw e.asChecked();
-            } catch (RemoteException e) {
-                // impossible
-                return;
-            }
+
+            mRemoteDevice.prepare2(maxCount, streamId);
         }
     }
 
@@ -753,14 +742,8 @@
             if (streamId == -1) {
                 throw new IllegalArgumentException("Surface is not part of this session");
             }
-            try {
-                mRemoteDevice.tearDown(streamId);
-            } catch (CameraRuntimeException e) {
-                throw e.asChecked();
-            } catch (RemoteException e) {
-                // impossible
-                return;
-            }
+
+            mRemoteDevice.tearDown(streamId);
         }
     }
 
@@ -875,45 +858,37 @@
 
         synchronized(mInterfaceLock) {
             checkIfCameraClosedOrInError();
-            int requestId;
-
             if (repeating) {
                 stopRepeating();
             }
 
-            LongParcelable lastFrameNumberRef = new LongParcelable();
-            try {
-                requestId = mRemoteDevice.submitRequestList(requestList, repeating,
-                        /*out*/lastFrameNumberRef);
-                if (DEBUG) {
-                    Log.v(TAG, "last frame number " + lastFrameNumberRef.getNumber());
-                }
-            } catch (CameraRuntimeException e) {
-                throw e.asChecked();
-            } catch (RemoteException e) {
-                // impossible
-                return -1;
+            SubmitInfo requestInfo;
+
+            CaptureRequest[] requestArray = requestList.toArray(new CaptureRequest[requestList.size()]);
+            requestInfo = mRemoteDevice.submitRequestList(requestArray, repeating);
+            if (DEBUG) {
+                Log.v(TAG, "last frame number " + requestInfo.getLastFrameNumber());
             }
 
             if (callback != null) {
-                mCaptureCallbackMap.put(requestId, new CaptureCallbackHolder(callback,
-                        requestList, handler, repeating, mNextSessionId - 1));
+                mCaptureCallbackMap.put(requestInfo.getRequestId(),
+                        new CaptureCallbackHolder(
+                            callback, requestList, handler, repeating, mNextSessionId - 1));
             } else {
                 if (DEBUG) {
-                    Log.d(TAG, "Listen for request " + requestId + " is null");
+                    Log.d(TAG, "Listen for request " + requestInfo.getRequestId() + " is null");
                 }
             }
 
-            long lastFrameNumber = lastFrameNumberRef.getNumber();
-
             if (repeating) {
                 if (mRepeatingRequestId != REQUEST_ID_NONE) {
-                    checkEarlyTriggerSequenceComplete(mRepeatingRequestId, lastFrameNumber);
+                    checkEarlyTriggerSequenceComplete(mRepeatingRequestId,
+                            requestInfo.getLastFrameNumber());
                 }
-                mRepeatingRequestId = requestId;
+                mRepeatingRequestId = requestInfo.getRequestId();
             } else {
-                mRequestLastFrameNumbersList.add(new RequestLastFrameNumbersHolder(requestList,
-                        requestId, lastFrameNumber));
+                mRequestLastFrameNumbersList.add(
+                    new RequestLastFrameNumbersHolder(requestList, requestInfo));
             }
 
             if (mIdle) {
@@ -921,7 +896,7 @@
             }
             mIdle = false;
 
-            return requestId;
+            return requestInfo.getRequestId();
         }
     }
 
@@ -949,19 +924,9 @@
                 int requestId = mRepeatingRequestId;
                 mRepeatingRequestId = REQUEST_ID_NONE;
 
-                try {
-                    LongParcelable lastFrameNumberRef = new LongParcelable();
-                    mRemoteDevice.cancelRequest(requestId, /*out*/lastFrameNumberRef);
-                    long lastFrameNumber = lastFrameNumberRef.getNumber();
+                long lastFrameNumber = mRemoteDevice.cancelRequest(requestId);
 
-                    checkEarlyTriggerSequenceComplete(requestId, lastFrameNumber);
-
-                } catch (CameraRuntimeException e) {
-                    throw e.asChecked();
-                } catch (RemoteException e) {
-                    // impossible
-                    return;
-                }
+                checkEarlyTriggerSequenceComplete(requestId, lastFrameNumber);
             }
         }
     }
@@ -974,14 +939,8 @@
             if (mRepeatingRequestId != REQUEST_ID_NONE) {
                 throw new IllegalStateException("Active repeating request ongoing");
             }
-            try {
-                mRemoteDevice.waitUntilIdle();
-            } catch (CameraRuntimeException e) {
-                throw e.asChecked();
-            } catch (RemoteException e) {
-                // impossible
-                return;
-            }
+
+            mRemoteDevice.waitUntilIdle();
         }
     }
 
@@ -997,19 +956,11 @@
                 mDeviceHandler.post(mCallOnIdle);
                 return;
             }
-            try {
-                LongParcelable lastFrameNumberRef = new LongParcelable();
-                mRemoteDevice.flush(/*out*/lastFrameNumberRef);
-                if (mRepeatingRequestId != REQUEST_ID_NONE) {
-                    long lastFrameNumber = lastFrameNumberRef.getNumber();
-                    checkEarlyTriggerSequenceComplete(mRepeatingRequestId, lastFrameNumber);
-                    mRepeatingRequestId = REQUEST_ID_NONE;
-                }
-            } catch (CameraRuntimeException e) {
-                throw e.asChecked();
-            } catch (RemoteException e) {
-                // impossible
-                return;
+
+            long lastFrameNumber = mRemoteDevice.flush();
+            if (mRepeatingRequestId != REQUEST_ID_NONE) {
+                checkEarlyTriggerSequenceComplete(mRepeatingRequestId, lastFrameNumber);
+                mRepeatingRequestId = REQUEST_ID_NONE;
             }
         }
     }
@@ -1021,14 +972,8 @@
                 return;
             }
 
-            try {
-                if (mRemoteDevice != null) {
-                    mRemoteDevice.disconnect();
-                }
-            } catch (CameraRuntimeException e) {
-                Log.e(TAG, "Exception while closing: ", e.asChecked());
-            } catch (RemoteException e) {
-                // impossible
+            if (mRemoteDevice != null) {
+                mRemoteDevice.disconnect();
             }
 
             // Only want to fire the onClosed callback once;
@@ -1171,6 +1116,11 @@
                 int sequenceId) {
             // default empty implementation
         }
+
+        public void onCaptureBufferLost(CameraDevice camera,
+                CaptureRequest request, Surface target, long frameNumber) {
+            // default empty implementation
+        }
     }
 
     /**
@@ -1297,14 +1247,14 @@
          * Create a request-last-frame-numbers holder with a list of requests, request ID, and
          * the last frame number returned by camera service.
          */
-        public RequestLastFrameNumbersHolder(List<CaptureRequest> requestList, int requestId,
-                long lastFrameNumber) {
+        public RequestLastFrameNumbersHolder(List<CaptureRequest> requestList, SubmitInfo requestInfo) {
             long lastRegularFrameNumber = CaptureCallback.NO_FRAMES_CAPTURED;
             long lastReprocessFrameNumber = CaptureCallback.NO_FRAMES_CAPTURED;
-            long frameNumber = lastFrameNumber;
+            long frameNumber = requestInfo.getLastFrameNumber();
 
-            if (lastFrameNumber < requestList.size() - 1) {
-                throw new IllegalArgumentException("lastFrameNumber: " + lastFrameNumber +
+            if (requestInfo.getLastFrameNumber() < requestList.size() - 1) {
+                throw new IllegalArgumentException(
+                        "lastFrameNumber: " + requestInfo.getLastFrameNumber() +
                         " should be at least " + (requestList.size() - 1) + " for the number of " +
                         " requests in the list: " + requestList.size());
             }
@@ -1330,7 +1280,7 @@
 
             mLastRegularFrameNumber = lastRegularFrameNumber;
             mLastReprocessFrameNumber = lastReprocessFrameNumber;
-            mRequestId = requestId;
+            mRequestId = requestInfo.getRequestId();
         }
 
         /**
@@ -1942,48 +1892,66 @@
 
             final CaptureRequest request = holder.getRequest(subsequenceId);
 
-            // No way to report buffer errors right now
+            Runnable failureDispatch = null;
             if (errorCode == ERROR_CAMERA_BUFFER) {
-                Log.e(TAG, String.format("Lost output buffer reported for frame %d", frameNumber));
-                return;
-            }
-
-            boolean mayHaveBuffers = (errorCode == ERROR_CAMERA_RESULT);
-
-            // This is only approximate - exact handling needs the camera service and HAL to
-            // disambiguate between request failures to due abort and due to real errors.
-            // For now, assume that if the session believes we're mid-abort, then the error
-            // is due to abort.
-            int reason = (mCurrentSession != null && mCurrentSession.isAborting()) ?
-                    CaptureFailure.REASON_FLUSHED :
-                    CaptureFailure.REASON_ERROR;
-
-            final CaptureFailure failure = new CaptureFailure(
-                request,
-                reason,
-                /*dropped*/ mayHaveBuffers,
-                requestId,
-                frameNumber);
-
-            Runnable failureDispatch = new Runnable() {
-                @Override
-                public void run() {
-                    if (!CameraDeviceImpl.this.isClosed()){
-                        holder.getCallback().onCaptureFailed(
-                            CameraDeviceImpl.this,
-                            request,
-                            failure);
-                    }
+                final Surface outputSurface =
+                        mConfiguredOutputs.get(resultExtras.getErrorStreamId()).getSurface();
+                if (DEBUG) {
+                    Log.v(TAG, String.format("Lost output buffer reported for frame %d, target %s",
+                            frameNumber, outputSurface));
                 }
-            };
-            holder.getHandler().post(failureDispatch);
+                failureDispatch = new Runnable() {
+                    @Override
+                    public void run() {
+                        if (!CameraDeviceImpl.this.isClosed()){
+                            holder.getCallback().onCaptureBufferLost(
+                                CameraDeviceImpl.this,
+                                request,
+                                outputSurface,
+                                frameNumber);
+                        }
+                    }
+                };
+            } else {
+                boolean mayHaveBuffers = (errorCode == ERROR_CAMERA_RESULT);
 
-            // Fire onCaptureSequenceCompleted if appropriate
-            if (DEBUG) {
-                Log.v(TAG, String.format("got error frame %d", frameNumber));
+                // This is only approximate - exact handling needs the camera service and HAL to
+                // disambiguate between request failures to due abort and due to real errors.  For
+                // now, assume that if the session believes we're mid-abort, then the error is due
+                // to abort.
+                int reason = (mCurrentSession != null && mCurrentSession.isAborting()) ?
+                        CaptureFailure.REASON_FLUSHED :
+                        CaptureFailure.REASON_ERROR;
+
+                final CaptureFailure failure = new CaptureFailure(
+                    request,
+                    reason,
+                    /*dropped*/ mayHaveBuffers,
+                    requestId,
+                    frameNumber);
+
+                failureDispatch = new Runnable() {
+                    @Override
+                    public void run() {
+                        if (!CameraDeviceImpl.this.isClosed()){
+                            holder.getCallback().onCaptureFailed(
+                                CameraDeviceImpl.this,
+                                request,
+                                failure);
+                        }
+                    }
+                };
+
+                // Fire onCaptureSequenceCompleted if appropriate
+                if (DEBUG) {
+                    Log.v(TAG, String.format("got error frame %d", frameNumber));
+                }
+                mFrameNumberTracker.updateTracker(frameNumber, /*error*/true, request.isReprocess());
+                checkAndFireSequenceComplete();
             }
-            mFrameNumberTracker.updateTracker(frameNumber, /*error*/true, request.isReprocess());
-            checkAndFireSequenceComplete();
+
+            // Dispatch the failure callback
+            holder.getHandler().post(failureDispatch);
         }
 
     } // public class CameraDeviceCallbacks
@@ -2039,4 +2007,28 @@
         return mCharacteristics;
     }
 
+    /**
+     * Listener for binder death.
+     *
+     * <p> Handle binder death for ICameraDeviceUser. Trigger onError.</p>
+     */
+    public void binderDied() {
+        Log.w(TAG, "CameraDevice " + mCameraId + " died unexpectedly");
+
+        if (mRemoteDevice == null) {
+            return; // Camera already closed
+        }
+
+        mInError = true;
+        Runnable r = new Runnable() {
+            @Override
+            public void run() {
+                if (!isClosed()) {
+                    mDeviceCallback.onError(CameraDeviceImpl.this,
+                            CameraDeviceCallbacks.ERROR_CAMERA_SERVICE);
+                }
+            }
+        };
+        CameraDeviceImpl.this.mDeviceHandler.post(r);
+    }
 }
diff --git a/core/java/android/hardware/camera2/impl/CameraMetadataNative.aidl b/core/java/android/hardware/camera2/impl/CameraMetadataNative.aidl
deleted file mode 100644
index 4a89129..0000000
--- a/core/java/android/hardware/camera2/impl/CameraMetadataNative.aidl
+++ /dev/null
@@ -1,20 +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 android.hardware.camera2.impl;
-
-/** @hide */
-parcelable CameraMetadataNative;
diff --git a/core/java/android/hardware/camera2/impl/CameraMetadataNative.java b/core/java/android/hardware/camera2/impl/CameraMetadataNative.java
index 12a2910..79eac26 100644
--- a/core/java/android/hardware/camera2/impl/CameraMetadataNative.java
+++ b/core/java/android/hardware/camera2/impl/CameraMetadataNative.java
@@ -58,6 +58,7 @@
 import android.location.LocationManager;
 import android.os.Parcelable;
 import android.os.Parcel;
+import android.os.ServiceSpecificException;
 import android.util.Log;
 import android.util.Size;
 
@@ -363,13 +364,24 @@
      * Set the global client-side vendor tag descriptor to allow use of vendor
      * tags in camera applications.
      *
-     * @return int A native status_t value corresponding to one of the
-     * {@link CameraBinderDecorator} integer constants.
-     * @see CameraBinderDecorator#throwOnError
-     *
+     * @throws ServiceSpecificException
      * @hide
      */
-    public static native int nativeSetupGlobalVendorTagDescriptor();
+    public static void setupGlobalVendorTagDescriptor() throws ServiceSpecificException {
+        int err = nativeSetupGlobalVendorTagDescriptor();
+        if (err != 0) {
+            throw new ServiceSpecificException(err, "Failure to set up global vendor tags");
+        }
+    }
+
+    /**
+     * Set the global client-side vendor tag descriptor to allow use of vendor
+     * tags in camera applications.
+     *
+     * @return int An error code corresponding to one of the
+     * {@link ICameraService} error constants, or 0 on success.
+     */
+    private static native int nativeSetupGlobalVendorTagDescriptor();
 
     /**
      * Set a camera metadata field to a value. The field definitions can be
diff --git a/core/java/android/hardware/camera2/impl/CaptureResultExtras.aidl b/core/java/android/hardware/camera2/impl/CaptureResultExtras.aidl
deleted file mode 100644
index ebc812a..0000000
--- a/core/java/android/hardware/camera2/impl/CaptureResultExtras.aidl
+++ /dev/null
@@ -1,20 +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.hardware.camera2.impl;
-
-/** @hide */
-parcelable CaptureResultExtras;
diff --git a/core/java/android/hardware/camera2/impl/CaptureResultExtras.java b/core/java/android/hardware/camera2/impl/CaptureResultExtras.java
index d859da7..40535e2 100644
--- a/core/java/android/hardware/camera2/impl/CaptureResultExtras.java
+++ b/core/java/android/hardware/camera2/impl/CaptureResultExtras.java
@@ -28,6 +28,7 @@
     private int precaptureTriggerId;
     private long frameNumber;
     private int partialResultCount;
+    private int errorStreamId;
 
     public static final Parcelable.Creator<CaptureResultExtras> CREATOR =
             new Parcelable.Creator<CaptureResultExtras>() {
@@ -48,13 +49,14 @@
 
     public CaptureResultExtras(int requestId, int subsequenceId, int afTriggerId,
                                int precaptureTriggerId, long frameNumber,
-                               int partialResultCount) {
+                               int partialResultCount, int errorStreamId) {
         this.requestId = requestId;
         this.subsequenceId = subsequenceId;
         this.afTriggerId = afTriggerId;
         this.precaptureTriggerId = precaptureTriggerId;
         this.frameNumber = frameNumber;
         this.partialResultCount = partialResultCount;
+        this.errorStreamId = errorStreamId;
     }
 
     @Override
@@ -70,6 +72,7 @@
         dest.writeInt(precaptureTriggerId);
         dest.writeLong(frameNumber);
         dest.writeInt(partialResultCount);
+        dest.writeInt(errorStreamId);
     }
 
     public void readFromParcel(Parcel in) {
@@ -79,6 +82,7 @@
         precaptureTriggerId = in.readInt();
         frameNumber = in.readLong();
         partialResultCount = in.readInt();
+        errorStreamId = in.readInt();
     }
 
     public int getRequestId() {
@@ -104,4 +108,8 @@
     public int getPartialResultCount() {
         return partialResultCount;
     }
+
+    public int getErrorStreamId() {
+        return errorStreamId;
+    }
 }
diff --git a/core/java/android/hardware/camera2/impl/ICameraDeviceUserWrapper.java b/core/java/android/hardware/camera2/impl/ICameraDeviceUserWrapper.java
new file mode 100644
index 0000000..ddc3fd1
--- /dev/null
+++ b/core/java/android/hardware/camera2/impl/ICameraDeviceUserWrapper.java
@@ -0,0 +1,212 @@
+/*
+ * 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.hardware.camera2.impl;
+
+import static android.hardware.camera2.CameraAccessException.CAMERA_DISABLED;
+import static android.hardware.camera2.CameraAccessException.CAMERA_DISCONNECTED;
+import static android.hardware.camera2.CameraAccessException.CAMERA_IN_USE;
+import static android.hardware.camera2.CameraAccessException.CAMERA_ERROR;
+import static android.hardware.camera2.CameraAccessException.MAX_CAMERAS_IN_USE;
+import static android.hardware.camera2.CameraAccessException.CAMERA_DEPRECATED_HAL;
+
+import android.hardware.ICameraService;
+import android.hardware.camera2.CameraManager;
+import android.hardware.camera2.CameraAccessException;
+import android.hardware.camera2.CaptureRequest;
+import android.hardware.camera2.ICameraDeviceUser;
+import android.hardware.camera2.impl.CameraMetadataNative;
+import android.hardware.camera2.params.OutputConfiguration;
+import android.hardware.camera2.utils.SubmitInfo;
+import android.os.RemoteException;
+import android.view.Surface;
+
+/**
+ * A wrapper around ICameraDeviceUser.
+ *
+ * Mainly used to convert ServiceSpecificExceptions to the correct
+ * checked / unchecked exception.
+ *
+ * @hide
+ */
+public class ICameraDeviceUserWrapper {
+
+    private final ICameraDeviceUser mRemoteDevice;
+
+    public ICameraDeviceUserWrapper(ICameraDeviceUser remoteDevice) {
+        if (remoteDevice == null) {
+            throw new NullPointerException("Remote device may not be null");
+        }
+        mRemoteDevice = remoteDevice;
+    }
+
+    public void disconnect()  {
+        try {
+            mRemoteDevice.disconnect();
+        } catch (RemoteException t) {
+            // ignore binder errors for disconnect
+        }
+    }
+
+    public SubmitInfo submitRequest(CaptureRequest request, boolean streaming)
+            throws CameraAccessException  {
+        try {
+            return mRemoteDevice.submitRequest(request, streaming);
+        } catch (Throwable t) {
+            CameraManager.throwAsPublicException(t);
+            throw new UnsupportedOperationException("Unexpected exception", t);
+        }
+    }
+
+    public SubmitInfo submitRequestList(CaptureRequest[] requestList, boolean streaming)
+            throws CameraAccessException {
+        try {
+            return mRemoteDevice.submitRequestList(requestList, streaming);
+        } catch (Throwable t) {
+            CameraManager.throwAsPublicException(t);
+            throw new UnsupportedOperationException("Unexpected exception", t);
+        }
+    }
+
+    public long cancelRequest(int requestId) throws CameraAccessException {
+        try {
+            return mRemoteDevice.cancelRequest(requestId);
+        } catch (Throwable t) {
+            CameraManager.throwAsPublicException(t);
+            throw new UnsupportedOperationException("Unexpected exception", t);
+        }
+    }
+
+    public void beginConfigure() throws CameraAccessException {
+        try {
+            mRemoteDevice.beginConfigure();
+        } catch (Throwable t) {
+            CameraManager.throwAsPublicException(t);
+            throw new UnsupportedOperationException("Unexpected exception", t);
+        }
+    }
+
+    public void endConfigure(boolean isConstrainedHighSpeed) throws CameraAccessException {
+        try {
+            mRemoteDevice.endConfigure(isConstrainedHighSpeed);
+        } catch (Throwable t) {
+            CameraManager.throwAsPublicException(t);
+            throw new UnsupportedOperationException("Unexpected exception", t);
+        }
+    }
+
+    public void deleteStream(int streamId) throws CameraAccessException {
+        try {
+            mRemoteDevice.deleteStream(streamId);
+        } catch (Throwable t) {
+            CameraManager.throwAsPublicException(t);
+            throw new UnsupportedOperationException("Unexpected exception", t);
+        }
+    }
+
+    public int createStream(OutputConfiguration outputConfiguration)
+            throws CameraAccessException {
+        try {
+            return mRemoteDevice.createStream(outputConfiguration);
+        } catch (Throwable t) {
+            CameraManager.throwAsPublicException(t);
+            throw new UnsupportedOperationException("Unexpected exception", t);
+        }
+    }
+
+    public int createInputStream(int width, int height, int format) throws CameraAccessException {
+        try {
+            return mRemoteDevice.createInputStream(width, height, format);
+        } catch (Throwable t) {
+            CameraManager.throwAsPublicException(t);
+            throw new UnsupportedOperationException("Unexpected exception", t);
+        }
+    }
+
+    public Surface getInputSurface() throws CameraAccessException {
+        try {
+            return mRemoteDevice.getInputSurface();
+        } catch (Throwable t) {
+            CameraManager.throwAsPublicException(t);
+            throw new UnsupportedOperationException("Unexpected exception", t);
+        }
+    }
+
+    public CameraMetadataNative createDefaultRequest(int templateId) throws CameraAccessException {
+        try {
+            return mRemoteDevice.createDefaultRequest(templateId);
+        } catch (Throwable t) {
+            CameraManager.throwAsPublicException(t);
+            throw new UnsupportedOperationException("Unexpected exception", t);
+        }
+    }
+
+    public CameraMetadataNative getCameraInfo() throws CameraAccessException {
+        try {
+            return mRemoteDevice.getCameraInfo();
+        } catch (Throwable t) {
+            CameraManager.throwAsPublicException(t);
+            throw new UnsupportedOperationException("Unexpected exception", t);
+        }
+    }
+
+    public void waitUntilIdle() throws CameraAccessException {
+        try {
+            mRemoteDevice.waitUntilIdle();
+        } catch (Throwable t) {
+            CameraManager.throwAsPublicException(t);
+            throw new UnsupportedOperationException("Unexpected exception", t);
+        }
+    }
+
+    public long flush() throws CameraAccessException {
+        try {
+            return mRemoteDevice.flush();
+        } catch (Throwable t) {
+            CameraManager.throwAsPublicException(t);
+            throw new UnsupportedOperationException("Unexpected exception", t);
+        }
+    }
+
+    public void prepare(int streamId) throws CameraAccessException {
+        try {
+            mRemoteDevice.prepare(streamId);
+        } catch (Throwable t) {
+            CameraManager.throwAsPublicException(t);
+            throw new UnsupportedOperationException("Unexpected exception", t);
+        }
+    }
+
+    public void tearDown(int streamId) throws CameraAccessException {
+        try {
+            mRemoteDevice.tearDown(streamId);
+        } catch (Throwable t) {
+            CameraManager.throwAsPublicException(t);
+            throw new UnsupportedOperationException("Unexpected exception", t);
+        }
+    }
+
+    public void prepare2(int maxCount, int streamId) throws CameraAccessException {
+        try {
+            mRemoteDevice.prepare2(maxCount, streamId);
+        } catch (Throwable t) {
+            CameraManager.throwAsPublicException(t);
+            throw new UnsupportedOperationException("Unexpected exception", t);
+        }
+    }
+
+
+}
diff --git a/core/java/android/hardware/camera2/legacy/BurstHolder.java b/core/java/android/hardware/camera2/legacy/BurstHolder.java
index e7b3682..23efe15 100644
--- a/core/java/android/hardware/camera2/legacy/BurstHolder.java
+++ b/core/java/android/hardware/camera2/legacy/BurstHolder.java
@@ -35,10 +35,10 @@
      *
      * @param requestId id of the burst request.
      * @param repeating true if this burst is repeating.
-     * @param requests a {@link List} of {@link CaptureRequest}s in this burst.
+     * @param requests the array of {@link CaptureRequest}s for this burst.
      * @param jpegSurfaceIds a {@link Collection} of IDs for the surfaces that have jpeg outputs.
      */
-    public BurstHolder(int requestId, boolean repeating, List<CaptureRequest> requests,
+    public BurstHolder(int requestId, boolean repeating, CaptureRequest[] requests,
                        Collection<Long> jpegSurfaceIds) {
         mRequestBuilders = new ArrayList<>();
         int i = 0;
diff --git a/core/java/android/hardware/camera2/legacy/CameraDeviceUserShim.java b/core/java/android/hardware/camera2/legacy/CameraDeviceUserShim.java
index 798c941..d01c275 100644
--- a/core/java/android/hardware/camera2/legacy/CameraDeviceUserShim.java
+++ b/core/java/android/hardware/camera2/legacy/CameraDeviceUserShim.java
@@ -16,6 +16,7 @@
 
 package android.hardware.camera2.legacy;
 
+import android.hardware.ICameraService;
 import android.hardware.Camera;
 import android.hardware.Camera.CameraInfo;
 import android.hardware.camera2.CameraAccessException;
@@ -23,12 +24,10 @@
 import android.hardware.camera2.CaptureRequest;
 import android.hardware.camera2.ICameraDeviceCallbacks;
 import android.hardware.camera2.ICameraDeviceUser;
-import android.hardware.camera2.utils.LongParcelable;
 import android.hardware.camera2.impl.CameraMetadataNative;
 import android.hardware.camera2.impl.CaptureResultExtras;
 import android.hardware.camera2.params.OutputConfiguration;
-import android.hardware.camera2.utils.CameraBinderDecorator;
-import android.hardware.camera2.utils.CameraRuntimeException;
+import android.hardware.camera2.utils.SubmitInfo;
 import android.os.ConditionVariable;
 import android.os.IBinder;
 import android.os.Looper;
@@ -36,6 +35,7 @@
 import android.os.HandlerThread;
 import android.os.Message;
 import android.os.RemoteException;
+import android.os.ServiceSpecificException;
 import android.util.Log;
 import android.util.SparseArray;
 import android.view.Surface;
@@ -93,7 +93,7 @@
 
     private static int translateErrorsFromCamera1(int errorCode) {
         if (errorCode == -EACCES) {
-            return CameraBinderDecorator.PERMISSION_DENIED;
+            return ICameraService.ERROR_PERMISSION_DENIED;
         }
 
         return errorCode;
@@ -173,7 +173,7 @@
          *
          * @return int error code
          *
-         * @throws CameraRuntimeException if the camera open times out with ({@code CAMERA_ERROR})
+         * @throws ServiceSpecificException if the camera open times out with ({@code CAMERA_ERROR})
          */
         public int waitForOpen(int timeoutMs) {
             // Block until the camera is open asynchronously
@@ -186,7 +186,7 @@
                     Log.e(TAG, "connectBinderShim - Failed to release camera after timeout ", e);
                 }
 
-                throw new CameraRuntimeException(CameraAccessException.CAMERA_ERROR);
+                throw new ServiceSpecificException(ICameraService.ERROR_INVALID_OPERATION);
             }
 
             return mInitErrors;
@@ -344,7 +344,7 @@
         Camera legacyCamera = init.getCamera();
 
         // Check errors old HAL initialization
-        CameraBinderDecorator.throwOnError(initErrors);
+        LegacyExceptionUtils.throwOnServiceError(initErrors);
 
         // Disable shutter sounds (this will work unconditionally) for api2 clients
         legacyCamera.disableShutterSound();
@@ -356,8 +356,8 @@
         try {
             legacyParameters = legacyCamera.getParameters();
         } catch (RuntimeException e) {
-            throw new CameraRuntimeException(CameraAccessException.CAMERA_ERROR,
-                    "Unable to get initial parameters", e);
+            throw new ServiceSpecificException(ICameraService.ERROR_INVALID_OPERATION,
+                    "Unable to get initial parameters: " + e.getMessage());
         }
 
         CameraCharacteristics characteristics =
@@ -386,101 +386,106 @@
     }
 
     @Override
-    public int submitRequest(CaptureRequest request, boolean streaming,
-                             /*out*/LongParcelable lastFrameNumber) {
+    public SubmitInfo submitRequest(CaptureRequest request, boolean streaming) {
         if (DEBUG) {
             Log.d(TAG, "submitRequest called.");
         }
         if (mLegacyDevice.isClosed()) {
-            Log.e(TAG, "Cannot submit request, device has been closed.");
-            return -ENODEV;
+            String err = "Cannot submit request, device has been closed.";
+            Log.e(TAG, err);
+            throw new ServiceSpecificException(ICameraService.ERROR_DISCONNECTED, err);
         }
 
         synchronized(mConfigureLock) {
             if (mConfiguring) {
-                Log.e(TAG, "Cannot submit request, configuration change in progress.");
-                return CameraBinderDecorator.INVALID_OPERATION;
+                String err = "Cannot submit request, configuration change in progress.";
+                Log.e(TAG, err);
+                throw new ServiceSpecificException(ICameraService.ERROR_INVALID_OPERATION, err);
             }
         }
-        return mLegacyDevice.submitRequest(request, streaming, lastFrameNumber);
+        return mLegacyDevice.submitRequest(request, streaming);
     }
 
     @Override
-    public int submitRequestList(List<CaptureRequest> request, boolean streaming,
-                                 /*out*/LongParcelable lastFrameNumber) {
+    public SubmitInfo submitRequestList(CaptureRequest[] request, boolean streaming) {
         if (DEBUG) {
             Log.d(TAG, "submitRequestList called.");
         }
         if (mLegacyDevice.isClosed()) {
-            Log.e(TAG, "Cannot submit request list, device has been closed.");
-            return -ENODEV;
+            String err = "Cannot submit request list, device has been closed.";
+            Log.e(TAG, err);
+            throw new ServiceSpecificException(ICameraService.ERROR_DISCONNECTED, err);
         }
 
         synchronized(mConfigureLock) {
             if (mConfiguring) {
-                Log.e(TAG, "Cannot submit request, configuration change in progress.");
-                return CameraBinderDecorator.INVALID_OPERATION;
+                String err = "Cannot submit request, configuration change in progress.";
+                Log.e(TAG, err);
+                throw new ServiceSpecificException(ICameraService.ERROR_INVALID_OPERATION, err);
             }
         }
-        return mLegacyDevice.submitRequestList(request, streaming, lastFrameNumber);
+        return mLegacyDevice.submitRequestList(request, streaming);
     }
 
     @Override
-    public int cancelRequest(int requestId, /*out*/LongParcelable lastFrameNumber) {
+    public long cancelRequest(int requestId) {
         if (DEBUG) {
             Log.d(TAG, "cancelRequest called.");
         }
         if (mLegacyDevice.isClosed()) {
-            Log.e(TAG, "Cannot cancel request, device has been closed.");
-            return -ENODEV;
+            String err = "Cannot cancel request, device has been closed.";
+            Log.e(TAG, err);
+            throw new ServiceSpecificException(ICameraService.ERROR_DISCONNECTED, err);
         }
 
         synchronized(mConfigureLock) {
             if (mConfiguring) {
-                Log.e(TAG, "Cannot cancel request, configuration change in progress.");
-                return CameraBinderDecorator.INVALID_OPERATION;
+                String err = "Cannot cancel request, configuration change in progress.";
+                Log.e(TAG, err);
+                throw new ServiceSpecificException(ICameraService.ERROR_INVALID_OPERATION, err);
             }
         }
-        long lastFrame = mLegacyDevice.cancelRequest(requestId);
-        lastFrameNumber.setNumber(lastFrame);
-        return CameraBinderDecorator.NO_ERROR;
+        return mLegacyDevice.cancelRequest(requestId);
     }
 
     @Override
-    public int beginConfigure() {
+    public void beginConfigure() {
         if (DEBUG) {
             Log.d(TAG, "beginConfigure called.");
         }
         if (mLegacyDevice.isClosed()) {
-            Log.e(TAG, "Cannot begin configure, device has been closed.");
-            return -ENODEV;
+            String err = "Cannot begin configure, device has been closed.";
+            Log.e(TAG, err);
+            throw new ServiceSpecificException(ICameraService.ERROR_DISCONNECTED, err);
         }
 
         synchronized(mConfigureLock) {
             if (mConfiguring) {
-                Log.e(TAG, "Cannot begin configure, configuration change already in progress.");
-                return CameraBinderDecorator.INVALID_OPERATION;
+                String err = "Cannot begin configure, configuration change already in progress.";
+                Log.e(TAG, err);
+                throw new ServiceSpecificException(ICameraService.ERROR_INVALID_OPERATION, err);
             }
             mConfiguring = true;
         }
-        return CameraBinderDecorator.NO_ERROR;
     }
 
     @Override
-    public int endConfigure(boolean isConstrainedHighSpeed) {
+    public void endConfigure(boolean isConstrainedHighSpeed) {
         if (DEBUG) {
             Log.d(TAG, "endConfigure called.");
         }
         if (mLegacyDevice.isClosed()) {
-            Log.e(TAG, "Cannot end configure, device has been closed.");
-            return -ENODEV;
+            String err = "Cannot end configure, device has been closed.";
+            Log.e(TAG, err);
+            throw new ServiceSpecificException(ICameraService.ERROR_DISCONNECTED, err);
         }
 
         ArrayList<Surface> surfaces = null;
         synchronized(mConfigureLock) {
             if (!mConfiguring) {
-                Log.e(TAG, "Cannot end configure, no configuration change in progress.");
-                return CameraBinderDecorator.INVALID_OPERATION;
+                String err = "Cannot end configure, no configuration change in progress.";
+                Log.e(TAG, err);
+                throw new ServiceSpecificException(ICameraService.ERROR_INVALID_OPERATION, err);
             }
             int numSurfaces = mSurfaces.size();
             if (numSurfaces > 0) {
@@ -491,32 +496,34 @@
             }
             mConfiguring = false;
         }
-        return mLegacyDevice.configureOutputs(surfaces);
+        mLegacyDevice.configureOutputs(surfaces);
     }
 
     @Override
-    public int deleteStream(int streamId) {
+    public void deleteStream(int streamId) {
         if (DEBUG) {
             Log.d(TAG, "deleteStream called.");
         }
         if (mLegacyDevice.isClosed()) {
-            Log.e(TAG, "Cannot delete stream, device has been closed.");
-            return -ENODEV;
+            String err = "Cannot delete stream, device has been closed.";
+            Log.e(TAG, err);
+            throw new ServiceSpecificException(ICameraService.ERROR_DISCONNECTED, err);
         }
 
         synchronized(mConfigureLock) {
             if (!mConfiguring) {
-                Log.e(TAG, "Cannot delete stream, beginConfigure hasn't been called yet.");
-                return CameraBinderDecorator.INVALID_OPERATION;
+                String err = "Cannot delete stream, no configuration change in progress.";
+                Log.e(TAG, err);
+                throw new ServiceSpecificException(ICameraService.ERROR_INVALID_OPERATION, err);
             }
             int index = mSurfaces.indexOfKey(streamId);
             if (index < 0) {
-                Log.e(TAG, "Cannot delete stream, stream id " + streamId + " doesn't exist.");
-                return CameraBinderDecorator.BAD_VALUE;
+                String err = "Cannot delete stream, stream id " + streamId + " doesn't exist.";
+                Log.e(TAG, err);
+                throw new ServiceSpecificException(ICameraService.ERROR_ILLEGAL_ARGUMENT, err);
             }
             mSurfaces.removeAt(index);
         }
-        return CameraBinderDecorator.NO_ERROR;
     }
 
     @Override
@@ -525,18 +532,21 @@
             Log.d(TAG, "createStream called.");
         }
         if (mLegacyDevice.isClosed()) {
-            Log.e(TAG, "Cannot create stream, device has been closed.");
-            return -ENODEV;
+            String err = "Cannot create stream, device has been closed.";
+            Log.e(TAG, err);
+            throw new ServiceSpecificException(ICameraService.ERROR_DISCONNECTED, err);
         }
 
         synchronized(mConfigureLock) {
             if (!mConfiguring) {
-                Log.e(TAG, "Cannot create stream, beginConfigure hasn't been called yet.");
-                return CameraBinderDecorator.INVALID_OPERATION;
+                String err = "Cannot create stream, beginConfigure hasn't been called yet.";
+                Log.e(TAG, err);
+                throw new ServiceSpecificException(ICameraService.ERROR_INVALID_OPERATION, err);
             }
             if (outputConfiguration.getRotation() != OutputConfiguration.ROTATION_0) {
-                Log.e(TAG, "Cannot create stream, stream rotation is not supported.");
-                return CameraBinderDecorator.INVALID_OPERATION;
+                String err = "Cannot create stream, stream rotation is not supported.";
+                Log.e(TAG, err);
+                throw new ServiceSpecificException(ICameraService.ERROR_ILLEGAL_ARGUMENT, err);
             }
             int id = ++mSurfaceIdCounter;
             mSurfaces.put(id, outputConfiguration.getSurface());
@@ -546,24 +556,27 @@
 
     @Override
     public int createInputStream(int width, int height, int format) {
-        Log.e(TAG, "creating input stream is not supported on legacy devices");
-        return CameraBinderDecorator.INVALID_OPERATION;
+        String err = "Creating input stream is not supported on legacy devices";
+        Log.e(TAG, err);
+        throw new ServiceSpecificException(ICameraService.ERROR_INVALID_OPERATION, err);
     }
 
     @Override
-    public int getInputSurface(/*out*/ Surface surface) {
-        Log.e(TAG, "getting input surface is not supported on legacy devices");
-        return CameraBinderDecorator.INVALID_OPERATION;
+    public Surface getInputSurface() {
+        String err = "Getting input surface is not supported on legacy devices";
+        Log.e(TAG, err);
+        throw new ServiceSpecificException(ICameraService.ERROR_INVALID_OPERATION, err);
     }
 
     @Override
-    public int createDefaultRequest(int templateId, /*out*/CameraMetadataNative request) {
+    public CameraMetadataNative createDefaultRequest(int templateId) {
         if (DEBUG) {
             Log.d(TAG, "createDefaultRequest called.");
         }
         if (mLegacyDevice.isClosed()) {
-            Log.e(TAG, "Cannot create default request, device has been closed.");
-            return -ENODEV;
+            String err = "Cannot create default request, device has been closed.";
+            Log.e(TAG, err);
+            throw new ServiceSpecificException(ICameraService.ERROR_DISCONNECTED, err);
         }
 
         CameraMetadataNative template;
@@ -571,99 +584,96 @@
             template =
                     LegacyMetadataMapper.createRequestTemplate(mCameraCharacteristics, templateId);
         } catch (IllegalArgumentException e) {
-            Log.e(TAG, "createDefaultRequest - invalid templateId specified");
-            return CameraBinderDecorator.BAD_VALUE;
+            String err = "createDefaultRequest - invalid templateId specified";
+            Log.e(TAG, err);
+            throw new ServiceSpecificException(ICameraService.ERROR_ILLEGAL_ARGUMENT, err);
         }
 
-        request.swap(template);
-        return CameraBinderDecorator.NO_ERROR;
+        return template;
     }
 
     @Override
-    public int getCameraInfo(/*out*/CameraMetadataNative info) {
+    public CameraMetadataNative getCameraInfo() {
         if (DEBUG) {
             Log.d(TAG, "getCameraInfo called.");
         }
         // TODO: implement getCameraInfo.
         Log.e(TAG, "getCameraInfo unimplemented.");
-        return CameraBinderDecorator.NO_ERROR;
+        return null;
     }
 
     @Override
-    public int waitUntilIdle() throws RemoteException {
+    public void waitUntilIdle() throws RemoteException {
         if (DEBUG) {
             Log.d(TAG, "waitUntilIdle called.");
         }
         if (mLegacyDevice.isClosed()) {
-            Log.e(TAG, "Cannot wait until idle, device has been closed.");
-            return -ENODEV;
+            String err = "Cannot wait until idle, device has been closed.";
+            Log.e(TAG, err);
+            throw new ServiceSpecificException(ICameraService.ERROR_DISCONNECTED, err);
         }
 
         synchronized(mConfigureLock) {
             if (mConfiguring) {
-                Log.e(TAG, "Cannot wait until idle, configuration change in progress.");
-                return CameraBinderDecorator.INVALID_OPERATION;
+                String err = "Cannot wait until idle, configuration change in progress.";
+                Log.e(TAG, err);
+                throw new ServiceSpecificException(ICameraService.ERROR_INVALID_OPERATION, err);
             }
         }
         mLegacyDevice.waitUntilIdle();
-        return CameraBinderDecorator.NO_ERROR;
     }
 
     @Override
-    public int flush(/*out*/LongParcelable lastFrameNumber) {
+    public long flush() {
         if (DEBUG) {
             Log.d(TAG, "flush called.");
         }
         if (mLegacyDevice.isClosed()) {
-            Log.e(TAG, "Cannot flush, device has been closed.");
-            return -ENODEV;
+            String err = "Cannot flush, device has been closed.";
+            Log.e(TAG, err);
+            throw new ServiceSpecificException(ICameraService.ERROR_DISCONNECTED, err);
         }
 
         synchronized(mConfigureLock) {
             if (mConfiguring) {
-                Log.e(TAG, "Cannot flush, configuration change in progress.");
-                return CameraBinderDecorator.INVALID_OPERATION;
+                String err = "Cannot flush, configuration change in progress.";
+                Log.e(TAG, err);
+                throw new ServiceSpecificException(ICameraService.ERROR_INVALID_OPERATION, err);
             }
         }
-        long lastFrame = mLegacyDevice.flush();
-        if (lastFrameNumber != null) {
-            lastFrameNumber.setNumber(lastFrame);
-        }
-        return CameraBinderDecorator.NO_ERROR;
+        return mLegacyDevice.flush();
     }
 
-    public int prepare(int streamId) {
+    public void prepare(int streamId) {
         if (DEBUG) {
             Log.d(TAG, "prepare called.");
         }
         if (mLegacyDevice.isClosed()) {
-            Log.e(TAG, "Cannot prepare stream, device has been closed.");
-            return -ENODEV;
+            String err = "Cannot prepare stream, device has been closed.";
+            Log.e(TAG, err);
+            throw new ServiceSpecificException(ICameraService.ERROR_DISCONNECTED, err);
         }
 
         // LEGACY doesn't support actual prepare, just signal success right away
         mCameraCallbacks.onPrepared(streamId);
-
-        return CameraBinderDecorator.NO_ERROR;
     }
 
-    public int prepare2(int maxCount, int streamId) {
+    public void prepare2(int maxCount, int streamId) {
         // We don't support this in LEGACY mode.
-        return prepare(streamId);
+        prepare(streamId);
     }
 
-    public int tearDown(int streamId) {
+    public void tearDown(int streamId) {
         if (DEBUG) {
             Log.d(TAG, "tearDown called.");
         }
         if (mLegacyDevice.isClosed()) {
-            Log.e(TAG, "Cannot tear down stream, device has been closed.");
-            return -ENODEV;
+            String err = "Cannot tear down stream, device has been closed.";
+            Log.e(TAG, err);
+            throw new ServiceSpecificException(ICameraService.ERROR_DISCONNECTED, err);
         }
 
         // LEGACY doesn't support actual teardown, so just a no-op
-
-        return CameraBinderDecorator.NO_ERROR;
     }
 
     @Override
diff --git a/core/java/android/hardware/camera2/legacy/LegacyCameraDevice.java b/core/java/android/hardware/camera2/legacy/LegacyCameraDevice.java
index fddfbde..661edd7 100644
--- a/core/java/android/hardware/camera2/legacy/LegacyCameraDevice.java
+++ b/core/java/android/hardware/camera2/legacy/LegacyCameraDevice.java
@@ -26,14 +26,13 @@
 import android.hardware.camera2.ICameraDeviceCallbacks;
 import android.hardware.camera2.params.StreamConfigurationMap;
 import android.hardware.camera2.utils.ArrayUtils;
-import android.hardware.camera2.utils.CameraBinderDecorator;
-import android.hardware.camera2.utils.LongParcelable;
+import android.hardware.camera2.utils.SubmitInfo;
 import android.hardware.camera2.impl.CameraMetadataNative;
-import android.hardware.camera2.utils.CameraRuntimeException;
 import android.os.ConditionVariable;
 import android.os.Handler;
 import android.os.HandlerThread;
 import android.os.RemoteException;
+import android.os.ServiceSpecificException;
 import android.util.Log;
 import android.util.Pair;
 import android.util.Size;
@@ -45,7 +44,6 @@
 import java.util.List;
 
 import static android.hardware.camera2.legacy.LegacyExceptionUtils.*;
-import static android.hardware.camera2.utils.CameraBinderDecorator.*;
 import static com.android.internal.util.Preconditions.*;
 
 /**
@@ -93,11 +91,11 @@
     private CaptureResultExtras getExtrasFromRequest(RequestHolder holder) {
         if (holder == null) {
             return new CaptureResultExtras(ILLEGAL_VALUE, ILLEGAL_VALUE, ILLEGAL_VALUE,
-                    ILLEGAL_VALUE, ILLEGAL_VALUE, ILLEGAL_VALUE);
+                    ILLEGAL_VALUE, ILLEGAL_VALUE, ILLEGAL_VALUE, ILLEGAL_VALUE);
         }
         return new CaptureResultExtras(holder.getRequestId(), holder.getSubsequeceId(),
                 /*afTriggerId*/0, /*precaptureTriggerId*/0, holder.getFrameNumber(),
-                /*partialResultCount*/1);
+                /*partialResultCount*/1, /*errorStreamId*/-1);
     }
 
     /**
@@ -357,9 +355,9 @@
         if (success) {
             mConfiguredSurfaces = outputs != null ? new ArrayList<>(outputs) : null;
         } else {
-            return CameraBinderDecorator.INVALID_OPERATION;
+            return LegacyExceptionUtils.INVALID_OPERATION;
         }
-        return CameraBinderDecorator.NO_ERROR;
+        return LegacyExceptionUtils.NO_ERROR;
     }
 
     /**
@@ -367,17 +365,16 @@
      *
      * @param requestList a list of capture requests to execute.
      * @param repeating {@code true} if this burst is repeating.
-     * @param frameNumber an output argument that contains either the frame number of the last frame
-     *                    that will be returned for this request, or the frame number of the last
-     *                    frame that will be returned for the current repeating request if this
-     *                    burst is set to be repeating.
-     * @return the request id.
+     * @return the submission info, including the new request id, and the last frame number, which
+     *   contains either the frame number of the last frame that will be returned for this request,
+     *   or the frame number of the last frame that will be returned for the current repeating
+     *   request if this burst is set to be repeating.
      */
-    public int submitRequestList(List<CaptureRequest> requestList, boolean repeating,
-            /*out*/LongParcelable frameNumber) {
-        if (requestList == null || requestList.isEmpty()) {
+    public SubmitInfo submitRequestList(CaptureRequest[] requestList, boolean repeating) {
+        if (requestList == null || requestList.length == 0) {
             Log.e(TAG, "submitRequestList - Empty/null requests are not allowed");
-            return BAD_VALUE;
+            throw new ServiceSpecificException(BAD_VALUE,
+                    "submitRequestList - Empty/null requests are not allowed");
         }
 
         List<Long> surfaceIds = (mConfiguredSurfaces == null) ? new ArrayList<Long>() :
@@ -388,28 +385,33 @@
             if (request.getTargets().isEmpty()) {
                 Log.e(TAG, "submitRequestList - "
                         + "Each request must have at least one Surface target");
-                return BAD_VALUE;
+                throw new ServiceSpecificException(BAD_VALUE,
+                        "submitRequestList - "
+                        + "Each request must have at least one Surface target");
             }
 
             for (Surface surface : request.getTargets()) {
                 if (surface == null) {
                     Log.e(TAG, "submitRequestList - Null Surface targets are not allowed");
-                    return BAD_VALUE;
+                    throw new ServiceSpecificException(BAD_VALUE,
+                            "submitRequestList - Null Surface targets are not allowed");
                 } else if (mConfiguredSurfaces == null) {
                     Log.e(TAG, "submitRequestList - must configure " +
                             " device with valid surfaces before submitting requests");
-                    return INVALID_OPERATION;
+                    throw new ServiceSpecificException(INVALID_OPERATION,
+                            "submitRequestList - must configure " +
+                            " device with valid surfaces before submitting requests");
                 } else if (!containsSurfaceId(surface, surfaceIds)) {
                     Log.e(TAG, "submitRequestList - cannot use a surface that wasn't configured");
-                    return BAD_VALUE;
+                    throw new ServiceSpecificException(BAD_VALUE,
+                            "submitRequestList - cannot use a surface that wasn't configured");
                 }
             }
         }
 
         // TODO: further validation of request here
         mIdle.close();
-        return mRequestThreadManager.submitCaptureRequests(requestList, repeating,
-                frameNumber);
+        return mRequestThreadManager.submitCaptureRequests(requestList, repeating);
     }
 
     /**
@@ -417,17 +419,14 @@
      *
      * @param request the capture request to execute.
      * @param repeating {@code true} if this request is repeating.
-     * @param frameNumber an output argument that contains either the frame number of the last frame
-     *                    that will be returned for this request, or the frame number of the last
-     *                    frame that will be returned for the current repeating request if this
-     *                    request is set to be repeating.
-     * @return the request id.
+     * @return the submission info, including the new request id, and the last frame number, which
+     *   contains either the frame number of the last frame that will be returned for this request,
+     *   or the frame number of the last frame that will be returned for the current repeating
+     *   request if this burst is set to be repeating.
      */
-    public int submitRequest(CaptureRequest request, boolean repeating,
-            /*out*/LongParcelable frameNumber) {
-        ArrayList<CaptureRequest> requestList = new ArrayList<CaptureRequest>();
-        requestList.add(request);
-        return submitRequestList(requestList, repeating, frameNumber);
+    public SubmitInfo submitRequest(CaptureRequest request, boolean repeating) {
+        CaptureRequest[] requestList = { request };
+        return submitRequestList(requestList, repeating);
     }
 
     /**
@@ -493,7 +492,7 @@
     protected void finalize() throws Throwable {
         try {
             close();
-        } catch (CameraRuntimeException e) {
+        } catch (ServiceSpecificException e) {
             Log.e(TAG, "Got error while trying to finalize, ignoring: " + e.getMessage());
         } finally {
             super.finalize();
@@ -615,14 +614,16 @@
         return LegacyExceptionUtils.throwOnError(nativeDetectSurfaceDataspace(surface));
     }
 
-    static void configureSurface(Surface surface, int width, int height,
-                                 int pixelFormat) throws BufferQueueAbandonedException {
+    static void connectSurface(Surface surface) throws BufferQueueAbandonedException {
         checkNotNull(surface);
-        checkArgumentPositive(width, "width must be positive.");
-        checkArgumentPositive(height, "height must be positive.");
 
-        LegacyExceptionUtils.throwOnError(nativeConfigureSurface(surface, width, height,
-                pixelFormat));
+        LegacyExceptionUtils.throwOnError(nativeConnectSurface(surface));
+    }
+
+    static void disconnectSurface(Surface surface) throws BufferQueueAbandonedException {
+        if (surface == null) return;
+
+        LegacyExceptionUtils.throwOnError(nativeDisconnectSurface(surface));
     }
 
     static void produceFrame(Surface surface, byte[] pixelBuffer, int width,
@@ -717,8 +718,7 @@
     private static native int nativeDetectSurfaceDimens(Surface surface,
             /*out*/int[/*2*/] dimens);
 
-    private static native int nativeConfigureSurface(Surface surface, int width, int height,
-                                                        int pixelFormat);
+    private static native int nativeConnectSurface(Surface surface);
 
     private static native int nativeProduceFrame(Surface surface, byte[] pixelBuffer, int width,
                                                     int height, int pixelFormat);
@@ -741,5 +741,7 @@
 
     private static native int nativeSetScalingMode(Surface surface, int scalingMode);
 
+    private static native int nativeDisconnectSurface(Surface surface);
+
     static native int nativeGetJpegFooterSize();
 }
diff --git a/core/java/android/hardware/camera2/legacy/LegacyExceptionUtils.java b/core/java/android/hardware/camera2/legacy/LegacyExceptionUtils.java
index 4501e81..93d6001 100644
--- a/core/java/android/hardware/camera2/legacy/LegacyExceptionUtils.java
+++ b/core/java/android/hardware/camera2/legacy/LegacyExceptionUtils.java
@@ -16,10 +16,11 @@
 
 package android.hardware.camera2.legacy;
 
-import android.hardware.camera2.utils.CameraBinderDecorator;
+import android.hardware.ICameraService;
+import android.os.ServiceSpecificException;
 import android.util.AndroidException;
 
-import static android.system.OsConstants.ENODEV;
+import static android.system.OsConstants.*;
 
 /**
  * Utility class containing exception handling used solely by the compatibility mode shim.
@@ -27,6 +28,14 @@
 public class LegacyExceptionUtils {
     private static final String TAG = "LegacyExceptionUtils";
 
+    public static final int NO_ERROR = 0;
+    public static final int PERMISSION_DENIED = -EPERM;
+    public static final int ALREADY_EXISTS = -EEXIST;
+    public static final int BAD_VALUE = -EINVAL;
+    public static final int DEAD_OBJECT = -ENOSYS;
+    public static final int INVALID_OPERATION = -EPIPE;
+    public static final int TIMED_OUT = -ETIMEDOUT;
+
     /**
      * Checked exception thrown when a BufferQueue has been abandoned by its consumer.
      */
@@ -58,8 +67,8 @@
      * @return {@code errorFlag} if the value was non-negative, throws otherwise.
      */
     public static int throwOnError(int errorFlag) throws BufferQueueAbandonedException {
-        if (errorFlag == CameraBinderDecorator.NO_ERROR) {
-            return CameraBinderDecorator.NO_ERROR;
+        if (errorFlag == NO_ERROR) {
+            return NO_ERROR;
         } else if (errorFlag == -ENODEV) {
             throw new BufferQueueAbandonedException();
         }
@@ -70,6 +79,59 @@
         return errorFlag;
     }
 
+    /**
+     * Throw error codes returned by the camera service as exceptions.
+     *
+     * @param errorFlag error to throw as an exception.
+     */
+    public static void throwOnServiceError(int errorFlag) {
+        int errorCode = ICameraService.ERROR_INVALID_OPERATION;
+        String errorMsg;
+
+        if (errorFlag >= NO_ERROR) {
+            return;
+        } else if (errorFlag == PERMISSION_DENIED) {
+            errorCode = ICameraService.ERROR_PERMISSION_DENIED;
+            errorMsg = "Lacking privileges to access camera service";
+        } else if (errorFlag == ALREADY_EXISTS) {
+            // This should be handled at the call site. Typically this isn't bad,
+            // just means we tried to do an operation that already completed.
+            return;
+        } else if (errorFlag == BAD_VALUE) {
+            errorCode = ICameraService.ERROR_ILLEGAL_ARGUMENT;
+            errorMsg = "Bad argument passed to camera service";
+        } else if (errorFlag == DEAD_OBJECT) {
+            errorCode = ICameraService.ERROR_DISCONNECTED;
+            errorMsg = "Camera service not available";
+        } else if (errorFlag == TIMED_OUT) {
+            errorCode = ICameraService.ERROR_INVALID_OPERATION;
+            errorMsg = "Operation timed out in camera service";
+        } else if (errorFlag == -EACCES) {
+            errorCode = ICameraService.ERROR_DISABLED;
+            errorMsg = "Camera disabled by policy";
+        } else if (errorFlag == -EBUSY) {
+            errorCode = ICameraService.ERROR_CAMERA_IN_USE;
+            errorMsg = "Camera already in use";
+        } else if (errorFlag == -EUSERS) {
+            errorCode = ICameraService.ERROR_MAX_CAMERAS_IN_USE;
+            errorMsg = "Maximum number of cameras in use";
+        } else if (errorFlag == -ENODEV) {
+            errorCode = ICameraService.ERROR_DISCONNECTED;
+            errorMsg = "Camera device not available";
+        } else if (errorFlag == -EOPNOTSUPP) {
+            errorCode = ICameraService.ERROR_DEPRECATED_HAL;
+            errorMsg = "Deprecated camera HAL does not support this";
+        } else if (errorFlag == INVALID_OPERATION) {
+            errorCode = ICameraService.ERROR_INVALID_OPERATION;
+            errorMsg = "Illegal state encountered in camera service.";
+        } else {
+            errorCode = ICameraService.ERROR_INVALID_OPERATION;
+            errorMsg = "Unknown camera device error " + errorFlag;
+        }
+
+        throw new ServiceSpecificException(errorCode, errorMsg);
+    }
+
     private LegacyExceptionUtils() {
         throw new AssertionError();
     }
diff --git a/core/java/android/hardware/camera2/legacy/RequestQueue.java b/core/java/android/hardware/camera2/legacy/RequestQueue.java
index c995029..8f252a1 100644
--- a/core/java/android/hardware/camera2/legacy/RequestQueue.java
+++ b/core/java/android/hardware/camera2/legacy/RequestQueue.java
@@ -16,7 +16,7 @@
 package android.hardware.camera2.legacy;
 
 import android.hardware.camera2.CaptureRequest;
-import android.hardware.camera2.utils.LongParcelable;
+import android.hardware.camera2.utils.SubmitInfo;
 import android.util.Log;
 import android.util.Pair;
 
@@ -111,31 +111,29 @@
      *
      * @param requests the burst of requests to add to the queue.
      * @param repeating true if the burst is repeating.
-     * @param frameNumber an output argument that contains either the frame number of the last frame
-     *                    that will be returned for this request, or the frame number of the last
-     *                    frame that will be returned for the current repeating request if this
-     *                    burst is set to be repeating.
-     * @return the request id.
+     * @return the submission info, including the new request id, and the last frame number, which
+     *   contains either the frame number of the last frame that will be returned for this request,
+     *   or the frame number of the last frame that will be returned for the current repeating
+     *   request if this burst is set to be repeating.
      */
-    public synchronized int submit(List<CaptureRequest> requests, boolean repeating,
-            /*out*/LongParcelable frameNumber) {
+    public synchronized SubmitInfo submit(CaptureRequest[] requests, boolean repeating) {
         int requestId = mCurrentRequestId++;
         BurstHolder burst = new BurstHolder(requestId, repeating, requests, mJpegSurfaceIds);
-        long ret = INVALID_FRAME;
+        long lastFrame = INVALID_FRAME;
         if (burst.isRepeating()) {
             Log.i(TAG, "Repeating capture request set.");
             if (mRepeatingRequest != null) {
-                ret = (mCurrentRepeatingFrameNumber == INVALID_FRAME) ? INVALID_FRAME :
+                lastFrame = (mCurrentRepeatingFrameNumber == INVALID_FRAME) ? INVALID_FRAME :
                         mCurrentRepeatingFrameNumber - 1;
             }
             mCurrentRepeatingFrameNumber = INVALID_FRAME;
             mRepeatingRequest = burst;
         } else {
             mRequestQueue.offer(burst);
-            ret = calculateLastFrame(burst.getRequestId());
+            lastFrame = calculateLastFrame(burst.getRequestId());
         }
-        frameNumber.setNumber(ret);
-        return requestId;
+        SubmitInfo info = new SubmitInfo(requestId, lastFrame);
+        return info;
     }
 
     private long calculateLastFrame(int requestId) {
diff --git a/core/java/android/hardware/camera2/legacy/RequestThreadManager.java b/core/java/android/hardware/camera2/legacy/RequestThreadManager.java
index 4866598..e8ce3ec 100644
--- a/core/java/android/hardware/camera2/legacy/RequestThreadManager.java
+++ b/core/java/android/hardware/camera2/legacy/RequestThreadManager.java
@@ -21,7 +21,7 @@
 import android.hardware.camera2.CameraCharacteristics;
 import android.hardware.camera2.CaptureRequest;
 import android.hardware.camera2.impl.CameraDeviceImpl;
-import android.hardware.camera2.utils.LongParcelable;
+import android.hardware.camera2.utils.SubmitInfo;
 import android.hardware.camera2.utils.SizeAreaComparator;
 import android.hardware.camera2.impl.CameraMetadataNative;
 import android.os.ConditionVariable;
@@ -365,6 +365,14 @@
             mGLThreadManager.waitUntilIdle();
         }
         resetJpegSurfaceFormats(mCallbackOutputs);
+
+        for (Surface s : mCallbackOutputs) {
+            try {
+                LegacyCameraDevice.disconnectSurface(s);
+            } catch (LegacyExceptionUtils.BufferQueueAbandonedException e) {
+                Log.w(TAG, "Surface abandoned, skipping...", e);
+            }
+        }
         mPreviewOutputs.clear();
         mCallbackOutputs.clear();
         mJpegSurfaceIds.clear();
@@ -392,6 +400,10 @@
                             mJpegSurfaceIds.add(LegacyCameraDevice.getSurfaceId(s));
                             mCallbackOutputs.add(s);
                             callbackOutputSizes.add(outSize);
+
+                            // LegacyCameraDevice is the producer of JPEG output surfaces
+                            // so LegacyCameraDevice needs to connect to the surfaces.
+                            LegacyCameraDevice.connectSurface(s);
                             break;
                         default:
                             LegacyCameraDevice.setScalingMode(s, LegacyCameraDevice.
@@ -1008,21 +1020,19 @@
      *
      * @param requests the burst of requests to add to the queue.
      * @param repeating true if the burst is repeating.
-     * @param frameNumber an output argument that contains either the frame number of the last frame
-     *                    that will be returned for this request, or the frame number of the last
-     *                    frame that will be returned for the current repeating request if this
-     *                    burst is set to be repeating.
-     * @return the request id.
+     * @return the submission info, including the new request id, and the last frame number, which
+     *   contains either the frame number of the last frame that will be returned for this request,
+     *   or the frame number of the last frame that will be returned for the current repeating
+     *   request if this burst is set to be repeating.
      */
-    public int submitCaptureRequests(List<CaptureRequest> requests, boolean repeating,
-            /*out*/LongParcelable frameNumber) {
+    public SubmitInfo submitCaptureRequests(CaptureRequest[] requests, boolean repeating) {
         Handler handler = mRequestThread.waitAndGetHandler();
-        int ret;
+        SubmitInfo info;
         synchronized (mIdleLock) {
-            ret = mRequestQueue.submit(requests, repeating, frameNumber);
+            info = mRequestQueue.submit(requests, repeating);
             handler.sendEmptyMessage(MSG_SUBMIT_CAPTURE_REQUEST);
         }
-        return ret;
+        return info;
     }
 
     /**
diff --git a/core/java/android/hardware/camera2/legacy/SurfaceTextureRenderer.java b/core/java/android/hardware/camera2/legacy/SurfaceTextureRenderer.java
index bc80fc1..70bc2fd 100644
--- a/core/java/android/hardware/camera2/legacy/SurfaceTextureRenderer.java
+++ b/core/java/android/hardware/camera2/legacy/SurfaceTextureRenderer.java
@@ -401,6 +401,13 @@
 
     private void clearState() {
         mSurfaces.clear();
+        for (EGLSurfaceHolder holder : mConversionSurfaces) {
+            try {
+                LegacyCameraDevice.disconnectSurface(holder.surface);
+            } catch (LegacyExceptionUtils.BufferQueueAbandonedException e) {
+                Log.w(TAG, "Surface abandoned, skipping...", e);
+            }
+        }
         mConversionSurfaces.clear();
         mPBufferPixels = null;
         if (mSurfaceTexture != null) {
@@ -631,6 +638,9 @@
                 holder.height = surfaceSize.getHeight();
                 if (LegacyCameraDevice.needsConversion(s)) {
                     mConversionSurfaces.add(holder);
+                    // LegacyCameraDevice is the producer of surfaces if it's not handled by EGL,
+                    // so LegacyCameraDevice needs to connect to the surfaces.
+                    LegacyCameraDevice.connectSurface(s);
                 } else {
                     mSurfaces.add(holder);
                 }
diff --git a/core/java/android/hardware/camera2/params/OutputConfiguration.aidl b/core/java/android/hardware/camera2/params/OutputConfiguration.aidl
deleted file mode 100644
index 0921cd8..0000000
--- a/core/java/android/hardware/camera2/params/OutputConfiguration.aidl
+++ /dev/null
@@ -1,20 +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.hardware.camera2.params;
-
-/** @hide */
-parcelable OutputConfiguration;
diff --git a/core/java/android/hardware/camera2/params/OutputConfiguration.java b/core/java/android/hardware/camera2/params/OutputConfiguration.java
index 4407e55..cd0c474 100644
--- a/core/java/android/hardware/camera2/params/OutputConfiguration.java
+++ b/core/java/android/hardware/camera2/params/OutputConfiguration.java
@@ -21,11 +21,11 @@
 import android.hardware.camera2.CameraDevice;
 import android.hardware.camera2.utils.HashCodeHelpers;
 import android.hardware.camera2.utils.SurfaceUtils;
+import android.os.Parcel;
+import android.os.Parcelable;
 import android.util.Log;
 import android.util.Size;
 import android.view.Surface;
-import android.os.Parcel;
-import android.os.Parcelable;
 
 import static com.android.internal.util.Preconditions.*;
 
diff --git a/core/java/android/hardware/camera2/params/VendorTagDescriptor.java b/core/java/android/hardware/camera2/params/VendorTagDescriptor.java
new file mode 100644
index 0000000..ea424e5
--- /dev/null
+++ b/core/java/android/hardware/camera2/params/VendorTagDescriptor.java
@@ -0,0 +1,67 @@
+/*
+ * 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.hardware.camera2.params;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.util.Log;
+
+/**
+ * A class for describing the vendor tags declared by a camera HAL module.
+ * Generally only used by the native side of
+ * android.hardware.camera2.impl.CameraMetadataNative
+ *
+ * @hide
+ */
+public final class VendorTagDescriptor implements Parcelable {
+
+    private VendorTagDescriptor(Parcel source) {
+    }
+
+    public static final Parcelable.Creator<VendorTagDescriptor> CREATOR =
+            new Parcelable.Creator<VendorTagDescriptor>() {
+        @Override
+        public VendorTagDescriptor createFromParcel(Parcel source) {
+            try {
+                VendorTagDescriptor vendorDescriptor = new VendorTagDescriptor(source);
+                return vendorDescriptor;
+            } catch (Exception e) {
+                Log.e(TAG, "Exception creating VendorTagDescriptor from parcel", e);
+                return null;
+            }
+        }
+
+        @Override
+        public VendorTagDescriptor[] newArray(int size) {
+            return new VendorTagDescriptor[size];
+        }
+    };
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        if (dest == null) {
+            throw new IllegalArgumentException("dest must not be null");
+        }
+    }
+
+    private static final String TAG = "VendorTagDescriptor";
+}
diff --git a/core/java/android/hardware/camera2/utils/BinderHolder.aidl b/core/java/android/hardware/camera2/utils/BinderHolder.aidl
deleted file mode 100644
index f39d645..0000000
--- a/core/java/android/hardware/camera2/utils/BinderHolder.aidl
+++ /dev/null
@@ -1,20 +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 android.hardware.camera2.utils;
-
-/** @hide */
-parcelable BinderHolder;
diff --git a/core/java/android/hardware/camera2/utils/BinderHolder.java b/core/java/android/hardware/camera2/utils/BinderHolder.java
deleted file mode 100644
index 9eea390..0000000
--- a/core/java/android/hardware/camera2/utils/BinderHolder.java
+++ /dev/null
@@ -1,74 +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 android.hardware.camera2.utils;
-
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.os.IBinder;
-
-/**
- * @hide
- */
-public class BinderHolder implements Parcelable {
-    private IBinder mBinder = null;
-
-    @Override
-    public int describeContents() {
-        return 0;
-    }
-
-    @Override
-    public void writeToParcel(Parcel dest, int flags) {
-        dest.writeStrongBinder(mBinder);
-    }
-
-    public void readFromParcel(Parcel src) {
-        mBinder = src.readStrongBinder();
-    }
-
-    public static final Parcelable.Creator<BinderHolder> CREATOR =
-             new Parcelable.Creator<BinderHolder>() {
-         @Override
-         public BinderHolder createFromParcel(Parcel in) {
-             return new BinderHolder(in);
-         }
-
-         @Override
-         public BinderHolder[] newArray(int size) {
-             return new BinderHolder[size];
-         }
-    };
-
-    public IBinder getBinder() {
-        return mBinder;
-    }
-
-    public void setBinder(IBinder binder) {
-        mBinder = binder;
-    }
-
-    public BinderHolder() {}
-
-    public BinderHolder(IBinder binder) {
-        mBinder = binder;
-    }
-
-    private BinderHolder(Parcel in) {
-        mBinder = in.readStrongBinder();
-    }
-}
-
diff --git a/core/java/android/hardware/camera2/utils/CameraBinderDecorator.java b/core/java/android/hardware/camera2/utils/CameraBinderDecorator.java
deleted file mode 100644
index 162edc9..0000000
--- a/core/java/android/hardware/camera2/utils/CameraBinderDecorator.java
+++ /dev/null
@@ -1,162 +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 android.hardware.camera2.utils;
-
-import static android.hardware.camera2.CameraAccessException.CAMERA_DISABLED;
-import static android.hardware.camera2.CameraAccessException.CAMERA_DISCONNECTED;
-import static android.hardware.camera2.CameraAccessException.CAMERA_IN_USE;
-import static android.hardware.camera2.CameraAccessException.CAMERA_ERROR;
-import static android.hardware.camera2.CameraAccessException.MAX_CAMERAS_IN_USE;
-import static android.hardware.camera2.CameraAccessException.CAMERA_DEPRECATED_HAL;
-import static android.system.OsConstants.*;
-
-import android.os.DeadObjectException;
-import android.os.RemoteException;
-
-import java.lang.reflect.Method;
-
-/**
- * Translate camera device status_t return values into exceptions.
- *
- * @see android.hardware.camera2.utils.CameraBinderDecorator#newInstance
- * @hide
- */
-public class CameraBinderDecorator {
-
-    public static final int NO_ERROR = 0;
-    public static final int PERMISSION_DENIED = -EPERM;
-    public static final int ALREADY_EXISTS = -EEXIST;
-    public static final int BAD_VALUE = -EINVAL;
-    public static final int DEAD_OBJECT = -ENOSYS;
-    public static final int INVALID_OPERATION = -EPIPE;
-    public static final int TIMED_OUT = -ETIMEDOUT;
-
-    /**
-     * TODO: add as error codes in Errors.h
-     * - POLICY_PROHIBITS
-     * - RESOURCE_BUSY
-     * - NO_SUCH_DEVICE
-     * - NOT_SUPPORTED
-     * - TOO_MANY_USERS
-     */
-
-    static class CameraBinderDecoratorListener implements Decorator.DecoratorListener {
-
-        @Override
-        public void onBeforeInvocation(Method m, Object[] args) {
-        }
-
-        @Override
-        public void onAfterInvocation(Method m, Object[] args, Object result) {
-            // int return type => status_t => convert to exception
-            if (m.getReturnType() == Integer.TYPE) {
-                int returnValue = (Integer) result;
-                throwOnError(returnValue);
-            }
-        }
-
-        @Override
-        public boolean onCatchException(Method m, Object[] args, Throwable t) {
-
-            if (t instanceof DeadObjectException) {
-                throw new CameraRuntimeException(CAMERA_DISCONNECTED,
-                        "Process hosting the camera service has died unexpectedly",
-                        t);
-            } else if (t instanceof RemoteException) {
-                throw new UnsupportedOperationException("An unknown RemoteException was thrown" +
-                        " which should never happen.", t);
-            }
-
-            return false;
-        }
-
-        @Override
-        public void onFinally(Method m, Object[] args) {
-        }
-
-    }
-
-    /**
-     * Throw error codes returned by the camera service as exceptions.
-     *
-     * @param errorFlag error to throw as an exception.
-     */
-    public static void throwOnError(int errorFlag) {
-        if (errorFlag == NO_ERROR) {
-            return;
-        } else if (errorFlag == PERMISSION_DENIED) {
-            throw new SecurityException("Lacking privileges to access camera service");
-        } else if (errorFlag == ALREADY_EXISTS) {
-            // This should be handled at the call site. Typically this isn't bad,
-            // just means we tried to do an operation that already completed.
-            return;
-        } else if (errorFlag == BAD_VALUE) {
-            throw new IllegalArgumentException("Bad argument passed to camera service");
-        } else if (errorFlag == DEAD_OBJECT) {
-            throw new CameraRuntimeException(CAMERA_DISCONNECTED);
-        } else if (errorFlag == TIMED_OUT) {
-            throw new CameraRuntimeException(CAMERA_ERROR,
-                    "Operation timed out in camera service");
-        } else if (errorFlag == -EACCES) {
-            throw new CameraRuntimeException(CAMERA_DISABLED);
-        } else if (errorFlag == -EBUSY) {
-            throw new CameraRuntimeException(CAMERA_IN_USE);
-        } else if (errorFlag == -EUSERS) {
-            throw new CameraRuntimeException(MAX_CAMERAS_IN_USE);
-        } else if (errorFlag == -ENODEV) {
-            throw new CameraRuntimeException(CAMERA_DISCONNECTED);
-        } else if (errorFlag == -EOPNOTSUPP) {
-            throw new CameraRuntimeException(CAMERA_DEPRECATED_HAL);
-        } else if (errorFlag == INVALID_OPERATION) {
-            throw new CameraRuntimeException(CAMERA_ERROR,
-                    "Illegal state encountered in camera service.");
-        }
-
-        /**
-         * Trap the rest of the negative return values. If we have known
-         * error codes i.e. ALREADY_EXISTS that aren't really runtime
-         * errors, then add them to the top switch statement
-         */
-        if (errorFlag < 0) {
-            throw new CameraRuntimeException(CAMERA_ERROR,
-                    String.format("Unknown camera device error %d", errorFlag));
-        }
-    }
-
-    /**
-     * <p>
-     * Wraps the type T with a proxy that will check 'status_t' return codes
-     * from the native side of the camera service, and throw Java exceptions
-     * automatically based on the code.
-     * </p>
-     * <p>
-     * In addition it also rewrites binder's RemoteException into either a
-     * CameraAccessException or an UnsupportedOperationException.
-     * </p>
-     * <p>
-     * As a result of calling any method on the proxy, RemoteException is
-     * guaranteed never to be thrown.
-     * </p>
-     *
-     * @param obj object that will serve as the target for all method calls
-     * @param <T> the type of the element you want to wrap. This must be an interface.
-     * @return a proxy that will intercept all invocations to obj
-     */
-    public static <T> T newInstance(T obj) {
-        return Decorator.<T> newInstance(obj, new CameraBinderDecoratorListener());
-    }
-}
diff --git a/core/java/android/hardware/camera2/utils/CameraRuntimeException.java b/core/java/android/hardware/camera2/utils/CameraRuntimeException.java
deleted file mode 100644
index 9ed88a9..0000000
--- a/core/java/android/hardware/camera2/utils/CameraRuntimeException.java
+++ /dev/null
@@ -1,63 +0,0 @@
-package android.hardware.camera2.utils;
-
-import android.hardware.camera2.CameraAccessException;
-
-/**
- * @hide
- */
-public class CameraRuntimeException extends RuntimeException {
-
-    private final int mReason;
-    private String mMessage;
-    private Throwable mCause;
-
-    public final int getReason() {
-        return mReason;
-    }
-
-    public CameraRuntimeException(int problem) {
-        super();
-        mReason = problem;
-    }
-
-    public CameraRuntimeException(int problem, String message) {
-        super(message);
-        mReason = problem;
-        mMessage = message;
-    }
-
-    public CameraRuntimeException(int problem, String message, Throwable cause) {
-        super(message, cause);
-        mReason = problem;
-        mMessage = message;
-        mCause = cause;
-    }
-
-    public CameraRuntimeException(int problem, Throwable cause) {
-        super(cause);
-        mReason = problem;
-        mCause = cause;
-    }
-
-    /**
-     * Recreate this exception as the CameraAccessException equivalent.
-     * @return CameraAccessException
-     */
-    public CameraAccessException asChecked() {
-        CameraAccessException e;
-
-        if (mMessage != null && mCause != null) {
-            e = new CameraAccessException(mReason, mMessage, mCause);
-        } else if (mMessage != null) {
-            e = new CameraAccessException(mReason, mMessage);
-        } else if (mCause != null) {
-            e = new CameraAccessException(mReason, mCause);
-        } else {
-            e = new CameraAccessException(mReason);
-        }
-        // throw and catch, so java has a chance to fill out the stack trace
-        e.setStackTrace(this.getStackTrace());
-
-        return e;
-    }
-}
diff --git a/core/java/android/hardware/camera2/utils/CameraServiceBinderDecorator.java b/core/java/android/hardware/camera2/utils/CameraServiceBinderDecorator.java
deleted file mode 100644
index c1fb6b1..0000000
--- a/core/java/android/hardware/camera2/utils/CameraServiceBinderDecorator.java
+++ /dev/null
@@ -1,70 +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.hardware.camera2.utils;
-
-import android.os.DeadObjectException;
-import android.os.RemoteException;
-import android.util.Log;
-
-import java.lang.reflect.Method;
-
-/**
- * Translate camera service status_t return values into exceptions.
- *
- * @see android.hardware.camera2.utils.CameraBinderDecorator#newInstance
- * @hide
- */
-public class CameraServiceBinderDecorator extends CameraBinderDecorator {
-
-    private static final String TAG = "CameraServiceBinderDecorator";
-
-    static class CameraServiceBinderDecoratorListener
-            extends CameraBinderDecorator.CameraBinderDecoratorListener {
-
-        // Pass through remote exceptions, unlike CameraBinderDecorator
-        @Override
-        public boolean onCatchException(Method m, Object[] args, Throwable t) {
-
-            if (t instanceof DeadObjectException) {
-                // Can sometimes happen (camera service died)
-                // Pass on silently
-            } else if (t instanceof RemoteException) {
-                // Some other kind of remote exception - this is not normal, so let's at least
-                // note it before moving on
-                Log.e(TAG, "Unexpected RemoteException from camera service call.", t);
-            }
-            // All other exceptions also get sent onward
-            return false;
-        }
-
-    }
-
-    /**
-     * <p>
-     * Wraps the type T with a proxy that will check 'status_t' return codes
-     * from the native side of the camera service, and throw Java exceptions
-     * automatically based on the code.
-     * </p>
-     *
-     * @param obj object that will serve as the target for all method calls
-     * @param <T> the type of the element you want to wrap. This must be an interface.
-     * @return a proxy that will intercept all invocations to obj
-     */
-    public static <T> T newInstance(T obj) {
-        return Decorator.<T> newInstance(obj, new CameraServiceBinderDecoratorListener());
-    }
-}
diff --git a/core/java/android/hardware/camera2/utils/Decorator.java b/core/java/android/hardware/camera2/utils/Decorator.java
deleted file mode 100644
index 5826497..0000000
--- a/core/java/android/hardware/camera2/utils/Decorator.java
+++ /dev/null
@@ -1,92 +0,0 @@
-
-package android.hardware.camera2.utils;
-
-import java.lang.reflect.*;
-
-/**
- * This is an implementation of the 'decorator' design pattern using Java's proxy mechanism.
- *
- * @see android.hardware.camera2.utils.Decorator#newInstance
- *
- * @hide
- */
-public class Decorator<T> implements InvocationHandler {
-
-    public interface DecoratorListener {
-        /**
-         * This method is called before the target method is invoked
-         * @param args arguments to target method
-         * @param m Method being called
-         */
-        void onBeforeInvocation(Method m, Object[] args);
-        /**
-         * This function is called after the target method is invoked
-         * if there were no uncaught exceptions
-         * @param args arguments to target method
-         * @param m Method being called
-         * @param result return value of target method
-         */
-        void onAfterInvocation(Method m, Object[] args, Object result);
-        /**
-         * This method is called only if there was an exception thrown by the target method
-         * during its invocation.
-         *
-         * @param args arguments to target method
-         * @param m Method being called
-         * @param t Throwable that was thrown
-         * @return false to rethrow exception, true if the exception was handled
-         */
-        boolean onCatchException(Method m, Object[] args, Throwable t);
-        /**
-         * This is called after the target method is invoked, regardless of whether or not
-         * there were any exceptions.
-         * @param args arguments to target method
-         * @param m Method being called
-         */
-        void onFinally(Method m, Object[] args);
-    }
-
-    private final T mObject;
-    private final DecoratorListener mListener;
-
-    /**
-     * Create a decorator wrapping the specified object's method calls.
-     *
-     * @param obj the object whose method calls you want to intercept
-     * @param listener the decorator handler for intercepted method calls
-     * @param <T> the type of the element you want to wrap. This must be an interface.
-     * @return a wrapped interface-compatible T
-     */
-    @SuppressWarnings("unchecked")
-    public static<T> T newInstance(T obj, DecoratorListener listener) {
-        return (T)java.lang.reflect.Proxy.newProxyInstance(
-                obj.getClass().getClassLoader(),
-                obj.getClass().getInterfaces(),
-                new Decorator<T>(obj, listener));
-    }
-
-    private Decorator(T obj, DecoratorListener listener) {
-        this.mObject = obj;
-        this.mListener = listener;
-    }
-
-    @Override
-    public Object invoke(Object proxy, Method m, Object[] args)
-            throws Throwable
-    {
-        Object result = null;
-        try {
-            mListener.onBeforeInvocation(m, args);
-            result = m.invoke(mObject, args);
-            mListener.onAfterInvocation(m, args, result);
-        } catch (InvocationTargetException e) {
-            Throwable t = e.getTargetException();
-            if (!mListener.onCatchException(m, args, t)) {
-                throw t;
-            }
-        } finally {
-            mListener.onFinally(m, args);
-        }
-        return result;
-    }
-}
diff --git a/core/java/android/hardware/camera2/utils/SubmitInfo.java b/core/java/android/hardware/camera2/utils/SubmitInfo.java
new file mode 100644
index 0000000..d1692b5
--- /dev/null
+++ b/core/java/android/hardware/camera2/utils/SubmitInfo.java
@@ -0,0 +1,106 @@
+/*
+ * 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.hardware.camera2.utils;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.hardware.camera2.ICameraDeviceUser;
+
+/**
+ * The status information returned for a successful capture request submission.
+ *
+ * Includes the request ID for the newly submitted capture request, and the
+ * last frame number of either the previous repeating request (for repeating
+ * requests), or of the request(s) just submitted (for single-shot capture).
+ *
+ * @hide
+ */
+public class SubmitInfo implements Parcelable {
+
+    private int mRequestId;
+    private long mLastFrameNumber;
+
+    public SubmitInfo() {
+        mRequestId = -1;
+        mLastFrameNumber = ICameraDeviceUser.NO_IN_FLIGHT_REPEATING_FRAMES;
+    }
+
+    public SubmitInfo(int requestId, long lastFrameNumber) {
+        mRequestId = requestId;
+        mLastFrameNumber = lastFrameNumber;
+    }
+
+    public static final Parcelable.Creator<SubmitInfo> CREATOR =
+            new Parcelable.Creator<SubmitInfo>() {
+        @Override
+        public SubmitInfo createFromParcel(Parcel in) {
+            return new SubmitInfo(in);
+        }
+
+        @Override
+        public SubmitInfo[] newArray(int size) {
+            return new SubmitInfo[size];
+        }
+    };
+
+    private SubmitInfo(Parcel in) {
+        readFromParcel(in);
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeInt(mRequestId);
+        dest.writeLong(mLastFrameNumber);
+    }
+
+    public void readFromParcel(Parcel in) {
+        mRequestId = in.readInt();
+        mLastFrameNumber = in.readLong();
+    }
+
+    /**
+     * Return the request ID for the submitted capture request/burst.
+     *
+     * This is used to track the completion status of the requested captures,
+     * and to cancel repeating requests.
+     */
+    public int getRequestId() {
+        return mRequestId;
+    }
+
+    /**
+     * Return the last frame number for the submitted capture request/burst.
+     *
+     * For a repeating request, this is the last frame number of the _prior_
+     * repeating request, to indicate when to fire the sequence completion callback
+     * for the prior repeating request.
+     *
+     * For a single-shot capture, this is the last frame number of _this_
+     * burst, to indicate when to fire the sequence completion callback for the request itself.
+     *
+     * For a repeating request, may be NO_IN_FLIGHT_REPEATING_FRAMES, if no
+     * instances of a prior repeating request were actually issued to the camera device.
+     */
+    public long getLastFrameNumber() {
+        return mLastFrameNumber;
+    }
+
+}
diff --git a/core/java/android/hardware/display/DisplayManagerGlobal.java b/core/java/android/hardware/display/DisplayManagerGlobal.java
index 121a187..93da3e5 100644
--- a/core/java/android/hardware/display/DisplayManagerGlobal.java
+++ b/core/java/android/hardware/display/DisplayManagerGlobal.java
@@ -132,8 +132,7 @@
                 return info;
             }
         } catch (RemoteException ex) {
-            Log.e(TAG, "Could not get display information from display manager.", ex);
-            return null;
+            throw ex.rethrowFromSystemServer();
         }
     }
 
@@ -159,8 +158,7 @@
                 return displayIds;
             }
         } catch (RemoteException ex) {
-            Log.e(TAG, "Could not get display ids from display manager.", ex);
-            return new int[] { Display.DEFAULT_DISPLAY };
+            throw ex.rethrowFromSystemServer();
         }
     }
 
@@ -237,8 +235,7 @@
             try {
                 mDm.registerCallback(mCallback);
             } catch (RemoteException ex) {
-                Log.e(TAG, "Failed to register callback with display manager service.", ex);
-                mCallback = null;
+                throw ex.rethrowFromSystemServer();
             }
         }
     }
@@ -267,7 +264,7 @@
                 try {
                     mDm.startWifiDisplayScan();
                 } catch (RemoteException ex) {
-                    Log.e(TAG, "Failed to scan for Wifi displays.", ex);
+                    throw ex.rethrowFromSystemServer();
                 }
             }
         }
@@ -279,7 +276,7 @@
                 try {
                     mDm.stopWifiDisplayScan();
                 } catch (RemoteException ex) {
-                    Log.e(TAG, "Failed to scan for Wifi displays.", ex);
+                    throw ex.rethrowFromSystemServer();
                 }
             } else if (mWifiDisplayScanNestCount < 0) {
                 Log.wtf(TAG, "Wifi display scan nest count became negative: "
@@ -297,7 +294,7 @@
         try {
             mDm.connectWifiDisplay(deviceAddress);
         } catch (RemoteException ex) {
-            Log.e(TAG, "Failed to connect to Wifi display " + deviceAddress + ".", ex);
+            throw ex.rethrowFromSystemServer();
         }
     }
 
@@ -305,7 +302,7 @@
         try {
             mDm.pauseWifiDisplay();
         } catch (RemoteException ex) {
-            Log.e(TAG, "Failed to pause Wifi display.", ex);
+            throw ex.rethrowFromSystemServer();
         }
     }
 
@@ -313,7 +310,7 @@
         try {
             mDm.resumeWifiDisplay();
         } catch (RemoteException ex) {
-            Log.e(TAG, "Failed to resume Wifi display.", ex);
+            throw ex.rethrowFromSystemServer();
         }
     }
 
@@ -321,7 +318,7 @@
         try {
             mDm.disconnectWifiDisplay();
         } catch (RemoteException ex) {
-            Log.e(TAG, "Failed to disconnect from Wifi display.", ex);
+            throw ex.rethrowFromSystemServer();
         }
     }
 
@@ -333,8 +330,7 @@
         try {
             mDm.renameWifiDisplay(deviceAddress, alias);
         } catch (RemoteException ex) {
-            Log.e(TAG, "Failed to rename Wifi display " + deviceAddress
-                    + " with alias " + alias + ".", ex);
+            throw ex.rethrowFromSystemServer();
         }
     }
 
@@ -346,7 +342,7 @@
         try {
             mDm.forgetWifiDisplay(deviceAddress);
         } catch (RemoteException ex) {
-            Log.e(TAG, "Failed to forget Wifi display.", ex);
+            throw ex.rethrowFromSystemServer();
         }
     }
 
@@ -354,8 +350,7 @@
         try {
             return mDm.getWifiDisplayStatus();
         } catch (RemoteException ex) {
-            Log.e(TAG, "Failed to get Wifi display status.", ex);
-            return new WifiDisplayStatus();
+            throw ex.rethrowFromSystemServer();
         }
     }
 
@@ -363,7 +358,7 @@
         try {
             mDm.requestColorTransform(displayId, colorTransformId);
         } catch (RemoteException ex) {
-            Log.e(TAG, "Failed to request color transform.", ex);
+            throw ex.rethrowFromSystemServer();
         }
     }
 
@@ -385,8 +380,7 @@
             displayId = mDm.createVirtualDisplay(callbackWrapper, projectionToken,
                     context.getPackageName(), name, width, height, densityDpi, surface, flags);
         } catch (RemoteException ex) {
-            Log.e(TAG, "Could not create virtual display: " + name, ex);
-            return null;
+            throw ex.rethrowFromSystemServer();
         }
         if (displayId < 0) {
             Log.e(TAG, "Could not create virtual display: " + name);
@@ -399,6 +393,7 @@
             try {
                 mDm.releaseVirtualDisplay(callbackWrapper);
             } catch (RemoteException ex) {
+                throw ex.rethrowFromSystemServer();
             }
             return null;
         }
@@ -409,7 +404,7 @@
         try {
             mDm.setVirtualDisplaySurface(token, surface);
         } catch (RemoteException ex) {
-            Log.w(TAG, "Failed to set virtual display surface.", ex);
+            throw ex.rethrowFromSystemServer();
         }
     }
 
@@ -418,7 +413,7 @@
         try {
             mDm.resizeVirtualDisplay(token, width, height, densityDpi);
         } catch (RemoteException ex) {
-            Log.w(TAG, "Failed to resize virtual display.", ex);
+            throw ex.rethrowFromSystemServer();
         }
     }
 
@@ -426,7 +421,7 @@
         try {
             mDm.releaseVirtualDisplay(token);
         } catch (RemoteException ex) {
-            Log.w(TAG, "Failed to release virtual display.", ex);
+            throw ex.rethrowFromSystemServer();
         }
     }
 
diff --git a/core/java/android/hardware/fingerprint/FingerprintManager.java b/core/java/android/hardware/fingerprint/FingerprintManager.java
index abd02f0..b8088f3 100644
--- a/core/java/android/hardware/fingerprint/FingerprintManager.java
+++ b/core/java/android/hardware/fingerprint/FingerprintManager.java
@@ -540,7 +540,7 @@
         if (mService != null) try {
             result = mService.preEnroll(mToken);
         } catch (RemoteException e) {
-            Log.w(TAG, "Remote exception in enroll: ", e);
+            throw e.rethrowFromSystemServer();
         }
         return result;
     }
@@ -555,7 +555,7 @@
         if (mService != null) try {
             result = mService.postEnroll(mToken);
         } catch (RemoteException e) {
-            Log.w(TAG, "Remote exception in post enroll: ", e);
+            throw e.rethrowFromSystemServer();
         }
         return result;
     }
@@ -571,7 +571,7 @@
         if (mService != null) try {
             mService.setActiveUser(userId);
         } catch (RemoteException e) {
-            Log.w(TAG, "Remote exception in setActiveUser: ", e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -614,7 +614,7 @@
             try {
                 mService.rename(fpId, userId, newName);
             } catch (RemoteException e) {
-                Log.v(TAG, "Remote exception in rename(): ", e);
+                throw e.rethrowFromSystemServer();
             }
         } else {
             Log.w(TAG, "rename(): Service not connected!");
@@ -632,7 +632,7 @@
         if (mService != null) try {
             return mService.getEnrolledFingerprints(userId, mContext.getOpPackageName());
         } catch (RemoteException e) {
-            Log.v(TAG, "Remote exception in getEnrolledFingerprints: ", e);
+            throw e.rethrowFromSystemServer();
         }
         return null;
     }
@@ -659,7 +659,7 @@
             return mService.hasEnrolledFingerprints(
                     UserHandle.myUserId(), mContext.getOpPackageName());
         } catch (RemoteException e) {
-            Log.v(TAG, "Remote exception in getEnrolledFingerprints: ", e);
+            throw e.rethrowFromSystemServer();
         }
         return false;
     }
@@ -674,7 +674,7 @@
         if (mService != null) try {
             return mService.hasEnrolledFingerprints(userId, mContext.getOpPackageName());
         } catch (RemoteException e) {
-            Log.v(TAG, "Remote exception in getEnrolledFingerprints: ", e);
+            throw e.rethrowFromSystemServer();
         }
         return false;
     }
@@ -691,7 +691,7 @@
                 long deviceId = 0; /* TODO: plumb hardware id to FPMS */
                 return mService.isHardwareDetected(deviceId, mContext.getOpPackageName());
             } catch (RemoteException e) {
-                Log.v(TAG, "Remote exception in isFingerprintHardwareDetected(): ", e);
+                throw e.rethrowFromSystemServer();
             }
         } else {
             Log.w(TAG, "isFingerprintHardwareDetected(): Service not connected!");
@@ -710,7 +710,7 @@
             try {
                 return mService.getAuthenticatorId(mContext.getOpPackageName());
             } catch (RemoteException e) {
-                Log.v(TAG, "Remote exception in getAuthenticatorId(): ", e);
+                throw e.rethrowFromSystemServer();
             }
         } else {
             Log.w(TAG, "getAuthenticatorId(): Service not connected!");
@@ -730,7 +730,7 @@
             try {
                 mService.resetTimeout(token);
             } catch (RemoteException e) {
-                Log.v(TAG, "Remote exception in resetTimeout(): ", e);
+                throw e.rethrowFromSystemServer();
             }
         } else {
             Log.w(TAG, "resetTimeout(): Service not connected!");
@@ -765,7 +765,7 @@
                     }
                 });
             } catch (RemoteException e) {
-                Log.v(TAG, "Remote exception in addLockoutResetCallback(): ", e);
+                throw e.rethrowFromSystemServer();
             }
         } else {
             Log.w(TAG, "addLockoutResetCallback(): Service not connected!");
@@ -881,8 +881,7 @@
         try {
             return ActivityManagerNative.getDefault().getCurrentUser().id;
         } catch (RemoteException e) {
-            Log.w(TAG, "Failed to get current user id\n");
-            return UserHandle.USER_NULL;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -890,7 +889,7 @@
         if (mService != null) try {
             mService.cancelEnrollment(mToken);
         } catch (RemoteException e) {
-            if (DEBUG) Log.w(TAG, "Remote exception while canceling enrollment");
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -898,7 +897,7 @@
         if (mService != null) try {
             mService.cancelAuthentication(mToken, mContext.getOpPackageName());
         } catch (RemoteException e) {
-            if (DEBUG) Log.w(TAG, "Remote exception while canceling enrollment");
+            throw e.rethrowFromSystemServer();
         }
     }
 
diff --git a/core/java/android/hardware/hdmi/HdmiControlManager.java b/core/java/android/hardware/hdmi/HdmiControlManager.java
index 6effc0d..ff87b67 100644
--- a/core/java/android/hardware/hdmi/HdmiControlManager.java
+++ b/core/java/android/hardware/hdmi/HdmiControlManager.java
@@ -267,7 +267,7 @@
             try {
                 types = mService.getSupportedTypes();
             } catch (RemoteException e) {
-                // Do nothing.
+                throw e.rethrowFromSystemServer();
             }
         }
         mHasTvDevice = hasDeviceType(types, HdmiDeviceInfo.DEVICE_TV);
@@ -403,7 +403,7 @@
         try {
             mService.addHotplugEventListener(wrappedListener);
         } catch (RemoteException e) {
-            Log.e(TAG, "failed to add hotplug event listener: ", e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -425,7 +425,7 @@
         try {
             mService.removeHotplugEventListener(wrappedListener);
         } catch (RemoteException e) {
-            Log.e(TAG, "failed to remove hotplug event listener: ", e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
diff --git a/core/java/android/hardware/input/InputManager.java b/core/java/android/hardware/input/InputManager.java
index cbe3412..fbac58c 100644
--- a/core/java/android/hardware/input/InputManager.java
+++ b/core/java/android/hardware/input/InputManager.java
@@ -252,7 +252,7 @@
                 try {
                     inputDevice = mIm.getInputDevice(id);
                 } catch (RemoteException ex) {
-                    throw new RuntimeException("Could not get input device information.", ex);
+                    throw ex.rethrowFromSystemServer();
                 }
                 if (inputDevice != null) {
                     mInputDevices.setValueAt(index, inputDevice);
@@ -284,7 +284,7 @@
                     try {
                         inputDevice = mIm.getInputDevice(id);
                     } catch (RemoteException ex) {
-                        // Ignore the problem for the purposes of this method.
+                        throw ex.rethrowFromSystemServer();
                     }
                     if (inputDevice == null) {
                         continue;
@@ -384,8 +384,7 @@
         try {
             return mIm.isInTabletMode();
         } catch (RemoteException ex) {
-            Log.w(TAG, "Could not get tablet mode state", ex);
-            return SWITCH_STATE_UNKNOWN;
+            throw ex.rethrowFromSystemServer();
         }
     }
 
@@ -439,7 +438,7 @@
         try {
             mIm.registerTabletModeChangedListener(listener);
         } catch (RemoteException ex) {
-            throw new RuntimeException("Could not register tablet mode changed listener", ex);
+            throw ex.rethrowFromSystemServer();
         }
         mTabletModeChangedListener = listener;
         mOnTabletModeChangedListeners = new ArrayList<>();
@@ -471,8 +470,7 @@
         try {
             return mIm.getKeyboardLayouts();
         } catch (RemoteException ex) {
-            Log.w(TAG, "Could not get list of keyboard layout informations.", ex);
-            return new KeyboardLayout[0];
+            throw ex.rethrowFromSystemServer();
         }
     }
 
@@ -494,8 +492,7 @@
         try {
             return mIm.getKeyboardLayoutsForInputDevice(identifier);
         } catch (RemoteException ex) {
-            Log.w(TAG, "Could not get list of keyboard layouts for input device.", ex);
-            return new KeyboardLayout[0];
+            throw ex.rethrowFromSystemServer();
         }
     }
 
@@ -516,8 +513,7 @@
         try {
             return mIm.getKeyboardLayout(keyboardLayoutDescriptor);
         } catch (RemoteException ex) {
-            Log.w(TAG, "Could not get keyboard layout information.", ex);
-            return null;
+            throw ex.rethrowFromSystemServer();
         }
     }
 
@@ -534,8 +530,7 @@
         try {
             return mIm.getCurrentKeyboardLayoutForInputDevice(identifier);
         } catch (RemoteException ex) {
-            Log.w(TAG, "Could not get current keyboard layout for input device.", ex);
-            return null;
+            throw ex.rethrowFromSystemServer();
         }
     }
 
@@ -565,7 +560,7 @@
             mIm.setCurrentKeyboardLayoutForInputDevice(identifier,
                     keyboardLayoutDescriptor);
         } catch (RemoteException ex) {
-            Log.w(TAG, "Could not set current keyboard layout for input device.", ex);
+            throw ex.rethrowFromSystemServer();
         }
     }
 
@@ -585,8 +580,7 @@
         try {
             return mIm.getEnabledKeyboardLayoutsForInputDevice(identifier);
         } catch (RemoteException ex) {
-            Log.w(TAG, "Could not get keyboard layouts for input device.", ex);
-            return ArrayUtils.emptyArray(String.class);
+            throw ex.rethrowFromSystemServer();
         }
     }
 
@@ -614,7 +608,7 @@
         try {
             mIm.addKeyboardLayoutForInputDevice(identifier, keyboardLayoutDescriptor);
         } catch (RemoteException ex) {
-            Log.w(TAG, "Could not add keyboard layout for input device.", ex);
+            throw ex.rethrowFromSystemServer();
         }
     }
 
@@ -642,7 +636,7 @@
         try {
             mIm.removeKeyboardLayoutForInputDevice(identifier, keyboardLayoutDescriptor);
         } catch (RemoteException ex) {
-            Log.w(TAG, "Could not remove keyboard layout for input device.", ex);
+            throw ex.rethrowFromSystemServer();
         }
     }
 
@@ -664,8 +658,7 @@
             return mIm.getKeyboardLayoutForInputDevice(
                     identifier, inputMethodInfo, inputMethodSubtype);
         } catch (RemoteException ex) {
-            Log.w(TAG, "Could not set keyboard layout.", ex);
-            return null;
+            throw ex.rethrowFromSystemServer();
         }
     }
 
@@ -687,7 +680,7 @@
             mIm.setKeyboardLayoutForInputDevice(identifier, inputMethodInfo,
                     inputMethodSubtype, keyboardLayoutDescriptor);
         } catch (RemoteException ex) {
-            Log.w(TAG, "Could not set keyboard layout.", ex);
+            throw ex.rethrowFromSystemServer();
         }
     }
 
@@ -704,8 +697,7 @@
         try {
             return mIm.getTouchCalibrationForInputDevice(inputDeviceDescriptor, surfaceRotation);
         } catch (RemoteException ex) {
-            Log.w(TAG, "Could not get calibration matrix for input device.", ex);
-            return TouchCalibration.IDENTITY;
+            throw ex.rethrowFromSystemServer();
         }
     }
 
@@ -726,7 +718,7 @@
         try {
             mIm.setTouchCalibrationForInputDevice(inputDeviceDescriptor, surfaceRotation, calibration);
         } catch (RemoteException ex) {
-            Log.w(TAG, "Could not set calibration matrix for input device.", ex);
+            throw ex.rethrowFromSystemServer();
         }
     }
 
@@ -793,7 +785,7 @@
         try {
             mIm.tryPointerSpeed(speed);
         } catch (RemoteException ex) {
-            Log.w(TAG, "Could not set temporary pointer speed.", ex);
+            throw ex.rethrowFromSystemServer();
         }
     }
 
@@ -831,7 +823,7 @@
         try {
             mIm.hasKeys(id, InputDevice.SOURCE_ANY, keyCodes, ret);
         } catch (RemoteException e) {
-            // no fallback; just return the empty array
+            throw e.rethrowFromSystemServer();
         }
         return ret;
     }
@@ -871,7 +863,7 @@
         try {
             return mIm.injectInputEvent(event, mode);
         } catch (RemoteException ex) {
-            return false;
+            throw ex.rethrowFromSystemServer();
         }
     }
 
@@ -887,7 +879,7 @@
         try {
             mIm.setPointerIconShape(iconId);
         } catch (RemoteException ex) {
-            // Do nothing.
+            throw ex.rethrowFromSystemServer();
         }
     }
 
@@ -896,7 +888,7 @@
         try {
             mIm.setCustomPointerIcon(icon);
         } catch (RemoteException ex) {
-            // Do nothing.
+            throw ex.rethrowFromSystemServer();
         }
     }
 
@@ -914,7 +906,7 @@
         try {
             mIm.setPointerIconDetached(detached);
         } catch (RemoteException ex) {
-            // Do nothing.
+            throw ex.rethrowFromSystemServer();
         }
     }
 
@@ -924,8 +916,7 @@
             try {
                 mIm.registerInputDevicesChangedListener(listener);
             } catch (RemoteException ex) {
-                throw new RuntimeException(
-                        "Could not get register input device changed listener", ex);
+                throw ex.rethrowFromSystemServer();
             }
             mInputDevicesChangedListener = listener;
         }
@@ -935,7 +926,7 @@
             try {
                 ids = mIm.getInputDeviceIds();
             } catch (RemoteException ex) {
-                throw new RuntimeException("Could not get input device ids.", ex);
+                throw ex.rethrowFromSystemServer();
             }
 
             mInputDevices = new SparseArray<InputDevice>();
@@ -1175,7 +1166,7 @@
             try {
                 mIm.vibrate(mDeviceId, pattern, repeat, mToken);
             } catch (RemoteException ex) {
-                Log.w(TAG, "Failed to vibrate.", ex);
+                throw ex.rethrowFromSystemServer();
             }
         }
 
@@ -1184,7 +1175,7 @@
             try {
                 mIm.cancelVibrate(mDeviceId, mToken);
             } catch (RemoteException ex) {
-                Log.w(TAG, "Failed to cancel vibration.", ex);
+                throw ex.rethrowFromSystemServer();
             }
         }
     }
diff --git a/core/java/android/hardware/soundtrigger/SoundTrigger.java b/core/java/android/hardware/soundtrigger/SoundTrigger.java
index cc2b764..b635088 100644
--- a/core/java/android/hardware/soundtrigger/SoundTrigger.java
+++ b/core/java/android/hardware/soundtrigger/SoundTrigger.java
@@ -689,12 +689,19 @@
                 return false;
             if (triggerInData != other.triggerInData)
                 return false;
-            if (captureFormat.getSampleRate() != other.captureFormat.getSampleRate())
-                return false;
-            if (captureFormat.getEncoding() != other.captureFormat.getEncoding())
-                return false;
-            if (captureFormat.getChannelMask() != other.captureFormat.getChannelMask())
-                return false;
+            if (captureFormat == null) {
+                if (other.captureFormat != null)
+                    return false;
+            } else {
+                if (other.captureFormat == null)
+                    return false;
+                if (captureFormat.getSampleRate() != other.captureFormat.getSampleRate())
+                    return false;
+                if (captureFormat.getEncoding() != other.captureFormat.getEncoding())
+                    return false;
+                if (captureFormat.getChannelMask() != other.captureFormat.getChannelMask())
+                    return false;
+            }
             return true;
         }
 
@@ -1002,10 +1009,10 @@
                 int encoding = in.readInt();
                 int channelMask = in.readInt();
                 captureFormat = (new AudioFormat.Builder())
-                        .setChannelMask(channelMask)
-                        .setEncoding(encoding)
-                        .setSampleRate(sampleRate)
-                        .build();
+                    .setChannelMask(channelMask)
+                    .setEncoding(encoding)
+                    .setSampleRate(sampleRate)
+                    .build();
             }
             byte[] data = in.readBlob();
             KeyphraseRecognitionExtra[] keyphraseExtras =
diff --git a/core/java/android/hardware/usb/UsbManager.java b/core/java/android/hardware/usb/UsbManager.java
index 1e3bcd0..3792e5c 100644
--- a/core/java/android/hardware/usb/UsbManager.java
+++ b/core/java/android/hardware/usb/UsbManager.java
@@ -302,8 +302,7 @@
             }
             return result;
         } catch (RemoteException e) {
-            Log.e(TAG, "RemoteException in getDeviceList", e);
-            return null;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -347,8 +346,7 @@
                 return new UsbAccessory[] { accessory };
             }
         } catch (RemoteException e) {
-            Log.e(TAG, "RemoteException in getAccessoryList", e);
-            return null;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -362,8 +360,7 @@
         try {
             return mService.openAccessory(accessory);
         } catch (RemoteException e) {
-            Log.e(TAG, "RemoteException in openAccessory", e);
-            return null;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -380,8 +377,7 @@
         try {
             return mService.hasDevicePermission(device);
         } catch (RemoteException e) {
-            Log.e(TAG, "RemoteException in hasPermission", e);
-            return false;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -398,8 +394,7 @@
         try {
             return mService.hasAccessoryPermission(accessory);
         } catch (RemoteException e) {
-            Log.e(TAG, "RemoteException in hasPermission", e);
-            return false;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -425,7 +420,7 @@
         try {
             mService.requestDevicePermission(device, mContext.getPackageName(), pi);
         } catch (RemoteException e) {
-            Log.e(TAG, "RemoteException in requestPermission", e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -451,7 +446,7 @@
         try {
             mService.requestAccessoryPermission(accessory, mContext.getPackageName(), pi);
         } catch (RemoteException e) {
-            Log.e(TAG, "RemoteException in requestPermission", e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -466,7 +461,7 @@
         try {
             mService.grantDevicePermission(device, Process.myUid());
         } catch (RemoteException e) {
-            Log.e(TAG, "RemoteException in grantPermission", e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -486,8 +481,7 @@
         try {
             return mService.isFunctionEnabled(function);
         } catch (RemoteException e) {
-            Log.e(TAG, "RemoteException in setCurrentFunction", e);
-            return false;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -517,7 +511,7 @@
         try {
             mService.setCurrentFunction(function);
         } catch (RemoteException e) {
-            Log.e(TAG, "RemoteException in setCurrentFunction", e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -533,7 +527,7 @@
         try {
             mService.setUsbDataUnlocked(unlocked);
         } catch (RemoteException e) {
-            Log.e(TAG, "RemoteException in setUsbDataUnlocked", e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -554,9 +548,8 @@
         try {
             return mService.getPorts();
         } catch (RemoteException e) {
-            Log.e(TAG, "RemoteException in getPorts", e);
+            throw e.rethrowFromSystemServer();
         }
-        return null;
     }
 
     /**
@@ -573,9 +566,8 @@
         try {
             return mService.getPortStatus(port.getId());
         } catch (RemoteException e) {
-            Log.e(TAG, "RemoteException in getPortStatus", e);
+            throw e.rethrowFromSystemServer();
         }
-        return null;
     }
 
     /**
@@ -604,7 +596,7 @@
         try {
             mService.setPortRoles(port.getId(), powerRole, dataRole);
         } catch (RemoteException e) {
-            Log.e(TAG, "RemoteException in setPortRole", e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index 7004e97..5f1043b 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -45,10 +45,12 @@
 import android.telephony.SubscriptionManager;
 import android.util.ArrayMap;
 import android.util.Log;
+import android.util.SparseArray;
 
 import com.android.internal.telephony.ITelephony;
 import com.android.internal.telephony.PhoneConstants;
 import com.android.internal.util.Protocol;
+import com.android.internal.util.MessageUtils;
 
 import libcore.net.event.NetworkEventDispatcher;
 
@@ -79,6 +81,13 @@
 public class ConnectivityManager {
     private static final String TAG = "ConnectivityManager";
 
+    private static final SparseArray<String> sMagicDecoderRing = MessageUtils.findMessageNames(
+            new Class[]{ConnectivityManager.class}, new String[]{"CALLBACK_"});
+
+    private static final String whatToString(int what) {
+        return sMagicDecoderRing.get(what, Integer.toString(what));
+    }
+
     /**
      * A change in network connectivity has occurred. A default connection has either
      * been established or lost. The NetworkInfo for the affected network is
@@ -733,7 +742,7 @@
         try {
             return mService.getActiveNetworkInfo();
         } catch (RemoteException e) {
-            return null;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -753,7 +762,7 @@
         try {
             return mService.getActiveNetwork();
         } catch (RemoteException e) {
-            return null;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -777,7 +786,7 @@
         try {
             return mService.setAlwaysOnVpnPackage(userId, vpnPackage);
         } catch (RemoteException e) {
-            return false;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -794,7 +803,7 @@
         try {
             return mService.getAlwaysOnVpnPackage(userId);
         } catch (RemoteException e) {
-            return null;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -815,7 +824,7 @@
         try {
             return mService.getActiveNetworkInfoForUid(uid);
         } catch (RemoteException e) {
-            return null;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -839,7 +848,7 @@
         try {
             return mService.getNetworkInfo(networkType);
         } catch (RemoteException e) {
-            return null;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -859,7 +868,7 @@
         try {
             return mService.getNetworkInfoForNetwork(network);
         } catch (RemoteException e) {
-            return null;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -880,7 +889,7 @@
         try {
             return mService.getAllNetworkInfo();
         } catch (RemoteException e) {
-            return null;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -900,7 +909,7 @@
         try {
             return mService.getNetworkForType(networkType);
         } catch (RemoteException e) {
-            return null;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -916,7 +925,7 @@
         try {
             return mService.getAllNetworks();
         } catch (RemoteException e) {
-            return null;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -929,7 +938,7 @@
         try {
             return mService.getDefaultNetworkCapabilitiesForUser(userId);
         } catch (RemoteException e) {
-            return null;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -948,7 +957,7 @@
         try {
             return mService.getActiveLinkProperties();
         } catch (RemoteException e) {
-            return null;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -972,7 +981,7 @@
         try {
             return mService.getLinkPropertiesForType(networkType);
         } catch (RemoteException e) {
-            return null;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -989,7 +998,7 @@
         try {
             return mService.getLinkProperties(network);
         } catch (RemoteException e) {
-            return null;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1006,7 +1015,7 @@
         try {
             return mService.getNetworkCapabilities(network);
         } catch (RemoteException e) {
-            return null;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1024,7 +1033,7 @@
         try {
             return mService.getCaptivePortalServerUrl();
         } catch (RemoteException e) {
-            return null;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1324,7 +1333,9 @@
         int type = legacyTypeForNetworkCapabilities(netCap);
         try {
             delay = mService.getRestoreDefaultNetworkDelay(type);
-        } catch (RemoteException e) {}
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
         LegacyRequest l = new LegacyRequest();
         l.networkCapabilities = netCap;
         l.delay = delay;
@@ -1542,7 +1553,7 @@
         try {
             return mService.requestRouteToHostAddress(networkType, hostAddress.getAddress());
         } catch (RemoteException e) {
-            return false;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1598,7 +1609,7 @@
         try {
             return mService.getActiveNetworkQuotaInfo();
         } catch (RemoteException e) {
-            return null;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1617,7 +1628,9 @@
                 Log.d("ConnectivityManager", "getMobileDataEnabled()- subId=" + subId
                         + " retVal=" + retVal);
                 return retVal;
-            } catch (RemoteException e) { }
+            } catch (RemoteException e) {
+                throw e.rethrowFromSystemServer();
+            }
         }
         Log.d("ConnectivityManager", "getMobileDataEnabled()- remote exception retVal=false");
         return false;
@@ -1678,6 +1691,7 @@
             getNetworkManagementService().registerNetworkActivityListener(rl);
             mNetworkActivityListeners.put(l, rl);
         } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1695,6 +1709,7 @@
         try {
             getNetworkManagementService().unregisterNetworkActivityListener(rl);
         } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1710,8 +1725,8 @@
         try {
             return getNetworkManagementService().isNetworkActive();
         } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
         }
-        return false;
     }
 
     /**
@@ -1785,7 +1800,7 @@
         try {
             return mService.getTetherableIfaces();
         } catch (RemoteException e) {
-            return new String[0];
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1802,7 +1817,7 @@
         try {
             return mService.getTetheredIfaces();
         } catch (RemoteException e) {
-            return new String[0];
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1825,7 +1840,7 @@
         try {
             return mService.getTetheringErroredIfaces();
         } catch (RemoteException e) {
-            return new String[0];
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1839,7 +1854,7 @@
         try {
             return mService.getTetheredDhcpRanges();
         } catch (RemoteException e) {
-            return new String[0];
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1871,7 +1886,7 @@
         try {
             return mService.tether(iface);
         } catch (RemoteException e) {
-            return TETHER_ERROR_SERVICE_UNAVAIL;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1897,7 +1912,7 @@
         try {
             return mService.untether(iface);
         } catch (RemoteException e) {
-            return TETHER_ERROR_SERVICE_UNAVAIL;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1917,7 +1932,7 @@
         try {
             return mService.isTetheringSupported();
         } catch (RemoteException e) {
-            return false;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -2005,7 +2020,7 @@
         try {
             mService.stopTethering(type);
         } catch (RemoteException e) {
-            Log.e(TAG, "Exception trying to stop tethering.", e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -2025,7 +2040,7 @@
         try {
             return mService.getTetherableUsbRegexs();
         } catch (RemoteException e) {
-            return new String[0];
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -2045,7 +2060,7 @@
         try {
             return mService.getTetherableWifiRegexs();
         } catch (RemoteException e) {
-            return new String[0];
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -2065,7 +2080,7 @@
         try {
             return mService.getTetherableBluetoothRegexs();
         } catch (RemoteException e) {
-            return new String[0];
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -2090,7 +2105,7 @@
         try {
             return mService.setUsbTethering(enable);
         } catch (RemoteException e) {
-            return TETHER_ERROR_SERVICE_UNAVAIL;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -2135,7 +2150,7 @@
         try {
             return mService.getLastTetherError(iface);
         } catch (RemoteException e) {
-            return TETHER_ERROR_SERVICE_UNAVAIL;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -2153,6 +2168,7 @@
         try {
             mService.reportInetCondition(networkType, percentage);
         } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -2174,6 +2190,7 @@
             mService.reportNetworkConnectivity(network, true);
             mService.reportNetworkConnectivity(network, false);
         } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -2192,6 +2209,7 @@
         try {
             mService.reportNetworkConnectivity(network, hasConnectivity);
         } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -2211,6 +2229,7 @@
         try {
             mService.setGlobalProxy(p);
         } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -2225,7 +2244,7 @@
         try {
             return mService.getGlobalProxy();
         } catch (RemoteException e) {
-            return null;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -2247,7 +2266,7 @@
         try {
             return mService.getProxyForNetwork(network);
         } catch (RemoteException e) {
-            return null;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -2282,8 +2301,9 @@
     public boolean isNetworkSupported(int networkType) {
         try {
             return mService.isNetworkSupported(networkType);
-        } catch (RemoteException e) {}
-        return false;
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
     }
 
     /**
@@ -2303,7 +2323,7 @@
         try {
             return mService.isActiveNetworkMetered();
         } catch (RemoteException e) {
-            return false;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -2320,7 +2340,7 @@
         try {
             return mService.updateLockdownVpn();
         } catch (RemoteException e) {
-            return false;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -2339,6 +2359,7 @@
         try {
             timeOutMs = mService.checkMobileProvisioning(suggestedTimeOutMs);
         } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
         }
         return timeOutMs;
     }
@@ -2351,8 +2372,8 @@
         try {
             return mService.getMobileProvisioningUrl();
         } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
         }
-        return null;
     }
 
     /**
@@ -2369,6 +2390,7 @@
         try {
             mService.setProvisioningNotificationVisible(visible, networkType, action);
         } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -2385,6 +2407,7 @@
         try {
             mService.setAirplaneMode(enable);
         } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -2392,14 +2415,18 @@
     public void registerNetworkFactory(Messenger messenger, String name) {
         try {
             mService.registerNetworkFactory(messenger, name);
-        } catch (RemoteException e) { }
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
     }
 
     /** {@hide} */
     public void unregisterNetworkFactory(Messenger messenger) {
         try {
             mService.unregisterNetworkFactory(messenger);
-        } catch (RemoteException e) { }
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
     }
 
     /**
@@ -2412,7 +2439,7 @@
         try {
             return mService.registerNetworkAgent(messenger, ni, lp, nc, score, misc);
         } catch (RemoteException e) {
-            return NETID_UNSET;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -2563,9 +2590,11 @@
 
         @Override
         public void handleMessage(Message message) {
-            if (DBG) Log.d(TAG, "CM callback handler got msg " + message.what);
             NetworkRequest request = (NetworkRequest) getObject(message, NetworkRequest.class);
             Network network = (Network) getObject(message, Network.class);
+            if (DBG) {
+                Log.d(TAG, whatToString(message.what) + " for network " + network);
+            }
             switch (message.what) {
                 case CALLBACK_PRECHECK: {
                     NetworkCallback callback = getCallback(request, "PRECHECK");
@@ -2730,7 +2759,9 @@
                     sNetworkCallback.put(networkCallback.networkRequest, networkCallback);
                 }
             }
-        } catch (RemoteException e) {}
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
         if (networkCallback.networkRequest == null) decCallbackHandlerRefCount();
         return networkCallback.networkRequest;
     }
@@ -2893,7 +2924,9 @@
         checkPendingIntent(operation);
         try {
             mService.pendingRequestForNetwork(request.networkCapabilities, operation);
-        } catch (RemoteException e) {}
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
     }
 
     /**
@@ -2911,7 +2944,9 @@
         checkPendingIntent(operation);
         try {
             mService.releasePendingNetworkRequest(operation);
-        } catch (RemoteException e) {}
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
     }
 
     private void checkPendingIntent(PendingIntent intent) {
@@ -2970,7 +3005,9 @@
         checkPendingIntent(operation);
         try {
             mService.pendingListenForNetwork(request.networkCapabilities, operation);
-        } catch (RemoteException e) {}
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
     }
 
     /**
@@ -2988,7 +3025,7 @@
         try {
             return mService.requestBandwidthUpdate(network);
         } catch (RemoteException e) {
-            return false;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -3008,7 +3045,9 @@
         }
         try {
             mService.releaseNetworkRequest(networkCallback.networkRequest);
-        } catch (RemoteException e) {}
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
     }
 
     /**
@@ -3044,7 +3083,9 @@
     public void setAcceptUnvalidated(Network network, boolean accept, boolean always) {
         try {
             mService.setAcceptUnvalidated(network, accept, always);
-        } catch (RemoteException e) {}
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
     }
 
     /**
@@ -3055,6 +3096,7 @@
         try {
             mService.factoryReset();
         } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -3262,7 +3304,7 @@
         try {
             return getNetworkPolicyManager().getRestrictBackgroundByCaller();
         } catch (RemoteException e) {
-            return RESTRICT_BACKGROUND_STATUS_DISABLED;
+            throw e.rethrowFromSystemServer();
         }
     }
 }
diff --git a/core/java/android/net/ConnectivityMetricsEvent.java b/core/java/android/net/ConnectivityMetricsEvent.java
index d040a85..098f1e6 100644
--- a/core/java/android/net/ConnectivityMetricsEvent.java
+++ b/core/java/android/net/ConnectivityMetricsEvent.java
@@ -16,12 +16,11 @@
 
 package android.net;
 
-import android.annotation.SystemApi;
 import android.os.Parcel;
 import android.os.Parcelable;
 
-@SystemApi
-public class ConnectivityMetricsEvent implements Parcelable {
+/** {@hide} */
+public final class ConnectivityMetricsEvent implements Parcelable {
 
     /**  The time when this event was collected, as returned by System.currentTimeMillis(). */
     final public long timestamp;
diff --git a/core/java/android/net/DataUsageRequest.java b/core/java/android/net/DataUsageRequest.java
index 5e96cc1..8526584 100644
--- a/core/java/android/net/DataUsageRequest.java
+++ b/core/java/android/net/DataUsageRequest.java
@@ -29,7 +29,7 @@
  * If no {@code uid}s are set, callbacks are restricted to device-owners,
  * carrier-privileged apps, or system apps.
  */
-public class DataUsageRequest implements Parcelable {
+public final class DataUsageRequest implements Parcelable {
 
     /**
      * @hide
diff --git a/core/java/android/net/EthernetManager.java b/core/java/android/net/EthernetManager.java
index f45737a..664b7b4 100644
--- a/core/java/android/net/EthernetManager.java
+++ b/core/java/android/net/EthernetManager.java
@@ -87,8 +87,8 @@
     public IpConfiguration getConfiguration() {
         try {
             return mService.getConfiguration();
-        } catch (NullPointerException | RemoteException e) {
-            return new IpConfiguration();
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -98,7 +98,8 @@
     public void setConfiguration(IpConfiguration config) {
         try {
             mService.setConfiguration(config);
-        } catch (NullPointerException | RemoteException e) {
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -109,8 +110,8 @@
     public boolean isAvailable() {
         try {
             return mService.isAvailable();
-        } catch (NullPointerException | RemoteException e) {
-            return false;
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -127,7 +128,8 @@
         if (mListeners.size() == 1) {
             try {
                 mService.addListener(mServiceListener);
-            } catch (NullPointerException | RemoteException e) {
+            } catch (RemoteException e) {
+                throw e.rethrowFromSystemServer();
             }
         }
     }
@@ -145,7 +147,8 @@
         if (mListeners.isEmpty()) {
             try {
                 mService.removeListener(mServiceListener);
-            } catch (NullPointerException | RemoteException e) {
+            } catch (RemoteException e) {
+                throw e.rethrowFromSystemServer();
             }
         }
     }
diff --git a/core/java/android/net/NetworkAgent.java b/core/java/android/net/NetworkAgent.java
index 20c2168..9e360e1 100644
--- a/core/java/android/net/NetworkAgent.java
+++ b/core/java/android/net/NetworkAgent.java
@@ -200,6 +200,14 @@
      */
     public static final int CMD_PREVENT_AUTOMATIC_RECONNECT = BASE + 15;
 
+    /**
+     * Sent by ConnectivityService to the NetworkAgent to install an APF program in the network
+     * chipset for use to filter packets.
+     *
+     * obj = byte[] containing the APF program bytecode.
+     */
+    public static final int CMD_PUSH_APF_PROGRAM = BASE + 16;
+
     public NetworkAgent(Looper looper, Context context, String logTag, NetworkInfo ni,
             NetworkCapabilities nc, LinkProperties lp, int score) {
         this(looper, context, logTag, ni, nc, lp, score, null);
@@ -319,6 +327,10 @@
                 preventAutomaticReconnect();
                 break;
             }
+            case CMD_PUSH_APF_PROGRAM: {
+                installPacketFilter((byte[]) msg.obj);
+                break;
+            }
         }
     }
 
@@ -494,6 +506,15 @@
     protected void preventAutomaticReconnect() {
     }
 
+    /**
+     * Install a packet filter.
+     * @param filter an APF program to filter incoming packets.
+     * @return {@code true} if filter successfully installed, {@code false} otherwise.
+     */
+    protected boolean installPacketFilter(byte[] filter) {
+        return false;
+    }
+
     protected void log(String s) {
         Log.d(LOG_TAG, "NetworkAgent: " + s);
     }
diff --git a/core/java/android/net/NetworkMisc.java b/core/java/android/net/NetworkMisc.java
index 5511a24..748699e 100644
--- a/core/java/android/net/NetworkMisc.java
+++ b/core/java/android/net/NetworkMisc.java
@@ -56,6 +56,22 @@
      */
     public String subscriberId;
 
+    /**
+     * Version of APF instruction set supported for packet filtering. 0 indicates no support for
+     * packet filtering using APF programs.
+     */
+    public int apfVersionSupported;
+
+    /**
+     * Maximum size of APF program allowed.
+     */
+    public int maximumApfProgramSize;
+
+    /**
+     * Format of packets passed to APF filter. Should be one of ARPHRD_*
+     */
+    public int apfPacketFormat;
+
     public NetworkMisc() {
     }
 
@@ -65,6 +81,9 @@
             explicitlySelected = nm.explicitlySelected;
             acceptUnvalidated = nm.acceptUnvalidated;
             subscriberId = nm.subscriberId;
+            apfVersionSupported = nm.apfVersionSupported;
+            maximumApfProgramSize = nm.maximumApfProgramSize;
+            apfPacketFormat = nm.apfPacketFormat;
         }
     }
 
@@ -79,6 +98,9 @@
         out.writeInt(explicitlySelected ? 1 : 0);
         out.writeInt(acceptUnvalidated ? 1 : 0);
         out.writeString(subscriberId);
+        out.writeInt(apfVersionSupported);
+        out.writeInt(maximumApfProgramSize);
+        out.writeInt(apfPacketFormat);
     }
 
     public static final Creator<NetworkMisc> CREATOR = new Creator<NetworkMisc>() {
@@ -89,6 +111,9 @@
             networkMisc.explicitlySelected = in.readInt() != 0;
             networkMisc.acceptUnvalidated = in.readInt() != 0;
             networkMisc.subscriberId = in.readString();
+            networkMisc.apfVersionSupported = in.readInt();
+            networkMisc.maximumApfProgramSize = in.readInt();
+            networkMisc.apfPacketFormat = in.readInt();
             return networkMisc;
         }
 
diff --git a/core/java/android/net/NetworkPolicyManager.java b/core/java/android/net/NetworkPolicyManager.java
index a83e722..8738424 100644
--- a/core/java/android/net/NetworkPolicyManager.java
+++ b/core/java/android/net/NetworkPolicyManager.java
@@ -68,10 +68,12 @@
     public static final int FIREWALL_CHAIN_NONE = 0;
     public static final int FIREWALL_CHAIN_DOZABLE = 1;
     public static final int FIREWALL_CHAIN_STANDBY = 2;
+    public static final int FIREWALL_CHAIN_POWERSAVE = 3;
 
     public static final String FIREWALL_CHAIN_NAME_NONE = "none";
     public static final String FIREWALL_CHAIN_NAME_DOZABLE = "dozable";
     public static final String FIREWALL_CHAIN_NAME_STANDBY = "standby";
+    public static final String FIREWALL_CHAIN_NAME_POWERSAVE = "powersave";
 
     private static final boolean ALLOW_PLATFORM_APP_POLICY = true;
 
@@ -106,6 +108,7 @@
         try {
             mService.setUidPolicy(uid, policy);
         } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -118,6 +121,7 @@
         try {
             mService.addUidPolicy(uid, policy);
         } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -130,6 +134,7 @@
         try {
             mService.removeUidPolicy(uid, policy);
         } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -137,7 +142,7 @@
         try {
             return mService.getUidPolicy(uid);
         } catch (RemoteException e) {
-            return POLICY_NONE;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -145,7 +150,7 @@
         try {
             return mService.getUidsWithPolicy(policy);
         } catch (RemoteException e) {
-            return new int[0];
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -153,6 +158,7 @@
         try {
             mService.registerListener(listener);
         } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -160,6 +166,7 @@
         try {
             mService.unregisterListener(listener);
         } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -167,6 +174,7 @@
         try {
             mService.setNetworkPolicies(policies);
         } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -174,7 +182,7 @@
         try {
             return mService.getNetworkPolicies(mContext.getOpPackageName());
         } catch (RemoteException e) {
-            return null;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -182,6 +190,7 @@
         try {
             mService.setRestrictBackground(restrictBackground);
         } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -189,7 +198,7 @@
         try {
             return mService.getRestrictBackground();
         } catch (RemoteException e) {
-            return false;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -202,6 +211,7 @@
         try {
             mService.factoryReset(subscriber);
         } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
         }
     }
 
diff --git a/core/java/android/net/NetworkScoreManager.java b/core/java/android/net/NetworkScoreManager.java
index b6fe68a..01c160f 100644
--- a/core/java/android/net/NetworkScoreManager.java
+++ b/core/java/android/net/NetworkScoreManager.java
@@ -166,7 +166,7 @@
         try {
             return mService.updateScores(networks);
         } catch (RemoteException e) {
-            return false;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -186,7 +186,7 @@
         try {
             return mService.clearScores();
         } catch (RemoteException e) {
-            return false;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -206,7 +206,7 @@
         try {
             return mService.setActiveScorer(packageName);
         } catch (RemoteException e) {
-            return false;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -221,6 +221,7 @@
         try {
             mService.disableScoring();
         } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -265,6 +266,7 @@
         try {
             mService.registerNetworkScoreCache(networkType, scoreCache);
         } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
         }
     }
 }
diff --git a/core/java/android/net/NetworkUtils.java b/core/java/android/net/NetworkUtils.java
index c6d919f..555032d 100644
--- a/core/java/android/net/NetworkUtils.java
+++ b/core/java/android/net/NetworkUtils.java
@@ -62,6 +62,13 @@
     public native static void attachDhcpFilter(FileDescriptor fd) throws SocketException;
 
     /**
+     * Attaches a socket filter that accepts ICMP6 router advertisement packets to the given socket.
+     * @param fd the socket's {@link FileDescriptor}.
+     * @param packetType the hardware address type, one of ARPHRD_*.
+     */
+    public native static void attachRaFilter(FileDescriptor fd, int packetType) throws SocketException;
+
+    /**
      * Binds the current process to the network designated by {@code netId}.  All sockets created
      * in the future (and not explicitly bound via a bound {@link SocketFactory} (see
      * {@link Network#getSocketFactory}) will be bound to this network.  Note that if this
diff --git a/core/java/android/net/TrafficStats.java b/core/java/android/net/TrafficStats.java
index e82485d..95ffb44 100644
--- a/core/java/android/net/TrafficStats.java
+++ b/core/java/android/net/TrafficStats.java
@@ -19,6 +19,7 @@
 import android.annotation.SystemApi;
 import android.app.DownloadManager;
 import android.app.backup.BackupManager;
+import android.app.usage.NetworkStatsManager;
 import android.content.Context;
 import android.media.MediaPlayer;
 import android.os.RemoteException;
@@ -33,12 +34,16 @@
 import java.net.SocketException;
 
 /**
- * Class that provides network traffic statistics.  These statistics include
+ * Class that provides network traffic statistics. These statistics include
  * bytes transmitted and received and network packets transmitted and received,
  * over all interfaces, over the mobile interface, and on a per-UID basis.
  * <p>
- * These statistics may not be available on all platforms.  If the statistics
- * are not supported by this device, {@link #UNSUPPORTED} will be returned.
+ * These statistics may not be available on all platforms. If the statistics are
+ * not supported by this device, {@link #UNSUPPORTED} will be returned.
+ * <p>
+ * Note that the statistics returned by this class reset and start from zero
+ * after every reboot. To access more robust historical network statistics data,
+ * use {@link NetworkStatsManager} instead.
  */
 public class TrafficStats {
     /**
@@ -310,7 +315,7 @@
         try {
             getStatsService().incrementOperationCount(uid, tag, operationCount);
         } catch (RemoteException e) {
-            throw new RuntimeException(e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -497,14 +502,27 @@
      * monotonically since device boot. Statistics are measured at the network
      * layer, so they include both TCP and UDP usage.
      * <p>
-     * Before {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR2}, this may return
-     * {@link #UNSUPPORTED} on devices where statistics aren't available.
+     * Before {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR2}, this may
+     * return {@link #UNSUPPORTED} on devices where statistics aren't available.
+     * <p>
+     * Starting in {@link android.os.Build.VERSION_CODES#N} this will only
+     * report traffic statistics for the calling UID. It will return
+     * {@link #UNSUPPORTED} for all other UIDs for privacy reasons. To access
+     * historical network statistics belonging to other UIDs, use
+     * {@link NetworkStatsManager}.
      *
      * @see android.os.Process#myUid()
      * @see android.content.pm.ApplicationInfo#uid
      */
     public static long getUidTxBytes(int uid) {
-        return nativeGetUidStat(uid, TYPE_TX_BYTES);
+        // This isn't actually enforcing any security; it just returns the
+        // unsupported value. The real filtering is done at the kernel level.
+        final int callingUid = android.os.Process.myUid();
+        if (callingUid == android.os.Process.SYSTEM_UID || callingUid == uid) {
+            return nativeGetUidStat(uid, TYPE_TX_BYTES);
+        } else {
+            return UNSUPPORTED;
+        }
     }
 
     /**
@@ -515,12 +533,25 @@
      * <p>
      * Before {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR2}, this may return
      * {@link #UNSUPPORTED} on devices where statistics aren't available.
+     * <p>
+     * Starting in {@link android.os.Build.VERSION_CODES#N} this will only
+     * report traffic statistics for the calling UID. It will return
+     * {@link #UNSUPPORTED} for all other UIDs for privacy reasons. To access
+     * historical network statistics belonging to other UIDs, use
+     * {@link NetworkStatsManager}.
      *
      * @see android.os.Process#myUid()
      * @see android.content.pm.ApplicationInfo#uid
      */
     public static long getUidRxBytes(int uid) {
-        return nativeGetUidStat(uid, TYPE_RX_BYTES);
+        // This isn't actually enforcing any security; it just returns the
+        // unsupported value. The real filtering is done at the kernel level.
+        final int callingUid = android.os.Process.myUid();
+        if (callingUid == android.os.Process.SYSTEM_UID || callingUid == uid) {
+            return nativeGetUidStat(uid, TYPE_RX_BYTES);
+        } else {
+            return UNSUPPORTED;
+        }
     }
 
     /**
@@ -531,12 +562,25 @@
      * <p>
      * Before {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR2}, this may return
      * {@link #UNSUPPORTED} on devices where statistics aren't available.
+     * <p>
+     * Starting in {@link android.os.Build.VERSION_CODES#N} this will only
+     * report traffic statistics for the calling UID. It will return
+     * {@link #UNSUPPORTED} for all other UIDs for privacy reasons. To access
+     * historical network statistics belonging to other UIDs, use
+     * {@link NetworkStatsManager}.
      *
      * @see android.os.Process#myUid()
      * @see android.content.pm.ApplicationInfo#uid
      */
     public static long getUidTxPackets(int uid) {
-        return nativeGetUidStat(uid, TYPE_TX_PACKETS);
+        // This isn't actually enforcing any security; it just returns the
+        // unsupported value. The real filtering is done at the kernel level.
+        final int callingUid = android.os.Process.myUid();
+        if (callingUid == android.os.Process.SYSTEM_UID || callingUid == uid) {
+            return nativeGetUidStat(uid, TYPE_TX_PACKETS);
+        } else {
+            return UNSUPPORTED;
+        }
     }
 
     /**
@@ -547,12 +591,25 @@
      * <p>
      * Before {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR2}, this may return
      * {@link #UNSUPPORTED} on devices where statistics aren't available.
+     * <p>
+     * Starting in {@link android.os.Build.VERSION_CODES#N} this will only
+     * report traffic statistics for the calling UID. It will return
+     * {@link #UNSUPPORTED} for all other UIDs for privacy reasons. To access
+     * historical network statistics belonging to other UIDs, use
+     * {@link NetworkStatsManager}.
      *
      * @see android.os.Process#myUid()
      * @see android.content.pm.ApplicationInfo#uid
      */
     public static long getUidRxPackets(int uid) {
-        return nativeGetUidStat(uid, TYPE_RX_PACKETS);
+        // This isn't actually enforcing any security; it just returns the
+        // unsupported value. The real filtering is done at the kernel level.
+        final int callingUid = android.os.Process.myUid();
+        if (callingUid == android.os.Process.SYSTEM_UID || callingUid == uid) {
+            return nativeGetUidStat(uid, TYPE_RX_PACKETS);
+        } else {
+            return UNSUPPORTED;
+        }
     }
 
     /**
@@ -653,7 +710,7 @@
         try {
             return getStatsService().getDataLayerSnapshotForUid(uid);
         } catch (RemoteException e) {
-            throw new RuntimeException(e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -666,7 +723,7 @@
         try {
             return getStatsService().getMobileIfaces();
         } catch (RemoteException e) {
-            throw new RuntimeException(e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
diff --git a/core/java/android/net/nsd/NsdManager.java b/core/java/android/net/nsd/NsdManager.java
index 377ed88..86bd502 100644
--- a/core/java/android/net/nsd/NsdManager.java
+++ b/core/java/android/net/nsd/NsdManager.java
@@ -619,7 +619,9 @@
     public void setEnabled(boolean enabled) {
         try {
             mService.setEnabled(enabled);
-        } catch (RemoteException e) { }
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
     }
 
     /**
@@ -632,7 +634,7 @@
         try {
             return mService.getMessenger();
         } catch (RemoteException e) {
-            return null;
+            throw e.rethrowFromSystemServer();
         }
     }
 }
diff --git a/core/java/android/os/BaseBundle.java b/core/java/android/os/BaseBundle.java
index ee7bd9a..5c71373 100644
--- a/core/java/android/os/BaseBundle.java
+++ b/core/java/android/os/BaseBundle.java
@@ -235,6 +235,12 @@
         return mParcelledData != null;
     }
 
+    /** @hide */
+    ArrayMap<String, Object> getMap() {
+        unparcel();
+        return mMap;
+    }
+
     /**
      * Returns the number of mappings contained in this Bundle.
      *
diff --git a/core/java/android/os/BatteryManager.java b/core/java/android/os/BatteryManager.java
index 56cb250..e40ebf7 100644
--- a/core/java/android/os/BatteryManager.java
+++ b/core/java/android/os/BatteryManager.java
@@ -221,7 +221,7 @@
         try {
             return mBatteryStats.isCharging();
         } catch (RemoteException e) {
-            return true;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -246,7 +246,7 @@
             else
                 ret = Long.MIN_VALUE;
         } catch (RemoteException e) {
-            ret = Long.MIN_VALUE;
+            throw e.rethrowFromSystemServer();
         }
 
         return ret;
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index 8281279..e1c7ad77 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -465,6 +465,7 @@
         };
 
         public abstract long getProcessStateTime(int state, long elapsedRealtimeUs, int which);
+        public abstract Timer getProcessStateTimer(int state);
 
         public abstract Timer getVibratorOnTimer();
 
diff --git a/media/mca/effect/java/android/media/effect/package-info.java b/core/java/android/os/DeadSystemException.java
similarity index 63%
copy from media/mca/effect/java/android/media/effect/package-info.java
copy to core/java/android/os/DeadSystemException.java
index b2c14ff..595365c 100644
--- a/media/mca/effect/java/android/media/effect/package-info.java
+++ b/core/java/android/os/DeadSystemException.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2011 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.
@@ -14,15 +14,14 @@
  * limitations under the License.
  */
 
-
-package android.media.effect;
+package android.os;
 
 /**
- * <h1>Effect Framework</h1>
- *
- * This package includes a collection of high-performance visual effects that make use of the
- * mobile filter framework subsystem.
- *
- * TODO: More Documentation
- *
+ * The core Android system has died and is going through a runtime restart. All
+ * running apps will be promptly be killed.
  */
+public class DeadSystemException extends DeadObjectException {
+    public DeadSystemException() {
+        super();
+    }
+}
diff --git a/core/java/android/os/Debug.java b/core/java/android/os/Debug.java
index e58744b..f382241 100644
--- a/core/java/android/os/Debug.java
+++ b/core/java/android/os/Debug.java
@@ -98,13 +98,15 @@
     /**
      * Default trace file path and file
      */
-    private static final String DEFAULT_TRACE_PATH_PREFIX =
-        Environment.getLegacyExternalStorageDirectory().getPath() + "/";
     private static final String DEFAULT_TRACE_BODY = "dmtrace";
     private static final String DEFAULT_TRACE_EXTENSION = ".trace";
-    private static final String DEFAULT_TRACE_FILE_PATH =
-        DEFAULT_TRACE_PATH_PREFIX + DEFAULT_TRACE_BODY
-        + DEFAULT_TRACE_EXTENSION;
+    private static class NoPreloadHolder {
+        private static final String DEFAULT_TRACE_PATH_PREFIX =
+                Environment.getLegacyExternalStorageDirectory().getPath() + "/";
+        private static final String DEFAULT_TRACE_FILE_PATH =
+                DEFAULT_TRACE_PATH_PREFIX + DEFAULT_TRACE_BODY
+                + DEFAULT_TRACE_EXTENSION;
+    }
 
 
     /**
@@ -942,7 +944,7 @@
      * tracing.
      */
     public static void startMethodTracing() {
-        VMDebug.startMethodTracing(DEFAULT_TRACE_FILE_PATH, 0, 0, false, 0);
+        VMDebug.startMethodTracing(fixTraceName(null), 0, 0, false, 0);
     }
 
     /**
@@ -1032,9 +1034,9 @@
      */
     private static String fixTraceName(String traceName) {
         if (traceName == null)
-            traceName = DEFAULT_TRACE_FILE_PATH;
+            traceName = NoPreloadHolder.DEFAULT_TRACE_FILE_PATH;
         if (traceName.charAt(0) != '/')
-            traceName = DEFAULT_TRACE_PATH_PREFIX + traceName;
+            traceName = NoPreloadHolder.DEFAULT_TRACE_PATH_PREFIX + traceName;
         if (!traceName.endsWith(DEFAULT_TRACE_EXTENSION))
             traceName = traceName + DEFAULT_TRACE_EXTENSION;
 
@@ -2158,6 +2160,14 @@
     public static native void dumpNativeBacktraceToFile(int pid, String file);
 
     /**
+     * Get description of unreachable native memory.
+     * @param limit the number of leaks to provide info on, 0 to only get a summary.
+     * @param contents true to include a hex dump of the contents of unreachable memory.
+     * @return the String containing a description of unreachable memory.
+     * @hide */
+    public static native String getUnreachableMemory(int limit, boolean contents);
+
+    /**
      * Return a String describing the calling method and location at a particular stack depth.
      * @param callStack the Thread stack
      * @param depth the depth of stack to return information for.
diff --git a/core/java/android/os/DropBoxManager.java b/core/java/android/os/DropBoxManager.java
index 2b14468..cb85eef 100644
--- a/core/java/android/os/DropBoxManager.java
+++ b/core/java/android/os/DropBoxManager.java
@@ -16,6 +16,9 @@
 
 package android.os;
 
+import android.content.Context;
+import android.util.Log;
+
 import com.android.internal.os.IDropBoxManagerService;
 
 import java.io.ByteArrayInputStream;
@@ -40,6 +43,8 @@
  */
 public class DropBoxManager {
     private static final String TAG = "DropBoxManager";
+
+    private final Context mContext;
     private final IDropBoxManagerService mService;
 
     /** Flag value: Entry's content was deleted to save space. */
@@ -249,14 +254,20 @@
     }
 
     /** {@hide} */
-    public DropBoxManager(IDropBoxManagerService service) { mService = service; }
+    public DropBoxManager(Context context, IDropBoxManagerService service) {
+        mContext = context;
+        mService = service;
+    }
 
     /**
      * Create a dummy instance for testing.  All methods will fail unless
      * overridden with an appropriate mock implementation.  To obtain a
      * functional instance, use {@link android.content.Context#getSystemService}.
      */
-    protected DropBoxManager() { mService = null; }
+    protected DropBoxManager() {
+        mContext = null;
+        mService = null;
+    }
 
     /**
      * Stores human-readable text.  The data may be discarded eventually (or even
@@ -267,7 +278,16 @@
      * @param data value to store
      */
     public void addText(String tag, String data) {
-        try { mService.add(new Entry(tag, 0, data)); } catch (RemoteException e) {}
+        try {
+            mService.add(new Entry(tag, 0, data));
+        } catch (RemoteException e) {
+            if (e instanceof TransactionTooLargeException
+                    && mContext.getApplicationInfo().targetSdkVersion < Build.VERSION_CODES.N) {
+                Log.e(TAG, "App sent too much data, so it was ignored", e);
+                return;
+            }
+            throw e.rethrowFromSystemServer();
+        }
     }
 
     /**
@@ -279,7 +299,16 @@
      */
     public void addData(String tag, byte[] data, int flags) {
         if (data == null) throw new NullPointerException("data == null");
-        try { mService.add(new Entry(tag, 0, data, flags)); } catch (RemoteException e) {}
+        try {
+            mService.add(new Entry(tag, 0, data, flags));
+        } catch (RemoteException e) {
+            if (e instanceof TransactionTooLargeException
+                    && mContext.getApplicationInfo().targetSdkVersion < Build.VERSION_CODES.N) {
+                Log.e(TAG, "App sent too much data, so it was ignored", e);
+                return;
+            }
+            throw e.rethrowFromSystemServer();
+        }
     }
 
     /**
@@ -297,7 +326,7 @@
         try {
             mService.add(entry);
         } catch (RemoteException e) {
-            // ignore
+            throw e.rethrowFromSystemServer();
         } finally {
             entry.close();
         }
@@ -312,7 +341,11 @@
      * @return whether events with that tag would be accepted
      */
     public boolean isTagEnabled(String tag) {
-        try { return mService.isTagEnabled(tag); } catch (RemoteException e) { return false; }
+        try {
+            return mService.isTagEnabled(tag);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
     }
 
     /**
@@ -325,7 +358,11 @@
      * @return the next entry, or null if there are no more entries
      */
     public Entry getNextEntry(String tag, long msec) {
-        try { return mService.getNextEntry(tag, msec); } catch (RemoteException e) { return null; }
+        try {
+            return mService.getNextEntry(tag, msec);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
     }
 
     // TODO: It may be useful to have some sort of notification mechanism
diff --git a/core/java/android/os/Environment.java b/core/java/android/os/Environment.java
index 1085b1e..307bd2d 100644
--- a/core/java/android/os/Environment.java
+++ b/core/java/android/os/Environment.java
@@ -258,6 +258,20 @@
         return buildPath(getDataDirectory(), "misc_de", String.valueOf(userId));
     }
 
+    private static File getDataProfilesDeDirectory(int userId) {
+        return buildPath(getDataDirectory(), "misc", "profiles", "cur", String.valueOf(userId));
+    }
+
+    /** {@hide} */
+    public static File getDataProfilesDePackageDirectory(int userId, String packageName) {
+        return buildPath(getDataProfilesDeDirectory(userId), packageName);
+    }
+
+    /** {@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");
@@ -493,7 +507,7 @@
      * </ul>
      * @hide
      */
-    private static final String[] STANDARD_DIRECTORIES = {
+    public static final String[] STANDARD_DIRECTORIES = {
             DIRECTORY_MUSIC,
             DIRECTORY_PODCASTS,
             DIRECTORY_RINGTONES,
diff --git a/core/java/android/os/HardwarePropertiesManager.java b/core/java/android/os/HardwarePropertiesManager.java
index c72a6481..9ca1dcd 100644
--- a/core/java/android/os/HardwarePropertiesManager.java
+++ b/core/java/android/os/HardwarePropertiesManager.java
@@ -69,7 +69,6 @@
      * @return an array of requested float device temperatures.
      *         Empty if platform doesn't provide the queried temperature.
      *
-     * @throws IllegalArgumentException if an incorrect temperature type is queried.
      * @throws SecurityException if a non profile or device owner tries to call this method.
     */
     public @NonNull float[] getDeviceTemperatures(@DeviceTemperatureType int type) {
@@ -80,11 +79,11 @@
             try {
                 return mService.getDeviceTemperatures(mContext.getOpPackageName(), type);
             } catch (RemoteException e) {
-                Log.w(TAG, "Could not get device temperatures", e);
-                return new float[0];
+                throw e.rethrowFromSystemServer();
             }
         default:
-            throw new IllegalArgumentException();
+            Log.w(TAG, "Unknown device temperature type.");
+            return new float[0];
         }
     }
 
@@ -100,8 +99,7 @@
         try {
             return mService.getCpuUsages(mContext.getOpPackageName());
         } catch (RemoteException e) {
-            Log.w(TAG, "Could not get CPU usages", e);
-            return new CpuUsageInfo[0];
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -117,8 +115,7 @@
         try {
             return mService.getFanSpeeds(mContext.getOpPackageName());
         } catch (RemoteException e) {
-            Log.w(TAG, "Could not get fan speeds", e);
-            return new float[0];
+            throw e.rethrowFromSystemServer();
         }
     }
 }
diff --git a/core/java/android/os/IDeviceIdleController.aidl b/core/java/android/os/IDeviceIdleController.aidl
index 838279b..082194b 100644
--- a/core/java/android/os/IDeviceIdleController.aidl
+++ b/core/java/android/os/IDeviceIdleController.aidl
@@ -25,10 +25,12 @@
     void removePowerSaveWhitelistApp(String name);
     String[] getSystemPowerWhitelistExceptIdle();
     String[] getSystemPowerWhitelist();
+    String[] getUserPowerWhitelist();
     String[] getFullPowerWhitelistExceptIdle();
     String[] getFullPowerWhitelist();
     int[] getAppIdWhitelistExceptIdle();
     int[] getAppIdWhitelist();
+    int[] getAppIdUserWhitelist();
     int[] getAppIdTempWhitelist();
     boolean isPowerSaveWhitelistExceptIdleApp(String name);
     boolean isPowerSaveWhitelistApp(String name);
diff --git a/core/java/android/os/PersistableBundle.java b/core/java/android/os/PersistableBundle.java
index ea180b2..5872f74 100644
--- a/core/java/android/os/PersistableBundle.java
+++ b/core/java/android/os/PersistableBundle.java
@@ -24,9 +24,6 @@
 import org.xmlpull.v1.XmlSerializer;
 
 import java.io.IOException;
-import java.util.Iterator;
-import java.util.Map;
-import java.util.Set;
 
 /**
  * A mapping from String values to various types that can be saved to persistent and later
@@ -82,6 +79,20 @@
         super(b);
     }
 
+
+    /**
+     * Constructs a PersistableBundle from a Bundle.
+     *
+     * @param b a Bundle to be copied.
+     *
+     * @throws IllegalArgumentException if any element of {@code b} cannot be persisted.
+     *
+     * @hide
+     */
+    public PersistableBundle(Bundle b) {
+        this(b.getMap());
+    }
+
     /**
      * Constructs a PersistableBundle containing the mappings passed in.
      *
@@ -101,6 +112,8 @@
             if (value instanceof ArrayMap) {
                 // Fix up any Maps by replacing them with PersistableBundles.
                 mMap.setValueAt(i, new PersistableBundle((ArrayMap<String, Object>) value));
+            } else if (value instanceof Bundle) {
+                mMap.setValueAt(i, new PersistableBundle(((Bundle) value)));
             } else if (!isValidType(value)) {
                 throw new IllegalArgumentException("Bad value in PersistableBundle key="
                         + mMap.keyAt(i) + " value=" + value);
diff --git a/core/java/android/os/PowerManager.java b/core/java/android/os/PowerManager.java
index 369ec15..2a4507c 100644
--- a/core/java/android/os/PowerManager.java
+++ b/core/java/android/os/PowerManager.java
@@ -620,6 +620,7 @@
         try {
             mService.userActivity(when, event, flags);
         } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -671,6 +672,7 @@
         try {
             mService.goToSleep(time, reason, flags);
         } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -697,6 +699,7 @@
         try {
             mService.wakeUp(time, "wakeUp", mContext.getOpPackageName());
         } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -707,6 +710,7 @@
         try {
             mService.wakeUp(time, reason, mContext.getOpPackageName());
         } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -735,6 +739,7 @@
         try {
             mService.nap(time);
         } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -757,6 +762,7 @@
         try {
             mService.boostScreenBrightness(time);
         } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -772,7 +778,7 @@
         try {
             return mService.isScreenBrightnessBoosted();
         } catch (RemoteException e) {
-            return false;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -790,6 +796,7 @@
         try {
             mService.setTemporaryScreenBrightnessSettingOverride(brightness);
         } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -803,7 +810,7 @@
         try {
             return mService.isWakeLockLevelSupported(level);
         } catch (RemoteException e) {
-            return false;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -867,7 +874,7 @@
         try {
             return mService.isInteractive();
         } catch (RemoteException e) {
-            return false;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -884,6 +891,7 @@
         try {
             mService.reboot(false, reason, true);
         } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -899,7 +907,7 @@
         try {
             return mService.isPowerSaveMode();
         } catch (RemoteException e) {
-            return false;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -916,7 +924,7 @@
         try {
             return mService.setPowerSaveMode(mode);
         } catch (RemoteException e) {
-            return false;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -936,7 +944,7 @@
         try {
             return mService.isDeviceIdleMode();
         } catch (RemoteException e) {
-            return false;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -956,7 +964,7 @@
         try {
             return mService.isLightDeviceIdleMode();
         } catch (RemoteException e) {
-            return false;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -975,7 +983,7 @@
         try {
             return mIDeviceIdleController.isPowerSaveWhitelistApp(packageName);
         } catch (RemoteException e) {
-            return false;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -992,6 +1000,7 @@
         try {
             mService.shutdown(confirm, reason, wait);
         } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1118,6 +1127,7 @@
                     try {
                         mService.releaseWakeLock(mToken, 0);
                     } catch (RemoteException e) {
+                        throw e.rethrowFromSystemServer();
                     }
                 }
             }
@@ -1186,6 +1196,7 @@
                     mService.acquireWakeLock(mToken, mFlags, mTag, mPackageName, mWorkSource,
                             mHistoryTag);
                 } catch (RemoteException e) {
+                    throw e.rethrowFromSystemServer();
                 }
                 mHeld = true;
             }
@@ -1224,6 +1235,7 @@
                         try {
                             mService.releaseWakeLock(mToken, flags);
                         } catch (RemoteException e) {
+                            throw e.rethrowFromSystemServer();
                         }
                         mHeld = false;
                     }
@@ -1280,6 +1292,7 @@
                     try {
                         mService.updateWakeLockWorkSource(mToken, mWorkSource, mHistoryTag);
                     } catch (RemoteException e) {
+                        throw e.rethrowFromSystemServer();
                     }
                 }
             }
diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java
index 9984755..4506f51 100644
--- a/core/java/android/os/Process.java
+++ b/core/java/android/os/Process.java
@@ -383,6 +383,9 @@
     public static final int SIGNAL_KILL = 9;
     public static final int SIGNAL_USR1 = 10;
 
+    private static long sStartElapsedRealtime;
+    private static long sStartUptimeMillis;
+
     /**
      * State for communicating with the zygote process.
      *
@@ -772,6 +775,26 @@
     public static final native long getElapsedCpuTime();
 
     /**
+     * Return the {@link SystemClock#elapsedRealtime()} at which this process was started.
+     */
+    public static final long getStartElapsedRealtime() {
+        return sStartElapsedRealtime;
+    }
+
+    /**
+     * Return the {@link SystemClock#uptimeMillis()} at which this process was started.
+     */
+    public static final long getStartUptimeMillis() {
+        return sStartUptimeMillis;
+    }
+
+    /** @hide */
+    public static final void setStartTimes(long elapsedRealtime, long uptimeMillis) {
+        sStartElapsedRealtime = elapsedRealtime;
+        sStartUptimeMillis = uptimeMillis;
+    }
+
+    /**
      * Returns true if the current process is a 64-bit runtime.
      */
     public static final boolean is64Bit() {
@@ -975,6 +998,31 @@
             throws IllegalArgumentException, SecurityException;
 
     /**
+     * On some devices, the foreground process may have one or more CPU
+     * cores exclusively reserved for it. This method can be used to
+     * retrieve which cores that are (if any), so the calling process
+     * can then use sched_setaffinity() to lock a thread to these cores.
+     * Note that the calling process must currently be running in the
+     * foreground for this method to return any cores.
+     *
+     * The CPU core(s) exclusively reserved for the foreground process will
+     * stay reserved for as long as the process stays in the foreground.
+     *
+     * As soon as a process leaves the foreground, those CPU cores will
+     * no longer be reserved for it, and will most likely be reserved for
+     * the new foreground process. It's not necessary to change the affinity
+     * of your process when it leaves the foreground (if you had previously
+     * set it to use a reserved core); the OS will automatically take care
+     * of resetting the affinity at that point.
+     *
+     * @return an array of integers, indicating the CPU cores exclusively
+     * reserved for this process. The array will have length zero if no
+     * CPU cores are exclusively reserved for this process at this point
+     * in time.
+     */
+    public static final native int[] getExclusiveCores();
+
+    /**
      * Set the priority of the calling thread, based on Linux priorities.  See
      * {@link #setThreadPriority(int, int)} for more information.
      * 
diff --git a/core/java/android/os/RemoteException.java b/core/java/android/os/RemoteException.java
index 98d7523..6d25fc1 100644
--- a/core/java/android/os/RemoteException.java
+++ b/core/java/android/os/RemoteException.java
@@ -15,6 +15,7 @@
  */
 
 package android.os;
+
 import android.util.AndroidException;
 
 /**
@@ -33,4 +34,25 @@
     public RuntimeException rethrowAsRuntimeException() {
         throw new RuntimeException(this);
     }
+
+    /**
+     * Rethrow this exception when we know it came from the system server. This
+     * gives us an opportunity to throw a nice clean
+     * {@link DeadSystemException} signal to avoid spamming logs with
+     * misleading stack traces.
+     * <p>
+     * Apps making calls into the system server may end up persisting internal
+     * state or making security decisions based on the perceived success or
+     * failure of a call, or any default values returned. For this reason, we
+     * want to strongly throw when there was trouble with the transaction.
+     *
+     * @hide
+     */
+    public RuntimeException rethrowFromSystemServer() {
+        if (this instanceof DeadObjectException) {
+            throw new RuntimeException(new DeadSystemException());
+        } else {
+            throw new RuntimeException(this);
+        }
+    }
 }
diff --git a/core/java/android/os/ServiceSpecificException.java b/core/java/android/os/ServiceSpecificException.java
index 20f237a5..04fca19 100644
--- a/core/java/android/os/ServiceSpecificException.java
+++ b/core/java/android/os/ServiceSpecificException.java
@@ -20,20 +20,23 @@
  *
  * <p>This exception includes an error code specific to the throwing
  * service.  This is mostly used by system services to indicate
- * domain specific error conditions.
+ * domain specific error conditions.</p>
+ *
+ * <p>Since these exceptions are designed to be passed through Binder
+ * interfaces, and to be generated by native-code Binder services,
+ * they do not support exception chaining.</p>
  *
  * @hide
  */
 public class ServiceSpecificException extends RuntimeException {
     public final int errorCode;
 
-    ServiceSpecificException(int errorCode, String message) {
+    public ServiceSpecificException(int errorCode, String message) {
         super(message);
         this.errorCode = errorCode;
     }
 
-    ServiceSpecificException(int errorCode) {
+    public ServiceSpecificException(int errorCode) {
         this.errorCode = errorCode;
     }
 }
-
diff --git a/core/java/android/os/StrictMode.java b/core/java/android/os/StrictMode.java
index 91d88da..e4a76db 100644
--- a/core/java/android/os/StrictMode.java
+++ b/core/java/android/os/StrictMode.java
@@ -1517,7 +1517,11 @@
                         violationMaskSubset,
                         info);
                 } catch (RemoteException e) {
-                    Log.e(TAG, "RemoteException trying to handle StrictMode violation", e);
+                    if (e instanceof DeadObjectException) {
+                        // System process is dead; ignore
+                    } else {
+                        Log.e(TAG, "RemoteException trying to handle StrictMode violation", e);
+                    }
                 } finally {
                     // Restore the policy.
                     setThreadPolicyMask(savedPolicyMask);
@@ -1569,7 +1573,11 @@
                             info);
                     }
                 } catch (RemoteException e) {
-                    Log.e(TAG, "RemoteException handling StrictMode violation", e);
+                    if (e instanceof DeadObjectException) {
+                        // System process is dead; ignore
+                    } else {
+                        Log.e(TAG, "RemoteException handling StrictMode violation", e);
+                    }
                 }
                 int outstanding = sDropboxCallsInFlight.decrementAndGet();
                 if (LOG_V) Log.d(TAG, "Dropbox complete; in-flight=" + outstanding);
@@ -1897,7 +1905,11 @@
                     violationMaskSubset,
                     info);
             } catch (RemoteException e) {
-                Log.e(TAG, "RemoteException trying to handle StrictMode violation", e);
+                if (e instanceof DeadObjectException) {
+                    // System process is dead; ignore
+                } else {
+                    Log.e(TAG, "RemoteException trying to handle StrictMode violation", e);
+                }
             } finally {
                 // Restore the policy.
                 setThreadPolicyMask(savedPolicyMask);
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index da7f85f..7223dfb 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -36,7 +36,7 @@
 import android.graphics.drawable.Drawable;
 import android.os.storage.StorageManager;
 import android.provider.Settings;
-import android.util.Log;
+import android.telephony.TelephonyManager;
 import android.view.WindowManager.LayoutParams;
 
 import com.android.internal.R;
@@ -681,6 +681,22 @@
     }
 
     /**
+     * Returns whether switching users is currently allowed.
+     * <p>For instance switching users is not allowed if the current user is in a phone call,
+     * or system user hasn't been unlocked yet
+     * @hide
+     */
+    public boolean canSwitchUsers() {
+        boolean allowUserSwitchingWhenSystemUserLocked = Settings.Global.getInt(
+                mContext.getContentResolver(),
+                Settings.Global.ALLOW_USER_SWITCHING_WHEN_SYSTEM_USER_LOCKED, 0) != 0;
+        boolean isSystemUserUnlocked = isUserUnlocked(UserHandle.SYSTEM);
+        boolean inCall = TelephonyManager.getDefault().getCallState()
+                != TelephonyManager.CALL_STATE_IDLE;
+        return (allowUserSwitchingWhenSystemUserLocked || isSystemUserUnlocked) && !inCall;
+    }
+
+    /**
      * Returns the user handle for the user that this process is running under.
      *
      * @return the user handle of this process.
@@ -700,8 +716,7 @@
         try {
             return mService.getUserInfo(getUserHandle()).name;
         } catch (RemoteException re) {
-            Log.w(TAG, "Could not get user name", re);
-            return "";
+            throw re.rethrowFromSystemServer();
         }
     }
 
@@ -771,8 +786,7 @@
         try {
             return mService.isRestricted();
         } catch (RemoteException re) {
-            Log.w(TAG, "Could not check if user is limited ", re);
-            return false;
+            throw re.rethrowFromSystemServer();
         }
     }
 
@@ -784,8 +798,7 @@
         try {
             return mService.canHaveRestrictedProfile(userId);
         } catch (RemoteException re) {
-            Log.w(TAG, "Could not check if user can have restricted profile", re);
-            return false;
+            throw re.rethrowFromSystemServer();
         }
     }
 
@@ -847,8 +860,8 @@
     public boolean isUserRunning(int userId) {
         try {
             return ActivityManagerNative.getDefault().isUserRunning(userId, 0);
-        } catch (RemoteException e) {
-            return false;
+        } catch (RemoteException re) {
+            throw re.rethrowFromSystemServer();
         }
     }
 
@@ -864,8 +877,8 @@
             // TODO: reconcile stopped vs stopping?
             return ActivityManagerNative.getDefault().isUserRunning(
                     user.getIdentifier(), ActivityManager.FLAG_OR_STOPPED);
-        } catch (RemoteException e) {
-            return false;
+        } catch (RemoteException re) {
+            throw re.rethrowFromSystemServer();
         }
     }
 
@@ -893,8 +906,8 @@
         try {
             return ActivityManagerNative.getDefault().isUserRunning(
                     user.getIdentifier(), ActivityManager.FLAG_AND_LOCKED);
-        } catch (RemoteException e) {
-            return false;
+        } catch (RemoteException re) {
+            throw re.rethrowFromSystemServer();
         }
     }
 
@@ -922,8 +935,8 @@
         try {
             return ActivityManagerNative.getDefault().isUserRunning(
                     user.getIdentifier(), ActivityManager.FLAG_AND_UNLOCKED);
-        } catch (RemoteException e) {
-            return false;
+        } catch (RemoteException re) {
+            throw re.rethrowFromSystemServer();
         }
     }
 
@@ -968,8 +981,7 @@
         try {
             return mService.getUserInfo(userHandle);
         } catch (RemoteException re) {
-            Log.w(TAG, "Could not get user info", re);
-            return null;
+            throw re.rethrowFromSystemServer();
         }
     }
 
@@ -990,8 +1002,7 @@
         try {
             return mService.getUserRestrictions(userHandle.getIdentifier());
         } catch (RemoteException re) {
-            Log.w(TAG, "Could not get user restrictions", re);
-            return Bundle.EMPTY;
+            throw re.rethrowFromSystemServer();
         }
     }
 
@@ -1007,9 +1018,7 @@
         try {
             return mService.hasBaseUserRestriction(restrictionKey, userHandle.getIdentifier());
         } catch (RemoteException re) {
-            Log.w(TAG, "Could not get base user restrictions for user " +
-                    userHandle.getIdentifier(), re);
-            return false;
+            throw re.rethrowFromSystemServer();
         }
     }
 
@@ -1065,7 +1074,7 @@
         try {
             mService.setUserRestriction(key, value, userHandle.getIdentifier());
         } catch (RemoteException re) {
-            Log.w(TAG, "Could not set user restriction", re);
+            throw re.rethrowFromSystemServer();
         }
     }
 
@@ -1092,8 +1101,7 @@
             return mService.hasUserRestriction(restrictionKey,
                     userHandle.getIdentifier());
         } catch (RemoteException re) {
-            Log.w(TAG, "Could not check user restrictions", re);
-            return false;
+            throw re.rethrowFromSystemServer();
         }
     }
 
@@ -1147,7 +1155,7 @@
                 mService.setUserRestriction(DISALLOW_OUTGOING_CALLS, true, user.id);
             }
         } catch (RemoteException re) {
-            Log.w(TAG, "Could not create a user", re);
+            throw re.rethrowFromSystemServer();
         }
         return user;
     }
@@ -1167,7 +1175,7 @@
                         Settings.Secure.SKIP_FIRST_USE_HINTS, "1", guest.id);
             }
         } catch (RemoteException re) {
-            Log.w(TAG, "Could not create a user", re);
+            throw re.rethrowFromSystemServer();
         }
         return guest;
     }
@@ -1188,8 +1196,7 @@
         try {
             return mService.createProfileForUser(name, flags, userHandle);
         } catch (RemoteException re) {
-            Log.w(TAG, "Could not create a user", re);
-            return null;
+            throw re.rethrowFromSystemServer();
         }
     }
 
@@ -1211,10 +1218,9 @@
                         UserHandle.of(user.id));
             }
             return user;
-        } catch (RemoteException e) {
-            Log.w(TAG, "Could not create a restricted profile", e);
+        } catch (RemoteException re) {
+            throw re.rethrowFromSystemServer();
         }
-        return null;
     }
 
     /**
@@ -1282,8 +1288,7 @@
         try {
             return mService.getSeedAccountName();
         } catch (RemoteException re) {
-            Log.w(TAG, "Could not get the seed account name", re);
-            return null;
+            throw re.rethrowFromSystemServer();
         }
     }
 
@@ -1297,8 +1302,7 @@
         try {
             return mService.getSeedAccountType();
         } catch (RemoteException re) {
-            Log.w(TAG, "Could not get the seed account type", re);
-            return null;
+            throw re.rethrowFromSystemServer();
         }
     }
 
@@ -1314,8 +1318,7 @@
         try {
             return mService.getSeedAccountOptions();
         } catch (RemoteException re) {
-            Log.w(TAG, "Could not get the seed account options", re);
-            return null;
+            throw re.rethrowFromSystemServer();
         }
     }
 
@@ -1336,7 +1339,7 @@
             mService.setSeedAccountData(userId, accountName, accountType, accountOptions,
                     /* persist= */ true);
         } catch (RemoteException re) {
-            Log.w(TAG, "Could not set the seed account data", re);
+            throw re.rethrowFromSystemServer();
         }
     }
 
@@ -1349,7 +1352,7 @@
         try {
             mService.clearSeedAccountData();
         } catch (RemoteException re) {
-            Log.w(TAG, "Could not clear the seed account data", re);
+            throw re.rethrowFromSystemServer();
         }
     }
 
@@ -1364,8 +1367,7 @@
         try {
             return mService.markGuestForDeletion(userHandle);
         } catch (RemoteException re) {
-            Log.w(TAG, "Could not mark guest for deletion", re);
-            return false;
+            throw re.rethrowFromSystemServer();
         }
     }
 
@@ -1384,8 +1386,8 @@
     public void setUserEnabled(@UserIdInt int userHandle) {
         try {
             mService.setUserEnabled(userHandle);
-        } catch (RemoteException e) {
-            Log.w(TAG, "Could not enable the profile", e);
+        } catch (RemoteException re) {
+            throw re.rethrowFromSystemServer();
         }
     }
 
@@ -1407,8 +1409,7 @@
         try {
             return mService.getUsers(false);
         } catch (RemoteException re) {
-            Log.w(TAG, "Could not get user list", re);
-            return null;
+            throw re.rethrowFromSystemServer();
         }
     }
 
@@ -1430,8 +1431,7 @@
             }
             return result;
         } catch (RemoteException re) {
-            Log.w(TAG, "Could not get users list", re);
-            return null;
+            throw re.rethrowFromSystemServer();
         }
     }
 
@@ -1447,8 +1447,7 @@
         try {
             return mService.getUserAccount(userHandle);
         } catch (RemoteException re) {
-            Log.w(TAG, "Could not get user account", re);
-            return null;
+            throw re.rethrowFromSystemServer();
         }
     }
 
@@ -1464,7 +1463,7 @@
         try {
             mService.setUserAccount(userHandle, accountName);
         } catch (RemoteException re) {
-            Log.w(TAG, "Could not set user account", re);
+            throw re.rethrowFromSystemServer();
         }
     }
 
@@ -1479,8 +1478,7 @@
         try {
             return mService.getPrimaryUser();
         } catch (RemoteException re) {
-            Log.w(TAG, "Could not get Primary user", re);
-            return null;
+            throw re.rethrowFromSystemServer();
         }
     }
 
@@ -1517,8 +1515,7 @@
         try {
             return mService.canAddMoreManagedProfiles(userId, allowedToRemoveOne);
         } catch (RemoteException re) {
-            Log.w(TAG, "Could not check if we can add more managed profiles", re);
-            return false;
+            throw re.rethrowFromSystemServer();
         }
     }
 
@@ -1537,8 +1534,7 @@
         try {
             return mService.getProfiles(userHandle, false /* enabledOnly */);
         } catch (RemoteException re) {
-            Log.w(TAG, "Could not get user list", re);
-            return null;
+            throw re.rethrowFromSystemServer();
         }
     }
 
@@ -1553,8 +1549,7 @@
         try {
             return mService.isSameProfileGroup(userId, otherUserId);
         } catch (RemoteException re) {
-            Log.w(TAG, "Could not get user list", re);
-            return false;
+            throw re.rethrowFromSystemServer();
         }
     }
 
@@ -1572,8 +1567,7 @@
         try {
             return mService.getProfiles(userHandle, true /* enabledOnly */);
         } catch (RemoteException re) {
-            Log.w(TAG, "Could not get user list", re);
-            return null;
+            throw re.rethrowFromSystemServer();
         }
     }
 
@@ -1589,8 +1583,7 @@
         try {
             users = mService.getProfiles(UserHandle.myUserId(), true /* enabledOnly */);
         } catch (RemoteException re) {
-            Log.w(TAG, "Could not get user list", re);
-            return null;
+            throw re.rethrowFromSystemServer();
         }
         for (UserInfo info : users) {
             UserHandle userHandle = new UserHandle(info.id);
@@ -1610,8 +1603,7 @@
         try {
             return mService.getCredentialOwnerProfile(userHandle);
         } catch (RemoteException re) {
-            Log.w(TAG, "Could not get credential owner", re);
-            return -1;
+            throw re.rethrowFromSystemServer();
         }
     }
 
@@ -1625,8 +1617,7 @@
         try {
             return mService.getProfileParent(userHandle);
         } catch (RemoteException re) {
-            Log.w(TAG, "Could not get profile parent", re);
-            return null;
+            throw re.rethrowFromSystemServer();
         }
     }
 
@@ -1640,8 +1631,8 @@
     public void setQuietModeEnabled(@UserIdInt int userHandle, boolean enableQuietMode) {
         try {
             mService.setQuietModeEnabled(userHandle, enableQuietMode);
-        } catch (RemoteException e) {
-            Log.w(TAG, "Could not change the profile's quiet mode", e);
+        } catch (RemoteException re) {
+            throw re.rethrowFromSystemServer();
         }
     }
 
@@ -1654,10 +1645,9 @@
     public boolean isQuietModeEnabled(UserHandle userHandle) {
         try {
             return mService.isQuietModeEnabled(userHandle.getIdentifier());
-        } catch (RemoteException e) {
-            Log.w(TAG, "Could not query the profile's quiet mode", e);
+        } catch (RemoteException re) {
+            throw re.rethrowFromSystemServer();
         }
-        return false;
     }
 
     /**
@@ -1668,7 +1658,7 @@
      * android.graphics.drawable.Drawable, UserHandle, android.graphics.Rect, int)}.
      * <p>
      * If the original drawable is a BitmapDrawable and the backing bitmap is
-     * mutable as per {@link android.graphics.Bitmap#isMutable()}, the bading
+     * mutable as per {@link android.graphics.Bitmap#isMutable()}, the badging
      * is performed in place and the original drawable is returned.
      * </p>
      *
@@ -1691,17 +1681,17 @@
      * badge to be used.
      * <p>
      * If the original drawable is a BitmapDrawable and the backing bitmap is
-     * mutable as per {@link android.graphics.Bitmap#isMutable()}, the bading
+     * mutable as per {@link android.graphics.Bitmap#isMutable()}, the badging
      * is performed in place and the original drawable is returned.
      * </p>
      *
      * @param badgedDrawable The drawable to badge.
      * @param user The target user.
      * @param badgeLocation Where in the bounds of the badged drawable to place
-     *         the badge. If not provided, the badge is applied on top of the entire
+     *         the badge. If it's {@code null}, the badge is applied on top of the entire
      *         drawable being badged.
      * @param badgeDensity The optional desired density for the badge as per
-     *         {@link android.util.DisplayMetrics#densityDpi}. If not provided,
+     *         {@link android.util.DisplayMetrics#densityDpi}. If it's not positive,
      *         the density of the display is used.
      * @return A drawable that combines the original drawable and a badge as
      *         determined by the system.
@@ -1742,8 +1732,7 @@
         try {
             return mService.getUsers(excludeDying);
         } catch (RemoteException re) {
-            Log.w(TAG, "Could not get user list", re);
-            return null;
+            throw re.rethrowFromSystemServer();
         }
     }
 
@@ -1757,8 +1746,7 @@
         try {
             return mService.removeUser(userHandle);
         } catch (RemoteException re) {
-            Log.w(TAG, "Could not remove user ", re);
-            return false;
+            throw re.rethrowFromSystemServer();
         }
     }
 
@@ -1774,7 +1762,7 @@
         try {
             mService.setUserName(userHandle, name);
         } catch (RemoteException re) {
-            Log.w(TAG, "Could not set the user name ", re);
+            throw re.rethrowFromSystemServer();
         }
     }
 
@@ -1788,7 +1776,7 @@
         try {
             mService.setUserIcon(userHandle, icon);
         } catch (RemoteException re) {
-            Log.w(TAG, "Could not set the user icon ", re);
+            throw re.rethrowFromSystemServer();
         }
     }
 
@@ -1813,7 +1801,7 @@
                 }
             }
         } catch (RemoteException re) {
-            Log.w(TAG, "Could not get the user icon ", re);
+            throw re.rethrowFromSystemServer();
         }
         return null;
     }
@@ -1869,9 +1857,8 @@
         try {
             return mService.getUserSerialNumber(userHandle);
         } catch (RemoteException re) {
-            Log.w(TAG, "Could not get serial number for user " + userHandle);
+            throw re.rethrowFromSystemServer();
         }
-        return -1;
     }
 
     /**
@@ -1887,9 +1874,8 @@
         try {
             return mService.getUserHandle(userSerialNumber);
         } catch (RemoteException re) {
-            Log.w(TAG, "Could not get userHandle for user " + userSerialNumber);
+            throw re.rethrowFromSystemServer();
         }
-        return -1;
     }
 
     /**
@@ -1915,9 +1901,8 @@
         try {
             return mService.getApplicationRestrictions(packageName);
         } catch (RemoteException re) {
-            Log.w(TAG, "Could not get application restrictions for package " + packageName);
+            throw re.rethrowFromSystemServer();
         }
-        return null;
     }
 
     /**
@@ -1927,9 +1912,8 @@
         try {
             return mService.getApplicationRestrictionsForUser(packageName, user.getIdentifier());
         } catch (RemoteException re) {
-            Log.w(TAG, "Could not get application restrictions for user " + user.getIdentifier());
+            throw re.rethrowFromSystemServer();
         }
-        return null;
     }
 
     /**
@@ -1940,7 +1924,7 @@
         try {
             mService.setApplicationRestrictions(packageName, restrictions, user.getIdentifier());
         } catch (RemoteException re) {
-            Log.w(TAG, "Could not set application restrictions for user " + user.getIdentifier());
+            throw re.rethrowFromSystemServer();
         }
     }
 
@@ -1964,7 +1948,7 @@
         try {
             mService.setDefaultGuestRestrictions(restrictions);
         } catch (RemoteException re) {
-            Log.w(TAG, "Could not set guest restrictions");
+            throw re.rethrowFromSystemServer();
         }
     }
 
@@ -1976,9 +1960,8 @@
         try {
             return mService.getDefaultGuestRestrictions();
         } catch (RemoteException re) {
-            Log.w(TAG, "Could not set guest restrictions");
+            throw re.rethrowFromSystemServer();
         }
-        return new Bundle();
     }
 
     /**
@@ -1991,8 +1974,7 @@
         try {
             return mService.getUserCreationTime(userHandle.getIdentifier());
         } catch (RemoteException re) {
-            Log.w(TAG, "Could not get user creation time", re);
-            return 0;
+            throw re.rethrowFromSystemServer();
         }
     }
 
@@ -2008,8 +1990,7 @@
         try {
             return mService.someUserHasSeedAccount(accountName, accountType);
         } catch (RemoteException re) {
-            Log.w(TAG, "Could not check seed accounts", re);
-            return false;
+            throw re.rethrowFromSystemServer();
         }
     }
 }
diff --git a/core/java/android/os/health/HealthKeys.java b/core/java/android/os/health/HealthKeys.java
new file mode 100644
index 0000000..842def3
--- /dev/null
+++ b/core/java/android/os/health/HealthKeys.java
@@ -0,0 +1,219 @@
+/*
+ * 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.os.health;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.lang.annotation.Annotation;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import java.lang.reflect.Field;
+import java.util.Arrays;
+
+/**
+ * Constants and stuff for the android.os.health package.
+ *
+ * @hide
+ */
+public class HealthKeys {
+
+    /**
+     * No valid key will ever be 0.
+     */
+    public static final int UNKNOWN_KEY = 0;
+
+    /*
+     * Base key for each of the different classes. There is
+     * nothing intrinsic to the operation of the value of the
+     * keys. It's just segmented for better debugging. The
+     * classes don't mix them anway.
+     */
+    public static final int BASE_UID = 10000;
+    public static final int BASE_PID = 20000;
+    public static final int BASE_PROCESS = 30000;
+    public static final int BASE_PACKAGE = 40000;
+    public static final int BASE_SERVICE = 50000;
+
+    /*
+     * The types of values supported by HealthStats.
+     */
+    public static final int TYPE_TIMER = 0;
+    public static final int TYPE_MEASUREMENT = 1;
+    public static final int TYPE_STATS = 2;
+    public static final int TYPE_TIMERS = 3;
+    public static final int TYPE_MEASUREMENTS = 4;
+
+    public static final int TYPE_COUNT = 5;
+
+    /**
+     * Annotation to mark public static final int fields that are to be used
+     * as field keys in HealthStats.
+     */
+    @Retention(RetentionPolicy.RUNTIME)
+    @Target({ElementType.FIELD})
+    public @interface Constant {
+        /**
+         * One of the TYPE_* constants above.
+         */
+        int type();
+    }
+
+    /**
+     * Class to gather the constants defined in a class full of constants and
+     * build the key indices used by HealthStatsWriter and HealthStats.
+     *
+     * @hide
+     */
+    public static class Constants {
+        private final String mDataType;
+        private final int[][] mKeys = new int[TYPE_COUNT][];
+
+        /**
+         * Pass in a class to gather the public static final int fields that are
+         * tagged with the @Constant annotation.
+         */
+        public Constants(Class clazz) {
+            // Save the class name for debugging
+            mDataType = clazz.getSimpleName();
+
+            // Iterate through the list of fields on this class, and build the
+            // constant arrays for these fields.
+            final Field[] fields = clazz.getDeclaredFields();
+            final Class<Constant> annotationClass = Constant.class;
+
+            final int N = fields.length;
+
+            final SortedIntArray[] keys = new SortedIntArray[mKeys.length];
+            for (int i=0; i<keys.length; i++) {
+                keys[i] = new SortedIntArray(N);
+            }
+
+            for (int i=0; i<N; i++) {
+                final Field field = fields[i];
+                final Constant constant = field.getAnnotation(annotationClass);
+                if (constant != null) {
+                    final int type = constant.type();
+                    if (type >= keys.length) {
+                        throw new RuntimeException("Unknown Constant type " + type
+                                + " on " + field);
+                    }
+                    try {
+                        keys[type].addValue(field.getInt(null));
+                    } catch (IllegalAccessException ex) {
+                        throw new RuntimeException("Can't read constant value type=" + type
+                                + " field=" + field, ex);
+                    }
+                }
+            }
+
+            for (int i=0; i<keys.length; i++) {
+                mKeys[i] = keys[i].getArray();
+            }
+        }
+
+        /**
+         * Get a string representation of this class. Useful for debugging. It will be the
+         * simple name of the class passed in the constructor.
+         */
+        public String getDataType() {
+            return mDataType;
+        }
+
+        /**
+         * Return how many keys there are for the given field type.
+         *
+         * @see TYPE_TIMER
+         * @see TYPE_MEASUREMENT
+         * @see TYPE_TIMERS
+         * @see TYPE_MEASUREMENTS
+         * @see TYPE_STATS
+         */
+        public int getSize(int type) {
+            return mKeys[type].length;
+        }
+
+        /**
+         * Return the index for the given type and key combination in the array of field
+         * keys or values.
+         *
+         * @see TYPE_TIMER
+         * @see TYPE_MEASUREMENT
+         * @see TYPE_TIMERS
+         * @see TYPE_MEASUREMENTS
+         * @see TYPE_STATS
+         */
+        public int getIndex(int type, int key) {
+            final int index = Arrays.binarySearch(mKeys[type], key);
+            if (index >= 0) {
+                return index;
+            } else {
+                throw new RuntimeException("Unknown Constant " + key + " (of type "
+                        + type + " )");
+            }
+        }
+
+        /**
+         * Get the array of keys for the given field type.
+         */
+        public int[] getKeys(int type) {
+            return mKeys[type];
+        }
+    }
+
+    /**
+     * An array of fixed size that will be sorted.
+     */
+    private static class SortedIntArray {
+        int mCount;
+        int[] mArray;
+
+        /**
+         * Construct with the maximum number of values.
+         */
+        SortedIntArray(int maxCount) {
+            mArray = new int[maxCount];
+        }
+
+        /**
+         * Add a value.
+         */
+        void addValue(int value) {
+            mArray[mCount++] = value;
+        }
+
+        /**
+         * Get the array of values that have been added, with the values in
+         * numerically increasing order.
+         */
+        int[] getArray() {
+            if (mCount == mArray.length) {
+                Arrays.sort(mArray);
+                return mArray;
+            } else {
+                final int[] result = new int[mCount];
+                System.arraycopy(mArray, 0, result, 0, mCount);
+                Arrays.sort(result);
+                return result;
+            }
+        }
+    }
+}
+
+
diff --git a/core/java/android/os/health/HealthStats.java b/core/java/android/os/health/HealthStats.java
new file mode 100644
index 0000000..f0489e2
--- /dev/null
+++ b/core/java/android/os/health/HealthStats.java
@@ -0,0 +1,481 @@
+/*
+ * 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.os.health;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.util.ArrayMap;
+
+import java.util.Arrays;
+import java.util.Map;
+
+/**
+ * A HealthStats object contains system health data about an application.
+ *
+ * <p>
+ * <b>Data Types</b><br>
+ * Each of the keys references data in one of five data types:
+ *
+ * <p>
+ * A <b>measurement</b> metric contains a sinlge {@code long} value. That value may
+ * be a count, a time, or some other type of value. The unit for a measurement
+ * (COUNT, MS, etc) will always be in the name of the constant for the key to
+ * retrieve it. For example, the
+ * {@link android.os.health.UidHealthStats#MEASUREMENT_WIFI_TX_MS UidHealthStats.MEASUREMENT_WIFI_TX_MS}
+ * value is the number of milliseconds (ms) that were spent transmitting on wifi by an
+ * application.  The
+ * {@link android.os.health.UidHealthStats#MEASUREMENT_MOBILE_RX_PACKETS UidHealthStats.MEASUREMENT_MOBILE_RX_PACKETS}
+ * measurement is the number of packets received on behalf of an application.
+ * The {@link android.os.health.UidHealthStats#MEASUREMENT_TOUCH_USER_ACTIVITY_COUNT
+ *     UidHealthStats.MEASUREMENT_TOUCH_USER_ACTIVITY_COUNT}
+ * measurement is the number of times the user touched the screen, causing the
+ * screen to stay awake.
+ *
+ *
+ * <p>
+ * A <b>timer</b> metric contains an {@code int} count and a {@code long} time,
+ * measured in milliseconds. Timers track how many times a resource was used, and
+ * the total duration for that usage. For example, the
+ * {@link android.os.health.UidHealthStats#TIMER_FLASHLIGHT}
+ * timer tracks how many times the application turned on the flashlight, and for
+ * how many milliseconds total it kept it on.
+ *
+ * <p>
+ * A <b>measurement map</b> metric is a mapping of {@link java.lang.String} names to
+ * {@link java.lang.Long} values.  The names typically are application provided names. For
+ * example, the
+ * {@link android.os.health.PackageHealthStats#MEASUREMENTS_WAKEUP_ALARMS_COUNT
+ *         PackageHealthStats.MEASUREMENTS_WAKEUP_ALARMS_COUNT}
+ * measurement map is a mapping of the tag provided to the
+ * {@link android.app.AlarmManager} when the alarm is scheduled.
+ *
+ * <p>
+ * A <b>timer map</b> metric is a mapping of {@link java.lang.String} names to
+ * {@link android.os.health.TimerStat} objects. The names are typically application
+ * provided names.  For example, the
+ * {@link android.os.health.UidHealthStats#TIMERS_WAKELOCKS_PARTIAL UidHealthStats.TIMERS_WAKELOCKS_PARTIAL}
+ * is a mapping of tag provided to the {@link android.os.PowerManager} when the
+ * wakelock is created to the number of times and for how long each wakelock was
+ * active.
+ *
+ * <p>
+ * Lastly, a <b>health stats</b> metric is a mapping of {@link java.lang.String}
+ * names to a recursive {@link android.os.health.HealthStats} object containing
+ * more detailed information. For example, the
+ * {@link android.os.health.UidHealthStats#STATS_PACKAGES UidHealthStats.STATS_PACKAGES}
+ * metric is a mapping of the package names for each of the APKs sharing a uid to
+ * the information recorded for that apk.  The returned HealthStats objects will
+ * each be associated with a different set of constants.  For the HealthStats
+ * returned for UidHealthStats.STATS_PACKAGES, the keys come from the
+ * {@link android.os.health.PackageHealthStats}  class.
+ *
+ */
+public class HealthStats {
+    // Header fields
+    private String mDataType;
+
+    // TimerStat fields
+    private int[] mTimerKeys;
+    private int[] mTimerCounts;
+    private long[] mTimerTimes;
+
+    // Measurement fields
+    private int[] mMeasurementKeys;
+    private long[] mMeasurementValues;
+
+    // Stats fields
+    private int[] mStatsKeys;
+    private ArrayMap<String,HealthStats>[] mStatsValues;
+
+    // Timers fields
+    private int[] mTimersKeys;
+    private ArrayMap<String,TimerStat>[] mTimersValues;
+
+    // Measurements fields
+    private int[] mMeasurementsKeys;
+    private ArrayMap<String,Long>[] mMeasurementsValues;
+
+    /**
+     * HealthStats empty constructor not implemented because this
+     * class is read-only.
+     */
+    private HealthStats() {
+        throw new RuntimeException("unsupported");
+    }
+
+    /**
+     * Construct a health stats object from a parcel.
+     *
+     * @hide
+     */
+    public HealthStats(Parcel in) {
+        int count;
+
+        // Header fields
+        mDataType = in.readString();
+
+        // TimerStat fields
+        count = in.readInt();
+        mTimerKeys = new int[count];
+        mTimerCounts = new int[count];
+        mTimerTimes = new long[count];
+        for (int i=0; i<count; i++) {
+            mTimerKeys[i] = in.readInt();
+            mTimerCounts[i] = in.readInt();
+            mTimerTimes[i] = in.readLong();
+        }
+
+        // Measurement fields
+        count = in.readInt();
+        mMeasurementKeys = new int[count];
+        mMeasurementValues = new long[count];
+        for (int i=0; i<count; i++) {
+            mMeasurementKeys[i] = in.readInt();
+            mMeasurementValues[i] = in.readLong();
+        }
+
+        // Stats fields
+        count = in.readInt();
+        mStatsKeys = new int[count];
+        mStatsValues = new ArrayMap[count];
+        for (int i=0; i<count; i++) {
+            mStatsKeys[i] = in.readInt();
+            mStatsValues[i] = createHealthStatsMap(in);
+        }
+
+        // Timers fields
+        count = in.readInt();
+        mTimersKeys = new int[count];
+        mTimersValues = new ArrayMap[count];
+        for (int i=0; i<count; i++) {
+            mTimersKeys[i] = in.readInt();
+            mTimersValues[i] = createParcelableMap(in, TimerStat.CREATOR);
+        }
+
+        // Measurements fields
+        count = in.readInt();
+        mMeasurementsKeys = new int[count];
+        mMeasurementsValues = new ArrayMap[count];
+        for (int i=0; i<count; i++) {
+            mMeasurementsKeys[i] = in.readInt();
+            mMeasurementsValues[i] = createLongsMap(in);
+        }
+    }
+
+    /**
+     * Get a name representing the contents of this object.
+     *
+     * @see UidHealthStats
+     * @see PackageHealthStats
+     * @see PidHealthStats
+     * @see ProcessHealthStats
+     * @see ServiceHealthStats
+     */
+    public String getDataType() {
+        return mDataType;
+    }
+
+    /**
+     * Return whether this object contains a TimerStat for the supplied key.
+     */
+    public boolean hasTimer(int key) {
+        return getIndex(mTimerKeys, key) >= 0;
+    }
+
+    /**
+     * Return a TimerStat object for the given key.
+     *
+     * This will allocate a new {@link TimerStat} object, which may be wasteful. Instead, use
+     * {@link #getTimerCount} and {@link #getTimerTime}.
+     *
+     * @throws IndexOutOfBoundsException When the key is not present in this object.
+     * @see #hasTimer hasTimer(int) To check if a value for the given key is present.
+     */
+    public TimerStat getTimer(int key) {
+        final int index = getIndex(mTimerKeys, key);
+        if (index < 0) {
+            throw new IndexOutOfBoundsException("Bad timer key dataType=" + mDataType
+                    + " key=" + key);
+        }
+        return new TimerStat(mTimerCounts[index], mTimerTimes[index]);
+    }
+
+    /**
+     * Get the count for the timer for the given key.
+     *
+     * @throws IndexOutOfBoundsException When the key is not present in this object.
+     * @see #hasTimer hasTimer(int) To check if a value for the given key is present.
+     */
+    public int getTimerCount(int key) {
+        final int index = getIndex(mTimerKeys, key);
+        if (index < 0) {
+            throw new IndexOutOfBoundsException("Bad timer key dataType=" + mDataType
+                    + " key=" + key);
+        }
+        return mTimerCounts[index];
+    }
+
+    /**
+     * Get the time for the timer for the given key, in milliseconds.
+     *
+     * @throws IndexOutOfBoundsException When the key is not present in this object.
+     * @see #hasTimer hasTimer(int) To check if a value for the given key is present.
+     */
+    public long getTimerTime(int key) {
+        final int index = getIndex(mTimerKeys, key);
+        if (index < 0) {
+            throw new IndexOutOfBoundsException("Bad timer key dataType=" + mDataType
+                    + " key=" + key);
+        }
+        return mTimerTimes[index];
+    }
+
+    /**
+     * Get the number of timer values in this object. Can be used to iterate through
+     * the available timers.
+     *
+     * @see #getTimerKeyAt
+     */
+    public int getTimerKeyCount() {
+        return mTimerKeys.length;
+    }
+
+    /**
+     * Get the key for the timer at the given index.  Index must be between 0 and the result
+     * of {@link #getTimerKeyCount getTimerKeyCount()}.
+     *
+     * @see #getTimerKeyCount
+     */
+    public int getTimerKeyAt(int index) {
+        return mTimerKeys[index];
+    }
+
+    /**
+     * Return whether this object contains a measurement for the supplied key.
+     */
+    public boolean hasMeasurement(int key) {
+        return getIndex(mMeasurementKeys, key) >= 0;
+    }
+
+    /**
+     * Get the measurement for the given key.
+     *
+     * @throws IndexOutOfBoundsException When the key is not present in this object.
+     * @see #hasMeasurement hasMeasurement(int) To check if a value for the given key is present.
+     */
+    public long getMeasurement(int key) {
+        final int index = getIndex(mMeasurementKeys, key);
+        if (index < 0) {
+            throw new IndexOutOfBoundsException("Bad measurement key dataType=" + mDataType
+                    + " key=" + key);
+        }
+        return mMeasurementValues[index];
+    }
+
+    /**
+     * Get the number of measurement values in this object. Can be used to iterate through
+     * the available measurements.
+     *
+     * @see #getMeasurementKeyAt
+     */
+    public int getMeasurementKeyCount() {
+        return mMeasurementKeys.length;
+    }
+
+    /**
+     * Get the key for the measurement at the given index.  Index must be between 0 and the result
+     * of {@link #getMeasurementKeyCount getMeasurementKeyCount()}.
+     *
+     * @see #getMeasurementKeyCount
+     */
+    public int getMeasurementKeyAt(int index) {
+        return mMeasurementKeys[index];
+    }
+
+    /**
+     * Return whether this object contains a HealthStats map for the supplied key.
+     */
+    public boolean hasStats(int key) {
+        return getIndex(mStatsKeys, key) >= 0;
+    }
+
+    /**
+     * Get the HealthStats map for the given key.
+     *
+     * @throws IndexOutOfBoundsException When the key is not present in this object.
+     * @see #hasStats hasStats(int) To check if a value for the given key is present.
+     */
+    public Map<String,HealthStats> getStats(int key) {
+        final int index = getIndex(mStatsKeys, key);
+        if (index < 0) {
+            throw new IndexOutOfBoundsException("Bad stats key dataType=" + mDataType
+                    + " key=" + key);
+        }
+        return mStatsValues[index];
+    }
+
+    /**
+     * Get the number of HealthStat map values in this object. Can be used to iterate through
+     * the available measurements.
+     *
+     * @see #getMeasurementKeyAt
+     */
+    public int getStatsKeyCount() {
+        return mStatsKeys.length;
+    }
+
+    /**
+     * Get the key for the timer at the given index.  Index must be between 0 and the result
+     * of {@link #getStatsKeyCount getStatsKeyCount()}.
+     *
+     * @see #getStatsKeyCount
+     */
+    public int getStatsKeyAt(int index) {
+        return mStatsKeys[index];
+    }
+
+    /**
+     * Return whether this object contains a timers map for the supplied key.
+     */
+    public boolean hasTimers(int key) {
+        return getIndex(mTimersKeys, key) >= 0;
+    }
+
+    /**
+     * Get the TimerStat map for the given key.
+     *
+     * @throws IndexOutOfBoundsException When the key is not present in this object.
+     * @see #hasTimers hasTimers(int) To check if a value for the given key is present.
+     */
+    public Map<String,TimerStat> getTimers(int key) {
+        final int index = getIndex(mTimersKeys, key);
+        if (index < 0) {
+            throw new IndexOutOfBoundsException("Bad timers key dataType=" + mDataType
+                    + " key=" + key);
+        }
+        return mTimersValues[index];
+    }
+
+    /**
+     * Get the number of timer map values in this object. Can be used to iterate through
+     * the available timer maps.
+     *
+     * @see #getTimersKeyAt
+     */
+    public int getTimersKeyCount() {
+        return mTimersKeys.length;
+    }
+
+    /**
+     * Get the key for the timer map at the given index.  Index must be between 0 and the result
+     * of {@link #getTimersKeyCount getTimersKeyCount()}.
+     *
+     * @see #getTimersKeyCount
+     */
+    public int getTimersKeyAt(int index) {
+        return mTimersKeys[index];
+    }
+
+    /**
+     * Return whether this object contains a measurements map for the supplied key.
+     */
+    public boolean hasMeasurements(int key) {
+        return getIndex(mMeasurementsKeys, key) >= 0;
+    }
+
+    /**
+     * Get the measurements map for the given key.
+     *
+     * @throws IndexOutOfBoundsException When the key is not present in this object.
+     * @see #hasMeasurements To check if a value for the given key is present.
+     */
+    public Map<String,Long> getMeasurements(int key) {
+        final int index = getIndex(mMeasurementsKeys, key);
+        if (index < 0) {
+            throw new IndexOutOfBoundsException("Bad measurements key dataType=" + mDataType
+                    + " key=" + key);
+        }
+        return mMeasurementsValues[index];
+    }
+
+    /**
+     * Get the number of measurement map values in this object. Can be used to iterate through
+     * the available measurement maps.
+     *
+     * @see #getMeasurementsKeyAt
+     */
+    public int getMeasurementsKeyCount() {
+        return mMeasurementsKeys.length;
+    }
+
+    /**
+     * Get the key for the measurement map at the given index.
+     * Index must be between 0 and the result
+     * of {@link #getMeasurementsKeyCount getMeasurementsKeyCount()}.
+     *
+     * @see #getMeasurementsKeyCount
+     */
+    public int getMeasurementsKeyAt(int index) {
+        return mMeasurementsKeys[index];
+    }
+
+    /**
+     * Get the index in keys of key.
+     */
+    private static int getIndex(int[] keys, int key) {
+        return Arrays.binarySearch(keys, key);
+    }
+
+    /**
+     * Create an ArrayMap<String,HealthStats> from the given Parcel.
+     */
+    private static ArrayMap<String,HealthStats> createHealthStatsMap(Parcel in) {
+        final int count = in.readInt();
+        final ArrayMap<String,HealthStats> result = new ArrayMap<String,HealthStats>(count);
+        for (int i=0; i<count; i++) {
+            result.put(in.readString(), new HealthStats(in));
+        }
+        return result;
+    }
+
+    /**
+     * Create an ArrayMap<String,T extends Parcelable> from the given Parcel using
+     * the given Parcelable.Creator.
+     */
+    private static <T extends Parcelable> ArrayMap<String,T> createParcelableMap(Parcel in,
+            Parcelable.Creator<T> creator) {
+        final int count = in.readInt();
+        final ArrayMap<String,T> result = new ArrayMap<String,T>(count);
+        for (int i=0; i<count; i++) {
+            result.put(in.readString(), creator.createFromParcel(in));
+        }
+        return result;
+    }
+
+    /**
+     * Create an ArrayMap<String,Long> from the given Parcel.
+     */
+    private static ArrayMap<String,Long> createLongsMap(Parcel in) {
+        final int count = in.readInt();
+        final ArrayMap<String,Long> result = new ArrayMap<String,Long>(count);
+        for (int i=0; i<count; i++) {
+            result.put(in.readString(), in.readLong());
+        }
+        return result;
+    }
+}
+
diff --git a/core/java/android/hardware/CameraInfo.aidl b/core/java/android/os/health/HealthStatsParceler.aidl
similarity index 82%
rename from core/java/android/hardware/CameraInfo.aidl
rename to core/java/android/os/health/HealthStatsParceler.aidl
index e21e694..68c348b 100644
--- a/core/java/android/hardware/CameraInfo.aidl
+++ b/core/java/android/os/health/HealthStatsParceler.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2013 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.
@@ -14,7 +14,6 @@
  * limitations under the License.
  */
 
-package android.hardware;
+package android.os.health;
 
-/** @hide */
-parcelable CameraInfo;
+parcelable HealthStatsParceler;
diff --git a/core/java/android/os/health/HealthStatsParceler.java b/core/java/android/os/health/HealthStatsParceler.java
new file mode 100644
index 0000000..28b3694
--- /dev/null
+++ b/core/java/android/os/health/HealthStatsParceler.java
@@ -0,0 +1,87 @@
+/*
+ * 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.os.health;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.util.ArrayMap;
+
+import java.util.Arrays;
+import java.util.Map;
+
+/**
+ * Class to allow sending the HealthStats through aidl generated glue.
+ *
+ * The alternative would be to send a HealthStats object, which would
+ * require constructing one, and then immediately flattening it. This
+ * saves that step at the cost of doing the extra flattening when
+ * accessed in the same process as the writer.
+ *
+ * The HealthStatsWriter passed in the constructor is retained, so don't
+ * reuse them.
+ * @hide
+ */
+public class HealthStatsParceler implements Parcelable {
+    private HealthStatsWriter mWriter;
+    private HealthStats mHealthStats;
+
+    public static final Parcelable.Creator<HealthStatsParceler> CREATOR
+            = new Parcelable.Creator<HealthStatsParceler>() {
+        public HealthStatsParceler createFromParcel(Parcel in) {
+            return new HealthStatsParceler(in);
+        }
+
+        public HealthStatsParceler[] newArray(int size) {
+            return new HealthStatsParceler[size];
+        }
+    };
+
+    public HealthStatsParceler(HealthStatsWriter writer) {
+        mWriter = writer;
+    }
+
+    public HealthStatsParceler(Parcel in) {
+        mHealthStats = new HealthStats(in);
+    }
+
+    public int describeContents() {
+        return 0;
+    }
+
+    public void writeToParcel(Parcel out, int flags) {
+        // See comment on mWriter declaration above.
+        if (mWriter != null) {
+            mWriter.flattenToParcel(out);
+        } else {
+            throw new RuntimeException("Can not re-parcel HealthStatsParceler that was"
+                    + " constructed from a Parcel");
+        }
+    }
+
+    public HealthStats getHealthStats() {
+        if (mWriter != null) {
+            final Parcel parcel = Parcel.obtain();
+            mWriter.flattenToParcel(parcel);
+            parcel.setDataPosition(0);
+            mHealthStats = new HealthStats(parcel);
+            parcel.recycle();
+        }
+
+        return mHealthStats;
+    }
+}
+
diff --git a/core/java/android/os/health/HealthStatsWriter.java b/core/java/android/os/health/HealthStatsWriter.java
new file mode 100644
index 0000000..351836b
--- /dev/null
+++ b/core/java/android/os/health/HealthStatsWriter.java
@@ -0,0 +1,288 @@
+/*
+ * 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.os.health;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.util.ArrayMap;
+
+import java.util.Map;
+
+/**
+ * Class to write the health stats data into a parcel, so it can then be
+ * retrieved via a {@link HealthStats} object.
+ *
+ * There is an attempt to keep this class as low overhead as possible, for
+ * example storing an int[] and a long[] instead of a TimerStat[].
+ *
+ * @hide
+ */
+public class HealthStatsWriter {
+    private final HealthKeys.Constants mConstants;
+
+    // TimerStat fields
+    private final boolean[] mTimerFields;
+    private final int[] mTimerCounts;
+    private final long[] mTimerTimes;
+
+    // Measurement fields
+    private final boolean[] mMeasurementFields;
+    private final long[] mMeasurementValues;
+
+    // Stats fields
+    private final ArrayMap<String,HealthStatsWriter>[] mStatsValues;
+
+    // Timers fields
+    private final ArrayMap<String,TimerStat>[] mTimersValues;
+
+    // Measurements fields
+    private final ArrayMap<String,Long>[] mMeasurementsValues;
+
+    /**
+     * Construct a HealthStatsWriter object with the given constants.
+     *
+     * The "getDataType()" of the resulting HealthStats object will be the
+     * short name of the java class that the Constants object was initalized
+     * with.
+     */
+    public HealthStatsWriter(HealthKeys.Constants constants) {
+        mConstants = constants;
+
+        // TimerStat
+        final int timerCount = constants.getSize(HealthKeys.TYPE_TIMER);
+        mTimerFields = new boolean[timerCount];
+        mTimerCounts = new int[timerCount];
+        mTimerTimes = new long[timerCount];
+
+        // Measurement
+        final int measurementCount = constants.getSize(HealthKeys.TYPE_MEASUREMENT);
+        mMeasurementFields = new boolean[measurementCount];
+        mMeasurementValues = new long[measurementCount];
+
+        // Stats
+        final int statsCount = constants.getSize(HealthKeys.TYPE_STATS);
+        mStatsValues = new ArrayMap[statsCount];
+
+        // Timers
+        final int timersCount = constants.getSize(HealthKeys.TYPE_TIMERS);
+        mTimersValues = new ArrayMap[timersCount];
+
+        // Measurements
+        final int measurementsCount = constants.getSize(HealthKeys.TYPE_MEASUREMENTS);
+        mMeasurementsValues = new ArrayMap[measurementsCount];
+    }
+
+    /**
+     * Add a timer for the given key.
+     */
+    public void addTimer(int timerId, int count, long time) {
+        final int index = mConstants.getIndex(HealthKeys.TYPE_TIMER, timerId);
+
+        mTimerFields[index] = true;
+        mTimerCounts[index] = count;
+        mTimerTimes[index] = time;
+    }
+
+    /**
+     * Add a measurement for the given key.
+     */
+    public void addMeasurement(int measurementId, long value) {
+        final int index = mConstants.getIndex(HealthKeys.TYPE_MEASUREMENT, measurementId);
+
+        mMeasurementFields[index] = true;
+        mMeasurementValues[index] = value;
+    }
+
+    /**
+     * Add a recursive HealthStats object for the given key and string name. The value
+     * is stored as a HealthStatsWriter until this object is written to a parcel, so
+     * don't attempt to reuse the HealthStatsWriter.
+     *
+     * The value field should not be null.
+     */
+    public void addStats(int key, String name, HealthStatsWriter value) {
+        final int index = mConstants.getIndex(HealthKeys.TYPE_STATS, key);
+
+        ArrayMap<String,HealthStatsWriter> map = mStatsValues[index];
+        if (map == null) {
+            map = mStatsValues[index] = new ArrayMap<String,HealthStatsWriter>(1);
+        }
+        map.put(name, value);
+    }
+
+    /**
+     * Add a TimerStat for the given key and string name.
+     *
+     * The value field should not be null.
+     */
+    public void addTimers(int key, String name, TimerStat value) {
+        final int index = mConstants.getIndex(HealthKeys.TYPE_TIMERS, key);
+
+        ArrayMap<String,TimerStat> map = mTimersValues[index];
+        if (map == null) {
+            map = mTimersValues[index] = new ArrayMap<String,TimerStat>(1);
+        }
+        map.put(name, value);
+    }
+
+    /**
+     * Add a measurement for the given key and string name.
+     */
+    public void addMeasurements(int key, String name, long value) {
+        final int index = mConstants.getIndex(HealthKeys.TYPE_MEASUREMENTS, key);
+
+        ArrayMap<String,Long> map = mMeasurementsValues[index];
+        if (map == null) {
+            map = mMeasurementsValues[index] = new ArrayMap<String,Long>(1);
+        }
+        map.put(name, value);
+    }
+
+    /**
+     * Flattens the data in this HealthStatsWriter to the Parcel format
+     * that can be unparceled into a HealthStat.
+     * @more
+     * (Called flattenToParcel because this HealthStatsWriter itself is
+     * not parcelable and we don't flatten all the business about the
+     * HealthKeys.Constants, only the values that were actually supplied)
+     */
+    public void flattenToParcel(Parcel out) {
+        int[] keys;
+
+        // Header fields
+        out.writeString(mConstants.getDataType());
+
+        // TimerStat fields
+        out.writeInt(countBooleanArray(mTimerFields));
+        keys = mConstants.getKeys(HealthKeys.TYPE_TIMER);
+        for (int i=0; i<keys.length; i++) {
+            if (mTimerFields[i]) {
+                out.writeInt(keys[i]);
+                out.writeInt(mTimerCounts[i]);
+                out.writeLong(mTimerTimes[i]);
+            }
+        }
+
+        // Measurement fields
+        out.writeInt(countBooleanArray(mMeasurementFields));
+        keys = mConstants.getKeys(HealthKeys.TYPE_MEASUREMENT);
+        for (int i=0; i<keys.length; i++) {
+            if (mMeasurementFields[i]) {
+                out.writeInt(keys[i]);
+                out.writeLong(mMeasurementValues[i]);
+            }
+        }
+
+        // Stats
+        out.writeInt(countObjectArray(mStatsValues));
+        keys = mConstants.getKeys(HealthKeys.TYPE_STATS);
+        for (int i=0; i<keys.length; i++) {
+            if (mStatsValues[i] != null) {
+                out.writeInt(keys[i]);
+                writeHealthStatsWriterMap(out, mStatsValues[i]);
+            }
+        }
+
+        // Timers
+        out.writeInt(countObjectArray(mTimersValues));
+        keys = mConstants.getKeys(HealthKeys.TYPE_TIMERS);
+        for (int i=0; i<keys.length; i++) {
+            if (mTimersValues[i] != null) {
+                out.writeInt(keys[i]);
+                writeParcelableMap(out, mTimersValues[i]);
+            }
+        }
+
+        // Measurements
+        out.writeInt(countObjectArray(mMeasurementsValues));
+        keys = mConstants.getKeys(HealthKeys.TYPE_MEASUREMENTS);
+        for (int i=0; i<keys.length; i++) {
+            if (mMeasurementsValues[i] != null) {
+                out.writeInt(keys[i]);
+                writeLongsMap(out, mMeasurementsValues[i]);
+            }
+        }
+    }
+
+    /**
+     * Count how many of the fields have been set.
+     */
+    private static int countBooleanArray(boolean[] fields) {
+        int count = 0;
+        final int N = fields.length;
+        for (int i=0; i<N; i++) {
+            if (fields[i]) {
+                count++;
+            }
+        }
+        return count;
+    }
+
+    /**
+     * Count how many of the fields have been set.
+     */
+    private static <T extends Object> int countObjectArray(T[] fields) {
+        int count = 0;
+        final int N = fields.length;
+        for (int i=0; i<N; i++) {
+            if (fields[i] != null) {
+                count++;
+            }
+        }
+        return count;
+    }
+
+    /**
+     * Write a map of String to HealthStatsWriter to the Parcel.
+     */
+    private static void writeHealthStatsWriterMap(Parcel out,
+            ArrayMap<String,HealthStatsWriter> map) {
+        final int N = map.size();
+        out.writeInt(N);
+        for (int i=0; i<N; i++) {
+            out.writeString(map.keyAt(i));
+            map.valueAt(i).flattenToParcel(out);
+        }
+    }
+
+    /**
+     * Write a map of String to Parcelables to the Parcel.
+     */
+    private static <T extends Parcelable> void writeParcelableMap(Parcel out,
+            ArrayMap<String,T> map) {
+        final int N = map.size();
+        out.writeInt(N);
+        for (int i=0; i<N; i++) {
+            out.writeString(map.keyAt(i));
+            map.valueAt(i).writeToParcel(out, 0);
+        }
+    }
+
+    /**
+     * Write a map of String to Longs to the Parcel.
+     */
+    private static void writeLongsMap(Parcel out, ArrayMap<String,Long> map) {
+        final int N = map.size();
+        out.writeInt(N);
+        for (int i=0; i<N; i++) {
+            out.writeString(map.keyAt(i));
+            out.writeLong(map.valueAt(i));
+        }
+    }
+}
+
+
diff --git a/core/java/android/os/health/PackageHealthStats.java b/core/java/android/os/health/PackageHealthStats.java
new file mode 100644
index 0000000..2c30d5f
--- /dev/null
+++ b/core/java/android/os/health/PackageHealthStats.java
@@ -0,0 +1,50 @@
+/*
+ * 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.os.health;
+
+/**
+ * Keys for {@link HealthStats} returned from
+ * {@link HealthStats#getStats(int) HealthStats.getStats(int)} with the
+ * {@link UidHealthStats#STATS_PACKAGES UidHealthStats.STATS_PACKAGES} key.
+ */
+public final class PackageHealthStats {
+
+    private PackageHealthStats() {
+    }
+
+    /**
+     * Key for a HealthStats with {@link ServiceHealthStats} keys for each of the
+     * services defined in this apk.
+     */
+    @HealthKeys.Constant(type=HealthKeys.TYPE_STATS)
+    public static final int STATS_SERVICES = HealthKeys.BASE_PACKAGE + 1;
+
+    /**
+     * Key for a map of the number of times that a package's wakeup alarms have fired
+     * while the device was on battery.
+     *
+     * @see android.app.AlarmManager.
+     */
+    @HealthKeys.Constant(type=HealthKeys.TYPE_MEASUREMENTS)
+    public static final int MEASUREMENTS_WAKEUP_ALARMS_COUNT = HealthKeys.BASE_PACKAGE + 2;
+
+    /**
+     * @hide
+     */
+    public static final HealthKeys.Constants CONSTANTS
+            = new HealthKeys.Constants(PackageHealthStats.class);
+}
diff --git a/core/java/android/os/health/PidHealthStats.java b/core/java/android/os/health/PidHealthStats.java
new file mode 100644
index 0000000..fe3c02c
--- /dev/null
+++ b/core/java/android/os/health/PidHealthStats.java
@@ -0,0 +1,42 @@
+/*
+ * 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.os.health;
+
+/**
+ * Keys for {@link HealthStats} returned from
+ * {@link HealthStats#getStats(int) HealthStats.getStats(int)} with the
+ * {@link UidHealthStats#STATS_PIDS UidHealthStats.STATS_PIDS} key.
+ */
+public final class PidHealthStats {
+
+    private PidHealthStats() {
+    }
+
+    @HealthKeys.Constant(type=HealthKeys.TYPE_MEASUREMENT)
+    public static final int MEASUREMENT_WAKE_NESTING_COUNT = HealthKeys.BASE_PID + 1;
+
+    @HealthKeys.Constant(type=HealthKeys.TYPE_MEASUREMENT)
+    public static final int MEASUREMENT_WAKE_SUM_MS = HealthKeys.BASE_PID + 2;
+
+    @HealthKeys.Constant(type=HealthKeys.TYPE_MEASUREMENT)
+    public static final int MEASUREMENT_WAKE_START_MS = HealthKeys.BASE_PID + 3;
+
+    /**
+     * @hide
+     */
+    public static final HealthKeys.Constants CONSTANTS = new HealthKeys.Constants(PidHealthStats.class);
+}
diff --git a/core/java/android/os/health/ProcessHealthStats.java b/core/java/android/os/health/ProcessHealthStats.java
new file mode 100644
index 0000000..e004ecb
--- /dev/null
+++ b/core/java/android/os/health/ProcessHealthStats.java
@@ -0,0 +1,51 @@
+/*
+ * 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.os.health;
+
+/**
+ * Keys for {@link HealthStats} returned from
+ * {@link HealthStats#getStats(int) HealthStats.getStats(int)} with the
+ * {@link UidHealthStats#STATS_PROCESSES UidHealthStats.STATS_PROCESSES} key.
+ */
+public final class ProcessHealthStats {
+
+    private ProcessHealthStats() {
+    }
+
+    @HealthKeys.Constant(type=HealthKeys.TYPE_MEASUREMENT)
+    public static final int MEASUREMENT_USER_TIME_MS = HealthKeys.BASE_PROCESS + 1;
+
+    @HealthKeys.Constant(type=HealthKeys.TYPE_MEASUREMENT)
+    public static final int MEASUREMENT_SYSTEM_TIME_MS = HealthKeys.BASE_PROCESS + 2;
+
+    @HealthKeys.Constant(type=HealthKeys.TYPE_MEASUREMENT)
+    public static final int MEASUREMENT_STARTS_COUNT = HealthKeys.BASE_PROCESS + 3;
+
+    @HealthKeys.Constant(type=HealthKeys.TYPE_MEASUREMENT)
+    public static final int MEASUREMENT_CRASHES_COUNT = HealthKeys.BASE_PROCESS + 4;
+
+    @HealthKeys.Constant(type=HealthKeys.TYPE_MEASUREMENT)
+    public static final int MEASUREMENT_ANR_COUNT = HealthKeys.BASE_PROCESS + 5;
+
+    @HealthKeys.Constant(type=HealthKeys.TYPE_MEASUREMENT)
+    public static final int MEASUREMENT_FOREGROUND_MS = HealthKeys.BASE_PROCESS + 6;
+
+    /**
+     * @hide
+     */
+    public static final HealthKeys.Constants CONSTANTS = new HealthKeys.Constants(ProcessHealthStats.class);
+}
diff --git a/core/java/android/os/health/ServiceHealthStats.java b/core/java/android/os/health/ServiceHealthStats.java
new file mode 100644
index 0000000..802ad31
--- /dev/null
+++ b/core/java/android/os/health/ServiceHealthStats.java
@@ -0,0 +1,40 @@
+/*
+ * 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.os.health;
+
+/**
+ * Keys for {@link HealthStats} returned from
+ * {@link HealthStats#getStats(int) HealthStats.getStats(int)} with the
+ * {@link PackageHealthStats#STATS_SERVICES PackageHealthStats.STATS_SERVICES} key.
+ */
+public final class ServiceHealthStats {
+
+    private ServiceHealthStats() {
+    }
+
+    @HealthKeys.Constant(type=HealthKeys.TYPE_MEASUREMENT)
+    public static final int MEASUREMENT_START_SERVICE_COUNT = HealthKeys.BASE_SERVICE + 1;
+
+    @HealthKeys.Constant(type=HealthKeys.TYPE_MEASUREMENT)
+    public static final int MEASUREMENT_LAUNCH_COUNT = HealthKeys.BASE_SERVICE + 2;
+
+    /**
+     * @hide
+     */
+    public static final HealthKeys.Constants CONSTANTS
+            = new HealthKeys.Constants(ServiceHealthStats.class);
+}
diff --git a/core/java/android/os/health/SystemHealthManager.java b/core/java/android/os/health/SystemHealthManager.java
new file mode 100644
index 0000000..520e84e
--- /dev/null
+++ b/core/java/android/os/health/SystemHealthManager.java
@@ -0,0 +1,121 @@
+/*
+ * 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.os.health;
+
+import android.content.Context;
+import android.os.BatteryStats;
+import android.os.Process;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+
+import com.android.internal.app.IBatteryStats;
+
+/**
+ * Provides access to data about how various system resources are used by applications.
+ * @more
+ * <b>Battery Usage</b><br>
+ * The statistics related to power (battery) usage are recorded since the device
+ * was last unplugged. It is expected that applications schedule more work to do
+ * while the device is plugged in (e.g. using {@link android.app.job.JobScheduler
+ * JobScheduler}), and while that can affect charging rates, it is still preferable
+ * to actually draining the battery.
+ */
+public class SystemHealthManager {
+    private final IBatteryStats mBatteryStats;
+
+    /**
+     * Construct a new SystemHealthManager object.
+     * @hide
+     */
+    public SystemHealthManager() {
+        mBatteryStats = IBatteryStats.Stub.asInterface(
+            ServiceManager.getService(BatteryStats.SERVICE_NAME));
+    }
+
+    /**
+     * Obtain a SystemHealthManager object for the supplied context.
+     */
+    public static SystemHealthManager from(Context context) {
+        return (SystemHealthManager)context.getSystemService(Context.SYSTEM_HEALTH_SERVICE);
+    }
+
+    /**
+     * Return a {@link HealthStats} object containing a snapshot of system health
+     * metrics for the given uid (user-id, which in usually corresponds to application).
+     * @more
+     *
+     * An application must hold the {@link android.Manifest.permission#BATTERY_STATS
+     * android.permission.BATTERY_STATS} permission in order to retrieve any HealthStats
+     * other than its own.
+     *
+     * @param uid User ID for a given application.
+     * @return A {@link HealthStats} object containing the metrics for the requested
+     * application. The keys for this HealthStats object will be from the {@link UidHealthStats}
+     * class.
+     * @see Process#myUid()
+     */
+    public HealthStats takeUidSnapshot(int uid) {
+        try {
+            final HealthStatsParceler parceler = mBatteryStats.takeUidSnapshot(uid);
+            return parceler.getHealthStats();
+        } catch (RemoteException ex) {
+            throw new RuntimeException(ex);
+        }
+    }
+
+    /**
+     * Return a {@link HealthStats} object containing a snapshot of system health
+     * metrics for the application calling this API. This method is the same as calling
+     * {@code takeUidSnapshot(Process.myUid())}.
+     *
+     * @return A {@link HealthStats} object containing the metrics for this application. The keys
+     * for this HealthStats object will be from the {@link UidHealthStats} class.
+     */
+    public HealthStats takeMyUidSnapshot() {
+        return takeUidSnapshot(Process.myUid());
+    }
+
+    /**
+     * Return a {@link HealthStats} object containing a snapshot of system health
+     * metrics for the given uids (user-id, which in usually corresponds to application).
+     * @more
+     *
+     * An application must hold the {@link android.Manifest.permission#BATTERY_STATS
+     * android.permission.BATTERY_STATS} permission in order to retrieve any HealthStats
+     * other than its own.
+     *
+     * @param uids An array of User IDs to retrieve.
+     * @return An array of {@link HealthStats} objects containing the metrics for each of
+     * the requested uids. The keys for this HealthStats object will be from the
+     * {@link UidHealthStats} class.
+     */
+    public HealthStats[] takeUidSnapshots(int[] uids) {
+        try {
+            final HealthStatsParceler[] parcelers = mBatteryStats.takeUidSnapshots(uids);
+            final HealthStats[] results = new HealthStats[uids.length];
+            final int N = uids.length;
+            for (int i=0; i<N; i++) {
+                results[i] = parcelers[i].getHealthStats();
+            }
+            return results;
+        } catch (RemoteException ex) {
+            throw new RuntimeException(ex);
+        }
+    }
+
+}
+
diff --git a/core/java/android/os/health/TimerStat.java b/core/java/android/os/health/TimerStat.java
new file mode 100644
index 0000000..fc51b60
--- /dev/null
+++ b/core/java/android/os/health/TimerStat.java
@@ -0,0 +1,116 @@
+/*
+ * 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.os.health;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * A TimerStat object stores a count and a time.
+ *
+ * @more
+ * When possible, the other APIs in this package avoid requiring a TimerStat
+ * object to be constructed, even internally, but the getTimers method on
+ * {@link android.os.health.HealthStats} does require TimerStat objects.
+ */
+public class TimerStat implements Parcelable {
+    private int mCount;
+    private long mTime;
+
+    /**
+     * The CREATOR instance for use by aidl Binder interfaces.
+     */
+    public static final Parcelable.Creator<TimerStat> CREATOR
+            = new Parcelable.Creator<TimerStat>() {
+        public TimerStat createFromParcel(Parcel in) {
+            return new TimerStat(in);
+        }
+
+        public TimerStat[] newArray(int size) {
+            return new TimerStat[size];
+        }
+    };
+
+    /**
+     * Construct an empty TimerStat object with the count and time set to 0.
+     */
+    public TimerStat() {
+    }
+
+    /**
+     * Construct a TimerStat object with the supplied count and time fields.
+     *
+     * @param count The count
+     * @param time The time
+     */
+    public TimerStat(int count, long time) {
+        mCount = count;
+        mTime = time;
+    }
+
+    /**
+     * Construct a TimerStat object reading the values from a {@link android.os.Parcel Parcel}
+     * object.
+     */
+    public TimerStat(Parcel in) {
+        mCount = in.readInt();
+        mTime = in.readLong();
+    }
+
+    /**
+     * @inheritDoc
+     */
+    public int describeContents() {
+        return 0;
+    }
+
+    /**
+     * Write this TimerStat object to a parcel.
+     */
+    public void writeToParcel(Parcel out, int flags) {
+        out.writeInt(mCount);
+        out.writeLong(mTime);
+    }
+
+    /**
+     * Set the count for this timer.
+     */
+    public void setCount(int count) {
+        mCount = count;
+    }
+
+    /**
+     * Get the count for this timer.
+     */
+    public int getCount() {
+        return mCount;
+    }
+
+    /**
+     * Set the time for this timer.
+     */
+    public void setTime(long time) {
+        mTime = time;
+    }
+
+    /**
+     * Get the time for this timer.
+     */
+    public long getTime() {
+        return mTime;
+    }
+}
diff --git a/core/java/android/os/health/UidHealthStats.java b/core/java/android/os/health/UidHealthStats.java
new file mode 100644
index 0000000..c7d257f
--- /dev/null
+++ b/core/java/android/os/health/UidHealthStats.java
@@ -0,0 +1,280 @@
+/*
+ * 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.os.health;
+
+/**
+ * Keys for {@link HealthStats} returned from
+ * {@link SystemHealthManager#takeUidSnapshot(int) SystemHealthManager.takeUidSnapshot(int)},
+ * {@link SystemHealthManager#takeMyUidSnapshot() SystemHealthManager.takeMyUidSnapshot()}, and
+ * {@link SystemHealthManager#takeUidSnapshots(int[]) SystemHealthManager.takeUidSnapshots(int[])}.
+ */
+public final class UidHealthStats {
+
+    private UidHealthStats() {
+    }
+
+    /**
+     * How many milliseconds this statistics report covers in wall-clock time while the
+     * device was on battery including both screen-on and screen-off time.
+     */
+    @HealthKeys.Constant(type=HealthKeys.TYPE_MEASUREMENT)
+    public static final int MEASUREMENT_REALTIME_BATTERY_MS = HealthKeys.BASE_UID + 1;
+
+    /**
+     * How many milliseconds this statistics report covers that the CPU was running while the
+     * device was on battery including both screen-on and screen-off time.
+     */
+    @HealthKeys.Constant(type=HealthKeys.TYPE_MEASUREMENT)
+    public static final int MEASUREMENT_UPTIME_BATTERY_MS = HealthKeys.BASE_UID + 2;
+
+    /**
+     * How many milliseconds this statistics report covers in wall-clock time while the
+     * device was on battery including both screen-on and screen-off time.
+     */
+    @HealthKeys.Constant(type=HealthKeys.TYPE_MEASUREMENT)
+    public static final int MEASUREMENT_REALTIME_SCREEN_OFF_BATTERY_MS = HealthKeys.BASE_UID + 3;
+
+    /**
+     * How many milliseconds this statistics report covers that the CPU was running while the
+     * device was on battery including both screen-on and screen-off time.
+     */
+    @HealthKeys.Constant(type=HealthKeys.TYPE_MEASUREMENT)
+    public static final int MEASUREMENT_UPTIME_SCREEN_OFF_BATTERY_MS = HealthKeys.BASE_UID + 4;
+
+    /**
+     * Key for a TimerStat for the times a
+     * {@link android.os.PowerManager#FULL_WAKE_LOCK full wake lock}
+     * was acquired for this uid.
+     */
+    @HealthKeys.Constant(type=HealthKeys.TYPE_TIMERS)
+    public static final int TIMERS_WAKELOCKS_FULL = HealthKeys.BASE_UID + 5;
+
+    /**
+     * Key for a TimerStat for the times a
+     * {@link android.os.PowerManager#PARTIAL_WAKE_LOCK full wake lock}
+     * was acquired for this uid.
+     */
+    @HealthKeys.Constant(type=HealthKeys.TYPE_TIMERS)
+    public static final int TIMERS_WAKELOCKS_PARTIAL = HealthKeys.BASE_UID + 6;
+
+    @HealthKeys.Constant(type=HealthKeys.TYPE_TIMERS)
+    public static final int TIMERS_WAKELOCKS_WINDOW = HealthKeys.BASE_UID + 7;
+
+    @HealthKeys.Constant(type=HealthKeys.TYPE_TIMERS)
+    public static final int TIMERS_WAKELOCKS_DRAW = HealthKeys.BASE_UID + 8;
+
+    /**
+     * Key for a map of Timers for the sync adapter syncs that were done for
+     * this uid.
+     */
+    @HealthKeys.Constant(type=HealthKeys.TYPE_TIMERS)
+    public static final int TIMERS_SYNCS = HealthKeys.BASE_UID + 9;
+
+    /**
+     * Key for a map of Timers for the {@link android.app.job.JobScheduler} jobs for
+     * this uid.
+     */
+    @HealthKeys.Constant(type=HealthKeys.TYPE_TIMERS)
+    public static final int TIMERS_JOBS = HealthKeys.BASE_UID + 10;
+
+    /**
+     * Key for a timer for the applications use of the GPS sensor.
+     */
+    @HealthKeys.Constant(type=HealthKeys.TYPE_TIMER)
+    public static final int TIMER_GPS_SENSOR = HealthKeys.BASE_UID + 11;
+
+    /**
+     * Key for a map of the sensor usage for this uid. The keys are a
+     * string representation of the handle for the sensor.
+     */
+    @HealthKeys.Constant(type=HealthKeys.TYPE_TIMERS)
+    public static final int TIMERS_SENSORS = HealthKeys.BASE_UID + 12;
+
+    /**
+     * Key for a HealthStats with {@link PidHealthStats} keys for each of the
+     * currently running processes for this uid.
+     */
+    @HealthKeys.Constant(type=HealthKeys.TYPE_STATS)
+    public static final int STATS_PIDS = HealthKeys.BASE_UID + 13;
+
+    /**
+     * Key for a HealthStats with {@link ProcessHealthStats} keys for each of the
+     * named processes for this uid.
+     */
+    @HealthKeys.Constant(type=HealthKeys.TYPE_STATS)
+    public static final int STATS_PROCESSES = HealthKeys.BASE_UID + 14;
+
+    /**
+     * Key for a HealthStats with {@link PackageHealthStats} keys for each of the
+     * APKs that share this uid.
+     */
+    @HealthKeys.Constant(type=HealthKeys.TYPE_STATS)
+    public static final int STATS_PACKAGES = HealthKeys.BASE_UID + 15;
+
+    @HealthKeys.Constant(type=HealthKeys.TYPE_MEASUREMENT)
+    public static final int MEASUREMENT_WIFI_IDLE_MS = HealthKeys.BASE_UID + 16;
+
+    @HealthKeys.Constant(type=HealthKeys.TYPE_MEASUREMENT)
+    public static final int MEASUREMENT_WIFI_RX_MS = HealthKeys.BASE_UID + 17;
+
+    @HealthKeys.Constant(type=HealthKeys.TYPE_MEASUREMENT)
+    public static final int MEASUREMENT_WIFI_TX_MS = HealthKeys.BASE_UID + 18;
+
+    @HealthKeys.Constant(type=HealthKeys.TYPE_MEASUREMENT)
+    public static final int MEASUREMENT_WIFI_POWER_MAMS = HealthKeys.BASE_UID + 19;
+
+    @HealthKeys.Constant(type=HealthKeys.TYPE_MEASUREMENT)
+    public static final int MEASUREMENT_BLUETOOTH_IDLE_MS = HealthKeys.BASE_UID + 20;
+
+    @HealthKeys.Constant(type=HealthKeys.TYPE_MEASUREMENT)
+    public static final int MEASUREMENT_BLUETOOTH_RX_MS = HealthKeys.BASE_UID + 21;
+
+    @HealthKeys.Constant(type=HealthKeys.TYPE_MEASUREMENT)
+    public static final int MEASUREMENT_BLUETOOTH_TX_MS = HealthKeys.BASE_UID + 22;
+
+    @HealthKeys.Constant(type=HealthKeys.TYPE_MEASUREMENT)
+    public static final int MEASUREMENT_BLUETOOTH_POWER_MAMS = HealthKeys.BASE_UID + 23;
+
+    @HealthKeys.Constant(type=HealthKeys.TYPE_MEASUREMENT)
+    public static final int MEASUREMENT_MOBILE_IDLE_MS = HealthKeys.BASE_UID + 24;
+
+    @HealthKeys.Constant(type=HealthKeys.TYPE_MEASUREMENT)
+    public static final int MEASUREMENT_MOBILE_RX_MS = HealthKeys.BASE_UID + 25;
+
+    @HealthKeys.Constant(type=HealthKeys.TYPE_MEASUREMENT)
+    public static final int MEASUREMENT_MOBILE_TX_MS = HealthKeys.BASE_UID + 26;
+
+    @HealthKeys.Constant(type=HealthKeys.TYPE_MEASUREMENT)
+    public static final int MEASUREMENT_MOBILE_POWER_MAMS = HealthKeys.BASE_UID + 27;
+
+    @HealthKeys.Constant(type=HealthKeys.TYPE_MEASUREMENT)
+    public static final int MEASUREMENT_WIFI_RUNNING_MS = HealthKeys.BASE_UID + 28;
+
+    @HealthKeys.Constant(type=HealthKeys.TYPE_MEASUREMENT)
+    public static final int MEASUREMENT_WIFI_FULL_LOCK_MS = HealthKeys.BASE_UID + 29;
+
+    @HealthKeys.Constant(type=HealthKeys.TYPE_TIMER)
+    public static final int TIMER_WIFI_SCAN = HealthKeys.BASE_UID + 30;
+
+    @HealthKeys.Constant(type=HealthKeys.TYPE_MEASUREMENT)
+    public static final int MEASUREMENT_WIFI_MULTICAST_MS = HealthKeys.BASE_UID + 31;
+
+    @HealthKeys.Constant(type=HealthKeys.TYPE_TIMER)
+    public static final int TIMER_AUDIO = HealthKeys.BASE_UID + 32;
+
+    @HealthKeys.Constant(type=HealthKeys.TYPE_TIMER)
+    public static final int TIMER_VIDEO = HealthKeys.BASE_UID + 33;
+
+    @HealthKeys.Constant(type=HealthKeys.TYPE_TIMER)
+    public static final int TIMER_FLASHLIGHT = HealthKeys.BASE_UID + 34;
+
+    @HealthKeys.Constant(type=HealthKeys.TYPE_TIMER)
+    public static final int TIMER_CAMERA = HealthKeys.BASE_UID + 35;
+
+    @HealthKeys.Constant(type=HealthKeys.TYPE_TIMER)
+    public static final int TIMER_FOREGROUND_ACTIVITY = HealthKeys.BASE_UID + 36;
+
+    @HealthKeys.Constant(type=HealthKeys.TYPE_TIMER)
+    public static final int TIMER_BLUETOOTH_SCAN = HealthKeys.BASE_UID + 37;
+
+    @HealthKeys.Constant(type=HealthKeys.TYPE_TIMER)
+    public static final int TIMER_PROCESS_STATE_TOP_MS = HealthKeys.BASE_UID + 38;
+
+    @HealthKeys.Constant(type=HealthKeys.TYPE_TIMER)
+    public static final int TIMER_PROCESS_STATE_FOREGROUND_SERVICE_MS = HealthKeys.BASE_UID + 39;
+
+    @HealthKeys.Constant(type=HealthKeys.TYPE_TIMER)
+    public static final int TIMER_PROCESS_STATE_TOP_SLEEPING_MS = HealthKeys.BASE_UID + 40;
+
+    @HealthKeys.Constant(type=HealthKeys.TYPE_TIMER)
+    public static final int TIMER_PROCESS_STATE_FOREGROUND_MS = HealthKeys.BASE_UID + 41;
+
+    @HealthKeys.Constant(type=HealthKeys.TYPE_TIMER)
+    public static final int TIMER_PROCESS_STATE_BACKGROUND_MS = HealthKeys.BASE_UID + 42;
+
+    @HealthKeys.Constant(type=HealthKeys.TYPE_TIMER)
+    public static final int TIMER_PROCESS_STATE_CACHED_MS = HealthKeys.BASE_UID + 43;
+
+    @HealthKeys.Constant(type=HealthKeys.TYPE_TIMER)
+    public static final int TIMER_VIBRATOR = HealthKeys.BASE_UID + 44;
+
+    @HealthKeys.Constant(type=HealthKeys.TYPE_MEASUREMENT)
+    public static final int MEASUREMENT_OTHER_USER_ACTIVITY_COUNT = HealthKeys.BASE_UID + 45;
+
+    @HealthKeys.Constant(type=HealthKeys.TYPE_MEASUREMENT)
+    public static final int MEASUREMENT_BUTTON_USER_ACTIVITY_COUNT = HealthKeys.BASE_UID + 46;
+
+    @HealthKeys.Constant(type=HealthKeys.TYPE_MEASUREMENT)
+    public static final int MEASUREMENT_TOUCH_USER_ACTIVITY_COUNT = HealthKeys.BASE_UID + 47;
+
+    @HealthKeys.Constant(type=HealthKeys.TYPE_MEASUREMENT)
+    public static final int MEASUREMENT_MOBILE_RX_BYTES = HealthKeys.BASE_UID + 48;
+
+    @HealthKeys.Constant(type=HealthKeys.TYPE_MEASUREMENT)
+    public static final int MEASUREMENT_MOBILE_TX_BYTES = HealthKeys.BASE_UID + 49;
+
+    @HealthKeys.Constant(type=HealthKeys.TYPE_MEASUREMENT)
+    public static final int MEASUREMENT_WIFI_RX_BYTES = HealthKeys.BASE_UID + 50;
+
+    @HealthKeys.Constant(type=HealthKeys.TYPE_MEASUREMENT)
+    public static final int MEASUREMENT_WIFI_TX_BYTES = HealthKeys.BASE_UID + 51;
+
+    @HealthKeys.Constant(type=HealthKeys.TYPE_MEASUREMENT)
+    public static final int MEASUREMENT_BLUETOOTH_RX_BYTES = HealthKeys.BASE_UID + 52;
+
+    @HealthKeys.Constant(type=HealthKeys.TYPE_MEASUREMENT)
+    public static final int MEASUREMENT_BLUETOOTH_TX_BYTES = HealthKeys.BASE_UID + 53;
+
+    @HealthKeys.Constant(type=HealthKeys.TYPE_MEASUREMENT)
+    public static final int MEASUREMENT_MOBILE_RX_PACKETS = HealthKeys.BASE_UID + 54;
+
+    @HealthKeys.Constant(type=HealthKeys.TYPE_MEASUREMENT)
+    public static final int MEASUREMENT_MOBILE_TX_PACKETS = HealthKeys.BASE_UID + 55;
+
+    @HealthKeys.Constant(type=HealthKeys.TYPE_MEASUREMENT)
+    public static final int MEASUREMENT_WIFI_RX_PACKETS = HealthKeys.BASE_UID + 56;
+
+    @HealthKeys.Constant(type=HealthKeys.TYPE_MEASUREMENT)
+    public static final int MEASUREMENT_WIFI_TX_PACKETS = HealthKeys.BASE_UID + 57;
+
+    @HealthKeys.Constant(type=HealthKeys.TYPE_MEASUREMENT)
+    public static final int MEASUREMENT_BLUETOOTH_RX_PACKETS = HealthKeys.BASE_UID + 58;
+
+    @HealthKeys.Constant(type=HealthKeys.TYPE_MEASUREMENT)
+    public static final int MEASUREMENT_BLUETOOTH_TX_PACKETS = HealthKeys.BASE_UID + 59;
+
+    @HealthKeys.Constant(type=HealthKeys.TYPE_TIMER)
+    public static final int TIMER_MOBILE_RADIO_ACTIVE = HealthKeys.BASE_UID + 61;
+
+    @HealthKeys.Constant(type=HealthKeys.TYPE_MEASUREMENT)
+    public static final int MEASUREMENT_USER_CPU_TIME_US = HealthKeys.BASE_UID + 62;
+
+    @HealthKeys.Constant(type=HealthKeys.TYPE_MEASUREMENT)
+    public static final int MEASUREMENT_SYSTEM_CPU_TIME_US = HealthKeys.BASE_UID + 63;
+
+    /**
+     * An estimate of the number of milliamp-microsends used by this uid.
+     */
+    @HealthKeys.Constant(type=HealthKeys.TYPE_MEASUREMENT)
+    public static final int MEASUREMENT_CPU_POWER_MAUS = HealthKeys.BASE_UID + 64;
+
+    /**
+     * @hide
+     */
+    public static final HealthKeys.Constants CONSTANTS = new HealthKeys.Constants(UidHealthStats.class);
+}
+
diff --git a/core/java/android/os/health/package.html b/core/java/android/os/health/package.html
new file mode 100644
index 0000000..3a46a5b
--- /dev/null
+++ b/core/java/android/os/health/package.html
@@ -0,0 +1,39 @@
+<html>
+<body>
+
+The android.os.health package contains a set of classes to provide data
+to track the system resources of applications.
+<p>
+Applications running in the background are responsible for a significant amount 
+of battery usage on a typical android device. There are several things that 
+applications can do in order to reduce their impact. For example, by using 
+{@link android.app.job.JobScheduler JobScheduler}, an application does not need 
+to independently monitor whether the network is available, whether the device is 
+plugged in, etc.  In addition to being simpler to use, the application's 
+services are only started when the required conditions have been met.  But even 
+when using the appropriate helper APIs, applications still can reduce their 
+footprint. This package provides more insight into what is going on behind the 
+scenes when an application is running.
+<p>
+Application data is tracked by which user id (uid) is using particular 
+resources. A snapshot of an application's measurements can be taken with the
+{@link android.os.health.SystemHealthManager#takeMyUidSnapshot() SystemHealth.takeMyUidSnapshot()} 
+method. The {@link android.os.health.HealthStats} object returned contains the 
+statistics.
+<p>
+<b>HealthStats</b><br>
+In order to be returned efficiently, the {@link android.os.health.HealthStats} 
+class uses a set of int keys to identify the data returned. The
+{@link android.os.health.UidHealthStats}, {@link android.os.health.PidHealthStats},
+{@link android.os.health.PackageHealthStats} , {@link android.os.health.ProcessHealthStats},
+and {@link android.os.health.ServiceHealthStats} classes provide those constants.
+Each {@link android.os.health.HealthStats} object will be associated with
+exactly one of those classes. The object returned from
+{@link android.os.health.SystemHealthManager#takeMyUidSnapshot() SystemHealth.takeMyUidSnapshot()}
+will be using the {@link android.os.health.UidHealthStats} keys, as it contains all
+of the data available for that uid.
+
+
+</body>
+</html>
+
diff --git a/core/java/android/os/storage/IMountService.java b/core/java/android/os/storage/IMountService.java
index fc440d2..c21c65a 100644
--- a/core/java/android/os/storage/IMountService.java
+++ b/core/java/android/os/storage/IMountService.java
@@ -2286,7 +2286,12 @@
 
     /**
      * Determines the encryption state of the volume.
-     * @return a numerical value. See {@code ENCRYPTION_STATE_*} for possible values.
+     * @return a numerical value. See {@code ENCRYPTION_STATE_*} for possible
+     * values.
+     * Note that this has been replaced in most cases by the APIs in
+     * StorageManager (see isEncryptable and below)
+     * This is still useful to get the error state when encryption has failed
+     * and CryptKeeper needs to throw up a screen advising the user what to do
      */
     public int getEncryptionState() throws RemoteException;
 
diff --git a/core/java/android/os/storage/StorageManager.java b/core/java/android/os/storage/StorageManager.java
index 97ee90d..61e6b95 100644
--- a/core/java/android/os/storage/StorageManager.java
+++ b/core/java/android/os/storage/StorageManager.java
@@ -332,7 +332,7 @@
             try {
                 mMountService.registerListener(delegate);
             } catch (RemoteException e) {
-                throw e.rethrowAsRuntimeException();
+                throw e.rethrowFromSystemServer();
             }
             mDelegates.add(delegate);
         }
@@ -353,7 +353,7 @@
                     try {
                         mMountService.unregisterListener(delegate);
                     } catch (RemoteException e) {
-                        throw e.rethrowAsRuntimeException();
+                        throw e.rethrowFromSystemServer();
                     }
                     i.remove();
                 }
@@ -434,10 +434,8 @@
         } catch (IOException e) {
             throw new IllegalArgumentException("Failed to resolve path: " + rawPath, e);
         } catch (RemoteException e) {
-            Log.e(TAG, "Failed to mount OBB", e);
+            throw e.rethrowFromSystemServer();
         }
-
-        return false;
     }
 
     /**
@@ -469,10 +467,8 @@
             mMountService.unmountObb(rawPath, force, mObbActionListener, nonce);
             return true;
         } catch (RemoteException e) {
-            Log.e(TAG, "Failed to mount OBB", e);
+            throw e.rethrowFromSystemServer();
         }
-
-        return false;
     }
 
     /**
@@ -487,10 +483,8 @@
         try {
             return mMountService.isObbMounted(rawPath);
         } catch (RemoteException e) {
-            Log.e(TAG, "Failed to check if OBB is mounted", e);
+            throw e.rethrowFromSystemServer();
         }
-
-        return false;
     }
 
     /**
@@ -508,10 +502,8 @@
         try {
             return mMountService.getMountedObbPath(rawPath);
         } catch (RemoteException e) {
-            Log.e(TAG, "Failed to find mounted path for OBB", e);
+            throw e.rethrowFromSystemServer();
         }
-
-        return null;
     }
 
     /** {@hide} */
@@ -519,7 +511,7 @@
         try {
             return Arrays.asList(mMountService.getDisks());
         } catch (RemoteException e) {
-            throw e.rethrowAsRuntimeException();
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -605,7 +597,7 @@
         try {
             return Arrays.asList(mMountService.getVolumes(0));
         } catch (RemoteException e) {
-            throw e.rethrowAsRuntimeException();
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -620,7 +612,7 @@
             }
             return res;
         } catch (RemoteException e) {
-            throw e.rethrowAsRuntimeException();
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -629,7 +621,7 @@
         try {
             return Arrays.asList(mMountService.getVolumeRecords(0));
         } catch (RemoteException e) {
-            throw e.rethrowAsRuntimeException();
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -672,7 +664,7 @@
         try {
             mMountService.mount(volId);
         } catch (RemoteException e) {
-            throw e.rethrowAsRuntimeException();
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -681,7 +673,7 @@
         try {
             mMountService.unmount(volId);
         } catch (RemoteException e) {
-            throw e.rethrowAsRuntimeException();
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -690,7 +682,7 @@
         try {
             mMountService.format(volId);
         } catch (RemoteException e) {
-            throw e.rethrowAsRuntimeException();
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -699,7 +691,7 @@
         try {
             return mMountService.benchmark(volId);
         } catch (RemoteException e) {
-            throw e.rethrowAsRuntimeException();
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -708,7 +700,7 @@
         try {
             mMountService.partitionPublic(diskId);
         } catch (RemoteException e) {
-            throw e.rethrowAsRuntimeException();
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -717,7 +709,7 @@
         try {
             mMountService.partitionPrivate(diskId);
         } catch (RemoteException e) {
-            throw e.rethrowAsRuntimeException();
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -726,7 +718,7 @@
         try {
             mMountService.partitionMixed(diskId, ratio);
         } catch (RemoteException e) {
-            throw e.rethrowAsRuntimeException();
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -759,7 +751,7 @@
         try {
             mMountService.setVolumeNickname(fsUuid, nickname);
         } catch (RemoteException e) {
-            throw e.rethrowAsRuntimeException();
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -769,7 +761,7 @@
             mMountService.setVolumeUserFlags(fsUuid, inited ? VolumeRecord.USER_FLAG_INITED : 0,
                     VolumeRecord.USER_FLAG_INITED);
         } catch (RemoteException e) {
-            throw e.rethrowAsRuntimeException();
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -779,7 +771,7 @@
             mMountService.setVolumeUserFlags(fsUuid, snoozed ? VolumeRecord.USER_FLAG_SNOOZED : 0,
                     VolumeRecord.USER_FLAG_SNOOZED);
         } catch (RemoteException e) {
-            throw e.rethrowAsRuntimeException();
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -788,7 +780,7 @@
         try {
             mMountService.forgetVolume(fsUuid);
         } catch (RemoteException e) {
-            throw e.rethrowAsRuntimeException();
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -802,7 +794,7 @@
         try {
             return mMountService.getPrimaryStorageUuid();
         } catch (RemoteException e) {
-            throw e.rethrowAsRuntimeException();
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -816,7 +808,7 @@
         try {
             mMountService.setPrimaryStorageUuid(volumeUuid, callback);
         } catch (RemoteException e) {
-            throw e.rethrowAsRuntimeException();
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -900,7 +892,7 @@
             }
             return mountService.getVolumeList(uid, packageName, flags);
         } catch (RemoteException e) {
-            throw e.rethrowAsRuntimeException();
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -984,7 +976,7 @@
         try {
             mMountService.createUserKey(userId, serialNumber, ephemeral);
         } catch (RemoteException e) {
-            throw e.rethrowAsRuntimeException();
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -993,7 +985,7 @@
         try {
             mMountService.destroyUserKey(userId);
         } catch (RemoteException e) {
-            throw e.rethrowAsRuntimeException();
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1002,7 +994,7 @@
         try {
             mMountService.unlockUserKey(userId, serialNumber, token, secret);
         } catch (RemoteException e) {
-            throw e.rethrowAsRuntimeException();
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1011,7 +1003,7 @@
         try {
             mMountService.lockUserKey(userId);
         } catch (RemoteException e) {
-            throw e.rethrowAsRuntimeException();
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1020,7 +1012,7 @@
         try {
             mMountService.prepareUserStorage(volumeUuid, userId, serialNumber, flags);
         } catch (RemoteException e) {
-            throw e.rethrowAsRuntimeException();
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1029,25 +1021,123 @@
         try {
             return mMountService.isUserKeyUnlocked(userId);
         } catch (RemoteException e) {
-            throw e.rethrowAsRuntimeException();
+            throw e.rethrowFromSystemServer();
         }
     }
 
-    /** {@hide} */
-    public static boolean isFileBasedEncryptionEnabled() {
-        return isNativeFileBasedEncryptionEnabled() || isEmulatedFileBasedEncryptionEnabled();
+    /** {@hide}
+     * Is this device encryptable or already encrypted?
+     * @return true for encryptable or encrypted
+     *         false not encrypted and not encryptable
+     */
+    public static boolean isEncryptable() {
+        final String state = SystemProperties.get("ro.crypto.state", "unsupported");
+        return !"unsupported".equalsIgnoreCase(state);
+    }
+
+    /** {@hide}
+     * Is this device already encrypted?
+     * @return true for encrypted. (Implies isEncryptable() == true)
+     *         false not encrypted
+     */
+    public static boolean isEncrypted() {
+        final String state = SystemProperties.get("ro.crypto.state", "");
+        return "encrypted".equalsIgnoreCase(state);
+    }
+
+    /** {@hide}
+     * Is this device file encrypted?
+     * @return true for file encrypted. (Implies isEncrypted() == true)
+     *         false not encrypted or block encrypted
+     */
+    public static boolean isFileEncryptedNativeOnly() {
+        if (!isEncrypted()) {
+            return false;
+        }
+
+        final String status = SystemProperties.get("ro.crypto.type", "");
+        return "file".equalsIgnoreCase(status);
+    }
+
+    /** {@hide}
+     * Is this device block encrypted?
+     * @return true for block encrypted. (Implies isEncrypted() == true)
+     *         false not encrypted or file encrypted
+     */
+    public static boolean isBlockEncrypted() {
+        if (!isEncrypted()) {
+            return false;
+        }
+        final String status = SystemProperties.get("ro.crypto.type", "");
+        return "block".equalsIgnoreCase(status);
+    }
+
+    /** {@hide}
+     * Is this device block encrypted with credentials?
+     * @return true for crediential block encrypted.
+     *         (Implies isBlockEncrypted() == true)
+     *         false not encrypted, file encrypted or default block encrypted
+     */
+    public static boolean isNonDefaultBlockEncrypted() {
+        if (!isBlockEncrypted()) {
+            return false;
+        }
+
+        try {
+            IMountService mountService = IMountService.Stub.asInterface(
+                    ServiceManager.getService("mount"));
+            return mountService.getPasswordType() != CRYPT_TYPE_DEFAULT;
+        } catch (RemoteException e) {
+            Log.e(TAG, "Error getting encryption type");
+            return false;
+        }
+    }
+
+    /** {@hide}
+     * Is this device in the process of being block encrypted?
+     * @return true for encrypting.
+     *         false otherwise
+     * Whether device isEncrypted at this point is undefined
+     * Note that only system services and CryptKeeper will ever see this return
+     * true - no app will ever be launched in this state.
+     * Also note that this state will not change without a teardown of the
+     * framework, so no service needs to check for changes during their lifespan
+     */
+    public static boolean isBlockEncrypting() {
+        final String state = SystemProperties.get("vold.encrypt_progress", "");
+        return !"".equalsIgnoreCase(state);
+    }
+
+    /** {@hide}
+     * Is this device non default block encrypted and in the process of
+     * prompting for credentials?
+     * @return true for prompting for credentials.
+     *         (Implies isNonDefaultBlockEncrypted() == true)
+     *         false otherwise
+     * Note that only system services and CryptKeeper will ever see this return
+     * true - no app will ever be launched in this state.
+     * Also note that this state will not change without a teardown of the
+     * framework, so no service needs to check for changes during their lifespan
+     */
+    public static boolean inCryptKeeperBounce() {
+        final String status = SystemProperties.get("vold.decrypt");
+        return "trigger_restart_min_framework".equals(status);
     }
 
     /** {@hide} */
-    public static boolean isNativeFileBasedEncryptionEnabled() {
-        return "file".equals(SystemProperties.get("ro.crypto.type", "none"));
-    }
-
-    /** {@hide} */
-    public static boolean isEmulatedFileBasedEncryptionEnabled() {
+    public static boolean isFileEncryptedEmulatedOnly() {
         return SystemProperties.getBoolean(StorageManager.PROP_EMULATE_FBE, false);
     }
 
+    /** {@hide}
+     * Is this device running in a file encrypted mode, either native or emulated?
+     * @return true for file encrypted, false otherwise
+     */
+    public static boolean isFileEncryptedNativeOrEmulated() {
+        return isFileEncryptedNativeOnly()
+               || isFileEncryptedEmulatedOnly();
+    }
+
     /** {@hide} */
     public static File maybeTranslateEmulatedPathToInternal(File path) {
         final IMountService mountService = IMountService.Stub.asInterface(
@@ -1064,7 +1154,8 @@
                     }
                 }
             }
-        } catch (RemoteException ignored) {
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
         }
         return path;
     }
@@ -1074,7 +1165,7 @@
         try {
             return mMountService.mountAppFuse(name);
         } catch (RemoteException e) {
-            throw e.rethrowAsRuntimeException();
+            throw e.rethrowFromSystemServer();
         }
     }
 
diff --git a/core/java/android/os/storage/StorageVolume.java b/core/java/android/os/storage/StorageVolume.java
index d860c7d..54d20d3 100644
--- a/core/java/android/os/storage/StorageVolume.java
+++ b/core/java/android/os/storage/StorageVolume.java
@@ -76,7 +76,7 @@
  */
 // NOTE: This is a legacy specialization of VolumeInfo which describes the volume for a specific
 // user, but is now part of the public API.
-public class StorageVolume implements Parcelable {
+public final class StorageVolume implements Parcelable {
 
     private final String mId;
     private final int mStorageId;
diff --git a/core/java/android/os/storage/VolumeInfo.java b/core/java/android/os/storage/VolumeInfo.java
index 4b70649..ea0597d 100644
--- a/core/java/android/os/storage/VolumeInfo.java
+++ b/core/java/android/os/storage/VolumeInfo.java
@@ -438,10 +438,6 @@
         final Intent intent = new Intent(DocumentsContract.ACTION_BROWSE);
         intent.addCategory(Intent.CATEGORY_DEFAULT);
         intent.setData(uri);
-
-        // note that docsui treats this as *force* show advanced. So sending
-        // false permits advanced to be shown based on user preferences.
-        intent.putExtra(DocumentsContract.EXTRA_SHOW_ADVANCED, isPrimary());
         intent.putExtra(DocumentsContract.EXTRA_SHOW_FILESIZE, true);
         return intent;
     }
diff --git a/core/java/android/preference/EditTextPreference.java b/core/java/android/preference/EditTextPreference.java
index ff37042..9467c22 100644
--- a/core/java/android/preference/EditTextPreference.java
+++ b/core/java/android/preference/EditTextPreference.java
@@ -49,6 +49,7 @@
     private EditText mEditText;
     
     private String mText;
+    private boolean mTextSet;
 
     public EditTextPreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
         super(context, attrs, defStyleAttr, defStyleRes);
@@ -85,15 +86,16 @@
      * @param text The text to save
      */
     public void setText(String text) {
-        final boolean wasBlocking = shouldDisableDependents();
-        
-        mText = text;
-        
-        persistString(text);
-        
-        final boolean isBlocking = shouldDisableDependents(); 
-        if (isBlocking != wasBlocking) {
-            notifyDependencyChange(isBlocking);
+        // Always persist/notify the first time.
+        final boolean changed = !TextUtils.equals(mText, text);
+        if (changed || !mTextSet) {
+            mText = text;
+            mTextSet = true;
+            persistString(text);
+            if(changed) {
+                notifyDependencyChange(shouldDisableDependents());
+                notifyChanged();
+            }
         }
     }
     
diff --git a/core/java/android/print/IPrintManager.aidl b/core/java/android/print/IPrintManager.aidl
index 9a80e37..5eb8cc2 100644
--- a/core/java/android/print/IPrintManager.aidl
+++ b/core/java/android/print/IPrintManager.aidl
@@ -16,12 +16,14 @@
 
 package android.print;
 
+import android.content.ComponentName;
 import android.graphics.drawable.Icon;
 import android.os.Bundle;
 import android.print.IPrinterDiscoveryObserver;
 import android.print.IPrintDocumentAdapter;
 import android.print.PrintJobId;
 import android.print.IPrintJobStateChangeListener;
+import android.print.IPrintServicesChangeListener;
 import android.print.PrinterId;
 import android.print.PrintJobInfo;
 import android.print.PrintAttributes;
@@ -45,8 +47,47 @@
     void removePrintJobStateChangeListener(in IPrintJobStateChangeListener listener,
             int userId);
 
-    List<PrintServiceInfo> getInstalledPrintServices(int userId);
-    List<PrintServiceInfo> getEnabledPrintServices(int userId);
+    /**
+     * Listen for changes to the installed and enabled print services.
+     *
+     * @param listener the listener to add
+     * @param userId the id of the user listening
+     *
+     * @see android.print.PrintManager#getPrintServices(int, String)
+     */
+    void addPrintServicesChangeListener(in IPrintServicesChangeListener listener,
+            int userId);
+
+    /**
+     * Stop listening for changes to the installed and enabled print services.
+     *
+     * @param listener the listener to remove
+     * @param userId the id of the user requesting the removal
+     *
+     * @see android.print.PrintManager#getPrintServices(int, String)
+     */
+    void removePrintServicesChangeListener(in IPrintServicesChangeListener listener,
+            int userId);
+
+    /**
+     * Get the print services.
+     *
+     * @param selectionFlags flags selecting which services to get
+     * @param selectedService if not null, the id of the print service to get
+     * @param userId the id of the user requesting the services
+     *
+     * @return the list of selected print services.
+     */
+    List<PrintServiceInfo> getPrintServices(int selectionFlags, int userId);
+
+    /**
+     * Enable or disable a print service.
+     *
+     * @param service The service to enabled or disable
+     * @param isEnabled whether the service should be enabled or disabled
+     * @param userId the id of the user requesting the services
+     */
+    void setPrintServiceEnabled(in ComponentName service, boolean isEnabled, int userId);
 
     void createPrinterDiscoverySession(in IPrinterDiscoveryObserver observer, int userId);
     void startPrinterDiscovery(in IPrinterDiscoveryObserver observer,
diff --git a/core/java/android/hardware/camera2/utils/LongParcelable.aidl b/core/java/android/print/IPrintServicesChangeListener.aidl
similarity index 70%
rename from core/java/android/hardware/camera2/utils/LongParcelable.aidl
rename to core/java/android/print/IPrintServicesChangeListener.aidl
index 98ad1b2..2a7ce89 100644
--- a/core/java/android/hardware/camera2/utils/LongParcelable.aidl
+++ b/core/java/android/print/IPrintServicesChangeListener.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2014 The Android Open Source Project
+ * Copyright (C) 2016 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -14,7 +14,13 @@
  * limitations under the License.
  */
 
-package android.hardware.camera2.utils;
+package android.print;
 
-/** @hide */
-parcelable LongParcelable;
+/**
+ * Interface for observing print services changes.
+ *
+ * @hide
+ */
+oneway interface IPrintServicesChangeListener {
+    void onPrintServicesChanged();
+}
diff --git a/core/java/android/print/PrintManager.java b/core/java/android/print/PrintManager.java
index 58f260c..25fc968 100644
--- a/core/java/android/print/PrintManager.java
+++ b/core/java/android/print/PrintManager.java
@@ -20,6 +20,7 @@
 import android.annotation.Nullable;
 import android.app.Activity;
 import android.app.Application.ActivityLifecycleCallbacks;
+import android.content.ComponentName;
 import android.content.Context;
 import android.content.IntentSender;
 import android.content.IntentSender.SendIntentException;
@@ -111,6 +112,38 @@
     private static final boolean DEBUG = false;
 
     private static final int MSG_NOTIFY_PRINT_JOB_STATE_CHANGED = 1;
+    private static final int MSG_NOTIFY_PRINT_SERVICES_CHANGED = 2;
+
+    /**
+     * Package name of print spooler.
+     *
+     * @hide
+     */
+    public static final String PRINT_SPOOLER_PACKAGE_NAME = "com.android.printspooler";
+
+    /**
+     * Select enabled services.
+     * </p>
+     * @see #getPrintServices
+     * @hide
+     */
+    public static final int ENABLED_SERVICES = 1 << 0;
+
+    /**
+     * Select disabled services.
+     * </p>
+     * @see #getPrintServices
+     * @hide
+     */
+    public static final int DISABLED_SERVICES = 1 << 1;
+
+    /**
+     * Select all services.
+     * </p>
+     * @see #getPrintServices
+     * @hide
+     */
+    public static final int ALL_SERVICES = ENABLED_SERVICES | DISABLED_SERVICES;
 
     /**
      * The action for launching the print dialog activity.
@@ -165,7 +198,10 @@
 
     private final Handler mHandler;
 
-    private Map<PrintJobStateChangeListener, PrintJobStateChangeListenerWrapper> mPrintJobStateChangeListeners;
+    private Map<PrintJobStateChangeListener, PrintJobStateChangeListenerWrapper>
+            mPrintJobStateChangeListeners;
+    private Map<PrintServicesChangeListener, PrintServicesChangeListenerWrapper>
+            mPrintServicesChangeListeners;
 
     /** @hide */
     public interface PrintJobStateChangeListener {
@@ -178,6 +214,15 @@
         public void onPrintJobStateChanged(PrintJobId printJobId);
     }
 
+    /** @hide */
+    public interface PrintServicesChangeListener {
+
+        /**
+         * Callback notifying that the print services changed.
+         */
+        public void onPrintServicesChanged();
+    }
+
     /**
      * Creates a new instance.
      *
@@ -207,6 +252,15 @@
                         }
                         args.recycle();
                     } break;
+                    case MSG_NOTIFY_PRINT_SERVICES_CHANGED: {
+                        PrintServicesChangeListenerWrapper wrapper =
+                                (PrintServicesChangeListenerWrapper) message.obj;
+                        PrintServicesChangeListener listener = wrapper.getListener();
+                        if (listener != null) {
+                            listener.onPrintServicesChanged();
+                        }
+                    } break;
+
                 }
             }
         };
@@ -232,9 +286,8 @@
         try {
             return mService.getPrintJobInfo(printJobId, mAppId, mUserId);
         } catch (RemoteException re) {
-            Log.e(LOG_TAG, "Error getting a print job info:" + printJobId, re);
+            throw re.rethrowFromSystemServer();
         }
-        return null;
     }
 
     /**
@@ -258,7 +311,7 @@
             mService.addPrintJobStateChangeListener(wrappedListener, mAppId, mUserId);
             mPrintJobStateChangeListeners.put(listener, wrappedListener);
         } catch (RemoteException re) {
-            Log.e(LOG_TAG, "Error adding print job state change listener", re);
+            throw re.rethrowFromSystemServer();
         }
     }
 
@@ -288,7 +341,7 @@
         try {
             mService.removePrintJobStateChangeListener(wrappedListener, mUserId);
         } catch (RemoteException re) {
-            Log.e(LOG_TAG, "Error removing print job state change listener", re);
+            throw re.rethrowFromSystemServer();
         }
     }
 
@@ -311,7 +364,7 @@
                 return new PrintJob(printJob, this);
             }
         } catch (RemoteException re) {
-            Log.e(LOG_TAG, "Error getting print job", re);
+            throw re.rethrowFromSystemServer();
         }
         return null;
     }
@@ -334,9 +387,8 @@
         try {
             return mService.getCustomPrinterIcon(printerId, mUserId);
         } catch (RemoteException re) {
-            Log.e(LOG_TAG, "Error getting custom printer icon", re);
+            throw re.rethrowFromSystemServer();
         }
-        return null;
     }
 
     /**
@@ -362,9 +414,8 @@
             }
             return printJobs;
         } catch (RemoteException re) {
-            Log.e(LOG_TAG, "Error getting print jobs", re);
+            throw re.rethrowFromSystemServer();
         }
-        return Collections.emptyList();
     }
 
     void cancelPrintJob(PrintJobId printJobId) {
@@ -375,7 +426,7 @@
         try {
             mService.cancelPrintJob(printJobId, mAppId, mUserId);
         } catch (RemoteException re) {
-            Log.e(LOG_TAG, "Error canceling a print job: " + printJobId, re);
+            throw re.rethrowFromSystemServer();
         }
     }
 
@@ -387,7 +438,7 @@
         try {
             mService.restartPrintJob(printJobId, mAppId, mUserId);
         } catch (RemoteException re) {
-            Log.e(LOG_TAG, "Error restarting a print job: " + printJobId, re);
+            throw re.rethrowFromSystemServer();
         }
     }
 
@@ -475,51 +526,91 @@
                 }
             }
         } catch (RemoteException re) {
-            Log.e(LOG_TAG, "Error creating a print job", re);
+            throw re.rethrowFromSystemServer();
         }
         return null;
     }
 
     /**
-     * Gets the list of enabled print services.
+     * Listen for changes to the installed and enabled print services.
      *
-     * @return The enabled service list or an empty list.
-     * @hide
+     * @param listener the listener to add
+     *
+     * @see android.print.PrintManager#getPrintServices
      */
-    public List<PrintServiceInfo> getEnabledPrintServices() {
+    void addPrintServicesChangeListener(@NonNull PrintServicesChangeListener listener) {
         if (mService == null) {
             Log.w(LOG_TAG, "Feature android.software.print not available");
-            return Collections.emptyList();
+            return;
         }
+        if (mPrintServicesChangeListeners == null) {
+            mPrintServicesChangeListeners = new ArrayMap<PrintServicesChangeListener,
+                    PrintServicesChangeListenerWrapper>();
+        }
+        PrintServicesChangeListenerWrapper wrappedListener =
+                new PrintServicesChangeListenerWrapper(listener, mHandler);
         try {
-            List<PrintServiceInfo> enabledServices = mService.getEnabledPrintServices(mUserId);
-            if (enabledServices != null) {
-                return enabledServices;
-            }
+            mService.addPrintServicesChangeListener(wrappedListener, mUserId);
+            mPrintServicesChangeListeners.put(listener, wrappedListener);
         } catch (RemoteException re) {
-            Log.e(LOG_TAG, "Error getting the enabled print services", re);
+            throw re.rethrowFromSystemServer();
         }
-        return Collections.emptyList();
     }
 
     /**
-     * Gets the list of installed print services.
+     * Stop listening for changes to the installed and enabled print services.
      *
-     * @return The installed service list or an empty list.
-     * @hide
+     * @param listener the listener to remove
+     *
+     * @see android.print.PrintManager#getPrintServices
      */
-    public List<PrintServiceInfo> getInstalledPrintServices() {
+    void removePrintServicesChangeListener(@NonNull PrintServicesChangeListener listener) {
         if (mService == null) {
             Log.w(LOG_TAG, "Feature android.software.print not available");
-            return Collections.emptyList();
+            return;
         }
+        if (mPrintServicesChangeListeners == null) {
+            return;
+        }
+        PrintServicesChangeListenerWrapper wrappedListener =
+                mPrintServicesChangeListeners.remove(listener);
+        if (wrappedListener == null) {
+            return;
+        }
+        if (mPrintServicesChangeListeners.isEmpty()) {
+            mPrintServicesChangeListeners = null;
+        }
+        wrappedListener.destroy();
         try {
-            List<PrintServiceInfo> installedServices = mService.getInstalledPrintServices(mUserId);
-            if (installedServices != null) {
-                return installedServices;
+            mService.removePrintServicesChangeListener(wrappedListener, mUserId);
+        } catch (RemoteException re) {
+            Log.e(LOG_TAG, "Error removing print services change listener", re);
+        }
+    }
+
+
+    /**
+     * Gets the list of print services, but does not register for updates. The user has to register
+     * for updates by itself, or use {@link PrintServicesLoader}.
+     *
+     * @param selectionFlags flags selecting which services to get. Either
+     *                       {@link #ENABLED_SERVICES},{@link #DISABLED_SERVICES}, or both.
+     *
+     * @return The enabled service list or an empty list.
+     *
+     * @see #addPrintServicesChangeListener(PrintServicesChangeListener)
+     * @see #removePrintServicesChangeListener(PrintServicesChangeListener)
+     *
+     * @hide
+     */
+    public @NonNull List<PrintServiceInfo> getPrintServices(int selectionFlags) {
+        try {
+            List<PrintServiceInfo> services = mService.getPrintServices(selectionFlags, mUserId);
+            if (services != null) {
+                return services;
             }
         } catch (RemoteException re) {
-            Log.e(LOG_TAG, "Error getting the installed print services", re);
+            throw re.rethrowFromSystemServer();
         }
         return Collections.emptyList();
     }
@@ -536,6 +627,26 @@
     }
 
     /**
+     * Enable or disable a print service.
+     *
+     * @param service The service to enabled or disable
+     * @param isEnabled whether the service should be enabled or disabled
+     *
+     * @hide
+     */
+    public void setPrintServiceEnabled(@NonNull ComponentName service, boolean isEnabled) {
+        if (mService == null) {
+            Log.w(LOG_TAG, "Feature android.software.print not available");
+            return;
+        }
+        try {
+            mService.setPrintServiceEnabled(service, isEnabled, mUserId);
+        } catch (RemoteException re) {
+            Log.e(LOG_TAG, "Error enabling or disabling " + service, re);
+        }
+    }
+
+    /**
      * @hide
      */
     public static final class PrintDocumentAdapterDelegate extends IPrintDocumentAdapter.Stub
@@ -1099,4 +1210,36 @@
             return mWeakListener.get();
         }
     }
+
+    /**
+     * @hide
+     */
+    public static final class PrintServicesChangeListenerWrapper extends
+            IPrintServicesChangeListener.Stub {
+        private final WeakReference<PrintServicesChangeListener> mWeakListener;
+        private final WeakReference<Handler> mWeakHandler;
+
+        public PrintServicesChangeListenerWrapper(PrintServicesChangeListener listener,
+                Handler handler) {
+            mWeakListener = new WeakReference<>(listener);
+            mWeakHandler = new WeakReference<>(handler);
+        }
+
+        @Override
+        public void onPrintServicesChanged() {
+            Handler handler = mWeakHandler.get();
+            PrintServicesChangeListener listener = mWeakListener.get();
+            if (handler != null && listener != null) {
+                handler.obtainMessage(MSG_NOTIFY_PRINT_SERVICES_CHANGED, this).sendToTarget();
+            }
+        }
+
+        public void destroy() {
+            mWeakListener.clear();
+        }
+
+        public PrintServicesChangeListener getListener() {
+            return mWeakListener.get();
+        }
+    }
 }
diff --git a/core/java/android/print/PrintServicesLoader.java b/core/java/android/print/PrintServicesLoader.java
new file mode 100644
index 0000000..ed41114
--- /dev/null
+++ b/core/java/android/print/PrintServicesLoader.java
@@ -0,0 +1,125 @@
+/*
+ * 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.print;
+
+import android.annotation.NonNull;
+import android.content.Context;
+import android.content.Loader;
+import android.os.Handler;
+import android.os.Message;
+import android.printservice.PrintServiceInfo;
+
+import java.util.List;
+
+/**
+ * Loader for the list of print services. Can be parametrized to select a subset.
+ *
+ * @hide
+ */
+public class PrintServicesLoader extends Loader<List<PrintServiceInfo>> {
+    /** What type of services to load. */
+    private final int mSelectionFlags;
+
+    /** The print manager to be used by this object */
+    private final @NonNull PrintManager mPrintManager;
+
+    /** Handler to sequentialize the delivery of the results to the main thread */
+    private Handler mHandler;
+
+    /** Listens for updates to the data from the platform */
+    private PrintManager.PrintServicesChangeListener mListener;
+
+    /**
+     * Create a new PrintServicesLoader.
+     *
+     * @param selectionFlags What type of services to load.
+     */
+    public PrintServicesLoader(@NonNull PrintManager printManager, @NonNull Context context,
+            int selectionFlags) {
+        super(context);
+        mPrintManager = printManager;
+        mSelectionFlags = selectionFlags;
+    }
+
+    @Override
+    protected void onForceLoad() {
+        queueNewResult();
+    }
+
+    /**
+     * Read the print services and queue it to be delivered on the main thread.
+     */
+    private void queueNewResult() {
+        Message m = mHandler.obtainMessage(0);
+        m.obj = mPrintManager.getPrintServices(mSelectionFlags);
+        mHandler.sendMessage(m);
+    }
+
+    @Override
+    protected void onStartLoading() {
+        mHandler = new MyHandler();
+        mListener = new PrintManager.PrintServicesChangeListener() {
+            @Override public void onPrintServicesChanged() {
+                queueNewResult();
+            }
+        };
+
+        mPrintManager.addPrintServicesChangeListener(mListener);
+
+        // Immediately deliver a result
+        deliverResult(mPrintManager.getPrintServices(mSelectionFlags));
+    }
+
+    @Override
+    protected void onStopLoading() {
+        if (mListener != null) {
+            mPrintManager.removePrintServicesChangeListener(mListener);
+            mListener = null;
+        }
+
+        if (mHandler != null) {
+            mHandler.removeMessages(0);
+            mHandler = null;
+        }
+    }
+
+    @Override
+    protected void onReset() {
+        onStopLoading();
+    }
+
+    /**
+     * Handler to sequentialize all the updates to the main thread.
+     */
+    private class MyHandler extends Handler {
+        /**
+         * Create a new handler on the main thread.
+         */
+        public MyHandler() {
+            super(getContext().getMainLooper());
+        }
+
+        @Override
+        public void handleMessage(Message msg) {
+            super.handleMessage(msg);
+
+            if (isStarted()) {
+                deliverResult((List<PrintServiceInfo>) msg.obj);
+            }
+        }
+    }
+}
diff --git a/core/java/android/printservice/PrintServiceInfo.java b/core/java/android/printservice/PrintServiceInfo.java
index 91e01f2..45e3d47 100644
--- a/core/java/android/printservice/PrintServiceInfo.java
+++ b/core/java/android/printservice/PrintServiceInfo.java
@@ -55,6 +55,8 @@
 
     private final String mId;
 
+    private boolean mIsEnabled;
+
     private final ResolveInfo mResolveInfo;
 
     private final String mSettingsActivityName;
@@ -70,6 +72,7 @@
      */
     public PrintServiceInfo(Parcel parcel) {
         mId = parcel.readString();
+        mIsEnabled = parcel.readByte() != 0;
         mResolveInfo = parcel.readParcelable(null);
         mSettingsActivityName = parcel.readString();
         mAddPrintersActivityName = parcel.readString();
@@ -180,6 +183,24 @@
     }
 
     /**
+     * If the service was enabled when it was read from the system.
+     *
+     * @return The id.
+     */
+    public boolean isEnabled() {
+        return mIsEnabled;
+    }
+
+    /**
+     * Mark a service as enabled or not
+     *
+     * @param isEnabled If the service should be marked as enabled.
+     */
+    public void setIsEnabled(boolean isEnabled) {
+        mIsEnabled = isEnabled;
+    }
+
+    /**
      * The service {@link ResolveInfo}.
      *
      * @return The info.
@@ -238,6 +259,7 @@
     @Override
     public void writeToParcel(Parcel parcel, int flagz) {
         parcel.writeString(mId);
+        parcel.writeByte((byte)(mIsEnabled ? 1 : 0));
         parcel.writeParcelable(mResolveInfo, 0);
         parcel.writeString(mSettingsActivityName);
         parcel.writeString(mAddPrintersActivityName);
@@ -276,6 +298,7 @@
         StringBuilder builder = new StringBuilder();
         builder.append("PrintServiceInfo{");
         builder.append("id=").append(mId);
+        builder.append("isEnabled=").append(mIsEnabled);
         builder.append(", resolveInfo=").append(mResolveInfo);
         builder.append(", settingsActivityName=").append(mSettingsActivityName);
         builder.append(", addPrintersActivityName=").append(mAddPrintersActivityName);
diff --git a/core/java/android/provider/BlockedNumberContract.java b/core/java/android/provider/BlockedNumberContract.java
index b921351..def303a 100644
--- a/core/java/android/provider/BlockedNumberContract.java
+++ b/core/java/android/provider/BlockedNumberContract.java
@@ -32,6 +32,12 @@
  * blocked numbers are discarded by the platform. Notifications upon provider changes can be
  * received using a {@link android.database.ContentObserver}.
  * </p>
+ * <p>
+ * The platform will not block messages, and calls from emergency numbers as defined by
+ * {@link android.telephony.PhoneNumberUtils#isEmergencyNumber(String)}. If the user contacts
+ * emergency services, number blocking is disabled by the platform for a duration defined by
+ * {@link android.telephony.CarrierConfigManager#KEY_DURATION_BLOCKING_DISABLED_AFTER_EMERGENCY_INT}.
+ * </p>
  *
  * <h3> Permissions </h3>
  * <p>
@@ -141,25 +147,26 @@
 
         /**
          * Content URI for the blocked numbers.
-         *
-         * Supported operations
-         * blocked
-         * - query
-         * - delete
-         * - insert
-         *
-         * blocked/ID
-         * - query (selection is not supported)
-         * - delete (selection is not supported)
+         * <h3> Supported operations </h3>
+         * <p> blocked
+         * <ul>
+         * <li> query
+         * <li> delete
+         * <li> insert
+         * </ul>
+         * <p> blocked/ID
+         * <ul>
+         * <li> query (selection is not supported)
+         * <li> delete (selection is not supported)
+         * </ul>
          */
-        public static final Uri CONTENT_URI = Uri.withAppendedPath(AUTHORITY_URI,
-                "blocked");
+        public static final Uri CONTENT_URI = Uri.withAppendedPath(AUTHORITY_URI, "blocked");
 
         /**
          * The MIME type of {@link #CONTENT_URI} itself providing a directory of blocked phone
          * numbers.
          */
-        public static final String CONTENT_TYPE = "vnd.android.cursor.dir/blocked_numbers";
+        public static final String CONTENT_TYPE = "vnd.android.cursor.dir/blocked_number";
 
         /**
          * The MIME type of a blocked phone number under {@link #CONTENT_URI}.
@@ -215,7 +222,7 @@
 
     /**
      * Returns {@code true} if blocking numbers is supported for the current user.
-     * <p> Typically, blocking numbers is only supported for the primary user.
+     * <p> Typically, blocking numbers is only supported for one user at a time.
      */
     public static boolean canCurrentUserBlockNumbers(Context context) {
         final Bundle res = context.getContentResolver().call(
@@ -292,6 +299,9 @@
             return res != null && res.getBoolean(RES_NUMBER_IS_BLOCKED, false);
         }
 
+        /**
+         * Returns the current status of block suppression.
+         */
         public static BlockSuppressionStatus getBlockSuppressionStatus(Context context) {
             final Bundle res = context.getContentResolver().call(
                     AUTHORITY_URI, METHOD_GET_BLOCK_SUPPRESSION_STATUS, null, null);
diff --git a/core/java/android/provider/ContactsContract.java b/core/java/android/provider/ContactsContract.java
index 904b393..3658df9 100644
--- a/core/java/android/provider/ContactsContract.java
+++ b/core/java/android/provider/ContactsContract.java
@@ -5185,6 +5185,10 @@
          *     <li>
          *     Corp contacts will get artificial {@link #LOOKUP_KEY}s too.
          *     </li>
+         *     <li>
+         *     Returned work contact IDs and lookup keys are not accepted in places that not
+         *     explicitly say to accept them.
+         *     </li>
          * </ul>
          * <p>
          * A contact lookup URL built by
@@ -6194,6 +6198,10 @@
              *     <li>
              *     Corp contacts will get artificial {@link #LOOKUP_KEY}s too.
              *     </li>
+             *     <li>
+             *     Returned work contact IDs and lookup keys are not accepted in places that not
+             *     explicitly say to accept them.
+             *     </li>
              * </ul>
              * <p>
              * A contact lookup URL built by
@@ -8466,7 +8474,9 @@
          *            around this {@link View}.
          * @param lookupUri A {@link ContactsContract.Contacts#CONTENT_LOOKUP_URI} style
          *            {@link Uri} that describes a specific contact to feature
-         *            in this dialog.
+         *            in this dialog. A work lookup uri is supported here,
+         *            see {@link CommonDataKinds.Email#ENTERPRISE_CONTENT_LOOKUP_URI} and
+         *            {@link PhoneLookup#ENTERPRISE_CONTENT_FILTER_URI}.
          * @param mode Any of {@link #MODE_SMALL}, {@link #MODE_MEDIUM}, or
          *            {@link #MODE_LARGE}, indicating the desired dialog size,
          *            when supported.
@@ -8500,7 +8510,9 @@
          * @param lookupUri A
          *            {@link ContactsContract.Contacts#CONTENT_LOOKUP_URI} style
          *            {@link Uri} that describes a specific contact to feature
-         *            in this dialog.
+         *            in this dialog. A work lookup uri is supported here,
+         *            see {@link CommonDataKinds.Email#ENTERPRISE_CONTENT_LOOKUP_URI} and
+         *            {@link PhoneLookup#ENTERPRISE_CONTENT_FILTER_URI}.
          * @param mode Any of {@link #MODE_SMALL}, {@link #MODE_MEDIUM}, or
          *            {@link #MODE_LARGE}, indicating the desired dialog size,
          *            when supported.
@@ -8531,7 +8543,9 @@
          * @param lookupUri A
          *            {@link ContactsContract.Contacts#CONTENT_LOOKUP_URI} style
          *            {@link Uri} that describes a specific contact to feature
-         *            in this dialog.
+         *            in this dialog. A work lookup uri is supported here,
+         *            see {@link CommonDataKinds.Email#ENTERPRISE_CONTENT_LOOKUP_URI} and
+         *            {@link PhoneLookup#ENTERPRISE_CONTENT_FILTER_URI}.
          * @param excludeMimes Optional list of {@link Data#MIMETYPE} MIME-types
          *            to exclude when showing this dialog. For example, when
          *            already viewing the contact details card, this can be used
@@ -8569,7 +8583,9 @@
          * @param lookupUri A
          *            {@link ContactsContract.Contacts#CONTENT_LOOKUP_URI} style
          *            {@link Uri} that describes a specific contact to feature
-         *            in this dialog.
+         *            in this dialog. A work lookup uri is supported here,
+         *            see {@link CommonDataKinds.Email#ENTERPRISE_CONTENT_LOOKUP_URI} and
+         *            {@link PhoneLookup#ENTERPRISE_CONTENT_FILTER_URI}.
          * @param excludeMimes Optional list of {@link Data#MIMETYPE} MIME-types
          *            to exclude when showing this dialog. For example, when
          *            already viewing the contact details card, this can be used
@@ -8763,6 +8779,15 @@
          * <li><em>Note: Some apps may choose to use phone number as the unique contact ID in DATA1.
          * If this applies to you and you’d like phone number to be shown below the Contact Name by
          * the Voice Assistant, then you may choose to leave DATA3 empty.</em></li>
+         * <li><em>Note: If your app also uses DATA3 to display contact details in the Contacts App,
+         * make sure it does not include prefix text such as "Message +<phone>" or "Free Message
+         * +<phone>", etc. If you must show the prefix text in the Contacts App, please use a
+         * different DATA# column, and update your contacts.xml to point to this new column. </em>
+         * </li>
+         * <li>Everytime the user sends a message to a contact, your app may choose to update the
+         * {@link ContactOptionsColumns#TIMES_CONTACTED} entry through DataUsageFeedback class.
+         * Doing this will allow Voice Assistant to bias speech recognition to contacts frequently
+         * contacted, this is particularly useful for contact names that are hard to pronounce.</li>
          * </ul>
          * <p>
          * Input: {@link android.content.Intent#getType} is the MIME type of the data being sent.
diff --git a/core/java/android/provider/DocumentsContract.java b/core/java/android/provider/DocumentsContract.java
index 3700098..e7a9b7d 100644
--- a/core/java/android/provider/DocumentsContract.java
+++ b/core/java/android/provider/DocumentsContract.java
@@ -93,9 +93,6 @@
     public static final String EXTRA_PACKAGE_NAME = "android.content.extra.PACKAGE_NAME";
 
     /** {@hide} */
-    public static final String EXTRA_SHOW_ADVANCED = "android.content.extra.SHOW_ADVANCED";
-
-    /** {@hide} */
     public static final String EXTRA_SHOW_FILESIZE = "android.content.extra.SHOW_FILESIZE";
 
     /** {@hide} */
@@ -122,8 +119,6 @@
     public static final String EXTRA_PROMPT = "android.provider.extra.PROMPT";
 
     /** {@hide} */
-    public static final String ACTION_MANAGE_ROOT = "android.provider.action.MANAGE_ROOT";
-    /** {@hide} */
     public static final String ACTION_MANAGE_DOCUMENT = "android.provider.action.MANAGE_DOCUMENT";
 
     /** {@hide} */
@@ -386,18 +381,6 @@
          */
 
         public static final int FLAG_ARCHIVE = 1 << 15;
-        /**
-         * Flag indicating that document titles should be hidden when viewing
-         * this directory in a larger format grid. For example, a directory
-         * containing only images may want the image thumbnails to speak for
-         * themselves. Only valid when {@link #COLUMN_MIME_TYPE} is
-         * {@link #MIME_TYPE_DIR}.
-         *
-         * @see #COLUMN_FLAGS
-         * @see #FLAG_DIR_PREFERS_GRID
-         * @hide
-         */
-        public static final int FLAG_DIR_HIDE_GRID_TITLES = 1 << 16;
     }
 
     /**
@@ -481,7 +464,6 @@
         /**
          * Capacity of a root in bytes. This column is optional, and may be
          * {@code null} if unknown or unbounded.
-         * {@hide}
          * <p>
          * Type: INTEGER (long)
          */
@@ -564,22 +546,29 @@
         public static final int FLAG_EMPTY = 1 << 16;
 
         /**
-         * Flag indicating that this root should only be visible to advanced
-         * users.
-         *
-         * @see #COLUMN_FLAGS
-         * @hide
-         */
-        public static final int FLAG_ADVANCED = 1 << 17;
-
-        /**
          * Flag indicating that this root has settings.
          *
          * @see #COLUMN_FLAGS
          * @see DocumentsContract#ACTION_DOCUMENT_ROOT_SETTINGS
          * @hide
          */
-        public static final int FLAG_HAS_SETTINGS = 1 << 18;
+        public static final int FLAG_HAS_SETTINGS = 1 << 17;
+
+        /**
+         * Flag indicating that this root is on removable SD card storage.
+         *
+         * @see #COLUMN_FLAGS
+         * @hide
+         */
+        public static final int FLAG_REMOVABLE_SD = 1 << 18;
+
+        /**
+         * Flag indicating that this root is on removable USB storage.
+         *
+         * @see #COLUMN_FLAGS
+         * @hide
+         */
+        public static final int FLAG_REMOVABLE_USB = 1 << 19;
     }
 
     /**
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index cb45deb..d4ff766 100755
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -1241,6 +1241,32 @@
     public static final String ACTION_SHOW_ADMIN_SUPPORT_DETAILS
             = "android.settings.SHOW_ADMIN_SUPPORT_DETAILS";
 
+    /**
+     * Activity Action: Show a dialog for remote bugreport flow.
+     * <p>
+     * Input: Nothing.
+     * <p>
+     * Output: Nothing.
+     *
+     * @hide
+     */
+    @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+    public static final String ACTION_SHOW_REMOTE_BUGREPORT_DIALOG
+            = "android.settings.SHOW_REMOTE_BUGREPORT_DIALOG";
+
+    /**
+     * Activity Action: Show VR listener settings.
+     * <p>
+     * Input: Nothing.
+     * <p>
+     * Output: Nothing.
+     *
+     * @see android.service.vr.VrListenerService
+     */
+    @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+    public static final String ACTION_VR_LISTENER_SETTINGS
+            = "android.settings.VR_LISTENER_SETTINGS";
+
     // End of Intent actions for Settings
 
     /**
@@ -4522,6 +4548,13 @@
         public static final String USER_SETUP_COMPLETE = "user_setup_complete";
 
         /**
+         * Prefix for category name that marks whether a suggested action from that category was
+         * completed.
+         * @hide
+         */
+        public static final String COMPLETED_CATEGORY_PREFIX = "suggested.completed_category.";
+
+        /**
          * List of input methods that are currently enabled.  This is a string
          * containing the IDs of all enabled input methods, each ID separated
          * by ':'.
@@ -5834,15 +5867,6 @@
         public static final String ASSIST_SCREENSHOT_ENABLED = "assist_screenshot_enabled";
 
         /**
-         * Names of the service component that the current user has explicitly allowed to
-         * see and change the importance of all of the user's notifications.
-         *
-         * @hide
-         */
-        public static final String ENABLED_NOTIFICATION_ASSISTANT
-                = "enabled_notification_assistant";
-
-        /**
          * Names of the service components that the current user has explicitly allowed to
          * see all of the user's notifications, separated by ':'.
          *
@@ -6021,6 +6045,14 @@
         public static final String BRIGHTNESS_USE_TWILIGHT = "brightness_use_twilight";
 
         /**
+         * Names of the service components that the current user has explicitly allowed to
+         * be a VR mode listener, separated by ':'.
+         *
+         * @hide
+         */
+        public static final String ENABLED_VR_LISTENERS = "enabled_vr_listeners";
+
+        /**
          * This are the settings to be backed up.
          *
          * NOTE: Settings are backed up and restored in the order they appear
@@ -6047,6 +6079,7 @@
             BACKUP_AUTO_RESTORE,
             ENABLED_ACCESSIBILITY_SERVICES,
             ENABLED_NOTIFICATION_LISTENERS,
+            ENABLED_VR_LISTENERS,
             ENABLED_INPUT_METHODS,
             TOUCH_EXPLORATION_GRANTED_ACCESSIBILITY_SERVICES,
             TOUCH_EXPLORATION_ENABLED,
@@ -7753,6 +7786,31 @@
         public static final String ALARM_MANAGER_CONSTANTS = "alarm_manager_constants";
 
         /**
+         * ShortcutManager specific settings.
+         * This is encoded as a key=value list, separated by commas. Ex:
+         *
+         * "reset_interval_sec=86400,max_daily_updates=5"
+         *
+         * The following keys are supported:
+         *
+         * <pre>
+         * reset_interval_sec              (long)
+         * max_daily_updates               (int)
+         * max_icon_dimension_dp           (int, DP)
+         * max_icon_dimension_dp_lowram    (int, DP)
+         * max_shortcuts                   (int)
+         * icon_quality                    (int, 0-100)
+         * icon_format                     (String)
+         * </pre>
+         *
+         * <p>
+         * Type: string
+         * @hide
+         * @see com.android.server.pm.ShortcutService.ConfigConstants
+         */
+        public static final String SHORTCUT_MANAGER_CONSTANTS = "shortcut_manager_constants";
+
+        /**
          * Get the key that retrieves a bluetooth headset's priority.
          * @hide
          */
@@ -8240,6 +8298,13 @@
                 "allow_user_switching_when_system_user_locked";
 
         /**
+         * Boot count since the device starts running APK level 24.
+         * <p>
+         * Type: int
+         */
+        public static final String BOOT_COUNT = "boot_count";
+
+        /**
          * Settings to backup. This is here so that it's in the same place as the settings
          * keys and easy to update.
          *
diff --git a/core/java/android/security/net/config/XmlConfigSource.java b/core/java/android/security/net/config/XmlConfigSource.java
index 2a8773c..d57d0f5 100644
--- a/core/java/android/security/net/config/XmlConfigSource.java
+++ b/core/java/android/security/net/config/XmlConfigSource.java
@@ -339,7 +339,7 @@
                 }
                 if (mDebugBuild) {
                     debugConfigBuilder =
-                            parseConfigEntry(parser, seenDomains, null, CONFIG_DEBUG).get(0).first;
+                            parseConfigEntry(parser, null, null, CONFIG_DEBUG).get(0).first;
                 } else {
                     XmlUtils.skipCurrentTag(parser);
                 }
@@ -348,6 +348,11 @@
                 XmlUtils.skipCurrentTag(parser);
             }
         }
+        // If debug is true and there was no debug-overrides in the file check for an extra
+        // _debug resource.
+        if (mDebugBuild && debugConfigBuilder == null) {
+            debugConfigBuilder = parseDebugOverridesResource();
+        }
 
         // Use the platform default as the parent of the base config for any values not provided
         // there. If there is no base config use the platform default.
@@ -385,6 +390,43 @@
         mDomainMap = configs;
     }
 
+    private NetworkSecurityConfig.Builder parseDebugOverridesResource()
+            throws IOException, XmlPullParserException, ParserException {
+        Resources resources = mContext.getResources();
+        String packageName = resources.getResourcePackageName(mResourceId);
+        String entryName = resources.getResourceEntryName(mResourceId);
+        int resId = resources.getIdentifier(entryName + "_debug", "xml", packageName);
+        // No debug-overrides resource was found, nothing to parse.
+        if (resId == 0) {
+            return null;
+        }
+        NetworkSecurityConfig.Builder debugConfigBuilder = null;
+        // Parse debug-overrides out of the _debug resource.
+        try (XmlResourceParser parser = resources.getXml(resId)) {
+            XmlUtils.beginDocument(parser, "network-security-config");
+            int outerDepth = parser.getDepth();
+            boolean seenDebugOverrides = false;
+            while (XmlUtils.nextElementWithin(parser, outerDepth)) {
+                if ("debug-overrides".equals(parser.getName())) {
+                    if (seenDebugOverrides) {
+                        throw new ParserException(parser, "Only one debug-overrides allowed");
+                    }
+                    if (mDebugBuild) {
+                        debugConfigBuilder =
+                                parseConfigEntry(parser, null, null, CONFIG_DEBUG).get(0).first;
+                    } else {
+                        XmlUtils.skipCurrentTag(parser);
+                    }
+                    seenDebugOverrides = true;
+                } else {
+                    XmlUtils.skipCurrentTag(parser);
+                }
+            }
+        }
+
+        return debugConfigBuilder;
+    }
+
     public static class ParserException extends Exception {
 
         public ParserException(XmlPullParser parser, String message, Throwable cause) {
diff --git a/core/java/android/service/carrier/CarrierMessagingService.java b/core/java/android/service/carrier/CarrierMessagingService.java
index f5396a3..140341c 100644
--- a/core/java/android/service/carrier/CarrierMessagingService.java
+++ b/core/java/android/service/carrier/CarrierMessagingService.java
@@ -51,6 +51,30 @@
             = "android.service.carrier.CarrierMessagingService";
 
     /**
+     * The default bitmask value passed to the callback of {@link #onReceiveTextSms} with all
+     * {@code RECEIVE_OPTIONS_x} flags cleared to indicate that the message should be kept and a
+     * new message notification should be shown.
+     *
+     * @see #RECEIVE_OPTIONS_DROP
+     * @see #RECEIVE_OPTIONS_SKIP_NOTIFY_WHEN_CREDENTIAL_ENCRYPTED_STORAGE_UNAVAILABLE
+     */
+    public static final int RECEIVE_OPTIONS_DEFAULT = 0;
+
+    /**
+     * Used to set the flag in the bitmask passed to the callback of {@link #onReceiveTextSms} to
+     * indicate that the inbound SMS should be dropped.
+     */
+    public static final int RECEIVE_OPTIONS_DROP = 0x1;
+
+    /**
+     * Used to set the flag in the bitmask passed to the callback of {@link #onReceiveTextSms} to
+     * indicate that a new message notification should not be shown to the user when the
+     * credential-encrypted storage of the device is not available before the user unlocks the
+     * phone. It is only applicable to devices that support file-based encryption.
+     */
+    public static final int RECEIVE_OPTIONS_SKIP_NOTIFY_WHEN_CREDENTIAL_ENCRYPTED_STORAGE_UNAVAILABLE = 0x2;
+
+    /**
      * Indicates that an SMS or MMS message was successfully sent.
      */
     public static final int SEND_STATUS_OK = 0;
@@ -96,7 +120,9 @@
      * @param subId SMS subscription ID of the SIM
      * @param callback result callback. Call with {@code true} to keep an inbound SMS message and
      *        deliver to SMS apps, and {@code false} to drop the message.
+     * @deprecated Use {@link #onReceiveTextSms} instead.
      */
+    @Deprecated
     public void onFilterSms(@NonNull MessagePdu pdu, @NonNull String format, int destPort,
             int subId, @NonNull ResultCallback<Boolean> callback) {
         // optional
@@ -107,6 +133,36 @@
     }
 
     /**
+     * Override this method to filter inbound SMS messages.
+     *
+     * <p>This method will be called once for every incoming text SMS. You can invoke the callback
+     * with a bitmask to tell the platform how to handle the SMS. For a SMS received on a
+     * file-based encryption capable device while the credential-encrypted storage is not available,
+     * this method will be called for the second time when the credential-encrypted storage becomes
+     * available after the user unlocks the phone, if the bit {@link #RECEIVE_OPTIONS_DROP} is not
+     * set when invoking the callback.
+     *
+     * @param pdu the PDUs of the message
+     * @param format the format of the PDUs, typically "3gpp" or "3gpp2"
+     * @param destPort the destination port of a binary SMS, this will be -1 for text SMS
+     * @param subId SMS subscription ID of the SIM
+     * @param callback result callback. Call with a bitmask integer to indicate how the incoming
+     *        text SMS should be handled by the platform. Use {@link #RECEIVE_OPTIONS_DROP} and
+     *        {@link #RECEIVE_OPTIONS_SKIP_NOTIFY_WHEN_CREDENTIAL_ENCRYPTED_STORAGE_UNAVAILABLE}
+     *        to set the flags in the bitmask.
+     */
+    public void onReceiveTextSms(@NonNull MessagePdu pdu, @NonNull String format,
+            int destPort, int subId, @NonNull final ResultCallback<Integer> callback) {
+        onFilterSms(pdu, format, destPort, subId, new ResultCallback<Boolean>() {
+            @Override
+            public void onReceiveResult(Boolean result) throws RemoteException {
+                callback.onReceiveResult(result ? RECEIVE_OPTIONS_DEFAULT : RECEIVE_OPTIONS_DROP
+                    | RECEIVE_OPTIONS_SKIP_NOTIFY_WHEN_CREDENTIAL_ENCRYPTED_STORAGE_UNAVAILABLE);
+            }
+        });
+    }
+
+    /**
      * Override this method to intercept text SMSs sent from the device.
      * @deprecated Override {@link #onSendTextSms} below instead.
      *
@@ -408,10 +464,11 @@
         @Override
         public void filterSms(MessagePdu pdu, String format, int destPort,
                               int subId, final ICarrierMessagingCallback callback) {
-            onFilterSms(pdu, format, destPort, subId, new ResultCallback<Boolean>() {
+            onReceiveTextSms(pdu, format, destPort, subId,
+                new ResultCallback<Integer>() {
                     @Override
-                    public void onReceiveResult(final Boolean result) throws RemoteException {
-                        callback.onFilterComplete(result);
+                    public void onReceiveResult(Integer options) throws RemoteException {
+                        callback.onFilterComplete(options);
                     }
                 });
         }
diff --git a/core/java/android/service/carrier/ICarrierMessagingCallback.aidl b/core/java/android/service/carrier/ICarrierMessagingCallback.aidl
index 6118a20..2753669 100644
--- a/core/java/android/service/carrier/ICarrierMessagingCallback.aidl
+++ b/core/java/android/service/carrier/ICarrierMessagingCallback.aidl
@@ -22,7 +22,7 @@
  * @hide
  */
 oneway interface ICarrierMessagingCallback {
-    void onFilterComplete(boolean keepMessage);
+    void onFilterComplete(int result);
     void onSendSmsComplete(int result, int messageRef);
     void onSendMultipartSmsComplete(int result, in int[] messageRefs);
     void onSendMmsComplete(int result, in byte[] sendConfPdu);
diff --git a/core/java/android/service/notification/Condition.java b/core/java/android/service/notification/Condition.java
index 11737c6..0163b47 100644
--- a/core/java/android/service/notification/Condition.java
+++ b/core/java/android/service/notification/Condition.java
@@ -16,32 +16,56 @@
 
 package android.service.notification;
 
+import android.annotation.IntDef;
 import android.annotation.SystemApi;
+import android.app.AutomaticZenRule;
 import android.content.Context;
 import android.net.Uri;
 import android.os.Parcel;
 import android.os.Parcelable;
 
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 import java.util.Objects;
 
 /**
- * Condition information from condition providers. Used to tell the system to enter Do Not Disturb
- * mode and request that the system exit Do Not Disturb mode.
+ * The current condition of an {@link android.app.AutomaticZenRule}, provided by the
+ * {@link ConditionProviderService} that owns the rule. Used to tell the system to enter Do Not
+ * Disturb mode and request that the system exit Do Not Disturb mode.
  */
 public class Condition implements Parcelable {
 
+    @SystemApi
     public static final String SCHEME = "condition";
 
+    /** @hide */
+    @IntDef({STATE_FALSE, STATE_TRUE, STATE_TRUE, STATE_ERROR})
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface State {}
+
+    /**
+     * Indicates that Do Not Disturb should be turned off. Note that all Conditions from all
+     * {@link ConditionProviderService} providers must be off for Do Not Disturb to be turned off on
+     * the device.
+     */
     public static final int STATE_FALSE = 0;
+    /**
+     * Indicates that Do Not Disturb should be turned on.
+     */
     public static final int STATE_TRUE = 1;
+
+    @SystemApi
     public static final int STATE_UNKNOWN = 2;
+    @SystemApi
     public static final int STATE_ERROR = 3;
 
+    @SystemApi
     public static final int FLAG_RELEVANT_NOW = 1 << 0;
+    @SystemApi
     public static final int FLAG_RELEVANT_ALWAYS = 1 << 1;
 
     /**
-     * The URI representing the condition being updated.
+     * The URI representing the rule being updated.
      * See {@link android.app.AutomaticZenRule#getConditionId()}.
      */
     public final Uri id;
@@ -52,23 +76,17 @@
      */
     public final String summary;
 
-    /**
-     * Additional information about what the rule encoded in {@link #id} means when it is enabled.
-     * User visible if the state of the condition is {@link #STATE_TRUE}.
-     */
+    @SystemApi
     public final String line1;
-
-    /**
-     * Additional information about what the rule encoded in {@link #id} means when it is enabled.
-     * User visible if the state of the condition is {@link #STATE_TRUE}.
-     */
+    @SystemApi
     public final String line2;
 
     /**
-     * The state of this condition. {@link #STATE_TRUE} will enable Do Not Disturb mode. Any other
-     * state will turn Do Not Disturb off for this rule. Note that Do Not Disturb might still be
-     * enabled globally if other conditions are in a {@link #STATE_TRUE} state.
+     * The state of this condition. {@link #STATE_TRUE} will enable Do Not Disturb mode.
+     * {@link #STATE_FALSE} will turn Do Not Disturb off for this rule. Note that Do Not Disturb
+     * might still be enabled globally if other conditions are in a {@link #STATE_TRUE} state.
      */
+    @State
     public final int state;
 
     @SystemApi
@@ -76,8 +94,13 @@
     @SystemApi
     public final int icon;
 
-    public Condition(Uri id, String summary, String line1, String line2, int state) {
-        this(id, summary, line1, line2, -1, state, FLAG_RELEVANT_ALWAYS);
+    /**
+     * An object representing the current state of a {@link android.app.AutomaticZenRule}.
+     * @param id the {@link android.app.AutomaticZenRule#getConditionId()} of the zen rule
+     * @param summary a user visible description of the rule state.
+     */
+    public Condition(Uri id, String summary, int state) {
+        this(id, summary, "", "", -1, state, FLAG_RELEVANT_ALWAYS);
     }
 
     @SystemApi
@@ -85,8 +108,6 @@
             int state, int flags) {
         if (id == null) throw new IllegalArgumentException("id is required");
         if (summary == null) throw new IllegalArgumentException("summary is required");
-        if (line1 == null) throw new IllegalArgumentException("line1 is required");
-        if (line2 == null) throw new IllegalArgumentException("line2 is required");
         if (!isValidState(state)) throw new IllegalArgumentException("state is invalid: " + state);
         this.id = id;
         this.summary = summary;
@@ -97,7 +118,7 @@
         this.flags = flags;
     }
 
-    private Condition(Parcel source) {
+    public Condition(Parcel source) {
         this((Uri)source.readParcelable(Condition.class.getClassLoader()),
                 source.readString(),
                 source.readString(),
@@ -135,6 +156,7 @@
             .append(']').toString();
     }
 
+    @SystemApi
     public static String stateToString(int state) {
         if (state == STATE_FALSE) return "STATE_FALSE";
         if (state == STATE_TRUE) return "STATE_TRUE";
@@ -143,6 +165,7 @@
         throw new IllegalArgumentException("state is invalid: " + state);
     }
 
+    @SystemApi
     public static String relevanceToString(int flags) {
         final boolean now = (flags & FLAG_RELEVANT_NOW) != 0;
         final boolean always = (flags & FLAG_RELEVANT_ALWAYS) != 0;
@@ -175,6 +198,7 @@
         return 0;
     }
 
+    @SystemApi
     public Condition copy() {
         final Parcel parcel = Parcel.obtain();
         try {
@@ -186,10 +210,14 @@
         }
     }
 
+    @SystemApi
     public static Uri.Builder newId(Context context) {
-        return new Uri.Builder().scheme(SCHEME).authority(context.getPackageName());
+        return new Uri.Builder()
+                .scheme(Condition.SCHEME)
+                .authority(context.getPackageName());
     }
 
+    @SystemApi
     public static boolean isValidId(Uri id, String pkg) {
         return id != null && SCHEME.equals(id.getScheme()) && pkg.equals(id.getAuthority());
     }
diff --git a/core/java/android/service/notification/ConditionProviderService.java b/core/java/android/service/notification/ConditionProviderService.java
index adcc9d6..44c3887 100644
--- a/core/java/android/service/notification/ConditionProviderService.java
+++ b/core/java/android/service/notification/ConditionProviderService.java
@@ -102,9 +102,6 @@
      */
     abstract public void onConnected();
 
-    /**
-     * @removed
-     */
     @SystemApi
     public void onRequestConditions(int relevance) {}
 
diff --git a/core/java/android/service/notification/INotificationListener.aidl b/core/java/android/service/notification/INotificationListener.aidl
index a0de17f..8c35901 100644
--- a/core/java/android/service/notification/INotificationListener.aidl
+++ b/core/java/android/service/notification/INotificationListener.aidl
@@ -23,7 +23,7 @@
 /** @hide */
 oneway interface INotificationListener
 {
-    // listeners and assistants
+    // listeners and rankers
     void onListenerConnected(in NotificationRankingUpdate update);
     void onNotificationPosted(in IStatusBarNotificationHolder notificationHolder,
             in NotificationRankingUpdate update);
@@ -33,7 +33,7 @@
     void onListenerHintsChanged(int hints);
     void onInterruptionFilterChanged(int interruptionFilter);
 
-    // assistants only
+    // rankers only
     void onNotificationEnqueued(in IStatusBarNotificationHolder notificationHolder, int importance, boolean user);
     void onNotificationVisibilityChanged(String key, long time, boolean visible);
     void onNotificationClick(String key, long time);
diff --git a/core/java/android/service/notification/NotificationAssistantService.java b/core/java/android/service/notification/NotificationAssistantService.java
deleted file mode 100644
index b5387f1..0000000
--- a/core/java/android/service/notification/NotificationAssistantService.java
+++ /dev/null
@@ -1,275 +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.service.notification;
-
-import android.annotation.SdkConstant;
-import android.annotation.SystemApi;
-import android.app.INotificationManager;
-import android.app.Notification;
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.Intent;
-import android.net.Uri;
-import android.os.IBinder;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.os.RemoteException;
-import android.os.ServiceManager;
-import android.util.Log;
-
-/**
- * A service that helps the user manage notifications by modifying the
- * relative importance of notifications.
- * <p>To extend this class, you must declare the service in your manifest file with
- * the {@link android.Manifest.permission#BIND_NOTIFICATION_ASSISTANT_SERVICE} permission
- * and include an intent filter with the {@link #SERVICE_INTERFACE} action. For example:</p>
- * <pre>
- * &lt;service android:name=".NotificationAssistant"
- *          android:label="&#64;string/service_name"
- *          android:permission="android.permission.BIND_NOTIFICATION_ASSISTANT_SERVICE">
- *     &lt;intent-filter>
- *         &lt;action android:name="android.service.notification.NotificationAssistantService" />
- *     &lt;/intent-filter>
- * &lt;/service></pre>
- * @hide
- */
-@SystemApi
-public abstract class NotificationAssistantService extends NotificationListenerService {
-    private static final String TAG = "NotificationAssistant";
-
-    /**
-     * The {@link Intent} that must be declared as handled by the service.
-     */
-    @SdkConstant(SdkConstant.SdkConstantType.SERVICE_ACTION)
-    public static final String SERVICE_INTERFACE
-            = "android.service.notification.NotificationAssistantService";
-
-    /** Notification was canceled by the status bar reporting a 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;
-
-    /** Notification was canceled by the status bar reporting a user dismiss all. */
-    public static final int REASON_DELEGATE_CANCEL_ALL = 3;
-
-    /** Notification was canceled by the status bar reporting an inflation error. */
-    public static final int REASON_DELEGATE_ERROR = 4;
-
-    /** Notification was canceled by the package manager modifying the package. */
-    public static final int REASON_PACKAGE_CHANGED = 5;
-
-    /** Notification was canceled by the owning user context being stopped. */
-    public static final int REASON_USER_STOPPED = 6;
-
-    /** Notification was canceled by the user banning the package. */
-    public static final int REASON_PACKAGE_BANNED = 7;
-
-    /** Notification was canceled by the app canceling this specific notification. */
-    public static final int REASON_APP_CANCEL = 8;
-
-    /** Notification was canceled by the app cancelling all its notifications. */
-    public static final int REASON_APP_CANCEL_ALL = 9;
-
-    /** Notification was canceled by a listener reporting a user dismissal. */
-    public static final int REASON_LISTENER_CANCEL = 10;
-
-    /** Notification was canceled by a listener reporting a user dismiss all. */
-    public static final int REASON_LISTENER_CANCEL_ALL = 11;
-
-    /** Notification was canceled because it was a member of a canceled group. */
-    public static final int REASON_GROUP_SUMMARY_CANCELED = 12;
-
-    /** Notification was canceled because it was an invisible member of a group. */
-    public static final int REASON_GROUP_OPTIMIZATION = 13;
-
-    /** Notification was canceled by the device administrator suspending the package. */
-    public static final int REASON_PACKAGE_SUSPENDED = 14;
-
-    /** Notification was canceled by the owning managed profile being turned off. */
-    public static final int REASON_PROFILE_TURNED_OFF = 15;
-
-    public class Adjustment {
-        int mImportance;
-        CharSequence mExplanation;
-        Uri mReference;
-
-        /**
-         * Create a notification importance adjustment.
-         *
-         * @param importance The final importance of the notification.
-         * @param explanation A human-readable justification for the adjustment.
-         * @param reference A reference to an external object that augments the
-         *                  explanation, such as a
-         *                  {@link android.provider.ContactsContract.Contacts#CONTENT_LOOKUP_URI},
-         *                  or null.
-         */
-        public Adjustment(int importance, CharSequence explanation, Uri reference) {
-            mImportance = importance;
-            mExplanation = explanation;
-            mReference = reference;
-        }
-    }
-
-    @Override
-    public IBinder onBind(Intent intent) {
-        if (mWrapper == null) {
-            mWrapper = new NotificationAssistantWrapper();
-        }
-        return mWrapper;
-    }
-
-    /**
-     * A notification was posted by an app. Called before alert.
-     *
-     * @param sbn the new notification
-     * @param importance the initial importance of the notification.
-     * @param user true if the initial importance reflects an explicit user preference.
-     * @return an adjustment or null to take no action, within 100ms.
-     */
-    abstract public Adjustment onNotificationEnqueued(StatusBarNotification sbn,
-          int importance, boolean user);
-
-    /**
-     * The visibility of a notification has changed.
-     *
-     * @param key the notification key
-     * @param time milliseconds since midnight, January 1, 1970 UTC.
-     * @param visible true if the notification became visible, false if hidden.
-     */
-    public void onNotificationVisibilityChanged(String key, long time, boolean visible)
-    {
-        // Do nothing, Override this to collect visibility statistics.
-    }
-
-    /**
-     * The user clicked on a notification.
-     *
-     * @param key the notification key
-     * @param time milliseconds since midnight, January 1, 1970 UTC.
-     */
-    public void onNotificationClick(String key, long time)
-    {
-        // Do nothing, Override this to collect click statistics
-    }
-
-    /**
-     * The user clicked on a notification action.
-     *
-     * @param key the notification key
-     * @param time milliseconds since midnight, January 1, 1970 UTC.
-     * @param actionIndex the index of the action button that was pressed.
-     */
-    public void onNotificationActionClick(String key, long time, int actionIndex)
-    {
-        // Do nothing, Override this to collect action button click statistics
-    }
-
-    /**
-     * A notification was removed.
-
-     * @param key the notification key
-     * @param time milliseconds since midnight, January 1, 1970 UTC.
-     * @param reason see {@link #REASON_LISTENER_CANCEL}, etc.
-     */
-    public void onNotificationRemoved(String key, long time, int reason) {
-        // Do nothing, Override this to collect dismissal statistics
-    }
-
-    /**
-     * Change the importance of an existing notification.  N.B. this won’t cause
-     * an existing notification to alert, but might allow a future update to
-     * this notification to alert.
-     *
-     * @param key the notification key
-     * @param adjustment the new importance with an explanation
-     */
-    public final void adjustImportance(String key, Adjustment adjustment)
-    {
-        if (!isBound()) return;
-        try {
-            getNotificationInterface().setImportanceFromAssistant(mWrapper, key,
-                    adjustment.mImportance, adjustment.mExplanation);
-        } catch (android.os.RemoteException ex) {
-            Log.v(TAG, "Unable to contact notification manager", ex);
-        }
-    }
-
-    private class NotificationAssistantWrapper extends NotificationListenerWrapper {
-        @Override
-        public void onNotificationEnqueued(IStatusBarNotificationHolder sbnHolder,
-                                           int importance, boolean user) throws RemoteException {
-            StatusBarNotification sbn;
-            try {
-                sbn = sbnHolder.get();
-            } catch (RemoteException e) {
-                Log.w(TAG, "onNotificationEnqueued: Error receiving StatusBarNotification", e);
-                return;
-            }
-
-            try {
-                Adjustment adjustment =
-                    NotificationAssistantService.this.onNotificationEnqueued(sbn, importance, user);
-                if (adjustment != null) {
-                    adjustImportance(sbn.getKey(), adjustment);
-                }
-            } catch (Throwable t) {
-                Log.w(TAG, "Error running onNotificationEnqueued", t);
-            }
-        }
-
-        @Override
-        public void onNotificationVisibilityChanged(String key, long time, boolean visible)
-                throws RemoteException {
-            try {
-                NotificationAssistantService.this.onNotificationVisibilityChanged(key, time,
-                        visible);
-            } catch (Throwable t) {
-                Log.w(TAG, "Error running onNotificationVisibilityChanged", t);
-            }
-        }
-
-        @Override
-        public void onNotificationClick(String key, long time) throws RemoteException {
-            try {
-                NotificationAssistantService.this.onNotificationClick(key, time);
-            } catch (Throwable t) {
-                Log.w(TAG, "Error running onNotificationClick", t);
-            }
-        }
-
-        @Override
-        public void onNotificationActionClick(String key, long time, int actionIndex)
-                throws RemoteException {
-            try {
-                NotificationAssistantService.this.onNotificationActionClick(key, time, actionIndex);
-            } catch (Throwable t) {
-                Log.w(TAG, "Error running onNotificationActionClick", t);
-            }
-        }
-
-        @Override
-        public void onNotificationRemovedReason(String key, long time, int reason)
-                throws RemoteException {
-            try {
-                NotificationAssistantService.this.onNotificationRemoved(key, time, reason);
-            } catch (Throwable t) {
-                Log.w(TAG, "Error running onNotificationRemoved", t);
-            }
-        }
-    }
-}
diff --git a/core/java/android/service/notification/NotificationListenerService.java b/core/java/android/service/notification/NotificationListenerService.java
index 7b461b1..afdd1d4 100644
--- a/core/java/android/service/notification/NotificationListenerService.java
+++ b/core/java/android/service/notification/NotificationListenerService.java
@@ -15,8 +15,12 @@
  */
 
 package android.service.notification;
-import android.service.notification.IStatusBarNotificationHolder;
 
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
+
+import android.annotation.IntDef;
 import android.annotation.SystemApi;
 import android.annotation.SdkConstant;
 import android.app.INotificationManager;
@@ -42,7 +46,11 @@
 import android.util.ArrayMap;
 import android.util.ArraySet;
 import android.util.Log;
-
+import android.widget.RemoteViews;
+import com.android.internal.annotations.GuardedBy;
+import com.android.internal.os.SomeArgs;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
@@ -61,16 +69,6 @@
  *         &lt;action android:name="android.service.notification.NotificationListenerService" />
  *     &lt;/intent-filter>
  * &lt;/service></pre>
- * <p> Typically, while enabled in user settings, this service will be bound on boot or when a
- * settings change occurs that could affect whether this service should run.  However, for some
- * system usage modes, the you may instead specify that this service is instead bound and unbound
- * in response to mode changes by including a category in the intent filter.  Currently
- * supported categories are:
- * <ul>
- *   <li>{@link #CATEGORY_VR_NOTIFICATIONS} - this service is bound when an Activity has enabled
- *   VR mode. {@see android.app.Activity#setVrMode(boolean)}.</li>
- * </ul>
- * </p>
  */
 public abstract class NotificationListenerService extends Service {
     // TAG = "NotificationListenerService[MySubclass]"
@@ -160,19 +158,30 @@
     @SystemApi
     public static final int TRIM_LIGHT = 1;
 
+    private final Object mLock = new Object();
+
+    private Handler mHandler;
+
     /** @hide */
     protected NotificationListenerWrapper mWrapper = null;
+
+    @GuardedBy("mLock")
     private RankingMap mRankingMap;
 
     private INotificationManager mNoMan;
 
-    /** Only valid after a successful call to (@link registerAsService}. */
-    private int mCurrentUser;
+    /**
+     * Only valid after a successful call to (@link registerAsService}.
+     * @hide
+     */
+    protected int mCurrentUser;
 
-
-    // This context is required for system services since NotificationListenerService isn't
-    // started as a real Service and hence no context is available.
-    private Context mSystemContext;
+    /**
+     * This context is required for system services since NotificationListenerService isn't
+     * started as a real Service and hence no context is available..
+     * @hide
+     */
+    protected Context mSystemContext;
 
     /**
      * The {@link Intent} that must be declared as handled by the service.
@@ -181,16 +190,11 @@
     public static final String SERVICE_INTERFACE
             = "android.service.notification.NotificationListenerService";
 
-    /**
-     * If this category is declared in the application manifest for a service of this type, this
-     * service will be bound when VR mode is enabled, and unbound when VR mode is disabled rather
-     * than the normal lifecycle for a notification service.
-     *
-     * {@see android.app.Activity#setVrMode(boolean)}
-     */
-    @SdkConstant(SdkConstant.SdkConstantType.INTENT_CATEGORY)
-    public static final String CATEGORY_VR_NOTIFICATIONS =
-        "android.intent.category.vr.notifications";
+    @Override
+    protected void attachBaseContext(Context base) {
+        super.attachBaseContext(base);
+        mHandler = new MyHandler(getMainLooper());
+    }
 
     /**
      * Implement this method to learn about new notifications as they are posted by apps.
@@ -639,7 +643,9 @@
      * @return A {@link RankingMap} object providing access to ranking information
      */
     public RankingMap getCurrentRanking() {
-        return mRankingMap;
+        synchronized (mLock) {
+            return mRankingMap;
+        }
     }
 
     @Override
@@ -674,13 +680,14 @@
     @SystemApi
     public void registerAsSystemService(Context context, ComponentName componentName,
             int currentUser) throws RemoteException {
-        mSystemContext = context;
         if (mWrapper == null) {
             mWrapper = new NotificationListenerWrapper();
         }
+        mSystemContext = context;
         INotificationManager noMan = getNotificationInterface();
         noMan.registerListener(mWrapper, componentName, currentUser);
         mCurrentUser = currentUser;
+        mHandler = new MyHandler(context.getMainLooper());
     }
 
     /**
@@ -707,7 +714,7 @@
      * <P>The service should wait for the {@link #onListenerConnected()} event
      * before performing any operations.
      */
-    public static final void requestRebind(ComponentName componentName)
+    public static void requestRebind(ComponentName componentName)
             throws RemoteException {
         INotificationManager noMan = INotificationManager.Stub.asInterface(
                 ServiceManager.getService(Context.NOTIFICATION_SERVICE));
@@ -752,9 +759,16 @@
     private void maybePopulateRemoteViews(Notification notification) {
         if (getContext().getApplicationInfo().targetSdkVersion < Build.VERSION_CODES.N) {
             Builder builder = Builder.recoverBuilder(getContext(), notification);
-            notification.contentView = builder.makeContentView();
-            notification.bigContentView = builder.makeBigContentView();
-            notification.headsUpContentView = builder.makeHeadsUpContentView();
+
+            // Some styles wrap Notification's contentView, bigContentView and headsUpContentView.
+            // First inflate them all, only then set them to avoid recursive wrapping.
+            RemoteViews content = builder.createContentView();
+            RemoteViews big = builder.createBigContentView();
+            RemoteViews headsUp = builder.createHeadsUpContentView();
+
+            notification.contentView = content;
+            notification.bigContentView = big;
+            notification.headsUpContentView = headsUp;
         }
     }
 
@@ -772,7 +786,6 @@
             }
 
             try {
-                Notification notification = sbn.getNotification();
                 // convert icon metadata to legacy format for older clients
                 createLegacyIconExtras(sbn.getNotification());
                 maybePopulateRemoteViews(sbn.getNotification());
@@ -784,20 +797,23 @@
             }
 
             // protect subclass from concurrent modifications of (@link mNotificationKeys}.
-            synchronized (mWrapper) {
-                applyUpdate(update);
-                try {
-                    if (sbn != null) {
-                        NotificationListenerService.this.onNotificationPosted(sbn, mRankingMap);
-                    } else {
-                        // still pass along the ranking map, it may contain other information
-                        NotificationListenerService.this.onNotificationRankingUpdate(mRankingMap);
-                    }
-                } catch (Throwable t) {
-                    Log.w(TAG, "Error running onNotificationPosted", t);
+            synchronized (mLock) {
+                applyUpdateLocked(update);
+                if (sbn != null) {
+                    SomeArgs args = SomeArgs.obtain();
+                    args.arg1 = sbn;
+                    args.arg2 = mRankingMap;
+                    mHandler.obtainMessage(MyHandler.MSG_ON_NOTIFICATION_POSTED,
+                            args).sendToTarget();
+                } else {
+                    // still pass along the ranking map, it may contain other information
+                    mHandler.obtainMessage(MyHandler.MSG_ON_NOTIFICATION_RANKING_UPDATE,
+                            mRankingMap).sendToTarget();
                 }
             }
+
         }
+
         @Override
         public void onNotificationRemoved(IStatusBarNotificationHolder sbnHolder,
                 NotificationRankingUpdate update) {
@@ -809,56 +825,48 @@
                 return;
             }
             // protect subclass from concurrent modifications of (@link mNotificationKeys}.
-            synchronized (mWrapper) {
-                applyUpdate(update);
-                try {
-                    NotificationListenerService.this.onNotificationRemoved(sbn, mRankingMap);
-                } catch (Throwable t) {
-                    Log.w(TAG, "Error running onNotificationRemoved", t);
-                }
+            synchronized (mLock) {
+                applyUpdateLocked(update);
+                SomeArgs args = SomeArgs.obtain();
+                args.arg1 = sbn;
+                args.arg2 = mRankingMap;
+                mHandler.obtainMessage(MyHandler.MSG_ON_NOTIFICATION_REMOVED,
+                        args).sendToTarget();
             }
+
         }
+
         @Override
         public void onListenerConnected(NotificationRankingUpdate update) {
             // protect subclass from concurrent modifications of (@link mNotificationKeys}.
-            synchronized (mWrapper) {
-                applyUpdate(update);
-                try {
-                    NotificationListenerService.this.onListenerConnected();
-                } catch (Throwable t) {
-                    Log.w(TAG, "Error running onListenerConnected", t);
-                }
+            synchronized (mLock) {
+                applyUpdateLocked(update);
             }
+            mHandler.obtainMessage(MyHandler.MSG_ON_LISTENER_CONNECTED).sendToTarget();
         }
+
         @Override
         public void onNotificationRankingUpdate(NotificationRankingUpdate update)
                 throws RemoteException {
             // protect subclass from concurrent modifications of (@link mNotificationKeys}.
-            synchronized (mWrapper) {
-                applyUpdate(update);
-                try {
-                    NotificationListenerService.this.onNotificationRankingUpdate(mRankingMap);
-                } catch (Throwable t) {
-                    Log.w(TAG, "Error running onNotificationRankingUpdate", t);
-                }
+            synchronized (mLock) {
+                applyUpdateLocked(update);
+                mHandler.obtainMessage(MyHandler.MSG_ON_NOTIFICATION_RANKING_UPDATE,
+                        mRankingMap).sendToTarget();
             }
+
         }
+
         @Override
         public void onListenerHintsChanged(int hints) throws RemoteException {
-            try {
-                NotificationListenerService.this.onListenerHintsChanged(hints);
-            } catch (Throwable t) {
-                Log.w(TAG, "Error running onListenerHintsChanged", t);
-            }
+            mHandler.obtainMessage(MyHandler.MSG_ON_LISTENER_HINTS_CHANGED,
+                    hints, 0).sendToTarget();
         }
 
         @Override
         public void onInterruptionFilterChanged(int interruptionFilter) throws RemoteException {
-            try {
-                NotificationListenerService.this.onInterruptionFilterChanged(interruptionFilter);
-            } catch (Throwable t) {
-                Log.w(TAG, "Error running onInterruptionFilterChanged", t);
-            }
+            mHandler.obtainMessage(MyHandler.MSG_ON_INTERRUPTION_FILTER_CHANGED,
+                    interruptionFilter, 0).sendToTarget();
         }
 
         @Override
@@ -891,11 +899,12 @@
         }
     }
 
-    private void applyUpdate(NotificationRankingUpdate update) {
+    private void applyUpdateLocked(NotificationRankingUpdate update) {
         mRankingMap = new RankingMap(update);
     }
 
-    private Context getContext() {
+    /** @hide */
+    protected Context getContext() {
         if (mSystemContext != null) {
             return mSystemContext;
         }
@@ -911,6 +920,14 @@
      * current {@link RankingMap}.
      */
     public static class Ranking {
+
+        /** @hide */
+        @IntDef({VISIBILITY_NO_OVERRIDE, IMPORTANCE_UNSPECIFIED, IMPORTANCE_NONE,
+                IMPORTANCE_MIN, IMPORTANCE_LOW, IMPORTANCE_DEFAULT, IMPORTANCE_HIGH,
+                IMPORTANCE_MAX})
+        @Retention(RetentionPolicy.SOURCE)
+        public @interface Importance {}
+
         /** Value signifying that the user has not expressed a per-app visibility override value.
          * @hide */
         public static final int VISIBILITY_NO_OVERRIDE = -1000;
@@ -929,26 +946,31 @@
         public static final int IMPORTANCE_NONE = 0;
 
         /**
-         * Low notification importance: only shows in the shade, below the fold.
+         * Min notification importance: only shows in the shade, below the fold.
          */
-        public static final int IMPORTANCE_LOW = 1;
+        public static final int IMPORTANCE_MIN = 1;
 
         /**
-         * Default notification importance: shows everywhere, but is not intrusive.
+         * Low notification importance: shows everywhere, but is not intrusive.
          */
-        public static final int IMPORTANCE_DEFAULT = 2;
+        public static final int IMPORTANCE_LOW = 2;
 
         /**
-         * Higher notification importance: shows everywhere, makes noise,
+         * Default notification importance: shows everywhere, allowed to makes noise,
          * but does not visually intrude.
          */
-        public static final int IMPORTANCE_HIGH = 3;
+        public static final int IMPORTANCE_DEFAULT = 3;
 
         /**
-         * Highest notification importance: shows everywhere, makes noise,
-         * and also visually intrudes.
+         * Higher notification importance: shows everywhere, allowed to makes noise and peek.
          */
-        public static final int IMPORTANCE_MAX = 4;
+        public static final int IMPORTANCE_HIGH = 4;
+
+        /**
+         * Highest notification importance: shows everywhere, allowed to makes noise, peek, and
+         * use full screen intents.
+         */
+        public static final int IMPORTANCE_MAX = 5;
 
         private String mKey;
         private int mRank = -1;
@@ -956,7 +978,7 @@
         private boolean mMatchesInterruptionFilter;
         private int mVisibilityOverride;
         private int mSuppressedVisualEffects;
-        private int mImportance;
+        private @Importance int mImportance;
         private CharSequence mImportanceExplanation;
 
         public Ranking() {}
@@ -1022,7 +1044,7 @@
          *
          * @return the rank of the notification
          */
-        public int getImportance() {
+        public @Importance int getImportance() {
             return mImportance;
         }
 
@@ -1041,7 +1063,7 @@
                 CharSequence explanation) {
             mKey = key;
             mRank = rank;
-            mIsAmbient = importance < IMPORTANCE_DEFAULT;
+            mIsAmbient = importance < IMPORTANCE_LOW;
             mMatchesInterruptionFilter = matchesInterruptionFilter;
             mVisibilityOverride = visibilityOverride;
             mSuppressedVisualEffects = suppressedVisualEffects;
@@ -1058,6 +1080,8 @@
                     return "UNSPECIFIED";
                 case IMPORTANCE_NONE:
                     return "NONE";
+                case IMPORTANCE_MIN:
+                    return "MIN";
                 case IMPORTANCE_LOW:
                     return "LOW";
                 case IMPORTANCE_DEFAULT:
@@ -1264,4 +1288,57 @@
             }
         };
     }
+
+    private final class MyHandler extends Handler {
+        public static final int MSG_ON_NOTIFICATION_POSTED = 1;
+        public static final int MSG_ON_NOTIFICATION_REMOVED = 2;
+        public static final int MSG_ON_LISTENER_CONNECTED = 3;
+        public static final int MSG_ON_NOTIFICATION_RANKING_UPDATE = 4;
+        public static final int MSG_ON_LISTENER_HINTS_CHANGED = 5;
+        public static final int MSG_ON_INTERRUPTION_FILTER_CHANGED = 6;
+
+        public MyHandler(Looper looper) {
+            super(looper, null, false);
+        }
+
+        @Override
+        public void handleMessage(Message msg) {
+            switch (msg.what) {
+                case MSG_ON_NOTIFICATION_POSTED: {
+                    SomeArgs args = (SomeArgs) msg.obj;
+                    StatusBarNotification sbn = (StatusBarNotification) args.arg1;
+                    RankingMap rankingMap = (RankingMap) args.arg2;
+                    args.recycle();
+                    onNotificationPosted(sbn, rankingMap);
+                } break;
+
+                case MSG_ON_NOTIFICATION_REMOVED: {
+                    SomeArgs args = (SomeArgs) msg.obj;
+                    StatusBarNotification sbn = (StatusBarNotification) args.arg1;
+                    RankingMap rankingMap = (RankingMap) args.arg2;
+                    args.recycle();
+                    onNotificationRemoved(sbn, rankingMap);
+                } break;
+
+                case MSG_ON_LISTENER_CONNECTED: {
+                    onListenerConnected();
+                } break;
+
+                case MSG_ON_NOTIFICATION_RANKING_UPDATE: {
+                    RankingMap rankingMap = (RankingMap) msg.obj;
+                    onNotificationRankingUpdate(rankingMap);
+                } break;
+
+                case MSG_ON_LISTENER_HINTS_CHANGED: {
+                    final int hints = msg.arg1;
+                    onListenerHintsChanged(hints);
+                } break;
+
+                case MSG_ON_INTERRUPTION_FILTER_CHANGED: {
+                    final int interruptionFilter = msg.arg1;
+                    onInterruptionFilterChanged(interruptionFilter);
+                } break;
+            }
+        }
+    }
 }
diff --git a/core/java/android/service/notification/NotificationRankerService.java b/core/java/android/service/notification/NotificationRankerService.java
new file mode 100644
index 0000000..47fdac6
--- /dev/null
+++ b/core/java/android/service/notification/NotificationRankerService.java
@@ -0,0 +1,343 @@
+/*
+ * 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.service.notification;
+
+import android.annotation.SdkConstant;
+import android.annotation.SystemApi;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.net.Uri;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Looper;
+import android.os.Message;
+import android.os.RemoteException;
+import android.util.Log;
+import com.android.internal.os.SomeArgs;
+
+/**
+ * A service that helps the user manage notifications. This class is only used to
+ * extend the framework service and may not be implemented by non-framework components.
+ * @hide
+ */
+@SystemApi
+public abstract class NotificationRankerService extends NotificationListenerService {
+    private static final String TAG = "NotificationRankers";
+
+    /**
+     * The {@link Intent} that must be declared as handled by the service.
+     */
+    @SdkConstant(SdkConstant.SdkConstantType.SERVICE_ACTION)
+    public static final String SERVICE_INTERFACE
+            = "android.service.notification.NotificationRankerService";
+
+    /** Notification was canceled by the status bar reporting a 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;
+
+    /** Notification was canceled by the status bar reporting a user dismiss all. */
+    public static final int REASON_DELEGATE_CANCEL_ALL = 3;
+
+    /** Notification was canceled by the status bar reporting an inflation error. */
+    public static final int REASON_DELEGATE_ERROR = 4;
+
+    /** Notification was canceled by the package manager modifying the package. */
+    public static final int REASON_PACKAGE_CHANGED = 5;
+
+    /** Notification was canceled by the owning user context being stopped. */
+    public static final int REASON_USER_STOPPED = 6;
+
+    /** Notification was canceled by the user banning the package. */
+    public static final int REASON_PACKAGE_BANNED = 7;
+
+    /** Notification was canceled by the app canceling this specific notification. */
+    public static final int REASON_APP_CANCEL = 8;
+
+    /** Notification was canceled by the app cancelling all its notifications. */
+    public static final int REASON_APP_CANCEL_ALL = 9;
+
+    /** Notification was canceled by a listener reporting a user dismissal. */
+    public static final int REASON_LISTENER_CANCEL = 10;
+
+    /** Notification was canceled by a listener reporting a user dismiss all. */
+    public static final int REASON_LISTENER_CANCEL_ALL = 11;
+
+    /** Notification was canceled because it was a member of a canceled group. */
+    public static final int REASON_GROUP_SUMMARY_CANCELED = 12;
+
+    /** Notification was canceled because it was an invisible member of a group. */
+    public static final int REASON_GROUP_OPTIMIZATION = 13;
+
+    /** Notification was canceled by the device administrator suspending the package. */
+    public static final int REASON_PACKAGE_SUSPENDED = 14;
+
+    /** Notification was canceled by the owning managed profile being turned off. */
+    public static final int REASON_PROFILE_TURNED_OFF = 15;
+
+    public class Adjustment {
+        int mImportance;
+        CharSequence mExplanation;
+        Uri mReference;
+
+        /**
+         * Create a notification importance adjustment.
+         *
+         * @param importance The final importance of the notification.
+         * @param explanation A human-readable justification for the adjustment.
+         * @param reference A reference to an external object that augments the
+         *                  explanation, such as a
+         *                  {@link android.provider.ContactsContract.Contacts#CONTENT_LOOKUP_URI},
+         *                  or null.
+         */
+        public Adjustment(int importance, CharSequence explanation, Uri reference) {
+            mImportance = importance;
+            mExplanation = explanation;
+            mReference = reference;
+        }
+    }
+
+    private Handler mHandler;
+
+    /** @hide */
+    @Override
+    public void registerAsSystemService(Context context, ComponentName componentName,
+            int currentUser)  {
+        throw new UnsupportedOperationException("the ranker lifecycle is managed by the system.");
+    }
+
+    /** @hide */
+    @Override
+    public void unregisterAsSystemService()  {
+        throw new UnsupportedOperationException("the ranker lifecycle is managed by the system.");
+    }
+
+    @Override
+    protected void attachBaseContext(Context base) {
+        super.attachBaseContext(base);
+        mHandler = new MyHandler(getContext().getMainLooper());
+    }
+
+    @Override
+    public final IBinder onBind(Intent intent) {
+        if (mWrapper == null) {
+            mWrapper = new NotificationRankingServiceWrapper();
+        }
+        return mWrapper;
+    }
+
+    /**
+     * A notification was posted by an app. Called before alert.
+     *
+     * @param sbn the new notification
+     * @param importance the initial importance of the notification.
+     * @param user true if the initial importance reflects an explicit user preference.
+     * @return an adjustment or null to take no action, within 100ms.
+     */
+    abstract public Adjustment onNotificationEnqueued(StatusBarNotification sbn,
+          int importance, boolean user);
+
+    /**
+     * The visibility of a notification has changed.
+     *
+     * @param key the notification key
+     * @param time milliseconds since midnight, January 1, 1970 UTC.
+     * @param visible true if the notification became visible, false if hidden.
+     */
+    public void onNotificationVisibilityChanged(String key, long time, boolean visible)
+    {
+        // Do nothing, Override this to collect visibility statistics.
+    }
+
+    /**
+     * The user clicked on a notification.
+     *
+     * @param key the notification key
+     * @param time milliseconds since midnight, January 1, 1970 UTC.
+     */
+    public void onNotificationClick(String key, long time)
+    {
+        // Do nothing, Override this to collect click statistics
+    }
+
+    /**
+     * The user clicked on a notification action.
+     *
+     * @param key the notification key
+     * @param time milliseconds since midnight, January 1, 1970 UTC.
+     * @param actionIndex the index of the action button that was pressed.
+     */
+    public void onNotificationActionClick(String key, long time, int actionIndex)
+    {
+        // Do nothing, Override this to collect action button click statistics
+    }
+
+    /**
+     * A notification was removed.
+
+     * @param key the notification key
+     * @param time milliseconds since midnight, January 1, 1970 UTC.
+     * @param reason see {@link #REASON_LISTENER_CANCEL}, etc.
+     */
+    public void onNotificationRemoved(String key, long time, int reason) {
+        // Do nothing, Override this to collect dismissal statistics
+    }
+
+    /**
+     * Change the importance of an existing notification.  N.B. this won’t cause
+     * an existing notification to alert, but might allow a future update to
+     * this notification to alert.
+     *
+     * @param key the notification key
+     * @param adjustment the new importance with an explanation
+     */
+    public final void adjustImportance(String key, Adjustment adjustment) {
+        if (!isBound()) return;
+        try {
+            getNotificationInterface().setImportanceFromRankerService(mWrapper, key,
+                    adjustment.mImportance, adjustment.mExplanation);
+        } catch (android.os.RemoteException ex) {
+            Log.v(TAG, "Unable to contact notification manager", ex);
+        }
+    }
+
+    private class NotificationRankingServiceWrapper extends NotificationListenerWrapper {
+        @Override
+        public void onNotificationEnqueued(IStatusBarNotificationHolder sbnHolder,
+                int importance, boolean user) {
+            StatusBarNotification sbn;
+            try {
+                sbn = sbnHolder.get();
+            } catch (RemoteException e) {
+                Log.w(TAG, "onNotificationEnqueued: Error receiving StatusBarNotification", e);
+                return;
+            }
+
+            SomeArgs args = SomeArgs.obtain();
+            args.arg1 = sbn;
+            args.argi1 = importance;
+            args.argi2 = user ? 1 : 0;
+            mHandler.obtainMessage(MyHandler.MSG_ON_NOTIFICATION_ENQUEUED,
+                    args).sendToTarget();
+        }
+
+        @Override
+        public void onNotificationVisibilityChanged(String key, long time, boolean visible) {
+            SomeArgs args = SomeArgs.obtain();
+            args.arg1 = key;
+            args.arg2 = time;
+            args.argi1 = visible ? 1 : 0;
+            mHandler.obtainMessage(MyHandler.MSG_ON_NOTIFICATION_VISIBILITY_CHANGED,
+                    args).sendToTarget();
+        }
+
+        @Override
+        public void onNotificationClick(String key, long time) {
+            SomeArgs args = SomeArgs.obtain();
+            args.arg1 = key;
+            args.arg2 = time;
+            mHandler.obtainMessage(MyHandler.MSG_ON_NOTIFICATION_CLICK,
+                    args).sendToTarget();
+        }
+
+        @Override
+        public void onNotificationActionClick(String key, long time, int actionIndex) {
+            SomeArgs args = SomeArgs.obtain();
+            args.arg1 = key;
+            args.arg2 = time;
+            args.argi1 = actionIndex;
+            mHandler.obtainMessage(MyHandler.MSG_ON_NOTIFICATION_ACTION_CLICK,
+                    args).sendToTarget();
+        }
+
+        @Override
+        public void onNotificationRemovedReason(String key, long time, int reason) {
+            SomeArgs args = SomeArgs.obtain();
+            args.arg1 = key;
+            args.arg2 = time;
+            args.argi1 = reason;
+            mHandler.obtainMessage(MyHandler.MSG_ON_NOTIFICATION_REMOVED_REASON,
+                    args).sendToTarget();
+        }
+    }
+
+    private final class MyHandler extends Handler {
+        public static final int MSG_ON_NOTIFICATION_ENQUEUED = 1;
+        public static final int MSG_ON_NOTIFICATION_VISIBILITY_CHANGED = 2;
+        public static final int MSG_ON_NOTIFICATION_CLICK = 3;
+        public static final int MSG_ON_NOTIFICATION_ACTION_CLICK = 4;
+        public static final int MSG_ON_NOTIFICATION_REMOVED_REASON = 5;
+
+        public MyHandler(Looper looper) {
+            super(looper, null, false);
+        }
+
+        @Override
+        public void handleMessage(Message msg) {
+            switch (msg.what) {
+                case MSG_ON_NOTIFICATION_ENQUEUED: {
+                    SomeArgs args = (SomeArgs) msg.obj;
+                    StatusBarNotification sbn = (StatusBarNotification) args.arg1;
+                    final int importance = args.argi1;
+                    final boolean user = args.argi2 == 1;
+                    args.recycle();
+                    Adjustment adjustment = onNotificationEnqueued(sbn, importance, user);
+                    if (adjustment != null) {
+                        adjustImportance(sbn.getKey(), adjustment);
+                    }
+                } break;
+
+                case MSG_ON_NOTIFICATION_VISIBILITY_CHANGED: {
+                    SomeArgs args = (SomeArgs) msg.obj;
+                    final String key = (String) args.arg1;
+                    final long time = (long) args.arg2;
+                    final boolean visible = args.argi1 == 1;
+                    args.recycle();
+                    onNotificationVisibilityChanged(key, time, visible);
+                } break;
+
+                case MSG_ON_NOTIFICATION_CLICK: {
+                    SomeArgs args = (SomeArgs) msg.obj;
+                    final String key = (String) args.arg1;
+                    final long time = (long) args.arg2;
+                    args.recycle();
+                    onNotificationClick(key, time);
+                } break;
+
+                case MSG_ON_NOTIFICATION_ACTION_CLICK: {
+                    SomeArgs args = (SomeArgs) msg.obj;
+                    final String key = (String) args.arg1;
+                    final long time = (long) args.arg2;
+                    final int actionIndex = args.argi1;
+                    args.recycle();
+                    onNotificationActionClick(key, time, actionIndex);
+                } break;
+
+                case MSG_ON_NOTIFICATION_REMOVED_REASON: {
+                    SomeArgs args = (SomeArgs) msg.obj;
+                    final String key = (String) args.arg1;
+                    final long time = (long) args.arg2;
+                    final int reason = args.argi1;
+                    args.recycle();
+                    onNotificationRemoved(key, time, reason);
+                } break;
+            }
+        }
+    }
+}
diff --git a/core/java/android/service/notification/ZenModeConfig.aidl b/core/java/android/service/notification/ZenModeConfig.aidl
index c73b75e..4644103 100644
--- a/core/java/android/service/notification/ZenModeConfig.aidl
+++ b/core/java/android/service/notification/ZenModeConfig.aidl
@@ -17,4 +17,5 @@
 package android.service.notification;
 
 parcelable ZenModeConfig;
+parcelable ZenModeConfig.ZenRule;
 
diff --git a/core/java/android/service/notification/ZenModeConfig.java b/core/java/android/service/notification/ZenModeConfig.java
index 97939a9..27315ee 100644
--- a/core/java/android/service/notification/ZenModeConfig.java
+++ b/core/java/android/service/notification/ZenModeConfig.java
@@ -1017,7 +1017,7 @@
     public static class ZenRule implements Parcelable {
         public boolean enabled;
         public boolean snoozing;         // user manually disabled this instance
-        public String name;              // required for automatic (unique)
+        public String name;              // required for automatic
         public int zenMode;
         public Uri conditionId;          // required for automatic
         public Condition condition;      // optional
diff --git a/core/java/android/service/persistentdata/PersistentDataBlockManager.java b/core/java/android/service/persistentdata/PersistentDataBlockManager.java
index ddb6980..cfeed51 100644
--- a/core/java/android/service/persistentdata/PersistentDataBlockManager.java
+++ b/core/java/android/service/persistentdata/PersistentDataBlockManager.java
@@ -85,8 +85,7 @@
         try {
             return sService.write(data);
         } catch (RemoteException e) {
-            onError("writing data");
-            return -1;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -97,8 +96,7 @@
         try {
             return sService.read();
         } catch (RemoteException e) {
-            onError("reading data");
-            return null;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -111,8 +109,7 @@
         try {
             return sService.getDataBlockSize();
         } catch (RemoteException e) {
-            onError("getting data block size");
-            return -1;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -125,8 +122,7 @@
         try {
             return sService.getMaximumDataBlockSize();
         } catch (RemoteException e) {
-            onError("getting maximum data block size");
-            return -1;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -138,7 +134,7 @@
         try {
             sService.wipe();
         } catch (RemoteException e) {
-            onError("wiping persistent partition");
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -149,7 +145,7 @@
         try {
             sService.setOemUnlockEnabled(enabled);
         } catch (RemoteException e) {
-            onError("setting OEM unlock enabled to " + enabled);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -160,8 +156,7 @@
         try {
             return sService.getOemUnlockEnabled();
         } catch (RemoteException e) {
-            onError("getting OEM unlock enabled bit");
-            return false;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -178,12 +173,7 @@
         try {
             return sService.getFlashLockState();
         } catch (RemoteException e) {
-            onError("getting flash lock state");
-            return FLASH_LOCK_UNKNOWN;
+            throw e.rethrowFromSystemServer();
         }
     }
-
-    private void onError(String msg) {
-        Slog.v(TAG, "Remote exception while " + msg);
-    }
 }
diff --git a/core/java/android/content/pm/VerificationParams.aidl b/core/java/android/service/vr/IVrListener.aidl
similarity index 80%
rename from core/java/android/content/pm/VerificationParams.aidl
rename to core/java/android/service/vr/IVrListener.aidl
index 5bb7f6962..b7273ba 100644
--- a/core/java/android/content/pm/VerificationParams.aidl
+++ b/core/java/android/service/vr/IVrListener.aidl
@@ -1,5 +1,5 @@
-/*
- * Copyright 2012, 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.
@@ -14,6 +14,9 @@
  * limitations under the License.
  */
 
-package android.content.pm;
+package android.service.vr;
 
-parcelable VerificationParams;
+/** @hide */
+oneway interface IVrListener {
+
+}
\ No newline at end of file
diff --git a/core/java/android/service/vr/VrListenerService.java b/core/java/android/service/vr/VrListenerService.java
new file mode 100644
index 0000000..5f1f659
--- /dev/null
+++ b/core/java/android/service/vr/VrListenerService.java
@@ -0,0 +1,88 @@
+/**
+ * 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.service.vr;
+
+import android.annotation.NonNull;
+import android.annotation.SdkConstant;
+import android.app.ActivityManager;
+import android.app.Service;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.os.IBinder;
+
+/**
+ * A service that is bound from the system while running in virtual reality (VR) mode.
+ *
+ * <p>To extend this class, you must declare the service in your manifest file with
+ * the {@link android.Manifest.permission#BIND_VR_LISTENER_SERVICE} permission
+ * and include an intent filter with the {@link #SERVICE_INTERFACE} action. For example:</p>
+ * <pre>
+ * &lt;service android:name=".VrListener"
+ *          android:label="&#64;string/service_name"
+ *          android:permission="android.permission.BIND_VR_LISTENER_SERVICE">
+ *     &lt;intent-filter>
+ *         &lt;action android:name="android.service.vr.VrListenerService" />
+ *     &lt;/intent-filter>
+ * &lt;/service>
+ * </pre>
+ *
+ * <p>
+ * This service is bound when the system enters VR mode and is unbound when the system leaves VR
+ * mode.
+ * {@see android.app.Activity#setVrMode(boolean)}
+ * </p>
+ */
+public abstract class VrListenerService extends Service {
+
+    /**
+     * The {@link Intent} that must be declared as handled by the service.
+     */
+    @SdkConstant(SdkConstant.SdkConstantType.SERVICE_ACTION)
+    public static final String SERVICE_INTERFACE = "android.service.vr.VrListenerService";
+
+    /**
+     * @hide
+     */
+    public static class VrListenerBinder extends IVrListener.Stub {
+    }
+
+    private final VrListenerBinder mBinder = new VrListenerBinder();
+
+    @Override
+    public IBinder onBind(Intent intent) {
+        return mBinder;
+    }
+
+    /**
+     * Check if the given package is available to be enabled/disabled in VR mode settings.
+     *
+     * @param context the {@link Context} to use for looking up the requested component.
+     * @param requestedComponent the name of the component that implements
+     * {@link android.service.vr.VrListenerService} to check.
+     *
+     * @return {@code true} if this package is enabled in settings.
+     */
+    public static final boolean isVrModePackageEnabled(@NonNull Context context,
+            @NonNull ComponentName requestedComponent) {
+        ActivityManager am = context.getSystemService(ActivityManager.class);
+        if (am == null) {
+            return false;
+        }
+        return am.isVrModePackageEnabled(requestedComponent);
+    }
+}
diff --git a/core/java/android/text/BoringLayout.java b/core/java/android/text/BoringLayout.java
index 0f65f80..bfe5c3f 100644
--- a/core/java/android/text/BoringLayout.java
+++ b/core/java/android/text/BoringLayout.java
@@ -423,9 +423,6 @@
     private float mMax;
     private int mEllipsizedWidth, mEllipsizedStart, mEllipsizedCount;
 
-    private static final TextPaint sTemp =
-                                new TextPaint();
-
     public static class Metrics extends Paint.FontMetricsInt {
         public int width;
 
diff --git a/core/java/android/text/method/BaseKeyListener.java b/core/java/android/text/method/BaseKeyListener.java
index e79dfca..3564e11 100644
--- a/core/java/android/text/method/BaseKeyListener.java
+++ b/core/java/android/text/method/BaseKeyListener.java
@@ -16,6 +16,7 @@
 
 package android.text.method;
 
+import android.graphics.Paint;
 import android.icu.lang.UCharacter;
 import android.icu.lang.UProperty;
 import android.view.KeyEvent;
@@ -25,6 +26,8 @@
 import android.text.style.ReplacementSpan;
 import android.widget.TextView;
 
+import com.android.internal.annotations.GuardedBy;
+
 import java.text.BreakIterator;
 import java.util.Arrays;
 import java.util.Collections;
@@ -45,6 +48,11 @@
         implements KeyListener {
     /* package */ static final Object OLD_SEL_START = new NoCopySpan.Concrete();
 
+    private final Object mLock = new Object();
+
+    @GuardedBy("mLock")
+    static Paint sCachedPaint = null;
+
     /**
      * Performs the action that happens when you press the {@link KeyEvent#KEYCODE_DEL} key in
      * a {@link TextView}.  If there is a selection, deletes the selection; otherwise,
@@ -258,20 +266,15 @@
     }
 
     // Returns the end offset to be deleted by a forward delete key from the given offset.
-    private static int getOffsetForForwardDeleteKey(CharSequence text, int offset) {
+    private static int getOffsetForForwardDeleteKey(CharSequence text, int offset, Paint paint) {
         final int len = text.length();
 
         if (offset >= len - 1) {
             return len;
         }
 
-        int codePoint = Character.codePointAt(text, offset);
-        offset += Character.charCount(codePoint);
-        if (offset == len) {
-            return len;
-        }
-
-        // TODO: Handle emoji, combining chars, etc.
+        offset = paint.getTextRunCursor(text, offset, len, Paint.DIRECTION_LTR /* not used */,
+                offset, Paint.CURSOR_AFTER);
 
         return adjustReplacementSpan(text, offset, false /* move to the end */);
     }
@@ -311,7 +314,18 @@
         final int start = Selection.getSelectionEnd(content);
         final int end;
         if (isForwardDelete) {
-            end = getOffsetForForwardDeleteKey(content, start);
+            final Paint paint;
+            if (view instanceof TextView) {
+                paint = ((TextView)view).getPaint();
+            } else {
+                synchronized (mLock) {
+                    if (sCachedPaint == null) {
+                        sCachedPaint = new Paint();
+                    }
+                    paint = sCachedPaint;
+                }
+            }
+            end = getOffsetForForwardDeleteKey(content, start, paint);
         } else {
             end = getOffsetForBackspaceKey(content, start);
         }
diff --git a/core/java/android/text/util/Linkify.java b/core/java/android/text/util/Linkify.java
index fbd9924..bd376ea 100644
--- a/core/java/android/text/util/Linkify.java
+++ b/core/java/android/text/util/Linkify.java
@@ -224,7 +224,7 @@
         }
 
         if ((mask & EMAIL_ADDRESSES) != 0) {
-            gatherLinks(links, text, Patterns.EMAIL_ADDRESS,
+            gatherLinks(links, text, Patterns.AUTOLINK_EMAIL_ADDRESS,
                 new String[] { "mailto:" },
                 null, null);
         }
diff --git a/core/java/android/transition/ArcMotion.java b/core/java/android/transition/ArcMotion.java
index fa4c8d2..70443ba 100644
--- a/core/java/android/transition/ArcMotion.java
+++ b/core/java/android/transition/ArcMotion.java
@@ -15,13 +15,13 @@
  */
 package android.transition;
 
-import com.android.internal.R;
-
 import android.content.Context;
 import android.content.res.TypedArray;
 import android.graphics.Path;
 import android.util.AttributeSet;
 
+import com.android.internal.R;
+
 /**
  * A PathMotion that generates a curved path along an arc on an imaginary circle containing
  * the two points. If the horizontal distance between the points is less than the vertical
@@ -207,7 +207,7 @@
             ey = (startY + endY) / 2;
         } else {
             float deltaX = endX - startX;
-            float deltaY = startY - endY; // Y is inverted compared to diagram above.
+            float deltaY = endY - startY;
             // hypotenuse squared.
             float h2 = deltaX * deltaX + deltaY * deltaY;
 
@@ -219,24 +219,35 @@
             float midDist2 = h2 * 0.25f;
 
             float minimumArcDist2 = 0;
+            boolean isQuadrant1Or3 = (deltaX * deltaY) > 0;
 
-            if (Math.abs(deltaX) < Math.abs(deltaY)) {
+            if ((Math.abs(deltaX) < Math.abs(deltaY))) {
                 // Similar triangles bfa and bde mean that (ab/fb = eb/bd)
                 // Therefore, eb = ab * bd / fb
                 // ab = hypotenuse
                 // bd = hypotenuse/2
                 // fb = deltaY
                 float eDistY = h2 / (2 * deltaY);
-                ey = endY + eDistY;
-                ex = endX;
+                if (isQuadrant1Or3) {
+                    ey = startY + eDistY;
+                    ex = startX;
+                } else {
+                    ey = endY - eDistY;
+                    ex = endX;
+                }
 
                 minimumArcDist2 = midDist2 * mMinimumVerticalTangent
                         * mMinimumVerticalTangent;
             } else {
                 // Same as above, but flip X & Y
                 float eDistX = h2 / (2 * deltaX);
-                ex = endX + eDistX;
-                ey = endY;
+                if (isQuadrant1Or3) {
+                    ex = endX - eDistX;
+                    ey = endY;
+                } else {
+                    ex = startX + eDistX;
+                    ey = startY;
+                }
 
                 minimumArcDist2 = midDist2 * mMinimumHorizontalTangent
                         * mMinimumHorizontalTangent;
diff --git a/core/java/android/transition/Slide.java b/core/java/android/transition/Slide.java
index 9af65e4..2645f86 100644
--- a/core/java/android/transition/Slide.java
+++ b/core/java/android/transition/Slide.java
@@ -47,6 +47,7 @@
     private static final String PROPNAME_SCREEN_POSITION = "android:slide:screenPosition";
     private CalculateSlide mSlideCalculator = sCalculateBottom;
     private @GravityFlag int mSlideEdge = Gravity.BOTTOM;
+    private float mSlideFraction = 1;
 
     /** @hide */
     @Retention(RetentionPolicy.SOURCE)
@@ -56,16 +57,16 @@
     private interface CalculateSlide {
 
         /** Returns the translation value for view when it goes out of the scene */
-        float getGoneX(ViewGroup sceneRoot, View view);
+        float getGoneX(ViewGroup sceneRoot, View view, float fraction);
 
         /** Returns the translation value for view when it goes out of the scene */
-        float getGoneY(ViewGroup sceneRoot, View view);
+        float getGoneY(ViewGroup sceneRoot, View view, float fraction);
     }
 
     private static abstract class CalculateSlideHorizontal implements CalculateSlide {
 
         @Override
-        public float getGoneY(ViewGroup sceneRoot, View view) {
+        public float getGoneY(ViewGroup sceneRoot, View view, float fraction) {
             return view.getTranslationY();
         }
     }
@@ -73,27 +74,27 @@
     private static abstract class CalculateSlideVertical implements CalculateSlide {
 
         @Override
-        public float getGoneX(ViewGroup sceneRoot, View view) {
+        public float getGoneX(ViewGroup sceneRoot, View view, float fraction) {
             return view.getTranslationX();
         }
     }
 
     private static final CalculateSlide sCalculateLeft = new CalculateSlideHorizontal() {
         @Override
-        public float getGoneX(ViewGroup sceneRoot, View view) {
-            return view.getTranslationX() - sceneRoot.getWidth();
+        public float getGoneX(ViewGroup sceneRoot, View view, float fraction) {
+            return view.getTranslationX() - sceneRoot.getWidth() * fraction;
         }
     };
 
     private static final CalculateSlide sCalculateStart = new CalculateSlideHorizontal() {
         @Override
-        public float getGoneX(ViewGroup sceneRoot, View view) {
+        public float getGoneX(ViewGroup sceneRoot, View view, float fraction) {
             final boolean isRtl = sceneRoot.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL;
             final float x;
             if (isRtl) {
-                x = view.getTranslationX() + sceneRoot.getWidth();
+                x = view.getTranslationX() + sceneRoot.getWidth() * fraction;
             } else {
-                x = view.getTranslationX() - sceneRoot.getWidth();
+                x = view.getTranslationX() - sceneRoot.getWidth() * fraction;
             }
             return x;
         }
@@ -101,27 +102,27 @@
 
     private static final CalculateSlide sCalculateTop = new CalculateSlideVertical() {
         @Override
-        public float getGoneY(ViewGroup sceneRoot, View view) {
-            return view.getTranslationY() - sceneRoot.getHeight();
+        public float getGoneY(ViewGroup sceneRoot, View view, float fraction) {
+            return view.getTranslationY() - sceneRoot.getHeight() * fraction;
         }
     };
 
     private static final CalculateSlide sCalculateRight = new CalculateSlideHorizontal() {
         @Override
-        public float getGoneX(ViewGroup sceneRoot, View view) {
-            return view.getTranslationX() + sceneRoot.getWidth();
+        public float getGoneX(ViewGroup sceneRoot, View view, float fraction) {
+            return view.getTranslationX() + sceneRoot.getWidth() * fraction;
         }
     };
 
     private static final CalculateSlide sCalculateEnd = new CalculateSlideHorizontal() {
         @Override
-        public float getGoneX(ViewGroup sceneRoot, View view) {
+        public float getGoneX(ViewGroup sceneRoot, View view, float fraction) {
             final boolean isRtl = sceneRoot.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL;
             final float x;
             if (isRtl) {
-                x = view.getTranslationX() - sceneRoot.getWidth();
+                x = view.getTranslationX() - sceneRoot.getWidth() * fraction;
             } else {
-                x = view.getTranslationX() + sceneRoot.getWidth();
+                x = view.getTranslationX() + sceneRoot.getWidth() * fraction;
             }
             return x;
         }
@@ -129,8 +130,8 @@
 
     private static final CalculateSlide sCalculateBottom = new CalculateSlideVertical() {
         @Override
-        public float getGoneY(ViewGroup sceneRoot, View view) {
-            return view.getTranslationY() + sceneRoot.getHeight();
+        public float getGoneY(ViewGroup sceneRoot, View view, float fraction) {
+            return view.getTranslationY() + sceneRoot.getHeight() * fraction;
         }
     };
 
@@ -237,8 +238,8 @@
         int[] position = (int[]) endValues.values.get(PROPNAME_SCREEN_POSITION);
         float endX = view.getTranslationX();
         float endY = view.getTranslationY();
-        float startX = mSlideCalculator.getGoneX(sceneRoot, view);
-        float startY = mSlideCalculator.getGoneY(sceneRoot, view);
+        float startX = mSlideCalculator.getGoneX(sceneRoot, view, mSlideFraction);
+        float startY = mSlideCalculator.getGoneY(sceneRoot, view, mSlideFraction);
         return TranslationAnimationCreator
                 .createAnimation(view, endValues, position[0], position[1],
                         startX, startY, endX, endY, sDecelerate, this);
@@ -253,10 +254,15 @@
         int[] position = (int[]) startValues.values.get(PROPNAME_SCREEN_POSITION);
         float startX = view.getTranslationX();
         float startY = view.getTranslationY();
-        float endX = mSlideCalculator.getGoneX(sceneRoot, view);
-        float endY = mSlideCalculator.getGoneY(sceneRoot, view);
+        float endX = mSlideCalculator.getGoneX(sceneRoot, view, mSlideFraction);
+        float endY = mSlideCalculator.getGoneY(sceneRoot, view, mSlideFraction);
         return TranslationAnimationCreator
                 .createAnimation(view, startValues, position[0], position[1],
                         startX, startY, endX, endY, sAccelerate, this);
     }
+
+    /** @hide */
+    public void setSlideFraction(float slideFraction) {
+        mSlideFraction = slideFraction;
+    }
 }
diff --git a/core/java/android/transition/Transition.java b/core/java/android/transition/Transition.java
index 4afa9fe..316c7e3 100644
--- a/core/java/android/transition/Transition.java
+++ b/core/java/android/transition/Transition.java
@@ -41,12 +41,12 @@
 import android.widget.ListView;
 import android.widget.Spinner;
 
+import com.android.internal.R;
+
 import java.util.ArrayList;
 import java.util.List;
 import java.util.StringTokenizer;
 
-import com.android.internal.R;
-
 /**
  * A Transition holds information about animations that will be run on its
  * targets during a scene change. Subclasses of this abstract class may
@@ -192,7 +192,7 @@
     private TransitionValuesMaps mStartValues = new TransitionValuesMaps();
     private TransitionValuesMaps mEndValues = new TransitionValuesMaps();
     TransitionSet mParent = null;
-    private int[] mMatchOrder = DEFAULT_MATCH_ORDER;
+    int[] mMatchOrder = DEFAULT_MATCH_ORDER;
     ArrayList<TransitionValues> mStartValuesList; // only valid after playTransition starts
     ArrayList<TransitionValues> mEndValuesList; // only valid after playTransitions starts
 
@@ -246,7 +246,7 @@
 
     // The function used to interpolate along two-dimensional points. Typically used
     // for adding curves to x/y View motion.
-    private PathMotion mPathMotion = STRAIGHT_PATH_MOTION;
+    PathMotion mPathMotion = STRAIGHT_PATH_MOTION;
 
     /**
      * Constructs a Transition object with no target objects. A transition with
@@ -780,7 +780,7 @@
                 }
             }
         }
-        if (minStartDelay != 0) {
+        if (startDelays.size() != 0) {
             for (int i = 0; i < startDelays.size(); i++) {
                 int index = startDelays.keyAt(i);
                 Animator animator = mAnimators.get(index);
diff --git a/core/java/android/util/ArrayMap.java b/core/java/android/util/ArrayMap.java
index bdb1fdc..92a5803 100644
--- a/core/java/android/util/ArrayMap.java
+++ b/core/java/android/util/ArrayMap.java
@@ -67,7 +67,7 @@
     /**
      * @hide Special immutable empty ArrayMap.
      */
-    public static final ArrayMap EMPTY = new ArrayMap(true);
+    public static final ArrayMap EMPTY = new ArrayMap<>(-1);
 
     /**
      * Caches of small array objects to avoid spamming garbage.  The cache
@@ -80,6 +80,7 @@
     static Object[] mTwiceBaseCache;
     static int mTwiceBaseCacheSize;
 
+    final boolean mIdentityHashCode;
     int[] mHashes;
     Object[] mArray;
     int mSize;
@@ -236,16 +237,27 @@
      * will grow once items are added to it.
      */
     public ArrayMap() {
-        mHashes = EmptyArray.INT;
-        mArray = EmptyArray.OBJECT;
-        mSize = 0;
+        this(0, false);
     }
 
     /**
      * Create a new ArrayMap with a given initial capacity.
      */
     public ArrayMap(int capacity) {
-        if (capacity == 0) {
+        this(capacity, false);
+    }
+
+    /** {@hide} */
+    public ArrayMap(int capacity, boolean identityHashCode) {
+        mIdentityHashCode = identityHashCode;
+
+        // If this is immutable, use the sentinal EMPTY_IMMUTABLE_INTS
+        // instance instead of the usual EmptyArray.INT. The reference
+        // is checked later to see if the array is allowed to grow.
+        if (capacity < 0) {
+            mHashes = EMPTY_IMMUTABLE_INTS;
+            mArray = EmptyArray.OBJECT;
+        } else if (capacity == 0) {
             mHashes = EmptyArray.INT;
             mArray = EmptyArray.OBJECT;
         } else {
@@ -254,15 +266,6 @@
         mSize = 0;
     }
 
-    private ArrayMap(boolean immutable) {
-        // If this is immutable, use the sentinal EMPTY_IMMUTABLE_INTS
-        // instance instead of the usual EmptyArray.INT. The reference
-        // is checked later to see if the array is allowed to grow.
-        mHashes = immutable ? EMPTY_IMMUTABLE_INTS : EmptyArray.INT;
-        mArray = EmptyArray.OBJECT;
-        mSize = 0;
-    }
-
     /**
      * Create a new ArrayMap with the mappings from the given ArrayMap.
      */
@@ -336,7 +339,8 @@
      * @return Returns the index of the key if it exists, else a negative integer.
      */
     public int indexOfKey(Object key) {
-        return key == null ? indexOfNull() : indexOf(key, key.hashCode());
+        return key == null ? indexOfNull()
+                : indexOf(key, mIdentityHashCode ? System.identityHashCode(key) : key.hashCode());
     }
 
     int indexOfValue(Object value) {
@@ -437,7 +441,7 @@
             hash = 0;
             index = indexOfNull();
         } else {
-            hash = key.hashCode();
+            hash = mIdentityHashCode ? System.identityHashCode(key) : key.hashCode();
             index = indexOf(key, hash);
         }
         if (index >= 0) {
@@ -488,7 +492,8 @@
      */
     public void append(K key, V value) {
         int index = mSize;
-        final int hash = key == null ? 0 : key.hashCode();
+        final int hash = key == null ? 0
+                : (mIdentityHashCode ? System.identityHashCode(key) : key.hashCode());
         if (index >= mHashes.length) {
             throw new IllegalStateException("Array is full");
         }
diff --git a/core/java/android/util/ArraySet.java b/core/java/android/util/ArraySet.java
index b7a3c42..9e9314f 100644
--- a/core/java/android/util/ArraySet.java
+++ b/core/java/android/util/ArraySet.java
@@ -69,6 +69,7 @@
     static Object[] mTwiceBaseCache;
     static int mTwiceBaseCacheSize;
 
+    final boolean mIdentityHashCode;
     int[] mHashes;
     Object[] mArray;
     int mSize;
@@ -222,15 +223,19 @@
      * will grow once items are added to it.
      */
     public ArraySet() {
-        mHashes = EmptyArray.INT;
-        mArray = EmptyArray.OBJECT;
-        mSize = 0;
+        this(0, false);
     }
 
     /**
      * Create a new ArraySet with a given initial capacity.
      */
     public ArraySet(int capacity) {
+        this(capacity, false);
+    }
+
+    /** {@hide} */
+    public ArraySet(int capacity, boolean identityHashCode) {
+        mIdentityHashCode = identityHashCode;
         if (capacity == 0) {
             mHashes = EmptyArray.INT;
             mArray = EmptyArray.OBJECT;
@@ -306,7 +311,8 @@
      * @return Returns the index of the value if it exists, else a negative integer.
      */
     public int indexOf(Object key) {
-        return key == null ? indexOfNull() : indexOf(key, key.hashCode());
+        return key == null ? indexOfNull()
+                : indexOf(key, mIdentityHashCode ? System.identityHashCode(key) : key.hashCode());
     }
 
     /**
@@ -343,7 +349,7 @@
             hash = 0;
             index = indexOfNull();
         } else {
-            hash = value.hashCode();
+            hash = mIdentityHashCode ? System.identityHashCode(value) : value.hashCode();
             index = indexOf(value, hash);
         }
         if (index >= 0) {
diff --git a/core/java/android/util/LocaleList.java b/core/java/android/util/LocaleList.java
index fc39004..fa3921c 100644
--- a/core/java/android/util/LocaleList.java
+++ b/core/java/android/util/LocaleList.java
@@ -478,8 +478,6 @@
     /**
      * Returns the default locale list, adjusted by moving the default locale to its first
      * position.
-     *
-     * {@hide}
      */
     @NonNull @Size(min=1)
     public static LocaleList getAdjustedDefault() {
diff --git a/core/java/android/util/Log.java b/core/java/android/util/Log.java
index 3d7cb49..5bc6c94 100644
--- a/core/java/android/util/Log.java
+++ b/core/java/android/util/Log.java
@@ -16,6 +16,8 @@
 
 package android.util;
 
+import android.os.DeadSystemException;
+
 import com.android.internal.os.RuntimeInit;
 import com.android.internal.util.FastPrintWriter;
 import com.android.internal.util.LineBreakBufferedWriter;
@@ -405,6 +407,11 @@
                 if (t instanceof UnknownHostException) {
                     break;
                 }
+                if (t instanceof DeadSystemException) {
+                    lbbw.println("DeadSystemException: The system died; "
+                            + "earlier logs will point to the root cause");
+                    break;
+                }
                 t = t.getCause();
             }
             if (t == null) {
diff --git a/core/java/android/util/Patterns.java b/core/java/android/util/Patterns.java
index 9f2bcfd..9ed4850 100644
--- a/core/java/android/util/Patterns.java
+++ b/core/java/android/util/Patterns.java
@@ -394,6 +394,36 @@
     public static final Pattern AUTOLINK_WEB_URL = Pattern.compile(
             "(" + WEB_URL_WITH_PROTOCOL + "|" + WEB_URL_WITHOUT_PROTOCOL + ")");
 
+    /**
+     * Regular expression for valid email characters. Does not include some of the valid characters
+     * defined in RFC5321: #&~!^`{}/=$*?|
+     */
+    private static final String EMAIL_CHAR = LABEL_CHAR + "\\+\\-_%'";
+
+    /**
+     * Regular expression for local part of an email address. RFC5321 section 4.5.3.1.1 limits
+     * the local part to be at most 64 octets.
+     */
+    private static final String EMAIL_ADDRESS_LOCAL_PART =
+            "[" + EMAIL_CHAR + "]" + "(?:[" + EMAIL_CHAR + "\\.]{1,62}[" + EMAIL_CHAR + "])?";
+
+    /**
+     * Regular expression for the domain part of an email address. RFC5321 section 4.5.3.1.2 limits
+     * the domain to be at most 255 octets.
+     */
+    private static final String EMAIL_ADDRESS_DOMAIN =
+            "(?=.{1,255}(?:\\s|$|^))" + HOST_NAME;
+
+    /**
+     * Regular expression pattern to match email addresses. It excludes double quoted local parts
+     * and the special characters #&~!^`{}/=$*?| that are included in RFC5321.
+     * @hide
+     */
+    public static final Pattern AUTOLINK_EMAIL_ADDRESS = Pattern.compile("(" + WORD_BOUNDARY +
+            "(?:" + EMAIL_ADDRESS_LOCAL_PART + "@" + EMAIL_ADDRESS_DOMAIN + ")" +
+            WORD_BOUNDARY + ")"
+    );
+
     public static final Pattern EMAIL_ADDRESS
         = Pattern.compile(
             "[a-zA-Z0-9\\+\\.\\_\\%\\-\\+]{1,256}" +
diff --git a/core/java/android/util/apk/ApkSignatureSchemeV2Verifier.java b/core/java/android/util/apk/ApkSignatureSchemeV2Verifier.java
index 728f723..60c7270 100644
--- a/core/java/android/util/apk/ApkSignatureSchemeV2Verifier.java
+++ b/core/java/android/util/apk/ApkSignatureSchemeV2Verifier.java
@@ -75,6 +75,36 @@
     public static final int SF_ATTRIBUTE_ANDROID_APK_SIGNED_ID = 2;
 
     /**
+     * Returns {@code true} if the provided APK contains an APK Signature Scheme V2
+     * signature. The signature will not be verified.
+     */
+    public static boolean hasSignature(String apkFile) throws IOException {
+        try (RandomAccessFile apk = new RandomAccessFile(apkFile, "r")) {
+            long fileSize = apk.length();
+            if (fileSize > Integer.MAX_VALUE) {
+                return false;
+            }
+            MappedByteBuffer apkContents =
+                    apk.getChannel().map(FileChannel.MapMode.READ_ONLY, 0, fileSize);
+            // ZipUtils and APK Signature Scheme v2 verifier expect little-endian byte order.
+            apkContents.order(ByteOrder.LITTLE_ENDIAN);
+
+            final int centralDirOffset =
+                    (int) getCentralDirOffset(apkContents, getEocdOffset(apkContents));
+            // Find the APK Signing Block.
+            int apkSigningBlockOffset = findApkSigningBlock(apkContents, centralDirOffset);
+            ByteBuffer apkSigningBlock =
+                    sliceFromTo(apkContents, apkSigningBlockOffset, centralDirOffset);
+
+            // Find the APK Signature Scheme v2 Block inside the APK Signing Block.
+            findApkSignatureSchemeV2Block(apkSigningBlock);
+            return true;
+        } catch (SignatureNotFoundException e) {
+        }
+        return false;
+    }
+
+    /**
      * Verifies APK Signature Scheme v2 signatures of the provided APK and returns the certificates
      * associated with each signer.
      *
@@ -130,31 +160,8 @@
         // ZipUtils and APK Signature Scheme v2 verifier expect little-endian byte order.
         apkContents.order(ByteOrder.LITTLE_ENDIAN);
 
-        // Find the offset of ZIP End of Central Directory (EoCD)
-        int eocdOffset = ZipUtils.findZipEndOfCentralDirectoryRecord(apkContents);
-        if (eocdOffset == -1) {
-            throw new SignatureNotFoundException(
-                    "Not an APK file: ZIP End of Central Directory record not found");
-        }
-        if (ZipUtils.isZip64EndOfCentralDirectoryLocatorPresent(apkContents, eocdOffset)) {
-            throw new SignatureNotFoundException("ZIP64 APK not supported");
-        }
-        ByteBuffer eocd = sliceFromTo(apkContents, eocdOffset, apkContents.capacity());
-
-        // Look up the offset of ZIP Central Directory.
-        long centralDirOffsetLong = ZipUtils.getZipEocdCentralDirectoryOffset(eocd);
-        if (centralDirOffsetLong >= eocdOffset) {
-            throw new SignatureNotFoundException(
-                    "ZIP Central Directory offset out of range: " + centralDirOffsetLong
-                    + ". ZIP End of Central Directory offset: " + eocdOffset);
-        }
-        long centralDirSizeLong = ZipUtils.getZipEocdCentralDirectorySizeBytes(eocd);
-        if (centralDirOffsetLong + centralDirSizeLong != eocdOffset) {
-            throw new SignatureNotFoundException(
-                    "ZIP Central Directory is not immediately followed by End of Central"
-                    + " Directory");
-        }
-        int centralDirOffset = (int) centralDirOffsetLong;
+        final int eocdOffset = getEocdOffset(apkContents);
+        final int centralDirOffset = (int) getCentralDirOffset(apkContents, eocdOffset);
 
         // Find the APK Signing Block.
         int apkSigningBlockOffset = findApkSigningBlock(apkContents, centralDirOffset);
@@ -499,6 +506,43 @@
         return result;
     }
 
+    /**
+     * Finds the offset of ZIP End of Central Directory (EoCD).
+     *
+     * @throws SignatureNotFoundException If the EoCD could not be found
+     */
+    private static int getEocdOffset(ByteBuffer apkContents) throws SignatureNotFoundException {
+        int eocdOffset = ZipUtils.findZipEndOfCentralDirectoryRecord(apkContents);
+        if (eocdOffset == -1) {
+            throw new SignatureNotFoundException(
+                    "Not an APK file: ZIP End of Central Directory record not found");
+        }
+        return eocdOffset;
+    }
+
+    private static long getCentralDirOffset(ByteBuffer apkContents, int eocdOffset)
+            throws SignatureNotFoundException {
+        if (ZipUtils.isZip64EndOfCentralDirectoryLocatorPresent(apkContents, eocdOffset)) {
+            throw new SignatureNotFoundException("ZIP64 APK not supported");
+        }
+        ByteBuffer eocd = sliceFromTo(apkContents, eocdOffset, apkContents.capacity());
+
+        // Look up the offset of ZIP Central Directory.
+        long centralDirOffsetLong = ZipUtils.getZipEocdCentralDirectoryOffset(eocd);
+        if (centralDirOffsetLong >= eocdOffset) {
+            throw new SignatureNotFoundException(
+                    "ZIP Central Directory offset out of range: " + centralDirOffsetLong
+                    + ". ZIP End of Central Directory offset: " + eocdOffset);
+        }
+        long centralDirSizeLong = ZipUtils.getZipEocdCentralDirectorySizeBytes(eocd);
+        if (centralDirOffsetLong + centralDirSizeLong != eocdOffset) {
+            throw new SignatureNotFoundException(
+                    "ZIP Central Directory is not immediately followed by End of Central"
+                    + " Directory");
+        }
+        return centralDirOffsetLong;
+    }
+
     private static final int getChunkCount(int inputSizeBytes) {
         return (inputSizeBytes + CHUNK_SIZE_BYTES - 1) / CHUNK_SIZE_BYTES;
     }
diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl
index 5b9930b..f912e51 100644
--- a/core/java/android/view/IWindowManager.aidl
+++ b/core/java/android/view/IWindowManager.aidl
@@ -20,6 +20,7 @@
 import com.android.internal.os.IResultReceiver;
 import com.android.internal.view.IInputContext;
 import com.android.internal.view.IInputMethodClient;
+import com.android.internal.policy.IShortcutService;
 
 import android.content.res.CompatibilityInfo;
 import android.content.res.Configuration;
@@ -166,7 +167,7 @@
             in CompatibilityInfo compatInfo, CharSequence nonLocalizedLabel, int labelRes,
             int icon, int logo, int windowFlags, IBinder transferFrom, boolean createIfNeeded);
     void setAppVisibility(IBinder token, boolean visible);
-    void notifyAppStopped(IBinder token);
+    void notifyAppStopped(IBinder token, boolean stopped);
     void startAppFreezingScreen(IBinder token, int configChanges);
     void stopAppFreezingScreen(IBinder token, boolean force);
     void removeAppToken(IBinder token);
@@ -362,6 +363,12 @@
     void setDockedStackResizing(boolean resizing);
 
     /**
+     * Sets the region the user can touch the divider. This region will be excluded from the region
+     * which is used to cause a focus switch when dispatching touch.
+     */
+    void setDockedStackDividerTouchRegion(in Rect touchableRegion);
+
+    /**
      * Registers a listener that will be called when the dock divider changes its visibility or when
      * the docked stack gets added/removed.
      */
@@ -387,4 +394,11 @@
      * Retrieves the current stable insets from the primary display.
      */
     void getStableInsets(out Rect outInsets);
+
+    /**
+     * Register shortcut key. Shortcut code is packed as:
+     * (MetaState << Integer.SIZE) | KeyCode
+     * @hide
+     */
+    void registerShortcutKey(in long shortcutCode, IShortcutService keySubscriber);
 }
diff --git a/core/java/android/view/NotificationHeaderView.java b/core/java/android/view/NotificationHeaderView.java
index b9a7421..cff9d8e 100644
--- a/core/java/android/view/NotificationHeaderView.java
+++ b/core/java/android/view/NotificationHeaderView.java
@@ -35,7 +35,6 @@
 public class NotificationHeaderView extends ViewGroup {
     public static final int NO_COLOR = -1;
     private final int mChildMinWidth;
-    private final int mExpandTopPadding;
     private final int mContentEndMargin;
     private View mAppName;
     private View mSubTextView;
@@ -43,12 +42,10 @@
     private HeaderTouchListener mTouchListener = new HeaderTouchListener();
     private ImageView mExpandButton;
     private View mIcon;
-    private TextView mChildCount;
     private View mProfileBadge;
     private View mInfo;
     private int mIconColor;
     private int mOriginalNotificationColor;
-    private boolean mGroupHeader;
     private boolean mExpanded;
     private boolean mShowWorkBadgeAtEnd;
 
@@ -70,7 +67,6 @@
                 com.android.internal.R.dimen.notification_header_shrink_min_width);
         mContentEndMargin = getResources().getDimensionPixelSize(
                 com.android.internal.R.dimen.notification_content_margin_end);
-        mExpandTopPadding = (int) (1 * getResources().getDisplayMetrics().density);
     }
 
     @Override
@@ -80,7 +76,6 @@
         mSubTextView = findViewById(com.android.internal.R.id.header_sub_text);
         mExpandButton = (ImageView) findViewById(com.android.internal.R.id.expand_button);
         mIcon = findViewById(com.android.internal.R.id.icon);
-        mChildCount = (TextView) findViewById(com.android.internal.R.id.number_of_children);
         mProfileBadge = findViewById(com.android.internal.R.id.profile_badge);
         mInfo = findViewById(com.android.internal.R.id.header_content_info);
     }
@@ -193,17 +188,6 @@
         updateTouchListener();
     }
 
-    public void setChildCount(int childCount) {
-        if (childCount > 0) {
-            mChildCount.setText(getContext().getString(
-                    com.android.internal.R.string.notification_children_count_bracketed,
-                    childCount));
-            mChildCount.setVisibility(VISIBLE);
-        } else {
-            mChildCount.setVisibility(GONE);
-        }
-    }
-
     @RemotableViewMethod
     public void setOriginalIconColor(int color) {
         mIconColor = color;
@@ -222,11 +206,6 @@
         return mOriginalNotificationColor;
     }
 
-    public void setIsGroupHeader(boolean isGroupHeader) {
-        mGroupHeader = isGroupHeader;
-        updateExpandButton();
-    }
-
     @RemotableViewMethod
     public void setExpanded(boolean expanded) {
         mExpanded = expanded;
@@ -235,24 +214,13 @@
 
     private void updateExpandButton() {
         int drawableId;
-        int paddingTop = 0;
-        if (mGroupHeader) {
-            if (mExpanded) {
-                drawableId = com.android.internal.R.drawable.ic_collapse_bundle;
-            } else {
-                drawableId =com.android.internal.R.drawable.ic_expand_bundle;
-            }
+        if (mExpanded) {
+            drawableId = com.android.internal.R.drawable.ic_collapse_notification;
         } else {
-            if (mExpanded) {
-                drawableId = com.android.internal.R.drawable.ic_collapse_notification;
-            } else {
-                drawableId = com.android.internal.R.drawable.ic_expand_notification;
-            }
-            paddingTop = mExpandTopPadding;
+            drawableId = com.android.internal.R.drawable.ic_expand_notification;
         }
         mExpandButton.setImageDrawable(getContext().getDrawable(drawableId));
         mExpandButton.setColorFilter(mOriginalNotificationColor);
-        mExpandButton.setPadding(0, paddingTop, 0, 0);
     }
 
     public void setShowWorkBadgeAtEnd(boolean showWorkBadgeAtEnd) {
diff --git a/core/java/android/view/Surface.aidl b/core/java/android/view/Surface.aidl
deleted file mode 100644
index 90bf37a..0000000
--- a/core/java/android/view/Surface.aidl
+++ /dev/null
@@ -1,20 +0,0 @@
-/* //device/java/android/android/view/Surface.aidl
-**
-** 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 
-**
-**     http://www.apache.org/licenses/LICENSE-2.0 
-**
-** Unless required by applicable law or agreed to in writing, software 
-** distributed under the License is distributed on an "AS IS" BASIS, 
-** WITHOUT 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.view;
-
-parcelable Surface;
diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java
index b58c68f..aa86c03 100644
--- a/core/java/android/view/SurfaceControl.java
+++ b/core/java/android/view/SurfaceControl.java
@@ -36,6 +36,7 @@
             throws OutOfResourcesException;
     private static native void nativeRelease(long nativeObject);
     private static native void nativeDestroy(long nativeObject);
+    private static native void nativeDisconnect(long nativeObject);
 
     private static native Bitmap nativeScreenshot(IBinder displayToken,
             Rect sourceCrop, int width, int height, int minLayer, int maxLayer,
@@ -341,6 +342,15 @@
         mCloseGuard.close();
     }
 
+    /**
+     * Disconnect any client still connected to the surface.
+     */
+    public void disconnect() {
+        if (mNativeObject != 0) {
+            nativeDisconnect(mNativeObject);
+        }
+    }
+
     private void checkNotReleased() {
         if (mNativeObject == 0) throw new NullPointerException(
                 "mNativeObject is null. Have you called release() already?");
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index e7be7af..57ab6d4 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -10270,6 +10270,27 @@
     }
 
     /**
+     * Like {@link #getWindowVisibleDisplayFrame}, but returns the "full" display frame this window
+     * is currently in without any insets.
+     *
+     * @hide
+     */
+    public void getWindowDisplayFrame(Rect outRect) {
+        if (mAttachInfo != null) {
+            try {
+                mAttachInfo.mSession.getDisplayFrame(mAttachInfo.mWindow, outRect);
+            } catch (RemoteException e) {
+                return;
+            }
+            return;
+        }
+        // The view is not attached to a display so we don't have a context.
+        // Make a best guess about the display size.
+        Display d = DisplayManagerGlobal.getInstance().getRealDisplay(Display.DEFAULT_DISPLAY);
+        d.getRectSize(outRect);
+    }
+
+    /**
      * Dispatch a notification about a resource configuration change down
      * the view hierarchy.
      * ViewGroups should override to route to their children.
@@ -17484,7 +17505,7 @@
      *        {@link SystemClock#uptimeMillis} timebase.
      */
     @Override
-    public void scheduleDrawable(Drawable who, Runnable what, long when) {
+    public void scheduleDrawable(@NonNull Drawable who, @NonNull Runnable what, long when) {
         if (verifyDrawable(who) && what != null) {
             final long delay = when - SystemClock.uptimeMillis();
             if (mAttachInfo != null) {
@@ -17506,7 +17527,7 @@
      * @param what the action to cancel
      */
     @Override
-    public void unscheduleDrawable(Drawable who, Runnable what) {
+    public void unscheduleDrawable(@NonNull Drawable who, @NonNull Runnable what) {
         if (verifyDrawable(who) && what != null) {
             if (mAttachInfo != null) {
                 mAttachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
@@ -17616,7 +17637,7 @@
      * @see #drawableStateChanged()
      */
     @CallSuper
-    protected boolean verifyDrawable(Drawable who) {
+    protected boolean verifyDrawable(@NonNull Drawable who) {
         // Avoid verifying the scroll bar drawable so that we don't end up in
         // an invalidation loop. This effectively prevents the scroll bar
         // drawable from triggering invalidations and scheduling runnables.
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index c54ce80..d29bc21 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -5357,9 +5357,6 @@
     void offsetRectBetweenParentAndChild(View descendant, Rect rect,
             boolean offsetFromChildToParent, boolean clipToBounds) {
 
-        final RectF rectF = mAttachInfo != null ? mAttachInfo.mTmpTransformRect1 : new RectF();
-        final Matrix inverse = mAttachInfo != null ? mAttachInfo.mTmpMatrix : new Matrix();
-
         // already in the same coord system :)
         if (descendant == this) {
             return;
@@ -5373,16 +5370,8 @@
                 && (theParent != this)) {
 
             if (offsetFromChildToParent) {
-                rect.offset(-descendant.mScrollX, -descendant.mScrollY);
-
-                if (!descendant.hasIdentityMatrix()) {
-                    rectF.set(rect);
-                    descendant.getMatrix().mapRect(rectF);
-                    rectF.roundOut(rect);
-                }
-
-                rect.offset(descendant.mLeft, descendant.mTop);
-
+                rect.offset(descendant.mLeft - descendant.mScrollX,
+                        descendant.mTop - descendant.mScrollY);
                 if (clipToBounds) {
                     View p = (View) theParent;
                     boolean intersected = rect.intersect(0, 0, p.mRight - p.mLeft,
@@ -5400,16 +5389,8 @@
                         rect.setEmpty();
                     }
                 }
-                rect.offset(-descendant.mLeft, -descendant.mTop);
-
-                if (!descendant.hasIdentityMatrix()) {
-                    descendant.getMatrix().invert(inverse);
-                    rectF.set(rect);
-                    inverse.mapRect(rectF);
-                    rectF.roundOut(rect);
-                }
-
-                rect.offset(descendant.mScrollX, descendant.mScrollY);
+                rect.offset(descendant.mScrollX - descendant.mLeft,
+                        descendant.mScrollY - descendant.mTop);
             }
 
             descendant = (View) theParent;
@@ -5420,26 +5401,11 @@
         // to get into our coordinate space
         if (theParent == this) {
             if (offsetFromChildToParent) {
-                rect.offset(-descendant.mScrollX, -descendant.mScrollY);
-
-                if (!descendant.hasIdentityMatrix()) {
-                    rectF.set(rect);
-                    descendant.getMatrix().mapRect(rectF);
-                    rectF.roundOut(rect);
-                }
-
-                rect.offset(descendant.mLeft, descendant.mTop);
+                rect.offset(descendant.mLeft - descendant.mScrollX,
+                        descendant.mTop - descendant.mScrollY);
             } else {
-                rect.offset(-descendant.mLeft, -descendant.mTop);
-
-                if (!descendant.hasIdentityMatrix()) {
-                    descendant.getMatrix().invert(inverse);
-                    rectF.set(rect);
-                    inverse.mapRect(rectF);
-                    rectF.roundOut(rect);
-                }
-
-                rect.offset(descendant.mScrollX, descendant.mScrollY);
+                rect.offset(descendant.mScrollX - descendant.mLeft,
+                        descendant.mScrollY - descendant.mTop);
             }
         } else {
             throw new IllegalArgumentException("parameter must be a descendant of this view");
diff --git a/core/java/android/view/ViewGroupOverlay.java b/core/java/android/view/ViewGroupOverlay.java
index 16afc5d..c2807ba 100644
--- a/core/java/android/view/ViewGroupOverlay.java
+++ b/core/java/android/view/ViewGroupOverlay.java
@@ -15,6 +15,7 @@
  */
 package android.view;
 
+import android.annotation.NonNull;
 import android.content.Context;
 import android.graphics.drawable.Drawable;
 
@@ -37,7 +38,7 @@
     }
 
     /**
-     * Adds a View to the overlay. The bounds of the added view should be
+     * Adds a {@code View} to the overlay. The bounds of the added view should be
      * relative to the host view. Any view added to the overlay should be
      * removed when it is no longer needed or no longer visible.
      *
@@ -54,23 +55,32 @@
      * and 200 pixels down from the origin of the overlay's
      * host view, then the view will be offset by (100, 200).</p>
      *
-     * @param view The View to be added to the overlay. The added view will be
+     * <p>{@code View}s added with this API will be drawn in the order they were
+     * added. Drawing of the overlay views will happen before drawing of any of the
+     * {@code Drawable}s added with {@link #add(Drawable)} API even if a call to
+     * this API happened after the call to {@link #add(Drawable)}.</p>
+     *
+     * <p>Passing <code>null</code> parameter will result in an
+     * {@link IllegalArgumentException} being thrown.</p>
+     *
+     * @param view The {@code View} to be added to the overlay. The added view will be
      * drawn when the overlay is drawn.
      * @see #remove(View)
      * @see ViewOverlay#add(Drawable)
      */
-    public void add(View view) {
+    public void add(@NonNull View view) {
         mOverlayViewGroup.add(view);
     }
 
     /**
-     * Removes the specified View from the overlay.
+     * Removes the specified {@code View} from the overlay. Passing <code>null</code> parameter
+     * will result in an {@link IllegalArgumentException} being thrown.
      *
-     * @param view The View to be removed from the overlay.
+     * @param view The {@code View} to be removed from the overlay.
      * @see #add(View)
      * @see ViewOverlay#remove(Drawable)
      */
-    public void remove(View view) {
+    public void remove(@NonNull View view) {
         mOverlayViewGroup.remove(view);
     }
 }
diff --git a/core/java/android/view/ViewOverlay.java b/core/java/android/view/ViewOverlay.java
index 5e5ef29..69c30ba 100644
--- a/core/java/android/view/ViewOverlay.java
+++ b/core/java/android/view/ViewOverlay.java
@@ -16,6 +16,7 @@
 package android.view;
 
 import android.animation.LayoutTransition;
+import android.annotation.NonNull;
 import android.content.Context;
 import android.graphics.Canvas;
 import android.graphics.Rect;
@@ -59,25 +60,30 @@
     }
 
     /**
-     * Adds a Drawable to the overlay. The bounds of the drawable should be relative to
+     * Adds a {@link Drawable} to the overlay. The bounds of the drawable should be relative to
      * the host view. Any drawable added to the overlay should be removed when it is no longer
-     * needed or no longer visible.
+     * needed or no longer visible. Adding an already existing {@link Drawable}
+     * is a no-op. Passing <code>null</code> parameter will result in an
+     * {@link IllegalArgumentException} being thrown.
      *
-     * @param drawable The Drawable to be added to the overlay. This drawable will be
-     * drawn when the view redraws its overlay.
+     * @param drawable The {@link Drawable} to be added to the overlay. This drawable will be
+     * drawn when the view redraws its overlay. {@link Drawable}s will be drawn in the order that
+     * they were added.
      * @see #remove(Drawable)
      */
-    public void add(Drawable drawable) {
+    public void add(@NonNull Drawable drawable) {
         mOverlayViewGroup.add(drawable);
     }
 
     /**
-     * Removes the specified Drawable from the overlay.
+     * Removes the specified {@link Drawable} from the overlay. Removing a {@link Drawable} that was
+     * not added with {@link #add(Drawable)} is a no-op. Passing <code>null</code> parameter will
+     * result in an {@link IllegalArgumentException} being thrown.
      *
-     * @param drawable The Drawable to be removed from the overlay.
+     * @param drawable The {@link Drawable} to be removed from the overlay.
      * @see #add(Drawable)
      */
-    public void remove(Drawable drawable) {
+    public void remove(@NonNull Drawable drawable) {
         mOverlayViewGroup.remove(drawable);
     }
 
@@ -119,7 +125,7 @@
          * The View for which this is an overlay. Invalidations of the overlay are redirected to
          * this host view.
          */
-        View mHostView;
+        final View mHostView;
 
         /**
          * The set of drawables to draw when the overlay is rendered.
@@ -137,10 +143,12 @@
             mRenderNode.setLeftTopRightBottom(0, 0, mRight, mBottom);
         }
 
-        public void add(Drawable drawable) {
+        public void add(@NonNull Drawable drawable) {
+            if (drawable == null) {
+                throw new IllegalArgumentException("drawable must be non-null");
+            }
             if (mDrawables == null) {
-
-                mDrawables = new ArrayList<Drawable>();
+                mDrawables = new ArrayList<>();
             }
             if (!mDrawables.contains(drawable)) {
                 // Make each drawable unique in the overlay; can't add it more than once
@@ -150,7 +158,10 @@
             }
         }
 
-        public void remove(Drawable drawable) {
+        public void remove(@NonNull Drawable drawable) {
+            if (drawable == null) {
+                throw new IllegalArgumentException("drawable must be non-null");
+            }
             if (mDrawables != null) {
                 mDrawables.remove(drawable);
                 invalidate(drawable.getBounds());
@@ -159,11 +170,15 @@
         }
 
         @Override
-        protected boolean verifyDrawable(Drawable who) {
+        protected boolean verifyDrawable(@NonNull Drawable who) {
             return super.verifyDrawable(who) || (mDrawables != null && mDrawables.contains(who));
         }
 
-        public void add(View child) {
+        public void add(@NonNull View child) {
+            if (child == null) {
+                throw new IllegalArgumentException("view must be non-null");
+            }
+
             if (child.getParent() instanceof ViewGroup) {
                 ViewGroup parent = (ViewGroup) child.getParent();
                 if (parent != mHostView && parent.getParent() != null &&
@@ -190,7 +205,11 @@
             super.addView(child);
         }
 
-        public void remove(View view) {
+        public void remove(@NonNull View view) {
+            if (view == null) {
+                throw new IllegalArgumentException("view must be non-null");
+            }
+
             super.removeView(view);
         }
 
@@ -210,7 +229,7 @@
         }
 
         @Override
-        public void invalidateDrawable(Drawable drawable) {
+        public void invalidateDrawable(@NonNull Drawable drawable) {
             invalidate(drawable.getBounds());
         }
 
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index b9eb0a9..f7405e2 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -1077,7 +1077,11 @@
             if (!mStopped) {
                 scheduleTraversals();
             } else {
-                destroyHardwareResources();
+                if (mAttachInfo.mHardwareRenderer != null) {
+                    if (DEBUG_DRAW) Log.d(mTag, "WindowStopped on " + getTitle());
+                    mAttachInfo.mHardwareRenderer.updateSurface(null);
+                    mAttachInfo.mHardwareRenderer.destroyHardwareResources(mView);
+                }
             }
         }
     }
@@ -4393,8 +4397,14 @@
     private boolean updatePointerIcon(MotionEvent event) {
         final float x = event.getX();
         final float y = event.getY();
+        if (mView == null) {
+            // E.g. click outside a popup to dismiss it
+            Slog.d(mTag, "updatePointerIcon called after view was removed");
+            return false;
+        }
         if (x < 0 || x >= mView.getWidth() || y < 0 || y >= mView.getHeight()) {
-            Slog.e(mTag, "updatePointerIcon called with position out of bounds");
+            // E.g. when moving window divider with mouse
+            Slog.d(mTag, "updatePointerIcon called with position out of bounds");
             return false;
         }
         final PointerIcon pointerIcon = mView.getPointerIcon(event, x, y);
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index 6e02516..17f1991 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -135,6 +135,18 @@
     }
 
     /**
+     * Message for taking fullscreen screenshot
+     * @hide
+     */
+    final int TAKE_SCREENSHOT_FULLSCREEN = 1;
+
+    /**
+     * Message for taking screenshot of selected region.
+     * @hide
+     */
+    final int TAKE_SCREENSHOT_SELECTED_REGION = 2;
+
+    /**
      * @hide
      */
     public static final String PARCEL_KEY_SHORTCUTS_ARRAY = "shortcuts_array";
@@ -269,6 +281,7 @@
             @ViewDebug.IntToString(from = TYPE_VOICE_INTERACTION_STARTING, to = "TYPE_VOICE_INTERACTION_STARTING"),
             @ViewDebug.IntToString(from = TYPE_DOCK_DIVIDER, to = "TYPE_DOCK_DIVIDER"),
             @ViewDebug.IntToString(from = TYPE_QS_DIALOG, to = "TYPE_QS_DIALOG"),
+            @ViewDebug.IntToString(from = TYPE_SCREENSHOT, to = "TYPE_SCREENSHOT")
         })
         public int type;
 
@@ -622,6 +635,13 @@
         public static final int TYPE_QS_DIALOG = FIRST_SYSTEM_WINDOW+35;
 
         /**
+         * Window type: shares similar characteristics with {@link #TYPE_DREAM}. The layer is
+         * reserved for screenshot region selection.
+         * @hide
+         */
+        public static final int TYPE_SCREENSHOT = FIRST_SYSTEM_WINDOW + 36;
+
+        /**
          * End of types of system windows.
          */
         public static final int LAST_SYSTEM_WINDOW      = 2999;
diff --git a/core/java/android/view/WindowManagerPolicy.java b/core/java/android/view/WindowManagerPolicy.java
index 2fbfd2d..b011414 100644
--- a/core/java/android/view/WindowManagerPolicy.java
+++ b/core/java/android/view/WindowManagerPolicy.java
@@ -29,7 +29,9 @@
 import android.os.Bundle;
 import android.os.IBinder;
 import android.os.Looper;
+import android.os.RemoteException;
 import android.view.animation.Animation;
+import com.android.internal.policy.IShortcutService;
 
 import java.io.PrintWriter;
 import java.lang.annotation.Retention;
@@ -121,6 +123,14 @@
     public final static int ACTION_PASS_TO_USER = 0x00000001;
 
     /**
+     * Register shortcuts for window manager to dispatch.
+     * Shortcut code is packed as (metaState << Integer.SIZE) | keyCode
+     * @hide
+     */
+    void registerShortcutKey(long shortcutCode, IShortcutService shortcutKeyReceiver)
+            throws RemoteException;
+
+    /**
      * Interface to the Window Manager state associated with a particular
      * window.  You can hold on to an instance of this interface from the call
      * to prepareAddWindow() until removeWindow().
diff --git a/core/java/android/view/inputmethod/InputConnectionWrapper.java b/core/java/android/view/inputmethod/InputConnectionWrapper.java
index 65c7654..42d1442 100644
--- a/core/java/android/view/inputmethod/InputConnectionWrapper.java
+++ b/core/java/android/view/inputmethod/InputConnectionWrapper.java
@@ -21,13 +21,22 @@
 import android.view.KeyEvent;
 
 /**
- * <p>Wrapper class for proxying calls to another InputConnection.  Subclass
- * and have fun!
+ * <p>Wrapper class for proxying calls to another InputConnection.  Subclass and have fun!
  */
 public class InputConnectionWrapper implements InputConnection {
     private InputConnection mTarget;
     final boolean mMutable;
-    
+
+    /**
+     * Initializes a wrapper.
+     *
+     * <p><b>Caveat:</b> Although the system can accept {@code (InputConnection) null} in some
+     * places, you cannot emulate such a behavior by non-null {@link InputConnectionWrapper} that
+     * has {@code null} in {@code target}.</p>
+     * @param target the {@link InputConnection} to be proxied.
+     * @param mutable set {@code true} to protect this object from being reconfigured to target
+     * another {@link InputConnection}.  Note that this is ignored while the target is {@code null}.
+     */
     public InputConnectionWrapper(InputConnection target, boolean mutable) {
         mMutable = mutable;
         mTarget = target;
@@ -35,6 +44,12 @@
 
     /**
      * Change the target of the input connection.
+     *
+     * <p><b>Caveat:</b> Although the system can accept {@code (InputConnection) null} in some
+     * places, you cannot emulate such a behavior by non-null {@link InputConnectionWrapper} that
+     * has {@code null} in {@code target}.</p>
+     * @param target the {@link InputConnection} to be proxied.
+     * @throws SecurityException when this wrapper has non-null target and is immutable.
      */
     public void setTarget(InputConnection target) {
         if (mTarget != null && !mMutable) {
@@ -42,99 +57,195 @@
         }
         mTarget = target;
     }
-    
+
+    /**
+     * {@inheritDoc}
+     * @throws NullPointerException if the target is {@code null}.
+     */
     public CharSequence getTextBeforeCursor(int n, int flags) {
         return mTarget.getTextBeforeCursor(n, flags);
     }
-    
+
+    /**
+     * {@inheritDoc}
+     * @throws NullPointerException if the target is {@code null}.
+     */
     public CharSequence getTextAfterCursor(int n, int flags) {
         return mTarget.getTextAfterCursor(n, flags);
     }
 
+    /**
+     * {@inheritDoc}
+     * @throws NullPointerException if the target is {@code null}.
+     */
     public CharSequence getSelectedText(int flags) {
         return mTarget.getSelectedText(flags);
     }
 
+    /**
+     * {@inheritDoc}
+     * @throws NullPointerException if the target is {@code null}.
+     */
     public int getCursorCapsMode(int reqModes) {
         return mTarget.getCursorCapsMode(reqModes);
     }
-    
+
+    /**
+     * {@inheritDoc}
+     * @throws NullPointerException if the target is {@code null}.
+     */
     public ExtractedText getExtractedText(ExtractedTextRequest request, int flags) {
         return mTarget.getExtractedText(request, flags);
     }
 
+    /**
+     * {@inheritDoc}
+     * @throws NullPointerException if the target is {@code null}.
+     */
     public boolean deleteSurroundingTextInCodePoints(int beforeLength, int afterLength) {
         return mTarget.deleteSurroundingTextInCodePoints(beforeLength, afterLength);
     }
 
+    /**
+     * {@inheritDoc}
+     * @throws NullPointerException if the target is {@code null}.
+     */
     public boolean deleteSurroundingText(int beforeLength, int afterLength) {
         return mTarget.deleteSurroundingText(beforeLength, afterLength);
     }
 
+    /**
+     * {@inheritDoc}
+     * @throws NullPointerException if the target is {@code null}.
+     */
     public boolean setComposingText(CharSequence text, int newCursorPosition) {
         return mTarget.setComposingText(text, newCursorPosition);
     }
 
+    /**
+     * {@inheritDoc}
+     * @throws NullPointerException if the target is {@code null}.
+     */
     public boolean setComposingRegion(int start, int end) {
         return mTarget.setComposingRegion(start, end);
     }
 
+    /**
+     * {@inheritDoc}
+     * @throws NullPointerException if the target is {@code null}.
+     */
     public boolean finishComposingText() {
         return mTarget.finishComposingText();
     }
-    
+
+    /**
+     * {@inheritDoc}
+     * @throws NullPointerException if the target is {@code null}.
+     */
     public boolean commitText(CharSequence text, int newCursorPosition) {
         return mTarget.commitText(text, newCursorPosition);
     }
 
+    /**
+     * {@inheritDoc}
+     * @throws NullPointerException if the target is {@code null}.
+     */
     public boolean commitCompletion(CompletionInfo text) {
         return mTarget.commitCompletion(text);
     }
 
+    /**
+     * {@inheritDoc}
+     * @throws NullPointerException if the target is {@code null}.
+     */
     public boolean commitCorrection(CorrectionInfo correctionInfo) {
         return mTarget.commitCorrection(correctionInfo);
     }
 
+    /**
+     * {@inheritDoc}
+     * @throws NullPointerException if the target is {@code null}.
+     */
     public boolean setSelection(int start, int end) {
         return mTarget.setSelection(start, end);
     }
-    
+
+    /**
+     * {@inheritDoc}
+     * @throws NullPointerException if the target is {@code null}.
+     */
     public boolean performEditorAction(int editorAction) {
         return mTarget.performEditorAction(editorAction);
     }
-    
+
+    /**
+     * {@inheritDoc}
+     * @throws NullPointerException if the target is {@code null}.
+     */
     public boolean performContextMenuAction(int id) {
         return mTarget.performContextMenuAction(id);
     }
-    
+
+    /**
+     * {@inheritDoc}
+     * @throws NullPointerException if the target is {@code null}.
+     */
     public boolean beginBatchEdit() {
         return mTarget.beginBatchEdit();
     }
-    
+
+    /**
+     * {@inheritDoc}
+     * @throws NullPointerException if the target is {@code null}.
+     */
     public boolean endBatchEdit() {
         return mTarget.endBatchEdit();
     }
-    
+
+    /**
+     * {@inheritDoc}
+     * @throws NullPointerException if the target is {@code null}.
+     */
     public boolean sendKeyEvent(KeyEvent event) {
         return mTarget.sendKeyEvent(event);
     }
 
+    /**
+     * {@inheritDoc}
+     * @throws NullPointerException if the target is {@code null}.
+     */
     public boolean clearMetaKeyStates(int states) {
         return mTarget.clearMetaKeyStates(states);
     }
-    
+
+    /**
+     * {@inheritDoc}
+     * @throws NullPointerException if the target is {@code null}.
+     */
     public boolean reportFullscreenMode(boolean enabled) {
         return mTarget.reportFullscreenMode(enabled);
     }
-    
+
+    /**
+     * {@inheritDoc}
+     * @throws NullPointerException if the target is {@code null}.
+     */
     public boolean performPrivateCommand(String action, Bundle data) {
         return mTarget.performPrivateCommand(action, data);
     }
 
+    /**
+     * {@inheritDoc}
+     * @throws NullPointerException if the target is {@code null}.
+     */
     public boolean requestCursorUpdates(int cursorUpdateMode) {
         return mTarget.requestCursorUpdates(cursorUpdateMode);
     }
 
+    /**
+     * {@inheritDoc}
+     * @throws NullPointerException if the target is {@code null}.
+     */
     public Handler getHandler() {
         return mTarget.getHandler();
     }
diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java
index 4c015ba..859df43 100644
--- a/core/java/android/view/inputmethod/InputMethodManager.java
+++ b/core/java/android/view/inputmethod/InputMethodManager.java
@@ -664,7 +664,7 @@
         try {
             return mService.getInputMethodList();
         } catch (RemoteException e) {
-            throw new RuntimeException(e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -672,7 +672,7 @@
         try {
             return mService.getEnabledInputMethodList();
         } catch (RemoteException e) {
-            throw new RuntimeException(e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -689,7 +689,7 @@
             return mService.getEnabledInputMethodSubtypeList(
                     imi == null ? null : imi.getId(), allowsImplicitlySelectedSubtypes);
         } catch (RemoteException e) {
-            throw new RuntimeException(e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -697,7 +697,7 @@
         try {
             mService.updateStatusIcon(imeToken, packageName, iconId);
         } catch (RemoteException e) {
-            throw new RuntimeException(e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -705,7 +705,7 @@
         try {
             mService.updateStatusIcon(imeToken, null, 0);
         } catch (RemoteException e) {
-            throw new RuntimeException(e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -714,7 +714,7 @@
         try {
             mService.setImeWindowStatus(imeToken, vis, backDisposition);
         } catch (RemoteException e) {
-            throw new RuntimeException(e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -728,7 +728,7 @@
         try {
             mService.registerSuggestionSpansForNotification(spans);
         } catch (RemoteException e) {
-            throw new RuntimeException(e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -737,7 +737,7 @@
         try {
             mService.notifySuggestionPicked(span, originalString, index);
         } catch (RemoteException e) {
-            throw new RuntimeException(e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -833,6 +833,7 @@
                 try {
                     mService.finishInput(mClient);
                 } catch (RemoteException e) {
+                    throw e.rethrowFromSystemServer();
                 }
             }
             notifyInputConnectionFinished();
@@ -996,9 +997,8 @@
             try {
                 return mService.showSoftInput(mClient, flags, resultReceiver);
             } catch (RemoteException e) {
+                throw e.rethrowFromSystemServer();
             }
-            
-            return false;
         }
     }
     
@@ -1007,6 +1007,7 @@
         try {
             mService.showSoftInput(mClient, flags, resultReceiver);
         } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
         }
     }
     
@@ -1065,8 +1066,8 @@
             try {
                 return mService.hideSoftInput(mClient, flags, resultReceiver);
             } catch (RemoteException e) {
+                throw e.rethrowFromSystemServer();
             }
-            return false;
         }
     }
     
@@ -1421,6 +1422,7 @@
         try {
             mService.hideSoftInput(mClient, HIDE_NOT_ALWAYS, null);
         } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1476,6 +1478,7 @@
                         rootView.getWindowToken(), controlFlags, softInputMode, windowFlags, null,
                         null);
             } catch (RemoteException e) {
+                throw e.rethrowFromSystemServer();
             }
         }
     }
@@ -1716,7 +1719,7 @@
         try {
             mService.setInputMethod(token, id);
         } catch (RemoteException e) {
-            throw new RuntimeException(e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1733,7 +1736,7 @@
         try {
             mService.setInputMethodAndSubtype(token, id, subtype);
         } catch (RemoteException e) {
-            throw new RuntimeException(e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1753,7 +1756,7 @@
         try {
             mService.hideMySoftInput(token, flags);
         } catch (RemoteException e) {
-            throw new RuntimeException(e);
+            throw e.rethrowFromSystemServer();
         }
     }
     
@@ -1774,7 +1777,7 @@
         try {
             mService.showMySoftInput(token, flags);
         } catch (RemoteException e) {
-            throw new RuntimeException(e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1980,7 +1983,7 @@
                         SHOW_IM_PICKER_MODE_EXCLUDE_AUXILIARY_SUBTYPES;
                 mService.showInputMethodPickerFromClient(mClient, mode);
             } catch (RemoteException e) {
-                Log.w(TAG, "IME died: " + mCurId, e);
+                throw e.rethrowFromSystemServer();
             }
         }
     }
@@ -1989,7 +1992,7 @@
         try {
             mService.showInputMethodPickerFromClient(mClient, SHOW_IM_PICKER_MODE_AUTO);
         } catch (RemoteException e) {
-            Log.w(TAG, "IME died: " + mCurId, e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -2003,7 +2006,7 @@
             try {
                 mService.showInputMethodAndSubtypeEnablerFromClient(mClient, imiId);
             } catch (RemoteException e) {
-                Log.w(TAG, "IME died: " + mCurId, e);
+                throw e.rethrowFromSystemServer();
             }
         }
     }
@@ -2018,8 +2021,7 @@
             try {
                 return mService.getCurrentInputMethodSubtype();
             } catch (RemoteException e) {
-                Log.w(TAG, "IME died: " + mCurId, e);
-                return null;
+                throw e.rethrowFromSystemServer();
             }
         }
     }
@@ -2036,8 +2038,7 @@
             try {
                 return mService.setCurrentInputMethodSubtype(subtype);
             } catch (RemoteException e) {
-                Log.w(TAG, "IME died: " + mCurId, e);
-                return false;
+                throw e.rethrowFromSystemServer();
             }
         }
     }
@@ -2071,7 +2072,7 @@
                 mLastSentUserActionNotificationSequenceNumber =
                         mNextUserActionNotificationSequenceNumber;
             } catch (RemoteException e) {
-                Log.w(TAG, "IME died: " + mCurId, e);
+                throw e.rethrowFromSystemServer();
             }
         }
     }
@@ -2104,7 +2105,7 @@
                     }
                 }
             } catch (RemoteException e) {
-                Log.w(TAG, "IME died: " + mCurId, e);
+                throw e.rethrowFromSystemServer();
             }
             return ret;
         }
@@ -2119,8 +2120,7 @@
             try {
                 return mService.getInputMethodWindowVisibleHeight();
             } catch (RemoteException e) {
-                Log.w(TAG, "IME died: " + mCurId, e);
-                return 0;
+                throw e.rethrowFromSystemServer();
             }
         }
     }
@@ -2139,8 +2139,7 @@
             try {
                 return mService.switchToLastInputMethod(imeToken);
             } catch (RemoteException e) {
-                Log.w(TAG, "IME died: " + mCurId, e);
-                return false;
+                throw e.rethrowFromSystemServer();
             }
         }
     }
@@ -2160,8 +2159,7 @@
             try {
                 return mService.switchToNextInputMethod(imeToken, onlyCurrentIme);
             } catch (RemoteException e) {
-                Log.w(TAG, "IME died: " + mCurId, e);
-                return false;
+                throw e.rethrowFromSystemServer();
             }
         }
     }
@@ -2182,8 +2180,7 @@
             try {
                 return mService.shouldOfferSwitchingToNextInputMethod(imeToken);
             } catch (RemoteException e) {
-                Log.w(TAG, "IME died: " + mCurId, e);
-                return false;
+                throw e.rethrowFromSystemServer();
             }
         }
     }
@@ -2218,7 +2215,7 @@
             try {
                 mService.setAdditionalInputMethodSubtypes(imiId, subtypes);
             } catch (RemoteException e) {
-                Log.w(TAG, "IME died: " + mCurId, e);
+                throw e.rethrowFromSystemServer();
             }
         }
     }
@@ -2228,8 +2225,7 @@
             try {
                 return mService.getLastInputMethodSubtype();
             } catch (RemoteException e) {
-                Log.w(TAG, "IME died: " + mCurId, e);
-                return null;
+                throw e.rethrowFromSystemServer();
             }
         }
     }
diff --git a/core/java/android/view/textservice/SpellCheckerInfo.java b/core/java/android/view/textservice/SpellCheckerInfo.java
index 471b6d4..fc17f7a 100644
--- a/core/java/android/view/textservice/SpellCheckerInfo.java
+++ b/core/java/android/view/textservice/SpellCheckerInfo.java
@@ -31,10 +31,12 @@
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.util.AttributeSet;
+import android.util.PrintWriterPrinter;
 import android.util.Slog;
 import android.util.Xml;
 
 import java.io.IOException;
+import java.io.PrintWriter;
 import java.util.ArrayList;
 
 /**
@@ -55,7 +57,7 @@
     /**
      * The array of subtypes.
      */
-    private final ArrayList<SpellCheckerSubtype> mSubtypes = new ArrayList<SpellCheckerSubtype>();
+    private final ArrayList<SpellCheckerSubtype> mSubtypes = new ArrayList<>();
 
     /**
      * Constructor.
@@ -267,4 +269,22 @@
     public int describeContents() {
         return 0;
     }
+
+    /**
+     * @hide
+     */
+    public void dump(final PrintWriter pw, final String prefix) {
+        pw.println(prefix + "mId=" + mId);
+        pw.println(prefix + "mSettingsActivityName=" + mSettingsActivityName);
+        pw.println(prefix + "Service:");
+        mService.dump(new PrintWriterPrinter(pw), prefix + "  ");
+        final int N = getSubtypeCount();
+        for (int i = 0; i < N; i++) {
+            final SpellCheckerSubtype st = getSubtypeAt(i);
+            pw.println(prefix + "  " + "Subtype #" + i + ":");
+            pw.println(prefix + "    " + "locale=" + st.getLocale()
+                    + " languageTag=" + st.getLanguageTag());
+            pw.println(prefix + "    " + "extraValue=" + st.getExtraValue());
+        }
+    }
 }
diff --git a/core/java/android/webkit/WebViewFactory.java b/core/java/android/webkit/WebViewFactory.java
index ad50ff6..3d72260 100644
--- a/core/java/android/webkit/WebViewFactory.java
+++ b/core/java/android/webkit/WebViewFactory.java
@@ -262,11 +262,11 @@
                         "For security reasons, WebView is not allowed in privileged processes");
             }
 
+            StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads();
             Trace.traceBegin(Trace.TRACE_TAG_WEBVIEW, "WebViewFactory.getProvider()");
             try {
                 Class<WebViewFactoryProvider> providerClass = getProviderClass();
 
-                StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads();
                 Trace.traceBegin(Trace.TRACE_TAG_WEBVIEW, "providerClass.newInstance()");
                 try {
                     sProviderInstance = providerClass.getConstructor(WebViewDelegate.class)
@@ -278,10 +278,10 @@
                     throw new AndroidRuntimeException(e);
                 } finally {
                     Trace.traceEnd(Trace.TRACE_TAG_WEBVIEW);
-                    StrictMode.setThreadPolicy(oldPolicy);
                 }
             } finally {
                 Trace.traceEnd(Trace.TRACE_TAG_WEBVIEW);
+                StrictMode.setThreadPolicy(oldPolicy);
             }
         }
     }
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index 496f7ee..7cbe8de 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -2864,7 +2864,7 @@
     }
 
     @Override
-    public boolean verifyDrawable(Drawable dr) {
+    public boolean verifyDrawable(@NonNull Drawable dr) {
         return mSelector == dr || super.verifyDrawable(dr);
     }
 
@@ -3078,7 +3078,8 @@
             final int motionPosition = mClickMotionPosition;
             if (adapter != null && mItemCount > 0 &&
                     motionPosition != INVALID_POSITION &&
-                    motionPosition < adapter.getCount() && sameWindow()) {
+                    motionPosition < adapter.getCount() && sameWindow() &&
+                    adapter.isEnabled(motionPosition)) {
                 final View view = getChildAt(motionPosition - mFirstPosition);
                 // If there is no view, something bad happened (the view scrolled off the
                 // screen, etc.) and we should cancel the click
diff --git a/core/java/android/widget/AbsSeekBar.java b/core/java/android/widget/AbsSeekBar.java
index 34f3a47..878a9eb 100644
--- a/core/java/android/widget/AbsSeekBar.java
+++ b/core/java/android/widget/AbsSeekBar.java
@@ -18,6 +18,7 @@
 
 import com.android.internal.R;
 
+import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.content.Context;
 import android.content.res.ColorStateList;
@@ -485,7 +486,7 @@
     }
 
     @Override
-    protected boolean verifyDrawable(Drawable who) {
+    protected boolean verifyDrawable(@NonNull Drawable who) {
         return who == mThumb || who == mTickMark || super.verifyDrawable(who);
     }
 
diff --git a/core/java/android/widget/CheckedTextView.java b/core/java/android/widget/CheckedTextView.java
index 9f94005..df506ca 100644
--- a/core/java/android/widget/CheckedTextView.java
+++ b/core/java/android/widget/CheckedTextView.java
@@ -308,7 +308,7 @@
     }
 
     @Override
-    protected boolean verifyDrawable(Drawable who) {
+    protected boolean verifyDrawable(@NonNull Drawable who) {
         return who == mCheckMarkDrawable || super.verifyDrawable(who);
     }
 
diff --git a/core/java/android/widget/CompoundButton.java b/core/java/android/widget/CompoundButton.java
index b19fe17..5d7585f 100644
--- a/core/java/android/widget/CompoundButton.java
+++ b/core/java/android/widget/CompoundButton.java
@@ -474,7 +474,7 @@
     }
 
     @Override
-    protected boolean verifyDrawable(Drawable who) {
+    protected boolean verifyDrawable(@NonNull Drawable who) {
         return super.verifyDrawable(who) || who == mButtonDrawable;
     }
 
diff --git a/core/java/android/widget/DatePicker.java b/core/java/android/widget/DatePicker.java
index 87bee44..6e3dbd8 100644
--- a/core/java/android/widget/DatePicker.java
+++ b/core/java/android/widget/DatePicker.java
@@ -23,32 +23,17 @@
 import android.content.res.TypedArray;
 import android.os.Parcel;
 import android.os.Parcelable;
-import android.text.TextUtils;
-import android.text.InputType;
-import android.text.format.DateFormat;
-import android.text.format.DateUtils;
 import android.util.AttributeSet;
-import android.util.Log;
 import android.util.SparseArray;
-import android.view.LayoutInflater;
 import android.view.View;
 import android.view.accessibility.AccessibilityEvent;
-import android.view.inputmethod.EditorInfo;
-import android.view.inputmethod.InputMethodManager;
-import android.widget.NumberPicker.OnValueChangeListener;
 
 import com.android.internal.R;
 
-import java.text.DateFormatSymbols;
-import java.text.ParseException;
-import java.text.SimpleDateFormat;
-import java.util.Arrays;
 import java.util.Calendar;
 import java.util.Locale;
 import java.util.TimeZone;
 
-import libcore.icu.ICU;
-
 /**
  * Provides a widget for selecting a date.
  * <p>
@@ -527,6 +512,114 @@
         protected void onLocaleChanged(Locale locale) {
             // Stub.
         }
+
+        /**
+         * Class for managing state storing/restoring.
+         */
+        static class SavedState extends View.BaseSavedState {
+            private final int mSelectedYear;
+            private final int mSelectedMonth;
+            private final int mSelectedDay;
+            private final long mMinDate;
+            private final long mMaxDate;
+            private final int mCurrentView;
+            private final int mListPosition;
+            private final int mListPositionOffset;
+
+            public SavedState(Parcelable superState, int year, int month, int day, long minDate,
+                    long maxDate) {
+                this(superState, year, month, day, minDate, maxDate, 0, 0, 0);
+            }
+
+            /**
+             * Constructor called from {@link DatePicker#onSaveInstanceState()}
+             */
+            public SavedState(Parcelable superState, int year, int month, int day, long minDate,
+                    long maxDate, int currentView, int listPosition, int listPositionOffset) {
+                super(superState);
+                mSelectedYear = year;
+                mSelectedMonth = month;
+                mSelectedDay = day;
+                mMinDate = minDate;
+                mMaxDate = maxDate;
+                mCurrentView = currentView;
+                mListPosition = listPosition;
+                mListPositionOffset = listPositionOffset;
+            }
+
+            /**
+             * Constructor called from {@link #CREATOR}
+             */
+            private SavedState(Parcel in) {
+                super(in);
+                mSelectedYear = in.readInt();
+                mSelectedMonth = in.readInt();
+                mSelectedDay = in.readInt();
+                mMinDate = in.readLong();
+                mMaxDate = in.readLong();
+                mCurrentView = in.readInt();
+                mListPosition = in.readInt();
+                mListPositionOffset = in.readInt();
+            }
+
+            @Override
+            public void writeToParcel(Parcel dest, int flags) {
+                super.writeToParcel(dest, flags);
+                dest.writeInt(mSelectedYear);
+                dest.writeInt(mSelectedMonth);
+                dest.writeInt(mSelectedDay);
+                dest.writeLong(mMinDate);
+                dest.writeLong(mMaxDate);
+                dest.writeInt(mCurrentView);
+                dest.writeInt(mListPosition);
+                dest.writeInt(mListPositionOffset);
+            }
+
+            public int getSelectedDay() {
+                return mSelectedDay;
+            }
+
+            public int getSelectedMonth() {
+                return mSelectedMonth;
+            }
+
+            public int getSelectedYear() {
+                return mSelectedYear;
+            }
+
+            public long getMinDate() {
+                return mMinDate;
+            }
+
+            public long getMaxDate() {
+                return mMaxDate;
+            }
+
+            public int getCurrentView() {
+                return mCurrentView;
+            }
+
+            public int getListPosition() {
+                return mListPosition;
+            }
+
+            public int getListPositionOffset() {
+                return mListPositionOffset;
+            }
+
+            @SuppressWarnings("all")
+            // suppress unused and hiding
+            public static final Parcelable.Creator<SavedState> CREATOR = new Creator<SavedState>() {
+
+                public SavedState createFromParcel(Parcel in) {
+                    return new SavedState(in);
+                }
+
+                public SavedState[] newArray(int size) {
+                    return new SavedState[size];
+                }
+            };
+        }
     }
 
     /**
@@ -535,666 +628,7 @@
      *
      * @hide
      */
-    public static interface ValidationCallback {
+    public interface ValidationCallback {
         void onValidationChanged(boolean valid);
     }
-
-    /**
-     * A delegate implementing the basic DatePicker
-     */
-    private static class DatePickerSpinnerDelegate extends AbstractDatePickerDelegate {
-
-        private static final String DATE_FORMAT = "MM/dd/yyyy";
-
-        private static final int DEFAULT_START_YEAR = 1900;
-
-        private static final int DEFAULT_END_YEAR = 2100;
-
-        private static final boolean DEFAULT_CALENDAR_VIEW_SHOWN = true;
-
-        private static final boolean DEFAULT_SPINNERS_SHOWN = true;
-
-        private static final boolean DEFAULT_ENABLED_STATE = true;
-
-        private final LinearLayout mSpinners;
-
-        private final NumberPicker mDaySpinner;
-
-        private final NumberPicker mMonthSpinner;
-
-        private final NumberPicker mYearSpinner;
-
-        private final EditText mDaySpinnerInput;
-
-        private final EditText mMonthSpinnerInput;
-
-        private final EditText mYearSpinnerInput;
-
-        private final CalendarView mCalendarView;
-
-        private String[] mShortMonths;
-
-        private final java.text.DateFormat mDateFormat = new SimpleDateFormat(DATE_FORMAT);
-
-        private int mNumberOfMonths;
-
-        private Calendar mTempDate;
-
-        private Calendar mMinDate;
-
-        private Calendar mMaxDate;
-
-        private Calendar mCurrentDate;
-
-        private boolean mIsEnabled = DEFAULT_ENABLED_STATE;
-
-        DatePickerSpinnerDelegate(DatePicker delegator, Context context, AttributeSet attrs,
-                int defStyleAttr, int defStyleRes) {
-            super(delegator, context);
-
-            mDelegator = delegator;
-            mContext = context;
-
-            // initialization based on locale
-            setCurrentLocale(Locale.getDefault());
-
-            final TypedArray attributesArray = context.obtainStyledAttributes(attrs,
-                    R.styleable.DatePicker, defStyleAttr, defStyleRes);
-            boolean spinnersShown = attributesArray.getBoolean(R.styleable.DatePicker_spinnersShown,
-                    DEFAULT_SPINNERS_SHOWN);
-            boolean calendarViewShown = attributesArray.getBoolean(
-                    R.styleable.DatePicker_calendarViewShown, DEFAULT_CALENDAR_VIEW_SHOWN);
-            int startYear = attributesArray.getInt(R.styleable.DatePicker_startYear,
-                    DEFAULT_START_YEAR);
-            int endYear = attributesArray.getInt(R.styleable.DatePicker_endYear, DEFAULT_END_YEAR);
-            String minDate = attributesArray.getString(R.styleable.DatePicker_minDate);
-            String maxDate = attributesArray.getString(R.styleable.DatePicker_maxDate);
-            int layoutResourceId = attributesArray.getResourceId(
-                    R.styleable.DatePicker_legacyLayout, R.layout.date_picker_legacy);
-            attributesArray.recycle();
-
-            LayoutInflater inflater = (LayoutInflater) context
-                    .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
-            inflater.inflate(layoutResourceId, mDelegator, true);
-
-            OnValueChangeListener onChangeListener = new OnValueChangeListener() {
-                public void onValueChange(NumberPicker picker, int oldVal, int newVal) {
-                    updateInputState();
-                    mTempDate.setTimeInMillis(mCurrentDate.getTimeInMillis());
-                    // take care of wrapping of days and months to update greater fields
-                    if (picker == mDaySpinner) {
-                        int maxDayOfMonth = mTempDate.getActualMaximum(Calendar.DAY_OF_MONTH);
-                        if (oldVal == maxDayOfMonth && newVal == 1) {
-                            mTempDate.add(Calendar.DAY_OF_MONTH, 1);
-                        } else if (oldVal == 1 && newVal == maxDayOfMonth) {
-                            mTempDate.add(Calendar.DAY_OF_MONTH, -1);
-                        } else {
-                            mTempDate.add(Calendar.DAY_OF_MONTH, newVal - oldVal);
-                        }
-                    } else if (picker == mMonthSpinner) {
-                        if (oldVal == 11 && newVal == 0) {
-                            mTempDate.add(Calendar.MONTH, 1);
-                        } else if (oldVal == 0 && newVal == 11) {
-                            mTempDate.add(Calendar.MONTH, -1);
-                        } else {
-                            mTempDate.add(Calendar.MONTH, newVal - oldVal);
-                        }
-                    } else if (picker == mYearSpinner) {
-                        mTempDate.set(Calendar.YEAR, newVal);
-                    } else {
-                        throw new IllegalArgumentException();
-                    }
-                    // now set the date to the adjusted one
-                    setDate(mTempDate.get(Calendar.YEAR), mTempDate.get(Calendar.MONTH),
-                            mTempDate.get(Calendar.DAY_OF_MONTH));
-                    updateSpinners();
-                    updateCalendarView();
-                    notifyDateChanged();
-                }
-            };
-
-            mSpinners = (LinearLayout) mDelegator.findViewById(R.id.pickers);
-
-            // calendar view day-picker
-            mCalendarView = (CalendarView) mDelegator.findViewById(R.id.calendar_view);
-            mCalendarView.setOnDateChangeListener(new CalendarView.OnDateChangeListener() {
-                public void onSelectedDayChange(CalendarView view, int year, int month, int monthDay) {
-                    setDate(year, month, monthDay);
-                    updateSpinners();
-                    notifyDateChanged();
-                }
-            });
-
-            // day
-            mDaySpinner = (NumberPicker) mDelegator.findViewById(R.id.day);
-            mDaySpinner.setFormatter(NumberPicker.getTwoDigitFormatter());
-            mDaySpinner.setOnLongPressUpdateInterval(100);
-            mDaySpinner.setOnValueChangedListener(onChangeListener);
-            mDaySpinnerInput = (EditText) mDaySpinner.findViewById(R.id.numberpicker_input);
-
-            // month
-            mMonthSpinner = (NumberPicker) mDelegator.findViewById(R.id.month);
-            mMonthSpinner.setMinValue(0);
-            mMonthSpinner.setMaxValue(mNumberOfMonths - 1);
-            mMonthSpinner.setDisplayedValues(mShortMonths);
-            mMonthSpinner.setOnLongPressUpdateInterval(200);
-            mMonthSpinner.setOnValueChangedListener(onChangeListener);
-            mMonthSpinnerInput = (EditText) mMonthSpinner.findViewById(R.id.numberpicker_input);
-
-            // year
-            mYearSpinner = (NumberPicker) mDelegator.findViewById(R.id.year);
-            mYearSpinner.setOnLongPressUpdateInterval(100);
-            mYearSpinner.setOnValueChangedListener(onChangeListener);
-            mYearSpinnerInput = (EditText) mYearSpinner.findViewById(R.id.numberpicker_input);
-
-            // show only what the user required but make sure we
-            // show something and the spinners have higher priority
-            if (!spinnersShown && !calendarViewShown) {
-                setSpinnersShown(true);
-            } else {
-                setSpinnersShown(spinnersShown);
-                setCalendarViewShown(calendarViewShown);
-            }
-
-            // set the min date giving priority of the minDate over startYear
-            mTempDate.clear();
-            if (!TextUtils.isEmpty(minDate)) {
-                if (!parseDate(minDate, mTempDate)) {
-                    mTempDate.set(startYear, 0, 1);
-                }
-            } else {
-                mTempDate.set(startYear, 0, 1);
-            }
-            setMinDate(mTempDate.getTimeInMillis());
-
-            // set the max date giving priority of the maxDate over endYear
-            mTempDate.clear();
-            if (!TextUtils.isEmpty(maxDate)) {
-                if (!parseDate(maxDate, mTempDate)) {
-                    mTempDate.set(endYear, 11, 31);
-                }
-            } else {
-                mTempDate.set(endYear, 11, 31);
-            }
-            setMaxDate(mTempDate.getTimeInMillis());
-
-            // initialize to current date
-            mCurrentDate.setTimeInMillis(System.currentTimeMillis());
-            init(mCurrentDate.get(Calendar.YEAR), mCurrentDate.get(Calendar.MONTH), mCurrentDate
-                    .get(Calendar.DAY_OF_MONTH), null);
-
-            // re-order the number spinners to match the current date format
-            reorderSpinners();
-
-            // accessibility
-            setContentDescriptions();
-
-            // If not explicitly specified this view is important for accessibility.
-            if (mDelegator.getImportantForAccessibility() == IMPORTANT_FOR_ACCESSIBILITY_AUTO) {
-                mDelegator.setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES);
-            }
-        }
-
-        @Override
-        public void init(int year, int monthOfYear, int dayOfMonth,
-                         OnDateChangedListener onDateChangedListener) {
-            setDate(year, monthOfYear, dayOfMonth);
-            updateSpinners();
-            updateCalendarView();
-            mOnDateChangedListener = onDateChangedListener;
-        }
-
-        @Override
-        public void updateDate(int year, int month, int dayOfMonth) {
-            if (!isNewDate(year, month, dayOfMonth)) {
-                return;
-            }
-            setDate(year, month, dayOfMonth);
-            updateSpinners();
-            updateCalendarView();
-            notifyDateChanged();
-        }
-
-        @Override
-        public int getYear() {
-            return mCurrentDate.get(Calendar.YEAR);
-        }
-
-        @Override
-        public int getMonth() {
-            return mCurrentDate.get(Calendar.MONTH);
-        }
-
-        @Override
-        public int getDayOfMonth() {
-            return mCurrentDate.get(Calendar.DAY_OF_MONTH);
-        }
-
-        @Override
-        public void setFirstDayOfWeek(int firstDayOfWeek) {
-            mCalendarView.setFirstDayOfWeek(firstDayOfWeek);
-        }
-
-        @Override
-        public int getFirstDayOfWeek() {
-            return mCalendarView.getFirstDayOfWeek();
-        }
-
-        @Override
-        public void setMinDate(long minDate) {
-            mTempDate.setTimeInMillis(minDate);
-            if (mTempDate.get(Calendar.YEAR) == mMinDate.get(Calendar.YEAR)
-                    && mTempDate.get(Calendar.DAY_OF_YEAR) != mMinDate.get(Calendar.DAY_OF_YEAR)) {
-                return;
-            }
-            mMinDate.setTimeInMillis(minDate);
-            mCalendarView.setMinDate(minDate);
-            if (mCurrentDate.before(mMinDate)) {
-                mCurrentDate.setTimeInMillis(mMinDate.getTimeInMillis());
-                updateCalendarView();
-            }
-            updateSpinners();
-        }
-
-        @Override
-        public Calendar getMinDate() {
-            final Calendar minDate = Calendar.getInstance();
-            minDate.setTimeInMillis(mCalendarView.getMinDate());
-            return minDate;
-        }
-
-        @Override
-        public void setMaxDate(long maxDate) {
-            mTempDate.setTimeInMillis(maxDate);
-            if (mTempDate.get(Calendar.YEAR) == mMaxDate.get(Calendar.YEAR)
-                    && mTempDate.get(Calendar.DAY_OF_YEAR) != mMaxDate.get(Calendar.DAY_OF_YEAR)) {
-                return;
-            }
-            mMaxDate.setTimeInMillis(maxDate);
-            mCalendarView.setMaxDate(maxDate);
-            if (mCurrentDate.after(mMaxDate)) {
-                mCurrentDate.setTimeInMillis(mMaxDate.getTimeInMillis());
-                updateCalendarView();
-            }
-            updateSpinners();
-        }
-
-        @Override
-        public Calendar getMaxDate() {
-            final Calendar maxDate = Calendar.getInstance();
-            maxDate.setTimeInMillis(mCalendarView.getMaxDate());
-            return maxDate;
-        }
-
-        @Override
-        public void setEnabled(boolean enabled) {
-            mDaySpinner.setEnabled(enabled);
-            mMonthSpinner.setEnabled(enabled);
-            mYearSpinner.setEnabled(enabled);
-            mCalendarView.setEnabled(enabled);
-            mIsEnabled = enabled;
-        }
-
-        @Override
-        public boolean isEnabled() {
-            return mIsEnabled;
-        }
-
-        @Override
-        public CalendarView getCalendarView() {
-            return mCalendarView;
-        }
-
-        @Override
-        public void setCalendarViewShown(boolean shown) {
-            mCalendarView.setVisibility(shown ? VISIBLE : GONE);
-        }
-
-        @Override
-        public boolean getCalendarViewShown() {
-            return (mCalendarView.getVisibility() == View.VISIBLE);
-        }
-
-        @Override
-        public void setSpinnersShown(boolean shown) {
-            mSpinners.setVisibility(shown ? VISIBLE : GONE);
-        }
-
-        @Override
-        public boolean getSpinnersShown() {
-            return mSpinners.isShown();
-        }
-
-        @Override
-        public void onConfigurationChanged(Configuration newConfig) {
-            setCurrentLocale(newConfig.locale);
-        }
-
-        @Override
-        public Parcelable onSaveInstanceState(Parcelable superState) {
-            return new SavedState(superState, getYear(), getMonth(), getDayOfMonth());
-        }
-
-        @Override
-        public void onRestoreInstanceState(Parcelable state) {
-            SavedState ss = (SavedState) state;
-            setDate(ss.mYear, ss.mMonth, ss.mDay);
-            updateSpinners();
-            updateCalendarView();
-        }
-
-        @Override
-        public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
-            onPopulateAccessibilityEvent(event);
-            return true;
-        }
-
-        @Override
-        public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
-            final int flags = DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_YEAR;
-            String selectedDateUtterance = DateUtils.formatDateTime(mContext,
-                    mCurrentDate.getTimeInMillis(), flags);
-            event.getText().add(selectedDateUtterance);
-        }
-
-        /**
-         * Sets the current locale.
-         *
-         * @param locale The current locale.
-         */
-        @Override
-        protected void setCurrentLocale(Locale locale) {
-            super.setCurrentLocale(locale);
-
-            mTempDate = getCalendarForLocale(mTempDate, locale);
-            mMinDate = getCalendarForLocale(mMinDate, locale);
-            mMaxDate = getCalendarForLocale(mMaxDate, locale);
-            mCurrentDate = getCalendarForLocale(mCurrentDate, locale);
-
-            mNumberOfMonths = mTempDate.getActualMaximum(Calendar.MONTH) + 1;
-            mShortMonths = new DateFormatSymbols().getShortMonths();
-
-            if (usingNumericMonths()) {
-                // We're in a locale where a date should either be all-numeric, or all-text.
-                // All-text would require custom NumberPicker formatters for day and year.
-                mShortMonths = new String[mNumberOfMonths];
-                for (int i = 0; i < mNumberOfMonths; ++i) {
-                    mShortMonths[i] = String.format("%d", i + 1);
-                }
-            }
-        }
-
-        /**
-         * Tests whether the current locale is one where there are no real month names,
-         * such as Chinese, Japanese, or Korean locales.
-         */
-        private boolean usingNumericMonths() {
-            return Character.isDigit(mShortMonths[Calendar.JANUARY].charAt(0));
-        }
-
-        /**
-         * Gets a calendar for locale bootstrapped with the value of a given calendar.
-         *
-         * @param oldCalendar The old calendar.
-         * @param locale The locale.
-         */
-        private Calendar getCalendarForLocale(Calendar oldCalendar, Locale locale) {
-            if (oldCalendar == null) {
-                return Calendar.getInstance(locale);
-            } else {
-                final long currentTimeMillis = oldCalendar.getTimeInMillis();
-                Calendar newCalendar = Calendar.getInstance(locale);
-                newCalendar.setTimeInMillis(currentTimeMillis);
-                return newCalendar;
-            }
-        }
-
-        /**
-         * Reorders the spinners according to the date format that is
-         * explicitly set by the user and if no such is set fall back
-         * to the current locale's default format.
-         */
-        private void reorderSpinners() {
-            mSpinners.removeAllViews();
-            // We use numeric spinners for year and day, but textual months. Ask icu4c what
-            // order the user's locale uses for that combination. http://b/7207103.
-            String pattern = DateFormat.getBestDateTimePattern(Locale.getDefault(), "yyyyMMMdd");
-            char[] order = ICU.getDateFormatOrder(pattern);
-            final int spinnerCount = order.length;
-            for (int i = 0; i < spinnerCount; i++) {
-                switch (order[i]) {
-                    case 'd':
-                        mSpinners.addView(mDaySpinner);
-                        setImeOptions(mDaySpinner, spinnerCount, i);
-                        break;
-                    case 'M':
-                        mSpinners.addView(mMonthSpinner);
-                        setImeOptions(mMonthSpinner, spinnerCount, i);
-                        break;
-                    case 'y':
-                        mSpinners.addView(mYearSpinner);
-                        setImeOptions(mYearSpinner, spinnerCount, i);
-                        break;
-                    default:
-                        throw new IllegalArgumentException(Arrays.toString(order));
-                }
-            }
-        }
-
-        /**
-         * Parses the given <code>date</code> and in case of success sets the result
-         * to the <code>outDate</code>.
-         *
-         * @return True if the date was parsed.
-         */
-        private boolean parseDate(String date, Calendar outDate) {
-            try {
-                outDate.setTime(mDateFormat.parse(date));
-                return true;
-            } catch (ParseException e) {
-                Log.w(LOG_TAG, "Date: " + date + " not in format: " + DATE_FORMAT);
-                return false;
-            }
-        }
-
-        private boolean isNewDate(int year, int month, int dayOfMonth) {
-            return (mCurrentDate.get(Calendar.YEAR) != year
-                    || mCurrentDate.get(Calendar.MONTH) != month
-                    || mCurrentDate.get(Calendar.DAY_OF_MONTH) != dayOfMonth);
-        }
-
-        private void setDate(int year, int month, int dayOfMonth) {
-            mCurrentDate.set(year, month, dayOfMonth);
-            if (mCurrentDate.before(mMinDate)) {
-                mCurrentDate.setTimeInMillis(mMinDate.getTimeInMillis());
-            } else if (mCurrentDate.after(mMaxDate)) {
-                mCurrentDate.setTimeInMillis(mMaxDate.getTimeInMillis());
-            }
-        }
-
-        private void updateSpinners() {
-            // set the spinner ranges respecting the min and max dates
-            if (mCurrentDate.equals(mMinDate)) {
-                mDaySpinner.setMinValue(mCurrentDate.get(Calendar.DAY_OF_MONTH));
-                mDaySpinner.setMaxValue(mCurrentDate.getActualMaximum(Calendar.DAY_OF_MONTH));
-                mDaySpinner.setWrapSelectorWheel(false);
-                mMonthSpinner.setDisplayedValues(null);
-                mMonthSpinner.setMinValue(mCurrentDate.get(Calendar.MONTH));
-                mMonthSpinner.setMaxValue(mCurrentDate.getActualMaximum(Calendar.MONTH));
-                mMonthSpinner.setWrapSelectorWheel(false);
-            } else if (mCurrentDate.equals(mMaxDate)) {
-                mDaySpinner.setMinValue(mCurrentDate.getActualMinimum(Calendar.DAY_OF_MONTH));
-                mDaySpinner.setMaxValue(mCurrentDate.get(Calendar.DAY_OF_MONTH));
-                mDaySpinner.setWrapSelectorWheel(false);
-                mMonthSpinner.setDisplayedValues(null);
-                mMonthSpinner.setMinValue(mCurrentDate.getActualMinimum(Calendar.MONTH));
-                mMonthSpinner.setMaxValue(mCurrentDate.get(Calendar.MONTH));
-                mMonthSpinner.setWrapSelectorWheel(false);
-            } else {
-                mDaySpinner.setMinValue(1);
-                mDaySpinner.setMaxValue(mCurrentDate.getActualMaximum(Calendar.DAY_OF_MONTH));
-                mDaySpinner.setWrapSelectorWheel(true);
-                mMonthSpinner.setDisplayedValues(null);
-                mMonthSpinner.setMinValue(0);
-                mMonthSpinner.setMaxValue(11);
-                mMonthSpinner.setWrapSelectorWheel(true);
-            }
-
-            // make sure the month names are a zero based array
-            // with the months in the month spinner
-            String[] displayedValues = Arrays.copyOfRange(mShortMonths,
-                    mMonthSpinner.getMinValue(), mMonthSpinner.getMaxValue() + 1);
-            mMonthSpinner.setDisplayedValues(displayedValues);
-
-            // year spinner range does not change based on the current date
-            mYearSpinner.setMinValue(mMinDate.get(Calendar.YEAR));
-            mYearSpinner.setMaxValue(mMaxDate.get(Calendar.YEAR));
-            mYearSpinner.setWrapSelectorWheel(false);
-
-            // set the spinner values
-            mYearSpinner.setValue(mCurrentDate.get(Calendar.YEAR));
-            mMonthSpinner.setValue(mCurrentDate.get(Calendar.MONTH));
-            mDaySpinner.setValue(mCurrentDate.get(Calendar.DAY_OF_MONTH));
-
-            if (usingNumericMonths()) {
-                mMonthSpinnerInput.setRawInputType(InputType.TYPE_CLASS_NUMBER);
-            }
-        }
-
-        /**
-         * Updates the calendar view with the current date.
-         */
-        private void updateCalendarView() {
-            mCalendarView.setDate(mCurrentDate.getTimeInMillis(), false, false);
-        }
-
-
-        /**
-         * Notifies the listener, if such, for a change in the selected date.
-         */
-        private void notifyDateChanged() {
-            mDelegator.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SELECTED);
-            if (mOnDateChangedListener != null) {
-                mOnDateChangedListener.onDateChanged(mDelegator, getYear(), getMonth(),
-                        getDayOfMonth());
-            }
-        }
-
-        /**
-         * Sets the IME options for a spinner based on its ordering.
-         *
-         * @param spinner The spinner.
-         * @param spinnerCount The total spinner count.
-         * @param spinnerIndex The index of the given spinner.
-         */
-        private void setImeOptions(NumberPicker spinner, int spinnerCount, int spinnerIndex) {
-            final int imeOptions;
-            if (spinnerIndex < spinnerCount - 1) {
-                imeOptions = EditorInfo.IME_ACTION_NEXT;
-            } else {
-                imeOptions = EditorInfo.IME_ACTION_DONE;
-            }
-            TextView input = (TextView) spinner.findViewById(R.id.numberpicker_input);
-            input.setImeOptions(imeOptions);
-        }
-
-        private void setContentDescriptions() {
-            // Day
-            trySetContentDescription(mDaySpinner, R.id.increment,
-                    R.string.date_picker_increment_day_button);
-            trySetContentDescription(mDaySpinner, R.id.decrement,
-                    R.string.date_picker_decrement_day_button);
-            // Month
-            trySetContentDescription(mMonthSpinner, R.id.increment,
-                    R.string.date_picker_increment_month_button);
-            trySetContentDescription(mMonthSpinner, R.id.decrement,
-                    R.string.date_picker_decrement_month_button);
-            // Year
-            trySetContentDescription(mYearSpinner, R.id.increment,
-                    R.string.date_picker_increment_year_button);
-            trySetContentDescription(mYearSpinner, R.id.decrement,
-                    R.string.date_picker_decrement_year_button);
-        }
-
-        private void trySetContentDescription(View root, int viewId, int contDescResId) {
-            View target = root.findViewById(viewId);
-            if (target != null) {
-                target.setContentDescription(mContext.getString(contDescResId));
-            }
-        }
-
-        private void updateInputState() {
-            // Make sure that if the user changes the value and the IME is active
-            // for one of the inputs if this widget, the IME is closed. If the user
-            // changed the value via the IME and there is a next input the IME will
-            // be shown, otherwise the user chose another means of changing the
-            // value and having the IME up makes no sense.
-            InputMethodManager inputMethodManager = InputMethodManager.peekInstance();
-            if (inputMethodManager != null) {
-                if (inputMethodManager.isActive(mYearSpinnerInput)) {
-                    mYearSpinnerInput.clearFocus();
-                    inputMethodManager.hideSoftInputFromWindow(mDelegator.getWindowToken(), 0);
-                } else if (inputMethodManager.isActive(mMonthSpinnerInput)) {
-                    mMonthSpinnerInput.clearFocus();
-                    inputMethodManager.hideSoftInputFromWindow(mDelegator.getWindowToken(), 0);
-                } else if (inputMethodManager.isActive(mDaySpinnerInput)) {
-                    mDaySpinnerInput.clearFocus();
-                    inputMethodManager.hideSoftInputFromWindow(mDelegator.getWindowToken(), 0);
-                }
-            }
-        }
-    }
-
-    /**
-     * Class for managing state storing/restoring.
-     */
-    private static class SavedState extends BaseSavedState {
-
-        private final int mYear;
-
-        private final int mMonth;
-
-        private final int mDay;
-
-        /**
-         * Constructor called from {@link DatePicker#onSaveInstanceState()}
-         */
-        private SavedState(Parcelable superState, int year, int month, int day) {
-            super(superState);
-            mYear = year;
-            mMonth = month;
-            mDay = day;
-        }
-
-        /**
-         * Constructor called from {@link #CREATOR}
-         */
-        private SavedState(Parcel in) {
-            super(in);
-            mYear = in.readInt();
-            mMonth = in.readInt();
-            mDay = in.readInt();
-        }
-
-        @Override
-        public void writeToParcel(Parcel dest, int flags) {
-            super.writeToParcel(dest, flags);
-            dest.writeInt(mYear);
-            dest.writeInt(mMonth);
-            dest.writeInt(mDay);
-        }
-
-        @SuppressWarnings("all")
-        // suppress unused and hiding
-        public static final Parcelable.Creator<SavedState> CREATOR = new Creator<SavedState>() {
-
-            public SavedState createFromParcel(Parcel in) {
-                return new SavedState(in);
-            }
-
-            public SavedState[] newArray(int size) {
-                return new SavedState[size];
-            }
-        };
-    }
 }
diff --git a/core/java/android/widget/DatePickerCalendarDelegate.java b/core/java/android/widget/DatePickerCalendarDelegate.java
index cbb6109..5adac01 100755
--- a/core/java/android/widget/DatePickerCalendarDelegate.java
+++ b/core/java/android/widget/DatePickerCalendarDelegate.java
@@ -16,13 +16,14 @@
 
 package android.widget;
 
+import com.android.internal.R;
+
 import android.annotation.Nullable;
 import android.content.Context;
 import android.content.res.ColorStateList;
 import android.content.res.Configuration;
 import android.content.res.Resources;
 import android.content.res.TypedArray;
-import android.os.Parcel;
 import android.os.Parcelable;
 import android.text.format.DateFormat;
 import android.text.format.DateUtils;
@@ -37,8 +38,6 @@
 import android.widget.DayPickerView.OnDaySelectedListener;
 import android.widget.YearPickerView.OnYearSelectedListener;
 
-import com.android.internal.R;
-
 import java.text.SimpleDateFormat;
 import java.util.Calendar;
 import java.util.Locale;
@@ -550,25 +549,27 @@
 
     @Override
     public void onRestoreInstanceState(Parcelable state) {
-        final SavedState ss = (SavedState) state;
+        if (state instanceof SavedState) {
+            final SavedState ss = (SavedState) state;
 
-        // TODO: Move instance state into DayPickerView, YearPickerView.
-        mCurrentDate.set(ss.getSelectedYear(), ss.getSelectedMonth(), ss.getSelectedDay());
-        mMinDate.setTimeInMillis(ss.getMinDate());
-        mMaxDate.setTimeInMillis(ss.getMaxDate());
+            // TODO: Move instance state into DayPickerView, YearPickerView.
+            mCurrentDate.set(ss.getSelectedYear(), ss.getSelectedMonth(), ss.getSelectedDay());
+            mMinDate.setTimeInMillis(ss.getMinDate());
+            mMaxDate.setTimeInMillis(ss.getMaxDate());
 
-        onCurrentDateChanged(false);
+            onCurrentDateChanged(false);
 
-        final int currentView = ss.getCurrentView();
-        setCurrentView(currentView);
+            final int currentView = ss.getCurrentView();
+            setCurrentView(currentView);
 
-        final int listPosition = ss.getListPosition();
-        if (listPosition != -1) {
-            if (currentView == VIEW_MONTH_DAY) {
-                mDayPickerView.setPosition(listPosition);
-            } else if (currentView == VIEW_YEAR) {
-                final int listPositionOffset = ss.getListPositionOffset();
-                mYearPickerView.setSelectionFromTop(listPosition, listPositionOffset);
+            final int listPosition = ss.getListPosition();
+            if (listPosition != -1) {
+                if (currentView == VIEW_MONTH_DAY) {
+                    mDayPickerView.setPosition(listPosition);
+                } else if (currentView == VIEW_YEAR) {
+                    final int listPositionOffset = ss.getListPositionOffset();
+                    mYearPickerView.setSelectionFromTop(listPosition, listPositionOffset);
+                }
             }
         }
     }
@@ -613,108 +614,4 @@
     private void tryVibrate() {
         mDelegator.performHapticFeedback(HapticFeedbackConstants.CALENDAR_DATE);
     }
-
-    /**
-     * Class for managing state storing/restoring.
-     */
-    private static class SavedState extends View.BaseSavedState {
-        private final int mSelectedYear;
-        private final int mSelectedMonth;
-        private final int mSelectedDay;
-        private final long mMinDate;
-        private final long mMaxDate;
-        private final int mCurrentView;
-        private final int mListPosition;
-        private final int mListPositionOffset;
-
-        /**
-         * Constructor called from {@link DatePicker#onSaveInstanceState()}
-         */
-        private SavedState(Parcelable superState, int year, int month, int day,
-                long minDate, long maxDate, int currentView, int listPosition,
-                int listPositionOffset) {
-            super(superState);
-            mSelectedYear = year;
-            mSelectedMonth = month;
-            mSelectedDay = day;
-            mMinDate = minDate;
-            mMaxDate = maxDate;
-            mCurrentView = currentView;
-            mListPosition = listPosition;
-            mListPositionOffset = listPositionOffset;
-        }
-
-        /**
-         * Constructor called from {@link #CREATOR}
-         */
-        private SavedState(Parcel in) {
-            super(in);
-            mSelectedYear = in.readInt();
-            mSelectedMonth = in.readInt();
-            mSelectedDay = in.readInt();
-            mMinDate = in.readLong();
-            mMaxDate = in.readLong();
-            mCurrentView = in.readInt();
-            mListPosition = in.readInt();
-            mListPositionOffset = in.readInt();
-        }
-
-        @Override
-        public void writeToParcel(Parcel dest, int flags) {
-            super.writeToParcel(dest, flags);
-            dest.writeInt(mSelectedYear);
-            dest.writeInt(mSelectedMonth);
-            dest.writeInt(mSelectedDay);
-            dest.writeLong(mMinDate);
-            dest.writeLong(mMaxDate);
-            dest.writeInt(mCurrentView);
-            dest.writeInt(mListPosition);
-            dest.writeInt(mListPositionOffset);
-        }
-
-        public int getSelectedDay() {
-            return mSelectedDay;
-        }
-
-        public int getSelectedMonth() {
-            return mSelectedMonth;
-        }
-
-        public int getSelectedYear() {
-            return mSelectedYear;
-        }
-
-        public long getMinDate() {
-            return mMinDate;
-        }
-
-        public long getMaxDate() {
-            return mMaxDate;
-        }
-
-        public int getCurrentView() {
-            return mCurrentView;
-        }
-
-        public int getListPosition() {
-            return mListPosition;
-        }
-
-        public int getListPositionOffset() {
-            return mListPositionOffset;
-        }
-
-        @SuppressWarnings("all")
-        // suppress unused and hiding
-        public static final Parcelable.Creator<SavedState> CREATOR = new Creator<SavedState>() {
-
-            public SavedState createFromParcel(Parcel in) {
-                return new SavedState(in);
-            }
-
-            public SavedState[] newArray(int size) {
-                return new SavedState[size];
-            }
-        };
-    }
 }
diff --git a/core/java/android/widget/DatePickerSpinnerDelegate.java b/core/java/android/widget/DatePickerSpinnerDelegate.java
new file mode 100644
index 0000000..255de79
--- /dev/null
+++ b/core/java/android/widget/DatePickerSpinnerDelegate.java
@@ -0,0 +1,652 @@
+/*
+ * 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.widget;
+
+import android.content.Context;
+import android.content.res.Configuration;
+import android.content.res.TypedArray;
+import android.os.Parcelable;
+import android.text.InputType;
+import android.text.TextUtils;
+import android.text.format.DateFormat;
+import android.text.format.DateUtils;
+import android.util.AttributeSet;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.accessibility.AccessibilityEvent;
+import android.view.inputmethod.EditorInfo;
+import android.view.inputmethod.InputMethodManager;
+import android.widget.DatePicker.AbstractDatePickerDelegate;
+import android.widget.NumberPicker.OnValueChangeListener;
+
+import java.text.DateFormatSymbols;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Arrays;
+import java.util.Calendar;
+import java.util.Locale;
+
+import libcore.icu.ICU;
+
+/**
+ * A delegate implementing the basic DatePicker
+ */
+class DatePickerSpinnerDelegate extends AbstractDatePickerDelegate {
+
+    private static final String DATE_FORMAT = "MM/dd/yyyy";
+
+    private static final int DEFAULT_START_YEAR = 1900;
+
+    private static final int DEFAULT_END_YEAR = 2100;
+
+    private static final boolean DEFAULT_CALENDAR_VIEW_SHOWN = true;
+
+    private static final boolean DEFAULT_SPINNERS_SHOWN = true;
+
+    private static final boolean DEFAULT_ENABLED_STATE = true;
+
+    private final LinearLayout mSpinners;
+
+    private final NumberPicker mDaySpinner;
+
+    private final NumberPicker mMonthSpinner;
+
+    private final NumberPicker mYearSpinner;
+
+    private final EditText mDaySpinnerInput;
+
+    private final EditText mMonthSpinnerInput;
+
+    private final EditText mYearSpinnerInput;
+
+    private final CalendarView mCalendarView;
+
+    private String[] mShortMonths;
+
+    private final java.text.DateFormat mDateFormat = new SimpleDateFormat(DATE_FORMAT);
+
+    private int mNumberOfMonths;
+
+    private Calendar mTempDate;
+
+    private Calendar mMinDate;
+
+    private Calendar mMaxDate;
+
+    private Calendar mCurrentDate;
+
+    private boolean mIsEnabled = DEFAULT_ENABLED_STATE;
+
+    DatePickerSpinnerDelegate(DatePicker delegator, Context context, AttributeSet attrs,
+            int defStyleAttr, int defStyleRes) {
+        super(delegator, context);
+
+        mDelegator = delegator;
+        mContext = context;
+
+        // initialization based on locale
+        setCurrentLocale(Locale.getDefault());
+
+        final TypedArray attributesArray = context.obtainStyledAttributes(attrs,
+                com.android.internal.R.styleable.DatePicker, defStyleAttr, defStyleRes);
+        boolean spinnersShown = attributesArray.getBoolean(com.android.internal.R.styleable.DatePicker_spinnersShown,
+                DEFAULT_SPINNERS_SHOWN);
+        boolean calendarViewShown = attributesArray.getBoolean(
+                com.android.internal.R.styleable.DatePicker_calendarViewShown, DEFAULT_CALENDAR_VIEW_SHOWN);
+        int startYear = attributesArray.getInt(com.android.internal.R.styleable.DatePicker_startYear,
+                DEFAULT_START_YEAR);
+        int endYear = attributesArray.getInt(com.android.internal.R.styleable.DatePicker_endYear, DEFAULT_END_YEAR);
+        String minDate = attributesArray.getString(com.android.internal.R.styleable.DatePicker_minDate);
+        String maxDate = attributesArray.getString(com.android.internal.R.styleable.DatePicker_maxDate);
+        int layoutResourceId = attributesArray.getResourceId(
+                com.android.internal.R.styleable.DatePicker_legacyLayout, com.android.internal.R.layout.date_picker_legacy);
+        attributesArray.recycle();
+
+        LayoutInflater inflater = (LayoutInflater) context
+                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+        inflater.inflate(layoutResourceId, mDelegator, true);
+
+        OnValueChangeListener onChangeListener = new OnValueChangeListener() {
+            public void onValueChange(NumberPicker picker, int oldVal, int newVal) {
+                updateInputState();
+                mTempDate.setTimeInMillis(mCurrentDate.getTimeInMillis());
+                // take care of wrapping of days and months to update greater fields
+                if (picker == mDaySpinner) {
+                    int maxDayOfMonth = mTempDate.getActualMaximum(Calendar.DAY_OF_MONTH);
+                    if (oldVal == maxDayOfMonth && newVal == 1) {
+                        mTempDate.add(Calendar.DAY_OF_MONTH, 1);
+                    } else if (oldVal == 1 && newVal == maxDayOfMonth) {
+                        mTempDate.add(Calendar.DAY_OF_MONTH, -1);
+                    } else {
+                        mTempDate.add(Calendar.DAY_OF_MONTH, newVal - oldVal);
+                    }
+                } else if (picker == mMonthSpinner) {
+                    if (oldVal == 11 && newVal == 0) {
+                        mTempDate.add(Calendar.MONTH, 1);
+                    } else if (oldVal == 0 && newVal == 11) {
+                        mTempDate.add(Calendar.MONTH, -1);
+                    } else {
+                        mTempDate.add(Calendar.MONTH, newVal - oldVal);
+                    }
+                } else if (picker == mYearSpinner) {
+                    mTempDate.set(Calendar.YEAR, newVal);
+                } else {
+                    throw new IllegalArgumentException();
+                }
+                // now set the date to the adjusted one
+                setDate(mTempDate.get(Calendar.YEAR), mTempDate.get(Calendar.MONTH),
+                        mTempDate.get(Calendar.DAY_OF_MONTH));
+                updateSpinners();
+                updateCalendarView();
+                notifyDateChanged();
+            }
+        };
+
+        mSpinners = (LinearLayout) mDelegator.findViewById(com.android.internal.R.id.pickers);
+
+        // calendar view day-picker
+        mCalendarView = (CalendarView) mDelegator.findViewById(com.android.internal.R.id.calendar_view);
+        mCalendarView.setOnDateChangeListener(new CalendarView.OnDateChangeListener() {
+            public void onSelectedDayChange(CalendarView view, int year, int month, int monthDay) {
+                setDate(year, month, monthDay);
+                updateSpinners();
+                notifyDateChanged();
+            }
+        });
+
+        // day
+        mDaySpinner = (NumberPicker) mDelegator.findViewById(com.android.internal.R.id.day);
+        mDaySpinner.setFormatter(NumberPicker.getTwoDigitFormatter());
+        mDaySpinner.setOnLongPressUpdateInterval(100);
+        mDaySpinner.setOnValueChangedListener(onChangeListener);
+        mDaySpinnerInput = (EditText) mDaySpinner.findViewById(com.android.internal.R.id.numberpicker_input);
+
+        // month
+        mMonthSpinner = (NumberPicker) mDelegator.findViewById(com.android.internal.R.id.month);
+        mMonthSpinner.setMinValue(0);
+        mMonthSpinner.setMaxValue(mNumberOfMonths - 1);
+        mMonthSpinner.setDisplayedValues(mShortMonths);
+        mMonthSpinner.setOnLongPressUpdateInterval(200);
+        mMonthSpinner.setOnValueChangedListener(onChangeListener);
+        mMonthSpinnerInput = (EditText) mMonthSpinner.findViewById(com.android.internal.R.id.numberpicker_input);
+
+        // year
+        mYearSpinner = (NumberPicker) mDelegator.findViewById(com.android.internal.R.id.year);
+        mYearSpinner.setOnLongPressUpdateInterval(100);
+        mYearSpinner.setOnValueChangedListener(onChangeListener);
+        mYearSpinnerInput = (EditText) mYearSpinner.findViewById(com.android.internal.R.id.numberpicker_input);
+
+        // show only what the user required but make sure we
+        // show something and the spinners have higher priority
+        if (!spinnersShown && !calendarViewShown) {
+            setSpinnersShown(true);
+        } else {
+            setSpinnersShown(spinnersShown);
+            setCalendarViewShown(calendarViewShown);
+        }
+
+        // set the min date giving priority of the minDate over startYear
+        mTempDate.clear();
+        if (!TextUtils.isEmpty(minDate)) {
+            if (!parseDate(minDate, mTempDate)) {
+                mTempDate.set(startYear, 0, 1);
+            }
+        } else {
+            mTempDate.set(startYear, 0, 1);
+        }
+        setMinDate(mTempDate.getTimeInMillis());
+
+        // set the max date giving priority of the maxDate over endYear
+        mTempDate.clear();
+        if (!TextUtils.isEmpty(maxDate)) {
+            if (!parseDate(maxDate, mTempDate)) {
+                mTempDate.set(endYear, 11, 31);
+            }
+        } else {
+            mTempDate.set(endYear, 11, 31);
+        }
+        setMaxDate(mTempDate.getTimeInMillis());
+
+        // initialize to current date
+        mCurrentDate.setTimeInMillis(System.currentTimeMillis());
+        init(mCurrentDate.get(Calendar.YEAR), mCurrentDate.get(Calendar.MONTH), mCurrentDate
+                .get(Calendar.DAY_OF_MONTH), null);
+
+        // re-order the number spinners to match the current date format
+        reorderSpinners();
+
+        // accessibility
+        setContentDescriptions();
+
+        // If not explicitly specified this view is important for accessibility.
+        if (mDelegator.getImportantForAccessibility() == View.IMPORTANT_FOR_ACCESSIBILITY_AUTO) {
+            mDelegator.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_YES);
+        }
+    }
+
+    @Override
+    public void init(int year, int monthOfYear, int dayOfMonth,
+                     DatePicker.OnDateChangedListener onDateChangedListener) {
+        setDate(year, monthOfYear, dayOfMonth);
+        updateSpinners();
+        updateCalendarView();
+        mOnDateChangedListener = onDateChangedListener;
+    }
+
+    @Override
+    public void updateDate(int year, int month, int dayOfMonth) {
+        if (!isNewDate(year, month, dayOfMonth)) {
+            return;
+        }
+        setDate(year, month, dayOfMonth);
+        updateSpinners();
+        updateCalendarView();
+        notifyDateChanged();
+    }
+
+    @Override
+    public int getYear() {
+        return mCurrentDate.get(Calendar.YEAR);
+    }
+
+    @Override
+    public int getMonth() {
+        return mCurrentDate.get(Calendar.MONTH);
+    }
+
+    @Override
+    public int getDayOfMonth() {
+        return mCurrentDate.get(Calendar.DAY_OF_MONTH);
+    }
+
+    @Override
+    public void setFirstDayOfWeek(int firstDayOfWeek) {
+        mCalendarView.setFirstDayOfWeek(firstDayOfWeek);
+    }
+
+    @Override
+    public int getFirstDayOfWeek() {
+        return mCalendarView.getFirstDayOfWeek();
+    }
+
+    @Override
+    public void setMinDate(long minDate) {
+        mTempDate.setTimeInMillis(minDate);
+        if (mTempDate.get(Calendar.YEAR) == mMinDate.get(Calendar.YEAR)
+                && mTempDate.get(Calendar.DAY_OF_YEAR) != mMinDate.get(Calendar.DAY_OF_YEAR)) {
+            return;
+        }
+        mMinDate.setTimeInMillis(minDate);
+        mCalendarView.setMinDate(minDate);
+        if (mCurrentDate.before(mMinDate)) {
+            mCurrentDate.setTimeInMillis(mMinDate.getTimeInMillis());
+            updateCalendarView();
+        }
+        updateSpinners();
+    }
+
+    @Override
+    public Calendar getMinDate() {
+        final Calendar minDate = Calendar.getInstance();
+        minDate.setTimeInMillis(mCalendarView.getMinDate());
+        return minDate;
+    }
+
+    @Override
+    public void setMaxDate(long maxDate) {
+        mTempDate.setTimeInMillis(maxDate);
+        if (mTempDate.get(Calendar.YEAR) == mMaxDate.get(Calendar.YEAR)
+                && mTempDate.get(Calendar.DAY_OF_YEAR) != mMaxDate.get(Calendar.DAY_OF_YEAR)) {
+            return;
+        }
+        mMaxDate.setTimeInMillis(maxDate);
+        mCalendarView.setMaxDate(maxDate);
+        if (mCurrentDate.after(mMaxDate)) {
+            mCurrentDate.setTimeInMillis(mMaxDate.getTimeInMillis());
+            updateCalendarView();
+        }
+        updateSpinners();
+    }
+
+    @Override
+    public Calendar getMaxDate() {
+        final Calendar maxDate = Calendar.getInstance();
+        maxDate.setTimeInMillis(mCalendarView.getMaxDate());
+        return maxDate;
+    }
+
+    @Override
+    public void setEnabled(boolean enabled) {
+        mDaySpinner.setEnabled(enabled);
+        mMonthSpinner.setEnabled(enabled);
+        mYearSpinner.setEnabled(enabled);
+        mCalendarView.setEnabled(enabled);
+        mIsEnabled = enabled;
+    }
+
+    @Override
+    public boolean isEnabled() {
+        return mIsEnabled;
+    }
+
+    @Override
+    public CalendarView getCalendarView() {
+        return mCalendarView;
+    }
+
+    @Override
+    public void setCalendarViewShown(boolean shown) {
+        mCalendarView.setVisibility(shown ? View.VISIBLE : View.GONE);
+    }
+
+    @Override
+    public boolean getCalendarViewShown() {
+        return (mCalendarView.getVisibility() == View.VISIBLE);
+    }
+
+    @Override
+    public void setSpinnersShown(boolean shown) {
+        mSpinners.setVisibility(shown ? View.VISIBLE : View.GONE);
+    }
+
+    @Override
+    public boolean getSpinnersShown() {
+        return mSpinners.isShown();
+    }
+
+    @Override
+    public void onConfigurationChanged(Configuration newConfig) {
+        setCurrentLocale(newConfig.locale);
+    }
+
+    @Override
+    public Parcelable onSaveInstanceState(Parcelable superState) {
+        return new SavedState(superState, getYear(), getMonth(), getDayOfMonth(),
+                getMinDate().getTimeInMillis(), getMaxDate().getTimeInMillis());
+    }
+
+    @Override
+    public void onRestoreInstanceState(Parcelable state) {
+        if (state instanceof SavedState) {
+            final SavedState ss = (SavedState) state;
+            setDate(ss.getSelectedYear(), ss.getSelectedMonth(), ss.getSelectedDay());
+            updateSpinners();
+            updateCalendarView();
+        }
+    }
+
+    @Override
+    public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
+        onPopulateAccessibilityEvent(event);
+        return true;
+    }
+
+    @Override
+    public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
+        final int flags = DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_YEAR;
+        String selectedDateUtterance = DateUtils.formatDateTime(mContext,
+                mCurrentDate.getTimeInMillis(), flags);
+        event.getText().add(selectedDateUtterance);
+    }
+
+    /**
+     * Sets the current locale.
+     *
+     * @param locale The current locale.
+     */
+    @Override
+    protected void setCurrentLocale(Locale locale) {
+        super.setCurrentLocale(locale);
+
+        mTempDate = getCalendarForLocale(mTempDate, locale);
+        mMinDate = getCalendarForLocale(mMinDate, locale);
+        mMaxDate = getCalendarForLocale(mMaxDate, locale);
+        mCurrentDate = getCalendarForLocale(mCurrentDate, locale);
+
+        mNumberOfMonths = mTempDate.getActualMaximum(Calendar.MONTH) + 1;
+        mShortMonths = new DateFormatSymbols().getShortMonths();
+
+        if (usingNumericMonths()) {
+            // We're in a locale where a date should either be all-numeric, or all-text.
+            // All-text would require custom NumberPicker formatters for day and year.
+            mShortMonths = new String[mNumberOfMonths];
+            for (int i = 0; i < mNumberOfMonths; ++i) {
+                mShortMonths[i] = String.format("%d", i + 1);
+            }
+        }
+    }
+
+    /**
+     * Tests whether the current locale is one where there are no real month names,
+     * such as Chinese, Japanese, or Korean locales.
+     */
+    private boolean usingNumericMonths() {
+        return Character.isDigit(mShortMonths[Calendar.JANUARY].charAt(0));
+    }
+
+    /**
+     * Gets a calendar for locale bootstrapped with the value of a given calendar.
+     *
+     * @param oldCalendar The old calendar.
+     * @param locale The locale.
+     */
+    private Calendar getCalendarForLocale(Calendar oldCalendar, Locale locale) {
+        if (oldCalendar == null) {
+            return Calendar.getInstance(locale);
+        } else {
+            final long currentTimeMillis = oldCalendar.getTimeInMillis();
+            Calendar newCalendar = Calendar.getInstance(locale);
+            newCalendar.setTimeInMillis(currentTimeMillis);
+            return newCalendar;
+        }
+    }
+
+    /**
+     * Reorders the spinners according to the date format that is
+     * explicitly set by the user and if no such is set fall back
+     * to the current locale's default format.
+     */
+    private void reorderSpinners() {
+        mSpinners.removeAllViews();
+        // We use numeric spinners for year and day, but textual months. Ask icu4c what
+        // order the user's locale uses for that combination. http://b/7207103.
+        String pattern = DateFormat.getBestDateTimePattern(Locale.getDefault(), "yyyyMMMdd");
+        char[] order = ICU.getDateFormatOrder(pattern);
+        final int spinnerCount = order.length;
+        for (int i = 0; i < spinnerCount; i++) {
+            switch (order[i]) {
+                case 'd':
+                    mSpinners.addView(mDaySpinner);
+                    setImeOptions(mDaySpinner, spinnerCount, i);
+                    break;
+                case 'M':
+                    mSpinners.addView(mMonthSpinner);
+                    setImeOptions(mMonthSpinner, spinnerCount, i);
+                    break;
+                case 'y':
+                    mSpinners.addView(mYearSpinner);
+                    setImeOptions(mYearSpinner, spinnerCount, i);
+                    break;
+                default:
+                    throw new IllegalArgumentException(Arrays.toString(order));
+            }
+        }
+    }
+
+    /**
+     * Parses the given <code>date</code> and in case of success sets the result
+     * to the <code>outDate</code>.
+     *
+     * @return True if the date was parsed.
+     */
+    private boolean parseDate(String date, Calendar outDate) {
+        try {
+            outDate.setTime(mDateFormat.parse(date));
+            return true;
+        } catch (ParseException e) {
+            e.printStackTrace();
+            return false;
+        }
+    }
+
+    private boolean isNewDate(int year, int month, int dayOfMonth) {
+        return (mCurrentDate.get(Calendar.YEAR) != year
+                || mCurrentDate.get(Calendar.MONTH) != month
+                || mCurrentDate.get(Calendar.DAY_OF_MONTH) != dayOfMonth);
+    }
+
+    private void setDate(int year, int month, int dayOfMonth) {
+        mCurrentDate.set(year, month, dayOfMonth);
+        if (mCurrentDate.before(mMinDate)) {
+            mCurrentDate.setTimeInMillis(mMinDate.getTimeInMillis());
+        } else if (mCurrentDate.after(mMaxDate)) {
+            mCurrentDate.setTimeInMillis(mMaxDate.getTimeInMillis());
+        }
+    }
+
+    private void updateSpinners() {
+        // set the spinner ranges respecting the min and max dates
+        if (mCurrentDate.equals(mMinDate)) {
+            mDaySpinner.setMinValue(mCurrentDate.get(Calendar.DAY_OF_MONTH));
+            mDaySpinner.setMaxValue(mCurrentDate.getActualMaximum(Calendar.DAY_OF_MONTH));
+            mDaySpinner.setWrapSelectorWheel(false);
+            mMonthSpinner.setDisplayedValues(null);
+            mMonthSpinner.setMinValue(mCurrentDate.get(Calendar.MONTH));
+            mMonthSpinner.setMaxValue(mCurrentDate.getActualMaximum(Calendar.MONTH));
+            mMonthSpinner.setWrapSelectorWheel(false);
+        } else if (mCurrentDate.equals(mMaxDate)) {
+            mDaySpinner.setMinValue(mCurrentDate.getActualMinimum(Calendar.DAY_OF_MONTH));
+            mDaySpinner.setMaxValue(mCurrentDate.get(Calendar.DAY_OF_MONTH));
+            mDaySpinner.setWrapSelectorWheel(false);
+            mMonthSpinner.setDisplayedValues(null);
+            mMonthSpinner.setMinValue(mCurrentDate.getActualMinimum(Calendar.MONTH));
+            mMonthSpinner.setMaxValue(mCurrentDate.get(Calendar.MONTH));
+            mMonthSpinner.setWrapSelectorWheel(false);
+        } else {
+            mDaySpinner.setMinValue(1);
+            mDaySpinner.setMaxValue(mCurrentDate.getActualMaximum(Calendar.DAY_OF_MONTH));
+            mDaySpinner.setWrapSelectorWheel(true);
+            mMonthSpinner.setDisplayedValues(null);
+            mMonthSpinner.setMinValue(0);
+            mMonthSpinner.setMaxValue(11);
+            mMonthSpinner.setWrapSelectorWheel(true);
+        }
+
+        // make sure the month names are a zero based array
+        // with the months in the month spinner
+        String[] displayedValues = Arrays.copyOfRange(mShortMonths,
+                mMonthSpinner.getMinValue(), mMonthSpinner.getMaxValue() + 1);
+        mMonthSpinner.setDisplayedValues(displayedValues);
+
+        // year spinner range does not change based on the current date
+        mYearSpinner.setMinValue(mMinDate.get(Calendar.YEAR));
+        mYearSpinner.setMaxValue(mMaxDate.get(Calendar.YEAR));
+        mYearSpinner.setWrapSelectorWheel(false);
+
+        // set the spinner values
+        mYearSpinner.setValue(mCurrentDate.get(Calendar.YEAR));
+        mMonthSpinner.setValue(mCurrentDate.get(Calendar.MONTH));
+        mDaySpinner.setValue(mCurrentDate.get(Calendar.DAY_OF_MONTH));
+
+        if (usingNumericMonths()) {
+            mMonthSpinnerInput.setRawInputType(InputType.TYPE_CLASS_NUMBER);
+        }
+    }
+
+    /**
+     * Updates the calendar view with the current date.
+     */
+    private void updateCalendarView() {
+        mCalendarView.setDate(mCurrentDate.getTimeInMillis(), false, false);
+    }
+
+
+    /**
+     * Notifies the listener, if such, for a change in the selected date.
+     */
+    private void notifyDateChanged() {
+        mDelegator.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SELECTED);
+        if (mOnDateChangedListener != null) {
+            mOnDateChangedListener.onDateChanged(mDelegator, getYear(), getMonth(),
+                    getDayOfMonth());
+        }
+    }
+
+    /**
+     * Sets the IME options for a spinner based on its ordering.
+     *
+     * @param spinner The spinner.
+     * @param spinnerCount The total spinner count.
+     * @param spinnerIndex The index of the given spinner.
+     */
+    private void setImeOptions(NumberPicker spinner, int spinnerCount, int spinnerIndex) {
+        final int imeOptions;
+        if (spinnerIndex < spinnerCount - 1) {
+            imeOptions = EditorInfo.IME_ACTION_NEXT;
+        } else {
+            imeOptions = EditorInfo.IME_ACTION_DONE;
+        }
+        TextView input = (TextView) spinner.findViewById(com.android.internal.R.id.numberpicker_input);
+        input.setImeOptions(imeOptions);
+    }
+
+    private void setContentDescriptions() {
+        // Day
+        trySetContentDescription(mDaySpinner, com.android.internal.R.id.increment,
+                com.android.internal.R.string.date_picker_increment_day_button);
+        trySetContentDescription(mDaySpinner, com.android.internal.R.id.decrement,
+                com.android.internal.R.string.date_picker_decrement_day_button);
+        // Month
+        trySetContentDescription(mMonthSpinner, com.android.internal.R.id.increment,
+                com.android.internal.R.string.date_picker_increment_month_button);
+        trySetContentDescription(mMonthSpinner, com.android.internal.R.id.decrement,
+                com.android.internal.R.string.date_picker_decrement_month_button);
+        // Year
+        trySetContentDescription(mYearSpinner, com.android.internal.R.id.increment,
+                com.android.internal.R.string.date_picker_increment_year_button);
+        trySetContentDescription(mYearSpinner, com.android.internal.R.id.decrement,
+                com.android.internal.R.string.date_picker_decrement_year_button);
+    }
+
+    private void trySetContentDescription(View root, int viewId, int contDescResId) {
+        View target = root.findViewById(viewId);
+        if (target != null) {
+            target.setContentDescription(mContext.getString(contDescResId));
+        }
+    }
+
+    private void updateInputState() {
+        // Make sure that if the user changes the value and the IME is active
+        // for one of the inputs if this widget, the IME is closed. If the user
+        // changed the value via the IME and there is a next input the IME will
+        // be shown, otherwise the user chose another means of changing the
+        // value and having the IME up makes no sense.
+        InputMethodManager inputMethodManager = InputMethodManager.peekInstance();
+        if (inputMethodManager != null) {
+            if (inputMethodManager.isActive(mYearSpinnerInput)) {
+                mYearSpinnerInput.clearFocus();
+                inputMethodManager.hideSoftInputFromWindow(mDelegator.getWindowToken(), 0);
+            } else if (inputMethodManager.isActive(mMonthSpinnerInput)) {
+                mMonthSpinnerInput.clearFocus();
+                inputMethodManager.hideSoftInputFromWindow(mDelegator.getWindowToken(), 0);
+            } else if (inputMethodManager.isActive(mDaySpinnerInput)) {
+                mDaySpinnerInput.clearFocus();
+                inputMethodManager.hideSoftInputFromWindow(mDelegator.getWindowToken(), 0);
+            }
+        }
+    }
+}
diff --git a/core/java/android/widget/DayPickerPagerAdapter.java b/core/java/android/widget/DayPickerPagerAdapter.java
index f5840dc..8ce2f9c 100644
--- a/core/java/android/widget/DayPickerPagerAdapter.java
+++ b/core/java/android/widget/DayPickerPagerAdapter.java
@@ -282,7 +282,7 @@
     public CharSequence getPageTitle(int position) {
         final SimpleMonthView v = mItems.get(position).calendar;
         if (v != null) {
-            return v.getTitle();
+            return v.getMonthYearLabel();
         }
         return null;
     }
diff --git a/core/java/android/widget/EditText.java b/core/java/android/widget/EditText.java
index 1d242d3..434e3eb 100644
--- a/core/java/android/widget/EditText.java
+++ b/core/java/android/widget/EditText.java
@@ -117,6 +117,16 @@
         Selection.extendSelection(getText(), index);
     }
 
+    /**
+     * Causes words in the text that are longer than the view's width to be ellipsized instead of
+     * broken in the middle. {@link TextUtils.TruncateAt#MARQUEE
+     * TextUtils.TruncateAt#MARQUEE} is not supported.
+     *
+     * @param ellipsis Type of ellipsis to be applied.
+     * @throws IllegalArgumentException When the value of <code>ellipsis</code> parameter is
+     *      {@link TextUtils.TruncateAt#MARQUEE}.
+     * @see TextView#setEllipsize(TextUtils.TruncateAt)
+     */
     @Override
     public void setEllipsize(TextUtils.TruncateAt ellipsis) {
         if (ellipsis == TextUtils.TruncateAt.MARQUEE) {
diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java
index 881e5cd..3b6ba3a 100644
--- a/core/java/android/widget/Editor.java
+++ b/core/java/android/widget/Editor.java
@@ -215,7 +215,7 @@
 
     boolean mInBatchEditControllers;
     boolean mShowSoftInputOnFocus = true;
-    boolean mPreserveDetachedSelection;
+    private boolean mPreserveSelection;
     boolean mTemporaryDetach;
 
     boolean mIsBeingLongClicked;
@@ -290,7 +290,6 @@
     boolean mIsInsertionActionModeStartPending = false;
 
     private final SuggestionHelper mSuggestionHelper = new SuggestionHelper();
-    private SuggestionInfo[] mSuggestionInfosInContextMenu;
 
     Editor(TextView textView) {
         mTextView = textView;
@@ -351,10 +350,14 @@
     }
 
     void replace() {
+        if (mSuggestionsPopupWindow == null) {
+            mSuggestionsPopupWindow = new SuggestionsPopupWindow();
+        }
+        hideCursorAndSpanControllers();
+        mSuggestionsPopupWindow.show();
+
         int middle = (mTextView.getSelectionStart() + mTextView.getSelectionEnd()) / 2;
-        stopTextActionMode();
         Selection.setSelection((Spannable) mTextView.getText(), middle);
-        showSuggestions();
     }
 
     void onAttachedToWindow() {
@@ -377,13 +380,7 @@
         updateSpellCheckSpans(0, mTextView.getText().length(),
                 true /* create the spell checker if needed */);
 
-        if (mTextView.hasTransientState() &&
-                mTextView.getSelectionStart() != mTextView.getSelectionEnd()) {
-            // Since transient state is reference counted make sure it stays matched
-            // with our own calls to it for managing selection.
-            // The action mode callback will set this back again when/if the action mode starts.
-            mTextView.setHasTransientState(false);
-
+        if (mTextView.getSelectionStart() != mTextView.getSelectionEnd()) {
             // We had an active selection from before, start the selection mode.
             startSelectionActionMode();
         }
@@ -429,10 +426,8 @@
             mSpellChecker = null;
         }
 
-        mPreserveDetachedSelection = true;
         hideCursorAndSpanControllers();
-        stopTextActionMode();
-        mPreserveDetachedSelection = false;
+        stopTextActionModeWithPreservingSelection();
         mTemporaryDetach = false;
     }
 
@@ -930,7 +925,8 @@
     }
 
     void onLocaleChanged() {
-        // Will be re-created on demand in getWordIterator with the proper new locale
+        // Will be re-created on demand in getWordIterator and getWordIteratorWithText with the
+        // proper new locale
         mWordIterator = null;
         mWordIteratorWithText = null;
     }
@@ -1104,7 +1100,6 @@
                 mInsertionControllerEnabled) {
             final int offset = mTextView.getOffsetForPosition(mLastDownPositionX,
                     mLastDownPositionY);
-            stopTextActionMode();
             Selection.setSelection((Spannable) mTextView.getText(), offset);
             getInsertionController().show();
             mIsInsertionActionModeStartPending = true;
@@ -1208,18 +1203,15 @@
             mTextView.onEndBatchEdit();
 
             if (mTextView.isInExtractedMode()) {
-                // terminateTextSelectionMode removes selection, which we want to keep when
-                // ExtractEditText goes out of focus.
-                final int selStart = mTextView.getSelectionStart();
-                final int selEnd = mTextView.getSelectionEnd();
                 hideCursorAndSpanControllers();
-                stopTextActionMode();
-                Selection.setSelection((Spannable) mTextView.getText(), selStart, selEnd);
+                stopTextActionModeWithPreservingSelection();
             } else {
-                if (mTemporaryDetach) mPreserveDetachedSelection = true;
                 hideCursorAndSpanControllers();
-                stopTextActionMode();
-                if (mTemporaryDetach) mPreserveDetachedSelection = false;
+                if (mTemporaryDetach) {
+                    stopTextActionModeWithPreservingSelection();
+                } else {
+                    stopTextActionMode();
+                }
                 downgradeEasyCorrectionSpans();
             }
             // No need to create the controller
@@ -1290,10 +1282,8 @@
                 makeBlink();
             }
             final InputMethodManager imm = InputMethodManager.peekInstance();
-            final boolean immFullScreen = (imm != null && imm.isFullscreenMode());
-            if (mSelectionModifierCursorController != null && mTextView.hasSelection()
-                    && !immFullScreen && mTextActionMode != null) {
-                mSelectionModifierCursorController.show();
+            if (mTextView.hasSelection() && !extractedTextModeWillBeStarted()) {
+                startSelectionActionMode();
             }
         } else {
             if (mBlink != null) {
@@ -1304,9 +1294,7 @@
             }
             // Order matters! Must be done before onParentLostFocus to rely on isShowingUp
             hideCursorAndSpanControllers();
-            if (mSelectionModifierCursorController != null) {
-                mSelectionModifierCursorController.hide();
-            }
+            stopTextActionModeWithPreservingSelection();
             if (mSuggestionsPopupWindow != null) {
                 mSuggestionsPopupWindow.onParentLostFocus();
             }
@@ -1856,6 +1844,38 @@
         }
     }
 
+    void refreshTextActionMode() {
+        if (extractedTextModeWillBeStarted()) {
+            return;
+        }
+        final boolean hasSelection = mTextView.hasSelection();
+        final SelectionModifierCursorController selectionController = getSelectionController();
+        final InsertionPointCursorController insertionController = getInsertionController();
+        if ((selectionController != null && selectionController.isCursorBeingModified())
+                || (insertionController != null && insertionController.isCursorBeingModified())) {
+            // ActionMode should be managed by the currently active cursor controller.
+            return;
+        }
+        if (hasSelection) {
+            if (mTextActionMode == null || selectionController == null
+                    || !selectionController.isActive()) {
+                // Avoid dismissing the selection if it exists.
+                stopTextActionModeWithPreservingSelection();
+                startSelectionActionMode();
+            } else {
+                mTextActionMode.invalidateContentRect();
+            }
+        } else {
+            // Insertion action mode is started only when insertion controller is explicitly
+            // activated.
+            if (insertionController == null || !insertionController.isActive()) {
+                stopTextActionMode();
+            } else if (mTextActionMode != null) {
+                mTextActionMode.invalidateContentRect();
+            }
+        }
+    }
+
     /**
      * Start an Insertion action mode.
      */
@@ -1879,17 +1899,15 @@
 
     /**
      * Starts a Selection Action Mode with the current selection and ensures the selection handles
-     * are shown if there is a selection, otherwise the insertion handle is shown. This should be
-     * used when the mode is started from a non-touch event.
+     * are shown if there is a selection. This should be used when the mode is started from a
+     * non-touch event.
      *
      * @return true if the selection mode was actually started.
      */
-    boolean startSelectionActionMode() {
+    private boolean startSelectionActionMode() {
         boolean selectionStarted = startSelectionActionModeInternal();
         if (selectionStarted) {
             getSelectionController().show();
-        } else if (getInsertionController() != null) {
-            getInsertionController().show();
         }
         return selectionStarted;
     }
@@ -1907,66 +1925,52 @@
         if (extractedTextModeWillBeStarted()) {
             return false;
         }
-        if (mTextActionMode != null) {
-            mTextActionMode.finish();
-        }
-        if (!checkFieldAndSelectCurrentWord()) {
+        if (!checkField()) {
             return false;
         }
-
-        // Avoid dismissing the selection if it exists.
-        mPreserveDetachedSelection = true;
-        stopTextActionMode();
-        mPreserveDetachedSelection = false;
-
+        if (!mTextView.hasSelection() && !selectCurrentWord()) {
+            // No selection and cannot select a word.
+            return false;
+        }
+        stopTextActionModeWithPreservingSelection();
         getSelectionController().enterDrag(
                 SelectionModifierCursorController.DRAG_ACCELERATOR_MODE_WORD);
         return true;
     }
 
     /**
-     * Checks whether a selection can be performed on the current TextView and if so selects
-     * the current word.
+     * Checks whether a selection can be performed on the current TextView.
      *
-     * @return true if there already was a selection or if the current word was selected.
+     * @return true if a selection can be performed
      */
-    boolean checkFieldAndSelectCurrentWord() {
+    boolean checkField() {
         if (!mTextView.canSelectText() || !mTextView.requestFocus()) {
             Log.w(TextView.LOG_TAG,
                     "TextView does not support text selection. Selection cancelled.");
             return false;
         }
-
-        if (!mTextView.hasSelection()) {
-            // There may already be a selection on device rotation
-            return selectCurrentWord();
-        }
         return true;
     }
 
     private boolean startSelectionActionModeInternal() {
+        if (extractedTextModeWillBeStarted()) {
+            return false;
+        }
         if (mTextActionMode != null) {
             // Text action mode is already started
             mTextActionMode.invalidate();
             return false;
         }
 
-        if (!checkFieldAndSelectCurrentWord()) {
+        if (!checkField() || !mTextView.hasSelection()) {
             return false;
         }
 
-        boolean willExtract = extractedTextModeWillBeStarted();
+        ActionMode.Callback actionModeCallback =
+                new TextActionModeCallback(true /* hasSelection */);
+        mTextActionMode = mTextView.startActionMode(actionModeCallback, ActionMode.TYPE_FLOATING);
 
-        // Do not start the action mode when extracted text will show up full screen, which would
-        // immediately hide the newly created action bar and would be visually distracting.
-        if (!willExtract) {
-            ActionMode.Callback actionModeCallback =
-                    new TextActionModeCallback(true /* hasSelection */);
-            mTextActionMode = mTextView.startActionMode(
-                    actionModeCallback, ActionMode.TYPE_FLOATING);
-        }
-
-        final boolean selectionStarted = mTextActionMode != null || willExtract;
+        final boolean selectionStarted = mTextActionMode != null;
         if (selectionStarted && !mTextView.isTextSelectable() && mShowSoftInputOnFocus) {
             // Show the IME to be able to replace text, except when selecting non editable text.
             final InputMethodManager imm = InputMethodManager.peekInstance();
@@ -2087,7 +2091,7 @@
 
                     mShowSuggestionRunnable = new Runnable() {
                         public void run() {
-                            showSuggestions();
+                            replace();
                         }
                     };
                     // removeCallbacks is performed on every touch
@@ -2107,6 +2111,12 @@
         }
     }
 
+    private void stopTextActionModeWithPreservingSelection() {
+        mPreserveSelection = true;
+        stopTextActionMode();
+        mPreserveSelection = false;
+    }
+
     /**
      * @return True if this view supports insertion handles.
      */
@@ -2222,15 +2232,6 @@
         mCorrectionHighlighter.highlight(info);
     }
 
-    void showSuggestions() {
-        if (mSuggestionsPopupWindow == null) {
-            mSuggestionsPopupWindow = new SuggestionsPopupWindow();
-        }
-        hideCursorAndSpanControllers();
-        stopTextActionMode();
-        mSuggestionsPopupWindow.show();
-    }
-
     void onScrollChanged() {
         if (mPositionListener != null) {
             mPositionListener.onScrollChanged();
@@ -2394,17 +2395,22 @@
                 dragSourceEnd += shift;
             }
 
-            // Delete original selection
-            mTextView.deleteText_internal(dragSourceStart, dragSourceEnd);
+            mUndoInputFilter.setForceMerge(true);
+            try {
+                // Delete original selection
+                mTextView.deleteText_internal(dragSourceStart, dragSourceEnd);
 
-            // Make sure we do not leave two adjacent spaces.
-            final int prevCharIdx = Math.max(0,  dragSourceStart - 1);
-            final int nextCharIdx = Math.min(mTextView.getText().length(), dragSourceStart + 1);
-            if (nextCharIdx > prevCharIdx + 1) {
-                CharSequence t = mTextView.getTransformedText(prevCharIdx, nextCharIdx);
-                if (Character.isSpaceChar(t.charAt(0)) && Character.isSpaceChar(t.charAt(1))) {
-                    mTextView.deleteText_internal(prevCharIdx, prevCharIdx + 1);
+                // Make sure we do not leave two adjacent spaces.
+                final int prevCharIdx = Math.max(0,  dragSourceStart - 1);
+                final int nextCharIdx = Math.min(mTextView.getText().length(), dragSourceStart + 1);
+                if (nextCharIdx > prevCharIdx + 1) {
+                    CharSequence t = mTextView.getTransformedText(prevCharIdx, nextCharIdx);
+                    if (Character.isSpaceChar(t.charAt(0)) && Character.isSpaceChar(t.charAt(1))) {
+                        mTextView.deleteText_internal(prevCharIdx, prevCharIdx + 1);
+                    }
                 }
+            } finally {
+                mUndoInputFilter.setForceMerge(false);
             }
         }
     }
@@ -2436,34 +2442,35 @@
         if (offset == -1) {
             return;
         }
-        mPreserveDetachedSelection = true;
-        stopTextActionMode();
-        mPreserveDetachedSelection = false;
+        stopTextActionModeWithPreservingSelection();
         final boolean isOnSelection = mTextView.hasSelection()
                 && offset >= mTextView.getSelectionStart() && offset <= mTextView.getSelectionEnd();
         if (!isOnSelection) {
             // Right clicked position is not on the selection. Remove the selection and move the
             // cursor to the right clicked position.
-            stopTextActionMode();
             Selection.setSelection((Spannable) mTextView.getText(), offset);
+            stopTextActionMode();
         }
 
         if (shouldOfferToShowSuggestions()) {
-            if (mSuggestionInfosInContextMenu == null) {
-                mSuggestionInfosInContextMenu =
-                        new SuggestionInfo[SuggestionSpan.SUGGESTIONS_MAX_SIZE];
-                for (int i = 0; i < mSuggestionInfosInContextMenu.length; i++) {
-                    mSuggestionInfosInContextMenu[i] = new SuggestionInfo();
-                }
+            final SuggestionInfo[] suggestionInfoArray =
+                    new SuggestionInfo[SuggestionSpan.SUGGESTIONS_MAX_SIZE];
+            for (int i = 0; i < suggestionInfoArray.length; i++) {
+                suggestionInfoArray[i] = new SuggestionInfo();
             }
             final SubMenu subMenu = menu.addSubMenu(Menu.NONE, Menu.NONE, MENU_ITEM_ORDER_REPLACE,
                     com.android.internal.R.string.replace);
-            mSuggestionHelper.getSuggestionInfo(mSuggestionInfosInContextMenu);
-            int i = 0;
-            for (final SuggestionInfo info : mSuggestionInfosInContextMenu) {
-                info.mSuggestionEnd = info.mText.length();
-                subMenu.add(Menu.NONE, Menu.NONE, i++, info.mText)
-                        .setOnMenuItemClickListener(mOnContextMenuReplaceItemClickListener);
+            final int numItems = mSuggestionHelper.getSuggestionInfo(suggestionInfoArray);
+            for (int i = 0; i < numItems; i++) {
+                final SuggestionInfo info = suggestionInfoArray[i];
+                subMenu.add(Menu.NONE, Menu.NONE, i, info.mText)
+                        .setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
+                            @Override
+                            public boolean onMenuItemClick(MenuItem item) {
+                                replaceWithSuggestion(info);
+                                return true;
+                            }
+                        });
             }
         }
 
@@ -2506,11 +2513,40 @@
                 .setEnabled(mTextView.canSelectAllText())
                 .setOnMenuItemClickListener(mOnContextMenuItemClickListener);
 
-        mPreserveDetachedSelection = true;
+        mPreserveSelection = true;
     }
 
-    private void replaceWithSuggestion(SuggestionInfo suggestionInfo, int spanStart, int spanEnd) {
+    private void replaceWithSuggestion(final SuggestionInfo suggestionInfo) {
         final Editable editable = (Editable) mTextView.getText();
+        if (editable.getSpanStart(suggestionInfo.mSuggestionSpan) < 0) {
+            // Suggestion span coundn't be found. Try to find a suggestion span that has the same
+            // contents.
+            final SuggestionSpan[] suggestionSpans = editable.getSpans(
+                    suggestionInfo.mSuggestionSpanStart, suggestionInfo.mSuggestionSpanEnd,
+                    SuggestionSpan.class);
+            for (final SuggestionSpan suggestionSpan : suggestionSpans) {
+                final int spanStart = editable.getSpanStart(suggestionSpan);
+                if (spanStart != suggestionInfo.mSuggestionSpanStart) {
+                    continue;
+                }
+                int spanEnd = editable.getSpanEnd(suggestionSpan);
+                if (spanEnd != suggestionInfo.mSuggestionSpanEnd) {
+                    continue;
+                }
+                if (suggestionSpan.equals(suggestionInfo.mSuggestionSpan)) {
+                    // Found.
+                    suggestionInfo.mSuggestionSpan = suggestionSpan;
+                    break;
+                }
+            }
+        }
+        final int spanStart = editable.getSpanStart(suggestionInfo.mSuggestionSpan);
+        final int spanEnd = editable.getSpanEnd(suggestionInfo.mSuggestionSpan);
+        if (spanStart < 0 || spanEnd <= spanStart) {
+            // Span has been removed
+            return;
+        }
+
         final String originalText = TextUtils.substring(editable, spanStart, spanEnd);
         // SuggestionSpans are removed by replace: save them before
         SuggestionSpan[] suggestionSpans = editable.getSpans(spanStart, spanEnd,
@@ -2575,31 +2611,6 @@
         }
     };
 
-    private final MenuItem.OnMenuItemClickListener mOnContextMenuReplaceItemClickListener =
-            new MenuItem.OnMenuItemClickListener() {
-        @Override
-        public boolean onMenuItemClick(MenuItem item) {
-            int index = item.getOrder();
-            if (index < 0 || index >= mSuggestionInfosInContextMenu.length) {
-                clear();
-                return false;
-            }
-            final Spannable spannable = (Spannable) mTextView.getText();
-            final SuggestionSpan suggestionSpan =
-                    mSuggestionInfosInContextMenu[index].mSuggestionSpan;
-            replaceWithSuggestion(mSuggestionInfosInContextMenu[index],
-                    spannable.getSpanStart(suggestionSpan), spannable.getSpanEnd(suggestionSpan));
-            clear();
-            return true;
-        }
-
-        private void clear() {
-            for (final SuggestionInfo info : mSuggestionInfosInContextMenu) {
-                info.clear();
-            }
-        }
-    };
-
     /**
      * Controls the {@link EasyEditSpan} monitoring when it is added, and when the related
      * pop-up should be displayed.
@@ -3019,13 +3030,19 @@
     }
 
     private static class SuggestionInfo {
-        // Range of actual suggestion within text
+        // Range of actual suggestion within mText
         int mSuggestionStart, mSuggestionEnd;
 
         // The SuggestionSpan that this TextView represents
         @Nullable
         SuggestionSpan mSuggestionSpan;
 
+        // The SuggestionSpan start position
+        int mSuggestionSpanStart;
+
+        // The SuggestionSpan end position
+        int mSuggestionSpanEnd;
+
         // The index of this suggestion inside suggestionSpan
         int mSuggestionIndex;
 
@@ -3132,6 +3149,8 @@
                     suggestionInfo.mSuggestionIndex = suggestionIndex;
                     suggestionInfo.mSuggestionStart = 0;
                     suggestionInfo.mSuggestionEnd = suggestion.length();
+                    suggestionInfo.mSuggestionSpanStart = spanStart;
+                    suggestionInfo.mSuggestionSpanEnd = spanEnd;
                     suggestionInfo.mText.replace(0, suggestionInfo.mText.length(), suggestion);
                     numberOfSuggestions++;
                     if (numberOfSuggestions >= suggestionInfos.length) {
@@ -3160,6 +3179,7 @@
                 mTextView.getContext(), mTextView.mTextEditSuggestionHighlightStyle);
         private TextView mAddToDictionaryButton;
         private TextView mDeleteButton;
+        private ListView mSuggestionListView;
         private SuggestionSpan mMisspelledSpan;
         private int mContainerMarginWidth;
         private int mContainerMarginTop;
@@ -3177,7 +3197,7 @@
                 ((Spannable) mTextView.getText()).removeSpan(mSuggestionRangeSpan);
 
                 mTextView.setCursorVisible(mCursorWasVisibleBeforeSuggestions);
-                if (hasInsertionController()) {
+                if (hasInsertionController() && !extractedTextModeWillBeStarted()) {
                     getInsertionController().show();
                 }
             }
@@ -3213,12 +3233,12 @@
             mClippingLimitLeft = lp.leftMargin;
             mClippingLimitRight = lp.rightMargin;
 
-            final ListView suggestionListView = (ListView) relativeLayout.findViewById(
+            mSuggestionListView = (ListView) relativeLayout.findViewById(
                     com.android.internal.R.id.suggestionContainer);
 
             mSuggestionsAdapter = new SuggestionAdapter();
-            suggestionListView.setAdapter(mSuggestionsAdapter);
-            suggestionListView.setOnItemClickListener(this);
+            mSuggestionListView.setAdapter(mSuggestionsAdapter);
+            mSuggestionListView.setOnItemClickListener(this);
 
             // Inflate the suggestion items once and for all.
             mSuggestionInfos = new SuggestionInfo[MAX_NUMBER_SUGGESTIONS];
@@ -3327,6 +3347,9 @@
         @Override
         public void show() {
             if (!(mTextView.getText() instanceof Editable)) return;
+            if (extractedTextModeWillBeStarted()) {
+                return;
+            }
 
             if (updateSuggestions()) {
                 mCursorWasVisibleBeforeSuggestions = mCursorVisible;
@@ -3374,12 +3397,13 @@
                 popupBackground.getPadding(mTempRect);
                 width += mTempRect.left + mTempRect.right;
             }
+            mSuggestionListView.getLayoutParams().width = width;
             mPopupWindow.setWidth(width);
         }
 
         @Override
         protected int getTextOffset() {
-            return mTextView.getSelectionStart();
+            return (mTextView.getSelectionStart() + mTextView.getSelectionStart()) / 2;
         }
 
         @Override
@@ -3420,10 +3444,8 @@
                 if ((suggestionSpan.getFlags() & SuggestionSpan.FLAG_MISSPELLED) != 0) {
                     mMisspelledSpan = suggestionSpan;
                 }
-                final int spanStart = spannable.getSpanStart(suggestionSpan);
-                final int spanEnd = spannable.getSpanEnd(suggestionSpan);
-                spanUnionStart = Math.min(spanUnionStart, spanStart);
-                spanUnionEnd = Math.max(spanUnionEnd, spanEnd);
+                spanUnionStart = Math.min(spanUnionStart, suggestionInfo.mSuggestionSpanStart);
+                spanUnionEnd = Math.max(spanUnionEnd, suggestionInfo.mSuggestionSpanEnd);
             }
 
             for (int i = 0; i < mNumberOfSuggestions; i++) {
@@ -3462,8 +3484,8 @@
         private void highlightTextDifferences(SuggestionInfo suggestionInfo, int unionStart,
                 int unionEnd) {
             final Spannable text = (Spannable) mTextView.getText();
-            final int spanStart = text.getSpanStart(suggestionInfo.mSuggestionSpan);
-            final int spanEnd = text.getSpanEnd(suggestionInfo.mSuggestionSpan);
+            final int spanStart = suggestionInfo.mSuggestionSpanStart;
+            final int spanEnd = suggestionInfo.mSuggestionSpanEnd;
 
             // Adjust the start/end of the suggestion span
             suggestionInfo.mSuggestionStart = spanStart - unionStart;
@@ -3481,17 +3503,8 @@
 
         @Override
         public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
-            Editable editable = (Editable) mTextView.getText();
             SuggestionInfo suggestionInfo = mSuggestionInfos[position];
-
-            final int spanStart = editable.getSpanStart(suggestionInfo.mSuggestionSpan);
-            final int spanEnd = editable.getSpanEnd(suggestionInfo.mSuggestionSpan);
-            if (spanStart < 0 || spanEnd <= spanStart) {
-                // Span has been removed
-                hideWithCleanUp();
-                return;
-            }
-            replaceWithSuggestion(suggestionInfo, spanStart, spanEnd);
+            replaceWithSuggestion(suggestionInfo);
             hideWithCleanUp();
         }
     }
@@ -3554,7 +3567,6 @@
             }
 
             if (menu.hasVisibleItems() || mode.getCustomView() != null) {
-                mTextView.setHasTransientState(true);
                 return true;
             } else {
                 return false;
@@ -3624,8 +3636,7 @@
         }
 
         private void updateReplaceItem(Menu menu) {
-            boolean canReplace = mTextView.isSuggestionsEnabled() && shouldOfferToShowSuggestions()
-                    && !(mTextView.isInExtractedMode() && mTextView.hasSelection());
+            boolean canReplace = mTextView.isSuggestionsEnabled() && shouldOfferToShowSuggestions();
             boolean replaceItemExists = menu.findItem(TextView.ID_REPLACE) != null;
             if (canReplace && !replaceItemExists) {
                 menu.add(Menu.NONE, TextView.ID_REPLACE, MENU_ITEM_ORDER_REPLACE,
@@ -3655,15 +3666,14 @@
                 customCallback.onDestroyActionMode(mode);
             }
 
-            /*
-             * If we're ending this mode because we're detaching from a window,
-             * we still have selection state to preserve. Don't clear it, we'll
-             * bring back the selection mode when (if) we get reattached.
-             */
-            if (!mPreserveDetachedSelection) {
+            if (!mPreserveSelection) {
+                /*
+                 * Leave current selection when we tentatively destroy action mode for the
+                 * selection. If we're detaching from a window, we'll bring back the selection
+                 * mode when (if) we get reattached.
+                 */
                 Selection.setSelection((Spannable) mTextView.getText(),
                         mTextView.getSelectionEnd());
-                mTextView.setHasTransientState(false);
             }
 
             if (mSelectionModifierCursorController != null) {
@@ -4386,7 +4396,7 @@
                         if (distanceSquared < touchSlop * touchSlop) {
                             // Tapping on the handle toggles the insertion action mode.
                             if (mTextActionMode != null) {
-                                mTextActionMode.finish();
+                                stopTextActionMode();
                             } else {
                                 startInsertionActionMode();
                             }
@@ -4803,6 +4813,10 @@
          * preventing the activity from being recycled.
          */
         public void onDetached();
+
+        public boolean isCursorBeingModified();
+
+        public boolean isActive();
     }
 
     private class InsertionPointCursorController implements CursorController {
@@ -4846,6 +4860,16 @@
 
             if (mHandle != null) mHandle.onDetached();
         }
+
+        @Override
+        public boolean isCursorBeingModified() {
+            return mHandle != null && mHandle.isDragging();
+        }
+
+        @Override
+        public boolean isActive() {
+            return mHandle != null && mHandle.isShowing();
+        }
     }
 
     class SelectionModifierCursorController implements CursorController {
@@ -5035,9 +5059,7 @@
 
                         if (mStartOffset != offset) {
                             // Start character based drag accelerator.
-                            if (mTextActionMode != null) {
-                                mTextActionMode.finish();
-                            }
+                            stopTextActionMode();
                             enterDrag(DRAG_ACCELERATOR_MODE_CHARACTER);
                             mDiscardNextActionUp = true;
                             mHaventMovedEnoughToStartDrag = false;
@@ -5111,9 +5133,7 @@
             if (mInsertionActionModeRunnable != null) {
                 mTextView.removeCallbacks(mInsertionActionModeRunnable);
             }
-            if (mTextActionMode != null) {
-                mTextActionMode.finish();
-            }
+            stopTextActionMode();
             if (!selectCurrentParagraph()) {
                 return false;
             }
@@ -5222,6 +5242,12 @@
             mStartOffset = -1;
             mDragAcceleratorMode = DRAG_ACCELERATOR_MODE_INACTIVE;
             mSwitchedLines = false;
+            final int selectionStart = mTextView.getSelectionStart();
+            final int selectionEnd = mTextView.getSelectionEnd();
+            if (selectionStart > selectionEnd) {
+                Selection.setSelection((Spannable) mTextView.getText(),
+                        selectionEnd, selectionStart);
+            }
         }
 
         /**
@@ -5231,6 +5257,12 @@
             return mStartHandle != null && mStartHandle.isDragging();
         }
 
+        @Override
+        public boolean isCursorBeingModified() {
+            return isDragAcceleratorActive() || isSelectionStartDragged()
+                    || (mEndHandle != null && mEndHandle.isDragging());
+        }
+
         /**
          * @return true if the user is selecting text using the drag accelerator.
          */
@@ -5252,6 +5284,11 @@
             if (mStartHandle != null) mStartHandle.onDetached();
             if (mEndHandle != null) mEndHandle.onDetached();
         }
+
+        @Override
+        public boolean isActive() {
+            return mStartHandle != null && mStartHandle.isShowing();
+        }
     }
 
     private class CorrectionHighlighter {
@@ -5447,6 +5484,9 @@
         // rotates the screen during composition.
         private boolean mHasComposition;
 
+        // Whether to merge events into one operation.
+        private boolean mForceMerge;
+
         public UndoInputFilter(Editor editor) {
             mEditor = editor;
         }
@@ -5461,6 +5501,10 @@
             mHasComposition = parcel.readInt() != 0;
         }
 
+        public void setForceMerge(boolean forceMerge) {
+            mForceMerge = forceMerge;
+        }
+
         /**
          * Signals that a user-triggered edit is starting.
          */
@@ -5520,7 +5564,7 @@
                 // Otherwise the user inserted the composition.
                 String newText = TextUtils.substring(source, start, end);
                 EditOperation edit = new EditOperation(mEditor, "", dstart, newText);
-                recordEdit(edit, false /* forceMerge */);
+                recordEdit(edit, mForceMerge);
                 return true;
             }
 
@@ -5534,7 +5578,7 @@
             // the initial input filters run (e.g. a credit card formatter that adds spaces to a
             // string). This results in multiple filter() calls for what the user considers to be
             // a single operation. Always undo the whole set of changes in one step.
-            final boolean forceMerge = isInTextWatcher();
+            final boolean forceMerge = mForceMerge || isInTextWatcher();
 
             // Build a new operation with all the information from this edit.
             String newText = TextUtils.substring(source, start, end);
@@ -5975,7 +6019,7 @@
         private boolean fireIntent(Intent intent) {
             if (intent != null && Intent.ACTION_PROCESS_TEXT.equals(intent.getAction())) {
                 intent.putExtra(Intent.EXTRA_PROCESS_TEXT, mTextView.getSelectedText());
-                mEditor.mPreserveDetachedSelection = true;
+                mEditor.mPreserveSelection = true;
                 mTextView.startActivityForResult(intent, TextView.PROCESS_TEXT_REQUEST_CODE);
                 return true;
             }
diff --git a/core/java/android/widget/ImageView.java b/core/java/android/widget/ImageView.java
index f601f7d..3400873 100644
--- a/core/java/android/widget/ImageView.java
+++ b/core/java/android/widget/ImageView.java
@@ -212,7 +212,7 @@
     }
 
     @Override
-    protected boolean verifyDrawable(Drawable dr) {
+    protected boolean verifyDrawable(@NonNull Drawable dr) {
         return mDrawable == dr || super.verifyDrawable(dr);
     }
 
@@ -223,7 +223,7 @@
     }
 
     @Override
-    public void invalidateDrawable(Drawable dr) {
+    public void invalidateDrawable(@NonNull Drawable dr) {
         if (dr == mDrawable) {
             if (dr != null) {
                 // update cached drawable dimensions if they've changed
diff --git a/core/java/android/widget/PopupWindow.java b/core/java/android/widget/PopupWindow.java
index 54b3932..dd6a41f 100644
--- a/core/java/android/widget/PopupWindow.java
+++ b/core/java/android/widget/PopupWindow.java
@@ -23,7 +23,6 @@
 
 import android.annotation.NonNull;
 import android.content.Context;
-import android.content.res.Resources;
 import android.content.res.TypedArray;
 import android.graphics.PixelFormat;
 import android.graphics.Rect;
@@ -1587,18 +1586,16 @@
     public int getMaxAvailableHeight(
             @NonNull View anchor, int yOffset, boolean ignoreBottomDecorations) {
         final Rect displayFrame = new Rect();
-        anchor.getWindowVisibleDisplayFrame(displayFrame);
+        if (ignoreBottomDecorations) {
+            anchor.getWindowDisplayFrame(displayFrame);
+        } else {
+            anchor.getWindowVisibleDisplayFrame(displayFrame);
+        }
 
         final int[] anchorPos = mDrawingLocation;
         anchor.getLocationOnScreen(anchorPos);
 
-        final int bottomEdge;
-        if (ignoreBottomDecorations) {
-            final Resources res = anchor.getContext().getResources();
-            bottomEdge = res.getDisplayMetrics().heightPixels;
-        } else {
-            bottomEdge = displayFrame.bottom;
-        }
+        final int bottomEdge = displayFrame.bottom;
 
         final int distanceToBottom;
         if (mOverlapAnchor) {
@@ -1654,10 +1651,11 @@
         // to executing this method, so we can rely on that instead.
         final Transition exitTransition = mExitTransition;
         if (mIsAnchorRootAttached && exitTransition != null && decorView.isLaidOut()) {
-            // The decor view is non-interactive during exit transitions.
+            // The decor view is non-interactive and non-IME-focusable during exit transitions.
             final LayoutParams p = (LayoutParams) decorView.getLayoutParams();
             p.flags |= LayoutParams.FLAG_NOT_TOUCHABLE;
             p.flags |= LayoutParams.FLAG_NOT_FOCUSABLE;
+            p.flags &= ~LayoutParams.FLAG_ALT_FOCUSABLE_IM;
             mWindowManager.updateViewLayout(decorView, p);
 
             // Once we start dismissing the decor view, all state (including
diff --git a/core/java/android/widget/ProgressBar.java b/core/java/android/widget/ProgressBar.java
index 2099b04..ce94870 100644
--- a/core/java/android/widget/ProgressBar.java
+++ b/core/java/android/widget/ProgressBar.java
@@ -17,21 +17,15 @@
 package android.widget;
 
 import android.animation.ObjectAnimator;
+import android.annotation.InterpolatorRes;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
-import android.graphics.PorterDuff;
-
-import android.util.FloatProperty;
-import android.util.IntProperty;
-import android.view.accessibility.AccessibilityNodeInfo;
-import com.android.internal.R;
-
-import android.annotation.InterpolatorRes;
 import android.content.Context;
 import android.content.res.ColorStateList;
 import android.content.res.TypedArray;
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
+import android.graphics.PorterDuff;
 import android.graphics.Rect;
 import android.graphics.Shader;
 import android.graphics.drawable.Animatable;
@@ -46,6 +40,7 @@
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.util.AttributeSet;
+import android.util.FloatProperty;
 import android.util.MathUtils;
 import android.util.Pools.SynchronizedPool;
 import android.view.Gravity;
@@ -55,6 +50,7 @@
 import android.view.ViewHierarchyEncoder;
 import android.view.accessibility.AccessibilityEvent;
 import android.view.accessibility.AccessibilityManager;
+import android.view.accessibility.AccessibilityNodeInfo;
 import android.view.animation.AlphaAnimation;
 import android.view.animation.Animation;
 import android.view.animation.AnimationUtils;
@@ -63,6 +59,7 @@
 import android.view.animation.LinearInterpolator;
 import android.view.animation.Transformation;
 import android.widget.RemoteViews.RemoteView;
+import com.android.internal.R;
 
 import java.util.ArrayList;
 
@@ -606,15 +603,30 @@
 
             if (indeterminate) {
                 // swap between indeterminate and regular backgrounds
-                mCurrentDrawable = mIndeterminateDrawable;
+                swapCurrentDrawable(mIndeterminateDrawable);
                 startAnimation();
             } else {
-                mCurrentDrawable = mProgressDrawable;
+                swapCurrentDrawable(mProgressDrawable);
                 stopAnimation();
             }
         }
     }
 
+    private void swapCurrentDrawable(Drawable newDrawable) {
+        final Drawable oldDrawable = mCurrentDrawable;
+        mCurrentDrawable = newDrawable;
+        if (oldDrawable != mCurrentDrawable) {
+            if (oldDrawable != null) {
+                oldDrawable.setVisible(false, false);
+            }
+            if (mCurrentDrawable != null) {
+                mCurrentDrawable.setVisible(
+                        getVisibility() == VISIBLE && getWindowVisibility() == VISIBLE,
+                        false);
+            }
+        }
+    }
+
     /**
      * <p>Get the drawable used to draw the progress bar in
      * indeterminate mode.</p>
@@ -654,7 +666,7 @@
             }
 
             if (mIndeterminate) {
-                mCurrentDrawable = d;
+                swapCurrentDrawable(d);
                 postInvalidate();
             }
         }
@@ -820,7 +832,7 @@
             }
 
             if (!mIndeterminate) {
-                mCurrentDrawable = d;
+                swapCurrentDrawable(d);
                 postInvalidate();
             }
 
@@ -1217,7 +1229,7 @@
     }
 
     @Override
-    protected boolean verifyDrawable(Drawable who) {
+    protected boolean verifyDrawable(@NonNull Drawable who) {
         return who == mProgressDrawable || who == mIndeterminateDrawable
                 || super.verifyDrawable(who);
     }
@@ -1555,7 +1567,7 @@
      * <p>Start the indeterminate progress animation.</p>
      */
     void startAnimation() {
-        if (getVisibility() != VISIBLE) {
+        if (getVisibility() != VISIBLE || getWindowVisibility() != VISIBLE) {
             return;
         }
 
@@ -1653,18 +1665,34 @@
     protected void onVisibilityChanged(View changedView, int visibility) {
         super.onVisibilityChanged(changedView, visibility);
 
+        updateVisibility();
+    }
+
+    @Override
+    protected void onWindowVisibilityChanged(@Visibility int visibility) {
+        super.onWindowVisibilityChanged(visibility);
+
+        updateVisibility();
+    }
+
+    private void updateVisibility() {
+        final boolean isVisible = getVisibility() == VISIBLE && getWindowVisibility() == VISIBLE;
         if (mIndeterminate) {
             // let's be nice with the UI thread
-            if (visibility == GONE || visibility == INVISIBLE) {
-                stopAnimation();
-            } else {
+            if (isVisible) {
                 startAnimation();
+            } else {
+                stopAnimation();
             }
         }
+
+        if (mCurrentDrawable != null) {
+            mCurrentDrawable.setVisible(isVisible, false);
+        }
     }
 
     @Override
-    public void invalidateDrawable(Drawable dr) {
+    public void invalidateDrawable(@NonNull Drawable dr) {
         if (!mInDrawing) {
             if (verifyDrawable(dr)) {
                 final Rect dirty = dr.getBounds();
diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java
index 1cccfae..063288e 100644
--- a/core/java/android/widget/RemoteViews.java
+++ b/core/java/android/widget/RemoteViews.java
@@ -2563,6 +2563,8 @@
      * @param format The Chronometer format string, or null to
      *               simply display the timer value.
      * @param started True if you want the clock to be started, false if not.
+     *
+     * @see #setChronometerCountsDown(int, boolean)
      */
     public void setChronometer(int viewId, long base, String format, boolean started) {
         setLong(viewId, "setBase", base);
@@ -2571,6 +2573,18 @@
     }
 
     /**
+     * Equivalent to calling {@link Chronometer#setCountDown(boolean) Chronometer.setCountDown} on
+     * the chronometer with the given viewId.
+     *
+     * @param viewId The id of the {@link Chronometer} to change
+     * @param isCountDown True if you want the chronometer to count down to base instead of
+     *                    counting up.
+     */
+    public void setChronometerCountsDown(int viewId, boolean isCountDown) {
+        setBoolean(viewId, "setCountDown", isCountDown);
+    }
+
+    /**
      * Equivalent to calling {@link ProgressBar#setMax ProgressBar.setMax},
      * {@link ProgressBar#setProgress ProgressBar.setProgress}, and
      * {@link ProgressBar#setIndeterminate ProgressBar.setIndeterminate}
diff --git a/core/java/android/widget/ScrollBarDrawable.java b/core/java/android/widget/ScrollBarDrawable.java
index 8880217..11eab2a 100644
--- a/core/java/android/widget/ScrollBarDrawable.java
+++ b/core/java/android/widget/ScrollBarDrawable.java
@@ -18,6 +18,7 @@
 
 import com.android.internal.widget.ScrollBarUtils;
 
+import android.annotation.NonNull;
 import android.graphics.Canvas;
 import android.graphics.ColorFilter;
 import android.graphics.PixelFormat;
@@ -362,17 +363,17 @@
     }
 
     @Override
-    public void invalidateDrawable(Drawable who) {
+    public void invalidateDrawable(@NonNull Drawable who) {
         invalidateSelf();
     }
 
     @Override
-    public void scheduleDrawable(Drawable who, Runnable what, long when) {
+    public void scheduleDrawable(@NonNull Drawable who, @NonNull Runnable what, long when) {
         scheduleSelf(what, when);
     }
 
     @Override
-    public void unscheduleDrawable(Drawable who, Runnable what) {
+    public void unscheduleDrawable(@NonNull Drawable who, @NonNull Runnable what) {
         unscheduleSelf(what);
     }
 
diff --git a/core/java/android/widget/SearchView.java b/core/java/android/widget/SearchView.java
index 3796df7..9a4d69f 100644
--- a/core/java/android/widget/SearchView.java
+++ b/core/java/android/widget/SearchView.java
@@ -1358,6 +1358,17 @@
                     + Integer.toHexString(System.identityHashCode(this))
                     + " isIconified=" + isIconified + "}";
         }
+
+        public static final Parcelable.Creator<SavedState> CREATOR =
+                new Parcelable.Creator<SavedState>() {
+                    public SavedState createFromParcel(Parcel in) {
+                        return new SavedState(in);
+                    }
+
+                    public SavedState[] newArray(int size) {
+                        return new SavedState[size];
+                    }
+                };
     }
 
     @Override
diff --git a/core/java/android/widget/SimpleMonthView.java b/core/java/android/widget/SimpleMonthView.java
index 6edce91..43cf5a1 100644
--- a/core/java/android/widget/SimpleMonthView.java
+++ b/core/java/android/widget/SimpleMonthView.java
@@ -33,6 +33,7 @@
 import android.text.format.DateFormat;
 import android.util.AttributeSet;
 import android.util.IntArray;
+import android.util.Log;
 import android.util.MathUtils;
 import android.util.StateSet;
 import android.view.KeyEvent;
@@ -47,6 +48,7 @@
 import com.android.internal.widget.ExploreByTouchHelper;
 
 import java.text.NumberFormat;
+import java.util.Arrays;
 import java.util.Calendar;
 import java.util.Locale;
 
@@ -55,17 +57,22 @@
  * within the specified month.
  */
 class SimpleMonthView extends View {
+    private static final String LOG_TAG = "SimpleMonthView";
+
     private static final int DAYS_IN_WEEK = 7;
     private static final int MAX_WEEKS_IN_MONTH = 6;
 
     private static final int DEFAULT_SELECTED_DAY = -1;
     private static final int DEFAULT_WEEK_START = Calendar.SUNDAY;
 
-    private static final String DEFAULT_TITLE_FORMAT = "MMMMy";
+    private static final String MONTH_YEAR_FORMAT = "MMMMy";
     private static final String DAY_OF_WEEK_FORMAT = "EEEEE";
 
     private static final int SELECTED_HIGHLIGHT_ALPHA = 0xB0;
 
+    /** Temporary until we figure out why the date gets messed up. */
+    private static final boolean DEBUG_WRONG_DATE = true;
+
     private final TextPaint mMonthPaint = new TextPaint();
     private final TextPaint mDayOfWeekPaint = new TextPaint();
     private final TextPaint mDayPaint = new TextPaint();
@@ -73,13 +80,13 @@
     private final Paint mDayHighlightPaint = new Paint();
     private final Paint mDayHighlightSelectorPaint = new Paint();
 
-    private final Calendar mCalendar = Calendar.getInstance();
-    private final Calendar mDayOfWeekLabelCalendar = Calendar.getInstance();
+    private final String[] mDayOfWeekLabels = new String[7];
+
+    private final Calendar mCalendar;
+    private final Locale mLocale;
 
     private final MonthViewTouchHelper mTouchHelper;
 
-    private final SimpleDateFormat mTitleFormatter;
-    private final SimpleDateFormat mDayOfWeekFormatter;
     private final NumberFormat mDayFormatter;
 
     // Desired dimensions.
@@ -89,7 +96,7 @@
     private final int mDesiredCellWidth;
     private final int mDesiredDaySelectorRadius;
 
-    private CharSequence mTitle;
+    private String mMonthYearLabel;
 
     private int mMonth;
     private int mYear;
@@ -168,15 +175,44 @@
         setAccessibilityDelegate(mTouchHelper);
         setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES);
 
-        final Locale locale = res.getConfiguration().locale;
-        final String titleFormat = DateFormat.getBestDateTimePattern(locale, DEFAULT_TITLE_FORMAT);
-        mTitleFormatter = new SimpleDateFormat(titleFormat, locale);
-        mDayOfWeekFormatter = new SimpleDateFormat(DAY_OF_WEEK_FORMAT, locale);
-        mDayFormatter = NumberFormat.getIntegerInstance(locale);
+        mLocale = res.getConfiguration().locale;
+        mCalendar = Calendar.getInstance(mLocale);
+
+        mDayFormatter = NumberFormat.getIntegerInstance(mLocale);
+
+        updateMonthYearLabel();
+        updateDayOfWeekLabels();
 
         initPaints(res);
     }
 
+    private void updateMonthYearLabel() {
+        final String format = DateFormat.getBestDateTimePattern(mLocale, MONTH_YEAR_FORMAT);
+        final SimpleDateFormat formatter = new SimpleDateFormat(format, mLocale);
+        mMonthYearLabel = formatter.format(mCalendar.getTime());
+    }
+
+    private void updateDayOfWeekLabels() {
+        if (DEBUG_WRONG_DATE) {
+            Log.d(LOG_TAG, "enter updateDayOfWeekLabels()", new Exception());
+            Log.d(LOG_TAG, "mLocale => " + mLocale);
+            Log.d(LOG_TAG, "mWeekStart => " + mWeekStart);
+        }
+
+        final Calendar calendar = Calendar.getInstance(mLocale);
+        calendar.setFirstDayOfWeek(mWeekStart);
+
+        final SimpleDateFormat formatter = new SimpleDateFormat(DAY_OF_WEEK_FORMAT, mLocale);
+        for (int i = 0; i < 7; i++) {
+            calendar.set(Calendar.DAY_OF_WEEK, i);
+            mDayOfWeekLabels[i] = formatter.format(calendar.getTime());
+        }
+
+        if (DEBUG_WRONG_DATE) {
+            Log.d(LOG_TAG, "mDayOfWeekLabels <= " + Arrays.toString(mDayOfWeekLabels));
+        }
+    }
+
     /**
      * Applies the specified text appearance resource to a paint, returning the
      * text color if one is set in the text appearance.
@@ -236,13 +272,6 @@
         invalidate();
     }
 
-    public CharSequence getTitle() {
-        if (mTitle == null) {
-            mTitle = mTitleFormatter.format(mCalendar.getTime());
-        }
-        return mTitle;
-    }
-
     /**
      * Sets up the text and style properties for painting.
      */
@@ -607,7 +636,11 @@
         final float lineHeight = mMonthPaint.ascent() + mMonthPaint.descent();
         final float y = (mMonthHeight - lineHeight) / 2f;
 
-        canvas.drawText(getTitle().toString(), x, y, mMonthPaint);
+        canvas.drawText(mMonthYearLabel, x, y, mMonthPaint);
+    }
+
+    public String getMonthYearLabel() {
+        return mMonthYearLabel;
     }
 
     private void drawDaysOfWeek(Canvas canvas) {
@@ -630,16 +663,11 @@
             }
 
             final int dayOfWeek = (col + mWeekStart) % DAYS_IN_WEEK;
-            final String label = getDayOfWeekLabel(dayOfWeek);
+            final String label = mDayOfWeekLabels[dayOfWeek];
             canvas.drawText(label, colCenterRtl, rowCenter - halfLineHeight, p);
         }
     }
 
-    private String getDayOfWeekLabel(int dayOfWeek) {
-        mDayOfWeekLabelCalendar.set(Calendar.DAY_OF_WEEK, dayOfWeek);
-        return mDayOfWeekFormatter.format(mDayOfWeekLabelCalendar.getTime());
-    }
-
     /**
      * Draws the month days.
      */
@@ -746,12 +774,22 @@
      *                  {@link Calendar#SUNDAY} through {@link Calendar#SATURDAY}
      */
     public void setFirstDayOfWeek(int weekStart) {
+        if (DEBUG_WRONG_DATE) {
+            Log.d(LOG_TAG, "enter setFirstDayOfWeek(" + weekStart + ")", new Exception());
+        }
+
         if (isValidDayOfWeek(weekStart)) {
             mWeekStart = weekStart;
         } else {
             mWeekStart = mCalendar.getFirstDayOfWeek();
         }
 
+        if (DEBUG_WRONG_DATE) {
+            Log.d(LOG_TAG, "mWeekStart <=" + mWeekStart);
+        }
+
+        updateDayOfWeekLabels();
+
         // Invalidate cached accessibility information.
         mTouchHelper.invalidateRoot();
         invalidate();
@@ -807,11 +845,10 @@
         mEnabledDayStart = MathUtils.constrain(enabledDayStart, 1, mDaysInMonth);
         mEnabledDayEnd = MathUtils.constrain(enabledDayEnd, mEnabledDayStart, mDaysInMonth);
 
-        // Invalidate the old title.
-        mTitle = null;
-
         // Invalidate cached accessibility information.
         mTouchHelper.invalidateRoot();
+
+        updateMonthYearLabel();
     }
 
     private static int getDaysInMonth(int month, int year) {
diff --git a/core/java/android/widget/Switch.java b/core/java/android/widget/Switch.java
index 434516d..c4a1771 100644
--- a/core/java/android/widget/Switch.java
+++ b/core/java/android/widget/Switch.java
@@ -18,6 +18,7 @@
 
 import android.animation.ObjectAnimator;
 import android.annotation.DrawableRes;
+import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.StyleRes;
 import android.content.Context;
@@ -1371,7 +1372,7 @@
     }
 
     @Override
-    protected boolean verifyDrawable(Drawable who) {
+    protected boolean verifyDrawable(@NonNull Drawable who) {
         return super.verifyDrawable(who) || who == mThumbDrawable || who == mTrackDrawable;
     }
 
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 95fcdc1..e971f86 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -20,6 +20,7 @@
 import android.R;
 import android.annotation.ColorInt;
 import android.annotation.DrawableRes;
+import android.annotation.FloatRange;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.Size;
@@ -662,11 +663,12 @@
      */
     private int mDeviceProvisionedState = DEVICE_PROVISIONED_UNKNOWN;
 
-    /*
+    /**
      * Kick-start the font cache for the zygote process (to pay the cost of
      * initializing freetype for our default font only once).
+     * @hide
      */
-    static {
+    public static void preloadFontCache() {
         Paint p = new Paint();
         p.setAntiAlias(true);
         // We don't care about the result, just the side-effect of measuring.
@@ -1509,6 +1511,9 @@
                 if (result != null) {
                     if (isTextEditable()) {
                         replaceSelectionWithText(result);
+                        if (mEditor != null) {
+                            mEditor.refreshTextActionMode();
+                        }
                     } else {
                         if (result.length() > 0) {
                             Toast.makeText(getContext(), String.valueOf(result), Toast.LENGTH_LONG)
@@ -1518,12 +1523,7 @@
                 }
             } else if (mText instanceof Spannable) {
                 // Reset the selection.
-                stopTextActionMode();
-                Selection.setSelection((Spannable) mText, getSelectionStart(), getSelectionEnd());
-            }
-
-            if (mEditor.hasSelectionController()) {
-                mEditor.startSelectionActionMode();
+                Selection.setSelection((Spannable) mText, getSelectionEnd());
             }
         }
     }
@@ -3071,7 +3071,14 @@
      * @attr ref android.R.styleable#TextView_elegantTextHeight
      */
     public void setElegantTextHeight(boolean elegant) {
-        mTextPaint.setElegantTextHeight(elegant);
+        if (elegant != mTextPaint.isElegantTextHeight()) {
+            mTextPaint.setElegantTextHeight(elegant);
+            if (mLayout != null) {
+                nullLayouts();
+                requestLayout();
+                invalidate();
+            }
+        }
     }
 
     /**
@@ -5391,11 +5398,7 @@
         // - onFocusChanged cannot start it when focus is given to a view with selected text (after
         //   a screen rotation) since layout is not yet initialized at that point.
         if (mEditor != null && mEditor.mCreatedWithASelection) {
-            if (mEditor.extractedTextModeWillBeStarted()) {
-                mEditor.checkFieldAndSelectCurrentWord();
-            } else {
-                mEditor.startSelectionActionMode();
-            }
+            mEditor.refreshTextActionMode();
             mEditor.mCreatedWithASelection = false;
         }
 
@@ -5467,7 +5470,7 @@
     }
 
     @Override
-    protected boolean verifyDrawable(Drawable who) {
+    protected boolean verifyDrawable(@NonNull Drawable who) {
         final boolean verified = super.verifyDrawable(who);
         if (!verified && mDrawables != null) {
             for (Drawable dr : mDrawables.mShowing) {
@@ -5492,7 +5495,7 @@
     }
 
     @Override
-    public void invalidateDrawable(Drawable drawable) {
+    public void invalidateDrawable(@NonNull Drawable drawable) {
         boolean handled = false;
 
         if (verifyDrawable(drawable)) {
@@ -5834,8 +5837,7 @@
 
         final int layoutDirection = getLayoutDirection();
         final int absoluteGravity = Gravity.getAbsoluteGravity(mGravity, layoutDirection);
-        if (mEllipsize == TextUtils.TruncateAt.MARQUEE &&
-                mMarqueeFadeMode != MARQUEE_FADE_SWITCH_SHOW_ELLIPSIS) {
+        if (isMarqueeFadeEnabled()) {
             if (!mSingleLine && getLineCount() == 1 && canMarquee() &&
                     (absoluteGravity & Gravity.HORIZONTAL_GRAVITY_MASK) != Gravity.LEFT) {
                 final int width = mRight - mLeft;
@@ -6593,6 +6595,9 @@
         // in the extracted view.
         mEditor.hideCursorAndSpanControllers();
         stopTextActionMode();
+        if (mEditor.mSelectionModifierCursorController != null) {
+            mEditor.mSelectionModifierCursorController.resetTouchOffsets();
+        }
     }
 
     /**
@@ -7887,7 +7892,7 @@
     }
 
     /**
-     * Causes words in the text that are longer than the view is wide
+     * Causes words in the text that are longer than the view's width
      * to be ellipsized instead of broken in the middle.  You may also
      * want to {@link #setSingleLine} or {@link #setHorizontallyScrolling}
      * to constrain the text to a single line.  Use <code>null</code>
@@ -8288,6 +8293,16 @@
                 if (newSelEnd < 0) {
                     newSelEnd = Selection.getSelectionEnd(buf);
                 }
+
+                if (newSelStart == newSelEnd && hasTransientState()) {
+                    setHasTransientState(false);
+                } else if (newSelStart != newSelEnd && !hasTransientState()) {
+                    setHasTransientState(true);
+                }
+
+                if (mEditor != null) {
+                    mEditor.refreshTextActionMode();
+                }
                 onSelectionChanged(newSelStart, newSelEnd);
             }
         }
@@ -8615,78 +8630,59 @@
 
     @Override
     protected float getLeftFadingEdgeStrength() {
-        if (mEllipsize == TextUtils.TruncateAt.MARQUEE &&
-                mMarqueeFadeMode != MARQUEE_FADE_SWITCH_SHOW_ELLIPSIS) {
-            if (mMarquee != null && !mMarquee.isStopped()) {
-                final Marquee marquee = mMarquee;
-                if (marquee.shouldDrawLeftFade()) {
-                    final float scroll = marquee.getScroll();
-                    return scroll / getHorizontalFadingEdgeLength();
-                } else {
-                    return 0.0f;
-                }
-            } else if (getLineCount() == 1) {
-                final int layoutDirection = getLayoutDirection();
-                final int absoluteGravity = Gravity.getAbsoluteGravity(mGravity, layoutDirection);
-                switch (absoluteGravity & Gravity.HORIZONTAL_GRAVITY_MASK) {
-                    case Gravity.LEFT:
-                        return 0.0f;
-                    case Gravity.RIGHT:
-                        return (mLayout.getLineRight(0) - (mRight - mLeft) -
-                                getCompoundPaddingLeft() - getCompoundPaddingRight() -
-                                mLayout.getLineLeft(0)) / getHorizontalFadingEdgeLength();
-                    case Gravity.CENTER_HORIZONTAL:
-                    case Gravity.FILL_HORIZONTAL:
-                        final int textDirection = mLayout.getParagraphDirection(0);
-                        if (textDirection == Layout.DIR_LEFT_TO_RIGHT) {
-                            return 0.0f;
-                        } else {
-                            return (mLayout.getLineRight(0) - (mRight - mLeft) -
-                                getCompoundPaddingLeft() - getCompoundPaddingRight() -
-                                mLayout.getLineLeft(0)) / getHorizontalFadingEdgeLength();
-                        }
-                }
+        if (isMarqueeFadeEnabled() && mMarquee != null && !mMarquee.isStopped()) {
+            final Marquee marquee = mMarquee;
+            if (marquee.shouldDrawLeftFade()) {
+                return getHorizontalFadingEdgeStrength(marquee.getScroll(), 0.0f);
+            } else {
+                return 0.0f;
             }
+        } else if (getLineCount() == 1) {
+            final float lineLeft = getLayout().getLineLeft(0);
+            if(lineLeft > mScrollX) return 0.0f;
+            return getHorizontalFadingEdgeStrength(mScrollX, lineLeft);
         }
         return super.getLeftFadingEdgeStrength();
     }
 
     @Override
     protected float getRightFadingEdgeStrength() {
-        if (mEllipsize == TextUtils.TruncateAt.MARQUEE &&
-                mMarqueeFadeMode != MARQUEE_FADE_SWITCH_SHOW_ELLIPSIS) {
-            if (mMarquee != null && !mMarquee.isStopped()) {
-                final Marquee marquee = mMarquee;
-                final float maxFadeScroll = marquee.getMaxFadeScroll();
-                final float scroll = marquee.getScroll();
-                return (maxFadeScroll - scroll) / getHorizontalFadingEdgeLength();
-            } else if (getLineCount() == 1) {
-                final int layoutDirection = getLayoutDirection();
-                final int absoluteGravity = Gravity.getAbsoluteGravity(mGravity, layoutDirection);
-                switch (absoluteGravity & Gravity.HORIZONTAL_GRAVITY_MASK) {
-                    case Gravity.LEFT:
-                        final int textWidth = (mRight - mLeft) - getCompoundPaddingLeft() -
-                                getCompoundPaddingRight();
-                        final float lineWidth = mLayout.getLineWidth(0);
-                        return (lineWidth - textWidth) / getHorizontalFadingEdgeLength();
-                    case Gravity.RIGHT:
-                        return 0.0f;
-                    case Gravity.CENTER_HORIZONTAL:
-                    case Gravity.FILL_HORIZONTAL:
-                        final int textDirection = mLayout.getParagraphDirection(0);
-                        if (textDirection == Layout.DIR_RIGHT_TO_LEFT) {
-                            return 0.0f;
-                        } else {
-                            return (mLayout.getLineWidth(0) - ((mRight - mLeft) -
-                                getCompoundPaddingLeft() - getCompoundPaddingRight())) /
-                                getHorizontalFadingEdgeLength();
-                        }
-                }
-            }
+        if (isMarqueeFadeEnabled() && mMarquee != null && !mMarquee.isStopped()) {
+            final Marquee marquee = mMarquee;
+            return getHorizontalFadingEdgeStrength(marquee.getMaxFadeScroll(), marquee.getScroll());
+        } else if (getLineCount() == 1) {
+            final float rightEdge = mScrollX + (getWidth() - getCompoundPaddingLeft() -
+                    getCompoundPaddingRight());
+            final float lineRight = getLayout().getLineRight(0);
+            if(lineRight < rightEdge) return 0.0f;
+            return getHorizontalFadingEdgeStrength(rightEdge, lineRight);
         }
         return super.getRightFadingEdgeStrength();
     }
 
+    /**
+     * Calculates the fading edge strength as the ratio of the distance between two
+     * horizontal positions to {@link View#getHorizontalFadingEdgeLength()}. Uses the absolute
+     * value for the distance calculation.
+     *
+     * @param position1 A horizontal position.
+     * @param position2 A horizontal position.
+     * @return Fading edge strength between [0.0f, 1.0f].
+     */
+    @FloatRange(from=0.0, to=1.0)
+    private final float getHorizontalFadingEdgeStrength(float position1, float position2) {
+        final int horizontalFadingEdgeLength = getHorizontalFadingEdgeLength();
+        if(horizontalFadingEdgeLength == 0) return 0.0f;
+        final float diff = Math.abs(position1 - position2);
+        if(diff > horizontalFadingEdgeLength) return 1.0f;
+        return diff / horizontalFadingEdgeLength;
+    }
+
+    private final boolean isMarqueeFadeEnabled() {
+        return mEllipsize == TextUtils.TruncateAt.MARQUEE &&
+                mMarqueeFadeMode != MARQUEE_FADE_SWITCH_SHOW_ELLIPSIS;
+    }
+
     @Override
     protected int computeHorizontalScrollRange() {
         if (mLayout != null) {
@@ -8927,8 +8923,7 @@
     }
 
     void onLocaleChanged() {
-        // Will be re-created on demand in getWordIterator with the proper new locale
-        mEditor.mWordIterator = null;
+        mEditor.onLocaleChanged();
     }
 
     /**
@@ -9217,10 +9212,6 @@
                     }
                     if (start >= 0 && start <= end && end <= text.length()) {
                         Selection.setSelection((Spannable) text, start, end);
-                        // Make sure selection mode is engaged.
-                        if (mEditor != null) {
-                            mEditor.startSelectionActionMode();
-                        }
                         return true;
                     }
                 }
@@ -9411,16 +9402,7 @@
 
         switch (id) {
             case ID_SELECT_ALL:
-                // This starts an action mode if triggered from another action mode. Text is
-                // highlighted, so that it can be bulk edited, like selectAllOnFocus does. Returns
-                // true even if text is empty.
-                boolean shouldRestartActionMode =
-                        mEditor != null && mEditor.mTextActionMode != null;
-                stopTextActionMode();
                 selectAllText();
-                if (shouldRestartActionMode) {
-                    mEditor.startSelectionActionMode();
-                }
                 return true;
 
             case ID_UNDO:
@@ -9446,7 +9428,6 @@
             case ID_CUT:
                 setPrimaryClip(ClipData.newPlainText(null, getTransformedText(min, max)));
                 deleteText_internal(min, max);
-                stopTextActionMode();
                 return true;
 
             case ID_COPY:
@@ -9702,12 +9683,6 @@
     }
 
     boolean selectAllText() {
-        // Need to hide insert point cursor controller before settings selection, otherwise insert
-        // point cursor controller obtains cursor update event and update cursor with cancelling
-        // selection.
-        if (mEditor != null) {
-            mEditor.hideInsertionPointCursorController();
-        }
         final int length = mText.length();
         Selection.setSelection((Spannable) mText, 0, length);
         return length > 0;
@@ -9746,7 +9721,6 @@
                     }
                 }
             }
-            stopTextActionMode();
             sLastCutCopyOrTextChangedTime = 0;
         }
     }
@@ -9759,7 +9733,7 @@
             sharingIntent.removeExtra(android.content.Intent.EXTRA_TEXT);
             sharingIntent.putExtra(android.content.Intent.EXTRA_TEXT, selectedText);
             getContext().startActivity(Intent.createChooser(sharingIntent, null));
-            stopTextActionMode();
+            Selection.setSelection((Spannable) mText, getSelectionEnd());
         }
     }
 
@@ -10077,6 +10051,12 @@
                 && getAccessibilitySelectionEnd() == end) {
             return;
         }
+        CharSequence text = getIterableTextForAccessibility();
+        if (Math.min(start, end) >= 0 && Math.max(start, end) <= text.length()) {
+            Selection.setSelection((Spannable) text, start, end);
+        } else {
+            Selection.removeSelection((Spannable) text);
+        }
         // Hide all selection controllers used for adjusting selection
         // since we are doing so explicitlty by other means and these
         // controllers interact with how selection behaves.
@@ -10084,12 +10064,6 @@
             mEditor.hideCursorAndSpanControllers();
             mEditor.stopTextActionMode();
         }
-        CharSequence text = getIterableTextForAccessibility();
-        if (Math.min(start, end) >= 0 && Math.max(start, end) <= text.length()) {
-            Selection.setSelection((Spannable) text, start, end);
-        } else {
-            Selection.removeSelection((Spannable) text);
-        }
     }
 
     /** @hide */
diff --git a/core/java/android/widget/TimePicker.java b/core/java/android/widget/TimePicker.java
index a24d37f..f2fc617 100644
--- a/core/java/android/widget/TimePicker.java
+++ b/core/java/android/widget/TimePicker.java
@@ -22,8 +22,11 @@
 import android.content.Context;
 import android.content.res.Configuration;
 import android.content.res.TypedArray;
+import android.os.Parcel;
 import android.os.Parcelable;
+import android.os.Parcelable.Creator;
 import android.util.AttributeSet;
+import android.view.View;
 import android.view.accessibility.AccessibilityEvent;
 import com.android.internal.R;
 
@@ -301,5 +304,69 @@
             mContext = context;
             mLocale = context.getResources().getConfiguration().locale;
         }
+
+        protected static class SavedState extends View.BaseSavedState {
+            private final int mHour;
+            private final int mMinute;
+            private final boolean mIs24HourMode;
+            private final int mCurrentItemShowing;
+
+            public SavedState(Parcelable superState, int hour, int minute, boolean is24HourMode) {
+                this(superState, hour, minute, is24HourMode, 0);
+            }
+
+            public SavedState(Parcelable superState, int hour, int minute, boolean is24HourMode,
+                    int currentItemShowing) {
+                super(superState);
+                mHour = hour;
+                mMinute = minute;
+                mIs24HourMode = is24HourMode;
+                mCurrentItemShowing = currentItemShowing;
+            }
+
+            private SavedState(Parcel in) {
+                super(in);
+                mHour = in.readInt();
+                mMinute = in.readInt();
+                mIs24HourMode = (in.readInt() == 1);
+                mCurrentItemShowing = in.readInt();
+            }
+
+            public int getHour() {
+                return mHour;
+            }
+
+            public int getMinute() {
+                return mMinute;
+            }
+
+            public boolean is24HourMode() {
+                return mIs24HourMode;
+            }
+
+            public int getCurrentItemShowing() {
+                return mCurrentItemShowing;
+            }
+
+            @Override
+            public void writeToParcel(Parcel dest, int flags) {
+                super.writeToParcel(dest, flags);
+                dest.writeInt(mHour);
+                dest.writeInt(mMinute);
+                dest.writeInt(mIs24HourMode ? 1 : 0);
+                dest.writeInt(mCurrentItemShowing);
+            }
+
+            @SuppressWarnings({"unused", "hiding"})
+            public static final Creator<SavedState> CREATOR = new Creator<SavedState>() {
+                public SavedState createFromParcel(Parcel in) {
+                    return new SavedState(in);
+                }
+
+                public SavedState[] newArray(int size) {
+                    return new SavedState[size];
+                }
+            };
+        }
     }
 }
diff --git a/core/java/android/widget/TimePickerClockDelegate.java b/core/java/android/widget/TimePickerClockDelegate.java
index 05fd4c8..4a24e26 100644
--- a/core/java/android/widget/TimePickerClockDelegate.java
+++ b/core/java/android/widget/TimePickerClockDelegate.java
@@ -21,7 +21,6 @@
 import android.content.res.ColorStateList;
 import android.content.res.Resources;
 import android.content.res.TypedArray;
-import android.os.Parcel;
 import android.os.Parcelable;
 import android.text.SpannableStringBuilder;
 import android.text.format.DateFormat;
@@ -45,7 +44,6 @@
 import com.android.internal.widget.NumericTextView.OnValueChangedListener;
 
 import java.util.Calendar;
-import java.util.Locale;
 
 /**
  * A delegate implementing the radial clock-based TimePicker.
@@ -501,9 +499,11 @@
 
     @Override
     public void onRestoreInstanceState(Parcelable state) {
-        final SavedState ss = (SavedState) state;
-        initialize(ss.getHour(), ss.getMinute(), ss.is24HourMode(), ss.getCurrentItemShowing());
-        mRadialTimePickerView.invalidate();
+        if (state instanceof SavedState) {
+            final SavedState ss = (SavedState) state;
+            initialize(ss.getHour(), ss.getMinute(), ss.is24HourMode(), ss.getCurrentItemShowing());
+            mRadialTimePickerView.invalidate();
+        }
     }
 
     @Override
@@ -544,70 +544,6 @@
         }
     }
 
-    /**
-     * Used to save / restore state of time picker
-     */
-    private static class SavedState extends View.BaseSavedState {
-
-        private final int mHour;
-        private final int mMinute;
-        private final boolean mIs24HourMode;
-        private final int mCurrentItemShowing;
-
-        private SavedState(Parcelable superState, int hour, int minute, boolean is24HourMode,
-                int currentItemShowing) {
-            super(superState);
-            mHour = hour;
-            mMinute = minute;
-            mIs24HourMode = is24HourMode;
-            mCurrentItemShowing = currentItemShowing;
-        }
-
-        private SavedState(Parcel in) {
-            super(in);
-            mHour = in.readInt();
-            mMinute = in.readInt();
-            mIs24HourMode = (in.readInt() == 1);
-            mCurrentItemShowing = in.readInt();
-        }
-
-        public int getHour() {
-            return mHour;
-        }
-
-        public int getMinute() {
-            return mMinute;
-        }
-
-        public boolean is24HourMode() {
-            return mIs24HourMode;
-        }
-
-        public int getCurrentItemShowing() {
-            return mCurrentItemShowing;
-        }
-
-        @Override
-        public void writeToParcel(Parcel dest, int flags) {
-            super.writeToParcel(dest, flags);
-            dest.writeInt(mHour);
-            dest.writeInt(mMinute);
-            dest.writeInt(mIs24HourMode ? 1 : 0);
-            dest.writeInt(mCurrentItemShowing);
-        }
-
-        @SuppressWarnings({"unused", "hiding"})
-        public static final Creator<SavedState> CREATOR = new Creator<SavedState>() {
-            public SavedState createFromParcel(Parcel in) {
-                return new SavedState(in);
-            }
-
-            public SavedState[] newArray(int size) {
-                return new SavedState[size];
-            }
-        };
-    }
-
     private void tryVibrate() {
         mDelegator.performHapticFeedback(HapticFeedbackConstants.CLOCK_TICK);
     }
diff --git a/core/java/android/widget/TimePickerSpinnerDelegate.java b/core/java/android/widget/TimePickerSpinnerDelegate.java
index 863d409..b113fd9 100644
--- a/core/java/android/widget/TimePickerSpinnerDelegate.java
+++ b/core/java/android/widget/TimePickerSpinnerDelegate.java
@@ -18,7 +18,6 @@
 
 import android.content.Context;
 import android.content.res.TypedArray;
-import android.os.Parcel;
 import android.os.Parcelable;
 import android.text.format.DateFormat;
 import android.text.format.DateUtils;
@@ -32,7 +31,6 @@
 import com.android.internal.R;
 
 import java.util.Calendar;
-import java.util.Locale;
 
 import libcore.icu.LocaleData;
 
@@ -387,14 +385,16 @@
 
     @Override
     public Parcelable onSaveInstanceState(Parcelable superState) {
-        return new SavedState(superState, getHour(), getMinute());
+        return new SavedState(superState, getHour(), getMinute(), is24Hour());
     }
 
     @Override
     public void onRestoreInstanceState(Parcelable state) {
-        SavedState ss = (SavedState) state;
-        setHour(ss.getHour());
-        setMinute(ss.getMinute());
+        if (state instanceof SavedState) {
+            final SavedState ss = (SavedState) state;
+            setHour(ss.getHour());
+            setMinute(ss.getMinute());
+        }
     }
 
     @Override
@@ -525,52 +525,6 @@
         }
     }
 
-    /**
-     * Used to save / restore state of time picker
-     */
-    private static class SavedState extends View.BaseSavedState {
-        private final int mHour;
-        private final int mMinute;
-
-        private SavedState(Parcelable superState, int hour, int minute) {
-            super(superState);
-            mHour = hour;
-            mMinute = minute;
-        }
-
-        private SavedState(Parcel in) {
-            super(in);
-            mHour = in.readInt();
-            mMinute = in.readInt();
-        }
-
-        public int getHour() {
-            return mHour;
-        }
-
-        public int getMinute() {
-            return mMinute;
-        }
-
-        @Override
-        public void writeToParcel(Parcel dest, int flags) {
-            super.writeToParcel(dest, flags);
-            dest.writeInt(mHour);
-            dest.writeInt(mMinute);
-        }
-
-        @SuppressWarnings({"unused", "hiding"})
-        public static final Parcelable.Creator<SavedState> CREATOR = new Creator<SavedState>() {
-            public SavedState createFromParcel(Parcel in) {
-                return new SavedState(in);
-            }
-
-            public SavedState[] newArray(int size) {
-                return new SavedState[size];
-            }
-        };
-    }
-
     public static String[] getAmPmStrings(Context context) {
         String[] result = new String[2];
         LocaleData d = LocaleData.get(context.getResources().getConfiguration().locale);
diff --git a/core/java/com/android/internal/app/IBatteryStats.aidl b/core/java/com/android/internal/app/IBatteryStats.aidl
index 74fe94f..8e38c5a 100644
--- a/core/java/com/android/internal/app/IBatteryStats.aidl
+++ b/core/java/com/android/internal/app/IBatteryStats.aidl
@@ -20,6 +20,7 @@
 
 import android.os.ParcelFileDescriptor;
 import android.os.WorkSource;
+import android.os.health.HealthStatsParceler;
 import android.telephony.DataConnectionRealTimeInfo;
 import android.telephony.SignalStrength;
 
@@ -125,4 +126,7 @@
     void noteBleScanStarted(in WorkSource ws);
     void noteBleScanStopped(in WorkSource ws);
     void noteResetBleScan();
+
+    HealthStatsParceler takeUidSnapshot(int uid);
+    HealthStatsParceler[] takeUidSnapshots(in int[] uid);
 }
diff --git a/core/java/com/android/internal/app/LocaleHelper.java b/core/java/com/android/internal/app/LocaleHelper.java
index aca93ab..d8d6e56 100644
--- a/core/java/com/android/internal/app/LocaleHelper.java
+++ b/core/java/com/android/internal/app/LocaleHelper.java
@@ -180,14 +180,16 @@
      */
     public static final class LocaleInfoComparator implements Comparator<LocaleStore.LocaleInfo> {
         private final Collator mCollator;
+        private final boolean mCountryMode;
 
         /**
          * Constructor.
          *
          * @param sortLocale the locale to be used for sorting.
          */
-        public LocaleInfoComparator(Locale sortLocale) {
+        public LocaleInfoComparator(Locale sortLocale, boolean countryMode) {
             mCollator = Collator.getInstance(sortLocale);
+            mCountryMode = countryMode;
         }
 
         /**
@@ -202,9 +204,9 @@
         public int compare(LocaleStore.LocaleInfo lhs, LocaleStore.LocaleInfo rhs) {
             // We don't care about the various suggestion types, just "suggested" (!= 0)
             // and "all others" (== 0)
-            if (lhs.isSuggested() == rhs.isSuggested()) {
+            if (mCountryMode || (lhs.isSuggested() == rhs.isSuggested())) {
                 // They are in the same "bucket" (suggested / others), so we compare the text
-                return mCollator.compare(lhs.getLabel(), rhs.getLabel());
+                return mCollator.compare(lhs.getLabel(mCountryMode), rhs.getLabel(mCountryMode));
             } else {
                 // One locale is suggested and one is not, so we put them in different "buckets"
                 return lhs.isSuggested() ? -1 : 1;
diff --git a/core/java/com/android/internal/app/LocalePickerWithRegion.java b/core/java/com/android/internal/app/LocalePickerWithRegion.java
index 956ee8c..ea62899 100644
--- a/core/java/com/android/internal/app/LocalePickerWithRegion.java
+++ b/core/java/com/android/internal/app/LocalePickerWithRegion.java
@@ -21,6 +21,7 @@
 import android.app.ListFragment;
 import android.content.Context;
 import android.os.Bundle;
+import android.text.TextUtils;
 import android.util.LocaleList;
 import android.view.Menu;
 import android.view.MenuInflater;
@@ -50,7 +51,11 @@
     private Set<LocaleStore.LocaleInfo> mLocaleList;
     private LocaleStore.LocaleInfo mParentLocale;
     private boolean mTranslatedOnly = false;
-    private boolean mCountryMode = false;
+    private SearchView mSearchView = null;
+    private CharSequence mPreviousSearch = null;
+    private boolean mPreviousSearchHadFocus = false;
+    private int mFirstVisiblePosition = 0;
+    private int mTopDistance = 0;
 
     /**
      * Other classes can register to be notified when a locale was selected.
@@ -70,15 +75,14 @@
             boolean translatedOnly) {
         LocalePickerWithRegion localePicker = new LocalePickerWithRegion();
         boolean shouldShowTheList = localePicker.setListener(context, listener, parent,
-                true /* country mode */, translatedOnly);
+                translatedOnly);
         return shouldShowTheList ? localePicker : null;
     }
 
     public static LocalePickerWithRegion createLanguagePicker(Context context,
             LocaleSelectedListener listener, boolean translatedOnly) {
         LocalePickerWithRegion localePicker = new LocalePickerWithRegion();
-        localePicker.setListener(context, listener, null,
-                false /* language mode */, translatedOnly);
+        localePicker.setListener(context, listener, /* parent */ null, translatedOnly);
         return localePicker;
     }
 
@@ -96,14 +100,7 @@
      * "pretending" it was selected, and return false.</p>
      */
     private boolean setListener(Context context, LocaleSelectedListener listener,
-            LocaleStore.LocaleInfo parent, boolean countryMode, boolean translatedOnly) {
-        if (countryMode && (parent == null || parent.getLocale() == null)) {
-            // The list of countries is determined as all the countries where the parent language
-            // is used.
-            throw new IllegalArgumentException("The country selection list needs a parent.");
-        }
-
-        this.mCountryMode = countryMode;
+            LocaleStore.LocaleInfo parent, boolean translatedOnly) {
         this.mParentLocale = parent;
         this.mListener = listener;
         this.mTranslatedOnly = translatedOnly;
@@ -116,7 +113,7 @@
             Collections.addAll(langTagsToIgnore, langTags);
         }
 
-        if (countryMode) {
+        if (parent != null) {
             mLocaleList = LocaleStore.getLevelLocales(context,
                     langTagsToIgnore, parent, translatedOnly);
             if (mLocaleList.size() <= 1) {
@@ -138,13 +135,11 @@
         super.onCreate(savedInstanceState);
         setHasOptionsMenu(true);
 
-        final Locale sortingLocale = (mCountryMode && mParentLocale != null)
-                ? mParentLocale.getLocale()
-                : Locale.getDefault();
-
-        mAdapter = new SuggestedLocaleAdapter(mLocaleList, mCountryMode);
+        final boolean countryMode = mParentLocale != null;
+        final Locale sortingLocale = countryMode ? mParentLocale.getLocale() : Locale.getDefault();
+        mAdapter = new SuggestedLocaleAdapter(mLocaleList, countryMode);
         final LocaleHelper.LocaleInfoComparator comp =
-                new LocaleHelper.LocaleInfoComparator(sortingLocale);
+                new LocaleHelper.LocaleInfoComparator(sortingLocale, countryMode);
         mAdapter.sort(comp);
         setListAdapter(mAdapter);
     }
@@ -164,25 +159,41 @@
     public void onResume() {
         super.onResume();
 
-        if (mCountryMode) {
-            if (mParentLocale == null) {
-                this.getActivity().setTitle(R.string.country_selection_title);
-            } else {
-                this.getActivity().setTitle(mParentLocale.getFullNameNative());
-            }
+        if (mParentLocale != null) {
+            getActivity().setTitle(mParentLocale.getFullNameNative());
         } else {
-            this.getActivity().setTitle(R.string.language_selection_title);
+            getActivity().setTitle(R.string.language_selection_title);
         }
 
         getListView().requestFocus();
     }
 
     @Override
+    public void onPause() {
+        super.onPause();
+
+        // Save search status
+        if (mSearchView != null) {
+            mPreviousSearchHadFocus = mSearchView.hasFocus();
+            mPreviousSearch = mSearchView.getQuery();
+        } else {
+            mPreviousSearchHadFocus = false;
+            mPreviousSearch = null;
+        }
+
+        // Save scroll position
+        final ListView list = getListView();
+        final View firstChild = list.getChildAt(0);
+        mFirstVisiblePosition = list.getFirstVisiblePosition();
+        mTopDistance = (firstChild == null) ? 0 : (firstChild.getTop() - list.getPaddingTop());
+    }
+
+    @Override
     public void onListItemClick(ListView l, View v, int position, long id) {
         final LocaleStore.LocaleInfo locale =
                 (LocaleStore.LocaleInfo) getListAdapter().getItem(position);
 
-        if (mCountryMode || locale.getParent() != null) {
+        if (locale.getParent() != null) {
             if (mListener != null) {
                 mListener.onLocaleSelected(locale);
             }
@@ -205,15 +216,30 @@
 
     @Override
     public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
-        if (!mCountryMode) {
+        if (mParentLocale == null) {
             inflater.inflate(R.menu.language_selection_list, menu);
 
-            MenuItem mSearchMenuItem = menu.findItem(R.id.locale_search_menu);
-            SearchView mSearchView = (SearchView) mSearchMenuItem.getActionView();
+            final MenuItem searchMenuItem = menu.findItem(R.id.locale_search_menu);
+            mSearchView = (SearchView) searchMenuItem.getActionView();
 
             mSearchView.setQueryHint(getText(R.string.search_language_hint));
             mSearchView.setOnQueryTextListener(this);
-            mSearchView.setQuery("", false /* submit */);
+
+            // Restore previous search status
+            if (!TextUtils.isEmpty(mPreviousSearch)) {
+                searchMenuItem.expandActionView();
+                mSearchView.setIconified(false);
+                mSearchView.setActivated(true);
+                if (mPreviousSearchHadFocus) {
+                    mSearchView.requestFocus();
+                }
+                mSearchView.setQuery(mPreviousSearch, true /* submit */);
+            } else {
+                mSearchView.setQuery(null, false /* submit */);
+            }
+
+            // Restore previous scroll position
+            getListView().setSelectionFromTop(mFirstVisiblePosition, mTopDistance);
         }
     }
 
diff --git a/core/java/com/android/internal/app/LocaleStore.java b/core/java/com/android/internal/app/LocaleStore.java
index 465c4d8..c4e6675 100644
--- a/core/java/com/android/internal/app/LocaleStore.java
+++ b/core/java/com/android/internal/app/LocaleStore.java
@@ -145,11 +145,11 @@
             return mLangScriptKey;
         }
 
-        String getLabel() {
-            if (getParent() == null || this.isSuggestionOfType(SUGGESTION_TYPE_SIM)) {
-                return getFullNameNative();
-            } else {
+        String getLabel(boolean countryMode) {
+            if (countryMode) {
                 return getFullCountryNameNative();
+            } else {
+                return getFullNameNative();
             }
         }
 
@@ -311,9 +311,7 @@
             if (level == 2) {
                 if (parent != null) { // region selection
                     if (parentId.equals(li.getParent().toLanguageTag())) {
-                        if (!li.isSuggestionOfType(LocaleInfo.SUGGESTION_TYPE_SIM)) {
-                            result.add(li);
-                        }
+                        result.add(li);
                     }
                 } else { // language selection
                     if (li.isSuggestionOfType(LocaleInfo.SUGGESTION_TYPE_SIM)) {
diff --git a/core/java/com/android/internal/app/SuggestedLocaleAdapter.java b/core/java/com/android/internal/app/SuggestedLocaleAdapter.java
index 0d4a5aa..98102ea 100644
--- a/core/java/com/android/internal/app/SuggestedLocaleAdapter.java
+++ b/core/java/com/android/internal/app/SuggestedLocaleAdapter.java
@@ -156,7 +156,7 @@
 
                 TextView text = (TextView) convertView.findViewById(R.id.locale);
                 LocaleStore.LocaleInfo item = (LocaleStore.LocaleInfo) getItem(position);
-                text.setText(item.getLabel());
+                text.setText(item.getLabel(mCountryMode));
                 text.setTextLocale(item.getLocale());
                 if (mCountryMode) {
                     int layoutDir = TextUtils.getLayoutDirectionFromLocale(item.getParent());
@@ -171,6 +171,9 @@
     }
 
     private boolean showHeaders() {
+        if (mCountryMode) { // never show suggestions in country mode
+            return false;
+        }
         return mSuggestionCount != 0 && mSuggestionCount != mLocaleOptions.size();
     }
 
diff --git a/core/java/com/android/internal/inputmethod/InputMethodUtils.java b/core/java/com/android/internal/inputmethod/InputMethodUtils.java
index 4e48e45..90ee05e 100644
--- a/core/java/com/android/internal/inputmethod/InputMethodUtils.java
+++ b/core/java/com/android/internal/inputmethod/InputMethodUtils.java
@@ -505,7 +505,6 @@
         final int numSubtypes = subtypes.size();
 
         // Handle overridesImplicitlyEnabledSubtype mechanism.
-        final String systemLanguage = systemLocales.get(0).getLanguage();
         final HashMap<String, InputMethodSubtype> applicableModeAndSubtypesMap = new HashMap<>();
         for (int i = 0; i < numSubtypes; ++i) {
             // scan overriding implicitly enabled subtypes.
@@ -521,25 +520,20 @@
             return new ArrayList<>(applicableModeAndSubtypesMap.values());
         }
 
+        final HashMap<String, ArrayList<InputMethodSubtype>> nonKeyboardSubtypesMap =
+                new HashMap<>();
         final ArrayList<InputMethodSubtype> keyboardSubtypes = new ArrayList<>();
+
         for (int i = 0; i < numSubtypes; ++i) {
             final InputMethodSubtype subtype = subtypes.get(i);
-            if (TextUtils.equals(SUBTYPE_MODE_KEYBOARD, subtype.getMode())) {
+            final String mode = subtype.getMode();
+            if (SUBTYPE_MODE_KEYBOARD.equals(mode)) {
                 keyboardSubtypes.add(subtype);
             } else {
-                final Locale locale = subtype.getLocaleObject();
-                final String mode = subtype.getMode();
-                // TODO: Take secondary system locales into consideration.
-                if (locale != null && locale.equals(systemLanguage)) {
-                    final InputMethodSubtype applicableSubtype =
-                            applicableModeAndSubtypesMap.get(mode);
-                    // If more applicable subtypes are contained, skip.
-                    if (applicableSubtype != null) {
-                        if (systemLocale.equals(applicableSubtype.getLocaleObject())) continue;
-                        if (!systemLocale.equals(locale)) continue;
-                    }
-                    applicableModeAndSubtypesMap.put(mode, subtype);
+                if (!nonKeyboardSubtypesMap.containsKey(mode)) {
+                    nonKeyboardSubtypesMap.put(mode, new ArrayList<>());
                 }
+                nonKeyboardSubtypesMap.get(mode).add(subtype);
             }
         }
 
@@ -547,23 +541,25 @@
         LocaleUtils.filterByLanguage(keyboardSubtypes, sSubtypeToLocale, systemLocales,
                 applicableSubtypes);
 
-        boolean hasAsciiCapableKeyboard = false;
-        final int numApplicationSubtypes = applicableSubtypes.size();
-        for (int i = 0; i < numApplicationSubtypes; ++i) {
-            final InputMethodSubtype subtype = applicableSubtypes.get(i);
-            if (subtype.containsExtraValueKey(TAG_ASCII_CAPABLE)) {
-                hasAsciiCapableKeyboard = true;
-                break;
+        if (!applicableSubtypes.isEmpty()) {
+            boolean hasAsciiCapableKeyboard = false;
+            final int numApplicationSubtypes = applicableSubtypes.size();
+            for (int i = 0; i < numApplicationSubtypes; ++i) {
+                final InputMethodSubtype subtype = applicableSubtypes.get(i);
+                if (subtype.containsExtraValueKey(TAG_ASCII_CAPABLE)) {
+                    hasAsciiCapableKeyboard = true;
+                    break;
+                }
             }
-        }
-        if (!hasAsciiCapableKeyboard) {
-            final int numKeyboardSubtypes = keyboardSubtypes.size();
-            for (int i = 0; i < numKeyboardSubtypes; ++i) {
-                final InputMethodSubtype subtype = keyboardSubtypes.get(i);
-                final String mode = subtype.getMode();
-                if (SUBTYPE_MODE_KEYBOARD.equals(mode) && subtype.containsExtraValueKey(
-                        TAG_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE)) {
-                    applicableSubtypes.add(subtype);
+            if (!hasAsciiCapableKeyboard) {
+                final int numKeyboardSubtypes = keyboardSubtypes.size();
+                for (int i = 0; i < numKeyboardSubtypes; ++i) {
+                    final InputMethodSubtype subtype = keyboardSubtypes.get(i);
+                    final String mode = subtype.getMode();
+                    if (SUBTYPE_MODE_KEYBOARD.equals(mode) && subtype.containsExtraValueKey(
+                            TAG_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE)) {
+                        applicableSubtypes.add(subtype);
+                    }
                 }
             }
         }
@@ -576,7 +572,12 @@
             }
         }
 
-        applicableSubtypes.addAll(applicableModeAndSubtypesMap.values());
+        // For each non-keyboard mode, extract subtypes with system locales.
+        for (final ArrayList<InputMethodSubtype> subtypeList : nonKeyboardSubtypesMap.values()) {
+            LocaleUtils.filterByLanguage(subtypeList, sSubtypeToLocale, systemLocales,
+                    applicableSubtypes);
+        }
+
         return applicableSubtypes;
     }
 
diff --git a/core/java/com/android/internal/inputmethod/LocaleUtils.java b/core/java/com/android/internal/inputmethod/LocaleUtils.java
index 99bb4cb..2aa660e 100644
--- a/core/java/com/android/internal/inputmethod/LocaleUtils.java
+++ b/core/java/com/android/internal/inputmethod/LocaleUtils.java
@@ -18,15 +18,17 @@
 
 import com.android.internal.annotations.VisibleForTesting;
 
+import android.annotation.IntRange;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
-import android.text.TextUtils;
+import android.icu.util.ULocale;
 import android.util.LocaleList;
 
 import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
 import java.util.List;
 import java.util.Locale;
-import java.util.Objects;
 
 public final class LocaleUtils {
 
@@ -36,12 +38,138 @@
         Locale get(@Nullable T source);
     }
 
-    @Nullable
-    private static String getLanguage(@Nullable Locale locale) {
-        if (locale == null) {
-            return null;
+    /**
+     * Calculates a matching score for the single desired locale.
+     *
+     * @see LocaleUtils#calculateMatchingScore(ULocale, LocaleList, byte[])
+     *
+     * @param supported The locale supported by IME subtype.
+     * @param desired The locale preferred by user.
+     * @return A score based on the locale matching for the default subtype enabling.
+     */
+    @IntRange(from=1, to=3)
+    private static byte calculateMatchingSubScore(@NonNull final ULocale supported,
+            @NonNull final ULocale desired) {
+        // Assuming supported/desired is fully expanded.
+        if (supported.equals(desired)) {
+            return 3;  // Exact match.
         }
-        return locale.getLanguage();
+
+        // Skip language matching since it was already done in calculateMatchingScore.
+
+        final String supportedScript = supported.getScript();
+        if (supportedScript.isEmpty() || !supportedScript.equals(desired.getScript())) {
+            // TODO: Need subscript matching. For example, Hanb should match with Bopo.
+            return 1;
+        }
+
+        final String supportedCountry = supported.getCountry();
+        if (supportedCountry.isEmpty() || !supportedCountry.equals(desired.getCountry())) {
+            return 2;
+        }
+
+        // Ignore others e.g. variants, extensions.
+        return 3;
+    }
+
+    /**
+     * Calculates a matching score for the desired locale list.
+     *
+     * <p>The supported locale gets a matching score of 3 if all language, script and country of the
+     * supported locale matches with the desired locale.  The supported locale gets a matching
+     * score of 2 if the language and script of the supported locale matches with the desired
+     * locale. The supported locale gets a matching score of 1 if only language of the supported
+     * locale matches with the desired locale.  The supported locale gets a matching score of 0 if
+     * the language of the supported locale doesn't match with the desired locale.</p>
+     *
+     * @param supported The locale supported by IME subtyle.
+     * @param desired The locale list preferred by user. Typically system locale list.
+     * @param out The output buffer to be stored the individual score for the desired language list.
+     * The length of {@code out} must be same as the length of {@code desired} language list.
+     * @return {@code false} if supported locale doesn't match with any desired locale list.
+     * Otherwise {@code true}.
+     */
+    private static boolean calculateMatchingScore(@NonNull final ULocale supported,
+            @NonNull final LocaleList desired, @NonNull byte[] out) {
+        if (desired.isEmpty()) {
+            return false;
+        }
+
+        boolean allZeros = true;
+        final int N = desired.size();
+        for (int i = 0; i < N; ++i) {
+            final Locale locale = desired.get(i);
+
+            if (!locale.getLanguage().equals(supported.getLanguage())) {
+                // TODO: cache the result of addLikelySubtags if it is slow.
+                out[i] = 0;
+            } else {
+                out[i] = calculateMatchingSubScore(
+                        supported, ULocale.addLikelySubtags(ULocale.forLocale(locale)));
+                if (allZeros && out[i] != 0) {
+                    allZeros = false;
+                }
+            }
+        }
+        return !allZeros;
+    }
+
+    private static final class ScoreEntry implements Comparable<ScoreEntry> {
+        public int mIndex = -1;
+        @NonNull public final byte[] mScore;  // matching score of the i-th system languages.
+
+        ScoreEntry(@NonNull byte[] score, int index) {
+            mScore = new byte[score.length];
+            set(score, index);
+        }
+
+        private void set(@NonNull byte[] score, int index) {
+            for (int i = 0; i < mScore.length; ++i) {
+                mScore[i] = score[i];
+            }
+            mIndex = index;
+        }
+
+        /**
+         * Update score and index if the given score is better than this.
+         */
+        public void updateIfBetter(@NonNull byte[] score, int index) {
+            if (compare(mScore, score) == -1) {  // mScore < score
+                set(score, index);
+            }
+        }
+
+        /**
+         * Provides comaprison for bytes[].
+         *
+         * <p> Comparison does as follows. If the first value of {@code left} is larger than the
+         * first value of {@code right}, {@code left} is large than {@code right}.  If the first
+         * value of {@code left} is less than the first value of {@code right}, {@code left} is less
+         * than {@code right}. If the first value of {@code left} and the first value of
+         * {@code right} is equal, do the same comparison to the next value. Finally if all values
+         * in {@code left} and {@code right} are equal, {@code left} and {@code right} is equal.</p>
+         *
+         * @param left The length must be equal to {@code right}.
+         * @param right The length must be equal to {@code left}.
+         * @return 1 if {@code left} is larger than {@code right}. -1 if {@code left} is less than
+         * {@code right}. 0 if {@code left} and {@code right} is equal.
+         */
+        @IntRange(from=-1, to=1)
+        private static int compare(@NonNull byte[] left, @NonNull byte[] right) {
+            for (int i = 0; i < left.length; ++i) {
+                if (left[i] > right[i]) {
+                    return 1;
+                } else if (left[i] < right[i]) {
+                    return -1;
+                }
+            }
+            return 0;
+        }
+
+        @Override
+        public int compareTo(final ScoreEntry other) {
+            return -1 * compare(mScore, other.mScore);  // Order by descending order.
+        }
     }
 
     /**
@@ -52,14 +180,8 @@
      * {@code "en-GB", "ja", "en-AU", "fr-CA", "en-IN"} is specified to {@code preferredLanguages},
      * this method tries to copy at most one English locale, at most one Japanese, and at most one
      * French locale from {@code source} to {@code dest}.  Here the best matching English locale
-     * will be searched from {@code source} as follows.
-     * <ol>
-     *     <li>The first instance in {@code sources} that exactly matches {@code "en-GB"}</li>
-     *     <li>The first instance in {@code sources} that exactly matches {@code "en-AU"}</li>
-     *     <li>The first instance in {@code sources} that exactly matches {@code "en-IN"}</li>
-     *     <li>The first instance in {@code sources} that partially matches {@code "en"}</li>
-     * </ol>
-     * <p>Then this method iterates the same algorithm for Japanese then French.</p>
+     * will be searched from {@code source} based on matching score. For the score design, see
+     * {@link LocaleUtils#calculateMatchingScore(ULocale, LocaleList, byte[])}</p>
      *
      * @param sources Source items to be filtered.
      * @param extractor Type converter from the source items to {@link Locale} object.
@@ -74,69 +196,31 @@
             @NonNull LocaleExtractor<T> extractor,
             @NonNull LocaleList preferredLanguages,
             @NonNull ArrayList<T> dest) {
-        final Locale[] availableLocales = new Locale[sources.size()];
-        for (int i = 0; i < availableLocales.length; ++i) {
-            availableLocales[i] = extractor.get(sources.get(i));
-        }
-        final Locale[] sortedPreferredLanguages = new Locale[preferredLanguages.size()];
-        if (sortedPreferredLanguages.length > 0) {
-            int nextIndex = 0;
-            final int N = preferredLanguages.size();
-            languageLoop:
-            for (int i = 0; i < N; ++i) {
-                final String language = getLanguage(preferredLanguages.get(i));
-                for (int j = 0; j < nextIndex; ++j) {
-                    if (TextUtils.equals(getLanguage(sortedPreferredLanguages[j]), language)) {
-                        continue languageLoop;
-                    }
-                }
-                for (int j = i; j < N; ++j) {
-                    final Locale locale = preferredLanguages.get(j);
-                    if (TextUtils.equals(language, getLanguage(locale))) {
-                        sortedPreferredLanguages[nextIndex] = locale;
-                        ++nextIndex;
-                    }
-                }
+        final HashMap<String, ScoreEntry> scoreboard = new HashMap<>();
+        final byte[] score = new byte[preferredLanguages.size()];
+
+        final int sourceSize = sources.size();
+        for (int i = 0; i < sourceSize; ++i) {
+            final Locale locale = extractor.get(sources.get(i));
+            if (locale == null ||
+                    !calculateMatchingScore(ULocale.addLikelySubtags(ULocale.forLocale(locale)),
+                            preferredLanguages, score)) {
+                continue;
+            }
+
+            final String lang = locale.getLanguage();
+            final ScoreEntry bestScore = scoreboard.get(lang);
+            if (bestScore == null) {
+                scoreboard.put(lang, new ScoreEntry(score, i));
+            } else {
+                bestScore.updateIfBetter(score, i);
             }
         }
 
-
-        for (int languageIndex = 0; languageIndex < sortedPreferredLanguages.length;) {
-            // Finding the range.
-            final String language = getLanguage(sortedPreferredLanguages[languageIndex]);
-            int nextLanguageIndex = languageIndex;
-            for (; nextLanguageIndex < sortedPreferredLanguages.length; ++nextLanguageIndex) {
-                final Locale locale = sortedPreferredLanguages[nextLanguageIndex];
-                if (!TextUtils.equals(getLanguage(locale), language)) {
-                    break;
-                }
-            }
-
-            // Check exact match
-            boolean found = false;
-            for (int i = languageIndex; !found && i < nextLanguageIndex; ++i) {
-                final Locale locale = sortedPreferredLanguages[i];
-                for (int j = 0; j < availableLocales.length; ++j) {
-                    if (!Objects.equals(locale, availableLocales[j])) {
-                        continue;
-                    }
-                    dest.add(sources.get(j));
-                    found = true;
-                    break;
-                }
-            }
-
-            if (!found) {
-                // No exact match.  Use language match.
-                for (int j = 0; j < availableLocales.length; ++j) {
-                    if (!TextUtils.equals(language, getLanguage(availableLocales[j]))) {
-                        continue;
-                    }
-                    dest.add(sources.get(j));
-                    break;
-                }
-            }
-            languageIndex = nextLanguageIndex;
+        final ScoreEntry[] result = scoreboard.values().toArray(new ScoreEntry[scoreboard.size()]);
+        Arrays.sort(result);
+        for (final ScoreEntry entry : result) {
+            dest.add(sources.get(entry.mIndex));
         }
     }
-}
\ No newline at end of file
+}
diff --git a/core/java/com/android/internal/os/BatteryStatsHelper.java b/core/java/com/android/internal/os/BatteryStatsHelper.java
index f178c8c..1b52146 100644
--- a/core/java/com/android/internal/os/BatteryStatsHelper.java
+++ b/core/java/com/android/internal/os/BatteryStatsHelper.java
@@ -754,8 +754,7 @@
         try {
             ParcelFileDescriptor pfd = service.getStatisticsStream();
             if (pfd != null) {
-                FileInputStream fis = new ParcelFileDescriptor.AutoCloseInputStream(pfd);
-                try {
+                try (FileInputStream fis = new ParcelFileDescriptor.AutoCloseInputStream(pfd)) {
                     byte[] data = readFully(fis, MemoryFile.getSize(pfd.getFileDescriptor()));
                     Parcel parcel = Parcel.obtain();
                     parcel.unmarshall(data, 0, data.length);
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index d917cdb..c484121 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -5300,6 +5300,12 @@
         }
 
         @Override
+        public Timer getProcessStateTimer(int state) {
+            if (state < 0 || state >= NUM_PROCESS_STATE) return null;
+            return mProcessStateTimer[state];
+        }
+
+        @Override
         public Timer getVibratorOnTimer() {
             return mVibratorOnTimer;
         }
@@ -8192,7 +8198,8 @@
                             + " txPackets=" + entry.txPackets);
                 }
 
-                if (entry.rxBytes == 0 || entry.txBytes == 0) {
+                if (entry.rxBytes == 0 && entry.txBytes == 0) {
+                    // Skip the lookup below since there is no work to do.
                     continue;
                 }
 
diff --git a/core/java/com/android/internal/os/RuntimeInit.java b/core/java/com/android/internal/os/RuntimeInit.java
index e298201..fff9d7c 100644
--- a/core/java/com/android/internal/os/RuntimeInit.java
+++ b/core/java/com/android/internal/os/RuntimeInit.java
@@ -20,6 +20,7 @@
 import android.app.ActivityThread;
 import android.app.ApplicationErrorReport;
 import android.os.Build;
+import android.os.DeadObjectException;
 import android.os.Debug;
 import android.os.IBinder;
 import android.os.Process;
@@ -96,10 +97,14 @@
                 ActivityManagerNative.getDefault().handleApplicationCrash(
                         mApplicationObject, new ApplicationErrorReport.CrashInfo(e));
             } catch (Throwable t2) {
-                try {
-                    Clog_e(TAG, "Error reporting crash", t2);
-                } catch (Throwable t3) {
-                    // Even Clog_e() fails!  Oh well.
+                if (t2 instanceof DeadObjectException) {
+                    // System process is dead; ignore
+                } else {
+                    try {
+                        Clog_e(TAG, "Error reporting crash", t2);
+                    } catch (Throwable t3) {
+                        // Even Clog_e() fails!  Oh well.
+                    }
                 }
             } finally {
                 // Try everything to make sure this process goes away.
@@ -358,8 +363,12 @@
                 System.exit(10);
             }
         } catch (Throwable t2) {
-            Slog.e(TAG, "Error reporting WTF", t2);
-            Slog.e(TAG, "Original WTF:", t);
+            if (t2 instanceof DeadObjectException) {
+                // System process is dead; ignore
+            } else {
+                Slog.e(TAG, "Error reporting WTF", t2);
+                Slog.e(TAG, "Original WTF:", t);
+            }
         }
     }
 
diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java
index 6ad9e20..3abea26 100644
--- a/core/java/com/android/internal/os/ZygoteInit.java
+++ b/core/java/com/android/internal/os/ZygoteInit.java
@@ -36,6 +36,7 @@
 import android.util.EventLog;
 import android.util.Log;
 import android.webkit.WebViewFactory;
+import android.widget.TextView;
 
 import com.android.internal.os.InstallerConnection.InstallerException;
 
@@ -214,6 +215,7 @@
 
     private static void preloadTextResources() {
         Hyphenator.init();
+        TextView.preloadFontCache();
     }
 
     /**
@@ -497,11 +499,11 @@
 
         try {
             for (String classPathElement : classPathElements) {
+                // System server is fully AOTed and never profiled
+                // for profile guided compilation.
                 final int dexoptNeeded = DexFile.getDexOptNeeded(
-                        classPathElement, "*", instructionSet, false /* defer */);
+                        classPathElement, instructionSet, DexFile.COMPILATION_TYPE_FULL);
                 if (dexoptNeeded != DexFile.NO_DEXOPT_NEEDED) {
-                    // System server is fully AOTed and never profiled
-                    // for profile guided compilation.
                     installer.dexopt(classPathElement, Process.SYSTEM_UID, instructionSet,
                             dexoptNeeded, 0 /*dexFlags*/, null /*volumeUuid*/,
                             false /*useProfiles*/);
diff --git a/core/java/com/android/internal/policy/DividerSnapAlgorithm.java b/core/java/com/android/internal/policy/DividerSnapAlgorithm.java
index 84d0fc7..9907ea9 100644
--- a/core/java/com/android/internal/policy/DividerSnapAlgorithm.java
+++ b/core/java/com/android/internal/policy/DividerSnapAlgorithm.java
@@ -279,6 +279,26 @@
     }
 
     /**
+     * Cycles through all non-dismiss targets with a stepping of {@param increment}. It moves left
+     * if {@param increment} is negative and moves right otherwise.
+     */
+    public SnapTarget cycleNonDismissTarget(SnapTarget snapTarget, int increment) {
+        int index = mTargets.indexOf(snapTarget);
+        if (index != -1) {
+            SnapTarget newTarget = mTargets.get((index + mTargets.size() + increment)
+                    % mTargets.size());
+            if (newTarget == mDismissStartTarget) {
+                return mLastSplitTarget;
+            } else if (newTarget == mDismissEndTarget) {
+                return mFirstSplitTarget;
+            } else {
+                return newTarget;
+            }
+        }
+        return snapTarget;
+    }
+
+    /**
      * Represents a snap target for the divider.
      */
     public static class SnapTarget {
diff --git a/core/java/android/hardware/ICameraServiceListener.aidl b/core/java/com/android/internal/policy/IShortcutService.aidl
similarity index 62%
rename from core/java/android/hardware/ICameraServiceListener.aidl
rename to core/java/com/android/internal/policy/IShortcutService.aidl
index 49278b6..8550728 100644
--- a/core/java/android/hardware/ICameraServiceListener.aidl
+++ b/core/java/com/android/internal/policy/IShortcutService.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2013 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.
@@ -14,15 +14,16 @@
  * limitations under the License.
  */
 
-package android.hardware;
+package com.android.internal.policy;
 
-/** @hide */
-interface ICameraServiceListener
-{
+/**
+ * An interface to notify the shortcut service that a shortcut key is pressed
+ * @hide
+ */
+oneway interface IShortcutService {
     /**
-     * Keep up-to-date with frameworks/av/include/camera/ICameraServiceListener.h
+     * @param shortcutCode the keycode packed with meta information
      */
-    void onStatusChanged(int status, int cameraId);
-
-    void onTorchStatusChanged(int status, String cameraId);
+    void notifyShortcutKeyPressed(long shortcutCode);
 }
+
diff --git a/core/java/com/android/internal/util/ArrayUtils.java b/core/java/com/android/internal/util/ArrayUtils.java
index 8026949..ee73b90 100644
--- a/core/java/com/android/internal/util/ArrayUtils.java
+++ b/core/java/com/android/internal/util/ArrayUtils.java
@@ -27,6 +27,8 @@
 import java.lang.reflect.Array;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
 import java.util.Objects;
 
 /**
@@ -126,6 +128,13 @@
     /**
      * Checks if given array is null or has zero elements.
      */
+    public static boolean isEmpty(@Nullable List<?> array) {
+        return array == null || array.isEmpty();
+    }
+
+    /**
+     * Checks if given array is null or has zero elements.
+     */
     public static <T> boolean isEmpty(@Nullable T[] array) {
         return array == null || array.length == 0;
     }
@@ -469,4 +478,48 @@
         }
         return !diff;
     }
+
+    /**
+     * Removes elements that match the predicate in an efficient way that alters the order of
+     * elements in the collection. This should only be used if order is not important.
+     * @param collection The ArrayList from which to remove elements.
+     * @param predicate The predicate that each element is tested against.
+     * @return the number of elements removed.
+     */
+    public static <T> int unstableRemoveIf(@Nullable ArrayList<T> collection,
+                                           @NonNull java.util.function.Predicate<T> predicate) {
+        if (collection == null) {
+            return 0;
+        }
+
+        final int size = collection.size();
+        int leftIdx = 0;
+        int rightIdx = size - 1;
+        while (leftIdx <= rightIdx) {
+            // Find the next element to remove moving left to right.
+            while (leftIdx < size && !predicate.test(collection.get(leftIdx))) {
+                leftIdx++;
+            }
+
+            // Find the next element to keep moving right to left.
+            while (rightIdx > leftIdx && predicate.test(collection.get(rightIdx))) {
+                rightIdx--;
+            }
+
+            if (leftIdx >= rightIdx) {
+                // Done.
+                break;
+            }
+
+            Collections.swap(collection, leftIdx, rightIdx);
+            leftIdx++;
+            rightIdx--;
+        }
+
+        // leftIdx is now at the end.
+        for (int i = size - 1; i >= leftIdx; i--) {
+            collection.remove(i);
+        }
+        return size - leftIdx;
+    }
 }
diff --git a/core/java/com/android/internal/util/WakeupMessage.java b/core/java/com/android/internal/util/WakeupMessage.java
index 451078b..2653745 100644
--- a/core/java/com/android/internal/util/WakeupMessage.java
+++ b/core/java/com/android/internal/util/WakeupMessage.java
@@ -21,7 +21,9 @@
 import android.os.Handler;
 import android.os.Message;
 
-/**
+import com.android.internal.annotations.VisibleForTesting;
+
+ /**
  * An AlarmListener that sends the specified message to a Handler and keeps the system awake until
  * the message is processed.
  *
@@ -36,9 +38,13 @@
  */
 public class WakeupMessage implements AlarmManager.OnAlarmListener {
     private final AlarmManager mAlarmManager;
-    private final Handler mHandler;
-    private final String mCmdName;
-    private final int mCmd, mArg1, mArg2;
+
+    @VisibleForTesting
+    protected final Handler mHandler;
+    @VisibleForTesting
+    protected final String mCmdName;
+    @VisibleForTesting
+    protected final int mCmd, mArg1, mArg2;
     private boolean mScheduled;
 
     public WakeupMessage(Context context, Handler handler,
diff --git a/core/java/com/android/internal/widget/ActionBarContainer.java b/core/java/com/android/internal/widget/ActionBarContainer.java
index 398bbe7..baf3188 100644
--- a/core/java/com/android/internal/widget/ActionBarContainer.java
+++ b/core/java/com/android/internal/widget/ActionBarContainer.java
@@ -147,7 +147,7 @@
     }
 
     @Override
-    protected boolean verifyDrawable(Drawable who) {
+    protected boolean verifyDrawable(@NonNull Drawable who) {
         return (who == mBackground && !mIsSplit) || (who == mStackedBackground && mIsStacked) ||
                 (who == mSplitBackground && mIsSplit) || super.verifyDrawable(who);
     }
diff --git a/core/java/com/android/internal/widget/ImageFloatingTextView.java b/core/java/com/android/internal/widget/ImageFloatingTextView.java
index c4ed2e1..78c5e34 100644
--- a/core/java/com/android/internal/widget/ImageFloatingTextView.java
+++ b/core/java/com/android/internal/widget/ImageFloatingTextView.java
@@ -65,6 +65,8 @@
                 .setTextDirection(getTextDirectionHeuristic())
                 .setLineSpacing(getLineSpacingExtra(), getLineSpacingMultiplier())
                 .setIncludePad(getIncludeFontPadding())
+                .setEllipsize(shouldEllipsize ? effectiveEllipsize : null)
+                .setEllipsizedWidth(ellipsisWidth)
                 .setBreakStrategy(Layout.BREAK_STRATEGY_HIGH_QUALITY)
                 .setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_FULL);
         // we set the endmargin on the first 2 lines. this works just in our case but that's
diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java
index cbc735f..9d14478 100644
--- a/core/java/com/android/internal/widget/LockPatternUtils.java
+++ b/core/java/com/android/internal/widget/LockPatternUtils.java
@@ -887,8 +887,7 @@
      * @return true if device encryption is enabled
      */
     public static boolean isDeviceEncryptionEnabled() {
-        final String status = SystemProperties.get("ro.crypto.state", "unsupported");
-        return "encrypted".equalsIgnoreCase(status);
+        return StorageManager.isEncrypted();
     }
 
     /**
@@ -896,8 +895,7 @@
      * @return true if device is file encrypted
      */
     public static boolean isFileEncryptionEnabled() {
-        final String status = SystemProperties.get("ro.crypto.type", "");
-        return "file".equalsIgnoreCase(status);
+        return StorageManager.isFileEncryptedNativeOrEmulated();
     }
 
     /**
diff --git a/core/java/com/android/internal/widget/MediaNotificationView.java b/core/java/com/android/internal/widget/MediaNotificationView.java
index 6bba1b3..f63afad 100644
--- a/core/java/com/android/internal/widget/MediaNotificationView.java
+++ b/core/java/com/android/internal/widget/MediaNotificationView.java
@@ -89,36 +89,50 @@
         int topMargin = getMeasuredHeight() - mRightIcon.getMeasuredHeight()
                 - iconParams.bottomMargin;
         // If the topMargin is high enough we can also remove the header constraint!
+        boolean reMeasure = false;
         if (!hasIcon || topMargin >= mImageMinTopMargin) {
-            resetHeaderIndention();
+            reMeasure = resetHeaderIndention();
         } else {
             int paddingEnd = mNotificationContentImageMarginEnd;
             ViewGroup.MarginLayoutParams headerParams =
                     (MarginLayoutParams) mHeader.getLayoutParams();
-            headerParams.setMarginEnd(mRightIcon.getMeasuredWidth() + iconParams.getMarginEnd());
-            if (mHeader.getPaddingEnd() != paddingEnd) {
-                mHeader.setPadding(
-                        isLayoutRtl() ? paddingEnd : mHeader.getPaddingLeft(),
-                        mHeader.getPaddingTop(),
-                        isLayoutRtl() ? mHeader.getPaddingLeft() : paddingEnd,
-                        mHeader.getPaddingBottom());
+            int newMarginEnd = mRightIcon.getMeasuredWidth() + iconParams.getMarginEnd();
+            if (headerParams.getMarginEnd() != newMarginEnd) {
+                headerParams.setMarginEnd(newMarginEnd);
                 mHeader.setLayoutParams(headerParams);
+                reMeasure = true;
             }
+            if (mHeader.getPaddingEnd() != paddingEnd) {
+                mHeader.setPaddingRelative(mHeader.getPaddingStart(),
+                        mHeader.getPaddingTop(),
+                        paddingEnd,
+                        mHeader.getPaddingBottom());
+                reMeasure = true;
+            }
+        }
+        if (reMeasure) {
+            measureChildWithMargins(mHeader, widthMeasureSpec, 0, heightMeasureSpec, 0);
         }
     }
 
-    private void resetHeaderIndention() {
+    private boolean resetHeaderIndention() {
+        boolean remeasure = false;
         if (mHeader.getPaddingEnd() != mNotificationContentMarginEnd) {
-            ViewGroup.MarginLayoutParams headerParams =
-                    (MarginLayoutParams) mHeader.getLayoutParams();
-            headerParams.setMarginEnd(0);
-            mHeader.setPadding(
-                    isLayoutRtl() ? mNotificationContentMarginEnd : mHeader.getPaddingLeft(),
+            mHeader.setPaddingRelative(mHeader.getPaddingStart(),
                     mHeader.getPaddingTop(),
-                    isLayoutRtl() ? mHeader.getPaddingLeft() : mNotificationContentMarginEnd,
+                    mNotificationContentMarginEnd,
                     mHeader.getPaddingBottom());
-            mHeader.setLayoutParams(headerParams);
+            remeasure = true;
         }
+        ViewGroup.MarginLayoutParams headerParams =
+                (MarginLayoutParams) mHeader.getLayoutParams();
+        headerParams.setMarginEnd(0);
+        if (headerParams.getMarginEnd() != 0) {
+            headerParams.setMarginEnd(0);
+            mHeader.setLayoutParams(headerParams);
+            remeasure = true;
+        }
+        return remeasure;
     }
 
     public MediaNotificationView(Context context, AttributeSet attrs, int defStyleAttr,
diff --git a/core/java/com/android/internal/widget/ViewPager.java b/core/java/com/android/internal/widget/ViewPager.java
index 948a6bb..277fafd 100644
--- a/core/java/com/android/internal/widget/ViewPager.java
+++ b/core/java/com/android/internal/widget/ViewPager.java
@@ -17,6 +17,7 @@
 package com.android.internal.widget;
 
 import android.annotation.DrawableRes;
+import android.annotation.NonNull;
 import android.content.Context;
 import android.content.res.Resources;
 import android.content.res.TypedArray;
@@ -746,7 +747,7 @@
     }
 
     @Override
-    protected boolean verifyDrawable(Drawable who) {
+    protected boolean verifyDrawable(@NonNull Drawable who) {
         return super.verifyDrawable(who) || who == mMarginDrawable;
     }
 
diff --git a/core/java/com/android/server/BootReceiver.java b/core/java/com/android/server/BootReceiver.java
index ab75b7c..6d6c162 100644
--- a/core/java/com/android/server/BootReceiver.java
+++ b/core/java/com/android/server/BootReceiver.java
@@ -29,6 +29,7 @@
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.SystemProperties;
+import android.os.storage.StorageManager;
 import android.provider.Downloads;
 import android.util.AtomicFile;
 import android.util.Slog;
@@ -143,8 +144,7 @@
         HashMap<String, Long> timestamps = readTimestamps();
 
         if (SystemProperties.getLong("ro.runtime.firstboot", 0) == 0) {
-            if ("encrypted".equals(SystemProperties.get("ro.crypto.state"))
-                && "trigger_restart_min_framework".equals(SystemProperties.get("vold.decrypt"))) {
+            if (StorageManager.inCryptKeeperBounce()) {
                 // Encrypted, first boot to get PIN/pattern/password so data is tmpfs
                 // Don't set ro.runtime.firstboot so that we will do this again
                 // when data is properly mounted
diff --git a/core/java/com/android/server/net/NetworkPinner.java b/core/java/com/android/server/net/NetworkPinner.java
new file mode 100644
index 0000000..d922a48
--- /dev/null
+++ b/core/java/com/android/server/net/NetworkPinner.java
@@ -0,0 +1,146 @@
+/*
+ * 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.net;
+
+import android.content.Context;
+import android.net.ConnectivityManager;
+import android.net.ConnectivityManager.NetworkCallback;
+import android.net.Network;
+import android.net.NetworkRequest;
+import android.util.Log;
+
+import com.android.internal.annotations.GuardedBy;
+import com.android.internal.annotations.VisibleForTesting;
+
+/**
+ * A class that pins a process to the first network that satisfies a particular NetworkRequest.
+ *
+ * We use this to maintain compatibility with pre-M apps that call WifiManager.enableNetwork()
+ * to connect to a Wi-Fi network that has no Internet access, and then assume that they will be
+ * able to use that network because it's the system default.
+ *
+ * In order to maintain compatibility with apps that call setProcessDefaultNetwork themselves,
+ * we try not to set the default network unless they have already done so, and we try not to
+ * clear the default network unless we set it ourselves.
+ *
+ * This should maintain behaviour that's compatible with L, which would pin the whole system to
+ * any wifi network that was created via enableNetwork(..., true) until that network
+ * disconnected.
+ *
+ * Note that while this hack allows network traffic to flow, it is quite limited. For example:
+ *
+ * 1. setProcessDefaultNetwork only affects this process, so:
+ *    - Any subprocesses spawned by this process will not be pinned to Wi-Fi.
+ *    - If this app relies on any other apps on the device also being on Wi-Fi, that won't work
+ *      either, because other apps on the device will not be pinned.
+ * 2. The behaviour of other APIs is not modified. For example:
+ *    - getActiveNetworkInfo will return the system default network, not Wi-Fi.
+ *    - There will be no CONNECTIVITY_ACTION broadcasts about TYPE_WIFI.
+ *    - getProcessDefaultNetwork will not return null, so if any apps are relying on that, they
+ *      will be surprised as well.
+ *
+ * This class is a per-process singleton because the process default network is a per-process
+ * singleton.
+ *
+ */
+public class NetworkPinner extends NetworkCallback {
+
+    private static final String TAG = NetworkPinner.class.getSimpleName();
+
+    @VisibleForTesting
+    protected static final Object sLock = new Object();
+
+    @GuardedBy("sLock")
+    private static ConnectivityManager sCM;
+    @GuardedBy("sLock")
+    private static Callback sCallback;
+    @VisibleForTesting
+    @GuardedBy("sLock")
+    protected static Network sNetwork;
+
+    private static void maybeInitConnectivityManager(Context context) {
+        // TODO: what happens if an app calls a WifiManager API before ConnectivityManager is
+        // registered? Can we fix this by starting ConnectivityService before WifiService?
+        if (sCM == null) {
+            // Getting a ConnectivityManager does not leak the calling context, because it stores
+            // the application context and not the calling context.
+            sCM = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
+            if (sCM == null) {
+                throw new IllegalStateException("Bad luck, ConnectivityService not started.");
+            }
+        }
+    }
+
+    private static class Callback extends NetworkCallback {
+        @Override
+        public void onAvailable(Network network) {
+            synchronized(sLock) {
+                if (this != sCallback) return;
+
+                if (sCM.getBoundNetworkForProcess() == null && sNetwork == null) {
+                    sCM.bindProcessToNetwork(network);
+                    sNetwork = network;
+                    Log.d(TAG, "Wifi alternate reality enabled on network " + network);
+                }
+                sLock.notify();
+            }
+        }
+
+        @Override
+        public void onLost(Network network) {
+            synchronized (sLock) {
+                if (this != sCallback) return;
+
+                if (network.equals(sNetwork) && network.equals(sCM.getBoundNetworkForProcess())) {
+                    unpin();
+                    Log.d(TAG, "Wifi alternate reality disabled on network " + network);
+                }
+                sLock.notify();
+            }
+        }
+    }
+
+    public static void pin(Context context, NetworkRequest request) {
+        synchronized (sLock) {
+            if (sCallback == null) {
+                maybeInitConnectivityManager(context);
+                sCallback = new Callback();
+                try {
+                    sCM.registerNetworkCallback(request, sCallback);
+                } catch (SecurityException e) {
+                    Log.d(TAG, "Failed to register network callback", e);
+                    sCallback = null;
+                }
+            }
+        }
+    }
+
+    public static void unpin() {
+        synchronized (sLock) {
+            if (sCallback != null) {
+                try {
+                    sCM.bindProcessToNetwork(null);
+                    sCM.unregisterNetworkCallback(sCallback);
+                } catch (SecurityException e) {
+                    Log.d(TAG, "Failed to unregister network callback", e);
+                }
+                sCallback = null;
+                sNetwork = null;
+            }
+        }
+    }
+}
diff --git a/core/jni/Android.mk b/core/jni/Android.mk
index 4be36594..623b603 100644
--- a/core/jni/Android.mk
+++ b/core/jni/Android.mk
@@ -7,7 +7,7 @@
 LOCAL_CFLAGS += -Wno-unused-parameter
 LOCAL_CFLAGS += -Wno-non-virtual-dtor
 LOCAL_CFLAGS += -Wno-maybe-uninitialized -Wno-parentheses
-#LOCAL_CFLAGS += -DHWUI_NEW_OPS
+LOCAL_CFLAGS += -DHWUI_NEW_OPS
 LOCAL_CPPFLAGS += -Wno-conversion-null
 
 ifeq ($(TARGET_ARCH), arm)
@@ -33,6 +33,8 @@
     com_android_internal_content_NativeLibraryHelper.cpp \
     com_google_android_gles_jni_EGLImpl.cpp \
     com_google_android_gles_jni_GLImpl.cpp.arm \
+    android_app_Activity.cpp \
+    android_app_ApplicationLoaders.cpp \
     android_app_NativeActivity.cpp \
     android_auditing_SecurityLog.cpp \
     android_opengl_EGL14.cpp \
@@ -188,7 +190,6 @@
     $(call include-path-for, bluedroid) \
     $(call include-path-for, libhardware)/hardware \
     $(call include-path-for, libhardware_legacy)/hardware_legacy \
-    $(TOP)/frameworks/av/include \
     $(TOP)/frameworks/base/media/jni \
     $(TOP)/system/core/base/include \
     $(TOP)/system/core/include \
@@ -259,7 +260,8 @@
     libprocessgroup \
     libnativebridge \
     libradio_metadata \
-    libnativeloader
+    libnativeloader \
+    libmemunreachable \
 
 LOCAL_SHARED_LIBRARIES += \
     libhwui \
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index 017fb53..2a04526 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -177,6 +177,8 @@
 extern int register_android_backup_FileBackupHelperBase(JNIEnv *env);
 extern int register_android_backup_BackupHelperDispatcher(JNIEnv *env);
 extern int register_android_app_backup_FullBackup(JNIEnv *env);
+extern int register_android_app_ApplicationLoaders(JNIEnv* env);
+extern int register_android_app_Activity(JNIEnv *env);
 extern int register_android_app_ActivityThread(JNIEnv *env);
 extern int register_android_app_NativeActivity(JNIEnv *env);
 extern int register_android_media_RemoteDisplay(JNIEnv *env);
@@ -1371,6 +1373,8 @@
     REG_JNI(register_android_backup_FileBackupHelperBase),
     REG_JNI(register_android_backup_BackupHelperDispatcher),
     REG_JNI(register_android_app_backup_FullBackup),
+    REG_JNI(register_android_app_ApplicationLoaders),
+    REG_JNI(register_android_app_Activity),
     REG_JNI(register_android_app_ActivityThread),
     REG_JNI(register_android_app_NativeActivity),
     REG_JNI(register_android_util_jar_StrictJarFile),
diff --git a/core/jni/android/graphics/BitmapFactory.cpp b/core/jni/android/graphics/BitmapFactory.cpp
index 8b248b0..fb9b1e5 100644
--- a/core/jni/android/graphics/BitmapFactory.cpp
+++ b/core/jni/android/graphics/BitmapFactory.cpp
@@ -201,6 +201,26 @@
     const unsigned int mSize;
 };
 
+// Necessary for decodes when the native decoder cannot scale to appropriately match the sampleSize
+// (for example, RAW). If the sampleSize divides evenly into the dimension, we require that the
+// scale matches exactly. If sampleSize does not divide evenly, we allow the decoder to choose how
+// best to round.
+static bool needsFineScale(const int fullSize, const int decodedSize, const int sampleSize) {
+    if (fullSize % sampleSize == 0 && fullSize / sampleSize != decodedSize) {
+        return true;
+    } else if ((fullSize / sampleSize + 1) != decodedSize &&
+               (fullSize / sampleSize) != decodedSize) {
+        return true;
+    }
+    return false;
+}
+
+static bool needsFineScale(const SkISize fullSize, const SkISize decodedSize,
+                           const int sampleSize) {
+    return needsFineScale(fullSize.width(), decodedSize.width(), sampleSize) ||
+           needsFineScale(fullSize.height(), decodedSize.height(), sampleSize);
+}
+
 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
@@ -250,7 +270,6 @@
             }
         }
     }
-    const bool willScale = scale != 1.0f;
 
     // Create the codec.
     NinePatchPeeker peeker;
@@ -269,15 +288,28 @@
         prefColorType = kN32_SkColorType;
     }
 
-    // Determine the output size and return if the client only wants the size.
+    // Determine the output size.
     SkISize size = codec->getSampledDimensions(sampleSize);
+
+    int scaledWidth = size.width();
+    int scaledHeight = size.height();
+    bool willScale = false;
+
+    // Apply a fine scaling step if necessary.
+    if (needsFineScale(codec->getInfo().dimensions(), size, sampleSize)) {
+        willScale = true;
+        scaledWidth = codec->getInfo().width() / sampleSize;
+        scaledHeight = codec->getInfo().height() / sampleSize;
+    }
+
+    // Set the options and return if the client only wants the size.
     if (options != NULL) {
         jstring mimeType = encodedFormatToString(env, codec->getEncodedFormat());
         if (env->ExceptionCheck()) {
             return nullObjectReturn("OOM in encodedFormatToString()");
         }
-        env->SetIntField(options, gOptions_widthFieldID, size.width());
-        env->SetIntField(options, gOptions_heightFieldID, size.height());
+        env->SetIntField(options, gOptions_widthFieldID, scaledWidth);
+        env->SetIntField(options, gOptions_heightFieldID, scaledHeight);
         env->SetObjectField(options, gOptions_mimeFieldID, mimeType);
 
         if (onlyDecodeSize) {
@@ -285,6 +317,13 @@
         }
     }
 
+    // Scale is necessary due to density differences.
+    if (scale != 1.0f) {
+        willScale = true;
+        scaledWidth = static_cast<int>(scaledWidth * scale + 0.5f);
+        scaledHeight = static_cast<int>(scaledHeight * scale + 0.5f);
+    }
+
     android::Bitmap* reuseBitmap = nullptr;
     unsigned int existingBufferSize = 0;
     if (javaBitmap != NULL) {
@@ -381,13 +420,6 @@
             return nullObjectReturn("codec->getAndroidPixels() failed.");
     }
 
-    int scaledWidth = size.width();
-    int scaledHeight = size.height();
-    if (willScale) {
-        scaledWidth = int(scaledWidth * scale + 0.5f);
-        scaledHeight = int(scaledHeight * scale + 0.5f);
-    }
-
     jbyteArray ninePatchChunk = NULL;
     if (peeker.mPatch != NULL) {
         if (willScale) {
@@ -555,6 +587,12 @@
     std::unique_ptr<SkFILEStream> fileStream(new SkFILEStream(file,
             SkFILEStream::kCallerPasses_Ownership));
 
+    // If there is no offset for the file descriptor, we use SkFILEStream directly.
+    if (::lseek(descriptor, 0, SEEK_CUR) == 0) {
+        assert(isSeekable(dupDescriptor));
+        return doDecode(env, fileStream.release(), padding, bitmapFactoryOptions);
+    }
+
     // Use a buffered stream. Although an SkFILEStream can be rewound, this
     // ensures that SkImageDecoder::Factory never rewinds beyond the
     // current position of the file descriptor.
@@ -584,7 +622,7 @@
 
 static jboolean nativeIsSeekable(JNIEnv* env, jobject, jobject fileDescriptor) {
     jint descriptor = jniGetFDFromFileDescriptor(env, fileDescriptor);
-    return ::lseek64(descriptor, 0, SEEK_CUR) != -1 ? JNI_TRUE : JNI_FALSE;
+    return isSeekable(descriptor) ? JNI_TRUE : JNI_FALSE;
 }
 
 jobject decodeBitmap(JNIEnv* env, void* data, size_t size) {
diff --git a/core/jni/android/graphics/Utils.cpp b/core/jni/android/graphics/Utils.cpp
index 4f9ce8b..5fa445e 100644
--- a/core/jni/android/graphics/Utils.cpp
+++ b/core/jni/android/graphics/Utils.cpp
@@ -116,3 +116,7 @@
     }
     return NULL;
 }
+
+bool android::isSeekable(int descriptor) {
+    return ::lseek64(descriptor, 0, SEEK_CUR) != -1;
+}
diff --git a/core/jni/android/graphics/Utils.h b/core/jni/android/graphics/Utils.h
index c0b9410..d1a74a0 100644
--- a/core/jni/android/graphics/Utils.h
+++ b/core/jni/android/graphics/Utils.h
@@ -68,6 +68,10 @@
 
 jobject nullObjectReturn(const char msg[]);
 
+/** Check if the file descriptor is seekable.
+ */
+bool isSeekable(int descriptor);
+
 }; // namespace android
 
 #endif  // _ANDROID_GRAPHICS_UTILS_H_
diff --git a/core/jni/android/graphics/pdf/PdfDocument.cpp b/core/jni/android/graphics/pdf/PdfDocument.cpp
index 7a13fe4..5d496e5 100644
--- a/core/jni/android/graphics/pdf/PdfDocument.cpp
+++ b/core/jni/android/graphics/pdf/PdfDocument.cpp
@@ -94,8 +94,6 @@
             SkCanvas* canvas = document->beginPage(page->mWidth, page->mHeight,
                     &(page->mContentRect));
 
-            canvas->clipRect(page->mContentRect);
-            canvas->translate(page->mContentRect.left(), page->mContentRect.top());
             canvas->drawPicture(page->mPicture);
 
             document->endPage();
diff --git a/core/jni/android_app_Activity.cpp b/core/jni/android_app_Activity.cpp
new file mode 100644
index 0000000..56f4f01
--- /dev/null
+++ b/core/jni/android_app_Activity.cpp
@@ -0,0 +1,51 @@
+/*
+ * 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.
+ */
+
+#include <poll.h>
+
+#include <string>
+
+#include "core_jni_helpers.h"
+
+extern "C" void android_dlwarning(void*, void (*)(void*, const char*));
+
+namespace android
+{
+
+static jstring getDlWarning_native(JNIEnv* env, jobject) {
+    std::string msg;
+    android_dlwarning(&msg, [](void* obj, const char* msg) {
+        if (msg != nullptr) {
+            *reinterpret_cast<std::string*>(obj) = msg;
+        }
+    });
+
+    return msg.empty() ? nullptr : env->NewStringUTF(msg.c_str());
+}
+
+static const JNINativeMethod g_methods[] = {
+    { "getDlWarning",
+        "()Ljava/lang/String;",
+        reinterpret_cast<void*>(getDlWarning_native) },
+};
+
+static const char* const kActivityPathName = "android/app/Activity";
+
+int register_android_app_Activity(JNIEnv* env) {
+    return RegisterMethodsOrDie(env, kActivityPathName, g_methods, NELEM(g_methods));
+}
+
+} // namespace android
diff --git a/core/jni/android_app_ApplicationLoaders.cpp b/core/jni/android_app_ApplicationLoaders.cpp
new file mode 100644
index 0000000..89f22eb
--- /dev/null
+++ b/core/jni/android_app_ApplicationLoaders.cpp
@@ -0,0 +1,51 @@
+/*
+ * 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 <string>
+
+#include "nativeloader/native_loader.h"
+
+#include "core_jni_helpers.h"
+
+
+static jstring createClassloaderNamespace_native(JNIEnv* env,
+                                              jobject clazz,
+                                              jobject classLoader,
+                                              jint targetSdkVersion,
+                                              jstring librarySearchPath,
+                                              jstring libraryPermittedPath,
+                                              jboolean isShared) {
+    return android::CreateClassLoaderNamespace(env, targetSdkVersion,
+                                               classLoader, isShared == JNI_TRUE,
+                                               librarySearchPath, libraryPermittedPath);
+}
+
+static const JNINativeMethod g_methods[] = {
+    { "createClassloaderNamespace",
+      "(Ljava/lang/ClassLoader;ILjava/lang/String;Ljava/lang/String;Z)Ljava/lang/String;",
+      reinterpret_cast<void*>(createClassloaderNamespace_native) },
+};
+
+static const char* const kApplicationLoadersPathName = "android/app/ApplicationLoaders";
+
+namespace android
+{
+
+int register_android_app_ApplicationLoaders(JNIEnv* env) {
+    return RegisterMethodsOrDie(env, kApplicationLoadersPathName, g_methods, NELEM(g_methods));
+}
+
+} // namespace android
diff --git a/core/jni/android_app_NativeActivity.cpp b/core/jni/android_app_NativeActivity.cpp
index 88a56d2..6431b94 100644
--- a/core/jni/android_app_NativeActivity.cpp
+++ b/core/jni/android_app_NativeActivity.cpp
@@ -259,8 +259,7 @@
 loadNativeCode_native(JNIEnv* env, jobject clazz, jstring path, jstring funcName,
         jobject messageQueue, jstring internalDataDir, jstring obbDir,
         jstring externalDataDir, jint sdkVersion, jobject jAssetMgr,
-        jbyteArray savedState, jobject classLoader, jstring libraryPath,
-        jstring isolationPath) {
+        jbyteArray savedState, jobject classLoader, jstring libraryPath) {
     if (kLogTrace) {
         ALOGD("loadNativeCode_native");
     }
@@ -269,8 +268,7 @@
     std::unique_ptr<NativeCode> code;
     bool needNativeBridge = false;
 
-    void* handle = OpenNativeLibrary(env, sdkVersion, pathStr, classLoader,
-                                     false, libraryPath, isolationPath);
+    void* handle = OpenNativeLibrary(env, sdkVersion, pathStr, classLoader, libraryPath);
     if (handle == NULL) {
         if (NativeBridgeIsSupported(pathStr)) {
             handle = NativeBridgeLoadLibrary(pathStr, RTLD_LAZY);
@@ -656,7 +654,7 @@
 
 static const JNINativeMethod g_methods[] = {
     { "loadNativeCode",
-        "(Ljava/lang/String;Ljava/lang/String;Landroid/os/MessageQueue;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ILandroid/content/res/AssetManager;[BLjava/lang/ClassLoader;Ljava/lang/String;Ljava/lang/String;)J",
+        "(Ljava/lang/String;Ljava/lang/String;Landroid/os/MessageQueue;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ILandroid/content/res/AssetManager;[BLjava/lang/ClassLoader;Ljava/lang/String;)J",
         (void*)loadNativeCode_native },
     { "getDlError", "()Ljava/lang/String;", (void*) getDlError_native },
     { "unloadNativeCode", "(J)V", (void*)unloadNativeCode_native },
diff --git a/core/jni/android_hardware_camera2_CameraMetadata.cpp b/core/jni/android_hardware_camera2_CameraMetadata.cpp
index 7930027..f37fd78 100644
--- a/core/jni/android_hardware_camera2_CameraMetadata.cpp
+++ b/core/jni/android_hardware_camera2_CameraMetadata.cpp
@@ -33,9 +33,9 @@
 #include "core_jni_helpers.h"
 #include "android_runtime/android_hardware_camera2_CameraMetadata.h"
 
+#include <android/hardware/ICameraService.h>
 #include <binder/IServiceManager.h>
 #include <camera/CameraMetadata.h>
-#include <camera/ICameraService.h>
 #include <camera/VendorTagDescriptor.h>
 #include <nativehelper/ScopedUtfChars.h>
 #include <nativehelper/ScopedPrimitiveArray.h>
@@ -906,32 +906,35 @@
 
 static jint CameraMetadata_setupGlobalVendorTagDescriptor(JNIEnv *env, jobject thiz) {
     const String16 NAME("media.camera");
-    sp<ICameraService> cameraService;
+    sp<hardware::ICameraService> cameraService;
     status_t err = getService(NAME, /*out*/&cameraService);
 
     if (err != OK) {
         ALOGE("%s: Failed to get camera service, received error %s (%d)", __FUNCTION__,
                 strerror(-err), err);
-        return err;
+        return hardware::ICameraService::ERROR_DISCONNECTED;
     }
 
-    sp<VendorTagDescriptor> desc;
-    err = cameraService->getCameraVendorTagDescriptor(/*out*/desc);
+    sp<VendorTagDescriptor> desc = new VendorTagDescriptor();
+    binder::Status res = cameraService->getCameraVendorTagDescriptor(/*out*/desc.get());
 
-    if (err == -EOPNOTSUPP) {
-        ALOGW("%s: Camera HAL too old; does not support vendor tags", __FUNCTION__);
+    if (res.serviceSpecificErrorCode() == hardware::ICameraService::ERROR_DISCONNECTED) {
+        // No camera module available, not an error on devices with no cameras
         VendorTagDescriptor::clearGlobalVendorTagDescriptor();
-
         return OK;
-    } else if (err != OK) {
-        ALOGE("%s: Failed to setup vendor tag descriptors, received error %s (%d)",
-                __FUNCTION__, strerror(-err), err);
-        return err;
+    } else if (!res.isOk()) {
+        VendorTagDescriptor::clearGlobalVendorTagDescriptor();
+        ALOGE("%s: Failed to setup vendor tag descriptors: %s",
+                __FUNCTION__, res.toString8().string());
+        return res.serviceSpecificErrorCode();
     }
 
     err = VendorTagDescriptor::setAsGlobalVendorTagDescriptor(desc);
 
-    return err;
+    if (err != OK) {
+        return hardware::ICameraService::ERROR_INVALID_OPERATION;
+    }
+    return OK;
 }
 
 } // extern "C"
diff --git a/core/jni/android_hardware_camera2_DngCreator.cpp b/core/jni/android_hardware_camera2_DngCreator.cpp
index cb0abb6..d80d8f2 100644
--- a/core/jni/android_hardware_camera2_DngCreator.cpp
+++ b/core/jni/android_hardware_camera2_DngCreator.cpp
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-#define LOG_NDEBUG 0
+//#define LOG_NDEBUG 0
 #define LOG_TAG "DngCreator_JNI"
 #include <inttypes.h>
 #include <string.h>
@@ -80,6 +80,13 @@
         return nullptr; \
     }
 
+#define BAIL_IF_EXPR_RET_NULL_SP(expr, jnienv, tagId, writer) \
+    if (expr) { \
+        jniThrowExceptionFmt(jnienv, "java/lang/IllegalArgumentException", \
+                "Invalid metadata for tag %s (%x)", (writer)->getTagName(tagId), (tagId)); \
+        return nullptr; \
+    }
+
 
 #define ANDROID_DNGCREATOR_CTX_JNI_ID     "mNativeContext"
 
@@ -195,8 +202,8 @@
 NativeContext::NativeContext(const CameraMetadata& characteristics, const CameraMetadata& result) :
         mCharacteristics(std::make_shared<CameraMetadata>(characteristics)),
         mResult(std::make_shared<CameraMetadata>(result)), mThumbnailWidth(0),
-        mThumbnailHeight(0), mOrientation(0), mThumbnailSet(false), mGpsSet(false),
-        mDescriptionSet(false), mCaptureTimeSet(false) {}
+        mThumbnailHeight(0), mOrientation(TAG_ORIENTATION_UNKNOWN), mThumbnailSet(false),
+        mGpsSet(false), mDescriptionSet(false), mCaptureTimeSet(false) {}
 
 NativeContext::~NativeContext() {}
 
@@ -1096,7 +1103,7 @@
 
     {
         // Set orientation
-        uint16_t orientation = 1; // Normal
+        uint16_t orientation = TAG_ORIENTATION_NORMAL;
         BAIL_IF_INVALID_RET_NULL_SP(writer->addEntry(TAG_ORIENTATION, 1, &orientation, TIFF_IFD_0),
                 env, TAG_ORIENTATION, writer);
     }
@@ -1138,12 +1145,27 @@
     }
 
     {
-        // Set blacklevel tags
+        // Set blacklevel tags, using dynamic black level if available
         camera_metadata_entry entry =
-                characteristics.find(ANDROID_SENSOR_BLACK_LEVEL_PATTERN);
-        BAIL_IF_EMPTY_RET_NULL_SP(entry, env, TAG_BLACKLEVEL, writer);
-        const uint32_t* blackLevel = reinterpret_cast<const uint32_t*>(entry.data.i32);
-        BAIL_IF_INVALID_RET_NULL_SP(writer->addEntry(TAG_BLACKLEVEL, entry.count, blackLevel,
+                results.find(ANDROID_SENSOR_DYNAMIC_BLACK_LEVEL);
+        uint32_t blackLevelRational[8] = {0};
+        if (entry.count != 0) {
+            BAIL_IF_EXPR_RET_NULL_SP(entry.count != 4, env, TAG_BLACKLEVEL, writer);
+            for (size_t i = 0; i < entry.count; i++) {
+                blackLevelRational[i * 2] = static_cast<uint32_t>(entry.data.f[i] * 100);
+                blackLevelRational[i * 2 + 1] = 100;
+            }
+        } else {
+            // Fall back to static black level which is guaranteed
+            entry = characteristics.find(ANDROID_SENSOR_BLACK_LEVEL_PATTERN);
+            BAIL_IF_EXPR_RET_NULL_SP(entry.count != 4, env, TAG_BLACKLEVEL, writer);
+            for (size_t i = 0; i < entry.count; i++) {
+                blackLevelRational[i * 2] = static_cast<uint32_t>(entry.data.i32[i]);
+                blackLevelRational[i * 2 + 1] = 1;
+            }
+
+        }
+        BAIL_IF_INVALID_RET_NULL_SP(writer->addEntry(TAG_BLACKLEVEL, 4, blackLevelRational,
                 TIFF_IFD_0), env, TAG_BLACKLEVEL, writer);
 
         uint16_t repeatDim[2] = {2, 2};
@@ -1770,6 +1792,8 @@
 
     {
         // Set up orientation tags.
+        // Note: There's only one orientation field for the whole file, in IFD0
+        // The main image and any thumbnails therefore have the same orientation.
         uint16_t orientation = nativeContext->getOrientation();
         BAIL_IF_INVALID_RET_NULL_SP(writer->addEntry(TAG_ORIENTATION, 1, &orientation, TIFF_IFD_0),
                 env, TAG_ORIENTATION, writer);
@@ -1851,7 +1875,6 @@
         }
 
         Vector<uint16_t> tagsToMove;
-        tagsToMove.add(TAG_ORIENTATION);
         tagsToMove.add(TAG_NEWSUBFILETYPE);
         tagsToMove.add(TAG_ACTIVEAREA);
         tagsToMove.add(TAG_BITSPERSAMPLE);
@@ -1882,12 +1905,6 @@
             return nullptr;
         }
 
-        // Make sure both IFDs get the same orientation tag
-        sp<TiffEntry> orientEntry = writer->getEntry(TAG_ORIENTATION, TIFF_IFD_SUB1);
-        if (orientEntry.get() != nullptr) {
-            writer->addEntry(orientEntry, TIFF_IFD_0);
-        }
-
         // Setup thumbnail tags
 
         {
@@ -1913,8 +1930,10 @@
 
         {
             // Set bits per sample
-            uint16_t bits = BITS_PER_RGB_SAMPLE;
-            BAIL_IF_INVALID_RET_NULL_SP(writer->addEntry(TAG_BITSPERSAMPLE, 1, &bits, TIFF_IFD_0),
+            uint16_t bits[SAMPLES_PER_RGB_PIXEL];
+            for (int i = 0; i < SAMPLES_PER_RGB_PIXEL; i++) bits[i] = BITS_PER_RGB_SAMPLE;
+            BAIL_IF_INVALID_RET_NULL_SP(
+                    writer->addEntry(TAG_BITSPERSAMPLE, SAMPLES_PER_RGB_PIXEL, bits, TIFF_IFD_0),
                     env, TAG_BITSPERSAMPLE, writer);
         }
 
diff --git a/core/jni/android_hardware_camera2_legacy_LegacyCameraDevice.cpp b/core/jni/android_hardware_camera2_legacy_LegacyCameraDevice.cpp
index f1ea7ec..80f9d57 100644
--- a/core/jni/android_hardware_camera2_legacy_LegacyCameraDevice.cpp
+++ b/core/jni/android_hardware_camera2_legacy_LegacyCameraDevice.cpp
@@ -29,6 +29,7 @@
 
 #include <gui/Surface.h>
 #include <gui/IGraphicBufferProducer.h>
+#include <gui/IProducerListener.h>
 #include <ui/GraphicBuffer.h>
 #include <system/window.h>
 #include <hardware/camera3.h>
@@ -93,27 +94,17 @@
             cStep, yStride, cStride);
 }
 
-static status_t configureSurface(const sp<ANativeWindow>& anw,
-                                 int32_t width,
-                                 int32_t height,
-                                 int32_t pixelFmt,
-                                 int32_t maxBufferSlack) {
+static status_t connectSurface(const sp<Surface>& surface, int32_t maxBufferSlack) {
     status_t err = NO_ERROR;
-    err = native_window_set_buffers_dimensions(anw.get(), width, height);
-    if (err != NO_ERROR) {
-        ALOGE("%s: Failed to set native window buffer dimensions, error %s (%d).", __FUNCTION__,
+
+    err = surface->connect(NATIVE_WINDOW_API_CAMERA, /*listener*/NULL);
+    if (err != OK) {
+        ALOGE("%s: Unable to connect to surface, error %s (%d).", __FUNCTION__,
                 strerror(-err), err);
         return err;
     }
 
-    err = native_window_set_buffers_format(anw.get(), pixelFmt);
-    if (err != NO_ERROR) {
-        ALOGE("%s: Failed to set native window buffer format, error %s (%d).", __FUNCTION__,
-                strerror(-err), err);
-        return err;
-    }
-
-    err = native_window_set_usage(anw.get(), GRALLOC_USAGE_SW_WRITE_OFTEN);
+    err = native_window_set_usage(surface.get(), GRALLOC_USAGE_SW_WRITE_OFTEN);
     if (err != NO_ERROR) {
         ALOGE("%s: Failed to set native window usage flag, error %s (%d).", __FUNCTION__,
                 strerror(-err), err);
@@ -121,19 +112,17 @@
     }
 
     int minUndequeuedBuffers;
-    err = anw.get()->query(anw.get(),
-            NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS,
-            &minUndequeuedBuffers);
+    err = static_cast<ANativeWindow*>(surface.get())->query(surface.get(),
+            NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, &minUndequeuedBuffers);
     if (err != NO_ERROR) {
         ALOGE("%s: Failed to get native window min undequeued buffers, error %s (%d).",
                 __FUNCTION__, strerror(-err), err);
         return err;
     }
 
-    ALOGV("%s: Setting buffer count to %d, size to (%dx%d), fmt (0x%x)", __FUNCTION__,
-          maxBufferSlack + 1 + minUndequeuedBuffers,
-          width, height, pixelFmt);
-    err = native_window_set_buffer_count(anw.get(), maxBufferSlack + 1 + minUndequeuedBuffers);
+    ALOGV("%s: Setting buffer count to %d", __FUNCTION__,
+            maxBufferSlack + 1 + minUndequeuedBuffers);
+    err = native_window_set_buffer_count(surface.get(), maxBufferSlack + 1 + minUndequeuedBuffers);
     if (err != NO_ERROR) {
         ALOGE("%s: Failed to set native window buffer count, error %s (%d).", __FUNCTION__,
                 strerror(-err), err);
@@ -509,6 +498,26 @@
     return usage;
 }
 
+static jint LegacyCameraDevice_nativeDisconnectSurface(JNIEnv* env, jobject thiz,
+          jobject surface) {
+    ALOGV("nativeDisconnectSurface");
+    if (surface == nullptr) return NO_ERROR;
+
+    sp<ANativeWindow> anw;
+    if ((anw = getNativeWindow(env, surface)) == NULL) {
+        ALOGV("Buffer queue has already been abandoned.");
+        return NO_ERROR;
+    }
+
+    status_t err = native_window_api_disconnect(anw.get(), NATIVE_WINDOW_API_CAMERA);
+    if(err != NO_ERROR) {
+        jniThrowException(env, "Ljava/lang/UnsupportedOperationException;",
+            "Error while disconnecting surface");
+        return err;
+    }
+    return NO_ERROR;
+}
+
 static jint LegacyCameraDevice_nativeDetectTextureDimens(JNIEnv* env, jobject thiz,
         jobject surfaceTexture, jintArray dimens) {
     ALOGV("nativeDetectTextureDimens");
@@ -540,15 +549,14 @@
     return NO_ERROR;
 }
 
-static jint LegacyCameraDevice_nativeConfigureSurface(JNIEnv* env, jobject thiz, jobject surface,
-        jint width, jint height, jint pixelFormat) {
-    ALOGV("nativeConfigureSurface");
-    sp<ANativeWindow> anw;
-    if ((anw = getNativeWindow(env, surface)) == NULL) {
-        ALOGE("%s: Could not retrieve native window from surface.", __FUNCTION__);
+static jint LegacyCameraDevice_nativeConnectSurface(JNIEnv* env, jobject thiz, jobject surface) {
+    ALOGV("nativeConnectSurface");
+    sp<Surface> s;
+    if ((s = getSurface(env, surface)) == NULL) {
+        ALOGE("%s: Could not retrieve surface.", __FUNCTION__);
         return BAD_VALUE;
     }
-    status_t err = configureSurface(anw, width, height, pixelFormat, CAMERA_DEVICE_BUFFER_SLACK);
+    status_t err = connectSurface(s, CAMERA_DEVICE_BUFFER_SLACK);
     if (err != NO_ERROR) {
         ALOGE("%s: Error while configuring surface %s (%d).", __FUNCTION__, strerror(-err), err);
         return err;
@@ -740,9 +748,9 @@
     { "nativeDetectSurfaceDimens",
     "(Landroid/view/Surface;[I)I",
     (void *)LegacyCameraDevice_nativeDetectSurfaceDimens },
-    { "nativeConfigureSurface",
-    "(Landroid/view/Surface;III)I",
-    (void *)LegacyCameraDevice_nativeConfigureSurface },
+    { "nativeConnectSurface",
+    "(Landroid/view/Surface;)I",
+    (void *)LegacyCameraDevice_nativeConnectSurface },
     { "nativeProduceFrame",
     "(Landroid/view/Surface;[BIII)I",
     (void *)LegacyCameraDevice_nativeProduceFrame },
@@ -773,6 +781,9 @@
     { "nativeSetScalingMode",
     "(Landroid/view/Surface;I)I",
     (void *)LegacyCameraDevice_nativeSetScalingMode },
+    { "nativeDisconnectSurface",
+    "(Landroid/view/Surface;)I",
+    (void *)LegacyCameraDevice_nativeDisconnectSurface },
 };
 
 // Get all the required offsets in java class and register native functions
diff --git a/core/jni/android_media_AudioRecord.cpp b/core/jni/android_media_AudioRecord.cpp
index 6904fda..3e4e352 100644
--- a/core/jni/android_media_AudioRecord.cpp
+++ b/core/jni/android_media_AudioRecord.cpp
@@ -181,57 +181,14 @@
 static jint
 android_media_AudioRecord_setup(JNIEnv *env, jobject thiz, jobject weak_this,
         jobject jaa, jintArray jSampleRate, jint channelMask, jint channelIndexMask,
-        jint audioFormat, jint buffSizeInBytes, jintArray jSession, jstring opPackageName)
+        jint audioFormat, jint buffSizeInBytes, jintArray jSession, jstring opPackageName,
+        jlong nativeRecordInJavaObj)
 {
-    jint elements[1];
-    env->GetIntArrayRegion(jSampleRate, 0, 1, elements);
-    int sampleRateInHertz = elements[0];
-
     //ALOGV(">> Entering android_media_AudioRecord_setup");
-    //ALOGV("sampleRate=%d, audioFormat=%d, channel mask=%x, buffSizeInBytes=%d",
-    //     sampleRateInHertz, audioFormat, channelMask, buffSizeInBytes);
-
-    if (jaa == 0) {
-        ALOGE("Error creating AudioRecord: invalid audio attributes");
-        return (jint) AUDIO_JAVA_ERROR;
-    }
-
-    // channel index mask takes priority over channel position masks.
-    if (channelIndexMask) {
-        // Java channel index masks need the representation bits set.
-        channelMask = audio_channel_mask_from_representation_and_bits(
-                AUDIO_CHANNEL_REPRESENTATION_INDEX,
-                channelIndexMask);
-    }
-    // Java channel position masks map directly to the native definition
-
-    if (!audio_is_input_channel(channelMask)) {
-        ALOGE("Error creating AudioRecord: channel mask %#x is not valid.", channelMask);
-        return (jint) AUDIORECORD_ERROR_SETUP_INVALIDCHANNELMASK;
-    }
-    uint32_t channelCount = audio_channel_count_from_in_mask(channelMask);
-
-    // compare the format against the Java constants
-    audio_format_t format = audioFormatToNative(audioFormat);
-    if (format == AUDIO_FORMAT_INVALID) {
-        ALOGE("Error creating AudioRecord: unsupported audio format %d.", audioFormat);
-        return (jint) AUDIORECORD_ERROR_SETUP_INVALIDFORMAT;
-    }
-
-    size_t bytesPerSample = audio_bytes_per_sample(format);
-
-    if (buffSizeInBytes == 0) {
-         ALOGE("Error creating AudioRecord: frameCount is 0.");
-        return (jint) AUDIORECORD_ERROR_SETUP_ZEROFRAMECOUNT;
-    }
-    size_t frameSize = channelCount * bytesPerSample;
-    size_t frameCount = buffSizeInBytes / frameSize;
-
-    jclass clazz = env->GetObjectClass(thiz);
-    if (clazz == NULL) {
-        ALOGE("Can't find %s when setting up callback.", kClassPathName);
-        return (jint) AUDIORECORD_ERROR_SETUP_NATIVEINITFAILED;
-    }
+    //ALOGV("sampleRate=%d, audioFormat=%d, channel mask=%x, buffSizeInBytes=%d "
+    //     "nativeRecordInJavaObj=0x%llX",
+    //     sampleRateInHertz, audioFormat, channelMask, buffSizeInBytes, nativeRecordInJavaObj);
+    audio_channel_mask_t localChanMask = inChannelMaskToNative(channelMask);
 
     if (jSession == NULL) {
         ALOGE("Error creating AudioRecord: invalid session ID pointer");
@@ -247,55 +204,132 @@
     env->ReleasePrimitiveArrayCritical(jSession, nSession, 0);
     nSession = NULL;
 
-    ScopedUtfChars opPackageNameStr(env, opPackageName);
-
-    // create an uninitialized AudioRecord object
-    sp<AudioRecord> lpRecorder = new AudioRecord(String16(opPackageNameStr.c_str()));
-
     audio_attributes_t *paa = NULL;
-    // read the AudioAttributes values
-    paa = (audio_attributes_t *) calloc(1, sizeof(audio_attributes_t));
-    const jstring jtags =
-            (jstring) env->GetObjectField(jaa, javaAudioAttrFields.fieldFormattedTags);
-    const char* tags = env->GetStringUTFChars(jtags, NULL);
-    // copying array size -1, char array for tags was calloc'd, no need to NULL-terminate it
-    strncpy(paa->tags, tags, AUDIO_ATTRIBUTES_TAGS_MAX_SIZE - 1);
-    env->ReleaseStringUTFChars(jtags, tags);
-    paa->source = (audio_source_t) env->GetIntField(jaa, javaAudioAttrFields.fieldRecSource);
-    paa->flags = (audio_flags_mask_t)env->GetIntField(jaa, javaAudioAttrFields.fieldFlags);
-    ALOGV("AudioRecord_setup for source=%d tags=%s flags=%08x", paa->source, paa->tags, paa->flags);
+    sp<AudioRecord> lpRecorder = 0;
+    audiorecord_callback_cookie *lpCallbackData = NULL;
 
-    audio_input_flags_t flags = AUDIO_INPUT_FLAG_NONE;
-    if (paa->flags & AUDIO_FLAG_HW_HOTWORD) {
-        flags = AUDIO_INPUT_FLAG_HW_HOTWORD;
+    jclass clazz = env->GetObjectClass(thiz);
+    if (clazz == NULL) {
+        ALOGE("Can't find %s when setting up callback.", kClassPathName);
+        return (jint) AUDIORECORD_ERROR_SETUP_NATIVEINITFAILED;
     }
-    // create the callback information:
-    // this data will be passed with every AudioRecord callback
-    audiorecord_callback_cookie *lpCallbackData = new audiorecord_callback_cookie;
-    lpCallbackData->audioRecord_class = (jclass)env->NewGlobalRef(clazz);
-    // we use a weak reference so the AudioRecord object can be garbage collected.
-    lpCallbackData->audioRecord_ref = env->NewGlobalRef(weak_this);
-    lpCallbackData->busy = false;
 
-    const status_t status = lpRecorder->set(paa->source,
-        sampleRateInHertz,
-        format,        // word length, PCM
-        channelMask,
-        frameCount,
-        recorderCallback,// callback_t
-        lpCallbackData,// void* user
-        0,             // notificationFrames,
-        true,          // threadCanCallJava
-        sessionId,
-        AudioRecord::TRANSFER_DEFAULT,
-        flags,
-        -1, -1,        // default uid, pid
-        paa);
+    // if we pass in an existing *Native* AudioRecord, we don't need to create/initialize one.
+    if (nativeRecordInJavaObj == 0) {
+        if (jaa == 0) {
+            ALOGE("Error creating AudioRecord: invalid audio attributes");
+            return (jint) AUDIO_JAVA_ERROR;
+        }
 
-    if (status != NO_ERROR) {
-        ALOGE("Error creating AudioRecord instance: initialization check failed with status %d.",
-                status);
-        goto native_init_failure;
+        if (jSampleRate == 0) {
+            ALOGE("Error creating AudioRecord: invalid sample rates");
+            return (jint) AUDIO_JAVA_ERROR;
+        }
+        jint elements[1];
+        env->GetIntArrayRegion(jSampleRate, 0, 1, elements);
+        int sampleRateInHertz = elements[0];
+
+        // channel index mask takes priority over channel position masks.
+        if (channelIndexMask) {
+            // Java channel index masks need the representation bits set.
+            localChanMask = audio_channel_mask_from_representation_and_bits(
+                    AUDIO_CHANNEL_REPRESENTATION_INDEX,
+                    channelIndexMask);
+        }
+        // Java channel position masks map directly to the native definition
+
+        if (!audio_is_input_channel(localChanMask)) {
+            ALOGE("Error creating AudioRecord: channel mask %#x is not valid.", localChanMask);
+            return (jint) AUDIORECORD_ERROR_SETUP_INVALIDCHANNELMASK;
+        }
+        uint32_t channelCount = audio_channel_count_from_in_mask(localChanMask);
+
+        // compare the format against the Java constants
+        audio_format_t format = audioFormatToNative(audioFormat);
+        if (format == AUDIO_FORMAT_INVALID) {
+            ALOGE("Error creating AudioRecord: unsupported audio format %d.", audioFormat);
+            return (jint) AUDIORECORD_ERROR_SETUP_INVALIDFORMAT;
+        }
+
+        size_t bytesPerSample = audio_bytes_per_sample(format);
+
+        if (buffSizeInBytes == 0) {
+             ALOGE("Error creating AudioRecord: frameCount is 0.");
+            return (jint) AUDIORECORD_ERROR_SETUP_ZEROFRAMECOUNT;
+        }
+        size_t frameSize = channelCount * bytesPerSample;
+        size_t frameCount = buffSizeInBytes / frameSize;
+
+        ScopedUtfChars opPackageNameStr(env, opPackageName);
+
+        // create an uninitialized AudioRecord object
+        lpRecorder = new AudioRecord(String16(opPackageNameStr.c_str()));
+
+        // read the AudioAttributes values
+        paa = (audio_attributes_t *) calloc(1, sizeof(audio_attributes_t));
+        const jstring jtags =
+                (jstring) env->GetObjectField(jaa, javaAudioAttrFields.fieldFormattedTags);
+        const char* tags = env->GetStringUTFChars(jtags, NULL);
+        // copying array size -1, char array for tags was calloc'd, no need to NULL-terminate it
+        strncpy(paa->tags, tags, AUDIO_ATTRIBUTES_TAGS_MAX_SIZE - 1);
+        env->ReleaseStringUTFChars(jtags, tags);
+        paa->source = (audio_source_t) env->GetIntField(jaa, javaAudioAttrFields.fieldRecSource);
+        paa->flags = (audio_flags_mask_t)env->GetIntField(jaa, javaAudioAttrFields.fieldFlags);
+        ALOGV("AudioRecord_setup for source=%d tags=%s flags=%08x", paa->source, paa->tags, paa->flags);
+
+        audio_input_flags_t flags = AUDIO_INPUT_FLAG_NONE;
+        if (paa->flags & AUDIO_FLAG_HW_HOTWORD) {
+            flags = AUDIO_INPUT_FLAG_HW_HOTWORD;
+        }
+        // create the callback information:
+        // this data will be passed with every AudioRecord callback
+        lpCallbackData = new audiorecord_callback_cookie;
+        lpCallbackData->audioRecord_class = (jclass)env->NewGlobalRef(clazz);
+        // we use a weak reference so the AudioRecord object can be garbage collected.
+        lpCallbackData->audioRecord_ref = env->NewGlobalRef(weak_this);
+        lpCallbackData->busy = false;
+
+        const status_t status = lpRecorder->set(paa->source,
+            sampleRateInHertz,
+            format,        // word length, PCM
+            localChanMask,
+            frameCount,
+            recorderCallback,// callback_t
+            lpCallbackData,// void* user
+            0,             // notificationFrames,
+            true,          // threadCanCallJava
+            sessionId,
+            AudioRecord::TRANSFER_DEFAULT,
+            flags,
+            -1, -1,        // default uid, pid
+            paa);
+
+        if (status != NO_ERROR) {
+            ALOGE("Error creating AudioRecord instance: initialization check failed with status %d.",
+                    status);
+            goto native_init_failure;
+        }
+    } else { // end if nativeRecordInJavaObj == 0)
+        lpRecorder = (AudioRecord*)nativeRecordInJavaObj;
+        // TODO: We need to find out which members of the Java AudioRecord might need to be
+        // initialized from the Native AudioRecord
+        // these are directly returned from getters:
+        //  mSampleRate
+        //  mRecordSource
+        //  mAudioFormat
+        //  mChannelMask
+        //  mChannelCount
+        //  mState (?)
+        //  mRecordingState (?)
+        //  mPreferredDevice
+
+        // create the callback information:
+        // this data will be passed with every AudioRecord callback
+        lpCallbackData = new audiorecord_callback_cookie;
+        lpCallbackData->audioRecord_class = (jclass)env->NewGlobalRef(clazz);
+        // we use a weak reference so the AudioRecord object can be garbage collected.
+        lpCallbackData->audioRecord_ref = env->NewGlobalRef(weak_this);
+        lpCallbackData->busy = false;
     }
 
     nSession = (jint *) env->GetPrimitiveArrayCritical(jSession, NULL);
@@ -726,8 +760,8 @@
     // name,               signature,  funcPtr
     {"native_start",         "(II)I",    (void *)android_media_AudioRecord_start},
     {"native_stop",          "()V",    (void *)android_media_AudioRecord_stop},
-    {"native_setup",         "(Ljava/lang/Object;Ljava/lang/Object;[IIIII[ILjava/lang/String;)I",
-                                       (void *)android_media_AudioRecord_setup},
+    {"native_setup",         "(Ljava/lang/Object;Ljava/lang/Object;[IIIII[ILjava/lang/String;J)I",
+                                      (void *)android_media_AudioRecord_setup},
     {"native_finalize",      "()V",    (void *)android_media_AudioRecord_finalize},
     {"native_release",       "()V",    (void *)android_media_AudioRecord_release},
     {"native_read_in_byte_array",
diff --git a/core/jni/android_media_AudioSystem.cpp b/core/jni/android_media_AudioSystem.cpp
index 7d9e4a2..1eb0111 100644
--- a/core/jni/android_media_AudioSystem.cpp
+++ b/core/jni/android_media_AudioSystem.cpp
@@ -320,7 +320,7 @@
 static jint
 android_media_AudioSystem_newAudioSessionId(JNIEnv *env, jobject thiz)
 {
-    return AudioSystem::newAudioUniqueId();
+    return AudioSystem::newAudioUniqueId(AUDIO_UNIQUE_ID_USE_SESSION);
 }
 
 static jint
@@ -389,7 +389,8 @@
 
 static void
 android_media_AudioSystem_recording_callback(int event, int session, int source,
-        const audio_config_base_t *clientConfig, const audio_config_base_t *deviceConfig)
+        const audio_config_base_t *clientConfig, const audio_config_base_t *deviceConfig,
+        audio_patch_handle_t patchHandle)
 {
     JNIEnv *env = AndroidRuntime::getJNIEnv();
     if (env == NULL) {
@@ -401,12 +402,14 @@
     }
 
     // create an array for 2*3 integers to store the record configurations (client + device)
-    jintArray recParamArray = env->NewIntArray(6);
+    //                 plus 1 integer for the patch handle
+    const int REC_PARAM_SIZE = 7;
+    jintArray recParamArray = env->NewIntArray(REC_PARAM_SIZE);
     if (recParamArray == NULL) {
         ALOGE("recording callback: Couldn't allocate int array for configuration data");
         return;
     }
-    jint recParamData[6];
+    jint recParamData[REC_PARAM_SIZE];
     recParamData[0] = (jint) audioFormatFromNative(clientConfig->format);
     // FIXME this doesn't support index-based masks
     recParamData[1] = (jint) inChannelMaskFromNative(clientConfig->channel_mask);
@@ -415,7 +418,8 @@
     // FIXME this doesn't support index-based masks
     recParamData[4] = (jint) inChannelMaskFromNative(deviceConfig->channel_mask);
     recParamData[5] = (jint) deviceConfig->sample_rate;
-    env->SetIntArrayRegion(recParamArray, 0, 6, recParamData);
+    recParamData[6] = (jint) patchHandle;
+    env->SetIntArrayRegion(recParamArray, 0, REC_PARAM_SIZE, recParamData);
 
     // callback into java
     jclass clazz = env->FindClass(kClassPathName);
diff --git a/core/jni/android_media_AudioTrack.cpp b/core/jni/android_media_AudioTrack.cpp
index 84cc185..302cf63 100644
--- a/core/jni/android_media_AudioTrack.cpp
+++ b/core/jni/android_media_AudioTrack.cpp
@@ -213,55 +213,17 @@
 
 // ----------------------------------------------------------------------------
 static jint
-android_media_AudioTrack_setup(JNIEnv *env, jobject thiz, jobject weak_this,
-        jobject jaa,
+android_media_AudioTrack_setup(JNIEnv *env, jobject thiz, jobject weak_this, jobject jaa,
         jintArray jSampleRate, jint channelPositionMask, jint channelIndexMask,
-        jint audioFormat, jint buffSizeInBytes, jint memoryMode, jintArray jSession) {
+        jint audioFormat, jint buffSizeInBytes, jint memoryMode, jintArray jSession,
+        jlong nativeAudioTrack) {
 
-    jint elements[1];
-    env->GetIntArrayRegion(jSampleRate, 0, 1, elements);
-    int sampleRateInHertz = elements[0];
+    ALOGV("sampleRates=%p, channel mask=%x, index mask=%x, audioFormat(Java)=%d, buffSize=%d"
+        "nativeAudioTrack=0x%llX",
+        jSampleRate, channelPositionMask, channelIndexMask, audioFormat, buffSizeInBytes,
+        nativeAudioTrack);
 
-    ALOGV("sampleRate=%d, channel mask=%x, index mask=%x, audioFormat(Java)=%d, buffSize=%d",
-        sampleRateInHertz, channelPositionMask, channelIndexMask, audioFormat, buffSizeInBytes);
-
-    if (jaa == 0) {
-        ALOGE("Error creating AudioTrack: invalid audio attributes");
-        return (jint) AUDIO_JAVA_ERROR;
-    }
-
-    // Invalid channel representations are caught by !audio_is_output_channel() below.
-    audio_channel_mask_t nativeChannelMask = nativeChannelMaskFromJavaChannelMasks(
-            channelPositionMask, channelIndexMask);
-    if (!audio_is_output_channel(nativeChannelMask)) {
-        ALOGE("Error creating AudioTrack: invalid native channel mask %#x.", nativeChannelMask);
-        return (jint) AUDIOTRACK_ERROR_SETUP_INVALIDCHANNELMASK;
-    }
-
-    uint32_t channelCount = audio_channel_count_from_out_mask(nativeChannelMask);
-
-    // check the format.
-    // This function was called from Java, so we compare the format against the Java constants
-    audio_format_t format = audioFormatToNative(audioFormat);
-    if (format == AUDIO_FORMAT_INVALID) {
-        ALOGE("Error creating AudioTrack: unsupported audio format %d.", audioFormat);
-        return (jint) AUDIOTRACK_ERROR_SETUP_INVALIDFORMAT;
-    }
-
-    // compute the frame count
-    size_t frameCount;
-    if (audio_has_proportional_frames(format)) {
-        const size_t bytesPerSample = audio_bytes_per_sample(format);
-        frameCount = buffSizeInBytes / (channelCount * bytesPerSample);
-    } else {
-        frameCount = buffSizeInBytes;
-    }
-
-    jclass clazz = env->GetObjectClass(thiz);
-    if (clazz == NULL) {
-        ALOGE("Can't find %s when setting up callback.", kClassPathName);
-        return (jint) AUDIOTRACK_ERROR_SETUP_NATIVEINITFAILED;
-    }
+    sp<AudioTrack> lpTrack = 0;
 
     if (jSession == NULL) {
         ALOGE("Error creating AudioTrack: invalid session ID pointer");
@@ -277,91 +239,168 @@
     env->ReleasePrimitiveArrayCritical(jSession, nSession, 0);
     nSession = NULL;
 
-    // create the native AudioTrack object
-    sp<AudioTrack> lpTrack = new AudioTrack();
+    AudioTrackJniStorage* lpJniStorage = NULL;
 
     audio_attributes_t *paa = NULL;
-    // read the AudioAttributes values
-    paa = (audio_attributes_t *) calloc(1, sizeof(audio_attributes_t));
-    const jstring jtags =
-            (jstring) env->GetObjectField(jaa, javaAudioAttrFields.fieldFormattedTags);
-    const char* tags = env->GetStringUTFChars(jtags, NULL);
-    // copying array size -1, char array for tags was calloc'd, no need to NULL-terminate it
-    strncpy(paa->tags, tags, AUDIO_ATTRIBUTES_TAGS_MAX_SIZE - 1);
-    env->ReleaseStringUTFChars(jtags, tags);
-    paa->usage = (audio_usage_t) env->GetIntField(jaa, javaAudioAttrFields.fieldUsage);
-    paa->content_type =
-            (audio_content_type_t) env->GetIntField(jaa, javaAudioAttrFields.fieldContentType);
-    paa->flags = env->GetIntField(jaa, javaAudioAttrFields.fieldFlags);
 
-    ALOGV("AudioTrack_setup for usage=%d content=%d flags=0x%#x tags=%s",
-            paa->usage, paa->content_type, paa->flags, paa->tags);
+    jclass clazz = env->GetObjectClass(thiz);
+    if (clazz == NULL) {
+        ALOGE("Can't find %s when setting up callback.", kClassPathName);
+        return (jint) AUDIOTRACK_ERROR_SETUP_NATIVEINITFAILED;
+    }
 
-    // initialize the callback information:
-    // this data will be passed with every AudioTrack callback
-    AudioTrackJniStorage* lpJniStorage = new AudioTrackJniStorage();
-    lpJniStorage->mCallbackData.audioTrack_class = (jclass)env->NewGlobalRef(clazz);
-    // we use a weak reference so the AudioTrack object can be garbage collected.
-    lpJniStorage->mCallbackData.audioTrack_ref = env->NewGlobalRef(weak_this);
-    lpJniStorage->mCallbackData.busy = false;
+    // if we pass in an existing *Native* AudioTrack, we don't need to create/initialize one.
+    if (nativeAudioTrack == 0) {
+        if (jaa == 0) {
+            ALOGE("Error creating AudioTrack: invalid audio attributes");
+            return (jint) AUDIO_JAVA_ERROR;
+        }
 
-    // initialize the native AudioTrack object
-    status_t status = NO_ERROR;
-    switch (memoryMode) {
-    case MODE_STREAM:
+        if (jSampleRate == 0) {
+            ALOGE("Error creating AudioTrack: invalid sample rates");
+            return (jint) AUDIO_JAVA_ERROR;
+        }
 
-        status = lpTrack->set(
-                AUDIO_STREAM_DEFAULT,// stream type, but more info conveyed in paa (last argument)
-                sampleRateInHertz,
-                format,// word length, PCM
-                nativeChannelMask,
-                frameCount,
-                AUDIO_OUTPUT_FLAG_NONE,
-                audioCallback, &(lpJniStorage->mCallbackData),//callback, callback data (user)
-                0,// notificationFrames == 0 since not using EVENT_MORE_DATA to feed the AudioTrack
-                0,// shared mem
-                true,// thread can call Java
-                sessionId,// audio session ID
-                AudioTrack::TRANSFER_SYNC,
-                NULL,                         // default offloadInfo
-                -1, -1,                       // default uid, pid values
-                paa);
-        break;
+        int* sampleRates = env->GetIntArrayElements(jSampleRate, NULL);
+        int sampleRateInHertz = sampleRates[0];
+        env->ReleaseIntArrayElements(jSampleRate, sampleRates, JNI_ABORT);
 
-    case MODE_STATIC:
-        // AudioTrack is using shared memory
+        // Invalid channel representations are caught by !audio_is_output_channel() below.
+        audio_channel_mask_t nativeChannelMask = nativeChannelMaskFromJavaChannelMasks(
+                channelPositionMask, channelIndexMask);
+        if (!audio_is_output_channel(nativeChannelMask)) {
+            ALOGE("Error creating AudioTrack: invalid native channel mask %#x.", nativeChannelMask);
+            return (jint) AUDIOTRACK_ERROR_SETUP_INVALIDCHANNELMASK;
+        }
 
-        if (!lpJniStorage->allocSharedMem(buffSizeInBytes)) {
-            ALOGE("Error creating AudioTrack in static mode: error creating mem heap base");
+        uint32_t channelCount = audio_channel_count_from_out_mask(nativeChannelMask);
+
+        // check the format.
+        // This function was called from Java, so we compare the format against the Java constants
+        audio_format_t format = audioFormatToNative(audioFormat);
+        if (format == AUDIO_FORMAT_INVALID) {
+            ALOGE("Error creating AudioTrack: unsupported audio format %d.", audioFormat);
+            return (jint) AUDIOTRACK_ERROR_SETUP_INVALIDFORMAT;
+        }
+
+        // compute the frame count
+        size_t frameCount;
+        if (audio_is_linear_pcm(format)) {
+            const size_t bytesPerSample = audio_bytes_per_sample(format);
+            frameCount = buffSizeInBytes / (channelCount * bytesPerSample);
+        } else {
+            frameCount = buffSizeInBytes;
+        }
+
+        // create the native AudioTrack object
+        lpTrack = new AudioTrack();
+
+        // read the AudioAttributes values
+        paa = (audio_attributes_t *) calloc(1, sizeof(audio_attributes_t));
+        const jstring jtags =
+                (jstring) env->GetObjectField(jaa, javaAudioAttrFields.fieldFormattedTags);
+        const char* tags = env->GetStringUTFChars(jtags, NULL);
+        // copying array size -1, char array for tags was calloc'd, no need to NULL-terminate it
+        strncpy(paa->tags, tags, AUDIO_ATTRIBUTES_TAGS_MAX_SIZE - 1);
+        env->ReleaseStringUTFChars(jtags, tags);
+        paa->usage = (audio_usage_t) env->GetIntField(jaa, javaAudioAttrFields.fieldUsage);
+        paa->content_type =
+                (audio_content_type_t) env->GetIntField(jaa, javaAudioAttrFields.fieldContentType);
+        paa->flags = env->GetIntField(jaa, javaAudioAttrFields.fieldFlags);
+
+        ALOGV("AudioTrack_setup for usage=%d content=%d flags=0x%#x tags=%s",
+                paa->usage, paa->content_type, paa->flags, paa->tags);
+
+        // initialize the callback information:
+        // this data will be passed with every AudioTrack callback
+        lpJniStorage = new AudioTrackJniStorage();
+        lpJniStorage->mCallbackData.audioTrack_class = (jclass)env->NewGlobalRef(clazz);
+        // we use a weak reference so the AudioTrack object can be garbage collected.
+        lpJniStorage->mCallbackData.audioTrack_ref = env->NewGlobalRef(weak_this);
+        lpJniStorage->mCallbackData.busy = false;
+
+        // initialize the native AudioTrack object
+        status_t status = NO_ERROR;
+        switch (memoryMode) {
+        case MODE_STREAM:
+
+            status = lpTrack->set(
+                    AUDIO_STREAM_DEFAULT,// stream type, but more info conveyed in paa (last argument)
+                    sampleRateInHertz,
+                    format,// word length, PCM
+                    nativeChannelMask,
+                    frameCount,
+                    AUDIO_OUTPUT_FLAG_NONE,
+                    audioCallback, &(lpJniStorage->mCallbackData),//callback, callback data (user)
+                    0,// notificationFrames == 0 since not using EVENT_MORE_DATA to feed the AudioTrack
+                    0,// shared mem
+                    true,// thread can call Java
+                    sessionId,// audio session ID
+                    AudioTrack::TRANSFER_SYNC,
+                    NULL,                         // default offloadInfo
+                    -1, -1,                       // default uid, pid values
+                    paa);
+            break;
+
+        case MODE_STATIC:
+            // AudioTrack is using shared memory
+
+            if (!lpJniStorage->allocSharedMem(buffSizeInBytes)) {
+                ALOGE("Error creating AudioTrack in static mode: error creating mem heap base");
+                goto native_init_failure;
+            }
+
+            status = lpTrack->set(
+                    AUDIO_STREAM_DEFAULT,// stream type, but more info conveyed in paa (last argument)
+                    sampleRateInHertz,
+                    format,// word length, PCM
+                    nativeChannelMask,
+                    frameCount,
+                    AUDIO_OUTPUT_FLAG_NONE,
+                    audioCallback, &(lpJniStorage->mCallbackData),//callback, callback data (user));
+                    0,// notificationFrames == 0 since not using EVENT_MORE_DATA to feed the AudioTrack
+                    lpJniStorage->mMemBase,// shared mem
+                    true,// thread can call Java
+                    sessionId,// audio session ID
+                    AudioTrack::TRANSFER_SHARED,
+                    NULL,                         // default offloadInfo
+                    -1, -1,                       // default uid, pid values
+                    paa);
+            break;
+
+        default:
+            ALOGE("Unknown mode %d", memoryMode);
             goto native_init_failure;
         }
 
-        status = lpTrack->set(
-                AUDIO_STREAM_DEFAULT,// stream type, but more info conveyed in paa (last argument)
-                sampleRateInHertz,
-                format,// word length, PCM
-                nativeChannelMask,
-                frameCount,
-                AUDIO_OUTPUT_FLAG_NONE,
-                audioCallback, &(lpJniStorage->mCallbackData),//callback, callback data (user));
-                0,// notificationFrames == 0 since not using EVENT_MORE_DATA to feed the AudioTrack
-                lpJniStorage->mMemBase,// shared mem
-                true,// thread can call Java
-                sessionId,// audio session ID
-                AudioTrack::TRANSFER_SHARED,
-                NULL,                         // default offloadInfo
-                -1, -1,                       // default uid, pid values
-                paa);
-        break;
+        if (status != NO_ERROR) {
+            ALOGE("Error %d initializing AudioTrack", status);
+            goto native_init_failure;
+        }
+    } else {  // end if (nativeAudioTrack == 0)
+        lpTrack = (AudioTrack*)nativeAudioTrack;
+        // TODO: We need to find out which members of the Java AudioTrack might
+        // need to be initialized from the Native AudioTrack
+        // these are directly returned from getters:
+        //  mSampleRate
+        //  mAudioFormat
+        //  mStreamType
+        //  mChannelConfiguration
+        //  mChannelCount
+        //  mState (?)
+        //  mPlayState (?)
+        // these may be used internally (Java AudioTrack.audioParamCheck():
+        //  mChannelMask
+        //  mChannelIndexMask
+        //  mDataLoadMode
 
-    default:
-        ALOGE("Unknown mode %d", memoryMode);
-        goto native_init_failure;
-    }
-
-    if (status != NO_ERROR) {
-        ALOGE("Error %d initializing AudioTrack", status);
-        goto native_init_failure;
+        // initialize the callback information:
+        // this data will be passed with every AudioTrack callback
+        lpJniStorage = new AudioTrackJniStorage();
+        lpJniStorage->mCallbackData.audioTrack_class = (jclass)env->NewGlobalRef(clazz);
+        // we use a weak reference so the AudioTrack object can be garbage collected.
+        lpJniStorage->mCallbackData.audioTrack_ref = env->NewGlobalRef(weak_this);
+        lpJniStorage->mCallbackData.busy = false;
     }
 
     nSession = (jint *) env->GetPrimitiveArrayCritical(jSession, NULL);
@@ -394,9 +433,11 @@
     // since we had audio attributes, the stream type was derived from them during the
     // creation of the native AudioTrack: push the same value to the Java object
     env->SetIntField(thiz, javaAudioTrackFields.fieldStreamType, (jint) lpTrack->streamType());
-    // audio attributes were copied in AudioTrack creation
-    free(paa);
-    paa = NULL;
+    if (paa != NULL) {
+        // audio attributes were copied in AudioTrack creation
+        free(paa);
+        paa = NULL;
+    }
 
 
     return (jint) AUDIO_JAVA_SUCCESS;
@@ -418,7 +459,6 @@
     return (jint) AUDIOTRACK_ERROR_SETUP_NATIVEINITFAILED;
 }
 
-
 // ----------------------------------------------------------------------------
 static void
 android_media_AudioTrack_start(JNIEnv *env, jobject thiz)
@@ -501,7 +541,6 @@
         return;
     }
     //ALOGV("deleting lpTrack: %x\n", (int)lpTrack);
-    lpTrack->stop();
 
     // delete the JNI data
     AudioTrackJniStorage* pJniStorage = (AudioTrackJniStorage *)env->GetLongField(
@@ -1123,7 +1162,7 @@
     {"native_stop",          "()V",      (void *)android_media_AudioTrack_stop},
     {"native_pause",         "()V",      (void *)android_media_AudioTrack_pause},
     {"native_flush",         "()V",      (void *)android_media_AudioTrack_flush},
-    {"native_setup",     "(Ljava/lang/Object;Ljava/lang/Object;[IIIIII[I)I",
+    {"native_setup",     "(Ljava/lang/Object;Ljava/lang/Object;[IIIIII[IJ)I",
                                          (void *)android_media_AudioTrack_setup},
     {"native_finalize",      "()V",      (void *)android_media_AudioTrack_finalize},
     {"native_release",       "()V",      (void *)android_media_AudioTrack_release},
diff --git a/core/jni/android_net_NetUtils.cpp b/core/jni/android_net_NetUtils.cpp
index defb88a..880a79c 100644
--- a/core/jni/android_net_NetUtils.cpp
+++ b/core/jni/android_net_NetUtils.cpp
@@ -26,10 +26,13 @@
 #include <net/if.h>
 #include <linux/filter.h>
 #include <linux/if.h>
+#include <linux/if_arp.h>
 #include <linux/if_ether.h>
 #include <linux/if_packet.h>
 #include <net/if_ether.h>
+#include <netinet/icmp6.h>
 #include <netinet/ip.h>
+#include <netinet/ip6.h>
 #include <netinet/udp.h>
 #include <cutils/properties.h>
 
@@ -64,10 +67,9 @@
 
 static void android_net_utils_attachDhcpFilter(JNIEnv *env, jobject clazz, jobject javaFd)
 {
-    int fd = jniGetFDFromFileDescriptor(env, javaFd);
     uint32_t ip_offset = sizeof(ether_header);
     uint32_t proto_offset = ip_offset + offsetof(iphdr, protocol);
-    uint32_t flags_offset = ip_offset +  offsetof(iphdr, frag_off);
+    uint32_t flags_offset = ip_offset + offsetof(iphdr, frag_off);
     uint32_t dport_indirect_offset = ip_offset + offsetof(udphdr, dest);
     struct sock_filter filter_code[] = {
         // Check the protocol is UDP.
@@ -94,6 +96,45 @@
         filter_code,
     };
 
+    int fd = jniGetFDFromFileDescriptor(env, javaFd);
+    if (setsockopt(fd, SOL_SOCKET, SO_ATTACH_FILTER, &filter, sizeof(filter)) != 0) {
+        jniThrowExceptionFmt(env, "java/net/SocketException",
+                "setsockopt(SO_ATTACH_FILTER): %s", strerror(errno));
+    }
+}
+
+static void android_net_utils_attachRaFilter(JNIEnv *env, jobject clazz, jobject javaFd,
+        jint hardwareAddressType)
+{
+    if (hardwareAddressType != ARPHRD_ETHER) {
+        jniThrowExceptionFmt(env, "java/net/SocketException",
+                "attachRaFilter only supports ARPHRD_ETHER");
+        return;
+    }
+
+    uint32_t ipv6_offset = sizeof(ether_header);
+    uint32_t ipv6_next_header_offset = ipv6_offset + offsetof(ip6_hdr, ip6_nxt);
+    uint32_t icmp6_offset = ipv6_offset + sizeof(ip6_hdr);
+    uint32_t icmp6_type_offset = icmp6_offset + offsetof(icmp6_hdr, icmp6_type);
+    struct sock_filter filter_code[] = {
+        // Check IPv6 Next Header is ICMPv6.
+        BPF_STMT(BPF_LD  | BPF_B   | BPF_ABS,  ipv6_next_header_offset),
+        BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K,    IPPROTO_ICMPV6, 0, 3),
+
+        // Check ICMPv6 type is Router Advertisement.
+        BPF_STMT(BPF_LD  | BPF_B   | BPF_ABS,  icmp6_type_offset),
+        BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K,    ND_ROUTER_ADVERT, 0, 1),
+
+        // Accept or reject.
+        BPF_STMT(BPF_RET | BPF_K,              0xffff),
+        BPF_STMT(BPF_RET | BPF_K,              0)
+    };
+    struct sock_fprog filter = {
+        sizeof(filter_code) / sizeof(filter_code[0]),
+        filter_code,
+    };
+
+    int fd = jniGetFDFromFileDescriptor(env, javaFd);
     if (setsockopt(fd, SOL_SOCKET, SO_ATTACH_FILTER, &filter, sizeof(filter)) != 0) {
         jniThrowExceptionFmt(env, "java/net/SocketException",
                 "setsockopt(SO_ATTACH_FILTER): %s", strerror(errno));
@@ -148,6 +189,7 @@
     { "protectFromVpn", "(I)Z", (void*)android_net_utils_protectFromVpn },
     { "queryUserAccess", "(II)Z", (void*)android_net_utils_queryUserAccess },
     { "attachDhcpFilter", "(Ljava/io/FileDescriptor;)V", (void*) android_net_utils_attachDhcpFilter },
+    { "attachRaFilter", "(Ljava/io/FileDescriptor;I)V", (void*) android_net_utils_attachRaFilter },
 };
 
 int register_android_net_NetworkUtils(JNIEnv* env)
diff --git a/core/jni/android_opengl_GLES30.cpp b/core/jni/android_opengl_GLES30.cpp
index 2d69eaa..59b8911 100644
--- a/core/jni/android_opengl_GLES30.cpp
+++ b/core/jni/android_opengl_GLES30.cpp
@@ -2012,22 +2012,35 @@
 static void
 android_glGetTransformFeedbackVarying__IIILjava_nio_IntBuffer_2Ljava_nio_IntBuffer_2Ljava_nio_IntBuffer_2B
   (JNIEnv *_env, jobject _this, jint program, jint index, jint bufsize, jobject length_buf, jobject size_buf, jobject type_buf, jbyte name) {
+    jniThrowException(_env, "java/lang/UnsupportedOperationException", "deprecated");
+}
+
+/* void glGetTransformFeedbackVarying ( GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name ) */
+static void
+android_glGetTransformFeedbackVarying__IIILjava_nio_IntBuffer_2Ljava_nio_IntBuffer_2Ljava_nio_IntBuffer_2Ljava_nio_ByteBuffer_2
+  (JNIEnv *_env, jobject _this, jint program, jint index, jint bufsize, jobject length_buf, jobject size_buf, jobject type_buf, jobject name_buf) {
     jintArray _lengthArray = (jintArray) 0;
     jint _lengthBufferOffset = (jint) 0;
     jintArray _sizeArray = (jintArray) 0;
     jint _sizeBufferOffset = (jint) 0;
     jintArray _typeArray = (jintArray) 0;
     jint _typeBufferOffset = (jint) 0;
+    jbyteArray _nameArray = (jbyteArray)0;
+    jint _nameBufferOffset = (jint)0;
     jint _lengthRemaining;
     GLsizei *length = (GLsizei *) 0;
     jint _sizeRemaining;
     GLint *size = (GLint *) 0;
     jint _typeRemaining;
     GLenum *type = (GLenum *) 0;
+    jint _nameRemaining;
+    GLchar* name = (GLchar*)0;
+
 
     length = (GLsizei *)getPointer(_env, length_buf, (jarray*)&_lengthArray, &_lengthRemaining, &_lengthBufferOffset);
     size = (GLint *)getPointer(_env, size_buf, (jarray*)&_sizeArray, &_sizeRemaining, &_sizeBufferOffset);
     type = (GLenum *)getPointer(_env, type_buf, (jarray*)&_typeArray, &_typeRemaining, &_typeBufferOffset);
+    name = (GLchar*)getPointer(_env, name_buf, (jarray*)&_nameArray, &_nameRemaining, &_nameBufferOffset);
     if (length == NULL) {
         char * _lengthBase = (char *)_env->GetIntArrayElements(_lengthArray, (jboolean *) 0);
         length = (GLsizei *) (_lengthBase + _lengthBufferOffset);
@@ -2040,6 +2053,10 @@
         char * _typeBase = (char *)_env->GetIntArrayElements(_typeArray, (jboolean *) 0);
         type = (GLenum *) (_typeBase + _typeBufferOffset);
     }
+    if (name == NULL) {
+        char* _nameBase = (char *)_env->GetByteArrayElements(_nameArray, (jboolean*)0);
+        name = (GLchar *) (_nameBase + _nameBufferOffset);
+    }
     glGetTransformFeedbackVarying(
         (GLuint)program,
         (GLuint)index,
@@ -2047,11 +2064,7 @@
         (GLsizei *)length,
         (GLint *)size,
         (GLenum *)type,
-        // The cast below is incorrect. The driver will end up writing to the
-        // address specified by name, which will always crash the process since
-        // it is guaranteed to be in low memory. The additional static_cast
-        // suppresses the warning for now. http://b/19478262
-        (char *)static_cast<uintptr_t>(name)
+        (GLchar*)name
     );
     if (_typeArray) {
         releaseArrayPointer<jintArray, jint*, IntArrayReleaser>(_env, _typeArray, (jint*)type, JNI_TRUE);
@@ -2062,6 +2075,9 @@
     if (_lengthArray) {
         releaseArrayPointer<jintArray, jint*, IntArrayReleaser>(_env, _lengthArray, (jint*)length, JNI_TRUE);
     }
+    if (_nameArray) {
+        releaseArrayPointer<jbyteArray, jbyte*, ByteArrayReleaser>(_env, _nameArray, (jbyte*)name, JNI_TRUE);
+    }
 }
 
 /* void glGetTransformFeedbackVarying ( GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name ) */
@@ -5233,6 +5249,7 @@
 {"glTransformFeedbackVaryings", "(I[Ljava/lang/String;I)V", (void *) android_glTransformFeedbackVaryings },
 {"glGetTransformFeedbackVarying", "(III[II[II[II[BI)V", (void *) android_glGetTransformFeedbackVarying__III_3II_3II_3II_3BI },
 {"glGetTransformFeedbackVarying", "(IIILjava/nio/IntBuffer;Ljava/nio/IntBuffer;Ljava/nio/IntBuffer;B)V", (void *) android_glGetTransformFeedbackVarying__IIILjava_nio_IntBuffer_2Ljava_nio_IntBuffer_2Ljava_nio_IntBuffer_2B },
+{"glGetTransformFeedbackVarying", "(IIILjava/nio/IntBuffer;Ljava/nio/IntBuffer;Ljava/nio/IntBuffer;Ljava/nio/ByteBuffer;)V", (void *) android_glGetTransformFeedbackVarying__IIILjava_nio_IntBuffer_2Ljava_nio_IntBuffer_2Ljava_nio_IntBuffer_2Ljava_nio_ByteBuffer_2 },
 {"glGetTransformFeedbackVarying", "(II[II[II)Ljava/lang/String;", (void *) android_glGetTransformFeedbackVarying1 },
 {"glGetTransformFeedbackVarying", "(IILjava/nio/IntBuffer;Ljava/nio/IntBuffer;)Ljava/lang/String;", (void *) android_glGetTransformFeedbackVarying2 },
 {"glVertexAttribIPointerBounds", "(IIIILjava/nio/Buffer;I)V", (void *) android_glVertexAttribIPointerBounds__IIIILjava_nio_Buffer_2I },
diff --git a/core/jni/android_opengl_GLES31.cpp b/core/jni/android_opengl_GLES31.cpp
index 5751add..156e7bd 100644
--- a/core/jni/android_opengl_GLES31.cpp
+++ b/core/jni/android_opengl_GLES31.cpp
@@ -888,9 +888,69 @@
 static jint
 android_glCreateShaderProgramv
   (JNIEnv *_env, jobject _this, jint type, jobjectArray strings) {
+    jint _exception = 0;
+    const char * _exceptionType = NULL;
+    const char * _exceptionMessage = NULL;
+    GLsizei _count;
+    const GLchar** _strings = NULL;
+    jstring* _jstrings = NULL;
+    GLuint _returnValue = 0;
 
-    jniThrowException(_env, "java/lang/UnsupportedOperationException", "not yet implemented");
-    return 0;
+    if (!strings) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "strings == null";
+        goto exit;
+    }
+
+    _count = _env->GetArrayLength(strings);
+
+    _strings = (const GLchar**) calloc(_count, sizeof(const GLchar*));
+    if (!_strings) {
+        _exception = 1;
+        _exceptionType = "java/lang/OutOfMemoryError";
+        _exceptionMessage = "out of memory";
+        goto exit;
+    }
+
+    _jstrings = (jstring*) calloc(_count, sizeof(jstring));
+    if (!_jstrings) {
+        _exception = 1;
+        _exceptionType = "java/lang/OutOfMemoryError";
+        _exceptionMessage = "out of memory";
+        goto exit;
+    }
+
+    for(int i = 0; i < _count; i++) {
+        _jstrings[i] = (jstring) _env->GetObjectArrayElement(strings, i);
+        if (!_jstrings[i]) {
+            _exception = 1;
+            _exceptionType = "java/lang/IllegalArgumentException";
+            _exceptionMessage = "strings == null";
+            goto exit;
+        }
+        _strings[i] = _env->GetStringUTFChars(_jstrings[i], 0);
+    }
+
+    _returnValue = glCreateShaderProgramv((GLenum)type, _count, _strings);
+exit:
+    if (_strings && _jstrings) {
+        for(int i = 0; i < _count; i++) {
+            if (_strings[i] && _jstrings[i]) {
+                _env->ReleaseStringUTFChars(_jstrings[i], _strings[i]);
+            }
+        }
+    }
+    if (_strings) {
+        free(_strings);
+    }
+    if (_jstrings) {
+        free(_jstrings);
+    }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
+    return (jint)_returnValue;
 }
 /* void glBindProgramPipeline ( GLuint pipeline ) */
 static void
diff --git a/core/jni/android_os_Debug.cpp b/core/jni/android_os_Debug.cpp
index 03a1e71..f870a89 100644
--- a/core/jni/android_os_Debug.cpp
+++ b/core/jni/android_os_Debug.cpp
@@ -21,6 +21,7 @@
 #include "utils/misc.h"
 #include "cutils/debugger.h"
 #include <memtrack/memtrack.h>
+#include <memunreachable/memunreachable.h>
 
 #include <cutils/log.h>
 #include <fcntl.h>
@@ -36,6 +37,9 @@
 #include <ctype.h>
 #include <malloc.h>
 
+#include <iomanip>
+#include <string>
+
 namespace android
 {
 
@@ -258,7 +262,13 @@
             }
             name = line + name_pos;
             nameLen = strlen(name);
-
+            // Trim the end of the line if it is " (deleted)".
+            const char* deleted_str = " (deleted)";
+            if (nameLen > (int)strlen(deleted_str) &&
+                strcmp(name+nameLen-strlen(deleted_str), deleted_str) == 0) {
+                nameLen -= strlen(deleted_str);
+                name[nameLen] = '\0';
+            }
             if ((strstr(name, "[heap]") == name)) {
                 whichHeap = HEAP_NATIVE;
             } else if (strncmp(name, "[anon:libc_malloc]", 18) == 0) {
@@ -1023,6 +1033,13 @@
     close(fd);
 }
 
+static jstring android_os_Debug_getUnreachableMemory(JNIEnv* env, jobject clazz,
+    jint limit, jboolean contents)
+{
+    std::string s = GetUnreachableMemoryString(contents, limit);
+    return env->NewStringUTF(s.c_str());
+}
+
 /*
  * JNI registration.
  */
@@ -1058,6 +1075,8 @@
             (void*)android_os_Debug_getDeathObjectCount },
     { "dumpNativeBacktraceToFile", "(ILjava/lang/String;)V",
             (void*)android_os_Debug_dumpNativeBacktraceToFile },
+    { "getUnreachableMemory", "(IZ)Ljava/lang/String;",
+            (void*)android_os_Debug_getUnreachableMemory },
 };
 
 int register_android_os_Debug(JNIEnv *env)
diff --git a/core/jni/android_util_Binder.cpp b/core/jni/android_util_Binder.cpp
index ae109c6..abc6c4b 100644
--- a/core/jni/android_util_Binder.cpp
+++ b/core/jni/android_util_Binder.cpp
@@ -556,7 +556,7 @@
     }
 
     // For the rest of the function we will hold this lock, to serialize
-    // looking/creation of Java proxies for native Binder proxies.
+    // looking/creation/destruction of Java proxies for native Binder proxies.
     AutoMutex _l(mProxyLock);
 
     // Someone else's...  do we know about it?
@@ -1225,16 +1225,21 @@
 
 static void android_os_BinderProxy_destroy(JNIEnv* env, jobject obj)
 {
+    // Don't race with construction/initialization
+    AutoMutex _l(mProxyLock);
+
     IBinder* b = (IBinder*)
             env->GetLongField(obj, gBinderProxyOffsets.mObject);
     DeathRecipientList* drl = (DeathRecipientList*)
             env->GetLongField(obj, gBinderProxyOffsets.mOrgue);
 
     LOGDEATH("Destroying BinderProxy %p: binder=%p drl=%p\n", obj, b, drl);
-    env->SetLongField(obj, gBinderProxyOffsets.mObject, 0);
-    env->SetLongField(obj, gBinderProxyOffsets.mOrgue, 0);
-    drl->decStrong((void*)javaObjectForIBinder);
-    b->decStrong((void*)javaObjectForIBinder);
+    if (b != nullptr) {
+        env->SetLongField(obj, gBinderProxyOffsets.mObject, 0);
+        env->SetLongField(obj, gBinderProxyOffsets.mOrgue, 0);
+        drl->decStrong((void*)javaObjectForIBinder);
+        b->decStrong((void*)javaObjectForIBinder);
+    }
 
     IPCThreadState::self()->flushCommands();
 }
diff --git a/core/jni/android_util_Process.cpp b/core/jni/android_util_Process.cpp
index ee8fb19..f7a5e8a 100644
--- a/core/jni/android_util_Process.cpp
+++ b/core/jni/android_util_Process.cpp
@@ -17,6 +17,8 @@
 
 #define LOG_TAG "Process"
 
+// To make sure cpu_set_t is included from sched.h
+#define _GNU_SOURCE 1
 #include <utils/Log.h>
 #include <binder/IPCThreadState.h>
 #include <binder/IServiceManager.h>
@@ -288,6 +290,139 @@
     return (int) sp;
 }
 
+#ifdef ENABLE_CPUSETS
+/** Sample CPUset list format:
+ *  0-3,4,6-8
+ */
+static void parse_cpuset_cpus(char *cpus, cpu_set_t *cpu_set) {
+    unsigned int start, end, matched, i;
+    char *cpu_range = strtok(cpus, ",");
+    while (cpu_range != NULL) {
+        start = end = 0;
+        matched = sscanf(cpu_range, "%u-%u", &start, &end);
+        cpu_range = strtok(NULL, ",");
+        if (start >= CPU_SETSIZE) {
+            ALOGE("parse_cpuset_cpus: ignoring CPU number larger than %d.", CPU_SETSIZE);
+            continue;
+        } else if (end >= CPU_SETSIZE) {
+            ALOGE("parse_cpuset_cpus: ignoring CPU numbers larger than %d.", CPU_SETSIZE);
+            end = CPU_SETSIZE - 1;
+        }
+        if (matched == 1) {
+            CPU_SET(start, cpu_set);
+        } else if (matched == 2) {
+            for (i = start; i <= end; i++) {
+                CPU_SET(i, cpu_set);
+            }
+        } else {
+            ALOGE("Failed to match cpus");
+        }
+    }
+    return;
+}
+
+/**
+ * Stores the CPUs assigned to the cpuset corresponding to the
+ * SchedPolicy in the passed in cpu_set.
+ */
+static void get_cpuset_cores_for_policy(SchedPolicy policy, cpu_set_t *cpu_set)
+{
+    FILE *file;
+    const char *filename;
+
+    CPU_ZERO(cpu_set);
+
+    switch (policy) {
+        case SP_BACKGROUND:
+            filename = "/dev/cpuset/background/cpus";
+            break;
+        case SP_FOREGROUND:
+        case SP_AUDIO_APP:
+        case SP_AUDIO_SYS:
+            filename = "/dev/cpuset/foreground/cpus";
+            break;
+        case SP_TOP_APP:
+            filename = "/dev/cpuset/top-app/cpus";
+            break;
+        default:
+            filename = NULL;
+    }
+
+    if (!filename) return;
+
+    file = fopen(filename, "re");
+    if (file != NULL) {
+        // Parse cpus string
+        char *line = NULL;
+        size_t len = 0;
+        ssize_t num_read = getline(&line, &len, file);
+        fclose (file);
+        if (num_read > 0) {
+            parse_cpuset_cpus(line, cpu_set);
+        } else {
+            ALOGE("Failed to read %s", filename);
+        }
+        free(line);
+    }
+    return;
+}
+#endif
+
+
+/**
+ * Determine CPU cores exclusively assigned to the
+ * cpuset corresponding to the SchedPolicy and store
+ * 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);
+    }
+#else
+    (void) policy;
+    CPU_ZERO(cpu_set);
+#endif
+    return;
+}
+
+jintArray android_os_Process_getExclusiveCores(JNIEnv* env, jobject clazz) {
+    SchedPolicy sp;
+    cpu_set_t cpu_set;
+    jintArray cpus;
+    int pid = getpid();
+    if (get_sched_policy(pid, &sp) != 0) {
+        signalExceptionForGroupError(env, errno);
+        return NULL;
+    }
+    get_exclusive_cpuset_cores(sp, &cpu_set);
+    int num_cpus = CPU_COUNT(&cpu_set);
+    cpus = env->NewIntArray(num_cpus);
+    if (cpus == NULL) {
+        jniThrowException(env, "java/lang/OutOfMemoryError", NULL);
+        return NULL;
+    }
+
+    jint* cpu_elements = env->GetIntArrayElements(cpus, 0);
+    int count = 0;
+    for (int i = 0; i < CPU_SETSIZE && count < num_cpus; i++) {
+        if (CPU_ISSET(i, &cpu_set)) {
+            cpu_elements[count++] = i;
+        }
+    }
+
+    env->ReleaseIntArrayElements(cpus, cpu_elements, 0);
+    return cpus;
+}
+
 static void android_os_Process_setCanSelfBackground(JNIEnv* env, jobject clazz, jboolean bgOk) {
     // Establishes the calling thread as illegal to put into the background.
     // Typically used only for the system process's main looper.
@@ -1053,6 +1188,7 @@
     {"setThreadGroup",      "(II)V", (void*)android_os_Process_setThreadGroup},
     {"setProcessGroup",     "(II)V", (void*)android_os_Process_setProcessGroup},
     {"getProcessGroup",     "(I)I", (void*)android_os_Process_getProcessGroup},
+    {"getExclusiveCores",   "()[I", (void*)android_os_Process_getExclusiveCores},
     {"setSwappiness",   "(IZ)Z", (void*)android_os_Process_setSwappiness},
     {"setArgV0",    "(Ljava/lang/String;)V", (void*)android_os_Process_setArgV0},
     {"setUid", "(I)I", (void*)android_os_Process_setUid},
diff --git a/core/jni/android_view_Surface.cpp b/core/jni/android_view_Surface.cpp
index cf68449..b7701d6 100644
--- a/core/jni/android_view_Surface.cpp
+++ b/core/jni/android_view_Surface.cpp
@@ -411,22 +411,27 @@
         return 0;
     }
 
+    android::view::Surface surfaceShim;
+
+    // Calling code in Surface.java has already read the name of the Surface
+    // from the Parcel
+    surfaceShim.readFromParcel(parcel, /*nameAlreadyRead*/true);
+
     sp<Surface> self(reinterpret_cast<Surface *>(nativeObject));
-    sp<IBinder> binder(parcel->readStrongBinder());
 
     // update the Surface only if the underlying IGraphicBufferProducer
     // has changed.
-    if (self != NULL
-            && (IInterface::asBinder(self->getIGraphicBufferProducer()) == binder)) {
+    if (self != nullptr
+            && (IInterface::asBinder(self->getIGraphicBufferProducer()) ==
+                    IInterface::asBinder(surfaceShim.graphicBufferProducer))) {
         // same IGraphicBufferProducer, return ourselves
         return jlong(self.get());
     }
 
     sp<Surface> sur;
-    sp<IGraphicBufferProducer> gbp(interface_cast<IGraphicBufferProducer>(binder));
-    if (gbp != NULL) {
+    if (surfaceShim.graphicBufferProducer != nullptr) {
         // we have a new IGraphicBufferProducer, create a new Surface for it
-        sur = new Surface(gbp, true);
+        sur = new Surface(surfaceShim.graphicBufferProducer, true);
         // and keep a reference before passing to java
         sur->incStrong(&sRefBaseOwner);
     }
@@ -447,7 +452,13 @@
         return;
     }
     sp<Surface> self(reinterpret_cast<Surface *>(nativeObject));
-    parcel->writeStrongBinder( self != 0 ? IInterface::asBinder(self->getIGraphicBufferProducer()) : NULL);
+    android::view::Surface surfaceShim;
+    if (self != nullptr) {
+        surfaceShim.graphicBufferProducer = self->getIGraphicBufferProducer();
+    }
+    // Calling code in Surface.java has already written the name of the Surface
+    // to the Parcel
+    surfaceShim.writeToParcel(parcel, /*nameAlreadyWritten*/true);
 }
 
 static jint nativeGetWidth(JNIEnv* env, jclass clazz, jlong nativeObject) {
diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp
index 1dfe40a..c838d03 100644
--- a/core/jni/android_view_SurfaceControl.cpp
+++ b/core/jni/android_view_SurfaceControl.cpp
@@ -110,6 +110,13 @@
     ctrl->decStrong((void *)nativeCreate);
 }
 
+static void nativeDisconnect(JNIEnv* env, jclass clazz, jlong nativeObject) {
+    SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl *>(nativeObject);
+    if (ctrl != NULL) {
+        ctrl->disconnect();
+    }
+}
+
 static jobject nativeScreenshotBitmap(JNIEnv* env, jclass clazz,
         jobject displayTokenObj, jobject sourceCropObj, jint width, jint height,
         jint minLayer, jint maxLayer, bool allLayers, bool useIdentityTransform,
@@ -595,6 +602,8 @@
             (void*)nativeRelease },
     {"nativeDestroy", "(J)V",
             (void*)nativeDestroy },
+    {"nativeDisconnect", "(J)V",
+            (void*)nativeDisconnect },
     {"nativeScreenshot", "(Landroid/os/IBinder;Landroid/graphics/Rect;IIIIZZI)Landroid/graphics/Bitmap;",
             (void*)nativeScreenshotBitmap },
     {"nativeScreenshot", "(Landroid/os/IBinder;Landroid/view/Surface;Landroid/graphics/Rect;IIIIZZ)V",
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 30d6f29..fbc96c2 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -87,6 +87,7 @@
     <protected-broadcast android:name="android.os.action.DEVICE_IDLE_MODE_CHANGED" />
     <protected-broadcast android:name="android.os.action.POWER_SAVE_WHITELIST_CHANGED" />
     <protected-broadcast android:name="android.os.action.POWER_SAVE_TEMP_WHITELIST_CHANGED" />
+    <protected-broadcast android:name="android.os.action.POWER_SAVE_MODE_CHANGED_INTERNAL" />
 
     <protected-broadcast android:name="android.os.action.SCREEN_BRIGHTNESS_BOOST_CHANGED" />
 
@@ -167,7 +168,7 @@
         android:name="android.bluetooth.a2dp-sink.profile.action.PLAYING_STATE_CHANGED" />
     <protected-broadcast
         android:name="android.bluetooth.a2dp-sink.profile.action.AUDIO_CONFIG_CHANGED" />
-   <protected-broadcast
+    <protected-broadcast
         android:name="android.bluetooth.avrcp-controller.profile.action.CONNECTION_STATE_CHANGED" />
     <protected-broadcast
         android:name="android.bluetooth.input.profile.action.CONNECTION_STATE_CHANGED" />
@@ -265,6 +266,7 @@
     <protected-broadcast android:name="com.android.server.WifiManager.action.START_SCAN" />
     <protected-broadcast android:name="com.android.server.WifiManager.action.START_PNO" />
     <protected-broadcast android:name="com.android.server.WifiManager.action.DELAYED_DRIVER_STOP" />
+    <protected-broadcast android:name="com.android.server.WifiManager.action.DEVICE_IDLE" />
     <protected-broadcast android:name="com.android.server.action.REMOTE_BUGREPORT_SHARING_ACCEPTED" />
     <protected-broadcast android:name="com.android.server.action.REMOTE_BUGREPORT_SHARING_DECLINED" />
     <protected-broadcast android:name="android.net.wifi.WIFI_STATE_CHANGED" />
@@ -374,7 +376,10 @@
     <protected-broadcast android:name="android.app.action.ACTION_PASSWORD_FAILED" />
     <protected-broadcast android:name="android.app.action.ACTION_PASSWORD_SUCCEEDED" />
     <protected-broadcast android:name="com.android.server.ACTION_EXPIRED_PASSWORD_NOTIFICATION" />
+
     <protected-broadcast android:name="android.intent.action.MANAGED_PROFILE_ADDED" />
+    <protected-broadcast android:name="android.intent.action.MANAGED_PROFILE_UNLOCKED" />
+    <protected-broadcast android:name="android.intent.action.MANAGED_PROFILE_REMOVED" />
 
     <protected-broadcast android:name="android.bluetooth.adapter.action.BLE_STATE_CHANGED" />
     <protected-broadcast android:name="android.content.jobscheduler.JOB_DELAY_EXPIRED" />
@@ -432,7 +437,6 @@
     <protected-broadcast android:name="android.intent.action.DYNAMIC_SENSOR_CHANGED" />
 
     <protected-broadcast android:name="android.intent.action.ACTION_RADIO_OFF" />
-    <protected-broadcast android:name="android.intent.action.MANAGED_PROFILE_UNLOCKED" />
 
     <protected-broadcast android:name="android.accounts.LOGIN_ACCOUNTS_CHANGED" />
     <protected-broadcast android:name="com.android.sync.SYNC_CONN_STATUS_CHANGED" />
@@ -450,6 +454,10 @@
 
     <protected-broadcast android:name="android.intent.action.TWILIGHT_CHANGED" />
 
+    <protected-broadcast android:name="com.android.server.fingerprint.ACTION_LOCKOUT_RESET" />
+    <protected-broadcast android:name="android.net.wifi.PASSPOINT_ICON_RECEIVED" />
+    <protected-broadcast android:name="com.android.server.notification.CountdownConditionProvider" />
+
     <!-- ====================================================================== -->
     <!--                          RUNTIME PERMISSIONS                           -->
     <!-- ====================================================================== -->
@@ -965,16 +973,6 @@
     <!-- INSTALL PERMISSIONS                                                    -->
     <!-- ====================================================================== -->
 
-`   <!-- =========================================== -->
-    <!-- Permissions for accessing contact metadata -->
-    <!-- =========================================== -->
-    <eat-comment />
-
-    <!-- @SystemApi Allows an application to read/write contact metadata.
-         <p>Not for use by third-party applications. -->
-    <permission android:name="android.permission.READ_WRITE_CONTACT_METADATA"
-        android:protectionLevel="signature|system" />
-
     <!-- ================================== -->
     <!-- Permissions for accessing messages -->
     <!-- ================================== -->
@@ -986,6 +984,11 @@
     <permission android:name="android.permission.SEND_RESPOND_VIA_MESSAGE"
         android:protectionLevel="signature|privileged" />
 
+    <!-- @SystemApi Allows an application to send SMS to premium shortcodes without user permission.
+         <p>Not for use by third-party applications. -->
+    <permission android:name="android.permission.SEND_SMS_NO_CONFIRMATION"
+        android:protectionLevel="signature|privileged" />
+
     <!-- Allows an application to filter carrier specific sms.
          @hide -->
     <permission android:name="android.permission.CARRIER_FILTER_SMS"
@@ -1608,6 +1611,11 @@
     <permission android:name="android.permission.GET_PACKAGE_IMPORTANCE"
         android:protectionLevel="signature|privileged" />
 
+    <!-- Allows use of PendingIntent.getIntent().
+         @hide -->
+    <permission android:name="android.permission.GET_INTENT_SENDER_INTENT"
+        android:protectionLevel="signature" />
+
     <!-- ================================== -->
     <!-- Permissions affecting the display of other applications  -->
     <!-- ================================== -->
@@ -2766,12 +2774,11 @@
         android:protectionLevel="signature" />
 
     <!-- Must be required by an {@link
-         android.service.notification.NotificationAssistantService},
-         to ensure that only the system can bind to it.
+         android.service.notification.NotificationRankerService         to ensure that only the system can bind to it.
          <p>Protection level: signature
          @hide This is not a third-party API (intended for system apps). -->
     -->
-    <permission android:name="android.permission.BIND_NOTIFICATION_ASSISTANT_SERVICE"
+    <permission android:name="android.permission.BIND_NOTIFICATION_RANKER_SERVICE"
         android:protectionLevel="signature" />
 
     <!-- Must be required by a {@link
@@ -2926,6 +2933,12 @@
     <permission android:name="android.permission.WRITE_BLOCKED_NUMBERS"
                 android:protectionLevel="signature" />
 
+    <!-- Must be required by an {@link android.service.vr.VrListenerService}, to ensure that only
+         the system can bind to it.
+         <p>Protection level: signature -->
+    <permission android:name="android.permission.BIND_VR_LISTENER_SERVICE"
+        android:protectionLevel="signature" />
+
     <application android:process="system"
                  android:persistent="true"
                  android:hasCode="false"
diff --git a/core/res/assets/images/clock64.png b/core/res/assets/images/clock64.png
new file mode 100644
index 0000000..493a1ea
--- /dev/null
+++ b/core/res/assets/images/clock64.png
Binary files differ
diff --git a/core/res/res/drawable-nodpi/default_wallpaper.jpg b/core/res/res/drawable-nodpi/default_wallpaper.jpg
deleted file mode 100644
index d7475b4c..0000000
--- a/core/res/res/drawable-nodpi/default_wallpaper.jpg
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-nodpi/default_wallpaper.png b/core/res/res/drawable-nodpi/default_wallpaper.png
new file mode 100644
index 0000000..e9c4d5c
--- /dev/null
+++ b/core/res/res/drawable-nodpi/default_wallpaper.png
Binary files differ
diff --git a/core/res/res/drawable-sw600dp-nodpi/default_wallpaper.jpg b/core/res/res/drawable-sw600dp-nodpi/default_wallpaper.jpg
deleted file mode 100644
index 03a14c0..0000000
--- a/core/res/res/drawable-sw600dp-nodpi/default_wallpaper.jpg
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-sw600dp-nodpi/default_wallpaper.png b/core/res/res/drawable-sw600dp-nodpi/default_wallpaper.png
new file mode 100644
index 0000000..9f3efa5
--- /dev/null
+++ b/core/res/res/drawable-sw600dp-nodpi/default_wallpaper.png
Binary files differ
diff --git a/core/res/res/drawable-sw720dp-nodpi/default_wallpaper.jpg b/core/res/res/drawable-sw720dp-nodpi/default_wallpaper.jpg
deleted file mode 100644
index 543d118..0000000
--- a/core/res/res/drawable-sw720dp-nodpi/default_wallpaper.jpg
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-sw720dp-nodpi/default_wallpaper.png b/core/res/res/drawable-sw720dp-nodpi/default_wallpaper.png
new file mode 100644
index 0000000..8199e70
--- /dev/null
+++ b/core/res/res/drawable-sw720dp-nodpi/default_wallpaper.png
Binary files differ
diff --git a/core/res/res/drawable/work_widget_mask_view_background.xml b/core/res/res/drawable/work_widget_mask_view_background.xml
deleted file mode 100644
index 17f0dbc..0000000
--- a/core/res/res/drawable/work_widget_mask_view_background.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-Copyright (C) 2015 The Android Open Source Project
-
-   Licensed under the Apache License, Version 2.0 (the "License");
-    you may not use this file except in compliance with the License.
-    You may obtain a copy of the License at
-
-         http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
--->
- <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
-   <padding android:left="5dp" android:right="5dp" android:top="5dp" android:bottom="5dp"/>
-   <stroke android:width="1dp" android:color="#CCCCCC" />
- </shape>
diff --git a/core/res/res/layout/notification_template_header.xml b/core/res/res/layout/notification_template_header.xml
index 6669bae..0bbaa24 100644
--- a/core/res/res/layout/notification_template_header.xml
+++ b/core/res/res/layout/notification_template_header.xml
@@ -20,9 +20,9 @@
     android:id="@+id/notification_header"
     android:orientation="horizontal"
     android:layout_width="wrap_content"
-    android:layout_height="48dp"
+    android:layout_height="53dp"
     android:clipChildren="false"
-    android:paddingTop="5dp"
+    android:paddingTop="10dp"
     android:paddingBottom="16dp"
     android:paddingStart="@dimen/notification_content_margin_start"
     android:paddingEnd="16dp">
@@ -33,16 +33,6 @@
         android:layout_marginEnd="3dp"
         />
     <TextView
-        android:id="@+id/number_of_children"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:textAppearance="@style/TextAppearance.Material.Notification"
-        android:layout_marginEnd="3dp"
-        android:layout_marginStart="2dp"
-        android:visibility="gone"
-        android:singleLine="true"
-        />
-    <TextView
         android:id="@+id/app_name_text"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
diff --git a/core/res/res/layout/notification_template_material_base.xml b/core/res/res/layout/notification_template_material_base.xml
index a37bfa9..ccd26fb 100644
--- a/core/res/res/layout/notification_template_material_base.xml
+++ b/core/res/res/layout/notification_template_material_base.xml
@@ -41,7 +41,7 @@
         android:layout_height="wrap_content"
         android:layout_gravity="bottom"
         android:layout_marginStart="@dimen/notification_content_margin_start"
-        android:layout_marginBottom="11dp"
+        android:layout_marginBottom="15dp"
         android:layout_marginEnd="@dimen/notification_content_margin_end" >
         <include layout="@layout/notification_template_progress" />
     </FrameLayout>
diff --git a/core/res/res/layout/notification_template_material_big_base.xml b/core/res/res/layout/notification_template_material_big_base.xml
index f302087..d53fb5f 100644
--- a/core/res/res/layout/notification_template_material_big_base.xml
+++ b/core/res/res/layout/notification_template_material_big_base.xml
@@ -49,7 +49,7 @@
             android:layout_height="wrap_content"
             android:layout_gravity="bottom"
             android:layout_marginStart="@dimen/notification_content_margin_start"
-            android:layout_marginBottom="11dp"
+            android:layout_marginBottom="15dp"
             android:layout_marginEnd="@dimen/notification_content_margin_end">
             <include layout="@layout/notification_template_progress" />
         </FrameLayout>
diff --git a/core/res/res/layout/notification_template_material_big_media.xml b/core/res/res/layout/notification_template_material_big_media.xml
index a5ed187..04ea12d 100644
--- a/core/res/res/layout/notification_template_material_big_media.xml
+++ b/core/res/res/layout/notification_template_material_big_media.xml
@@ -25,7 +25,7 @@
     >
     <include layout="@layout/notification_template_header"
         android:layout_width="match_parent"
-        android:layout_height="48dp"
+        android:layout_height="53dp"
         android:layout_gravity="start"/>
     <LinearLayout
         android:layout_width="match_parent"
@@ -50,9 +50,10 @@
             android:id="@+id/media_actions"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
-            android:layout_marginTop="-15dp"
+            android:layout_marginTop="-21dp"
             android:paddingStart="8dp"
-            android:paddingBottom="8dp"
+            android:paddingBottom="12dp"
+            android:gravity="top"
             android:orientation="horizontal"
             android:layoutDirection="ltr"
             >
@@ -65,7 +66,7 @@
         android:layout_height="@dimen/media_notification_expanded_image_max_size"
         android:minWidth="40dp"
         android:layout_marginEnd="16dp"
-        android:layout_marginBottom="16dp"
+        android:layout_marginBottom="20dp"
         android:layout_gravity="bottom|end"
         android:scaleType="centerCrop"
         />
diff --git a/core/res/res/layout/notification_template_material_big_text.xml b/core/res/res/layout/notification_template_material_big_text.xml
index 9a4b28c..fdfefe1 100644
--- a/core/res/res/layout/notification_template_material_big_text.xml
+++ b/core/res/res/layout/notification_template_material_big_text.xml
@@ -39,7 +39,7 @@
         <com.android.internal.widget.ImageFloatingTextView android:id="@+id/big_text"
             android:layout_width="match_parent"
             android:layout_height="0dp"
-            android:layout_marginTop="1.5dp"
+            android:layout_marginTop="0.5dp"
             android:paddingBottom="@dimen/notification_content_margin_bottom"
             android:textAppearance="@style/TextAppearance.Material.Notification"
             android:singleLine="false"
diff --git a/core/res/res/layout/notification_template_material_media.xml b/core/res/res/layout/notification_template_material_media.xml
index cda0636..809e525 100644
--- a/core/res/res/layout/notification_template_material_media.xml
+++ b/core/res/res/layout/notification_template_material_media.xml
@@ -24,7 +24,7 @@
     >
     <include layout="@layout/notification_template_header"
         android:layout_width="fill_parent"
-        android:layout_height="48dp" />
+        android:layout_height="53dp" />
     <LinearLayout
         android:id="@+id/notification_main_column"
         android:layout_width="match_parent"
@@ -54,7 +54,7 @@
             android:layout_height="match_parent"
             android:layout_gravity="bottom|end"
             android:layout_marginStart="10dp"
-            android:layout_marginBottom="8dp"
+            android:layout_marginBottom="12dp"
             android:layoutDirection="ltr"
             android:orientation="horizontal"
             >
diff --git a/core/res/res/layout/notification_template_right_icon.xml b/core/res/res/layout/notification_template_right_icon.xml
index 3b358ab..15ccc67 100644
--- a/core/res/res/layout/notification_template_right_icon.xml
+++ b/core/res/res/layout/notification_template_right_icon.xml
@@ -19,7 +19,7 @@
     android:layout_width="40dp"
     android:layout_height="40dp"
     android:layout_marginEnd="16dp"
-    android:layout_marginTop="32dp"
+    android:layout_marginTop="36dp"
     android:layout_gravity="top|end"
     android:scaleType="centerCrop"
     />
diff --git a/core/res/res/layout/notification_template_text.xml b/core/res/res/layout/notification_template_text.xml
index 38470cd..a318bda 100644
--- a/core/res/res/layout/notification_template_text.xml
+++ b/core/res/res/layout/notification_template_text.xml
@@ -14,12 +14,12 @@
   ~ See the License for the specific language governing permissions and
   ~ limitations under the License
   -->
-<TextView xmlns:android="http://schemas.android.com/apk/res/android"
+<com.android.internal.widget.ImageFloatingTextView xmlns:android="http://schemas.android.com/apk/res/android"
     android:id="@+id/text"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
     android:layout_gravity="top"
-    android:layout_marginTop="1.5dp"
+    android:layout_marginTop="0.5dp"
     android:ellipsize="marquee"
     android:fadingEdge="horizontal"
     android:gravity="top"
diff --git a/core/res/res/layout/text_edit_suggestion_container_material.xml b/core/res/res/layout/text_edit_suggestion_container_material.xml
index 15b18dd..d1c65c0 100644
--- a/core/res/res/layout/text_edit_suggestion_container_material.xml
+++ b/core/res/res/layout/text_edit_suggestion_container_material.xml
@@ -33,7 +33,7 @@
             android:id="@+id/suggestionContainer"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
-            android:paddingTop="8dp"
+            android:paddingTop="4dp"
             android:paddingBottom="0dp"
             android:divider="@null" />
         <LinearLayout
diff --git a/core/res/res/layout/work_widget_mask_view.xml b/core/res/res/layout/work_widget_mask_view.xml
index ce86ddc..3c47705 100644
--- a/core/res/res/layout/work_widget_mask_view.xml
+++ b/core/res/res/layout/work_widget_mask_view.xml
@@ -15,20 +15,24 @@
     limitations under the License.
 -->
 <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/work_widget_mask_frame"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
-    android:background="#F3374248" >
+    android:background="#F3374248"
+    android:clickable="true" >
 
     <ImageView android:id="@+id/work_widget_app_icon"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
-        android:layout_gravity="center"/>
+        android:layout_gravity="center"
+        android:clickable="false" />
 
-    <ImageView
+    <ImageView android:id="@+id/work_widget_badge_icon"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:layout_gravity="bottom|right"
         android:layout_marginBottom="4dp"
         android:layout_marginRight="4dp"
-        android:src="@drawable/ic_corp_badge_off" />
+        android:src="@drawable/ic_corp_badge_off"
+        android:clickable="false" />
 </FrameLayout>
diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml
index fd4fff4..de4ccae 100644
--- a/core/res/res/values-af/strings.xml
+++ b/core/res/res/values-af/strings.xml
@@ -229,7 +229,6 @@
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Stembystand"</string>
     <string name="global_action_lockdown" msgid="8751542514724332873">"Sluit nou"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
-    <string name="notification_children_count_bracketed" msgid="1769425473168347839">"(<xliff:g id="NOTIFICATIONCOUNT">%d</xliff:g>)"</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>
     <string name="safeMode" msgid="2788228061547930246">"Veiligmodus"</string>
@@ -1052,13 +1051,12 @@
     <string name="usb_notification_message" msgid="7347368030849048437">"Raak vir meer opsies."</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"USB-ontfouter gekoppel"</string>
     <string name="adb_active_notification_message" msgid="1016654627626476142">"Raak om USB-ontfouting te deaktiveer."</string>
+    <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Neem tans foutverslag …"</string>
     <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Deel foutverslag?"</string>
     <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Deel tans foutverslag …"</string>
-    <string name="share_remote_bugreport_notification_message" msgid="752583906074230920">"Jou IT-administrateur het \'n foutverslag versoek om met die foutsporing van hierdie toestel te help. Programme en data sal dalk gedeel word en jou toestel sal dalk tydelik stadiger wees."</string>
-    <string name="share_finished_remote_bugreport_notification_message" msgid="4627312060769912353">"Jou IT-administrateur het \'n foutverslag versoek om met die foutsporing van hierdie toestel te help. Programme en data sal dalk gedeel word."</string>
-    <string name="sharing_remote_bugreport_notification_message" msgid="673106383408474893">"Dit sal jou toestel dalk tydelik stadiger maak"</string>
-    <string name="share_remote_bugreport_notification_accept" msgid="8203856129078669677">"AANVAAR"</string>
-    <string name="share_remote_bugreport_notification_decline" msgid="6337969352057443969">"WEIER"</string>
+    <string name="share_remote_bugreport_notification_message_finished" msgid="8610614010660772643">"Jou IT-administrateur het \'n foutverslag versoek om met die foutsporing van hierdie toestel te help. Programme en data sal dalk gedeel word."</string>
+    <string name="share_remote_bugreport_action" msgid="6249476773913384948">"DEEL"</string>
+    <string name="decline_remote_bugreport_action" msgid="6230987241608770062">"WEIER"</string>
     <string name="select_input_method" msgid="8547250819326693584">"Verander sleutelbord"</string>
     <string name="configure_input_methods" msgid="4769971288371946846">"Kies sleutelborde"</string>
     <string name="show_ime" msgid="2506087537466597099">"Hou dit op die skerm terwyl fisieke sleutelbord aktief is"</string>
@@ -1137,8 +1135,9 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Muurpapier"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Verander muurpapier"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Kennisgewingluisteraar"</string>
+    <string name="vr_listener_binding_label" msgid="4316591939343607306">"VR-luisteraar"</string>
     <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Toestandverskaffer"</string>
-    <string name="notification_assistant_binding_label" msgid="909456055569102952">"Kennisgewingassistent"</string>
+    <string name="notification_ranker_binding_label" msgid="774540592299064747">"Kennisgewingklassifiseringsdiens"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN geaktiveer"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN is geaktiveer deur <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Raak om die netwerk te bestuur."</string>
@@ -1467,7 +1466,7 @@
     <string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Vra PIN voordat jy ontspeld"</string>
     <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Vra ontsluitpatroon voordat jy ontspeld"</string>
     <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Vra wagwoord voordat jy ontspeld"</string>
-    <string name="dock_cropped_windows_text" msgid="6378424064779004428">"Program se grootte kan nie verander word nie; rollees dit met twee vingers."</string>
+    <string name="dock_forced_resizable" msgid="5914261505436217520">"Program sal dalk nie met verdeelde skerm werk nie."</string>
     <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"Program steun nie verdeelde skerm nie."</string>
     <string name="package_installed_device_owner" msgid="8420696545959087545">"Deur jou administrateur geïnstalleer"</string>
     <string name="package_updated_device_owner" msgid="8856631322440187071">"Opgedateer deur jou administrateur"</string>
@@ -1541,7 +1540,7 @@
     <string name="importance_from_person" msgid="9160133597262938296">"Dit is belangrik as gevolg van die mense wat betrokke is."</string>
     <string name="user_creation_account_exists" msgid="1942606193570143289">"Laat <xliff:g id="APP">%1$s</xliff:g> toe om \'n nuwe gebruiker met <xliff:g id="ACCOUNT">%2$s</xliff:g> te skep?"</string>
     <string name="user_creation_adding" msgid="4482658054622099197">"Laat <xliff:g id="APP">%1$s</xliff:g> toe om \'n nuwe gebruiker met <xliff:g id="ACCOUNT">%2$s</xliff:g> te skep (\'n gebruiker met hierdie rekening bestaan reeds)?"</string>
-    <string name="language_selection_title" msgid="7181332986330337171">"Taalvoorkeur"</string>
+    <string name="language_selection_title" msgid="2680677278159281088">"Voeg \'n taal by"</string>
     <string name="country_selection_title" msgid="2954859441620215513">"Streekvoorkeur"</string>
     <string name="search_language_hint" msgid="7042102592055108574">"Voer taalnaam in"</string>
     <string name="language_picker_section_suggested" msgid="8414489646861640885">"Voorgestel"</string>
@@ -1565,4 +1564,6 @@
     <string name="unpin_target" msgid="3556545602439143442">"Ontspeld"</string>
     <string name="app_info" msgid="6856026610594615344">"Programinligting"</string>
     <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="audit_safemode_notification" msgid="6351827251856877200">"Voer \'n fabriekterugstelling uit om hierdie toestel normaal te gebruik"</string>
+    <string name="audit_safemode_notification_details" msgid="1860601176690176413">"Raak om meer te wete te kom."</string>
 </resources>
diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml
index d9f9610..88e9367 100644
--- a/core/res/res/values-am/strings.xml
+++ b/core/res/res/values-am/strings.xml
@@ -229,7 +229,6 @@
     <string name="global_action_voice_assist" msgid="7751191495200504480">"የድምጽ እርዳታ"</string>
     <string name="global_action_lockdown" msgid="8751542514724332873">"አሁን ቆልፍ"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
-    <string name="notification_children_count_bracketed" msgid="1769425473168347839">"(<xliff:g id="NOTIFICATIONCOUNT">%d</xliff:g>)"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"ይዘቶች ተደብቀዋል"</string>
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"ይዘቶች በመመሪያ ተደብቀዋል"</string>
     <string name="safeMode" msgid="2788228061547930246">"የሚያስተማምን ሁነታ"</string>
@@ -1052,13 +1051,12 @@
     <string name="usb_notification_message" msgid="7347368030849048437">"ለተጨማሪ አማራጮች ነካ ያድርጉ።"</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"USB አድስ ተያይዟል"</string>
     <string name="adb_active_notification_message" msgid="1016654627626476142">"USB ማረሚያ ላለማንቃት ዳስስ።"</string>
+    <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"የሳንካ ሪፖርትን በመውሰድ ላይ…"</string>
     <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"የሳንካ ሪፖርት ይጋራ?"</string>
     <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"የሳንካ ሪፖርትን በማጋራት ላይ…"</string>
-    <string name="share_remote_bugreport_notification_message" msgid="752583906074230920">"የእርስዎ አይቲ አስተዳዳሪ ለዚህ መሣሪያ መላ ለመፈለግ እንዲያግዝ የሳንካ ሪፖርት ጠይቀዋል። መተግበሪያዎች እና ውሂብ ሊጋሩ ይችላሉ። ይሄ መሣሪያዎን ለጊዜው ሊያዘገየው ይችላል።"</string>
-    <string name="share_finished_remote_bugreport_notification_message" msgid="4627312060769912353">"የእርስዎ አይቲ አስተዳዳሪ ለዚህ መሣሪያ መላ ለመፈለግ የሳንካ ሪፖርት ጠይቀዋል። መተግበሪያዎች እና ውሂብ ሊጋሩ ይችላሉ።"</string>
-    <string name="sharing_remote_bugreport_notification_message" msgid="673106383408474893">"ይሄ መሣሪያዎን ለጊዜው ሊያዘገየው ይችላል"</string>
-    <string name="share_remote_bugreport_notification_accept" msgid="8203856129078669677">"ተቀበል"</string>
-    <string name="share_remote_bugreport_notification_decline" msgid="6337969352057443969">"ውድቅ አድርግ"</string>
+    <string name="share_remote_bugreport_notification_message_finished" msgid="8610614010660772643">"የእርስዎ አይቲ አስተዳዳሪ ለዚህ መሣሪያ መላ ለመፈለግ የሳንካ ሪፖርት ጠይቀዋል። መተግበሪያዎች እና ውሂብ ሊጋሩ ይችላሉ።"</string>
+    <string name="share_remote_bugreport_action" msgid="6249476773913384948">"አጋራ"</string>
+    <string name="decline_remote_bugreport_action" msgid="6230987241608770062">"አትቀበል"</string>
     <string name="select_input_method" msgid="8547250819326693584">"ቁልፍ ሰሌዳ ይቀይሩ"</string>
     <string name="configure_input_methods" msgid="4769971288371946846">"ቁልፍ ሰሌዳዎችን ምረጥ"</string>
     <string name="show_ime" msgid="2506087537466597099">"አካላዊ የቁልፍ ሰሌዳ ገቢር ሆኖ ሳለ በማያ ገጽ ላይ አቆየው"</string>
@@ -1137,8 +1135,9 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"ልጣፍ"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"ልጣፍ ለውጥ"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"ማሳወቂያ አዳማጭ"</string>
+    <string name="vr_listener_binding_label" msgid="4316591939343607306">"የምናባዊ እውነታ አዳማጭ"</string>
     <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"የሁኔታ አቅራቢ"</string>
-    <string name="notification_assistant_binding_label" msgid="909456055569102952">"የማሳወቂያ ረዳት"</string>
+    <string name="notification_ranker_binding_label" msgid="774540592299064747">"የማሳወቂያ ደረጃ ሰጪ አገልግሎት"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN ነቅቷል።"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN በ<xliff:g id="APP">%s</xliff:g>ገብሯል"</string>
     <string name="vpn_text" msgid="3011306607126450322">"አውታረመረብ ለማደራጀት  ንካ።"</string>
@@ -1467,7 +1466,7 @@
     <string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"ከመንቀል በፊት ፒን ጠይቅ"</string>
     <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"ከመንቀል በፊት የማስከፈቻ ስርዓተ-ጥለት ጠይቅ"</string>
     <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"ከመንቀል በፊት የይለፍ ቃል ጠይቅ"</string>
-    <string name="dock_cropped_windows_text" msgid="6378424064779004428">"የመተግበሪያው መጠን ሊቀየር የሚችል አይደለም፣ በሁለት ጣቶች ያሸብልሉት።"</string>
+    <string name="dock_forced_resizable" msgid="5914261505436217520">"መተግበሪያ ከተከፈለ ማያ ገጽ ጋር ላይሠራ ይችላል"</string>
     <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"መተግበሪያው የተከፈለ ማያ ገጽን አይደግፍም።"</string>
     <string name="package_installed_device_owner" msgid="8420696545959087545">"በእርስዎ አስተዳዳሪ ተጭኗል"</string>
     <string name="package_updated_device_owner" msgid="8856631322440187071">"በአስተዳዳሪዎ ተዘምኗል"</string>
@@ -1541,7 +1540,7 @@
     <string name="importance_from_person" msgid="9160133597262938296">"ይሄ በሚሳተፉ ሰዎች ምክንያት አስፈላጊ ነው።"</string>
     <string name="user_creation_account_exists" msgid="1942606193570143289">"<xliff:g id="APP">%1$s</xliff:g> በ<xliff:g id="ACCOUNT">%2$s</xliff:g> አዲስ ተጠቃሚ እንዲፈጥር ይፈቀድለት?"</string>
     <string name="user_creation_adding" msgid="4482658054622099197">"<xliff:g id="APP">%1$s</xliff:g> በ<xliff:g id="ACCOUNT">%2$s</xliff:g> አዲስ ተጠቃሚ እንዲፈጥር ይፈቀድለት (ይህ መለያ ያለው ተጠቃሚ አስቀድሞ አለ)?"</string>
-    <string name="language_selection_title" msgid="7181332986330337171">"የቋንቋ ምርጫ"</string>
+    <string name="language_selection_title" msgid="2680677278159281088">"ቋንቋ ያክሉ"</string>
     <string name="country_selection_title" msgid="2954859441620215513">"የክልል ምርጫ"</string>
     <string name="search_language_hint" msgid="7042102592055108574">"የቋንቋ ስም ይተይቡ"</string>
     <string name="language_picker_section_suggested" msgid="8414489646861640885">"የተጠቆሙ"</string>
@@ -1565,4 +1564,6 @@
     <string name="unpin_target" msgid="3556545602439143442">"ንቀል"</string>
     <string name="app_info" msgid="6856026610594615344">"የመተግበሪያ መረጃ"</string>
     <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="audit_safemode_notification" msgid="6351827251856877200">"ይህን መሣሪያ በመደበኛነት ለመጠቀም የፋብሪካ ዳግም ያስጀምሩ"</string>
+    <string name="audit_safemode_notification_details" msgid="1860601176690176413">"የበለጠ ለመረዳት ይንኩ።"</string>
 </resources>
diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml
index 056f1ae..84bc768 100644
--- a/core/res/res/values-ar/strings.xml
+++ b/core/res/res/values-ar/strings.xml
@@ -237,7 +237,6 @@
     <string name="global_action_voice_assist" msgid="7751191495200504480">"المساعد الصوتي"</string>
     <string name="global_action_lockdown" msgid="8751542514724332873">"قفل الآن"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
-    <string name="notification_children_count_bracketed" msgid="1769425473168347839">"(<xliff:g id="NOTIFICATIONCOUNT">%d</xliff:g>)"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"المحتويات مخفية"</string>
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"تم إخفاء المحتويات بواسطة السياسة"</string>
     <string name="safeMode" msgid="2788228061547930246">"الوضع الآمن"</string>
@@ -1084,13 +1083,12 @@
     <string name="usb_notification_message" msgid="7347368030849048437">"المس للحصول على مزيد من الخيارات."</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"‏تم توصيل تصحيح أخطاء USB"</string>
     <string name="adb_active_notification_message" msgid="1016654627626476142">"‏المس لتعطيل تصحيح أخطاء USB."</string>
+    <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"جارٍ الحصول على تقرير الخطأ…"</string>
     <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"هل تريد مشاركة تقرير الخطأ؟"</string>
     <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"جارٍ مشاركة تقرير الخطأ…"</string>
-    <string name="share_remote_bugreport_notification_message" msgid="752583906074230920">"طلب مشرف تكنولوجيا المعلومات الحصول على تقرير خطأ للمساعدة في تحرِّي مشكلة هذا الجهاز وإصلاحها. قد تتم مشاركة التطبيقات والبيانات. وقد يؤدي هذا إلى حدوث بطء مؤقت في جهازك."</string>
-    <string name="share_finished_remote_bugreport_notification_message" msgid="4627312060769912353">"طلب مشرف تكنولوجيا المعلومات الحصول على تقرير خطأ للمساعدة في تحرِّي مشكلة هذا الجهاز وإصلاحها. قد تتم مشاركة التطبيقات والبيانات."</string>
-    <string name="sharing_remote_bugreport_notification_message" msgid="673106383408474893">"قد يؤدي هذا إلى حدوث بطء مؤقت في جهازك"</string>
-    <string name="share_remote_bugreport_notification_accept" msgid="8203856129078669677">"قبول"</string>
-    <string name="share_remote_bugreport_notification_decline" msgid="6337969352057443969">"رفض"</string>
+    <string name="share_remote_bugreport_notification_message_finished" msgid="8610614010660772643">"طلب مشرف تكنولوجيا المعلومات الحصول على تقرير خطأ للمساعدة في تحرِّي مشكلة هذا الجهاز وإصلاحها؛ ويمكن أن تتم مشاركة التطبيقات والبيانات."</string>
+    <string name="share_remote_bugreport_action" msgid="6249476773913384948">"مشاركة"</string>
+    <string name="decline_remote_bugreport_action" msgid="6230987241608770062">"رفض"</string>
     <string name="select_input_method" msgid="8547250819326693584">"تغيير لوحة المفاتيح"</string>
     <string name="configure_input_methods" msgid="4769971288371946846">"اختيار لوحات المفاتيح"</string>
     <string name="show_ime" msgid="2506087537466597099">"استمرار عرضها على الشاشة أثناء نشاط لوحة المفاتيح الفعلية"</string>
@@ -1169,8 +1167,9 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"الخلفية"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"تغيير الخلفية"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"برنامج تلقّي الإشعارات الصوتية"</string>
+    <string name="vr_listener_binding_label" msgid="4316591939343607306">"مستمع واقع افتراضي"</string>
     <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"موفر الحالة"</string>
-    <string name="notification_assistant_binding_label" msgid="909456055569102952">"مساعد الإشعار"</string>
+    <string name="notification_ranker_binding_label" msgid="774540592299064747">"خدمة ترتيب أهمية الإشعارات"</string>
     <string name="vpn_title" msgid="19615213552042827">"‏تم تنشيط الشبكة الظاهرية الخاصة (VPN)"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"‏تم تنشيط VPN بواسطة <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"المس لإدارة الشبكة."</string>
@@ -1507,7 +1506,7 @@
     <string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"المطالبة برقم التعريف الشخصي قبل إزالة التثبيت"</string>
     <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"المطالبة بنقش إلغاء القفل قبل إزالة التثبيت"</string>
     <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"المطالبة بكلمة المرور قبل إزالة التثبيت"</string>
-    <string name="dock_cropped_windows_text" msgid="6378424064779004428">"التطبيق غير قابل لتغيير الحجم، يمكنك تمريره بإصبعين."</string>
+    <string name="dock_forced_resizable" msgid="5914261505436217520">"يمكن ألا يعمل التطبيق مع وضع تقسيم الشاشة."</string>
     <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"التطبيق لا يتيح تقسيم الشاشة."</string>
     <string name="package_installed_device_owner" msgid="8420696545959087545">"تم تثبيت الحزمة عن طريق المشرف"</string>
     <string name="package_updated_device_owner" msgid="8856631322440187071">"تم التحديث بواسطة المشرف"</string>
@@ -1617,7 +1616,7 @@
     <string name="importance_from_person" msgid="9160133597262938296">"هذه الرسالة مهمة نظرًا لأهمية الأشخاص المعنيين."</string>
     <string name="user_creation_account_exists" msgid="1942606193570143289">"هل تسمح لـ <xliff:g id="APP">%1$s</xliff:g> بإنشاء مستخدم جديد باستخدام <xliff:g id="ACCOUNT">%2$s</xliff:g>؟"</string>
     <string name="user_creation_adding" msgid="4482658054622099197">"هل تسمح لـ <xliff:g id="APP">%1$s</xliff:g> بإنشاء مستخدم جديد باستخدام <xliff:g id="ACCOUNT">%2$s</xliff:g> (يوجد مستخدم بهذا الحساب مسبقًا)؟"</string>
-    <string name="language_selection_title" msgid="7181332986330337171">"تفضيل اللغة"</string>
+    <string name="language_selection_title" msgid="2680677278159281088">"إضافة لغة"</string>
     <string name="country_selection_title" msgid="2954859441620215513">"تفضيل المنطقة"</string>
     <string name="search_language_hint" msgid="7042102592055108574">"اكتب اسم اللغة"</string>
     <string name="language_picker_section_suggested" msgid="8414489646861640885">"المقترحة"</string>
@@ -1641,4 +1640,6 @@
     <string name="unpin_target" msgid="3556545602439143442">"إزالة تثبيت"</string>
     <string name="app_info" msgid="6856026610594615344">"معلومات عن التطبيق"</string>
     <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="audit_safemode_notification" msgid="6351827251856877200">"يمكنك إعادة تعيين إعدادات المصنع لاستخدام هذا الجهاز بشكل عادي"</string>
+    <string name="audit_safemode_notification_details" msgid="1860601176690176413">"المس للتعرف على مزيد من المعلومات."</string>
 </resources>
diff --git a/core/res/res/values-az-rAZ/strings.xml b/core/res/res/values-az-rAZ/strings.xml
index a6bad85..3c4ce89 100644
--- a/core/res/res/values-az-rAZ/strings.xml
+++ b/core/res/res/values-az-rAZ/strings.xml
@@ -229,7 +229,6 @@
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Səs Yardımçısı"</string>
     <string name="global_action_lockdown" msgid="8751542514724332873">"İndi kilidləyin"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
-    <string name="notification_children_count_bracketed" msgid="1769425473168347839">"(<xliff:g id="NOTIFICATIONCOUNT">%d</xliff:g>)"</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>
     <string name="safeMode" msgid="2788228061547930246">"Təhlükəsiz rejim"</string>
@@ -1052,13 +1051,12 @@
     <string name="usb_notification_message" msgid="7347368030849048437">"Əlavə seçimlər üçün toxunun."</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"USB sazlama qoşuludur"</string>
     <string name="adb_active_notification_message" msgid="1016654627626476142">"USB debaqı deaktivasiya etmək üçün toxunun."</string>
+    <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Baq hesabat verilir..."</string>
     <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Baq hesabatı paylaşılsın?"</string>
     <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Baq hesabatı paylaşılır..."</string>
-    <string name="share_remote_bugreport_notification_message" msgid="752583906074230920">"IT admininiz bu cihazda nasazlıqların aşkarlanması üçün baq hesabatı sorğusu göndərdi. Tətbiqlər və data paylaşıla və cihazınız surəti müvəqqəti azala bilər."</string>
-    <string name="share_finished_remote_bugreport_notification_message" msgid="4627312060769912353">"IT admininiz bu cihazda nasazlıqların aşkarlanması üçün baq hesabatı sorğusu göndərdi. Tətbiqlər və data paylaşıla bilər."</string>
-    <string name="sharing_remote_bugreport_notification_message" msgid="673106383408474893">"Bu cihazınızın sürətini müvəqqəti olaraq azalda bilər"</string>
-    <string name="share_remote_bugreport_notification_accept" msgid="8203856129078669677">"QƏBUL EDİN"</string>
-    <string name="share_remote_bugreport_notification_decline" msgid="6337969352057443969">"RƏDD ET"</string>
+    <string name="share_remote_bugreport_notification_message_finished" msgid="8610614010660772643">"IT admininiz bu cihazda nasazlıqların aşkarlanması üçün baq hesabatı sorğusu göndərdi. Tətbiqlər və data paylaşıla bilər."</string>
+    <string name="share_remote_bugreport_action" msgid="6249476773913384948">"PAYLAŞIN"</string>
+    <string name="decline_remote_bugreport_action" msgid="6230987241608770062">"RƏDD ET"</string>
     <string name="select_input_method" msgid="8547250819326693584">"Klaviaturanı dəyişin"</string>
     <string name="configure_input_methods" msgid="4769971288371946846">"Klaviaturaları seçin"</string>
     <string name="show_ime" msgid="2506087537466597099">"Fiziki klaviatura aktiv olduğu halda ekranda saxlayın"</string>
@@ -1137,8 +1135,9 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Divar kağızı"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Divar kağızını dəyişin"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Bildiriş dinləyən"</string>
+    <string name="vr_listener_binding_label" msgid="4316591939343607306">"VR dinləyici"</string>
     <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Şərait provayderi"</string>
-    <string name="notification_assistant_binding_label" msgid="909456055569102952">"Bildiriş köməkçisi"</string>
+    <string name="notification_ranker_binding_label" msgid="774540592299064747">"Bildiriş qiymətləndirici xidmət"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN aktivləşdirildi"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN <xliff:g id="APP">%s</xliff:g> tərəfindən aktivləşdirilib"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Şəbəkəni idarə etmək üçün toxunun."</string>
@@ -1467,7 +1466,7 @@
     <string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Ayırmadan öncə PIN istənilsin"</string>
     <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Ayırmadan öncə kilid modeli istənilsin"</string>
     <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Ayırmadan öncə parol istənilsin"</string>
-    <string name="dock_cropped_windows_text" msgid="6378424064779004428">"Tətbiq ölçüləndirilmədi, iki barmağınızla sürüşdürün."</string>
+    <string name="dock_forced_resizable" msgid="5914261505436217520">"Tətbiq bölünmüş ekran ilə işləməyə bilər."</string>
     <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"Tətbiq ekran bölünməsini dəstəkləmir."</string>
     <string name="package_installed_device_owner" msgid="8420696545959087545">"Administratorunuz tərəfindən quraşdırılıb"</string>
     <string name="package_updated_device_owner" msgid="8856631322440187071">"Sizin administrator tərəfindən yeniləndi"</string>
@@ -1541,7 +1540,7 @@
     <string name="importance_from_person" msgid="9160133597262938296">"İnsanlar cəlb olunduğu üçün bu vacibdir."</string>
     <string name="user_creation_account_exists" msgid="1942606193570143289">"<xliff:g id="APP">%1$s</xliff:g> tətbiqinə <xliff:g id="ACCOUNT">%2$s</xliff:g> hesabı ilə yeni İstifadəçi yaratmağa icazə verilsin?"</string>
     <string name="user_creation_adding" msgid="4482658054622099197">"<xliff:g id="APP">%1$s</xliff:g> tətbiqinə<xliff:g id="ACCOUNT">%2$s</xliff:g> (bu hesab ilə İstifadəçi artıq mövcuddur) hesabı ilə yeni İstifadəçi yaratmağa icazə verilsin?"</string>
-    <string name="language_selection_title" msgid="7181332986330337171">"Dil seçimi"</string>
+    <string name="language_selection_title" msgid="2680677278159281088">"Dil əlavə edin"</string>
     <string name="country_selection_title" msgid="2954859441620215513">"Region seçimi"</string>
     <string name="search_language_hint" msgid="7042102592055108574">"Dil adını daxil edin"</string>
     <string name="language_picker_section_suggested" msgid="8414489646861640885">"Təklif edilmiş"</string>
@@ -1565,4 +1564,6 @@
     <string name="unpin_target" msgid="3556545602439143442">"Çıxarın"</string>
     <string name="app_info" msgid="6856026610594615344">"Tətbiq məlumatı"</string>
     <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="audit_safemode_notification" msgid="6351827251856877200">"Cihazı normal istifadə etmək üçün fabrik sıfırlaması"</string>
+    <string name="audit_safemode_notification_details" msgid="1860601176690176413">"Daha çox məlumat üçün toxunun."</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 144559a..5c73faf 100644
--- a/core/res/res/values-b+sr+Latn/strings.xml
+++ b/core/res/res/values-b+sr+Latn/strings.xml
@@ -163,7 +163,7 @@
     <string name="contentServiceTooManyDeletesNotificationDesc" msgid="8100981435080696431">"Previše <xliff:g id="CONTENT_TYPE">%s</xliff:g> izbrisanih stavki."</string>
     <string name="low_memory" product="tablet" msgid="6494019234102154896">"Memorija tableta je puna! Izbrišite neke datoteke da biste oslobodili prostor."</string>
     <string name="low_memory" product="watch" msgid="4415914910770005166">"Memorija sata je puna. Izbrišite neke datoteke da biste oslobodili prostor."</string>
-    <string name="low_memory" product="tv" msgid="516619861191025923">"Skladišni prostor na TV-u je popunjen. Izbrišite neke datoteke da biste oslobodili prostor."</string>
+    <string name="low_memory" product="tv" msgid="516619861191025923">"Memorijski prostor na TV-u je popunjen. Izbrišite neke datoteke da biste oslobodili prostor."</string>
     <string name="low_memory" product="default" msgid="3475999286680000541">"Skladište telefona je puno! Izbrišite neke datoteke kako biste oslobodili prostor."</string>
     <string name="ssl_ca_cert_warning" msgid="5848402127455021714">"Mreža se možda nadgleda"</string>
     <string name="ssl_ca_cert_noti_by_unknown" msgid="4475437862189850602">"Od strane nepoznate treće strane"</string>
@@ -231,7 +231,6 @@
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Glasovna pomoć"</string>
     <string name="global_action_lockdown" msgid="8751542514724332873">"Zaključaj odmah"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
-    <string name="notification_children_count_bracketed" msgid="1769425473168347839">"(<xliff:g id="NOTIFICATIONCOUNT">%d</xliff:g>)"</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>
     <string name="safeMode" msgid="2788228061547930246">"Bezbedni režim"</string>
@@ -312,7 +311,7 @@
     <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>
     <string name="permdesc_persistentActivity" product="default" msgid="4384760047508278272">"Dozvoljava aplikaciji da učini sopstvene komponente trajnim u memoriji. Ovo može da ograniči memoriju dostupnu drugim aplikacijama i uspori telefon."</string>
-    <string name="permlab_getPackageSize" msgid="7472921768357981986">"merenje prostora za skladištenje u aplikaciji"</string>
+    <string name="permlab_getPackageSize" msgid="7472921768357981986">"merenje memorijskog prostora u aplikaciji"</string>
     <string name="permdesc_getPackageSize" msgid="3921068154420738296">"Dozvoljava aplikaciji da preuzme veličine kôda, podataka i keša."</string>
     <string name="permlab_writeSettings" msgid="2226195290955224730">"izmena podešavanja sistema"</string>
     <string name="permdesc_writeSettings" msgid="7775723441558907181">"Dozvoljava aplikaciji da menja podatke o podešavanju sistema. Zlonamerne aplikacije mogu da oštete konfiguraciju sistema."</string>
@@ -885,9 +884,9 @@
     <string name="deleteText" msgid="6979668428458199034">"Izbriši"</string>
     <string name="inputMethod" msgid="1653630062304567879">"Metod unosa"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"Radnje u vezi sa tekstom"</string>
-    <string name="low_internal_storage_view_title" msgid="5576272496365684834">"Prostor za skladištenje je na izmaku"</string>
+    <string name="low_internal_storage_view_title" msgid="5576272496365684834">"Memorijski prostor je na izmaku"</string>
     <string name="low_internal_storage_view_text" msgid="6640505817617414371">"Neke sistemske funkcije možda ne funkcionišu"</string>
-    <string name="low_internal_storage_view_text_no_boot" msgid="6935190099204693424">"Nema dovoljno skladišnog prostora za sistem. Uverite se da imate 250 MB slobodnog prostora i ponovo pokrenite."</string>
+    <string name="low_internal_storage_view_text_no_boot" msgid="6935190099204693424">"Nema dovoljno memorijskog prostora za sistem. Uverite se da imate 250 MB slobodnog prostora i ponovo pokrenite."</string>
     <string name="app_running_notification_title" msgid="8718335121060787914">"Aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g> je pokrenuta"</string>
     <string name="app_running_notification_text" msgid="4653586947747330058">"Dodirnite za više informacija ili zaustavljanje aplikacije."</string>
     <string name="ok" msgid="5970060430562524910">"Potvrdi"</string>
@@ -1060,13 +1059,12 @@
     <string name="usb_notification_message" msgid="7347368030849048437">"Dodirnite za još opcija."</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"Otklanjanje grešaka sa USB-a je uspostavljeno"</string>
     <string name="adb_active_notification_message" msgid="1016654627626476142">"Dodirnite da biste onemogućili otklanjanje grešaka sa USB-a."</string>
+    <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Izveštaj o grešci se generiše…"</string>
     <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Želite li da podelite izveštaj o grešci?"</string>
     <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Deli se izveštaj o grešci…"</string>
-    <string name="share_remote_bugreport_notification_message" msgid="752583906074230920">"IT administrator je zatražio izveštaj o grešci radi lakšeg rešavanja problema u vezi sa ovim uređajem. Aplikacije i podaci mogu da se dele, a uređaj će se privremeno usporiti."</string>
-    <string name="share_finished_remote_bugreport_notification_message" msgid="4627312060769912353">"IT administrator je zatražio izveštaj o grešci radi lakšeg rešavanja problema u vezi sa ovim uređajem. Aplikacije i podaci mogu da se dele."</string>
-    <string name="sharing_remote_bugreport_notification_message" msgid="673106383408474893">"Ovo će privremeno usporiti uređaj"</string>
-    <string name="share_remote_bugreport_notification_accept" msgid="8203856129078669677">"PRIHVATI"</string>
-    <string name="share_remote_bugreport_notification_decline" msgid="6337969352057443969">"ODBIJ"</string>
+    <string name="share_remote_bugreport_notification_message_finished" msgid="8610614010660772643">"IT administrator je zatražio izveštaj o grešci radi lakšeg rešavanja problema u vezi sa ovim uređajem. Aplikacije i podaci mogu da se dele."</string>
+    <string name="share_remote_bugreport_action" msgid="6249476773913384948">"DELI"</string>
+    <string name="decline_remote_bugreport_action" msgid="6230987241608770062">"ODBIJ"</string>
     <string name="select_input_method" msgid="8547250819326693584">"Promenite tastaturu"</string>
     <string name="configure_input_methods" msgid="4769971288371946846">"Izaberite tastature"</string>
     <string name="show_ime" msgid="2506087537466597099">"Zadrži ga na ekranu dok je fizička tastatura aktivna"</string>
@@ -1145,8 +1143,9 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Pozadina"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Promena pozadine"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Monitor obaveštenja"</string>
+    <string name="vr_listener_binding_label" msgid="4316591939343607306">"Obrađivač za virtuelnu realnost"</string>
     <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Dobavljač uslova"</string>
-    <string name="notification_assistant_binding_label" msgid="909456055569102952">"Pomoćnik za obaveštenja"</string>
+    <string name="notification_ranker_binding_label" msgid="774540592299064747">"Usluga rangiranja obaveštenja"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN je aktiviran"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"Aplikacija <xliff:g id="APP">%s</xliff:g> je aktivirala VPN"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Dodirnite da biste upravljali mrežom."</string>
@@ -1477,7 +1476,7 @@
     <string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Traži PIN pre otkačinjanja"</string>
     <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Traži šablon za otključavanje pre otkačinjanja"</string>
     <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Traži lozinku pre otkačinjanja"</string>
-    <string name="dock_cropped_windows_text" msgid="6378424064779004428">"Veličina aplikacije ne može da se menja. Pomerajte je pomoću dva prsta."</string>
+    <string name="dock_forced_resizable" msgid="5914261505436217520">"Aplikacija možda neće funkcionisati sa podeljenim ekranom."</string>
     <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"Aplikacija ne podržava podeljeni ekran."</string>
     <string name="package_installed_device_owner" msgid="8420696545959087545">"Instalirao je vaš administrator"</string>
     <string name="package_updated_device_owner" msgid="8856631322440187071">"Ažurirao je administrator"</string>
@@ -1560,7 +1559,7 @@
     <string name="importance_from_person" msgid="9160133597262938296">"Ovo je važno zbog ljudi koji učestvuju."</string>
     <string name="user_creation_account_exists" msgid="1942606193570143289">"Želite li da dozvolite aplikaciji <xliff:g id="APP">%1$s</xliff:g> da napravi novog korisnika za <xliff:g id="ACCOUNT">%2$s</xliff:g>?"</string>
     <string name="user_creation_adding" msgid="4482658054622099197">"Želite li da dozvolite aplikaciji <xliff:g id="APP">%1$s</xliff:g> da napravi novog korisnika za <xliff:g id="ACCOUNT">%2$s</xliff:g> (korisnik sa ovim nalogom već postoji)?"</string>
-    <string name="language_selection_title" msgid="7181332986330337171">"Podešavanje jezika"</string>
+    <string name="language_selection_title" msgid="2680677278159281088">"Dodajte jezik"</string>
     <string name="country_selection_title" msgid="2954859441620215513">"Podešavanje regiona"</string>
     <string name="search_language_hint" msgid="7042102592055108574">"Unesite naziv jezika"</string>
     <string name="language_picker_section_suggested" msgid="8414489646861640885">"Predloženi"</string>
@@ -1583,6 +1582,7 @@
     <string name="pin_target" msgid="3052256031352291362">"Zakači"</string>
     <string name="unpin_target" msgid="3556545602439143442">"Otkači"</string>
     <string name="app_info" msgid="6856026610594615344">"Informacije o aplikaciji"</string>
-    <!-- no translation found for negative_duration (5688706061127375131) -->
-    <skip />
+    <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="audit_safemode_notification" msgid="6351827251856877200">"Resetujte uređaj na fabrička podešavanja da biste ga normalno koristili"</string>
+    <string name="audit_safemode_notification_details" msgid="1860601176690176413">"Dodirnite da biste saznali više."</string>
 </resources>
diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml
index 23bfab4..b2633a9 100644
--- a/core/res/res/values-bg/strings.xml
+++ b/core/res/res/values-bg/strings.xml
@@ -229,7 +229,6 @@
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Гласова помощ"</string>
     <string name="global_action_lockdown" msgid="8751542514724332873">"Заключване сега"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
-    <string name="notification_children_count_bracketed" msgid="1769425473168347839">"(<xliff:g id="NOTIFICATIONCOUNT">%d</xliff:g>)"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"Скрито съдържание"</string>
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Съдържанието е скрито чрез правило"</string>
     <string name="safeMode" msgid="2788228061547930246">"Безопасен режим"</string>
@@ -1052,13 +1051,12 @@
     <string name="usb_notification_message" msgid="7347368030849048437">"Докоснете за още опции."</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"Отстраняване на грешки през USB"</string>
     <string name="adb_active_notification_message" msgid="1016654627626476142">"Докоснете за деактивиране"</string>
+    <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Сигналът за програмна грешка се извлича…"</string>
     <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Да се сподели ли сигналът за програмна грешка?"</string>
     <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Сигналът за програмна грешка се споделя…"</string>
-    <string name="share_remote_bugreport_notification_message" msgid="752583906074230920">"Системният ви администратор поиска сигнал за програмна грешка с цел отстраняване на неизправностите на устройството. Възможно е да бъдат споделени приложения и данни и работата на устройството ви временно да се забави."</string>
-    <string name="share_finished_remote_bugreport_notification_message" msgid="4627312060769912353">"Системният ви администратор поиска сигнал за програмна грешка с цел отстраняване на неизправностите на това устройство. Възможно е да бъдат споделени приложения и данни."</string>
-    <string name="sharing_remote_bugreport_notification_message" msgid="673106383408474893">"Това може временно да забави работата на устройството ви"</string>
-    <string name="share_remote_bugreport_notification_accept" msgid="8203856129078669677">"ПРИЕМАМ"</string>
-    <string name="share_remote_bugreport_notification_decline" msgid="6337969352057443969">"ОТХВЪРЛЯМ"</string>
+    <string name="share_remote_bugreport_notification_message_finished" msgid="8610614010660772643">"Системният ви администратор поиска сигнал за програмна грешка с цел отстраняване на неизправностите на това устройство. Възможно е да бъдат споделени приложения и данни."</string>
+    <string name="share_remote_bugreport_action" msgid="6249476773913384948">"СПОДЕЛЯНЕ"</string>
+    <string name="decline_remote_bugreport_action" msgid="6230987241608770062">"ОТХВЪРЛЯНЕ"</string>
     <string name="select_input_method" msgid="8547250819326693584">"Промяна на клавиатурата"</string>
     <string name="configure_input_methods" msgid="4769971288371946846">"Избиране на клавиатури"</string>
     <string name="show_ime" msgid="2506087537466597099">"Показване на екрана, докато физическата клавиатура е активна"</string>
@@ -1137,8 +1135,9 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Тапет"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Промяна на тапета"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Слушател на известия"</string>
+    <string name="vr_listener_binding_label" msgid="4316591939343607306">"Приемател за виртуална реалност"</string>
     <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Доставчик на условия"</string>
-    <string name="notification_assistant_binding_label" msgid="909456055569102952">"Помощник за известия"</string>
+    <string name="notification_ranker_binding_label" msgid="774540592299064747">"Услуга за класифициране на известията"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN е активирана"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN е активирана от <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Докоснете за управление на мрежата."</string>
@@ -1467,7 +1466,7 @@
     <string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Запитване за ПИН код преди освобождаване"</string>
     <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Запитване за фигура за отключване преди освобождаване"</string>
     <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Запитване за парола преди освобождаване"</string>
-    <string name="dock_cropped_windows_text" msgid="6378424064779004428">"Приложението не може да се преоразмерява. Превъртете го с два пръста."</string>
+    <string name="dock_forced_resizable" msgid="5914261505436217520">"Приложението може да не работи в режим на разделен екран."</string>
     <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"Приложението не поддържа разделен екран."</string>
     <string name="package_installed_device_owner" msgid="8420696545959087545">"Инсталирано от администратора ви"</string>
     <string name="package_updated_device_owner" msgid="8856631322440187071">"Актуализирано от администратора ви"</string>
@@ -1541,7 +1540,7 @@
     <string name="importance_from_person" msgid="9160133597262938296">"Това е важно заради участващите хора."</string>
     <string name="user_creation_account_exists" msgid="1942606193570143289">"Да се разреши ли на <xliff:g id="APP">%1$s</xliff:g> да създаде нов потребител с профила <xliff:g id="ACCOUNT">%2$s</xliff:g>?"</string>
     <string name="user_creation_adding" msgid="4482658054622099197">"Да се разреши ли на <xliff:g id="APP">%1$s</xliff:g> да създаде нов потребител с профила <xliff:g id="ACCOUNT">%2$s</xliff:g> (вече съществува потребител с този профил)?"</string>
-    <string name="language_selection_title" msgid="7181332986330337171">"Езиково предпочитание"</string>
+    <string name="language_selection_title" msgid="2680677278159281088">"Добавяне на език"</string>
     <string name="country_selection_title" msgid="2954859441620215513">"Предпочитание за региона"</string>
     <string name="search_language_hint" msgid="7042102592055108574">"Въведете име на език"</string>
     <string name="language_picker_section_suggested" msgid="8414489646861640885">"Предложени"</string>
@@ -1564,6 +1563,7 @@
     <string name="pin_target" msgid="3052256031352291362">"Фиксиране"</string>
     <string name="unpin_target" msgid="3556545602439143442">"Освобождаване"</string>
     <string name="app_info" msgid="6856026610594615344">"Информация за приложението"</string>
-    <!-- no translation found for negative_duration (5688706061127375131) -->
-    <skip />
+    <string name="negative_duration" msgid="5688706061127375131">"-<xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="audit_safemode_notification" msgid="6351827251856877200">"Възстановете фабричните настройки, за да използвате това устройство нормално"</string>
+    <string name="audit_safemode_notification_details" msgid="1860601176690176413">"Докоснете, за да научите повече."</string>
 </resources>
diff --git a/core/res/res/values-bn-rBD/strings.xml b/core/res/res/values-bn-rBD/strings.xml
index 5c20c4e..2042c4c 100644
--- a/core/res/res/values-bn-rBD/strings.xml
+++ b/core/res/res/values-bn-rBD/strings.xml
@@ -229,7 +229,6 @@
     <string name="global_action_voice_assist" msgid="7751191495200504480">"ভয়েস সহায়তা"</string>
     <string name="global_action_lockdown" msgid="8751542514724332873">"এখনই লক করুন"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"৯৯৯+"</string>
-    <string name="notification_children_count_bracketed" msgid="1769425473168347839">"(<xliff:g id="NOTIFICATIONCOUNT">%d</xliff:g>টি)"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"লুকানো বিষয়বস্তু"</string>
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"নীতির কারণে সামগ্রী লুকানো আছে"</string>
     <string name="safeMode" msgid="2788228061547930246">"নিরাপদ মোড"</string>
@@ -1052,13 +1051,12 @@
     <string name="usb_notification_message" msgid="7347368030849048437">"আরো বিকল্পের জন্য স্পর্শ করুন৷"</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"USB ডিবাগিং সংযুক্ত হয়েছে"</string>
     <string name="adb_active_notification_message" msgid="1016654627626476142">"USB ডিবাগিং অক্ষম করতে স্পর্শ করুন৷"</string>
+    <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"ত্রুটির প্রতিবেদন নেওয়া হচ্ছে..."</string>
     <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"ত্রুটির প্রতিবেদন শেয়ার করবেন?"</string>
     <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"ত্রুটির প্রতিবেদন শেয়ার করা হচ্ছে..."</string>
-    <string name="share_remote_bugreport_notification_message" msgid="752583906074230920">"আপনার আইটি প্রশাসক এই ডিভাইসটির সমস্যা নিবারণে সহায়তা করতে একটি ত্রুটির প্রতিবেদন চেয়েছেন৷ অ্যাপ্লিকেশানগুলি এবং ডেটা শেয়ার করা হতে পারে এবং আপনার ডিভাইসটিকে অস্থায়ীভাবে ধীর করে দিতে পারে৷"</string>
-    <string name="share_finished_remote_bugreport_notification_message" msgid="4627312060769912353">"আপনার আইটি প্রশাসক এই ডিভাইসটির সমস্যা নিবারণে সহায়তা করতে একটি ত্রুটির প্রতিবেদন চেয়েছেন৷ অ্যাপ্লিকেশান এবং ডেটা শেয়ার করা হতে পারে৷"</string>
-    <string name="sharing_remote_bugreport_notification_message" msgid="673106383408474893">"এটি অস্থায়ীভাবে আপনার ডিভাইসটিকে ধীর করে দিতে পারে"</string>
-    <string name="share_remote_bugreport_notification_accept" msgid="8203856129078669677">"স্বীকার করুন"</string>
-    <string name="share_remote_bugreport_notification_decline" msgid="6337969352057443969">"অস্বীকার করুন"</string>
+    <string name="share_remote_bugreport_notification_message_finished" msgid="8610614010660772643">"আপনার আইটি প্রশাসক এই ডিভাইসটির সমস্যা নিবারণে সহায়তা করতে একটি ত্রুটির প্রতিবেদন চেয়েছেন৷ অ্যাপ্লিকেশান এবং ডেটা শেয়ার করা হতে পারে৷"</string>
+    <string name="share_remote_bugreport_action" msgid="6249476773913384948">"শেয়ার করুন"</string>
+    <string name="decline_remote_bugreport_action" msgid="6230987241608770062">"অস্বীকার করুন"</string>
     <string name="select_input_method" msgid="8547250819326693584">"কীবোর্ড পরিবর্তন করুন"</string>
     <string name="configure_input_methods" msgid="4769971288371946846">"কীবোর্ড চয়ন করুন"</string>
     <string name="show_ime" msgid="2506087537466597099">"ফিজিক্যাল কীবোর্ড সক্রিয় থাকার সময় এটিকে স্ক্রীনে রাখুন"</string>
@@ -1137,8 +1135,9 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"ওয়ালপেপার"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"ওয়ালপেপার পরিবর্তন করুন"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"বিজ্ঞপ্তির শ্রোতা"</string>
+    <string name="vr_listener_binding_label" msgid="4316591939343607306">"VR শ্রোতা"</string>
     <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"শর্ত প্রদানকারী"</string>
-    <string name="notification_assistant_binding_label" msgid="909456055569102952">"বিজ্ঞপ্তি সহায়ক"</string>
+    <string name="notification_ranker_binding_label" msgid="774540592299064747">"বিজ্ঞপ্তি র‌্যাঙ্কার পরিষেবা"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN সক্রিয়"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"<xliff:g id="APP">%s</xliff:g> এর দ্বারা VPN সক্রিয় করা হয়েছে"</string>
     <string name="vpn_text" msgid="3011306607126450322">"নেটওয়ার্ক পরিচালনা করতে স্পর্শ করুন৷"</string>
@@ -1467,7 +1466,7 @@
     <string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"আনপিন করার আগে পিন চান"</string>
     <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"আনপিন করার আগে আনলক প্যাটার্ন চান"</string>
     <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"আনপিন করার আগে পাসওয়ার্ড চান"</string>
-    <string name="dock_cropped_windows_text" msgid="6378424064779004428">"অ্যাপ্লিকেশানকে পুনরায় আকার দেওয়া যাবে না, দুটি আঙ্গুল ব্যবহার করে স্ক্রোল করুন৷"</string>
+    <string name="dock_forced_resizable" msgid="5914261505436217520">"অ্যাপ্লিকেশানটি বিভক্ত স্ক্রীনে কাজ নাও করতে পারে৷"</string>
     <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"অ্যাপ্লিকেশান বিভক্ত-স্ক্রীন সমর্থন করে না৷"</string>
     <string name="package_installed_device_owner" msgid="8420696545959087545">"আপনার প্রশাসক দ্বারা ইনস্টল করা হয়েছে"</string>
     <string name="package_updated_device_owner" msgid="8856631322440187071">"আপনার প্রশাসক দ্বারা আপডেট করা হয়েছে"</string>
@@ -1541,7 +1540,7 @@
     <string name="importance_from_person" msgid="9160133597262938296">"লোকজন জড়িত থাকার কারণে এটি গুরুত্বপূর্ণ।"</string>
     <string name="user_creation_account_exists" msgid="1942606193570143289">"<xliff:g id="APP">%1$s</xliff:g> কে <xliff:g id="ACCOUNT">%2$s</xliff:g> এর সাথে একজন নতুন ব্যবহারকারী তৈরি করার অনুমতি দেবেন কি?"</string>
     <string name="user_creation_adding" msgid="4482658054622099197">"<xliff:g id="APP">%1$s</xliff:g> কে <xliff:g id="ACCOUNT">%2$s</xliff:g> (একজন ব্যবহারকারী এই অ্যাকাউন্টে ইতিমধ্যেই বিদ্যমান আছেন) এর সাথে একজন নতুন ব্যবহারকারী তৈরি করার অনুমতি দেবেন কি?"</string>
-    <string name="language_selection_title" msgid="7181332986330337171">"পছন্দের ভাষা"</string>
+    <string name="language_selection_title" msgid="2680677278159281088">"একটি ভাষা যোগ করুন"</string>
     <string name="country_selection_title" msgid="2954859441620215513">"পছন্দের অঞ্চল"</string>
     <string name="search_language_hint" msgid="7042102592055108574">"ভাষার নাম লিখুন"</string>
     <string name="language_picker_section_suggested" msgid="8414489646861640885">"প্রস্তাবিত"</string>
@@ -1564,6 +1563,7 @@
     <string name="pin_target" msgid="3052256031352291362">"পিন করুন"</string>
     <string name="unpin_target" msgid="3556545602439143442">"আনপিন করুন"</string>
     <string name="app_info" msgid="6856026610594615344">"অ্যাপ্লিকেশানের তথ্য"</string>
-    <!-- no translation found for negative_duration (5688706061127375131) -->
-    <skip />
+    <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="audit_safemode_notification" msgid="6351827251856877200">"এই ডিভাইসটিকে স্বাভাবিকভাবে ব্যবহার করতে ফ্যাক্টরি পুনরায় সেট করুন"</string>
+    <string name="audit_safemode_notification_details" msgid="1860601176690176413">"আরো জানতে স্পর্শ করুন৷"</string>
 </resources>
diff --git a/core/res/res/values-bs-rBA/strings.xml b/core/res/res/values-bs-rBA/strings.xml
index 58627be..f352620 100644
--- a/core/res/res/values-bs-rBA/strings.xml
+++ b/core/res/res/values-bs-rBA/strings.xml
@@ -231,7 +231,6 @@
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Glasovna pomoć"</string>
     <string name="global_action_lockdown" msgid="8751542514724332873">"Zaključaj odmah"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
-    <string name="notification_children_count_bracketed" msgid="1769425473168347839">"(<xliff:g id="NOTIFICATIONCOUNT">%d</xliff:g>)"</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>
     <string name="safeMode" msgid="2788228061547930246">"Siguran način rada"</string>
@@ -1060,13 +1059,12 @@
     <string name="usb_notification_message" msgid="7347368030849048437">"Dodirnite za više opcija."</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"Uređaj za USB otklanjanje grešaka povezan"</string>
     <string name="adb_active_notification_message" msgid="1016654627626476142">"Dodirnite da biste onemogućili USB otklanjanje grešaka."</string>
+    <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Prijem izvještaja o grešci..."</string>
     <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Podijeliti izvještaj o grešci?"</string>
     <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Dijeljenje izvještaja o grešci..."</string>
-    <string name="share_remote_bugreport_notification_message" msgid="752583906074230920">"Vaš IT administrator je zatražio izvještaj o grešci kako bi pomogao riješiti problem na ovom uređaju. To može uzrokovati dijeljenje aplikacija i podataka te privremeno usporiti vaš uređaj."</string>
-    <string name="share_finished_remote_bugreport_notification_message" msgid="4627312060769912353">"Vaš IT administrator je zatražio izvještaj o grešci kako bi pomogao u rješavanju problema ovog uređaja. Aplikacije i podaci se mogu dijeliti."</string>
-    <string name="sharing_remote_bugreport_notification_message" msgid="673106383408474893">"To može privremeno usporiti vaš uređaj"</string>
-    <string name="share_remote_bugreport_notification_accept" msgid="8203856129078669677">"PRIHVATI"</string>
-    <string name="share_remote_bugreport_notification_decline" msgid="6337969352057443969">"ODBACI"</string>
+    <string name="share_remote_bugreport_notification_message_finished" msgid="8610614010660772643">"Vaš IT administrator je zatražio izvještaj o grešci kako bi pomogao u rješavanju problema ovog uređaja. Aplikacije i podaci se mogu dijeliti."</string>
+    <string name="share_remote_bugreport_action" msgid="6249476773913384948">"PODIJELI"</string>
+    <string name="decline_remote_bugreport_action" msgid="6230987241608770062">"ODBACI"</string>
     <string name="select_input_method" msgid="8547250819326693584">"Promijeni tastaturu"</string>
     <string name="configure_input_methods" msgid="4769971288371946846">"Odaberite tastature"</string>
     <string name="show_ime" msgid="2506087537466597099">"Prikaži na ekranu dok je fizička tastatura aktivna"</string>
@@ -1145,8 +1143,9 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Pozadinska slika"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Promijenite pozadinsku sliku"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Usluga za praćenje obavještenja"</string>
+    <string name="vr_listener_binding_label" msgid="4316591939343607306">"VR slušalac"</string>
     <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Pružalac uslova"</string>
-    <string name="notification_assistant_binding_label" msgid="909456055569102952">"Pomoćnik za obavještenja"</string>
+    <string name="notification_ranker_binding_label" msgid="774540592299064747">"Usluga rangiranja obavještenja"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN aktiviran"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"Aplikacija <xliff:g id="APP">%s</xliff:g> je aktivirala VPN"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Dodirnite za upravljanje mrežom."</string>
@@ -1477,7 +1476,7 @@
     <string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Traži PIN prije nego se otkači"</string>
     <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Traži uzorak za otključavanje prije nego se otkači"</string>
     <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Traži lozinku prije nego se otkači"</string>
-    <string name="dock_cropped_windows_text" msgid="6378424064779004428">"Veličina aplikacije nije promjenjiva, pomičite je s dva prsta."</string>
+    <string name="dock_forced_resizable" msgid="5914261505436217520">"Aplikacija možda neće raditi na podijeljenom ekranu"</string>
     <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"Aplikacija ne podržava dijeljenje ekrana."</string>
     <string name="package_installed_device_owner" msgid="8420696545959087545">"Instalirao administrator"</string>
     <string name="package_updated_device_owner" msgid="8856631322440187071">"Ažurirao administrator"</string>
@@ -1558,9 +1557,9 @@
     </plurals>
     <string name="importance_from_user" msgid="7318955817386549931">"Vi određujete značaj ovih obavještenja."</string>
     <string name="importance_from_person" msgid="9160133597262938296">"Ovo je značajno zbog osoba koje su uključene."</string>
-    <string name="user_creation_account_exists" msgid="1942606193570143289">"Da li dozvoljate da <xliff:g id="APP">%1$s</xliff:g> kreira novog korisnika za nalog <xliff:g id="ACCOUNT">%2$s</xliff:g>?"</string>
+    <string name="user_creation_account_exists" msgid="1942606193570143289">"Da li dozvoljavate aplikaciji <xliff:g id="APP">%1$s</xliff:g> da kreira novog korisnika s računom <xliff:g id="ACCOUNT">%2$s</xliff:g>?"</string>
     <string name="user_creation_adding" msgid="4482658054622099197">"Da li dozvoljavate da <xliff:g id="APP">%1$s</xliff:g> kreira novog korisnika za <xliff:g id="ACCOUNT">%2$s</xliff:g> (Korisnik sa ovim nalogom već postoji)?"</string>
-    <string name="language_selection_title" msgid="7181332986330337171">"Izbor jezika"</string>
+    <string name="language_selection_title" msgid="2680677278159281088">"Dodaj jezik"</string>
     <string name="country_selection_title" msgid="2954859441620215513">"Izbor regije"</string>
     <string name="search_language_hint" msgid="7042102592055108574">"Ukucajte naziv jezika"</string>
     <string name="language_picker_section_suggested" msgid="8414489646861640885">"Predloženo"</string>
@@ -1583,6 +1582,7 @@
     <string name="pin_target" msgid="3052256031352291362">"Zakači"</string>
     <string name="unpin_target" msgid="3556545602439143442">"Otkači"</string>
     <string name="app_info" msgid="6856026610594615344">"Informacije o aplikaciji"</string>
-    <!-- no translation found for negative_duration (5688706061127375131) -->
-    <skip />
+    <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="audit_safemode_notification" msgid="6351827251856877200">"Vratite na fabričke postavke kako biste mogli normalno koristiti ovaj uređaj"</string>
+    <string name="audit_safemode_notification_details" msgid="1860601176690176413">"Dodirnite da saznate više."</string>
 </resources>
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index ef8c2dd..5482896 100644
--- a/core/res/res/values-ca/strings.xml
+++ b/core/res/res/values-ca/strings.xml
@@ -229,7 +229,6 @@
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Assist. per veu"</string>
     <string name="global_action_lockdown" msgid="8751542514724332873">"Bloqueja ara"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"+999"</string>
-    <string name="notification_children_count_bracketed" msgid="1769425473168347839">"(<xliff:g id="NOTIFICATIONCOUNT">%d</xliff:g>)"</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>
     <string name="safeMode" msgid="2788228061547930246">"Mode segur"</string>
@@ -1052,13 +1051,12 @@
     <string name="usb_notification_message" msgid="7347368030849048437">"Toca per veure més opcions."</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"Depuració USB activada"</string>
     <string name="adb_active_notification_message" msgid="1016654627626476142">"Toca per desactivar la depuració USB"</string>
+    <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"S\'està creant l\'informe d\'errors…"</string>
     <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Vols compartir l\'informe d\'errors?"</string>
     <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"S\'està compartint l\'informe d\'errors…"</string>
-    <string name="share_remote_bugreport_notification_message" msgid="752583906074230920">"L\'administrador de TI ha sol·licitat un informe d\'errors per resoldre els problemes d\'aquest dispositiu. És possible que es comparteixin aplicacions i dades, i que el dispositiu funcioni més a poc a poc durant una estona."</string>
-    <string name="share_finished_remote_bugreport_notification_message" msgid="4627312060769912353">"El teu administrador de TI ha sol·licitat un informe d\'errors per resoldre els problemes d\'aquest dispositiu. És possible que es comparteixin aplicacions i dades."</string>
-    <string name="sharing_remote_bugreport_notification_message" msgid="673106383408474893">"És possible que el dispositiu funcioni més a poc a poc durant una estona"</string>
-    <string name="share_remote_bugreport_notification_accept" msgid="8203856129078669677">"ACCEPTA"</string>
-    <string name="share_remote_bugreport_notification_decline" msgid="6337969352057443969">"REBUTJA"</string>
+    <string name="share_remote_bugreport_notification_message_finished" msgid="8610614010660772643">"L\'administrador de TI ha sol·licitat un informe d\'errors per resoldre els problemes d\'aquest dispositiu. És possible que es comparteixin aplicacions i dades."</string>
+    <string name="share_remote_bugreport_action" msgid="6249476773913384948">"COMPARTEIX"</string>
+    <string name="decline_remote_bugreport_action" msgid="6230987241608770062">"REBUTJA"</string>
     <string name="select_input_method" msgid="8547250819326693584">"Canvia el teclat"</string>
     <string name="configure_input_methods" msgid="4769971288371946846">"Tria els teclats"</string>
     <string name="show_ime" msgid="2506087537466597099">"El deixa a la pantalla mentre el teclat físic està actiu"</string>
@@ -1137,8 +1135,9 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Fons de pantalla"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Canvia el fons de pantalla"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Oient de notificacions"</string>
+    <string name="vr_listener_binding_label" msgid="4316591939343607306">"Processador de realitat virtual"</string>
     <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Proveïdor de condicions"</string>
-    <string name="notification_assistant_binding_label" msgid="909456055569102952">"Assistent de notificacions"</string>
+    <string name="notification_ranker_binding_label" msgid="774540592299064747">"Servei de classificació de notificacions"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN activada"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"<xliff:g id="APP">%s</xliff:g> ha activat VPN"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Toca per gestionar la xarxa."</string>
@@ -1467,7 +1466,7 @@
     <string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Sol·licita el codi PIN per anul·lar"</string>
     <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Sol·licita el patró de desbloqueig per anul·lar"</string>
     <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Demana la contrasenya per anul·lar"</string>
-    <string name="dock_cropped_windows_text" msgid="6378424064779004428">"No es pot canviar la mida de l\'aplicació. Desplaça-la amb dos dits."</string>
+    <string name="dock_forced_resizable" msgid="5914261505436217520">"És possible que l\'aplicació no funcioni amb la pantalla dividida."</string>
     <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"L\'aplicació no admet la pantalla dividida."</string>
     <string name="package_installed_device_owner" msgid="8420696545959087545">"L\'administrador ho ha instal·lat"</string>
     <string name="package_updated_device_owner" msgid="8856631322440187071">"L\'administrador l\'ha actualitzat"</string>
@@ -1541,7 +1540,7 @@
     <string name="importance_from_person" msgid="9160133597262938296">"Aquest missatge és important per les persones implicades."</string>
     <string name="user_creation_account_exists" msgid="1942606193570143289">"Concedeixes permís a <xliff:g id="APP">%1$s</xliff:g> per crear un usuari amb el compte <xliff:g id="ACCOUNT">%2$s</xliff:g>?"</string>
     <string name="user_creation_adding" msgid="4482658054622099197">"Concedeixes permís a <xliff:g id="APP">%1$s</xliff:g> per crear un usuari amb el compte <xliff:g id="ACCOUNT">%2$s</xliff:g>? (Ja hi ha un usuari amb aquest compte.)"</string>
-    <string name="language_selection_title" msgid="7181332986330337171">"Preferència d\'idioma"</string>
+    <string name="language_selection_title" msgid="2680677278159281088">"Afegeix un idioma"</string>
     <string name="country_selection_title" msgid="2954859441620215513">"Preferència de regió"</string>
     <string name="search_language_hint" msgid="7042102592055108574">"Nom de l\'idioma"</string>
     <string name="language_picker_section_suggested" msgid="8414489646861640885">"Suggerits"</string>
@@ -1564,6 +1563,7 @@
     <string name="pin_target" msgid="3052256031352291362">"Fixa"</string>
     <string name="unpin_target" msgid="3556545602439143442">"No fixis"</string>
     <string name="app_info" msgid="6856026610594615344">"Informació de l\'aplicació"</string>
-    <!-- no translation found for negative_duration (5688706061127375131) -->
-    <skip />
+    <string name="negative_duration" msgid="5688706061127375131">"-<xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="audit_safemode_notification" msgid="6351827251856877200">"Restableix les dades de fàbrica del dispositiu per utilitzar-lo amb normalitat"</string>
+    <string name="audit_safemode_notification_details" msgid="1860601176690176413">"Toca per obtenir més informació."</string>
 </resources>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index 321e397..390dfd0 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -233,7 +233,6 @@
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Hlas. asistence"</string>
     <string name="global_action_lockdown" msgid="8751542514724332873">"Zamknout"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
-    <string name="notification_children_count_bracketed" msgid="1769425473168347839">"(<xliff:g id="NOTIFICATIONCOUNT">%d</xliff:g>)"</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>
     <string name="safeMode" msgid="2788228061547930246">"Nouzový režim"</string>
@@ -1068,13 +1067,12 @@
     <string name="usb_notification_message" msgid="7347368030849048437">"Klepnutím zobrazíte další možnosti."</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"Ladění přes USB připojeno"</string>
     <string name="adb_active_notification_message" msgid="1016654627626476142">"Dotykem zakážete ladění USB."</string>
+    <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Vytváření zprávy o chybě…"</string>
     <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Sdílet zprávu o chybě?"</string>
     <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Sdílení zprávy o chybě…"</string>
-    <string name="share_remote_bugreport_notification_message" msgid="752583906074230920">"Administrátor IT si vyžádal zprávu o chybě, aby mohl problém odstranit. Mohou být sdíleny aplikace a data a zařízení se může dočasně zpomalit."</string>
-    <string name="share_finished_remote_bugreport_notification_message" msgid="4627312060769912353">"Administrátor IT si vyžádal zprávu o chybě, aby mohl problém odstranit. Aplikace a data mohou být sdílena."</string>
-    <string name="sharing_remote_bugreport_notification_message" msgid="673106383408474893">"Zařízení se může dočasně zpomalit"</string>
-    <string name="share_remote_bugreport_notification_accept" msgid="8203856129078669677">"PŘIJMOUT"</string>
-    <string name="share_remote_bugreport_notification_decline" msgid="6337969352057443969">"ODMÍTNOUT"</string>
+    <string name="share_remote_bugreport_notification_message_finished" msgid="8610614010660772643">"Administrátor IT si vyžádal zprávu o chybě, aby mohl problém odstranit. Aplikace a data mohou být sdílena."</string>
+    <string name="share_remote_bugreport_action" msgid="6249476773913384948">"SDÍLET"</string>
+    <string name="decline_remote_bugreport_action" msgid="6230987241608770062">"ODMÍTNOUT"</string>
     <string name="select_input_method" msgid="8547250819326693584">"Změna klávesnice"</string>
     <string name="configure_input_methods" msgid="4769971288371946846">"Vybrat klávesnici"</string>
     <string name="show_ime" msgid="2506087537466597099">"Ponechat na obrazovce, když je aktivní fyzická klávesnice"</string>
@@ -1153,8 +1151,9 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Tapeta"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Změnit tapetu"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Aplikace poslouchající oznámení"</string>
+    <string name="vr_listener_binding_label" msgid="4316591939343607306">"Přijímač virtuální reality"</string>
     <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Poskytovatel podmínky"</string>
-    <string name="notification_assistant_binding_label" msgid="909456055569102952">"Asistent oznámení"</string>
+    <string name="notification_ranker_binding_label" msgid="774540592299064747">"Služba na hodnocení důležitosti oznámení"</string>
     <string name="vpn_title" msgid="19615213552042827">"Síť VPN je aktivována"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"Aplikace <xliff:g id="APP">%s</xliff:g> aktivovala síť VPN"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Dotykem zobrazíte správu sítě."</string>
@@ -1487,7 +1486,7 @@
     <string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Před uvolněním požádat o PIN"</string>
     <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Před uvolněním požádat o bezpečnostní gesto"</string>
     <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Před uvolněním požádat o heslo"</string>
-    <string name="dock_cropped_windows_text" msgid="6378424064779004428">"Velikost aplikace nelze změnit. Zobrazení můžete posouvat dvěma prsty."</string>
+    <string name="dock_forced_resizable" msgid="5914261505436217520">"Aplikace v režimu rozdělené obrazovky nemusí fungovat."</string>
     <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"Aplikace nepodporuje režim rozdělené obrazovky."</string>
     <string name="package_installed_device_owner" msgid="8420696545959087545">"Nainstalováno administrátorem"</string>
     <string name="package_updated_device_owner" msgid="8856631322440187071">"Aktualizováno administrátorem"</string>
@@ -1579,7 +1578,7 @@
     <string name="importance_from_person" msgid="9160133597262938296">"Tato zpráva je důležitá kvůli lidem zapojeným do konverzace."</string>
     <string name="user_creation_account_exists" msgid="1942606193570143289">"Povolit aplikaci <xliff:g id="APP">%1$s</xliff:g> vytvořit nového uživatele s účtem <xliff:g id="ACCOUNT">%2$s</xliff:g>?"</string>
     <string name="user_creation_adding" msgid="4482658054622099197">"Povolit aplikaci <xliff:g id="APP">%1$s</xliff:g> vytvořit nového uživatele s účtem <xliff:g id="ACCOUNT">%2$s</xliff:g>? (Uživatel s tímto účtem již existuje.)"</string>
-    <string name="language_selection_title" msgid="7181332986330337171">"Preferovaný jazyk"</string>
+    <string name="language_selection_title" msgid="2680677278159281088">"Přidat jazyk"</string>
     <string name="country_selection_title" msgid="2954859441620215513">"Preferovaná oblast"</string>
     <string name="search_language_hint" msgid="7042102592055108574">"Zadejte název jazyka"</string>
     <string name="language_picker_section_suggested" msgid="8414489646861640885">"Navrhované"</string>
@@ -1602,6 +1601,7 @@
     <string name="pin_target" msgid="3052256031352291362">"Připnout"</string>
     <string name="unpin_target" msgid="3556545602439143442">"Odepnout"</string>
     <string name="app_info" msgid="6856026610594615344">"Informace o aplikaci"</string>
-    <!-- no translation found for negative_duration (5688706061127375131) -->
-    <skip />
+    <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="audit_safemode_notification" msgid="6351827251856877200">"Chcete-li toto zařízení normálně používat, obnovte jej do továrního nastavení"</string>
+    <string name="audit_safemode_notification_details" msgid="1860601176690176413">"Klepnutím zobrazíte další informace."</string>
 </resources>
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index 8b89478..583a6b7 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -229,7 +229,6 @@
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Taleassistent"</string>
     <string name="global_action_lockdown" msgid="8751542514724332873">"Lås nu"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
-    <string name="notification_children_count_bracketed" msgid="1769425473168347839">"(<xliff:g id="NOTIFICATIONCOUNT">%d</xliff:g>)"</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>
     <string name="safeMode" msgid="2788228061547930246">"Sikker tilstand"</string>
@@ -1052,13 +1051,12 @@
     <string name="usb_notification_message" msgid="7347368030849048437">"Tryk for at se flere muligheder."</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"USB-fejlretning er tilsluttet"</string>
     <string name="adb_active_notification_message" msgid="1016654627626476142">"Tryk for at deaktivere USB-fejlretning."</string>
+    <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Opretter fejlrapport…"</string>
     <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Vil du dele fejlrapporten?"</string>
     <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Deler fejlrapport…"</string>
-    <string name="share_remote_bugreport_notification_message" msgid="752583906074230920">"Din it-administrator har anmodet om en fejlrapport for bedre at kunne finde og rette fejlen på enheden. Apps og data deles muligvis, og din enhed kan midlertidigt blive langsommere."</string>
-    <string name="share_finished_remote_bugreport_notification_message" msgid="4627312060769912353">"Din it-administrator har anmodet om en fejlrapport for bedre at kunne finde og rette fejlen på enheden. Apps og data deles muligvis."</string>
-    <string name="sharing_remote_bugreport_notification_message" msgid="673106383408474893">"Dette kan midlertidigt gøre enheden langsommere"</string>
-    <string name="share_remote_bugreport_notification_accept" msgid="8203856129078669677">"ACCEPTÉR"</string>
-    <string name="share_remote_bugreport_notification_decline" msgid="6337969352057443969">"AFVIS"</string>
+    <string name="share_remote_bugreport_notification_message_finished" msgid="8610614010660772643">"Din it-administrator har anmodet om en fejlrapport for bedre at kunne finde og rette fejlen på enheden. Apps og data deles muligvis."</string>
+    <string name="share_remote_bugreport_action" msgid="6249476773913384948">"DEL"</string>
+    <string name="decline_remote_bugreport_action" msgid="6230987241608770062">"AFVIS"</string>
     <string name="select_input_method" msgid="8547250819326693584">"Skift tastatur"</string>
     <string name="configure_input_methods" msgid="4769971288371946846">"Vælg tastaturer"</string>
     <string name="show_ime" msgid="2506087537466597099">"Behold den på skærmen, mens det fysiske tastatur er aktivt"</string>
@@ -1137,8 +1135,9 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Baggrund"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Skift baggrund"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Underretningslytter"</string>
+    <string name="vr_listener_binding_label" msgid="4316591939343607306">"VR-lyttefunktion"</string>
     <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Tjeneste til formidling af betingelser"</string>
-    <string name="notification_assistant_binding_label" msgid="909456055569102952">"Underretningsassistent"</string>
+    <string name="notification_ranker_binding_label" msgid="774540592299064747">"Tjeneste til rangering af underretninger"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN er aktiveret."</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN aktiveres af <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Tryk for at administrere netværket."</string>
@@ -1467,7 +1466,7 @@
     <string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Bed om pinkode inden frigørelse"</string>
     <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Bed om oplåsningsmønster ved deaktivering"</string>
     <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Bed om adgangskode inden frigørelse"</string>
-    <string name="dock_cropped_windows_text" msgid="6378424064779004428">"Appens størrelse kan ikke ændres. Gennemgå den ved at rulle med to fingre."</string>
+    <string name="dock_forced_resizable" msgid="5914261505436217520">"Appen fungerer muligvis ikke i delt skærm."</string>
     <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"Appen understøtter ikke delt skærm."</string>
     <string name="package_installed_device_owner" msgid="8420696545959087545">"Installeret af din administrator"</string>
     <string name="package_updated_device_owner" msgid="8856631322440187071">"Opdateret af administrator"</string>
@@ -1541,7 +1540,7 @@
     <string name="importance_from_person" msgid="9160133597262938296">"Dette er vigtigt på grund af de personer, det handler om."</string>
     <string name="user_creation_account_exists" msgid="1942606193570143289">"Vil du give <xliff:g id="APP">%1$s</xliff:g> tilladelse til at oprette en ny bruger med <xliff:g id="ACCOUNT">%2$s</xliff:g>?"</string>
     <string name="user_creation_adding" msgid="4482658054622099197">"Vil du give <xliff:g id="APP">%1$s</xliff:g> tilladelse til at oprette en ny bruger med <xliff:g id="ACCOUNT">%2$s</xliff:g> (der findes allerede en bruger med denne konto)?"</string>
-    <string name="language_selection_title" msgid="7181332986330337171">"Sprogindstilling"</string>
+    <string name="language_selection_title" msgid="2680677278159281088">"Tilføj et sprog"</string>
     <string name="country_selection_title" msgid="2954859441620215513">"Områdeindstilling"</string>
     <string name="search_language_hint" msgid="7042102592055108574">"Angiv sprogets navn"</string>
     <string name="language_picker_section_suggested" msgid="8414489646861640885">"Foreslået"</string>
@@ -1565,4 +1564,6 @@
     <string name="unpin_target" msgid="3556545602439143442">"Frigør"</string>
     <string name="app_info" msgid="6856026610594615344">"Oplysninger om appen"</string>
     <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="audit_safemode_notification" msgid="6351827251856877200">"Nulstil enheden til fabriksindstillingerne for at bruge den på normal vis"</string>
+    <string name="audit_safemode_notification_details" msgid="1860601176690176413">"Tryk for at få flere oplysninger."</string>
 </resources>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index d3a2959..b67402a 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -229,7 +229,6 @@
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Sprachassistent"</string>
     <string name="global_action_lockdown" msgid="8751542514724332873">"Jetzt sperren"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
-    <string name="notification_children_count_bracketed" msgid="1769425473168347839">"(<xliff:g id="NOTIFICATIONCOUNT">%d</xliff:g>)"</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>
     <string name="safeMode" msgid="2788228061547930246">"Abgesicherter Modus"</string>
@@ -1052,13 +1051,12 @@
     <string name="usb_notification_message" msgid="7347368030849048437">"Für weitere Optionen tippen"</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"USB-Debugging"</string>
     <string name="adb_active_notification_message" msgid="1016654627626476142">"Zum Deaktivieren berühren"</string>
+    <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Fehlerbericht wird abgerufen…"</string>
     <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Fehlerbericht teilen?"</string>
     <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Fehlerbericht wird geteilt…"</string>
-    <string name="share_remote_bugreport_notification_message" msgid="752583906074230920">"Dein IT-Administrator hat einen Fehlerbericht zur Fehlerbehebung dieses Geräts angefordert. Apps und Daten werden unter Umständen geteilt und dein Gerät wird möglicherweise vorübergehend langsamer."</string>
-    <string name="share_finished_remote_bugreport_notification_message" msgid="4627312060769912353">"Dein IT-Administrator hat einen Fehlerbericht zur Fehlerbehebung dieses Geräts angefordert. Apps und Daten werden unter Umständen geteilt."</string>
-    <string name="sharing_remote_bugreport_notification_message" msgid="673106383408474893">"Dadurch wird dein Gerät möglicherweise vorübergehend langsamer"</string>
-    <string name="share_remote_bugreport_notification_accept" msgid="8203856129078669677">"AKZEPTIEREN"</string>
-    <string name="share_remote_bugreport_notification_decline" msgid="6337969352057443969">"ABLEHNEN"</string>
+    <string name="share_remote_bugreport_notification_message_finished" msgid="8610614010660772643">"Dein IT-Administrator hat einen Fehlerbericht zur Fehlerbehebung für dieses Gerät angefordert. Apps und Daten werden unter Umständen geteilt."</string>
+    <string name="share_remote_bugreport_action" msgid="6249476773913384948">"TEILEN"</string>
+    <string name="decline_remote_bugreport_action" msgid="6230987241608770062">"ABLEHNEN"</string>
     <string name="select_input_method" msgid="8547250819326693584">"Tastatur ändern"</string>
     <string name="configure_input_methods" msgid="4769971288371946846">"Tastatur auswählen"</string>
     <string name="show_ime" msgid="2506087537466597099">"Auf dem Display einblenden, wenn die physische Tastatur aktiv ist"</string>
@@ -1137,8 +1135,9 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Hintergrund"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Hintergrund ändern"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Benachrichtigungs-Listener"</string>
+    <string name="vr_listener_binding_label" msgid="4316591939343607306">"VR-Listener"</string>
     <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Bedingungsprovider"</string>
-    <string name="notification_assistant_binding_label" msgid="909456055569102952">"Benachrichtigungsassistent"</string>
+    <string name="notification_ranker_binding_label" msgid="774540592299064747">"Service für Einstufung von Benachrichtigungen"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN aktiviert"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN wurde von <xliff:g id="APP">%s</xliff:g> aktiviert."</string>
     <string name="vpn_text" msgid="3011306607126450322">"Zum Verwalten des Netzwerks berühren"</string>
@@ -1467,7 +1466,7 @@
     <string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Vor dem Beenden nach PIN fragen"</string>
     <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Vor dem Beenden nach Entsperrungsmuster fragen"</string>
     <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Vor dem Beenden nach Passwort fragen"</string>
-    <string name="dock_cropped_windows_text" msgid="6378424064779004428">"Die Größe der App kann nicht angepasst werden. Scrolle sie mit zwei Fingern."</string>
+    <string name="dock_forced_resizable" msgid="5914261505436217520">"Die App funktioniert unter Umständen bei geteiltem Bildschirm nicht."</string>
     <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"Das Teilen des Bildschirms wird in dieser App nicht unterstützt."</string>
     <string name="package_installed_device_owner" msgid="8420696545959087545">"Von deinem Administrator installiert"</string>
     <string name="package_updated_device_owner" msgid="8856631322440187071">"Von deinem Administrator aktualisiert"</string>
@@ -1541,7 +1540,7 @@
     <string name="importance_from_person" msgid="9160133597262938296">"Diese Benachrichtigung ist aufgrund der beteiligten Personen wichtig."</string>
     <string name="user_creation_account_exists" msgid="1942606193570143289">"Möchtest du zulassen, dass <xliff:g id="APP">%1$s</xliff:g> einen neuen Nutzer mit <xliff:g id="ACCOUNT">%2$s</xliff:g> erstellt?"</string>
     <string name="user_creation_adding" msgid="4482658054622099197">"Möchtest du zulassen, dass <xliff:g id="APP">%1$s</xliff:g> einen neuen Nutzer mit <xliff:g id="ACCOUNT">%2$s</xliff:g> erstellt? Dieses Konto wird jedoch bereits von einem anderen Nutzer verwendet."</string>
-    <string name="language_selection_title" msgid="7181332986330337171">"Spracheinstellung"</string>
+    <string name="language_selection_title" msgid="2680677278159281088">"Sprache hinzufügen"</string>
     <string name="country_selection_title" msgid="2954859441620215513">"Region auswählen"</string>
     <string name="search_language_hint" msgid="7042102592055108574">"Sprache eingeben"</string>
     <string name="language_picker_section_suggested" msgid="8414489646861640885">"Vorschläge"</string>
@@ -1564,6 +1563,7 @@
     <string name="pin_target" msgid="3052256031352291362">"Markieren"</string>
     <string name="unpin_target" msgid="3556545602439143442">"Markierung entfernen"</string>
     <string name="app_info" msgid="6856026610594615344">"App-Informationen"</string>
-    <!-- no translation found for negative_duration (5688706061127375131) -->
-    <skip />
+    <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="audit_safemode_notification" msgid="6351827251856877200">"Gerät zur normalen Verwendung auf Werkseinstellungen zurücksetzen"</string>
+    <string name="audit_safemode_notification_details" msgid="1860601176690176413">"Für weitere Informationen tippen."</string>
 </resources>
diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml
index eb6de52..8450189 100644
--- a/core/res/res/values-el/strings.xml
+++ b/core/res/res/values-el/strings.xml
@@ -162,7 +162,7 @@
     <string name="contentServiceTooManyDeletesNotificationDesc" msgid="8100981435080696431">"Πάρα πολλές <xliff:g id="CONTENT_TYPE">%s</xliff:g> διαγραφές."</string>
     <string name="low_memory" product="tablet" msgid="6494019234102154896">"Ο αποθηκευτικός χώρος του tablet είναι πλήρης. Διαγράψτε μερικά αρχεία για να δημιουργήσετε ελεύθερο χώρο."</string>
     <string name="low_memory" product="watch" msgid="4415914910770005166">"Ο αποθηκευτικός χώρος παρακολούθησης είναι πλήρης! Διαγράψτε μερικά αρχεία για να απελευθερώσετε χώρο."</string>
-    <string name="low_memory" product="tv" msgid="516619861191025923">"Ο χώρος αποθήκευσης της τηλεόρασης είναι πλήρης. Διαγράψτε ορισμένα αρχεία, για να ελευθερώσετε χώρο."</string>
+    <string name="low_memory" product="tv" msgid="516619861191025923">"Ο αποθηκευτικός χώρος της τηλεόρασης είναι πλήρης. Διαγράψτε ορισμένα αρχεία, για να ελευθερώσετε χώρο."</string>
     <string name="low_memory" product="default" msgid="3475999286680000541">"Ο αποθηκευτικός χώρος του τηλεφώνου είναι πλήρης. Διαγράψτε μερικά αρχεία για να δημιουργήσετε ελεύθερο χώρο."</string>
     <string name="ssl_ca_cert_warning" msgid="5848402127455021714">"Το δίκτυο ενδέχεται να παρακολουθείται"</string>
     <string name="ssl_ca_cert_noti_by_unknown" msgid="4475437862189850602">"Από ένα άγνωστο τρίτο μέρος"</string>
@@ -229,7 +229,6 @@
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Φων.υποβοηθ."</string>
     <string name="global_action_lockdown" msgid="8751542514724332873">"Κλείδωμα τώρα"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
-    <string name="notification_children_count_bracketed" msgid="1769425473168347839">"(<xliff:g id="NOTIFICATIONCOUNT">%d</xliff:g>)"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"Κρυφό περιεχόμενο"</string>
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Το περιεχόμενο είναι κρυφό βάσει πολιτικής"</string>
     <string name="safeMode" msgid="2788228061547930246">"Ασφαλής λειτουργία"</string>
@@ -310,7 +309,7 @@
     <string name="permdesc_persistentActivity" product="tablet" msgid="8525189272329086137">"Επιτρέπει στην εφαρμογή να δημιουργεί μόνιμα τμήματα του εαυτού της στη μνήμη. Αυτό μπορεί να περιορίζει τη μνήμη που διατίθεται σε άλλες εφαρμογές, καθυστερώντας τη λειτουργία του tablet."</string>
     <string name="permdesc_persistentActivity" product="tv" msgid="5086862529499103587">"Επιτρέπει στην εφαρμογή να καθιστά τμήματά της μόνιμα στη μνήμη. Αυτό μπορεί να περιορίσει τη μνήμη που διατίθεται σε άλλες εφαρμογές, επιβραδύνοντας τη λειτουργία της τηλεόρασης."</string>
     <string name="permdesc_persistentActivity" product="default" msgid="4384760047508278272">"Επιτρέπει στην εφαρμογή να δημιουργεί μόνιμα τμήματα του εαυτού της στη μνήμη. Αυτό μπορεί να περιορίζει τη μνήμη που διατίθεται σε άλλες εφαρμογές, καθυστερώντας τη λειτουργία του τηλεφώνου."</string>
-    <string name="permlab_getPackageSize" msgid="7472921768357981986">"μέτρηση χώρου αποθήκευσης εφαρμογής"</string>
+    <string name="permlab_getPackageSize" msgid="7472921768357981986">"μέτρηση αποθηκευτικού χώρου εφαρμογής"</string>
     <string name="permdesc_getPackageSize" msgid="3921068154420738296">"Επιτρέπει στην εφαρμογή να ανακτήσει τα μεγέθη κώδικα, δεδομένων και προσωρινής μνήμης"</string>
     <string name="permlab_writeSettings" msgid="2226195290955224730">"τροποποίηση ρυθμίσεων συστήματος"</string>
     <string name="permdesc_writeSettings" msgid="7775723441558907181">"Επιτρέπει στην εφαρμογή την τροποποίηση των δεδομένων των ρυθμίσεων του συστήματος. Τυχόν κακόβουλες εφαρμογές ενδέχεται να καταστρέψουν τη διαμόρφωση του συστήματός σας."</string>
@@ -879,9 +878,9 @@
     <string name="deleteText" msgid="6979668428458199034">"Διαγραφή"</string>
     <string name="inputMethod" msgid="1653630062304567879">"Μέθοδος εισόδου"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"Ενέργειες κειμένου"</string>
-    <string name="low_internal_storage_view_title" msgid="5576272496365684834">"Ο χώρος αποθήκευσης εξαντλείται"</string>
+    <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>
+    <string name="low_internal_storage_view_text_no_boot" msgid="6935190099204693424">"Δεν υπάρχει αρκετός αποθηκευτικός χώρος για το σύστημα. Βεβαιωθείτε ότι διαθέτετε 250 MB ελεύθερου χώρου και κάντε επανεκκίνηση."</string>
     <string name="app_running_notification_title" msgid="8718335121060787914">"Η εφαρμογή <xliff:g id="APP_NAME">%1$s</xliff:g> εκτελείται"</string>
     <string name="app_running_notification_text" msgid="4653586947747330058">"Αγγίξτε για περισσότερες πληροφορίες ή για να διακόψετε την εκτέλεση της εφαρμογής."</string>
     <string name="ok" msgid="5970060430562524910">"OK"</string>
@@ -1052,13 +1051,12 @@
     <string name="usb_notification_message" msgid="7347368030849048437">"Αγγίξτε για περισσότερες επιλογές."</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"Συνδέθηκε ο εντοπισμός σφαλμάτων USB"</string>
     <string name="adb_active_notification_message" msgid="1016654627626476142">"Απεν. του εντοπ. σφαλμάτων USB."</string>
+    <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Λήψη αναφοράς σφάλματος…"</string>
     <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Κοινή χρήση αναφοράς σφάλματος;"</string>
     <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Κοινή χρήση αναφοράς σφάλματος…"</string>
-    <string name="share_remote_bugreport_notification_message" msgid="752583906074230920">"Ο διαχειριστής σας IT ζήτησε μια αναφορά σφάλματος για να συμβάλει στην αντιμετώπιση του προβλήματος αυτής της συσκευής. Ενδέχεται να γίνει κοινή χρήση των εφαρμογών και να επιβραδυνθεί προσωρινά τη λειτουργία της συσκευής σας."</string>
-    <string name="share_finished_remote_bugreport_notification_message" msgid="4627312060769912353">"Ο διαχειριστής σας IT ζήτησε μια αναφορά σφάλματος για να συμβάλει στην αντιμετώπιση του προβλήματος αυτής της συσκευής. Ενδέχεται να γίνει κοινή χρήση των εφαρμογών και των δεδομένων."</string>
-    <string name="sharing_remote_bugreport_notification_message" msgid="673106383408474893">"Αυτή η διαδικασία ενδέχεται να επιβραδύνει προσωρινά τη λειτουργία της συσκευής σας"</string>
-    <string name="share_remote_bugreport_notification_accept" msgid="8203856129078669677">"ΑΠΟΔΟΧΗ"</string>
-    <string name="share_remote_bugreport_notification_decline" msgid="6337969352057443969">"ΑΠΟΡΡΙΨΗ"</string>
+    <string name="share_remote_bugreport_notification_message_finished" msgid="8610614010660772643">"Ο διαχειριστής IT σας ζήτησε μια αναφορά σφάλματος για να συμβάλει στην αντιμετώπιση του προβλήματος αυτής της συσκευής. Ενδέχεται να κοινοποιηθούν οι εφαρμογές και τα δεδομένα."</string>
+    <string name="share_remote_bugreport_action" msgid="6249476773913384948">"ΚΟΙΝΟΠΟΙΗΣΗ"</string>
+    <string name="decline_remote_bugreport_action" msgid="6230987241608770062">"ΑΠΟΡΡΙΨΗ"</string>
     <string name="select_input_method" msgid="8547250819326693584">"Αλλαγή πληκτρολογίου"</string>
     <string name="configure_input_methods" msgid="4769971288371946846">"Επιλογή πληκτρολογίων"</string>
     <string name="show_ime" msgid="2506087537466597099">"Να παραμένει στην οθόνη όταν είναι ενεργό το φυσικό πληκτρολόγιο"</string>
@@ -1137,8 +1135,9 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Ταπετσαρία"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Αλλαγή ταπετσαρίας"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Υπηρεσία ακρόασης ειδοποίησης"</string>
+    <string name="vr_listener_binding_label" msgid="4316591939343607306">"Λειτουργία ακρόασης Εικονικής Πραγματικότητας"</string>
     <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Πάροχος συνθηκών"</string>
-    <string name="notification_assistant_binding_label" msgid="909456055569102952">"Βοηθός ειδοποιήσεων"</string>
+    <string name="notification_ranker_binding_label" msgid="774540592299064747">"Υπηρεσία κατάταξης ειδοποιήσεων"</string>
     <string name="vpn_title" msgid="19615213552042827">"Το VPN ενεργοποιήθηκε"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"Το VPN ενεργοποιήθηκε από την εφαρμογή <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Αγγίξτε για τη διαχείριση του δικτύου."</string>
@@ -1165,7 +1164,7 @@
       <item quantity="one">1 αντιστοιχία</item>
     </plurals>
     <string name="action_mode_done" msgid="7217581640461922289">"Τέλος"</string>
-    <string name="progress_erasing" product="nosdcard" msgid="4521573321524340058">"Διαγραφή χώρου αποθήκευσης USB..."</string>
+    <string name="progress_erasing" product="nosdcard" msgid="4521573321524340058">"Διαγραφή αποθηκευτικού χώρου USB..."</string>
     <string name="progress_erasing" product="default" msgid="6596988875507043042">"Διαγραφή κάρτας SD..."</string>
     <string name="share" msgid="1778686618230011964">"Κοινή χρ."</string>
     <string name="find" msgid="4808270900322985960">"Εύρεση"</string>
@@ -1223,12 +1222,12 @@
     <string name="action_menu_overflow_description" msgid="2295659037509008453">"Περισσότερες επιλογές"</string>
     <string name="action_bar_home_description_format" msgid="7965984360903693903">"%1$s, %2$s"</string>
     <string name="action_bar_home_subtitle_description_format" msgid="6985546530471780727">"%1$s, %2$s, %3$s"</string>
-    <string name="storage_internal" msgid="4891916833657929263">"Εσωτερικός χώρος αποθήκευσης"</string>
+    <string name="storage_internal" msgid="4891916833657929263">"Εσωτερικός αποθηκευτικός χώρος"</string>
     <string name="storage_sd_card" msgid="3282948861378286745">"Κάρτα SD"</string>
     <string name="storage_sd_card_label" msgid="6347111320774379257">"Κάρτα SD <xliff:g id="MANUFACTURER">%s</xliff:g>"</string>
     <string name="storage_usb_drive" msgid="6261899683292244209">"Μονάδα USB"</string>
     <string name="storage_usb_drive_label" msgid="4501418548927759953">"Μονάδα USB <xliff:g id="MANUFACTURER">%s</xliff:g>"</string>
-    <string name="storage_usb" msgid="3017954059538517278">"Χώρος αποθήκευσης USB"</string>
+    <string name="storage_usb" msgid="3017954059538517278">"Αποθηκευτικός χώρος USB"</string>
     <string name="extract_edit_menu_button" msgid="8940478730496610137">"Επεξεργασία"</string>
     <string name="data_usage_warning_title" msgid="1955638862122232342">"Προειδοποίηση χρήσης δεδομένων"</string>
     <string name="data_usage_warning_body" msgid="2814673551471969954">"Αγγίξτε για προβολή χρήσης/ρυθμ."</string>
@@ -1467,7 +1466,7 @@
     <string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Να γίνεται ερώτηση για το PIN, πριν από το ξεκαρφίτσωμα"</string>
     <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Να γίνεται ερώτηση για το μοτίβο ξεκλειδώματος, πριν από το ξεκαρφίτσωμα"</string>
     <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Να γίνεται ερώτηση για τον κωδικό πρόσβασης, πριν από το ξεκαρφίτσωμα"</string>
-    <string name="dock_cropped_windows_text" msgid="6378424064779004428">"Το μέγεθος της εφαρμογής δεν είναι προσαρμόσιμο. Σύρετε προς τα κάτω με δύο δάχτυλα."</string>
+    <string name="dock_forced_resizable" msgid="5914261505436217520">"Δεν είναι δυνατή η λειτουργία της εφαρμογής με διαχωρισμό οθόνης."</string>
     <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"Η εφαρμογή δεν υποστηρίζει διαχωρισμό οθόνης."</string>
     <string name="package_installed_device_owner" msgid="8420696545959087545">"Εγκαταστάθηκε από το διαχειριστή σας"</string>
     <string name="package_updated_device_owner" msgid="8856631322440187071">"Ενημερώθηκε από το διαχειριστή σας"</string>
@@ -1541,7 +1540,7 @@
     <string name="importance_from_person" msgid="9160133597262938296">"Αυτό είναι σημαντικό λόγω των ατόμων που συμμετέχουν."</string>
     <string name="user_creation_account_exists" msgid="1942606193570143289">"Να επιτραπεί στην εφαρμογή <xliff:g id="APP">%1$s</xliff:g> να δημιουργήσει έναν νέο χρήστη με το λογαριασμό <xliff:g id="ACCOUNT">%2$s</xliff:g>;"</string>
     <string name="user_creation_adding" msgid="4482658054622099197">"Να επιτραπεί στην εφαρμογή <xliff:g id="APP">%1$s</xliff:g> να δημιουργήσει έναν νέο χρήστη με το λογαριασμό <xliff:g id="ACCOUNT">%2$s</xliff:g> (υπάρχει ήδη χρήστης με αυτόν το λογαριασμό);"</string>
-    <string name="language_selection_title" msgid="7181332986330337171">"Προτίμηση γλώσσας"</string>
+    <string name="language_selection_title" msgid="2680677278159281088">"Προσθήκη γλώσσας"</string>
     <string name="country_selection_title" msgid="2954859441620215513">"Προτίμηση περιοχής"</string>
     <string name="search_language_hint" msgid="7042102592055108574">"Εισαγ. όνομα γλώσσας"</string>
     <string name="language_picker_section_suggested" msgid="8414489646861640885">"Προτεινόμενες"</string>
@@ -1564,6 +1563,7 @@
     <string name="pin_target" msgid="3052256031352291362">"Καρφίτσωμα"</string>
     <string name="unpin_target" msgid="3556545602439143442">"Ξεκαρφίτσωμα"</string>
     <string name="app_info" msgid="6856026610594615344">"Πληροφορίες εφαρμογής"</string>
-    <!-- no translation found for negative_duration (5688706061127375131) -->
-    <skip />
+    <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="audit_safemode_notification" msgid="6351827251856877200">"Επαναφέρετε τις εργοστασιακές ρυθμίσεις για να χρησιμοποιήσετε αυτήν τη συσκευή κανονικά"</string>
+    <string name="audit_safemode_notification_details" msgid="1860601176690176413">"Αγγίξτε για να μάθετε περισσότερα."</string>
 </resources>
diff --git a/core/res/res/values-en-rAU/strings.xml b/core/res/res/values-en-rAU/strings.xml
index bcdad3b..ac7ad91 100644
--- a/core/res/res/values-en-rAU/strings.xml
+++ b/core/res/res/values-en-rAU/strings.xml
@@ -229,7 +229,6 @@
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Voice Assist"</string>
     <string name="global_action_lockdown" msgid="8751542514724332873">"Lock now"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
-    <string name="notification_children_count_bracketed" msgid="1769425473168347839">"(<xliff:g id="NOTIFICATIONCOUNT">%d</xliff:g>)"</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>
     <string name="safeMode" msgid="2788228061547930246">"Safe mode"</string>
@@ -1052,13 +1051,12 @@
     <string name="usb_notification_message" msgid="7347368030849048437">"Touch for more options."</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"USB debugging connected"</string>
     <string name="adb_active_notification_message" msgid="1016654627626476142">"Touch to disable USB debugging."</string>
+    <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Taking bug report…"</string>
     <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Share bug report?"</string>
     <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Sharing bug report…"</string>
-    <string name="share_remote_bugreport_notification_message" msgid="752583906074230920">"Your IT admin requested a bug report to help troubleshoot this device. Apps and data may be shared and your device may temporarily slow down."</string>
-    <string name="share_finished_remote_bugreport_notification_message" msgid="4627312060769912353">"Your IT admin requested a bug report to help troubleshoot this device. Apps and data may be shared."</string>
-    <string name="sharing_remote_bugreport_notification_message" msgid="673106383408474893">"This may temporarily slow down your device"</string>
-    <string name="share_remote_bugreport_notification_accept" msgid="8203856129078669677">"ACCEPT"</string>
-    <string name="share_remote_bugreport_notification_decline" msgid="6337969352057443969">"DECLINE"</string>
+    <string name="share_remote_bugreport_notification_message_finished" msgid="8610614010660772643">"Your IT admin requested a bug report to help troubleshoot this device. Apps and data may be shared."</string>
+    <string name="share_remote_bugreport_action" msgid="6249476773913384948">"SHARE"</string>
+    <string name="decline_remote_bugreport_action" msgid="6230987241608770062">"DECLINE"</string>
     <string name="select_input_method" msgid="8547250819326693584">"Change keyboard"</string>
     <string name="configure_input_methods" msgid="4769971288371946846">"Choose keyboards"</string>
     <string name="show_ime" msgid="2506087537466597099">"Keep it on screen while physical keyboard is active"</string>
@@ -1137,8 +1135,9 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Wallpaper"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Change wallpaper"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Notification listener"</string>
+    <string name="vr_listener_binding_label" msgid="4316591939343607306">"VR listener"</string>
     <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Condition provider"</string>
-    <string name="notification_assistant_binding_label" msgid="909456055569102952">"Notification assistant"</string>
+    <string name="notification_ranker_binding_label" msgid="774540592299064747">"Notification ranker service"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN activated"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN is activated by <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Touch to manage the network."</string>
@@ -1467,7 +1466,7 @@
     <string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Ask for PIN before unpinning"</string>
     <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Ask for unlock pattern before unpinning"</string>
     <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Ask for password before unpinning"</string>
-    <string name="dock_cropped_windows_text" msgid="6378424064779004428">"App is not resizeable, scroll it with two fingers."</string>
+    <string name="dock_forced_resizable" msgid="5914261505436217520">"App may not work with split-screen."</string>
     <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"App does not support split-screen."</string>
     <string name="package_installed_device_owner" msgid="8420696545959087545">"Installed by your administrator"</string>
     <string name="package_updated_device_owner" msgid="8856631322440187071">"Updated by your administrator"</string>
@@ -1541,7 +1540,7 @@
     <string name="importance_from_person" msgid="9160133597262938296">"This is important because of the people involved."</string>
     <string name="user_creation_account_exists" msgid="1942606193570143289">"Allow <xliff:g id="APP">%1$s</xliff:g> to create a new User with <xliff:g id="ACCOUNT">%2$s</xliff:g> ?"</string>
     <string name="user_creation_adding" msgid="4482658054622099197">"Allow <xliff:g id="APP">%1$s</xliff:g> to create a new User with <xliff:g id="ACCOUNT">%2$s</xliff:g> (a User with this account already exists) ?"</string>
-    <string name="language_selection_title" msgid="7181332986330337171">"Language preference"</string>
+    <string name="language_selection_title" msgid="2680677278159281088">"Add a language"</string>
     <string name="country_selection_title" msgid="2954859441620215513">"Region preference"</string>
     <string name="search_language_hint" msgid="7042102592055108574">"Type language name"</string>
     <string name="language_picker_section_suggested" msgid="8414489646861640885">"Suggested"</string>
@@ -1565,4 +1564,6 @@
     <string name="unpin_target" msgid="3556545602439143442">"Unpin"</string>
     <string name="app_info" msgid="6856026610594615344">"App info"</string>
     <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="audit_safemode_notification" msgid="6351827251856877200">"Restore this device to factory settings to use normally"</string>
+    <string name="audit_safemode_notification_details" msgid="1860601176690176413">"Touch to find out more."</string>
 </resources>
diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml
index bcdad3b..ac7ad91 100644
--- a/core/res/res/values-en-rGB/strings.xml
+++ b/core/res/res/values-en-rGB/strings.xml
@@ -229,7 +229,6 @@
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Voice Assist"</string>
     <string name="global_action_lockdown" msgid="8751542514724332873">"Lock now"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
-    <string name="notification_children_count_bracketed" msgid="1769425473168347839">"(<xliff:g id="NOTIFICATIONCOUNT">%d</xliff:g>)"</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>
     <string name="safeMode" msgid="2788228061547930246">"Safe mode"</string>
@@ -1052,13 +1051,12 @@
     <string name="usb_notification_message" msgid="7347368030849048437">"Touch for more options."</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"USB debugging connected"</string>
     <string name="adb_active_notification_message" msgid="1016654627626476142">"Touch to disable USB debugging."</string>
+    <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Taking bug report…"</string>
     <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Share bug report?"</string>
     <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Sharing bug report…"</string>
-    <string name="share_remote_bugreport_notification_message" msgid="752583906074230920">"Your IT admin requested a bug report to help troubleshoot this device. Apps and data may be shared and your device may temporarily slow down."</string>
-    <string name="share_finished_remote_bugreport_notification_message" msgid="4627312060769912353">"Your IT admin requested a bug report to help troubleshoot this device. Apps and data may be shared."</string>
-    <string name="sharing_remote_bugreport_notification_message" msgid="673106383408474893">"This may temporarily slow down your device"</string>
-    <string name="share_remote_bugreport_notification_accept" msgid="8203856129078669677">"ACCEPT"</string>
-    <string name="share_remote_bugreport_notification_decline" msgid="6337969352057443969">"DECLINE"</string>
+    <string name="share_remote_bugreport_notification_message_finished" msgid="8610614010660772643">"Your IT admin requested a bug report to help troubleshoot this device. Apps and data may be shared."</string>
+    <string name="share_remote_bugreport_action" msgid="6249476773913384948">"SHARE"</string>
+    <string name="decline_remote_bugreport_action" msgid="6230987241608770062">"DECLINE"</string>
     <string name="select_input_method" msgid="8547250819326693584">"Change keyboard"</string>
     <string name="configure_input_methods" msgid="4769971288371946846">"Choose keyboards"</string>
     <string name="show_ime" msgid="2506087537466597099">"Keep it on screen while physical keyboard is active"</string>
@@ -1137,8 +1135,9 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Wallpaper"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Change wallpaper"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Notification listener"</string>
+    <string name="vr_listener_binding_label" msgid="4316591939343607306">"VR listener"</string>
     <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Condition provider"</string>
-    <string name="notification_assistant_binding_label" msgid="909456055569102952">"Notification assistant"</string>
+    <string name="notification_ranker_binding_label" msgid="774540592299064747">"Notification ranker service"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN activated"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN is activated by <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Touch to manage the network."</string>
@@ -1467,7 +1466,7 @@
     <string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Ask for PIN before unpinning"</string>
     <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Ask for unlock pattern before unpinning"</string>
     <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Ask for password before unpinning"</string>
-    <string name="dock_cropped_windows_text" msgid="6378424064779004428">"App is not resizeable, scroll it with two fingers."</string>
+    <string name="dock_forced_resizable" msgid="5914261505436217520">"App may not work with split-screen."</string>
     <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"App does not support split-screen."</string>
     <string name="package_installed_device_owner" msgid="8420696545959087545">"Installed by your administrator"</string>
     <string name="package_updated_device_owner" msgid="8856631322440187071">"Updated by your administrator"</string>
@@ -1541,7 +1540,7 @@
     <string name="importance_from_person" msgid="9160133597262938296">"This is important because of the people involved."</string>
     <string name="user_creation_account_exists" msgid="1942606193570143289">"Allow <xliff:g id="APP">%1$s</xliff:g> to create a new User with <xliff:g id="ACCOUNT">%2$s</xliff:g> ?"</string>
     <string name="user_creation_adding" msgid="4482658054622099197">"Allow <xliff:g id="APP">%1$s</xliff:g> to create a new User with <xliff:g id="ACCOUNT">%2$s</xliff:g> (a User with this account already exists) ?"</string>
-    <string name="language_selection_title" msgid="7181332986330337171">"Language preference"</string>
+    <string name="language_selection_title" msgid="2680677278159281088">"Add a language"</string>
     <string name="country_selection_title" msgid="2954859441620215513">"Region preference"</string>
     <string name="search_language_hint" msgid="7042102592055108574">"Type language name"</string>
     <string name="language_picker_section_suggested" msgid="8414489646861640885">"Suggested"</string>
@@ -1565,4 +1564,6 @@
     <string name="unpin_target" msgid="3556545602439143442">"Unpin"</string>
     <string name="app_info" msgid="6856026610594615344">"App info"</string>
     <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="audit_safemode_notification" msgid="6351827251856877200">"Restore this device to factory settings to use normally"</string>
+    <string name="audit_safemode_notification_details" msgid="1860601176690176413">"Touch to find out more."</string>
 </resources>
diff --git a/core/res/res/values-en-rIN/strings.xml b/core/res/res/values-en-rIN/strings.xml
index bcdad3b..ac7ad91 100644
--- a/core/res/res/values-en-rIN/strings.xml
+++ b/core/res/res/values-en-rIN/strings.xml
@@ -229,7 +229,6 @@
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Voice Assist"</string>
     <string name="global_action_lockdown" msgid="8751542514724332873">"Lock now"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
-    <string name="notification_children_count_bracketed" msgid="1769425473168347839">"(<xliff:g id="NOTIFICATIONCOUNT">%d</xliff:g>)"</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>
     <string name="safeMode" msgid="2788228061547930246">"Safe mode"</string>
@@ -1052,13 +1051,12 @@
     <string name="usb_notification_message" msgid="7347368030849048437">"Touch for more options."</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"USB debugging connected"</string>
     <string name="adb_active_notification_message" msgid="1016654627626476142">"Touch to disable USB debugging."</string>
+    <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Taking bug report…"</string>
     <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Share bug report?"</string>
     <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Sharing bug report…"</string>
-    <string name="share_remote_bugreport_notification_message" msgid="752583906074230920">"Your IT admin requested a bug report to help troubleshoot this device. Apps and data may be shared and your device may temporarily slow down."</string>
-    <string name="share_finished_remote_bugreport_notification_message" msgid="4627312060769912353">"Your IT admin requested a bug report to help troubleshoot this device. Apps and data may be shared."</string>
-    <string name="sharing_remote_bugreport_notification_message" msgid="673106383408474893">"This may temporarily slow down your device"</string>
-    <string name="share_remote_bugreport_notification_accept" msgid="8203856129078669677">"ACCEPT"</string>
-    <string name="share_remote_bugreport_notification_decline" msgid="6337969352057443969">"DECLINE"</string>
+    <string name="share_remote_bugreport_notification_message_finished" msgid="8610614010660772643">"Your IT admin requested a bug report to help troubleshoot this device. Apps and data may be shared."</string>
+    <string name="share_remote_bugreport_action" msgid="6249476773913384948">"SHARE"</string>
+    <string name="decline_remote_bugreport_action" msgid="6230987241608770062">"DECLINE"</string>
     <string name="select_input_method" msgid="8547250819326693584">"Change keyboard"</string>
     <string name="configure_input_methods" msgid="4769971288371946846">"Choose keyboards"</string>
     <string name="show_ime" msgid="2506087537466597099">"Keep it on screen while physical keyboard is active"</string>
@@ -1137,8 +1135,9 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Wallpaper"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Change wallpaper"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Notification listener"</string>
+    <string name="vr_listener_binding_label" msgid="4316591939343607306">"VR listener"</string>
     <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Condition provider"</string>
-    <string name="notification_assistant_binding_label" msgid="909456055569102952">"Notification assistant"</string>
+    <string name="notification_ranker_binding_label" msgid="774540592299064747">"Notification ranker service"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN activated"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN is activated by <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Touch to manage the network."</string>
@@ -1467,7 +1466,7 @@
     <string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Ask for PIN before unpinning"</string>
     <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Ask for unlock pattern before unpinning"</string>
     <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Ask for password before unpinning"</string>
-    <string name="dock_cropped_windows_text" msgid="6378424064779004428">"App is not resizeable, scroll it with two fingers."</string>
+    <string name="dock_forced_resizable" msgid="5914261505436217520">"App may not work with split-screen."</string>
     <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"App does not support split-screen."</string>
     <string name="package_installed_device_owner" msgid="8420696545959087545">"Installed by your administrator"</string>
     <string name="package_updated_device_owner" msgid="8856631322440187071">"Updated by your administrator"</string>
@@ -1541,7 +1540,7 @@
     <string name="importance_from_person" msgid="9160133597262938296">"This is important because of the people involved."</string>
     <string name="user_creation_account_exists" msgid="1942606193570143289">"Allow <xliff:g id="APP">%1$s</xliff:g> to create a new User with <xliff:g id="ACCOUNT">%2$s</xliff:g> ?"</string>
     <string name="user_creation_adding" msgid="4482658054622099197">"Allow <xliff:g id="APP">%1$s</xliff:g> to create a new User with <xliff:g id="ACCOUNT">%2$s</xliff:g> (a User with this account already exists) ?"</string>
-    <string name="language_selection_title" msgid="7181332986330337171">"Language preference"</string>
+    <string name="language_selection_title" msgid="2680677278159281088">"Add a language"</string>
     <string name="country_selection_title" msgid="2954859441620215513">"Region preference"</string>
     <string name="search_language_hint" msgid="7042102592055108574">"Type language name"</string>
     <string name="language_picker_section_suggested" msgid="8414489646861640885">"Suggested"</string>
@@ -1565,4 +1564,6 @@
     <string name="unpin_target" msgid="3556545602439143442">"Unpin"</string>
     <string name="app_info" msgid="6856026610594615344">"App info"</string>
     <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="audit_safemode_notification" msgid="6351827251856877200">"Restore this device to factory settings to use normally"</string>
+    <string name="audit_safemode_notification_details" msgid="1860601176690176413">"Touch to find out more."</string>
 </resources>
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index 0ea627dd..4623d77 100644
--- a/core/res/res/values-es-rUS/strings.xml
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -229,7 +229,6 @@
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Asistente voz"</string>
     <string name="global_action_lockdown" msgid="8751542514724332873">"Bloquear ahora"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
-    <string name="notification_children_count_bracketed" msgid="1769425473168347839">"(<xliff:g id="NOTIFICATIONCOUNT">%d</xliff:g>)"</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>
     <string name="safeMode" msgid="2788228061547930246">"Modo seguro"</string>
@@ -239,7 +238,7 @@
     <string name="permgrouplab_contacts" msgid="3657758145679177612">"Contactos"</string>
     <string name="permgroupdesc_contacts" msgid="6951499528303668046">"acceder a los contactos"</string>
     <string name="permgrouplab_location" msgid="7275582855722310164">"Ubicación"</string>
-    <string name="permgroupdesc_location" msgid="1346617465127855033">"acceso a la ubicación de este dispositivo"</string>
+    <string name="permgroupdesc_location" msgid="1346617465127855033">"acceder a la ubicación de este dispositivo"</string>
     <string name="permgrouplab_calendar" msgid="5863508437783683902">"Calendario"</string>
     <string name="permgroupdesc_calendar" msgid="3889615280211184106">"acceder al calendario"</string>
     <string name="permgrouplab_sms" msgid="228308803364967808">"SMS"</string>
@@ -1052,13 +1051,12 @@
     <string name="usb_notification_message" msgid="7347368030849048437">"Toca para ver más opciones."</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"Depuración por USB conectada"</string>
     <string name="adb_active_notification_message" msgid="1016654627626476142">"Toca para desactivar la depuración por USB."</string>
+    <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Realizando un informe de errores…"</string>
     <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"¿Compartir informe de errores?"</string>
     <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Compartiendo informe de errores…"</string>
-    <string name="share_remote_bugreport_notification_message" msgid="752583906074230920">"El administrador de TI solicitó un informe de errores para ayudar a solucionar los problemas de este dispositivo. Es posible que se compartan apps y datos, y que el dispositivo se ralentice temporalmente."</string>
-    <string name="share_finished_remote_bugreport_notification_message" msgid="4627312060769912353">"El administrador de TI solicitó un informe de errores para ayudar a solucionar los problemas de este dispositivo. Es posible que se compartan apps y datos."</string>
-    <string name="sharing_remote_bugreport_notification_message" msgid="673106383408474893">"Es posible que tu dispositivo se ralentice temporalmente"</string>
-    <string name="share_remote_bugreport_notification_accept" msgid="8203856129078669677">"ACEPTAR"</string>
-    <string name="share_remote_bugreport_notification_decline" msgid="6337969352057443969">"RECHAZAR"</string>
+    <string name="share_remote_bugreport_notification_message_finished" msgid="8610614010660772643">"El administrador de TI solicitó un informe de errores para solucionar los problemas de este dispositivo. Es posible que se compartan apps y datos."</string>
+    <string name="share_remote_bugreport_action" msgid="6249476773913384948">"COMPARTIR"</string>
+    <string name="decline_remote_bugreport_action" msgid="6230987241608770062">"RECHAZAR"</string>
     <string name="select_input_method" msgid="8547250819326693584">"Cambiar el teclado"</string>
     <string name="configure_input_methods" msgid="4769971288371946846">"Seleccionar teclados"</string>
     <string name="show_ime" msgid="2506087537466597099">"Mantener en la pantalla cuando el teclado físico está activo"</string>
@@ -1137,8 +1135,9 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Papel tapiz"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Cambiar fondo de pantalla"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Agente de escucha de notificaciones"</string>
+    <string name="vr_listener_binding_label" msgid="4316591939343607306">"Procesador de realidad virtual"</string>
     <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Proveedor de condiciones"</string>
-    <string name="notification_assistant_binding_label" msgid="909456055569102952">"Asistente de notificaciones"</string>
+    <string name="notification_ranker_binding_label" msgid="774540592299064747">"Servicio de clasificación de notificaciones"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN activada"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN está activado por <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Toca para administrar la red."</string>
@@ -1467,7 +1466,7 @@
     <string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Solicitar PIN para quitar fijación"</string>
     <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Solicitar patrón de desbloqueo para quitar fijación"</string>
     <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Solicitar contraseña para quitar fijación"</string>
-    <string name="dock_cropped_windows_text" msgid="6378424064779004428">"No se puede modificar el tamaño de la app. Desplázala con dos dedos."</string>
+    <string name="dock_forced_resizable" msgid="5914261505436217520">"Es posible que la app no funcione en el modo de pantalla dividida."</string>
     <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"La app no es compatible con la función de pantalla dividida."</string>
     <string name="package_installed_device_owner" msgid="8420696545959087545">"Lo instaló el administrador."</string>
     <string name="package_updated_device_owner" msgid="8856631322440187071">"Actualizado por el administrador"</string>
@@ -1541,7 +1540,7 @@
     <string name="importance_from_person" msgid="9160133597262938296">"Es importante debido a las personas involucradas."</string>
     <string name="user_creation_account_exists" msgid="1942606193570143289">"¿Quieres permitir que <xliff:g id="APP">%1$s</xliff:g> cree un usuario nuevo con <xliff:g id="ACCOUNT">%2$s</xliff:g>?"</string>
     <string name="user_creation_adding" msgid="4482658054622099197">"¿Quieres permitir que <xliff:g id="APP">%1$s</xliff:g> cree un usuario nuevo con <xliff:g id="ACCOUNT">%2$s</xliff:g>? (Ya existe un usuario con esta cuenta)"</string>
-    <string name="language_selection_title" msgid="7181332986330337171">"Preferencia de idioma"</string>
+    <string name="language_selection_title" msgid="2680677278159281088">"Agregar un idioma"</string>
     <string name="country_selection_title" msgid="2954859441620215513">"Preferencia de región"</string>
     <string name="search_language_hint" msgid="7042102592055108574">"Nombre del idioma"</string>
     <string name="language_picker_section_suggested" msgid="8414489646861640885">"Sugeridos"</string>
@@ -1564,6 +1563,7 @@
     <string name="pin_target" msgid="3052256031352291362">"Fijar"</string>
     <string name="unpin_target" msgid="3556545602439143442">"No fijar"</string>
     <string name="app_info" msgid="6856026610594615344">"Información de la app"</string>
-    <!-- no translation found for negative_duration (5688706061127375131) -->
-    <skip />
+    <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="audit_safemode_notification" msgid="6351827251856877200">"Restablece la configuración de fábrica para usar este dispositivo con normalidad"</string>
+    <string name="audit_safemode_notification_details" msgid="1860601176690176413">"Toca para obtener más información."</string>
 </resources>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index cf4c4ab..d44c07e 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -229,7 +229,6 @@
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Asistente voz"</string>
     <string name="global_action_lockdown" msgid="8751542514724332873">"Bloquear ahora"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"&gt; 999"</string>
-    <string name="notification_children_count_bracketed" msgid="1769425473168347839">"(<xliff:g id="NOTIFICATIONCOUNT">%d</xliff:g>)"</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>
     <string name="safeMode" msgid="2788228061547930246">"Modo seguro"</string>
@@ -276,7 +275,7 @@
     <string name="permdesc_install_shortcut" msgid="8341295916286736996">"Permite que una aplicación añada accesos directos a la pantalla de inicio sin intervención del usuario."</string>
     <string name="permlab_uninstall_shortcut" msgid="4729634524044003699">"desinstalar accesos directos"</string>
     <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">"redireccionar llamadas salientes"</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>
     <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>
@@ -1052,13 +1051,12 @@
     <string name="usb_notification_message" msgid="7347368030849048437">"Toca para obtener más opciones"</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"Depuración USB habilitada"</string>
     <string name="adb_active_notification_message" msgid="1016654627626476142">"Toca aquí para inhabilitarla"</string>
+    <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Creando informe de errores…"</string>
     <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"¿Compartir informe de errores?"</string>
     <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Compartiendo informe de errores…"</string>
-    <string name="share_remote_bugreport_notification_message" msgid="752583906074230920">"Tu administrador de TI ha solicitado un informe de errores para solucionar problemas de este dispositivo. Es posible que se compartan las aplicaciones y los datos. Puede que el dispositivo funcione más lento de forma temporal."</string>
-    <string name="share_finished_remote_bugreport_notification_message" msgid="4627312060769912353">"Tu administrador de TI ha solicitado un informe de errores para solucionar problemas de este dispositivo. Es posible que se compartan las aplicaciones y los datos."</string>
-    <string name="sharing_remote_bugreport_notification_message" msgid="673106383408474893">"Puede que el dispositivo funcione más lento de forma temporal"</string>
-    <string name="share_remote_bugreport_notification_accept" msgid="8203856129078669677">"ACEPTAR"</string>
-    <string name="share_remote_bugreport_notification_decline" msgid="6337969352057443969">"RECHAZAR"</string>
+    <string name="share_remote_bugreport_notification_message_finished" msgid="8610614010660772643">"Tu administrador de TI ha solicitado un informe de errores para solucionar problemas de este dispositivo. Es posible que se compartan las aplicaciones y los datos."</string>
+    <string name="share_remote_bugreport_action" msgid="6249476773913384948">"COMPARTIR"</string>
+    <string name="decline_remote_bugreport_action" msgid="6230987241608770062">"RECHAZAR"</string>
     <string name="select_input_method" msgid="8547250819326693584">"Cambiar teclado"</string>
     <string name="configure_input_methods" msgid="4769971288371946846">"Elegir teclados"</string>
     <string name="show_ime" msgid="2506087537466597099">"Debe seguir en pantalla mientras el teclado físico esté activo"</string>
@@ -1137,8 +1135,9 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Fondo de pantalla"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Cambiar fondo de pantalla"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Detector de notificaciones"</string>
+    <string name="vr_listener_binding_label" msgid="4316591939343607306">"Procesador de Realidad Virtual"</string>
     <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Proveedor de condiciones"</string>
-    <string name="notification_assistant_binding_label" msgid="909456055569102952">"Asistente de notificaciones"</string>
+    <string name="notification_ranker_binding_label" msgid="774540592299064747">"Servicio de clasificación de notificaciones"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN activada"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN activada por <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Toca para administrar la red."</string>
@@ -1447,7 +1446,7 @@
       <item quantity="one">Vuelve a intentarlo en 1 segundo</item>
     </plurals>
     <string name="restr_pin_try_later" msgid="973144472490532377">"Volver a intentar más tarde"</string>
-    <string name="immersive_cling_title" msgid="8394201622932303336">"Mostrando pantalla completa"</string>
+    <string name="immersive_cling_title" msgid="8394201622932303336">"Modo de pantalla completa"</string>
     <string name="immersive_cling_description" msgid="3482371193207536040">"Para salir, desliza hacia abajo desde arriba."</string>
     <string name="immersive_cling_positive" msgid="5016839404568297683">"Entendido"</string>
     <string name="done_label" msgid="2093726099505892398">"Listo"</string>
@@ -1467,7 +1466,7 @@
     <string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Solicitar PIN para desactivar"</string>
     <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Solicitar patrón de desbloqueo para desactivar"</string>
     <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Solicitar contraseña para desactivar"</string>
-    <string name="dock_cropped_windows_text" msgid="6378424064779004428">"No se puede cambiar el tamaño de la aplicación, desplázala con dos dedos."</string>
+    <string name="dock_forced_resizable" msgid="5914261505436217520">"Es posible que la aplicación no funcione con la pantalla dividida."</string>
     <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"La aplicación no admite la pantalla dividida."</string>
     <string name="package_installed_device_owner" msgid="8420696545959087545">"Instalado por tu administrador"</string>
     <string name="package_updated_device_owner" msgid="8856631322440187071">"Actualizado por tu administrador"</string>
@@ -1541,7 +1540,7 @@
     <string name="importance_from_person" msgid="9160133597262938296">"Esto es importante por los usuarios implicados."</string>
     <string name="user_creation_account_exists" msgid="1942606193570143289">"¿Permitir que <xliff:g id="APP">%1$s</xliff:g> cree un usuario con la cuenta <xliff:g id="ACCOUNT">%2$s</xliff:g>?"</string>
     <string name="user_creation_adding" msgid="4482658054622099197">"¿Permitir que <xliff:g id="APP">%1$s</xliff:g> cree un usuario con la cuenta <xliff:g id="ACCOUNT">%2$s</xliff:g> (ya existe un usuario con esta cuenta)?"</string>
-    <string name="language_selection_title" msgid="7181332986330337171">"Preferencia de idioma"</string>
+    <string name="language_selection_title" msgid="2680677278159281088">"Añade un idioma"</string>
     <string name="country_selection_title" msgid="2954859441620215513">"Preferencia de región"</string>
     <string name="search_language_hint" msgid="7042102592055108574">"Nombre de idioma"</string>
     <string name="language_picker_section_suggested" msgid="8414489646861640885">"Sugeridos"</string>
@@ -1568,6 +1567,7 @@
     <string name="pin_target" msgid="3052256031352291362">"Fijar"</string>
     <string name="unpin_target" msgid="3556545602439143442">"No fijar"</string>
     <string name="app_info" msgid="6856026610594615344">"Información de la aplicación"</string>
-    <!-- no translation found for negative_duration (5688706061127375131) -->
-    <skip />
+    <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="audit_safemode_notification" msgid="6351827251856877200">"Restablece los datos de fábrica para utilizar este dispositivo con normalidad"</string>
+    <string name="audit_safemode_notification_details" msgid="1860601176690176413">"Toca para obtener más información."</string>
 </resources>
diff --git a/core/res/res/values-et-rEE/strings.xml b/core/res/res/values-et-rEE/strings.xml
index 9d879e1..c35d222 100644
--- a/core/res/res/values-et-rEE/strings.xml
+++ b/core/res/res/values-et-rEE/strings.xml
@@ -229,7 +229,6 @@
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Häälabi"</string>
     <string name="global_action_lockdown" msgid="8751542514724332873">"Lukusta kohe"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
-    <string name="notification_children_count_bracketed" msgid="1769425473168347839">"(<xliff:g id="NOTIFICATIONCOUNT">%d</xliff:g>)"</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>
     <string name="safeMode" msgid="2788228061547930246">"Turvarežiim"</string>
@@ -1052,13 +1051,12 @@
     <string name="usb_notification_message" msgid="7347368030849048437">"Puudutage rohkemate valikute kuvamiseks."</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"USB-silumine ühendatud"</string>
     <string name="adb_active_notification_message" msgid="1016654627626476142">"Puudutage USB-silumise keelamiseks."</string>
+    <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Veaaruande võtmine …"</string>
     <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Kas jagada veaaruannet?"</string>
     <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Veaaruande jagamine …"</string>
-    <string name="share_remote_bugreport_notification_message" msgid="752583906074230920">"IT-administraator taotles veaaruannet, mis aitaks seadmes vigu otsida. Rakendusi ja andmeid võidakse jagada ja see võib ajutiselt teie seadet aeglustada."</string>
-    <string name="share_finished_remote_bugreport_notification_message" msgid="4627312060769912353">"IT-administraator taotles veaaruannet, mis aitaks seadmes vigu otsida. Rakendusi ja andmeid võidakse jagada."</string>
-    <string name="sharing_remote_bugreport_notification_message" msgid="673106383408474893">"See võib ajutiselt teie seadet aeglustada"</string>
-    <string name="share_remote_bugreport_notification_accept" msgid="8203856129078669677">"NÕUSTU"</string>
-    <string name="share_remote_bugreport_notification_decline" msgid="6337969352057443969">"KEELDU"</string>
+    <string name="share_remote_bugreport_notification_message_finished" msgid="8610614010660772643">"IT-administraator taotles veaaruannet, mis aitaks seadmes vigu otsida. Rakendusi ja andmeid võidakse jagada."</string>
+    <string name="share_remote_bugreport_action" msgid="6249476773913384948">"JAGA"</string>
+    <string name="decline_remote_bugreport_action" msgid="6230987241608770062">"KEELDU"</string>
     <string name="select_input_method" msgid="8547250819326693584">"Klaviatuuri muutmine"</string>
     <string name="configure_input_methods" msgid="4769971288371946846">"Vali klaviatuurid"</string>
     <string name="show_ime" msgid="2506087537466597099">"Hoia seda ekraanil, kui füüsiline klaviatuur on aktiivne"</string>
@@ -1137,8 +1135,9 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Taustapilt"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Muutke taustapilti"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Märguannete kuulamisteenus"</string>
+    <string name="vr_listener_binding_label" msgid="4316591939343607306">"Virtuaalreaalses režiimis kuulaja"</string>
     <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Tingimuse pakkuja"</string>
-    <string name="notification_assistant_binding_label" msgid="909456055569102952">"Märguannete abi"</string>
+    <string name="notification_ranker_binding_label" msgid="774540592299064747">"Märguannete tähtsuse määramise teenus"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN on aktiveeritud"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN-i aktiveeris <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Võrgu haldamiseks puudutage."</string>
@@ -1467,7 +1466,7 @@
     <string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Enne vabastamist küsi PIN-koodi"</string>
     <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Enne vabastamist küsi avamismustrit"</string>
     <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Enne vabastamist küsi parooli"</string>
-    <string name="dock_cropped_windows_text" msgid="6378424064779004428">"Rakenduse suurust ei saa muuta. Kerige kahe sõrmega."</string>
+    <string name="dock_forced_resizable" msgid="5914261505436217520">"Rakendus ei pruugi poolitatud ekraaniga töötada."</string>
     <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"Rakendus ei toeta jagatud ekraani."</string>
     <string name="package_installed_device_owner" msgid="8420696545959087545">"Installis teie administraator"</string>
     <string name="package_updated_device_owner" msgid="8856631322440187071">"Värskendas administraator"</string>
@@ -1541,7 +1540,7 @@
     <string name="importance_from_person" msgid="9160133597262938296">"See on tähtis osalevate inimeste tõttu."</string>
     <string name="user_creation_account_exists" msgid="1942606193570143289">"Kas lubada rakendusel <xliff:g id="APP">%1$s</xliff:g> luua uus kasutaja kontoga <xliff:g id="ACCOUNT">%2$s</xliff:g>?"</string>
     <string name="user_creation_adding" msgid="4482658054622099197">"Kas lubada rakendusel <xliff:g id="APP">%1$s</xliff:g> luua uus kasutaja kontoga <xliff:g id="ACCOUNT">%2$s</xliff:g> (selle kontoga kasutaja on juba olemas)?"</string>
-    <string name="language_selection_title" msgid="7181332986330337171">"Keele-eelistus"</string>
+    <string name="language_selection_title" msgid="2680677278159281088">"Keele lisamine"</string>
     <string name="country_selection_title" msgid="2954859441620215513">"Piirkonnaeelistus"</string>
     <string name="search_language_hint" msgid="7042102592055108574">"Sisestage keele nimi"</string>
     <string name="language_picker_section_suggested" msgid="8414489646861640885">"Soovitatud"</string>
@@ -1564,6 +1563,7 @@
     <string name="pin_target" msgid="3052256031352291362">"Kinnita"</string>
     <string name="unpin_target" msgid="3556545602439143442">"Vabasta"</string>
     <string name="app_info" msgid="6856026610594615344">"Rakenduse teave"</string>
-    <!-- no translation found for negative_duration (5688706061127375131) -->
-    <skip />
+    <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="audit_safemode_notification" msgid="6351827251856877200">"Seadme tavapäraseks kasutamiseks lähtestage see tehaseseadetele"</string>
+    <string name="audit_safemode_notification_details" msgid="1860601176690176413">"Lisateabe saamiseks puudutage."</string>
 </resources>
diff --git a/core/res/res/values-eu-rES/strings.xml b/core/res/res/values-eu-rES/strings.xml
index f43cd8c..bb83a9e 100644
--- a/core/res/res/values-eu-rES/strings.xml
+++ b/core/res/res/values-eu-rES/strings.xml
@@ -229,7 +229,6 @@
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Ahots-laguntza"</string>
     <string name="global_action_lockdown" msgid="8751542514724332873">"Blokeatu"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
-    <string name="notification_children_count_bracketed" msgid="1769425473168347839">"(<xliff:g id="NOTIFICATIONCOUNT">%d</xliff:g>)"</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>
     <string name="safeMode" msgid="2788228061547930246">"Modu segurua"</string>
@@ -1052,13 +1051,12 @@
     <string name="usb_notification_message" msgid="7347368030849048437">"Ukitu aukera gehiago ikusteko."</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"USB arazketa konektatuta"</string>
     <string name="adb_active_notification_message" msgid="1016654627626476142">"USB arazketa desgaitzeko, ukitu hau."</string>
+    <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Akatsen txostena sortzen…"</string>
     <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Akatsen txostena partekatu nahi duzu?"</string>
     <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Akatsen txostena partekatzen…"</string>
-    <string name="share_remote_bugreport_notification_message" msgid="752583906074230920">"IKT administratzaileak akatsen txostena eskatu du gailuko arazoa konpontzen laguntzeko. Baliteke aplikazioak eta datuak partekatzea, eta agian motelago ibiliko da gailua aldi batez."</string>
-    <string name="share_finished_remote_bugreport_notification_message" msgid="4627312060769912353">"IKT administratzaileak akatsen txostena eskatu du gailuko arazoa konpontzeko. Baliteke aplikazioak eta datuak partekatzea."</string>
-    <string name="sharing_remote_bugreport_notification_message" msgid="673106383408474893">"Agian motelago ibiliko da gailua aldi batez"</string>
-    <string name="share_remote_bugreport_notification_accept" msgid="8203856129078669677">"ONARTU"</string>
-    <string name="share_remote_bugreport_notification_decline" msgid="6337969352057443969">"BAZTERTU"</string>
+    <string name="share_remote_bugreport_notification_message_finished" msgid="8610614010660772643">"IKT administratzaileak akatsen txostena eskatu du gailuko arazoa konpontzeko. Baliteke aplikazioak eta datuak partekatzea."</string>
+    <string name="share_remote_bugreport_action" msgid="6249476773913384948">"PARTEKATU"</string>
+    <string name="decline_remote_bugreport_action" msgid="6230987241608770062">"BAZTERTU"</string>
     <string name="select_input_method" msgid="8547250819326693584">"Aldatu teklatua"</string>
     <string name="configure_input_methods" msgid="4769971288371946846">"Aukeratu teklatuak"</string>
     <string name="show_ime" msgid="2506087537466597099">"Erakutsi pantailan teklatu fisikoa aktibo dagoen bitartean"</string>
@@ -1137,8 +1135,9 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Horma-papera"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Aldatu horma-papera"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Jakinarazpenak hautemateko zerbitzua"</string>
+    <string name="vr_listener_binding_label" msgid="4316591939343607306">"Errealitate birtualeko hautemailea"</string>
     <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Baldintza-hornitzailea"</string>
-    <string name="notification_assistant_binding_label" msgid="909456055569102952">"Jakinarazpenen laguntzailea"</string>
+    <string name="notification_ranker_binding_label" msgid="774540592299064747">"Jakinarazpenen sailkapen-zerbitzua"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN eginbidea aktibatuta"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"<xliff:g id="APP">%s</xliff:g> aplikazioak VPN konexioa aktibatu du"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Ukitu sarea kudeatzeko."</string>
@@ -1467,8 +1466,8 @@
     <string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Eskatu PIN kodea aingura kendu aurretik"</string>
     <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Eskatu desblokeatzeko eredua aingura kendu aurretik"</string>
     <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Eskatu pasahitza aingura kendu aurretik"</string>
-    <string name="dock_cropped_windows_text" msgid="6378424064779004428">"Ezin da aldatu aplikazioaren tamaina. Erabili bi hatz aplikazioan gora eta behera egiteko."</string>
-    <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"Aplikazioak ez du onartzen pantaila banatua"</string>
+    <string name="dock_forced_resizable" msgid="5914261505436217520">"Baliteke aplikazioak ez funtzionatzea pantaila zatituan."</string>
+    <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"Aplikazioak ez du onartzen pantaila zatitua"</string>
     <string name="package_installed_device_owner" msgid="8420696545959087545">"Administratzaileak instalatu du"</string>
     <string name="package_updated_device_owner" msgid="8856631322440187071">"Administratzaileak eguneratu du"</string>
     <string name="package_deleted_device_owner" msgid="7650577387493101353">"Administratzaileak ezabatu du"</string>
@@ -1537,11 +1536,11 @@
       <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> hautatuta</item>
       <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> hautatuta</item>
     </plurals>
-    <string name="importance_from_user" msgid="7318955817386549931">"Zuk ezarri zenuen jakinarazpen hauen garrantzia."</string>
+    <string name="importance_from_user" msgid="7318955817386549931">"Zuk ezarri duzu jakinarazpen hauen garrantzia."</string>
     <string name="importance_from_person" msgid="9160133597262938296">"Garrantzitsua da eragiten dien pertsonengatik."</string>
     <string name="user_creation_account_exists" msgid="1942606193570143289">"<xliff:g id="APP">%1$s</xliff:g> aplikazioari <xliff:g id="ACCOUNT">%2$s</xliff:g> kontua duen erabiltzailea sortzea baimendu nahi diozu?"</string>
     <string name="user_creation_adding" msgid="4482658054622099197">"<xliff:g id="APP">%1$s</xliff:g> aplikazioari <xliff:g id="ACCOUNT">%2$s</xliff:g> kontua duen erabiltzailea sortzea baimendu nahi diozu? (Badago kontu hori duen erabiltzaile bat)"</string>
-    <string name="language_selection_title" msgid="7181332986330337171">"Hizkuntza-hobespena"</string>
+    <string name="language_selection_title" msgid="2680677278159281088">"Gehitu hizkuntza"</string>
     <string name="country_selection_title" msgid="2954859441620215513">"Lurralde-hobespena"</string>
     <string name="search_language_hint" msgid="7042102592055108574">"Adierazi hizkuntza"</string>
     <string name="language_picker_section_suggested" msgid="8414489646861640885">"Iradokitakoak"</string>
@@ -1565,4 +1564,6 @@
     <string name="unpin_target" msgid="3556545602439143442">"Kendu aingura"</string>
     <string name="app_info" msgid="6856026610594615344">"Aplikazioari buruzko informazioa"</string>
     <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="audit_safemode_notification" msgid="6351827251856877200">"Berrezarri jatorrizko egoerara gailua ohi bezala erabiltzen jarraitu ahal izateko"</string>
+    <string name="audit_safemode_notification_details" msgid="1860601176690176413">"Ukitu informazio gehiago lortzeko."</string>
 </resources>
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index 3237fec..eeab6d3 100644
--- a/core/res/res/values-fa/strings.xml
+++ b/core/res/res/values-fa/strings.xml
@@ -229,7 +229,6 @@
     <string name="global_action_voice_assist" msgid="7751191495200504480">"دستیار صوتی"</string>
     <string name="global_action_lockdown" msgid="8751542514724332873">"اکنون قفل شود"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"بیشتر از 999"</string>
-    <string name="notification_children_count_bracketed" msgid="1769425473168347839">"(<xliff:g id="NOTIFICATIONCOUNT">%d</xliff:g>)"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"محتواها پنهان هستند"</string>
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"محتوا بر اساس خط‌مشی پنهان شده است"</string>
     <string name="safeMode" msgid="2788228061547930246">"حالت ایمن"</string>
@@ -1052,13 +1051,12 @@
     <string name="usb_notification_message" msgid="7347368030849048437">"برای گزینه‌های بیشتر لمس کنید."</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"‏اشکال‌زدایی USB متصل شد"</string>
     <string name="adb_active_notification_message" msgid="1016654627626476142">"‏غیرفعال‌کردن اشکال‌زدایی‌USB: با لمس آن."</string>
+    <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"درحال گرفتن گزارش اشکال…"</string>
     <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"گزارش اشکال به اشتراک گذاشته شود؟"</string>
     <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"درحال اشتراک‌گذاری گزارش اشکال…‏"</string>
-    <string name="share_remote_bugreport_notification_message" msgid="752583906074230920">"سرپرست فناوری اطلاعات شما برای کمک به عیب‌یابی این دستگاه، درخواست گزارش اشکال کرده است. ممکن است برنامه‌ها و داده‌ها به اشتراک گذاشته شوند و سرعت دستگاهتان به‌طور موقت کاهش یابد."</string>
-    <string name="share_finished_remote_bugreport_notification_message" msgid="4627312060769912353">"سرپرست فناوری اطلاعات شما برای کمک به عیب‌یابی این دستگاه، گزارش اشکال درخواست کرده است. ممکن است برنامه‌ها و داده‌ها به اشتراک گذاشته شوند."</string>
-    <string name="sharing_remote_bugreport_notification_message" msgid="673106383408474893">"ممکن است سرعت دستگاهتان به‌طور موقت کاهش یابد"</string>
-    <string name="share_remote_bugreport_notification_accept" msgid="8203856129078669677">"پذیرفتن"</string>
-    <string name="share_remote_bugreport_notification_decline" msgid="6337969352057443969">"نپذیرفتن"</string>
+    <string name="share_remote_bugreport_notification_message_finished" msgid="8610614010660772643">"سرپرست فناوری اطلاعات شما برای کمک به عیب‌یابی این دستگاه، گزارش اشکال درخواست کرده است. ممکن است برنامه‌ها و داده‌ها به اشتراک گذاشته شوند."</string>
+    <string name="share_remote_bugreport_action" msgid="6249476773913384948">"اشتراک‌گذاری"</string>
+    <string name="decline_remote_bugreport_action" msgid="6230987241608770062">"نپذیرفتن"</string>
     <string name="select_input_method" msgid="8547250819326693584">"تغییر صفحه‌کلید"</string>
     <string name="configure_input_methods" msgid="4769971288371946846">"انتخاب صفحه‌کلیدها"</string>
     <string name="show_ime" msgid="2506087537466597099">"وقتی صفحه‌کلید فیزیکی فعال است این ویرایشگر را روی صفحه نگه‌می‌دارد"</string>
@@ -1137,8 +1135,9 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"کاغذدیواری"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"تغییر کاغذدیواری"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"شنونده اعلان"</string>
+    <string name="vr_listener_binding_label" msgid="4316591939343607306">"‏شنونده VR"</string>
     <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"ارائه‌دهنده وضعیت"</string>
-    <string name="notification_assistant_binding_label" msgid="909456055569102952">"دستیار اعلان"</string>
+    <string name="notification_ranker_binding_label" msgid="774540592299064747">"سرویس رتبه‌بندی اعلان"</string>
     <string name="vpn_title" msgid="19615213552042827">"‏VPN فعال شد"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"‏VPN توسط <xliff:g id="APP">%s</xliff:g> فعال شده است"</string>
     <string name="vpn_text" msgid="3011306607126450322">"برای مدیریت شبکه لمس کنید."</string>
@@ -1467,7 +1466,7 @@
     <string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"درخواست کد پین قبل از برداشتن پین"</string>
     <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"درخواست الگوی باز کردن قفل قبل از برداشتن پین"</string>
     <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"درخواست گذرواژه قبل از برداشتن پین"</string>
-    <string name="dock_cropped_windows_text" msgid="6378424064779004428">"اندازه برنامه قابل تغییر نیست، با دو انگشت آن را پیمایش کنید."</string>
+    <string name="dock_forced_resizable" msgid="5914261505436217520">"ممکن است برنامه با تقسیم صفحه کار نکند."</string>
     <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"برنامه از تقسیم صفحه پشتیبانی نمی‌کند."</string>
     <string name="package_installed_device_owner" msgid="8420696545959087545">"توسط سرپرستتان نصب شد"</string>
     <string name="package_updated_device_owner" msgid="8856631322440187071">"توسط سرپرست شما به‌روزرسانی شد"</string>
@@ -1541,7 +1540,7 @@
     <string name="importance_from_person" msgid="9160133597262938296">"به دلیل افراد درگیر مهم است."</string>
     <string name="user_creation_account_exists" msgid="1942606193570143289">"به <xliff:g id="APP">%1$s</xliff:g> امکان داده شود کاربر جدیدی با <xliff:g id="ACCOUNT">%2$s</xliff:g> اضافه کند؟"</string>
     <string name="user_creation_adding" msgid="4482658054622099197">"به <xliff:g id="APP">%1$s</xliff:g> امکان داده شود کاربر جدیدی با <xliff:g id="ACCOUNT">%2$s</xliff:g> ایجاد کند (کاربری با این حساب از قبل وجود دارد)؟"</string>
-    <string name="language_selection_title" msgid="7181332986330337171">"اولویت‌های زبان"</string>
+    <string name="language_selection_title" msgid="2680677278159281088">"افزودن زبان"</string>
     <string name="country_selection_title" msgid="2954859441620215513">"اولویت‌های منطقه"</string>
     <string name="search_language_hint" msgid="7042102592055108574">"نام زبان را تایپ کنید"</string>
     <string name="language_picker_section_suggested" msgid="8414489646861640885">"پیشنهادشده"</string>
@@ -1564,6 +1563,7 @@
     <string name="pin_target" msgid="3052256031352291362">"پین کردن"</string>
     <string name="unpin_target" msgid="3556545602439143442">"برداشتن پین"</string>
     <string name="app_info" msgid="6856026610594615344">"اطلاعات برنامه"</string>
-    <!-- no translation found for negative_duration (5688706061127375131) -->
-    <skip />
+    <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="audit_safemode_notification" msgid="6351827251856877200">"بازنشانی کارخانه‌ای برای استفاده عادی از این دستگاه"</string>
+    <string name="audit_safemode_notification_details" msgid="1860601176690176413">"برای یادگیری بیشتر لمس کنید."</string>
 </resources>
diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml
index d37d102..d45e0bd 100644
--- a/core/res/res/values-fi/strings.xml
+++ b/core/res/res/values-fi/strings.xml
@@ -229,7 +229,6 @@
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Ääniapuri"</string>
     <string name="global_action_lockdown" msgid="8751542514724332873">"Lukitse nyt"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
-    <string name="notification_children_count_bracketed" msgid="1769425473168347839">"(<xliff:g id="NOTIFICATIONCOUNT">%d</xliff:g>)"</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>
     <string name="safeMode" msgid="2788228061547930246">"Suojattu tila"</string>
@@ -1052,13 +1051,12 @@
     <string name="usb_notification_message" msgid="7347368030849048437">"Lisää vaihtoehtoja koskettamalla"</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"USB-vianetsintä yhdistetty"</string>
     <string name="adb_active_notification_message" msgid="1016654627626476142">"Sulje USB-vianetsintä koskettamalla."</string>
+    <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Luodaan virheraporttia…"</string>
     <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Jaetaanko virheraportti?"</string>
     <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Jaetaan virheraporttia…"</string>
-    <string name="share_remote_bugreport_notification_message" msgid="752583906074230920">"Järjestelmänvalvoja pyysi virheraporttia voidakseen auttaa laitteen vianetsinnässä. Sovelluksia ja tietoja voidaan jakaa, ja laitteen toiminta voi hidastua väliaikaisesti."</string>
-    <string name="share_finished_remote_bugreport_notification_message" msgid="4627312060769912353">"Järjestelmänvalvoja pyysi virheraporttia voidakseen auttaa laitteen vianetsinnässä. Sovelluksia ja tietoja voidaan jakaa."</string>
-    <string name="sharing_remote_bugreport_notification_message" msgid="673106383408474893">"Tämä voi hidastaa laitteen toimintaa väliaikaisesti."</string>
-    <string name="share_remote_bugreport_notification_accept" msgid="8203856129078669677">"HYVÄKSY"</string>
-    <string name="share_remote_bugreport_notification_decline" msgid="6337969352057443969">"HYLKÄÄ"</string>
+    <string name="share_remote_bugreport_notification_message_finished" msgid="8610614010660772643">"Järjestelmänvalvoja pyysi virheraporttia voidakseen auttaa laitteen vianetsinnässä. Sovelluksia ja tietoja voidaan jakaa."</string>
+    <string name="share_remote_bugreport_action" msgid="6249476773913384948">"JAA"</string>
+    <string name="decline_remote_bugreport_action" msgid="6230987241608770062">"HYLKÄÄ"</string>
     <string name="select_input_method" msgid="8547250819326693584">"Vaihda näppäimistö"</string>
     <string name="configure_input_methods" msgid="4769971288371946846">"Valitse näppäimistöt"</string>
     <string name="show_ime" msgid="2506087537466597099">"Pidä näytöllä, kun fyysinen näppäimistö on aktiivinen."</string>
@@ -1137,8 +1135,9 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Taustakuva"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Vaihda taustakuvaa"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Ilmoituskuuntelija"</string>
+    <string name="vr_listener_binding_label" msgid="4316591939343607306">"Virtuaalitodellisuuden kuuntelija"</string>
     <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Ehtojen toimituspalvelu"</string>
-    <string name="notification_assistant_binding_label" msgid="909456055569102952">"Ilmoitusapuri"</string>
+    <string name="notification_ranker_binding_label" msgid="774540592299064747">"Ilmoitusten sijoituspalvelu"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN on aktivoitu"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"<xliff:g id="APP">%s</xliff:g> on aktivoinut VPN-yhteyden"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Voit hallinnoida verkkoa koskettamalla."</string>
@@ -1467,7 +1466,7 @@
     <string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Pyydä PIN ennen irrotusta"</string>
     <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Pyydä lukituksenpoistokuvio ennen irrotusta"</string>
     <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Pyydä salasana ennen irrotusta"</string>
-    <string name="dock_cropped_windows_text" msgid="6378424064779004428">"Sovelluksen kokoa ei voi muuttaa. Vieritä näkymää kahdella sormella."</string>
+    <string name="dock_forced_resizable" msgid="5914261505436217520">"Sovellus ei ehkä toimi jaetulla näytöllä."</string>
     <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"Sovellus ei tue jaetun näytön tilaa."</string>
     <string name="package_installed_device_owner" msgid="8420696545959087545">"Järjestelmänvalvoja on asentanut paketin."</string>
     <string name="package_updated_device_owner" msgid="8856631322440187071">"Järjestelmänvalvojasi on päivittänyt paketin."</string>
@@ -1541,7 +1540,7 @@
     <string name="importance_from_person" msgid="9160133597262938296">"Tämä on tärkeää siihen liittyvien ihmisten perusteella."</string>
     <string name="user_creation_account_exists" msgid="1942606193570143289">"Myönnetäänkö sovellukselle <xliff:g id="APP">%1$s</xliff:g> oikeus luoda käyttäjä tilille <xliff:g id="ACCOUNT">%2$s</xliff:g>?"</string>
     <string name="user_creation_adding" msgid="4482658054622099197">"Myönnetäänkö sovellukselle <xliff:g id="APP">%1$s</xliff:g> oikeus luoda käyttäjä tilille <xliff:g id="ACCOUNT">%2$s</xliff:g> (tilillä on jo käyttäjä)?"</string>
-    <string name="language_selection_title" msgid="7181332986330337171">"Kieliasetus"</string>
+    <string name="language_selection_title" msgid="2680677278159281088">"Lisää kieli"</string>
     <string name="country_selection_title" msgid="2954859441620215513">"Alueasetus"</string>
     <string name="search_language_hint" msgid="7042102592055108574">"Anna kielen nimi"</string>
     <string name="language_picker_section_suggested" msgid="8414489646861640885">"Ehdotukset"</string>
@@ -1564,6 +1563,7 @@
     <string name="pin_target" msgid="3052256031352291362">"Kiinnitä"</string>
     <string name="unpin_target" msgid="3556545602439143442">"Irrota"</string>
     <string name="app_info" msgid="6856026610594615344">"Sovelluksen tiedot"</string>
-    <!-- no translation found for negative_duration (5688706061127375131) -->
-    <skip />
+    <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="audit_safemode_notification" msgid="6351827251856877200">"Palauta tehdasasetukset, jotta voit käyttää laitetta tavallisesti"</string>
+    <string name="audit_safemode_notification_details" msgid="1860601176690176413">"Lue lisätietoja koskettamalla."</string>
 </resources>
diff --git a/core/res/res/values-fr-rCA/strings.xml b/core/res/res/values-fr-rCA/strings.xml
index bb48fb1..6fa6f49 100644
--- a/core/res/res/values-fr-rCA/strings.xml
+++ b/core/res/res/values-fr-rCA/strings.xml
@@ -229,7 +229,6 @@
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Assist. vocale"</string>
     <string name="global_action_lockdown" msgid="8751542514724332873">"Verrouiller"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"&gt;999"</string>
-    <string name="notification_children_count_bracketed" msgid="1769425473168347839">"(<xliff:g id="NOTIFICATIONCOUNT">%d</xliff:g>)"</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>
     <string name="safeMode" msgid="2788228061547930246">"Mode sécurisé"</string>
@@ -1052,13 +1051,12 @@
     <string name="usb_notification_message" msgid="7347368030849048437">"Touchez pour afficher plus d\'options."</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"Débogage USB connecté"</string>
     <string name="adb_active_notification_message" msgid="1016654627626476142">"Appuyez pour désactiver le débogage USB."</string>
+    <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Création d\'un rapport de bogue en cours..."</string>
     <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Partager le rapport de bogue?"</string>
     <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Partage du rapport de bogue en cours..."</string>
-    <string name="share_remote_bugreport_notification_message" msgid="752583906074230920">"Votre administrateur informatique a demandé un rapport de bogue pour l\'aider à dépanner cet appareil. Les applications et les données peuvent être partagées. Cela pourrait temporairement ralentir votre appareil."</string>
-    <string name="share_finished_remote_bugreport_notification_message" msgid="4627312060769912353">"Votre administrateur informatique a demandé un rapport de bogue pour l\'aider à dépanner cet appareil. Les applications et les données peuvent être partagées."</string>
-    <string name="sharing_remote_bugreport_notification_message" msgid="673106383408474893">"Cela pourrait temporairement ralentir votre appareil."</string>
-    <string name="share_remote_bugreport_notification_accept" msgid="8203856129078669677">"ACCEPTER"</string>
-    <string name="share_remote_bugreport_notification_decline" msgid="6337969352057443969">"REFUSER"</string>
+    <string name="share_remote_bugreport_notification_message_finished" msgid="8610614010660772643">"Votre administrateur informatique a demandé un rapport de bogue pour l\'aider à dépanner cet appareil. Les applications et les données peuvent être partagées."</string>
+    <string name="share_remote_bugreport_action" msgid="6249476773913384948">"PARTAGER"</string>
+    <string name="decline_remote_bugreport_action" msgid="6230987241608770062">"REFUSER"</string>
     <string name="select_input_method" msgid="8547250819326693584">"Changer de clavier"</string>
     <string name="configure_input_methods" msgid="4769971288371946846">"Choisir les claviers"</string>
     <string name="show_ime" msgid="2506087537466597099">"Afficher lorsque le clavier physique est activé"</string>
@@ -1137,8 +1135,9 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Fond d\'écran"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Changer de fond d\'écran"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Outil d\'écoute des notifications"</string>
+    <string name="vr_listener_binding_label" msgid="4316591939343607306">"Écouteur de réalité virtuelle"</string>
     <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Fournisseur de conditions"</string>
-    <string name="notification_assistant_binding_label" msgid="909456055569102952">"Assistant des notifications"</string>
+    <string name="notification_ranker_binding_label" msgid="774540592299064747">"Service de classement des notifications"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN activé"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN activé par <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Appuyez ici pour gérer le réseau."</string>
@@ -1467,7 +1466,7 @@
     <string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Demander le NIP avant d\'annuler l\'épinglage"</string>
     <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Demander le schéma de déverrouillage avant d\'annuler l\'épinglage"</string>
     <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Demander le mot de passe avant d\'annuler l\'épinglage"</string>
-    <string name="dock_cropped_windows_text" msgid="6378424064779004428">"Impossible de redimensionner l\'application. Faites-la défiler avec deux doigts."</string>
+    <string name="dock_forced_resizable" msgid="5914261505436217520">"Il est possible que l\'application ne fonctionne pas en mode Écran partagé."</string>
     <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"L\'application n\'est pas compatible avec l\'écran partagé."</string>
     <string name="package_installed_device_owner" msgid="8420696545959087545">"Installé par votre administrateur"</string>
     <string name="package_updated_device_owner" msgid="8856631322440187071">"Mis à jour par votre administrateur"</string>
@@ -1541,7 +1540,7 @@
     <string name="importance_from_person" msgid="9160133597262938296">"Ces notifications sont importantes en raison des participants."</string>
     <string name="user_creation_account_exists" msgid="1942606193570143289">"Autoriser <xliff:g id="APP">%1$s</xliff:g> à créer un profil d\'utilisateur avec le compte <xliff:g id="ACCOUNT">%2$s</xliff:g>?"</string>
     <string name="user_creation_adding" msgid="4482658054622099197">"Autoriser <xliff:g id="APP">%1$s</xliff:g> à créer un profil d\'utilisateur avec le compte <xliff:g id="ACCOUNT">%2$s</xliff:g>? (Un utilisateur associé à ce compte existe déjà.)"</string>
-    <string name="language_selection_title" msgid="7181332986330337171">"Préférences linguistiques"</string>
+    <string name="language_selection_title" msgid="2680677278159281088">"Ajouter une langue"</string>
     <string name="country_selection_title" msgid="2954859441620215513">"Préférences régionales"</string>
     <string name="search_language_hint" msgid="7042102592055108574">"Entrez la langue"</string>
     <string name="language_picker_section_suggested" msgid="8414489646861640885">"Suggestions"</string>
@@ -1564,6 +1563,7 @@
     <string name="pin_target" msgid="3052256031352291362">"Épingler"</string>
     <string name="unpin_target" msgid="3556545602439143442">"Annuler l\'épinglage"</string>
     <string name="app_info" msgid="6856026610594615344">"Détails de l\'application"</string>
-    <!-- no translation found for negative_duration (5688706061127375131) -->
-    <skip />
+    <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="audit_safemode_notification" msgid="6351827251856877200">"Rétablissez la configuration d\'usine pour utiliser cet appareil normalement"</string>
+    <string name="audit_safemode_notification_details" msgid="1860601176690176413">"Touchez ici pour en savoir plus."</string>
 </resources>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index fc58839..02ad9e6 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -229,7 +229,6 @@
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Assistance vocale"</string>
     <string name="global_action_lockdown" msgid="8751542514724332873">"Verrouiller"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"&gt;999"</string>
-    <string name="notification_children_count_bracketed" msgid="1769425473168347839">"(<xliff:g id="NOTIFICATIONCOUNT">%d</xliff:g>)"</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>
     <string name="safeMode" msgid="2788228061547930246">"Mode sécurisé"</string>
@@ -1052,13 +1051,12 @@
     <string name="usb_notification_message" msgid="7347368030849048437">"Appuyez pour afficher plus d\'options"</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"Débogage USB activé"</string>
     <string name="adb_active_notification_message" msgid="1016654627626476142">"Appuyez pour désact. débogage USB"</string>
+    <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Création du rapport de bug…"</string>
     <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Partager le rapport de bug ?"</string>
     <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Partage du rapport de bug…"</string>
-    <string name="share_remote_bugreport_notification_message" msgid="752583906074230920">"Votre administrateur informatique a demandé un rapport de bug pour l\'aider à résoudre le problème lié à cet appareil. Il est possible que des applications et des données soient partagées et que votre appareil ralentisse temporairement."</string>
-    <string name="share_finished_remote_bugreport_notification_message" msgid="4627312060769912353">"Votre administrateur informatique a demandé un rapport de bug pour l\'aider à résoudre le problème lié à cet appareil. Il est possible que des applications et des données soient partagées."</string>
-    <string name="sharing_remote_bugreport_notification_message" msgid="673106383408474893">"Ceci risque de ralentir temporairement votre appareil."</string>
-    <string name="share_remote_bugreport_notification_accept" msgid="8203856129078669677">"ACCEPTER"</string>
-    <string name="share_remote_bugreport_notification_decline" msgid="6337969352057443969">"REFUSER"</string>
+    <string name="share_remote_bugreport_notification_message_finished" msgid="8610614010660772643">"Votre administrateur informatique a demandé un rapport de bug pour l\'aider à résoudre le problème lié à cet appareil. Il est possible que des applications et des données soient partagées."</string>
+    <string name="share_remote_bugreport_action" msgid="6249476773913384948">"PARTAGER"</string>
+    <string name="decline_remote_bugreport_action" msgid="6230987241608770062">"REFUSER"</string>
     <string name="select_input_method" msgid="8547250819326693584">"Changer de clavier"</string>
     <string name="configure_input_methods" msgid="4769971288371946846">"Sélectionner des claviers"</string>
     <string name="show_ime" msgid="2506087537466597099">"Afficher lorsque le clavier physique est activé"</string>
@@ -1137,8 +1135,9 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Fond d\'écran"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Changer de fond d\'écran"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Outil d\'écoute des notifications"</string>
+    <string name="vr_listener_binding_label" msgid="4316591939343607306">"Écouteur de réalité virtuelle"</string>
     <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Fournisseur de conditions"</string>
-    <string name="notification_assistant_binding_label" msgid="909456055569102952">"Assistant de notifications"</string>
+    <string name="notification_ranker_binding_label" msgid="774540592299064747">"Service de classement des notifications"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN activé"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN activé par <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Appuyez ici pour gérer le réseau."</string>
@@ -1467,7 +1466,7 @@
     <string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Demander le code PIN avant d\'annuler l\'épinglage"</string>
     <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Demander le schéma de déverrouillage avant d\'annuler l\'épinglage"</string>
     <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Demander le mot de passe avant d\'annuler l\'épinglage"</string>
-    <string name="dock_cropped_windows_text" msgid="6378424064779004428">"Il est impossible de redimensionner l\'application. Faites-la défiler avec deux doigts."</string>
+    <string name="dock_forced_resizable" msgid="5914261505436217520">"Il est possible que l\'application ne fonctionne pas en mode Écran partagé."</string>
     <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"Application incompatible avec l\'écran partagé."</string>
     <string name="package_installed_device_owner" msgid="8420696545959087545">"Installé par votre administrateur"</string>
     <string name="package_updated_device_owner" msgid="8856631322440187071">"Mis à jour par votre administrateur"</string>
@@ -1541,7 +1540,7 @@
     <string name="importance_from_person" msgid="9160133597262938296">"Ces notifications sont importantes en raison des participants."</string>
     <string name="user_creation_account_exists" msgid="1942606193570143289">"Autoriser <xliff:g id="APP">%1$s</xliff:g> à créer un profil utilisateur avec le compte <xliff:g id="ACCOUNT">%2$s</xliff:g> ?"</string>
     <string name="user_creation_adding" msgid="4482658054622099197">"Autoriser <xliff:g id="APP">%1$s</xliff:g> à créer un profil utilisateur avec le compte <xliff:g id="ACCOUNT">%2$s</xliff:g> (un utilisateur associé à ce compte existe déjà) ?"</string>
-    <string name="language_selection_title" msgid="7181332986330337171">"Préférences linguistiques"</string>
+    <string name="language_selection_title" msgid="2680677278159281088">"Ajouter une langue"</string>
     <string name="country_selection_title" msgid="2954859441620215513">"Préférences régionales"</string>
     <string name="search_language_hint" msgid="7042102592055108574">"Saisissez la langue"</string>
     <string name="language_picker_section_suggested" msgid="8414489646861640885">"Recommandations"</string>
@@ -1564,6 +1563,7 @@
     <string name="pin_target" msgid="3052256031352291362">"Épingler"</string>
     <string name="unpin_target" msgid="3556545602439143442">"Retirer"</string>
     <string name="app_info" msgid="6856026610594615344">"Infos sur l\'appli"</string>
-    <!-- no translation found for negative_duration (5688706061127375131) -->
-    <skip />
+    <string name="negative_duration" msgid="5688706061127375131">"− <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="audit_safemode_notification" msgid="6351827251856877200">"Rétablir la configuration d\'usine pour utiliser cet appareil normalement"</string>
+    <string name="audit_safemode_notification_details" msgid="1860601176690176413">"Appuyez ici pour en savoir plus."</string>
 </resources>
diff --git a/core/res/res/values-gl-rES/strings.xml b/core/res/res/values-gl-rES/strings.xml
index a8ebf9e..cb0ac76 100644
--- a/core/res/res/values-gl-rES/strings.xml
+++ b/core/res/res/values-gl-rES/strings.xml
@@ -229,7 +229,6 @@
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Asistente voz"</string>
     <string name="global_action_lockdown" msgid="8751542514724332873">"Bloquear agora"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"&gt;999"</string>
-    <string name="notification_children_count_bracketed" msgid="1769425473168347839">"(<xliff:g id="NOTIFICATIONCOUNT">%d</xliff:g>)"</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>
     <string name="safeMode" msgid="2788228061547930246">"Modo seguro"</string>
@@ -1052,13 +1051,12 @@
     <string name="usb_notification_message" msgid="7347368030849048437">"Toca para ver máis opcións."</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"Depuración USB conectada"</string>
     <string name="adb_active_notification_message" msgid="1016654627626476142">"Toca aquí para desactivala"</string>
+    <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Creando informe de erros…"</string>
     <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Queres compartir o informe de erros?"</string>
     <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Compartindo informe de erros..."</string>
-    <string name="share_remote_bugreport_notification_message" msgid="752583906074230920">"O teu administrador de TI solicitou un informe de erros para axudar a solucionar os problemas deste dispositivo. É posible que se compartan aplicacións e datos e que se reduza a velocidade do teu dispositivo temporalmente."</string>
-    <string name="share_finished_remote_bugreport_notification_message" msgid="4627312060769912353">"O teu administrador de TI solicitou un informe de erros para axudar a solucionar os problemas deste dispositivo. É posible que se compartan aplicacións e datos."</string>
-    <string name="sharing_remote_bugreport_notification_message" msgid="673106383408474893">"Esta acción pode reducir a velocidade do teu dispositivo temporalmente"</string>
-    <string name="share_remote_bugreport_notification_accept" msgid="8203856129078669677">"ACEPTAR"</string>
-    <string name="share_remote_bugreport_notification_decline" msgid="6337969352057443969">"ANULAR"</string>
+    <string name="share_remote_bugreport_notification_message_finished" msgid="8610614010660772643">"O teu administrador de TI solicitou un informe de erros para axudar a solucionar os problemas deste dispositivo. É posible que se compartan aplicacións e datos."</string>
+    <string name="share_remote_bugreport_action" msgid="6249476773913384948">"COMPARTIR"</string>
+    <string name="decline_remote_bugreport_action" msgid="6230987241608770062">"ANULAR"</string>
     <string name="select_input_method" msgid="8547250819326693584">"Cambiar teclado"</string>
     <string name="configure_input_methods" msgid="4769971288371946846">"Seleccionar teclados"</string>
     <string name="show_ime" msgid="2506087537466597099">"Manteno na pantalla mentres o teclado físico estea activo"</string>
@@ -1137,8 +1135,9 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Fondo de pantalla"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Cambiar fondo de pantalla"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Axente de escoita de notificacións"</string>
+    <string name="vr_listener_binding_label" msgid="4316591939343607306">"Axente de escoita de RV"</string>
     <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Provedor de condicións"</string>
-    <string name="notification_assistant_binding_label" msgid="909456055569102952">"Asistente de notificacións"</string>
+    <string name="notification_ranker_binding_label" msgid="774540592299064747">"Servizo de clasificación de notificacións"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN activada"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"<xliff:g id="APP">%s</xliff:g> activou a VPN"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Toca aquí para xestionar a rede."</string>
@@ -1467,7 +1466,7 @@
     <string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Solicitar un PIN antes de soltar a pantalla"</string>
     <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Solicitar un padrón de desbloqueo antes de soltar a pantalla"</string>
     <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Solicitar un contrasinal antes de soltar a pantalla"</string>
-    <string name="dock_cropped_windows_text" msgid="6378424064779004428">"Non se pode cambiar o tamaño da aplicación. Desprázate por ela con dous dedos."</string>
+    <string name="dock_forced_resizable" msgid="5914261505436217520">"Pode que a aplicación non funcione coa pantalla dividida."</string>
     <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"A aplicación non é compatible coa función de pantalla dividida."</string>
     <string name="package_installed_device_owner" msgid="8420696545959087545">"Instalado polo administrador"</string>
     <string name="package_updated_device_owner" msgid="8856631322440187071">"Actualizado polo administrador"</string>
@@ -1541,7 +1540,7 @@
     <string name="importance_from_person" msgid="9160133597262938296">"É importante polas persoas involucradas."</string>
     <string name="user_creation_account_exists" msgid="1942606193570143289">"Queres permitir que <xliff:g id="APP">%1$s</xliff:g> cree un usuario novo con <xliff:g id="ACCOUNT">%2$s</xliff:g>?"</string>
     <string name="user_creation_adding" msgid="4482658054622099197">"Queres permitir que <xliff:g id="APP">%1$s</xliff:g> cree un usuario novo con <xliff:g id="ACCOUNT">%2$s</xliff:g>? (Xa existe un usuario con esta conta)"</string>
-    <string name="language_selection_title" msgid="7181332986330337171">"Preferencia de idioma"</string>
+    <string name="language_selection_title" msgid="2680677278159281088">"Engadir un idioma"</string>
     <string name="country_selection_title" msgid="2954859441620215513">"Preferencia de rexión"</string>
     <string name="search_language_hint" msgid="7042102592055108574">"Nome do idioma"</string>
     <string name="language_picker_section_suggested" msgid="8414489646861640885">"Suxeridos"</string>
@@ -1564,6 +1563,7 @@
     <string name="pin_target" msgid="3052256031352291362">"Fixar"</string>
     <string name="unpin_target" msgid="3556545602439143442">"Soltar"</string>
     <string name="app_info" msgid="6856026610594615344">"Información da aplicación"</string>
-    <!-- no translation found for negative_duration (5688706061127375131) -->
-    <skip />
+    <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="audit_safemode_notification" msgid="6351827251856877200">"Restablecemento da configuración de fábrica para usar este dispositivo con normalidade"</string>
+    <string name="audit_safemode_notification_details" msgid="1860601176690176413">"Toca para acceder a máis información"</string>
 </resources>
diff --git a/core/res/res/values-gu-rIN/strings.xml b/core/res/res/values-gu-rIN/strings.xml
index 5ab0447..6270867 100644
--- a/core/res/res/values-gu-rIN/strings.xml
+++ b/core/res/res/values-gu-rIN/strings.xml
@@ -229,7 +229,6 @@
     <string name="global_action_voice_assist" msgid="7751191495200504480">"વૉઇસ સહાય"</string>
     <string name="global_action_lockdown" msgid="8751542514724332873">"હવે લૉક કરો"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
-    <string name="notification_children_count_bracketed" msgid="1769425473168347839">"(<xliff:g id="NOTIFICATIONCOUNT">%d</xliff:g>)"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"સામગ્રીઓ છુપાવેલ છે"</string>
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"નીતિ દ્વારા સામગ્રી છુપાવાઈ"</string>
     <string name="safeMode" msgid="2788228061547930246">"સુરક્ષિત મોડ"</string>
@@ -1052,13 +1051,12 @@
     <string name="usb_notification_message" msgid="7347368030849048437">"વધુ વિકલ્પો માટે ટચ કરો."</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"USB ડીબગિંગ કનેક્ટ થયું."</string>
     <string name="adb_active_notification_message" msgid="1016654627626476142">"USB ડીબગિંગ અક્ષમ કરવા માટે ટચ કરો."</string>
+    <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"બગ રિપોર્ટ લઈ રહ્યાં છે…"</string>
     <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"બગ રિપોર્ટ શેર કરીએ?"</string>
     <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"બગ રિપોર્ટ શેર કરી રહ્યાં છે…"</string>
-    <string name="share_remote_bugreport_notification_message" msgid="752583906074230920">"તમારા IT વ્યવસ્થાપક એ આ ઉપકરણની સમસ્યા નિવારણમાં સહાય માટે બગ રિપોર્ટની વિનંતી કરી છે. ઍપ્લિકેશનો અને ડેટા શેર કરવામાં આવી શકે છે અને તમારા ઉપકરણને અસ્થાયી રૂપે ધીમું કરી શકે છે."</string>
-    <string name="share_finished_remote_bugreport_notification_message" msgid="4627312060769912353">"તમારા IT વ્યવસ્થાપક એ આ ઉપકરણની સમસ્યા નિવારણમાં સહાય માટે બગ રિપોર્ટની વિનંતી કરી છે. ઍપ્લિકેશનો અને ડેટા શેર કરવામાં આવી શકે છે."</string>
-    <string name="sharing_remote_bugreport_notification_message" msgid="673106383408474893">"આ અસ્થાયી રૂપે તમારા ઉપકરણને ધીમું કરી શકે છે"</string>
-    <string name="share_remote_bugreport_notification_accept" msgid="8203856129078669677">"સ્વીકારો"</string>
-    <string name="share_remote_bugreport_notification_decline" msgid="6337969352057443969">"નકારો"</string>
+    <string name="share_remote_bugreport_notification_message_finished" msgid="8610614010660772643">"તમારા IT વ્યવસ્થાપક એ આ ઉપકરણની સમસ્યા નિવારણમાં સહાય માટે બગ રિપોર્ટની વિનંતી કરી છે. ઍપ્લિકેશનો અને ડેટા શેર કરવામાં આવી શકે છે."</string>
+    <string name="share_remote_bugreport_action" msgid="6249476773913384948">"શેર કરો"</string>
+    <string name="decline_remote_bugreport_action" msgid="6230987241608770062">"નકારો"</string>
     <string name="select_input_method" msgid="8547250819326693584">"કીબોર્ડ બદલો"</string>
     <string name="configure_input_methods" msgid="4769971288371946846">"કીબોર્ડ્સ પસંદ કરો"</string>
     <string name="show_ime" msgid="2506087537466597099">"જ્યારે ભૌતિક કીબોર્ડ સક્રિય હોય ત્યારે તેને સ્ક્રીન પર રાખો"</string>
@@ -1137,8 +1135,9 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"વૉલપેપર"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"વૉલપેપર બદલો"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"સૂચના સાંભળનાર"</string>
+    <string name="vr_listener_binding_label" msgid="4316591939343607306">"VR સાંભળનાર"</string>
     <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"શરત પ્રદાતા"</string>
-    <string name="notification_assistant_binding_label" msgid="909456055569102952">"સૂચના સહાયક"</string>
+    <string name="notification_ranker_binding_label" msgid="774540592299064747">"સૂચના રેંકર સેવા"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN સક્રિય કર્યું"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"<xliff:g id="APP">%s</xliff:g> દ્વારા VPN સક્રિય થયું"</string>
     <string name="vpn_text" msgid="3011306607126450322">"નેટવર્કને સંચાલિત કરવા માટે ટચ કરો."</string>
@@ -1467,7 +1466,7 @@
     <string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"અનપિન કરતાં પહેલાં PIN માટે પૂછો"</string>
     <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"અનપિન કરતા પહેલાં અનલૉક પેટર્ન માટે પૂછો"</string>
     <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"અનપિન કરતાં પહેલાં પાસવર્ડ માટે પૂછો"</string>
-    <string name="dock_cropped_windows_text" msgid="6378424064779004428">"ઍપ્લિકેશનનું કદ બદલવા યોગ્ય નથી, બે આંગળીઓ વડે તેને સ્ક્રોલ કરો."</string>
+    <string name="dock_forced_resizable" msgid="5914261505436217520">"વિભાજિત-સ્ક્રીન સાથે ઍપ્લિકેશન કદાચ કામ ન કરે."</string>
     <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"ઍપ્લિકેશન સ્ક્રીન-વિભાજનનું સમર્થન કરતી નથી."</string>
     <string name="package_installed_device_owner" msgid="8420696545959087545">"તમારા વ્યવસ્થાપક દ્વારા ઇન્સ્ટોલ કરેલ"</string>
     <string name="package_updated_device_owner" msgid="8856631322440187071">"તમારા વ્યવસ્થાપક દ્વારા અપડેટ થયેલ"</string>
@@ -1541,7 +1540,7 @@
     <string name="importance_from_person" msgid="9160133597262938296">"શામેલ થયેલ લોકોને કારણે આ મહત્વપૂર્ણ છે."</string>
     <string name="user_creation_account_exists" msgid="1942606193570143289">"<xliff:g id="APP">%1$s</xliff:g> ને <xliff:g id="ACCOUNT">%2$s</xliff:g> સાથે એક નવા વપરાશકર્તાને બનાવવાની મંજૂરી આપીએ?"</string>
     <string name="user_creation_adding" msgid="4482658054622099197">"<xliff:g id="ACCOUNT">%2$s</xliff:g> સાથે <xliff:g id="APP">%1$s</xliff:g> ને એક નવા વપરાશકર્તાને બનાવવાની મંજૂરી આપીએ (આ એકાઉન્ટ સાથેના એક વપરાશકર્તા પહેલાંથી અસ્તિત્વમાં છે)?"</string>
-    <string name="language_selection_title" msgid="7181332986330337171">"ભાષા પસંદગી"</string>
+    <string name="language_selection_title" msgid="2680677278159281088">"એક ભાષા ઉમેરો"</string>
     <string name="country_selection_title" msgid="2954859441620215513">"પ્રદેશ પસંદગી"</string>
     <string name="search_language_hint" msgid="7042102592055108574">"ભાષાનું નામ ટાઇપ કરો"</string>
     <string name="language_picker_section_suggested" msgid="8414489646861640885">"સૂચવેલા"</string>
@@ -1565,4 +1564,6 @@
     <string name="unpin_target" msgid="3556545602439143442">"અનપિન કરો"</string>
     <string name="app_info" msgid="6856026610594615344">"ઍપ્લિકેશન માહિતી"</string>
     <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="audit_safemode_notification" msgid="6351827251856877200">"આ ઉપકરણને સામાન્ય રીતે ઉપયોગ કરવા માટે ફેક્ટરી રીસેટ કરો"</string>
+    <string name="audit_safemode_notification_details" msgid="1860601176690176413">"વધુ જાણવા માટે ટચ કરો."</string>
 </resources>
diff --git a/media/java/android/media/AudioRecordConfiguration.aidl b/core/res/res/values-h426dp-port/integers.xml
similarity index 70%
copy from media/java/android/media/AudioRecordConfiguration.aidl
copy to core/res/res/values-h426dp-port/integers.xml
index afe912b..94abbec 100644
--- a/media/java/android/media/AudioRecordConfiguration.aidl
+++ b/core/res/res/values-h426dp-port/integers.xml
@@ -1,4 +1,7 @@
-/* Copyright 2016, The Android Open Source Project
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2016, The Android Open Source Project
 **
 ** Licensed under the Apache License, Version 2.0 (the "License");
 ** you may not use this file except in compliance with the License.
@@ -12,7 +15,8 @@
 ** See the License for the specific language governing permissions and
 ** limitations under the License.
 */
-
-package android.media;
-
-parcelable AudioRecordConfiguration;
+-->
+<resources>
+    <integer name="date_picker_mode">2</integer>
+    <integer name="time_picker_mode">2</integer>
+</resources>
diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml
index 9760462..82e1d83 100644
--- a/core/res/res/values-hi/strings.xml
+++ b/core/res/res/values-hi/strings.xml
@@ -229,7 +229,6 @@
     <string name="global_action_voice_assist" msgid="7751191495200504480">"वॉइस सहायक"</string>
     <string name="global_action_lockdown" msgid="8751542514724332873">"अभी लॉक करें"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
-    <string name="notification_children_count_bracketed" msgid="1769425473168347839">"(<xliff:g id="NOTIFICATIONCOUNT">%d</xliff:g>)"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"छिपी हुई सामग्री"</string>
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"सामग्री पॉलिसी के द्वारा छिपी हुई है"</string>
     <string name="safeMode" msgid="2788228061547930246">"सुरक्षित मोड"</string>
@@ -1052,13 +1051,12 @@
     <string name="usb_notification_message" msgid="7347368030849048437">"और विकल्पों के लिए स्पर्श करें."</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"USB डीबग कनेक्ट किया गया"</string>
     <string name="adb_active_notification_message" msgid="1016654627626476142">"USB डीबग करना अक्षम करने के लिए स्‍पर्श करें."</string>
+    <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"बग रिपोर्ट प्राप्त की जा रही है…"</string>
     <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"बग रिपोर्ट साझा करें?"</string>
     <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"बग रिपोर्ट साझा की जा रही है…"</string>
-    <string name="share_remote_bugreport_notification_message" msgid="752583906074230920">"इस डिवाइस के समस्या निवारण में सहायता हेतु आपके आईटी व्यवस्थापक ने बग रिपोर्ट के लिए अनुरोध किया है. ऐप्स और डेटा को साझा किया जा सकता है और आपके डिवाइस की गति अस्थायी रूप से धीमी हो सकती है."</string>
-    <string name="share_finished_remote_bugreport_notification_message" msgid="4627312060769912353">"आपके आईटी व्यवस्थापक ने इस डिवाइस के समस्या निवारण में सहायता के लिए एक बग रिपोर्ट का अनुरोध किया है. ऐप्स और डेटा साझा किए जा सकते हैं."</string>
-    <string name="sharing_remote_bugreport_notification_message" msgid="673106383408474893">"इससे आपका डिवाइस अस्थायी रूप से धीमा हो सकता है"</string>
-    <string name="share_remote_bugreport_notification_accept" msgid="8203856129078669677">"स्वीकार करें"</string>
-    <string name="share_remote_bugreport_notification_decline" msgid="6337969352057443969">"अस्वीकार करें"</string>
+    <string name="share_remote_bugreport_notification_message_finished" msgid="8610614010660772643">"आपके आईटी व्यवस्थापक ने इस डिवाइस के समस्या निवारण में सहायता के लिए एक बग रिपोर्ट का अनुरोध किया है. ऐप्स और डेटा को साझा किया जा सकता है."</string>
+    <string name="share_remote_bugreport_action" msgid="6249476773913384948">"साझा करें"</string>
+    <string name="decline_remote_bugreport_action" msgid="6230987241608770062">"अस्वीकार करें"</string>
     <string name="select_input_method" msgid="8547250819326693584">"कीबोर्ड बदलें"</string>
     <string name="configure_input_methods" msgid="4769971288371946846">"कीबोर्ड चुनें"</string>
     <string name="show_ime" msgid="2506087537466597099">"भौतिक कीबोर्ड के सक्रिय होने के दौरान इसे स्‍क्रीन पर बनाए रखें"</string>
@@ -1137,8 +1135,9 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"वॉलपेपर"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"वॉलपेपर बदलें"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"नोटिफिकेशन श्रवणकर्ता"</string>
+    <string name="vr_listener_binding_label" msgid="4316591939343607306">"VR श्रोता"</string>
     <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"स्थिति प्रदाता"</string>
-    <string name="notification_assistant_binding_label" msgid="909456055569102952">"नोटिफिकेशन सहायक"</string>
+    <string name="notification_ranker_binding_label" msgid="774540592299064747">"नोटिफ़िकेशन रैंकर सेवा"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN सक्रिय"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN को <xliff:g id="APP">%s</xliff:g> द्वारा सक्रिय किया गया है"</string>
     <string name="vpn_text" msgid="3011306607126450322">"नेटवर्क प्रबंधित करने के लिए स्‍पर्श करें."</string>
@@ -1467,7 +1466,7 @@
     <string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"अनपिन करने से पहले पिन के लिए पूछें"</string>
     <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"अनपिन करने से पहले अनलॉक पैटर्न के लिए पूछें"</string>
     <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"अनपिन करने से पहले पासवर्ड के लिए पूछें"</string>
-    <string name="dock_cropped_windows_text" msgid="6378424064779004428">"ऐप का आकार बदला नहीं जा सकता है, इसे दो अंगुलियों से स्क्रॉल करें."</string>
+    <string name="dock_forced_resizable" msgid="5914261505436217520">"हो सकता है कि ऐप्लिकेशन विभाजित स्क्रीन के साथ काम ना करे."</string>
     <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"ऐप विभाजित स्‍क्रीन का समर्थन नहीं करता है."</string>
     <string name="package_installed_device_owner" msgid="8420696545959087545">"आपके नियंत्रक द्वारा इंस्‍टॉल किया गया"</string>
     <string name="package_updated_device_owner" msgid="8856631322440187071">"आपके नियंत्रक द्वारा अपडेट किया गया"</string>
@@ -1541,7 +1540,7 @@
     <string name="importance_from_person" msgid="9160133597262938296">"यह मौजूद व्यक्तियों के कारण महत्वपूर्ण है."</string>
     <string name="user_creation_account_exists" msgid="1942606193570143289">"<xliff:g id="APP">%1$s</xliff:g> को <xliff:g id="ACCOUNT">%2$s</xliff:g> के द्वारा एक नया उपयोगकर्ता बनाने दें?"</string>
     <string name="user_creation_adding" msgid="4482658054622099197">"<xliff:g id="APP">%1$s</xliff:g> को <xliff:g id="ACCOUNT">%2$s</xliff:g> के द्वारा एक नया उपयोगकर्ता बनाने दें (इस खाते वाला एक उपयोगकर्ता पहले से मौजूद है) ?"</string>
-    <string name="language_selection_title" msgid="7181332986330337171">"भाषा प्राथमिकता"</string>
+    <string name="language_selection_title" msgid="2680677278159281088">"भाषा जोड़ें"</string>
     <string name="country_selection_title" msgid="2954859441620215513">"क्षेत्र प्राथमिकता"</string>
     <string name="search_language_hint" msgid="7042102592055108574">"भाषा का नाम लिखें"</string>
     <string name="language_picker_section_suggested" msgid="8414489646861640885">"सुझाए गए"</string>
@@ -1565,4 +1564,6 @@
     <string name="unpin_target" msgid="3556545602439143442">"अनपिन करें"</string>
     <string name="app_info" msgid="6856026610594615344">"ऐप की जानकारी"</string>
     <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="audit_safemode_notification" msgid="6351827251856877200">"इस डिवाइस का सामान्य रूप से उपयोग करने के लिए फ़ैक्टरी रीसेट करें"</string>
+    <string name="audit_safemode_notification_details" msgid="1860601176690176413">"अधिक जानने के लिए स्पर्श करें."</string>
 </resources>
diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml
index cb6b377..cd23a1a 100644
--- a/core/res/res/values-hr/strings.xml
+++ b/core/res/res/values-hr/strings.xml
@@ -231,7 +231,6 @@
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Glasovna pomoć"</string>
     <string name="global_action_lockdown" msgid="8751542514724332873">"Zaključaj sada"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
-    <string name="notification_children_count_bracketed" msgid="1769425473168347839">"(<xliff:g id="NOTIFICATIONCOUNT">%d</xliff:g>)"</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>
     <string name="safeMode" msgid="2788228061547930246">"Siguran način rada"</string>
@@ -1060,13 +1059,12 @@
     <string name="usb_notification_message" msgid="7347368030849048437">"Dodirnite za više opcija."</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"Priključen je alat za uklanjanje pogrešaka USB-om"</string>
     <string name="adb_active_notification_message" msgid="1016654627626476142">"Dodirnite da se onemogući otklanjanje pogrešaka USB-om."</string>
+    <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Izrada izvješća o programskoj pogrešci…"</string>
     <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Želite li podijeliti izvješće o programskoj pogrešci?"</string>
     <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Dijeljenje izvješća o programskoj pogrešci…"</string>
-    <string name="share_remote_bugreport_notification_message" msgid="752583906074230920">"IT administrator zatražio je izvješće o programskoj pogrešci radi lakšeg rješavanja problema na uređaju. Moguće je da će se aplikacije i podaci dijeliti, što bi moglo privremeno usporiti uređaj."</string>
-    <string name="share_finished_remote_bugreport_notification_message" msgid="4627312060769912353">"IT administrator zatražio je izvješće o programskoj pogrešci radi lakšeg rješavanja problema na uređaju. Moguće je da će se aplikacije i podaci dijeliti."</string>
-    <string name="sharing_remote_bugreport_notification_message" msgid="673106383408474893">"To bi moglo privremeno usporiti uređaj"</string>
-    <string name="share_remote_bugreport_notification_accept" msgid="8203856129078669677">"PRIHVATI"</string>
-    <string name="share_remote_bugreport_notification_decline" msgid="6337969352057443969">"ODBIJ"</string>
+    <string name="share_remote_bugreport_notification_message_finished" msgid="8610614010660772643">"IT administrator zatražio je izvješće o programskoj pogrešci radi lakšeg rješavanja problema na uređaju. Moguće je da će se aplikacije i podaci dijeliti."</string>
+    <string name="share_remote_bugreport_action" msgid="6249476773913384948">"DIJELI"</string>
+    <string name="decline_remote_bugreport_action" msgid="6230987241608770062">"ODBIJ"</string>
     <string name="select_input_method" msgid="8547250819326693584">"Promjena tipkovnice"</string>
     <string name="configure_input_methods" msgid="4769971288371946846">"Odaberi tipkovnice"</string>
     <string name="show_ime" msgid="2506087537466597099">"Zadržava se na zaslonu dok je fizička tipkovnica aktivna"</string>
@@ -1145,8 +1143,9 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Pozadinska slika"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Promjena pozadinske slike"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Slušatelj obavijesti"</string>
+    <string name="vr_listener_binding_label" msgid="4316591939343607306">"Slušatelj virtualne stvarnosti"</string>
     <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Davatalj uvjeta"</string>
-    <string name="notification_assistant_binding_label" msgid="909456055569102952">"Pomoćnik za obavijesti"</string>
+    <string name="notification_ranker_binding_label" msgid="774540592299064747">"Usluga rangiranja obavijesti"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN aktiviran"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"Aplikacija <xliff:g id="APP">%s</xliff:g> aktivirala je VPN"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Dodirnite za upravljanje mrežom."</string>
@@ -1477,7 +1476,7 @@
     <string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Traži PIN radi otkvačivanja"</string>
     <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Traži uzorak za otključavanje radi otkvačivanja"</string>
     <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Traži zaporku radi otkvačivanja"</string>
-    <string name="dock_cropped_windows_text" msgid="6378424064779004428">"Veličina aplikacije ne može se mijenjati, pomičite je s dva prsta."</string>
+    <string name="dock_forced_resizable" msgid="5914261505436217520">"Aplikacija možda neće funkcionirati s podijeljenim zaslonom."</string>
     <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"Aplikacija ne podržava podijeljeni zaslon."</string>
     <string name="package_installed_device_owner" msgid="8420696545959087545">"Instalirao administrator"</string>
     <string name="package_updated_device_owner" msgid="8856631322440187071">"Ažurira vaš administrator"</string>
@@ -1560,7 +1559,7 @@
     <string name="importance_from_person" msgid="9160133597262938296">"Važno je zbog uključenih osoba."</string>
     <string name="user_creation_account_exists" msgid="1942606193570143289">"Želite li dopustiti aplikaciji <xliff:g id="APP">%1$s</xliff:g> da izradi novog korisnika s računom <xliff:g id="ACCOUNT">%2$s</xliff:g>?"</string>
     <string name="user_creation_adding" msgid="4482658054622099197">"Želite li dopustiti aplikaciji <xliff:g id="APP">%1$s</xliff:g> da izradi novog korisnika s računom <xliff:g id="ACCOUNT">%2$s</xliff:g> (korisnik s tim računom već postoji)?"</string>
-    <string name="language_selection_title" msgid="7181332986330337171">"Postavke jezika"</string>
+    <string name="language_selection_title" msgid="2680677278159281088">"Dodavanje jezika"</string>
     <string name="country_selection_title" msgid="2954859441620215513">"Postavke regije"</string>
     <string name="search_language_hint" msgid="7042102592055108574">"Unesite naziv jezika"</string>
     <string name="language_picker_section_suggested" msgid="8414489646861640885">"Predloženo"</string>
@@ -1584,4 +1583,6 @@
     <string name="unpin_target" msgid="3556545602439143442">"Otkvači"</string>
     <string name="app_info" msgid="6856026610594615344">"Informacije o aplikaciji"</string>
     <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="audit_safemode_notification" msgid="6351827251856877200">"Uređaj je vraćen na tvorničke postavke da biste ga mogli upotrebljavati na pravilan način"</string>
+    <string name="audit_safemode_notification_details" msgid="1860601176690176413">"Dodirnite da biste saznali više."</string>
 </resources>
diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml
index ad049aa..ffa8d21 100644
--- a/core/res/res/values-hu/strings.xml
+++ b/core/res/res/values-hu/strings.xml
@@ -229,7 +229,6 @@
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Hangsegéd"</string>
     <string name="global_action_lockdown" msgid="8751542514724332873">"Zárolás most"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
-    <string name="notification_children_count_bracketed" msgid="1769425473168347839">"(<xliff:g id="NOTIFICATIONCOUNT">%d</xliff:g>)"</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>
     <string name="safeMode" msgid="2788228061547930246">"Biztonsági üzemmód"</string>
@@ -1052,13 +1051,12 @@
     <string name="usb_notification_message" msgid="7347368030849048437">"Érintse meg a további lehetőségekhez."</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"USB hibakereső csatlakoztatva"</string>
     <string name="adb_active_notification_message" msgid="1016654627626476142">"Érintse meg az USB hibakeresés kikapcsolásához."</string>
+    <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Hibajelentés készítése…"</string>
     <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Megosztja a hibajelentést?"</string>
     <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Hibajelentés megosztása…"</string>
-    <string name="share_remote_bugreport_notification_message" msgid="752583906074230920">"A rendszergazda hibajelentést kért, hogy segíthessen az eszközzel kapcsolatos probléma megoldásában. Előfordulhat, hogy a rendszer megosztja az alkalmazásokat és adatokat, továbbá eszköze átmenetileg lelassulhat."</string>
-    <string name="share_finished_remote_bugreport_notification_message" msgid="4627312060769912353">"A rendszergazda hibajelentést kért, hogy segíthessen az eszközzel kapcsolatos probléma megoldásában. Előfordulhat, hogy a rendszer megosztja az alkalmazásokat és adatokat."</string>
-    <string name="sharing_remote_bugreport_notification_message" msgid="673106383408474893">"Előfordulhat, hogy eszköze emiatt átmenetileg lelassul"</string>
-    <string name="share_remote_bugreport_notification_accept" msgid="8203856129078669677">"ELFOGADOM"</string>
-    <string name="share_remote_bugreport_notification_decline" msgid="6337969352057443969">"ELUTASÍTOM"</string>
+    <string name="share_remote_bugreport_notification_message_finished" msgid="8610614010660772643">"A rendszergazda hibajelentést kért, hogy segíthessen az eszközzel kapcsolatos probléma megoldásában. Előfordulhat, hogy a rendszer megosztja az alkalmazásokat és adatokat."</string>
+    <string name="share_remote_bugreport_action" msgid="6249476773913384948">"MEGOSZTÁS"</string>
+    <string name="decline_remote_bugreport_action" msgid="6230987241608770062">"ELUTASÍTÁS"</string>
     <string name="select_input_method" msgid="8547250819326693584">"Billentyűzet megváltoztatása"</string>
     <string name="configure_input_methods" msgid="4769971288371946846">"Billentyűzetek kiválasztása"</string>
     <string name="show_ime" msgid="2506087537466597099">"Maradjon a képernyőn, amíg a billentyűzet aktív"</string>
@@ -1137,8 +1135,9 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Háttérkép"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Háttérkép megváltoztatása"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Értesítésfigyelő"</string>
+    <string name="vr_listener_binding_label" msgid="4316591939343607306">"Virtuálisvalóság-figyelő"</string>
     <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Feltételbiztosító"</string>
-    <string name="notification_assistant_binding_label" msgid="909456055569102952">"Értesítési segéd"</string>
+    <string name="notification_ranker_binding_label" msgid="774540592299064747">"Értesítésrangsoroló szolgáltatás"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN aktiválva"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"A(z) <xliff:g id="APP">%s</xliff:g> aktiválta a VPN-t"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Érintse meg a hálózat kezeléséhez."</string>
@@ -1467,7 +1466,7 @@
     <string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"PIN-kód kérése a rögzítés feloldásához"</string>
     <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Feloldási minta kérése a rögzítés feloldásához"</string>
     <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Jelszó kérése a rögzítés feloldásához"</string>
-    <string name="dock_cropped_windows_text" msgid="6378424064779004428">"Az alkalmazást nem lehet átméretezni – két ujjal görgessen."</string>
+    <string name="dock_forced_resizable" msgid="5914261505436217520">"Lehet, hogy az alkalmazás nem működik osztott képernyős nézetben."</string>
     <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"Az alkalmazás nem támogatja az osztott képernyős nézetet."</string>
     <string name="package_installed_device_owner" msgid="8420696545959087545">"A rendszergazda telepítette"</string>
     <string name="package_updated_device_owner" msgid="8856631322440187071">"Frissítette a rendszergazda"</string>
@@ -1541,7 +1540,7 @@
     <string name="importance_from_person" msgid="9160133597262938296">"Ez az üzenet a résztvevők miatt fontos."</string>
     <string name="user_creation_account_exists" msgid="1942606193570143289">"Engedélyezi a(z) <xliff:g id="APP">%1$s</xliff:g> számára, hogy új felhasználót hozzon létre a(z) <xliff:g id="ACCOUNT">%2$s</xliff:g> fiókkal?"</string>
     <string name="user_creation_adding" msgid="4482658054622099197">"Engedélyezi a(z) <xliff:g id="APP">%1$s</xliff:g> számára, hogy új felhasználót hozzon létre a(z) <xliff:g id="ACCOUNT">%2$s</xliff:g> fiókkal? (Már létezik felhasználó ezzel a fiókkal.)"</string>
-    <string name="language_selection_title" msgid="7181332986330337171">"Nyelvi beállítás"</string>
+    <string name="language_selection_title" msgid="2680677278159281088">"Nyelv hozzáadása"</string>
     <string name="country_selection_title" msgid="2954859441620215513">"Régió beállítása"</string>
     <string name="search_language_hint" msgid="7042102592055108574">"Adja meg a nyelvet"</string>
     <string name="language_picker_section_suggested" msgid="8414489646861640885">"Javasolt"</string>
@@ -1564,6 +1563,7 @@
     <string name="pin_target" msgid="3052256031352291362">"Rögzítés"</string>
     <string name="unpin_target" msgid="3556545602439143442">"Feloldás"</string>
     <string name="app_info" msgid="6856026610594615344">"Alkalmazásinformáció"</string>
-    <!-- no translation found for negative_duration (5688706061127375131) -->
-    <skip />
+    <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="audit_safemode_notification" msgid="6351827251856877200">"Gyári beállítások visszaállítása az eszköz normál módú használatához"</string>
+    <string name="audit_safemode_notification_details" msgid="1860601176690176413">"Érintse meg a további információkért."</string>
 </resources>
diff --git a/core/res/res/values-hy-rAM/strings.xml b/core/res/res/values-hy-rAM/strings.xml
index 1e71987..909a5c9 100644
--- a/core/res/res/values-hy-rAM/strings.xml
+++ b/core/res/res/values-hy-rAM/strings.xml
@@ -229,7 +229,6 @@
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Ձայնային օգնութ"</string>
     <string name="global_action_lockdown" msgid="8751542514724332873">"Կողպել հիմա"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
-    <string name="notification_children_count_bracketed" msgid="1769425473168347839">"(<xliff:g id="NOTIFICATIONCOUNT">%d</xliff:g>)"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"Բովանդակությունը թաքցված է"</string>
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Բովանդակությունը թաքցվել է ըստ քաղաքականության"</string>
     <string name="safeMode" msgid="2788228061547930246">"Անվտանգ ռեժիմ"</string>
@@ -1052,13 +1051,12 @@
     <string name="usb_notification_message" msgid="7347368030849048437">"Հպեք՝ լրացուցիչ ընտրանքների համար:"</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"USB վրիպազերծումը միացված է"</string>
     <string name="adb_active_notification_message" msgid="1016654627626476142">"Հպեք` USB կարգաբերումը կասեցնելու համար:"</string>
+    <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Վրիպակի զեկույցի ստեղծում…"</string>
     <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Տրամադրե՞լ վրիպակի զեկույցը:"</string>
     <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Վրիպակի զեկույցի տրամադրում…"</string>
-    <string name="share_remote_bugreport_notification_message" msgid="752583906074230920">"Այս սարքի անսարքությունների վերացման նպատակով ձեր ՏՏ ադմինիստրատորին անհրաժեշտ է վրիպակի զեկույց: Կարող են տրամադրվել տեղեկություններ ձեր հավելվածների մասին և այլ տվյալներ, իսկ սարքի աշխատանքը կարող է դանդաղել:"</string>
-    <string name="share_finished_remote_bugreport_notification_message" msgid="4627312060769912353">"Այս սարքի անսարքությունների վերացման նպատակով ձեր ՏՏ ադմինիստրատորին անհրաժեշտ է վրիպակի զեկույց: Կարող են տրամադրվել տեղեկություններ ձեր հավելվածներնի մասին և այլ տվյալներ:"</string>
-    <string name="sharing_remote_bugreport_notification_message" msgid="673106383408474893">"Այդ ընթացքում ձեր սարքի աշխատանքը կարող է դանդաղել"</string>
-    <string name="share_remote_bugreport_notification_accept" msgid="8203856129078669677">"ԸՆԴՈՒՆԵԼ"</string>
-    <string name="share_remote_bugreport_notification_decline" msgid="6337969352057443969">"ՄԵՐԺԵԼ"</string>
+    <string name="share_remote_bugreport_notification_message_finished" msgid="8610614010660772643">"Այս սարքի անսարքությունների վերացման նպատակով ձեր ՏՏ ադմինիստրատորին անհրաժեշտ է վրիպակի զեկույց: Կարող են տրամադրվել տեղեկություններ ձեր հավելվածների մասին և այլ տվյալներ:"</string>
+    <string name="share_remote_bugreport_action" msgid="6249476773913384948">"ՏՐԱՄԱԴՐԵԼ"</string>
+    <string name="decline_remote_bugreport_action" msgid="6230987241608770062">"ՄԵՐԺԵԼ"</string>
     <string name="select_input_method" msgid="8547250819326693584">"Փոխել ստեղնաշարը"</string>
     <string name="configure_input_methods" msgid="4769971288371946846">"Ընտրել ստեղնաշար"</string>
     <string name="show_ime" msgid="2506087537466597099">"Պահել էկրանին մինչդեռ ֆիզիկական ստեղնաշարն ակտիվ է"</string>
@@ -1137,8 +1135,9 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Պաստառ"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Փոխել պաստառը"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Ծանուցման ունկնդիր"</string>
+    <string name="vr_listener_binding_label" msgid="4316591939343607306">"VR ունկնդրիչ"</string>
     <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Պայմանների մատակարար"</string>
-    <string name="notification_assistant_binding_label" msgid="909456055569102952">"Ծանուցումների օգնական"</string>
+    <string name="notification_ranker_binding_label" msgid="774540592299064747">"Ըստ կարևորության ծանուցումների դասակարգման ծառայություն"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN-ը ակտիվացված է"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN-ն ակտիվացված է <xliff:g id="APP">%s</xliff:g>-ի կողմից"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Հպեք` ցանցի կառավարման համար:"</string>
@@ -1467,7 +1466,7 @@
     <string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Ապաամրացնելուց առաջ հարցնել PIN-կոդը"</string>
     <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Ապաամրացնելուց առաջ հարցնել ապակողպող նախշը"</string>
     <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Ապաամրացնելուց առաջ հարցնել գաղտնաբառը"</string>
-    <string name="dock_cropped_windows_text" msgid="6378424064779004428">"Հավելվածի չափը հնարավոր չէ փոխել, ոլորեք այն երկու մատի օգնությամբ:"</string>
+    <string name="dock_forced_resizable" msgid="5914261505436217520">"Հավելվածը չի կարող աշխատել տրոհված էկրանի ռեժիմում:"</string>
     <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"Հավելվածը չի աջակցում էկրանի տրոհումը:"</string>
     <string name="package_installed_device_owner" msgid="8420696545959087545">"Ադմինիստրատորը տեղադրել է այն"</string>
     <string name="package_updated_device_owner" msgid="8856631322440187071">"Ադմինիստրատորը թարմացրել է այն"</string>
@@ -1541,7 +1540,7 @@
     <string name="importance_from_person" msgid="9160133597262938296">"Կարևոր է, քանի որ որոշակի մարդիկ են ներգրավված:"</string>
     <string name="user_creation_account_exists" msgid="1942606193570143289">"Թույլ տա՞լ <xliff:g id="APP">%1$s</xliff:g> հավելվածին <xliff:g id="ACCOUNT">%2$s</xliff:g> հաշվով նոր Օգտվող ստեղծել:"</string>
     <string name="user_creation_adding" msgid="4482658054622099197">"Թույլ տա՞լ <xliff:g id="APP">%1$s</xliff:g> հավելվածին <xliff:g id="ACCOUNT">%2$s</xliff:g> հաշվով նոր Օգտվող ստեղծել (նման հաշվով Օգտվող արդեն գոյություն ունի):"</string>
-    <string name="language_selection_title" msgid="7181332986330337171">"Նախընտրելի լեզու"</string>
+    <string name="language_selection_title" msgid="2680677278159281088">"Ավելացնել լեզու"</string>
     <string name="country_selection_title" msgid="2954859441620215513">"Նախընտրելի տարածաշրջան"</string>
     <string name="search_language_hint" msgid="7042102592055108574">"Մուտքագրեք լեզուն"</string>
     <string name="language_picker_section_suggested" msgid="8414489646861640885">"Առաջարկներ"</string>
@@ -1564,6 +1563,7 @@
     <string name="pin_target" msgid="3052256031352291362">"Ամրացնել"</string>
     <string name="unpin_target" msgid="3556545602439143442">"Ապամրացնել"</string>
     <string name="app_info" msgid="6856026610594615344">"Հավելվածի տվյալներ"</string>
-    <!-- no translation found for negative_duration (5688706061127375131) -->
-    <skip />
+    <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="audit_safemode_notification" msgid="6351827251856877200">"Սարքը սովորական ռեժիմում օգտագործելու համար կատարեք գործարանային վերակայում"</string>
+    <string name="audit_safemode_notification_details" msgid="1860601176690176413">"Հպեք՝ ավելին իմանալու համար:"</string>
 </resources>
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index 5eacff7..14b7526 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -229,7 +229,6 @@
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Bantuan Suara"</string>
     <string name="global_action_lockdown" msgid="8751542514724332873">"Kunci sekarang"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
-    <string name="notification_children_count_bracketed" msgid="1769425473168347839">"(<xliff:g id="NOTIFICATIONCOUNT">%d</xliff:g>)"</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>
     <string name="safeMode" msgid="2788228061547930246">"Mode aman"</string>
@@ -1052,13 +1051,12 @@
     <string name="usb_notification_message" msgid="7347368030849048437">"Sentuh untuk opsi lainnya."</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"Debugging USB terhubung"</string>
     <string name="adb_active_notification_message" msgid="1016654627626476142">"Sentuh untuk menonaktifkan debugging USB."</string>
+    <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Mengambil laporan bug…"</string>
     <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Bagikan laporan bug?"</string>
     <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Membagikan laporan bug..."</string>
-    <string name="share_remote_bugreport_notification_message" msgid="752583906074230920">"Admin IT meminta laporan bug untuk membantu memecahkan masalah perangkat ini. Aplikasi dan data mungkin dibagikan dan untuk sementara perangkat mungkin menjadi lambat."</string>
-    <string name="share_finished_remote_bugreport_notification_message" msgid="4627312060769912353">"Admin IT meminta laporan bug untuk membantu memecahkan masalah perangkat ini. Aplikasi dan data mungkin dibagikan."</string>
-    <string name="sharing_remote_bugreport_notification_message" msgid="673106383408474893">"Tindakan ini mungkin memperlambat perangkat untuk sementara"</string>
-    <string name="share_remote_bugreport_notification_accept" msgid="8203856129078669677">"SETUJU"</string>
-    <string name="share_remote_bugreport_notification_decline" msgid="6337969352057443969">"TOLAK"</string>
+    <string name="share_remote_bugreport_notification_message_finished" msgid="8610614010660772643">"Admin IT meminta laporan bug untuk membantu memecahkan masalah perangkat ini. Aplikasi dan data mungkin dibagikan."</string>
+    <string name="share_remote_bugreport_action" msgid="6249476773913384948">"BAGIKAN"</string>
+    <string name="decline_remote_bugreport_action" msgid="6230987241608770062">"TOLAK"</string>
     <string name="select_input_method" msgid="8547250819326693584">"Ubah keyboard"</string>
     <string name="configure_input_methods" msgid="4769971288371946846">"Pilih keyboard"</string>
     <string name="show_ime" msgid="2506087537466597099">"Pertahankan di layar jika keyboard fisik masih aktif"</string>
@@ -1137,8 +1135,9 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Wallpaper"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Ubah wallpaper"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Pendengar pemberitahuan"</string>
+    <string name="vr_listener_binding_label" msgid="4316591939343607306">"Pemroses Realitas Maya"</string>
     <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Penyedia ketentuan"</string>
-    <string name="notification_assistant_binding_label" msgid="909456055569102952">"Asisten notifikasi"</string>
+    <string name="notification_ranker_binding_label" msgid="774540592299064747">"Layanan penentu peringkat notifikasi"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN diaktifkan"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN diaktifkan oleh <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Sentuh untuk mengelola jaringan."</string>
@@ -1467,7 +1466,7 @@
     <string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Meminta PIN sebelum melepas sematan"</string>
     <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Meminta pola pembukaan kunci sebelum melepas sematan"</string>
     <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Meminta sandi sebelum melepas sematan"</string>
-    <string name="dock_cropped_windows_text" msgid="6378424064779004428">"Aplikasi tidak dapat diubah ukurannya, gulir dengan dua jari."</string>
+    <string name="dock_forced_resizable" msgid="5914261505436217520">"Aplikasi mungkin tidak berfungsi dengan layar terpisah."</string>
     <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"App tidak mendukung layar terpisah."</string>
     <string name="package_installed_device_owner" msgid="8420696545959087545">"Dipasang oleh administrator"</string>
     <string name="package_updated_device_owner" msgid="8856631322440187071">"Diperbarui oleh administrator"</string>
@@ -1541,7 +1540,7 @@
     <string name="importance_from_person" msgid="9160133597262938296">"Ini penting karena orang-orang yang terlibat."</string>
     <string name="user_creation_account_exists" msgid="1942606193570143289">"Izinkan <xliff:g id="APP">%1$s</xliff:g> membuat Pengguna baru dengan <xliff:g id="ACCOUNT">%2$s</xliff:g> ?"</string>
     <string name="user_creation_adding" msgid="4482658054622099197">"Izinkan <xliff:g id="APP">%1$s</xliff:g> membuat Pengguna baru dengan <xliff:g id="ACCOUNT">%2$s</xliff:g> (Pengguna dengan akun ini sudah ada) ?"</string>
-    <string name="language_selection_title" msgid="7181332986330337171">"Preferensi bahasa"</string>
+    <string name="language_selection_title" msgid="2680677278159281088">"Tambahkan bahasa"</string>
     <string name="country_selection_title" msgid="2954859441620215513">"Preferensi wilayah"</string>
     <string name="search_language_hint" msgid="7042102592055108574">"Ketik nama bahasa"</string>
     <string name="language_picker_section_suggested" msgid="8414489646861640885">"Disarankan"</string>
@@ -1565,4 +1564,6 @@
     <string name="unpin_target" msgid="3556545602439143442">"Lepas pin"</string>
     <string name="app_info" msgid="6856026610594615344">"Info aplikasi"</string>
     <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="audit_safemode_notification" msgid="6351827251856877200">"Dikembalikan ke setelan pabrik untuk menggunakan perangkat ini secara normal"</string>
+    <string name="audit_safemode_notification_details" msgid="1860601176690176413">"Sentuh untuk mempelajari lebih lanjut."</string>
 </resources>
diff --git a/core/res/res/values-is-rIS/strings.xml b/core/res/res/values-is-rIS/strings.xml
index 6a64e94..e3278f3 100644
--- a/core/res/res/values-is-rIS/strings.xml
+++ b/core/res/res/values-is-rIS/strings.xml
@@ -229,7 +229,6 @@
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Raddaðstoð"</string>
     <string name="global_action_lockdown" msgid="8751542514724332873">"Læsa núna"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
-    <string name="notification_children_count_bracketed" msgid="1769425473168347839">"(<xliff:g id="NOTIFICATIONCOUNT">%d</xliff:g>)"</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>
     <string name="safeMode" msgid="2788228061547930246">"Örugg stilling"</string>
@@ -1052,13 +1051,12 @@
     <string name="usb_notification_message" msgid="7347368030849048437">"Snertu til að fá fleiri valkosti."</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"USB-villuleit tengd"</string>
     <string name="adb_active_notification_message" msgid="1016654627626476142">"Snertu til að slökkva á USB-villuleit."</string>
+    <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Tekur við villutilkynningu…"</string>
     <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Deila villutilkynningu?"</string>
     <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Deilir villutilkynningu..."</string>
-    <string name="share_remote_bugreport_notification_message" msgid="752583906074230920">"Kerfisstjórinn þinn óskaði eftir villutilkynningu til að auðvelda úrræðaleit á þessu tæki. Forritum og gögnum verður hugsanlega deilt og mögulegt er að þetta hægi tímabundið á tækinu."</string>
-    <string name="share_finished_remote_bugreport_notification_message" msgid="4627312060769912353">"Kerfisstjórinn þinn óskaði eftir villutilkynningu til að auðvelda úrræðaleit á þessu tæki. Forritum og gögnum verður hugsanlega deilt."</string>
-    <string name="sharing_remote_bugreport_notification_message" msgid="673106383408474893">"Hugsanlega hægir þetta tímabundið á tækinu þínu"</string>
-    <string name="share_remote_bugreport_notification_accept" msgid="8203856129078669677">"SAMÞYKKJA"</string>
-    <string name="share_remote_bugreport_notification_decline" msgid="6337969352057443969">"HAFNA"</string>
+    <string name="share_remote_bugreport_notification_message_finished" msgid="8610614010660772643">"Kerfisstjórinn þinn óskaði eftir villutilkynningu til að auðvelda úrræðaleit á þessu tæki. Forritum og gögnum verður hugsanlega deilt."</string>
+    <string name="share_remote_bugreport_action" msgid="6249476773913384948">"DEILA"</string>
+    <string name="decline_remote_bugreport_action" msgid="6230987241608770062">"HAFNA"</string>
     <string name="select_input_method" msgid="8547250819326693584">"Skipta um lyklaborð"</string>
     <string name="configure_input_methods" msgid="4769971288371946846">"Velja lyklaborð"</string>
     <string name="show_ime" msgid="2506087537466597099">"Haltu því á skjánum meðan vélbúnaðarlyklaborðið er virkt"</string>
@@ -1137,8 +1135,9 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Veggfóður"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Skipta um veggfóður"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Tilkynningahlustun"</string>
+    <string name="vr_listener_binding_label" msgid="4316591939343607306">"Sýndarveruleikavöktun"</string>
     <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Skilyrðaveita"</string>
-    <string name="notification_assistant_binding_label" msgid="909456055569102952">"Tilkynningaaðstoð"</string>
+    <string name="notification_ranker_binding_label" msgid="774540592299064747">"Tilkynningaröðun"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN virkjað"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN er virkjað með <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Snertu til að hafa umsjón með netinu."</string>
@@ -1467,7 +1466,7 @@
     <string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Biðja um PIN-númer til að losa"</string>
     <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Biðja um opnunarmynstur til að losa"</string>
     <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Biðja um aðgangsorð til að losa"</string>
-    <string name="dock_cropped_windows_text" msgid="6378424064779004428">"Ekki er hægt að breyta stærð forritsins; flettu upp og niður með tveimur fingrum."</string>
+    <string name="dock_forced_resizable" msgid="5914261505436217520">"Hugsanlega virkar forritið ekki ef skjánum er skipt upp."</string>
     <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"Forritið styður ekki að skjánum sé skipt."</string>
     <string name="package_installed_device_owner" msgid="8420696545959087545">"Uppsett af kerfisstjóra"</string>
     <string name="package_updated_device_owner" msgid="8856631322440187071">"Uppfært af kerfisstjóranum"</string>
@@ -1541,7 +1540,7 @@
     <string name="importance_from_person" msgid="9160133597262938296">"Þetta er mikilvægt vegna fólksins sem tekur þátt í þessu."</string>
     <string name="user_creation_account_exists" msgid="1942606193570143289">"Leyfa <xliff:g id="APP">%1$s</xliff:g> að stofna nýjan notanda með <xliff:g id="ACCOUNT">%2$s</xliff:g>?"</string>
     <string name="user_creation_adding" msgid="4482658054622099197">"Leyfa <xliff:g id="APP">%1$s</xliff:g> að stofna nýjan notanda með <xliff:g id="ACCOUNT">%2$s</xliff:g> (notandi með þennan reikning er þegar fyrir hendi)?"</string>
-    <string name="language_selection_title" msgid="7181332986330337171">"Val tungumáls"</string>
+    <string name="language_selection_title" msgid="2680677278159281088">"Bæta við tungumáli"</string>
     <string name="country_selection_title" msgid="2954859441620215513">"Svæðisval"</string>
     <string name="search_language_hint" msgid="7042102592055108574">"Sláðu inn heiti tungumáls"</string>
     <string name="language_picker_section_suggested" msgid="8414489646861640885">"Tillögur"</string>
@@ -1564,6 +1563,7 @@
     <string name="pin_target" msgid="3052256031352291362">"Festa"</string>
     <string name="unpin_target" msgid="3556545602439143442">"Losa"</string>
     <string name="app_info" msgid="6856026610594615344">"Forritsupplýsingar"</string>
-    <!-- no translation found for negative_duration (5688706061127375131) -->
-    <skip />
+    <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="audit_safemode_notification" msgid="6351827251856877200">"Núllstilltu til að nota þetta tæki í venjulegri stillingu"</string>
+    <string name="audit_safemode_notification_details" msgid="1860601176690176413">"Snertu til að fá frekari upplýsingar."</string>
 </resources>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index 55a6c86..6f1c1ec 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -229,7 +229,6 @@
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Voice Assist"</string>
     <string name="global_action_lockdown" msgid="8751542514724332873">"Blocca ora"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
-    <string name="notification_children_count_bracketed" msgid="1769425473168347839">"(<xliff:g id="NOTIFICATIONCOUNT">%d</xliff:g>)"</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>
     <string name="safeMode" msgid="2788228061547930246">"Modalità provvisoria"</string>
@@ -1052,13 +1051,12 @@
     <string name="usb_notification_message" msgid="7347368030849048437">"Tocca per visualizzare più opzioni."</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"Debug USB collegato"</string>
     <string name="adb_active_notification_message" msgid="1016654627626476142">"Tocca per disattivare il debug USB."</string>
+    <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Recupero della segnalazione di bug…"</string>
     <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Condividere la segnalazione di bug?"</string>
     <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Condivisione della segnalazione di bug…"</string>
-    <string name="share_remote_bugreport_notification_message" msgid="752583906074230920">"L\'amministratore IT ha richiesto una segnalazione di bug per poter risolvere più facilmente i problemi di questo dispositivo. Potrebbero essere condivisi dati e app e il dispositivo potrebbe rallentare temporaneamente."</string>
-    <string name="share_finished_remote_bugreport_notification_message" msgid="4627312060769912353">"L\'amministratore IT ha richiesto una segnalazione di bug per poter risolvere più facilmente i problemi di questo dispositivo. Potrebbero essere condivisi dati e app."</string>
-    <string name="sharing_remote_bugreport_notification_message" msgid="673106383408474893">"Il dispositivo potrebbe rallentare temporaneamente"</string>
-    <string name="share_remote_bugreport_notification_accept" msgid="8203856129078669677">"ACCETTO"</string>
-    <string name="share_remote_bugreport_notification_decline" msgid="6337969352057443969">"RIFIUTO"</string>
+    <string name="share_remote_bugreport_notification_message_finished" msgid="8610614010660772643">"L\'amministratore IT ha richiesto una segnalazione di bug per poter risolvere più facilmente i problemi di questo dispositivo. Potrebbero essere condivisi dati e app."</string>
+    <string name="share_remote_bugreport_action" msgid="6249476773913384948">"CONDIVIDI"</string>
+    <string name="decline_remote_bugreport_action" msgid="6230987241608770062">"RIFIUTO"</string>
     <string name="select_input_method" msgid="8547250819326693584">"Cambia tastiera"</string>
     <string name="configure_input_methods" msgid="4769971288371946846">"Scegli tastiera"</string>
     <string name="show_ime" msgid="2506087537466597099">"Tieni sullo schermo quando è attiva la tastiera fisica"</string>
@@ -1137,8 +1135,9 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Sfondo"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Cambia sfondo"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Listener di notifica"</string>
+    <string name="vr_listener_binding_label" msgid="4316591939343607306">"Listener realtà virtuale"</string>
     <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Provider condizioni"</string>
-    <string name="notification_assistant_binding_label" msgid="909456055569102952">"Assistente notifica"</string>
+    <string name="notification_ranker_binding_label" msgid="774540592299064747">"Servizio di classificazione delle notifiche"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN attiva"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN attivata da <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Tocca per gestire la rete."</string>
@@ -1467,7 +1466,7 @@
     <string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Richiedi il PIN per lo sblocco"</string>
     <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Richiedi sequenza di sblocco prima di sbloccare"</string>
     <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Richiedi password prima di sbloccare"</string>
-    <string name="dock_cropped_windows_text" msgid="6378424064779004428">"Non è possibile ridimensionare l\'app: scorri con due dita."</string>
+    <string name="dock_forced_resizable" msgid="5914261505436217520">"L\'app potrebbe non funzionare con lo schermo diviso."</string>
     <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"L\'app non supporta la modalità Schermo diviso."</string>
     <string name="package_installed_device_owner" msgid="8420696545959087545">"Installato dall\'amministratore"</string>
     <string name="package_updated_device_owner" msgid="8856631322440187071">"Aggiornato dall\'amministratore"</string>
@@ -1541,7 +1540,7 @@
     <string name="importance_from_person" msgid="9160133597262938296">"Importante a causa delle persone coinvolte."</string>
     <string name="user_creation_account_exists" msgid="1942606193570143289">"Consentire a <xliff:g id="APP">%1$s</xliff:g> di creare un nuovo utente con <xliff:g id="ACCOUNT">%2$s</xliff:g>?"</string>
     <string name="user_creation_adding" msgid="4482658054622099197">"Consentire a <xliff:g id="APP">%1$s</xliff:g> di creare un nuovo utente con <xliff:g id="ACCOUNT">%2$s</xliff:g>? (Esiste già un utente con questo account)"</string>
-    <string name="language_selection_title" msgid="7181332986330337171">"Preferenza lingua"</string>
+    <string name="language_selection_title" msgid="2680677278159281088">"Aggiungi una lingua"</string>
     <string name="country_selection_title" msgid="2954859441620215513">"Area geografica preferita"</string>
     <string name="search_language_hint" msgid="7042102592055108574">"Digita nome lingua"</string>
     <string name="language_picker_section_suggested" msgid="8414489646861640885">"Suggerite"</string>
@@ -1565,4 +1564,6 @@
     <string name="unpin_target" msgid="3556545602439143442">"Sblocca"</string>
     <string name="app_info" msgid="6856026610594615344">"Informazioni app"</string>
     <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="audit_safemode_notification" msgid="6351827251856877200">"Esegui il ripristino dei dati di fabbrica per utilizzare normalmente il dispositivo"</string>
+    <string name="audit_safemode_notification_details" msgid="1860601176690176413">"Tocca per ulteriori informazioni."</string>
 </resources>
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index 5fe8842..8ac3490 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/strings.xml
@@ -233,7 +233,6 @@
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Voice Assist"</string>
     <string name="global_action_lockdown" msgid="8751542514724332873">"נעל עכשיו"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
-    <string name="notification_children_count_bracketed" msgid="1769425473168347839">"(<xliff:g id="NOTIFICATIONCOUNT">%d</xliff:g>)"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"התוכן מוסתר"</string>
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"התוכן מוסתר על ידי המדיניות"</string>
     <string name="safeMode" msgid="2788228061547930246">"מצב בטוח"</string>
@@ -1068,13 +1067,12 @@
     <string name="usb_notification_message" msgid="7347368030849048437">"גע להצגת עוד אפשרויות."</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"‏ניפוי באגים של USB מחובר"</string>
     <string name="adb_active_notification_message" msgid="1016654627626476142">"‏גע כדי להשבית ניפוי באגים בהתקן ה-USB."</string>
+    <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"עיבוד דוח על באג..."</string>
     <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"האם לשתף דוח על באג?"</string>
     <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"שיתוף דוח על באג…"</string>
-    <string name="share_remote_bugreport_notification_message" msgid="752583906074230920">"‏מנהל ה-IT ביקש דוח על באג כדי לסייע בפתרון בעיות במכשיר זה. ייתכן שאפליקציות ונתונים ישותפו. פעילות המכשיר עשויה להאט באופן זמני."</string>
-    <string name="share_finished_remote_bugreport_notification_message" msgid="4627312060769912353">"‏מנהל ה-IT שלך ביקש דוח על באג כדי לסייע בפתרון בעיות במכשיר זה. ייתכן שאפליקציות ונתונים ישותפו."</string>
-    <string name="sharing_remote_bugreport_notification_message" msgid="673106383408474893">"קצב הפעולה של המכשיר עשוי להיות איטי יותר באופן זמני כתוצאה מכך"</string>
-    <string name="share_remote_bugreport_notification_accept" msgid="8203856129078669677">"אישור"</string>
-    <string name="share_remote_bugreport_notification_decline" msgid="6337969352057443969">"דחייה"</string>
+    <string name="share_remote_bugreport_notification_message_finished" msgid="8610614010660772643">"‏מנהל ה-IT שלך ביקש דוח על באג כדי לסייע בפתרון בעיות במכשיר זה. ייתכן שאפליקציות ונתונים ישותפו."</string>
+    <string name="share_remote_bugreport_action" msgid="6249476773913384948">"שתף"</string>
+    <string name="decline_remote_bugreport_action" msgid="6230987241608770062">"דחה"</string>
     <string name="select_input_method" msgid="8547250819326693584">"שינוי מקלדת"</string>
     <string name="configure_input_methods" msgid="4769971288371946846">"בחר מקלדות"</string>
     <string name="show_ime" msgid="2506087537466597099">"השאר אותו במסך בזמן שהמקלדת הפיזית פעילה"</string>
@@ -1153,8 +1151,9 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"טפט"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"שנה טפט"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"מאזין להתראות"</string>
+    <string name="vr_listener_binding_label" msgid="4316591939343607306">"‏מאזין VR"</string>
     <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"ספק תנאי"</string>
-    <string name="notification_assistant_binding_label" msgid="909456055569102952">"אסיסטנט ההודעות"</string>
+    <string name="notification_ranker_binding_label" msgid="774540592299064747">"שירות של דירוג הודעות"</string>
     <string name="vpn_title" msgid="19615213552042827">"‏VPN מופעל"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"‏VPN מופעל על ידי <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"גע כדי לנהל את הרשת."</string>
@@ -1487,7 +1486,7 @@
     <string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"‏בקש PIN לפני ביטול הצמדה"</string>
     <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"בקש קו ביטול נעילה לפני ביטול הצמדה"</string>
     <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"בקש סיסמה לפני ביטול הצמדה"</string>
-    <string name="dock_cropped_windows_text" msgid="6378424064779004428">"אין אפשרות לשנות את גודל האפליקציה, גלול אותה בשתי אצבעות."</string>
+    <string name="dock_forced_resizable" msgid="5914261505436217520">"ייתכן שהיישום לא יפעל עם מסך מפוצל."</string>
     <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"האפליקציה אינה תומכת במסך מפוצל."</string>
     <string name="package_installed_device_owner" msgid="8420696545959087545">"הותקנה על ידי מנהל המערכת שלך"</string>
     <string name="package_updated_device_owner" msgid="8856631322440187071">"עודכן על ידי מנהל המערכת שלך"</string>
@@ -1579,7 +1578,7 @@
     <string name="importance_from_person" msgid="9160133597262938296">"ההודעה חשובה בשל האנשים המעורבים."</string>
     <string name="user_creation_account_exists" msgid="1942606193570143289">"האם לאפשר ל-<xliff:g id="APP">%1$s</xliff:g> ליצור משתמש חדש לחשבון <xliff:g id="ACCOUNT">%2$s</xliff:g> ?"</string>
     <string name="user_creation_adding" msgid="4482658054622099197">"האם לאפשר ל-<xliff:g id="APP">%1$s</xliff:g> ליצור משתמש חדש לחשבון <xliff:g id="ACCOUNT">%2$s</xliff:g> (כבר קיים משתמש לחשבון הזה) ?"</string>
-    <string name="language_selection_title" msgid="7181332986330337171">"העדפת שפה"</string>
+    <string name="language_selection_title" msgid="2680677278159281088">"הוספת שפה"</string>
     <string name="country_selection_title" msgid="2954859441620215513">"העדפת אזור"</string>
     <string name="search_language_hint" msgid="7042102592055108574">"הקלד שם שפה"</string>
     <string name="language_picker_section_suggested" msgid="8414489646861640885">"הצעות"</string>
@@ -1603,4 +1602,6 @@
     <string name="unpin_target" msgid="3556545602439143442">"בטל הצמדה"</string>
     <string name="app_info" msgid="6856026610594615344">"פרטי אפליקציה"</string>
     <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="audit_safemode_notification" msgid="6351827251856877200">"איפוס להגדרות היצרן לצורך שימוש במכשיר זה באופן רגיל"</string>
+    <string name="audit_safemode_notification_details" msgid="1860601176690176413">"גע לקבלת מידע נוסף."</string>
 </resources>
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index e9dde2b..5c97295 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -213,8 +213,7 @@
     <string name="bugreport_option_interactive_title" msgid="8635056131768862479">"対話型レポート"</string>
     <string name="bugreport_option_interactive_summary" msgid="8180152634022797629">"ほとんどの場合はこのオプションを使用します。レポートの進行状況を追跡し、問題についての詳細情報を確認することができます。レポート作成に時間がかかってもあまり使用されないセクションは省略されることがあります。"</string>
     <string name="bugreport_option_full_title" msgid="6354382025840076439">"完全レポート"</string>
-    <!-- no translation found for bugreport_option_full_summary (6687306111256813257) -->
-    <skip />
+    <string name="bugreport_option_full_summary" msgid="6687306111256813257">"端末の反応がないとき、または速度が遅すぎるときにシステムへの影響を最小限に抑えたい場合は、このオプションを使用します。またすべてのレポート セクションを表示したい場合にもこのオプションを使用します。スクリーンショットは作成されず、詳細情報も表示できません。"</string>
     <plurals name="bugreport_countdown" formatted="false" msgid="6878900193900090368">
       <item quantity="other"><xliff:g id="NUMBER_1">%d</xliff:g> 秒後にバグレポートのスクリーンショットが作成されます。</item>
       <item quantity="one"><xliff:g id="NUMBER_0">%d</xliff:g> 秒後にバグレポートのスクリーンショットが作成されます。</item>
@@ -230,7 +229,6 @@
     <string name="global_action_voice_assist" msgid="7751191495200504480">"音声アシスト"</string>
     <string name="global_action_lockdown" msgid="8751542514724332873">"今すぐロック"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
-    <string name="notification_children_count_bracketed" msgid="1769425473168347839">"(<xliff:g id="NOTIFICATIONCOUNT">%d</xliff:g> 件)"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"コンテンツが非表示"</string>
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"ポリシーによって非表示になっているコンテンツ"</string>
     <string name="safeMode" msgid="2788228061547930246">"セーフモード"</string>
@@ -1053,13 +1051,12 @@
     <string name="usb_notification_message" msgid="7347368030849048437">"タップしてその他のオプションを表示"</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"USBデバッグが接続されました"</string>
     <string name="adb_active_notification_message" msgid="1016654627626476142">"タップしてUSBデバッグを無効化"</string>
+    <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"バグレポートを取得しています…"</string>
     <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"バグレポートを共有しますか?"</string>
     <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"バグレポートの共有中…"</string>
-    <string name="share_remote_bugreport_notification_message" msgid="752583906074230920">"IT 管理者からこの端末のトラブルシューティングに役立てるためバグレポートを共有するようリクエストがありました。アプリやデータが共有され、端末の動作が一時的に遅くなる場合があります。"</string>
-    <string name="share_finished_remote_bugreport_notification_message" msgid="4627312060769912353">"IT 管理者からこの端末のトラブルシューティングに役立てるためバグレポートを共有するようリクエストがありました。アプリやデータが共有されることがあります。"</string>
-    <string name="sharing_remote_bugreport_notification_message" msgid="673106383408474893">"共有によって端末の動作が一時的に遅くなる場合があります"</string>
-    <string name="share_remote_bugreport_notification_accept" msgid="8203856129078669677">"同意する"</string>
-    <string name="share_remote_bugreport_notification_decline" msgid="6337969352057443969">"同意しない"</string>
+    <string name="share_remote_bugreport_notification_message_finished" msgid="8610614010660772643">"IT 管理者からこの端末のトラブルシューティングに役立てるためバグレポートを共有するようリクエストがありました。アプリやデータが共有されることがあります。"</string>
+    <string name="share_remote_bugreport_action" msgid="6249476773913384948">"共有する"</string>
+    <string name="decline_remote_bugreport_action" msgid="6230987241608770062">"共有しない"</string>
     <string name="select_input_method" msgid="8547250819326693584">"キーボードの変更"</string>
     <string name="configure_input_methods" msgid="4769971288371946846">"キーボードの選択"</string>
     <string name="show_ime" msgid="2506087537466597099">"物理キーボードが有効になっている間は、画面に表示されます"</string>
@@ -1138,8 +1135,9 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"壁紙"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"壁紙を変更"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"通知リスナー"</string>
+    <string name="vr_listener_binding_label" msgid="4316591939343607306">"VR リスナー"</string>
     <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"コンディションプロバイダ"</string>
-    <string name="notification_assistant_binding_label" msgid="909456055569102952">"通知アシスタント"</string>
+    <string name="notification_ranker_binding_label" msgid="774540592299064747">"通知ランカー サービス"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPNが有効になりました"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"VPNが<xliff:g id="APP">%s</xliff:g>により有効化されました"</string>
     <string name="vpn_text" msgid="3011306607126450322">"タップしてネットワークを管理します。"</string>
@@ -1468,7 +1466,7 @@
     <string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"オフライン再生を解除する前にPINの入力を求める"</string>
     <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"画面固定を解除する前にロック解除パターンの入力を求める"</string>
     <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"オフライン再生を解除する前にパスワードの入力を求める"</string>
-    <string name="dock_cropped_windows_text" msgid="6378424064779004428">"アプリのサイズは変更できません。2 本の指でスクロールしてください。"</string>
+    <string name="dock_forced_resizable" msgid="5914261505436217520">"アプリは分割画面では動作しないことがあります。"</string>
     <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"アプリで分割画面がサポートされていません。"</string>
     <string name="package_installed_device_owner" msgid="8420696545959087545">"管理者によってインストールされました"</string>
     <string name="package_updated_device_owner" msgid="8856631322440187071">"管理者によって更新されています"</string>
@@ -1542,22 +1540,17 @@
     <string name="importance_from_person" msgid="9160133597262938296">"関係するユーザーのため、この設定は重要です。"</string>
     <string name="user_creation_account_exists" msgid="1942606193570143289">"<xliff:g id="APP">%1$s</xliff:g> が <xliff:g id="ACCOUNT">%2$s</xliff:g> で新しいユーザーを作成できるようにしますか?"</string>
     <string name="user_creation_adding" msgid="4482658054622099197">"<xliff:g id="APP">%1$s</xliff:g> が <xliff:g id="ACCOUNT">%2$s</xliff:g> で新しいユーザーを作成できるようにしますか?(このアカウントのユーザーはすでに存在します)"</string>
-    <string name="language_selection_title" msgid="7181332986330337171">"言語設定"</string>
+    <string name="language_selection_title" msgid="2680677278159281088">"言語を追加"</string>
     <string name="country_selection_title" msgid="2954859441620215513">"地域設定"</string>
     <string name="search_language_hint" msgid="7042102592055108574">"言語名を入力"</string>
     <string name="language_picker_section_suggested" msgid="8414489646861640885">"言語の候補"</string>
     <string name="language_picker_section_all" msgid="3097279199511617537">"すべての言語"</string>
     <string name="locale_search_menu" msgid="2560710726687249178">"検索"</string>
-    <!-- no translation found for work_mode_off_title (8954725060677558855) -->
-    <skip />
-    <!-- no translation found for work_mode_off_message (3286169091278094476) -->
-    <skip />
-    <!-- no translation found for work_mode_turn_on (2062544985670564875) -->
-    <skip />
-    <!-- no translation found for suspended_package_title (3408150347778524435) -->
-    <skip />
-    <!-- no translation found for suspended_package_message (6341091587106868601) -->
-    <skip />
+    <string name="work_mode_off_title" msgid="8954725060677558855">"Work モード OFF"</string>
+    <string name="work_mode_off_message" msgid="3286169091278094476">"仕事用プロファイルで、アプリ、バックグラウンド同期などの関連機能の使用を許可します。"</string>
+    <string name="work_mode_turn_on" msgid="2062544985670564875">"ON にする"</string>
+    <string name="suspended_package_title" msgid="3408150347778524435">"%1$sが無効です"</string>
+    <string name="suspended_package_message" msgid="6341091587106868601">"%1$s管理者によって無効になっています。詳しくは管理者までお問い合わせください。"</string>
     <string name="new_sms_notification_title" msgid="8442817549127555977">"新着メッセージがあります"</string>
     <string name="new_sms_notification_content" msgid="7002938807812083463">"表示するには SMS アプリを開きます"</string>
     <string name="user_encrypted_title" msgid="9054897468831672082">"一部機能が制限されている可能性"</string>
@@ -1571,4 +1564,6 @@
     <string name="unpin_target" msgid="3556545602439143442">"固定を解除"</string>
     <string name="app_info" msgid="6856026610594615344">"アプリ情報"</string>
     <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="audit_safemode_notification" msgid="6351827251856877200">"この端末は正常に使用するために出荷時設定にリセットされました"</string>
+    <string name="audit_safemode_notification_details" msgid="1860601176690176413">"タップして詳細をご確認ください。"</string>
 </resources>
diff --git a/core/res/res/values-ka-rGE/strings.xml b/core/res/res/values-ka-rGE/strings.xml
index fa6dac2..15167f7 100644
--- a/core/res/res/values-ka-rGE/strings.xml
+++ b/core/res/res/values-ka-rGE/strings.xml
@@ -229,7 +229,6 @@
     <string name="global_action_voice_assist" msgid="7751191495200504480">"ხმოვანი ასისტ."</string>
     <string name="global_action_lockdown" msgid="8751542514724332873">"ახლა ჩაკეტვა"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
-    <string name="notification_children_count_bracketed" msgid="1769425473168347839">"(<xliff:g id="NOTIFICATIONCOUNT">%d</xliff:g>)"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"შიგთავსი დამალულია"</string>
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"შიგთავსი დამალულია წესების შესაბამისად"</string>
     <string name="safeMode" msgid="2788228061547930246">"უსაფრთხო რეჟიმი"</string>
@@ -1052,13 +1051,12 @@
     <string name="usb_notification_message" msgid="7347368030849048437">"შეეხეთ დამატებითი პარამეტრებისთვის."</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"USB გამართვა შეერთებულია"</string>
     <string name="adb_active_notification_message" msgid="1016654627626476142">"შეეხეთ, რათა შეწყვიტოთ USB-ის გამართვა."</string>
+    <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"მიმდინარეობს ხარვეზის შესახებ ანგარიშის შექმნა…"</string>
     <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"გსურთ ხარვეზის შესახებ ანგარიშის გაზიარება?"</string>
     <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"მიმდინარეობს ხარვეზის შესახებ ანგარიშის გაზიარება…"</string>
-    <string name="share_remote_bugreport_notification_message" msgid="752583906074230920">"ამ მოწყობილობის პრობლემების აღმოფხვრაში დასახმარებლად, თქვენი IT ადმინისტრატორი ხარვეზის შესახებ ანგარიშს ითხოვს, რა დროსაც შეიძლება გაზიარდეს აპები და მონაცემები, ხოლო თქვენი მოწყობილობა დროებით შენელდეს."</string>
-    <string name="share_finished_remote_bugreport_notification_message" msgid="4627312060769912353">"ამ მოწყობილობის პრობლემების აღმოფხვრაში დასახმარებლად, თქვენი IT ადმინისტრატორი ხარვეზის შესახებ ანგარიშს ითხოვს, რა დროსაც შეიძლება გაზიარდეს აპები და მონაცემები."</string>
-    <string name="sharing_remote_bugreport_notification_message" msgid="673106383408474893">"ამან შეიძლება დროებით შეანელოს თქვენი მოწყობილობა"</string>
-    <string name="share_remote_bugreport_notification_accept" msgid="8203856129078669677">"მიღება"</string>
-    <string name="share_remote_bugreport_notification_decline" msgid="6337969352057443969">"უარყოფა"</string>
+    <string name="share_remote_bugreport_notification_message_finished" msgid="8610614010660772643">"ამ მოწყობილობის პრობლემების აღმოფხვრაში დასახმარებლად, თქვენი IT ადმინისტრატორი ხარვეზის შესახებ ანგარიშს ითხოვს, რა დროსაც შეიძლება გაზიარდეს აპები და მონაცემები."</string>
+    <string name="share_remote_bugreport_action" msgid="6249476773913384948">"გაზიარება"</string>
+    <string name="decline_remote_bugreport_action" msgid="6230987241608770062">"უარყოფა"</string>
     <string name="select_input_method" msgid="8547250819326693584">"კლავიატურის შეცვლა"</string>
     <string name="configure_input_methods" msgid="4769971288371946846">"კლავიატურების არჩევა"</string>
     <string name="show_ime" msgid="2506087537466597099">"აქტიური ფიზიკური კლავიატურისას ეკრანზე შენარჩუნება"</string>
@@ -1137,8 +1135,9 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"ფონი"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"ფონის შეცვლა"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"შეტყობინებების მსმენელი"</string>
+    <string name="vr_listener_binding_label" msgid="4316591939343607306">"ვირტუალური რეალობის მსმენელი"</string>
     <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"მდგომარეობის პროვაიდერი"</string>
-    <string name="notification_assistant_binding_label" msgid="909456055569102952">"შეტყობინებათა ასისტენტი"</string>
+    <string name="notification_ranker_binding_label" msgid="774540592299064747">"შეტყობინებების მნიშვნელობის დონის შეფასების სერვისი"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN გააქტიურებულია"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN გააქტიურებულია <xliff:g id="APP">%s</xliff:g>-ის მიერ"</string>
     <string name="vpn_text" msgid="3011306607126450322">"შეეხეთ ქსელის სამართავად."</string>
@@ -1467,7 +1466,7 @@
     <string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"ფიქსაციის მოხსნამდე PIN-ის მოთხოვნა"</string>
     <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"ფიქსაციის მოხსნამდე განბლოკვის ნიმუშის მოთხოვნა"</string>
     <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"ფიქსაციის მოხსნამდე პაროლის მოთხოვნა"</string>
-    <string name="dock_cropped_windows_text" msgid="6378424064779004428">"აპის ზომა ვერ შეიცვლება. გადაადგილდით მასში ორი თითის მეშვეობით."</string>
+    <string name="dock_forced_resizable" msgid="5914261505436217520">"აპმა შეიძლება არ იმუშაოს გაყოფილი ეკრანის რეჟიმში."</string>
     <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"ეკრანის გაყოფა არ არის მხარდაჭერილი აპის მიერ."</string>
     <string name="package_installed_device_owner" msgid="8420696545959087545">"თქვენი ადმინისტრატორის მიერ დაყენებული"</string>
     <string name="package_updated_device_owner" msgid="8856631322440187071">"განახლებულია თქვენი ადმინისტრატორის მიერ"</string>
@@ -1541,7 +1540,7 @@
     <string name="importance_from_person" msgid="9160133597262938296">"მნიშვნელოვანია ჩართული მომხმარებლების გამო."</string>
     <string name="user_creation_account_exists" msgid="1942606193570143289">"მიეცეს უფლება <xliff:g id="APP">%1$s</xliff:g>-ს, <xliff:g id="ACCOUNT">%2$s</xliff:g>-ის მეშვეობით ახალი მომხმარებელი შექმნას ?"</string>
     <string name="user_creation_adding" msgid="4482658054622099197">"მიეცეს უფლება <xliff:g id="APP">%1$s</xliff:g>-ს, <xliff:g id="ACCOUNT">%2$s</xliff:g>-ის მეშვეობით ახალი მომხმარებელი შექმნას (ამ ანგარიშის მქონე მომხმარებელი უკვე არსებობს) ?"</string>
-    <string name="language_selection_title" msgid="7181332986330337171">"ენის პარამეტრები"</string>
+    <string name="language_selection_title" msgid="2680677278159281088">"ენის დამატება"</string>
     <string name="country_selection_title" msgid="2954859441620215513">"რეგიონის პარამეტრები"</string>
     <string name="search_language_hint" msgid="7042102592055108574">"აკრიფეთ ენის სახელი"</string>
     <string name="language_picker_section_suggested" msgid="8414489646861640885">"რეკომენდებული"</string>
@@ -1564,6 +1563,7 @@
     <string name="pin_target" msgid="3052256031352291362">"ჩამაგრება"</string>
     <string name="unpin_target" msgid="3556545602439143442">"ჩამაგრების მოხსნა"</string>
     <string name="app_info" msgid="6856026610594615344">"აპის შესახებ"</string>
-    <!-- no translation found for negative_duration (5688706061127375131) -->
-    <skip />
+    <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="audit_safemode_notification" msgid="6351827251856877200">"ამ მოწყობილობის ჩვეულებრივად გამოსაყენებლად, დააბრუნეთ ქარხნული პარამეტრები"</string>
+    <string name="audit_safemode_notification_details" msgid="1860601176690176413">"შეეხეთ მეტის გასაგებად."</string>
 </resources>
diff --git a/core/res/res/values-kk-rKZ/strings.xml b/core/res/res/values-kk-rKZ/strings.xml
index 81e8ecd..24b5e07 100644
--- a/core/res/res/values-kk-rKZ/strings.xml
+++ b/core/res/res/values-kk-rKZ/strings.xml
@@ -229,7 +229,6 @@
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Дауыс көмекшісі"</string>
     <string name="global_action_lockdown" msgid="8751542514724332873">"Қазір бекіту"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
-    <string name="notification_children_count_bracketed" msgid="1769425473168347839">"(<xliff:g id="NOTIFICATIONCOUNT">%d</xliff:g>)"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"Мазмұн жасырылған"</string>
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Мазмұн саясатқа сай жасырылған"</string>
     <string name="safeMode" msgid="2788228061547930246">"Қауіпсіз режим"</string>
@@ -1052,13 +1051,12 @@
     <string name="usb_notification_message" msgid="7347368030849048437">"Қосымша параметрлер үшін түртіңіз."</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"USB жөндеу қосылған"</string>
     <string name="adb_active_notification_message" msgid="1016654627626476142">"USB жөндеуді өшіру үшін түртіңіз."</string>
+    <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Қате туралы есеп алынуда…"</string>
     <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Қате туралы есепті бөлісу керек пе?"</string>
     <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Қате туралы есеп бөлісілуде…"</string>
-    <string name="share_remote_bugreport_notification_message" msgid="752583906074230920">"АТ әкімшісі осы құрылғы ақауларын жоюға көмектесу үшін қате туралы есепті сұрады. Қолданбалар және деректер бөлісілуі әрі құрылғының жұмысы уақытша баяулауы мүмкін."</string>
-    <string name="share_finished_remote_bugreport_notification_message" msgid="4627312060769912353">"АТ әкімшісі осы құрылғы ақауларын жоюға көмектесу үшін қате туралы есепті сұрады. Қолданбалар және деректер бөлісілуі мүмкін."</string>
-    <string name="sharing_remote_bugreport_notification_message" msgid="673106383408474893">"Бұл құрылғы жұмысын уақытша баяулатуы мүмкін"</string>
-    <string name="share_remote_bugreport_notification_accept" msgid="8203856129078669677">"ҚАБЫЛДАУ"</string>
-    <string name="share_remote_bugreport_notification_decline" msgid="6337969352057443969">"ҚАБЫЛДАМАУ"</string>
+    <string name="share_remote_bugreport_notification_message_finished" msgid="8610614010660772643">"АТ әкімшісі осы құрылғы ақауларын жоюға көмектесу үшін қате туралы есепті сұрады. Қолданбалар мен деректерді бөлісуі мүмкін."</string>
+    <string name="share_remote_bugreport_action" msgid="6249476773913384948">"БӨЛІСУ"</string>
+    <string name="decline_remote_bugreport_action" msgid="6230987241608770062">"ҚАБЫЛДАМАУ"</string>
     <string name="select_input_method" msgid="8547250819326693584">"Пернетақтаны өзгерту"</string>
     <string name="configure_input_methods" msgid="4769971288371946846">"Пернетақталарды таңдау"</string>
     <string name="show_ime" msgid="2506087537466597099">"Физикалық пернетақта белсенді кезде оны экранда ұстау"</string>
@@ -1137,8 +1135,9 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Артқы фоны"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Артқы фонын өзгерту"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Хабар бақылағыш"</string>
+    <string name="vr_listener_binding_label" msgid="4316591939343607306">"VR тыңдаушы"</string>
     <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Шарт провайдері"</string>
-    <string name="notification_assistant_binding_label" msgid="909456055569102952">"Хабарландыру көмекшісі"</string>
+    <string name="notification_ranker_binding_label" msgid="774540592299064747">"Хабарландыруларды жіктеу қызметі"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN белсенді"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"ВЖЭ <xliff:g id="APP">%s</xliff:g> арқылы қосылған"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Желіні басқару үшін түрту."</string>
@@ -1467,7 +1466,7 @@
     <string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Босату алдында PIN кодын сұрау"</string>
     <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Босату алдында бекітпесін ашу өрнегін сұрау"</string>
     <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Босату алдында құпия сөзді сұрау"</string>
-    <string name="dock_cropped_windows_text" msgid="6378424064779004428">"Қолданба өлшемін өзгерту мүмкін емес, оны екі саусақпен айналдырыңыз."</string>
+    <string name="dock_forced_resizable" msgid="5914261505436217520">"Қолданба бөлінген экранда жұмыс істемеуі мүмкін."</string>
     <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"Қодланба бөлінген экранды қолдамайды."</string>
     <string name="package_installed_device_owner" msgid="8420696545959087545">"Әкімші орнатқан"</string>
     <string name="package_updated_device_owner" msgid="8856631322440187071">"Әкімші жаңартты"</string>
@@ -1541,7 +1540,7 @@
     <string name="importance_from_person" msgid="9160133597262938296">"Қатысты адамдарға байланысты бұл маңызды."</string>
     <string name="user_creation_account_exists" msgid="1942606193570143289">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACCOUNT">%2$s</xliff:g> есептік жазбасы бар жаңа пайдаланушы жасауға рұқсат ету керек пе?"</string>
     <string name="user_creation_adding" msgid="4482658054622099197">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACCOUNT">%2$s</xliff:g> есептік жазбасында жаңа пайдаланушы жасауға рұқсат ету керек пе (осы есептік жазбасы бар пайдаланушы әлдеқашан бар) ?"</string>
-    <string name="language_selection_title" msgid="7181332986330337171">"Тіл параметрі"</string>
+    <string name="language_selection_title" msgid="2680677278159281088">"Тілді қосу"</string>
     <string name="country_selection_title" msgid="2954859441620215513">"Аймақ параметрі"</string>
     <string name="search_language_hint" msgid="7042102592055108574">"Тіл атауын теріңіз"</string>
     <string name="language_picker_section_suggested" msgid="8414489646861640885">"Ұсынылған"</string>
@@ -1564,6 +1563,7 @@
     <string name="pin_target" msgid="3052256031352291362">"PIN код"</string>
     <string name="unpin_target" msgid="3556545602439143442">"Босату"</string>
     <string name="app_info" msgid="6856026610594615344">"Қолданба ақпараты"</string>
-    <!-- no translation found for negative_duration (5688706061127375131) -->
-    <skip />
+    <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="audit_safemode_notification" msgid="6351827251856877200">"Осы құрылғыны әдеттегідей пайдалану үшін зауыттық параметрлерді қалпына келтіріңіз"</string>
+    <string name="audit_safemode_notification_details" msgid="1860601176690176413">"Қосымша мәліметтер алу үшін түртіңіз."</string>
 </resources>
diff --git a/core/res/res/values-km-rKH/strings.xml b/core/res/res/values-km-rKH/strings.xml
index 46a951f..e3e46b0 100644
--- a/core/res/res/values-km-rKH/strings.xml
+++ b/core/res/res/values-km-rKH/strings.xml
@@ -229,7 +229,6 @@
     <string name="global_action_voice_assist" msgid="7751191495200504480">"ជំនួយសម្លេង"</string>
     <string name="global_action_lockdown" msgid="8751542514724332873">"ចាក់សោ​ឥឡូវនេះ"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
-    <string name="notification_children_count_bracketed" msgid="1769425473168347839">"(<xliff:g id="NOTIFICATIONCOUNT">%d</xliff:g>)"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"បាន​លាក់​មាតិកា"</string>
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"មាតិកាត្រូវបានលាក់ដោយផ្អែកលើគោលការណ៍"</string>
     <string name="safeMode" msgid="2788228061547930246">"របៀប​​​សុវត្ថិភាព"</string>
@@ -1054,13 +1053,12 @@
     <string name="usb_notification_message" msgid="7347368030849048437">"ប៉ះដើម្បីបានជម្រើសថែមទៀត។"</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"បាន​ភ្ជាប់​ការ​កែ​កំហុស​យូអេសប៊ី"</string>
     <string name="adb_active_notification_message" msgid="1016654627626476142">"ប៉ះ ដើម្បី​បិទ​ការ​កែ​កំហុស​យូអេសប៊ី។"</string>
+    <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"កំពុងទទួលយករបាយការណ៍កំហុស…"</string>
     <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"ចែករំលែករបាយការណ៍កំហុសឬ?"</string>
     <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"កំពុងចែករំលែករបាយកំហុស…"</string>
-    <string name="share_remote_bugreport_notification_message" msgid="752583906074230920">"អ្នកគ្រប់គ្រងផ្នែកព័ត៌មានវិទ្យារបស់អ្នកបានស្នើរបាយការណ៍កំហុសដើម្បីដោះស្រាយកំហុសឧបករណ៍នេះ។ កម្មវិធី និងទិន្នន័យអាចនឹងត្រូវបានចែករំលែក ហើយឧបករណ៍របស់អ្នកអាចនឹងយឺតជាបណ្តោះអាសន្ន។"</string>
-    <string name="share_finished_remote_bugreport_notification_message" msgid="4627312060769912353">"អ្នកគ្រប់គ្រងផ្នែកព័ត៌មានវិទ្យារបស់អ្នកបានស្នើរបាយការណ៍កំហុសដើម្បីដោះស្រាយកំហុសឧបករណ៍នេះ។ កម្មវិធី និងទិន្នន័យអាចនឹងត្រូវបានចែករំលែក។"</string>
-    <string name="sharing_remote_bugreport_notification_message" msgid="673106383408474893">"វាអាចនឹងធ្វើឲ្យឧបករណ៍របស់អ្នកយឺតជាបណ្តោះអាសន្ន។"</string>
-    <string name="share_remote_bugreport_notification_accept" msgid="8203856129078669677">"ព្រមទទួល"</string>
-    <string name="share_remote_bugreport_notification_decline" msgid="6337969352057443969">"បដិសេធ"</string>
+    <string name="share_remote_bugreport_notification_message_finished" msgid="8610614010660772643">"អ្នកគ្រប់គ្រងផ្នែកព័ត៌មានវិទ្យារបស់អ្នកបានស្នើរបាយការណ៍កំហុសដើម្បីដោះស្រាយកំហុសឧបករណ៍នេះ។ កម្មវិធី និងទិន្នន័យអាចនឹងត្រូវបានចែករំលែក។"</string>
+    <string name="share_remote_bugreport_action" msgid="6249476773913384948">"ចែករំលែក"</string>
+    <string name="decline_remote_bugreport_action" msgid="6230987241608770062">"បដិសេធ"</string>
     <string name="select_input_method" msgid="8547250819326693584">"ប្ដូរ​ក្ដារចុច"</string>
     <string name="configure_input_methods" msgid="4769971288371946846">"ជ្រើស​ក្ដារចុច"</string>
     <string name="show_ime" msgid="2506087537466597099">"ទុកវានៅលើអេក្រង់ខណៈពេលក្តារចុចពិតប្រាកដកំពុងសកម្ម"</string>
@@ -1139,8 +1137,9 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"ផ្ទាំង​រូបភាព"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"ប្ដូរ​ផ្ទាំង​រូបភាព"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"កម្មវិធី​ស្ដាប់​ការ​ជូន​ដំណឹង"</string>
+    <string name="vr_listener_binding_label" msgid="4316591939343607306">"កម្មវិធីស្តាប់ VR"</string>
     <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"ក្រុមហ៊ុន​ផ្ដល់​លក្ខខណ្ឌ"</string>
-    <string name="notification_assistant_binding_label" msgid="909456055569102952">"ជំនួយការជូនដំណឹង"</string>
+    <string name="notification_ranker_binding_label" msgid="774540592299064747">"សេវាកម្មវាយតម្លៃការជូនដំណឹង"</string>
     <string name="vpn_title" msgid="19615213552042827">"បាន​ធ្វើ​ឲ្យ VPN សកម្ម"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"បាន​ធ្វើ​ឲ្យ VPN សកម្ម​ដោយ <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"ប៉ះ ដើម្បី​គ្រប់គ្រង​បណ្ដាញ។"</string>
@@ -1469,7 +1468,7 @@
     <string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"សួរ​រក​កូដ PIN មុន​ពេល​ផ្ដាច់"</string>
     <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"សួរ​រក​លំនាំ​ដោះ​សោ​មុន​ពេល​ផ្ដាច់"</string>
     <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"សួរ​រក​ពាក្យ​សម្ងាត់​មុន​ពេល​ផ្ដាច់"</string>
-    <string name="dock_cropped_windows_text" msgid="6378424064779004428">"កម្មវិធីមិនអាចផ្លាស់ប្តូរទំហំបានទេ សូមរមូរវាដោយប្រើម្រាមដៃពីរ។"</string>
+    <string name="dock_forced_resizable" msgid="5914261505436217520">"កម្មវិធីអាចនឹងមិនដំណើរការនៅលើអេក្រង់បំបែកទេ"</string>
     <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"កម្មវិធីមិនគាំទ្រអេក្រង់បំបែកជាពីរទេ"</string>
     <string name="package_installed_device_owner" msgid="8420696545959087545">"បានដំឡើងដោយអ្នកគ្រប់គ្រងរបស់អ្នក"</string>
     <string name="package_updated_device_owner" msgid="8856631322440187071">"បានធ្វើបច្ចុប្បន្នភាពដោយអ្នកគ្រប់គ្រងរបស់អ្នក"</string>
@@ -1543,7 +1542,7 @@
     <string name="importance_from_person" msgid="9160133597262938296">"វាមានសារៈសំខាន់ដោយសារតែមនុស្សដែលពាក់ព័ន្ធ"</string>
     <string name="user_creation_account_exists" msgid="1942606193570143289">"អនុញ្ញាតឲ្យ <xliff:g id="APP">%1$s</xliff:g> បង្កើតអ្នកប្រើថ្មីដោយប្រើ <xliff:g id="ACCOUNT">%2$s</xliff:g> ឬទេ?"</string>
     <string name="user_creation_adding" msgid="4482658054622099197">"អនុញ្ញាតឲ្យ <xliff:g id="APP">%1$s</xliff:g> បង្កើតអ្នកប្រើថ្មីដោយប្រើ <xliff:g id="ACCOUNT">%2$s</xliff:g> (មានអ្នកប្រើសម្រាប់គណនីនេះរួចហើយ) ឬទេ?"</string>
-    <string name="language_selection_title" msgid="7181332986330337171">"ចំណូល​ចិត្ត​ភាសា"</string>
+    <string name="language_selection_title" msgid="2680677278159281088">"បន្ថែមភាសា"</string>
     <string name="country_selection_title" msgid="2954859441620215513">"ចំណូលចិត្តតំបន់"</string>
     <string name="search_language_hint" msgid="7042102592055108574">"វាយបញ្ចូលឈ្មោះភាសា"</string>
     <string name="language_picker_section_suggested" msgid="8414489646861640885">"បាន​ស្នើ"</string>
@@ -1567,4 +1566,6 @@
     <string name="unpin_target" msgid="3556545602439143442">"មិនខ្ទាស់"</string>
     <string name="app_info" msgid="6856026610594615344">"ព័ត៌មាន​កម្មវិធី"</string>
     <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="audit_safemode_notification" msgid="6351827251856877200">"កំណត់ដូចចេញពីរោងចក្រឡើងវិញដើម្បីប្រើឧបករណ៍នេះតាមធម្មតា"</string>
+    <string name="audit_safemode_notification_details" msgid="1860601176690176413">"ប៉ះ​ ដើម្បី​​ស្វែងយល់​បន្ថែម។"</string>
 </resources>
diff --git a/core/res/res/values-kn-rIN/strings.xml b/core/res/res/values-kn-rIN/strings.xml
index 5a025e4..7a41d4b 100644
--- a/core/res/res/values-kn-rIN/strings.xml
+++ b/core/res/res/values-kn-rIN/strings.xml
@@ -229,7 +229,6 @@
     <string name="global_action_voice_assist" msgid="7751191495200504480">"ಧ್ವನಿ ಸಹಾಯಕ"</string>
     <string name="global_action_lockdown" msgid="8751542514724332873">"ಈಗ ಲಾಕ್ ಮಾಡಿ"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
-    <string name="notification_children_count_bracketed" msgid="1769425473168347839">"(<xliff:g id="NOTIFICATIONCOUNT">%d</xliff:g>)"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"ವಿಷಯಗಳನ್ನು ಮರೆಮಾಡಲಾಗಿದೆ"</string>
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"ನೀತಿಯಿಂದ ಮರೆಮಾಡಲಾಗಿರುವ ವಿಷಯಗಳು"</string>
     <string name="safeMode" msgid="2788228061547930246">"ಸುರಕ್ಷಿತ ಮೋಡ್"</string>
@@ -1052,13 +1051,12 @@
     <string name="usb_notification_message" msgid="7347368030849048437">"ಹೆಚ್ಚಿನ ಆಯ್ಕೆಗಳಿಗೆ ಸ್ಪರ್ಶಿಸಿ."</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"USB ಡೀಬಗಿಂಗ್‌‌ ಸಂಪರ್ಕ"</string>
     <string name="adb_active_notification_message" msgid="1016654627626476142">"USB ಡೀಬಗಿಂಗ್‌ ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಲು ಸ್ಪರ್ಶಿಸಿ."</string>
+    <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"ದೋಷದ ವರದಿಯನ್ನು ತೆಗೆದುಕೊಳ್ಳಲಾಗುತ್ತಿದೆ…"</string>
     <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"ಬಗ್ ವರದಿಯನ್ನು ಹಂಚುವುದೇ?"</string>
     <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"ಬಗ್ ವರದಿಯನ್ನು ಹಂಚಿಕೊಳ್ಳಲಾಗುತ್ತಿದೆ…"</string>
-    <string name="share_remote_bugreport_notification_message" msgid="752583906074230920">"ಈ ಸಾಧನದ ಸಮಸ್ಯೆ ನಿವಾರಿಸುವುದಕ್ಕೆ ಸಹಾಯ ಮಾಡಲು ನಿಮ್ಮ IT ನಿರ್ವಾಹಕರು ಬಗ್‌ ವರದಿಯನ್ನು ವಿನಂತಿಸಿದ್ದಾರೆ. ಅಪ್ಲಿಕೇಶನ್‌ಗಳು ಮತ್ತು ಡೇಟಾವನ್ನು ಹಂಚಿಕೊಳ್ಳಬಹುದು ಹಾಗು ನಿಮ್ಮ ಸಾಧನವು ತಾತ್ಕಾಲಿಕವಾಗಿ ನಿಧಾನಗೊಳ್ಳಬಹುದು."</string>
-    <string name="share_finished_remote_bugreport_notification_message" msgid="4627312060769912353">"ಈ ಸಾಧನದ ಸಮಸ್ಯೆ ನಿವಾರಿಸಲು ಸಹಾಯ ಮಾಡಲು ನಿಮ್ಮ IT ನಿರ್ವಾಹಕರು ಬಗ್ ವರದಿಯನ್ನು ವಿನಂತಿಸಿದ್ದಾರೆ. ಅಪ್ಲಿಕೇಶನ್‌ಗಳು ಮತ್ತು ಡೇಟಾವನ್ನು ಹಂಚಿಕೊಳ್ಳಬಹುದು."</string>
-    <string name="sharing_remote_bugreport_notification_message" msgid="673106383408474893">"ಇದು ನಿಮ್ಮ ಸಾಧನವನ್ನು ತಾತ್ಕಾಲಿಕವಾಗಿ ನಿಧಾನಗೊಳಿಸಬಹುದು"</string>
-    <string name="share_remote_bugreport_notification_accept" msgid="8203856129078669677">"ಸಮ್ಮತಿಸು"</string>
-    <string name="share_remote_bugreport_notification_decline" msgid="6337969352057443969">"ತಿರಸ್ಕರಿಸು"</string>
+    <string name="share_remote_bugreport_notification_message_finished" msgid="8610614010660772643">"ಈ ಸಾಧನದ ಸಮಸ್ಯೆ ನಿವಾರಿಸಲು ಸಹಾಯ ಮಾಡಲು ನಿಮ್ಮ IT ನಿರ್ವಾಹಕರು ಬಗ್ ವರದಿಯನ್ನು ವಿನಂತಿಸಿದ್ದಾರೆ. ಅಪ್ಲಿಕೇಶನ್‌ಗಳು ಮತ್ತು ಡೇಟಾವನ್ನು ಹಂಚಿಕೊಳ್ಳಬಹುದು."</string>
+    <string name="share_remote_bugreport_action" msgid="6249476773913384948">"ಹಂಚಿಕೊಳ್ಳಿ"</string>
+    <string name="decline_remote_bugreport_action" msgid="6230987241608770062">"ನಿರಾಕರಿಸು"</string>
     <string name="select_input_method" msgid="8547250819326693584">"ಕೀಬೋರ್ಡ್ ಬದಲಿಸಿ"</string>
     <string name="configure_input_methods" msgid="4769971288371946846">"ಕೀಬೋರ್ಡ್‌ಗಳನ್ನು ಆಯ್ಕೆಮಾಡಿ"</string>
     <string name="show_ime" msgid="2506087537466597099">"ಭೌತಿಕ ಕೀಬೋರ್ಡ್ ಸಕ್ರಿಯವಾಗಿರುವಾಗ ಅದನ್ನು ಪರದೆಯ ಮೇಲೆ ಇರಿಸಿಕೊಳ್ಳಿ"</string>
@@ -1137,8 +1135,9 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"ವಾಲ್‌ಪೇಪರ್"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"ವಾಲ್‌ಪೇಪರ್ ಬದಲಿಸಿ"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"ಅಧಿಸೂಚನೆ ಕೇಳುಗ"</string>
+    <string name="vr_listener_binding_label" msgid="4316591939343607306">"VR ಕೇಳುವಿಕೆ"</string>
     <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"ಕಂಡೀಶನ್ ಪೂರೈಕೆದಾರರು"</string>
-    <string name="notification_assistant_binding_label" msgid="909456055569102952">"ಅಧಿಸೂಚನೆ ಸಹಾಯಕ"</string>
+    <string name="notification_ranker_binding_label" msgid="774540592299064747">"ಅಧಿಸೂಚನೆ ಶ್ರೇಣಿಯ ಸೇವೆ"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN ಸಕ್ರಿಯಗೊಂಡಿದೆ"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"<xliff:g id="APP">%s</xliff:g> ಮೂಲಕ VPN ಸಕ್ರಿಯಗೊಂಡಿದೆ"</string>
     <string name="vpn_text" msgid="3011306607126450322">"ನೆಟ್‍ವರ್ಕ್ ನಿರ್ವಹಿಸಲು ಸ್ಪರ್ಶಿಸಿ"</string>
@@ -1467,7 +1466,7 @@
     <string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"ಅನ್‌ಪಿನ್ ಮಾಡಲು ಪಿನ್‌ ಕೇಳು"</string>
     <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"ಅನ್‌ಪಿನ್ ಮಾಡಲು ಅನ್‌ಲಾಕ್ ಪ್ಯಾಟರ್ನ್ ಕೇಳಿ"</string>
     <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"ಅನ್‌ಪಿನ್ ಮಾಡಲು ಪಾಸ್‌ವರ್ಡ್ ಕೇಳು"</string>
-    <string name="dock_cropped_windows_text" msgid="6378424064779004428">"ಅಪ್ಲಿಕೇಶನ್‌ ಅನ್ನು ಮರುಗಾತ್ರಗೊಳಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ, ಅದನ್ನು ಎರಡು ಬೆರಳುಗಳಿಂದ ಸ್ಕ್ರಾಲ್ ಮಾಡಿ."</string>
+    <string name="dock_forced_resizable" msgid="5914261505436217520">"ವಿಭಜಿಸಿದ ಪರದೆಯಲ್ಲಿ ಅಪ್ಲಿಕೇಶನ್ ಕೆಲಸ ಮಾಡದೇ ಇರಬಹುದು."</string>
     <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"ಅಪ್ಲಿಕೇಶನ್ ಸ್ಪ್ಲಿಟ್ ಸ್ಕ್ರೀನ್ ಅನ್ನು ಬೆಂಬಲಿಸುವುದಿಲ್ಲ."</string>
     <string name="package_installed_device_owner" msgid="8420696545959087545">"ನಿಮ್ಮ ನಿರ್ವಾಹಕರಿಂದ ಸ್ಥಾಪಿಸಲಾಗಿದೆ"</string>
     <string name="package_updated_device_owner" msgid="8856631322440187071">"ನಿಮ್ಮ ನಿರ್ವಾಹಕರಿಂದ ನವೀಕರಿಸಲಾಗಿದೆ"</string>
@@ -1541,7 +1540,7 @@
     <string name="importance_from_person" msgid="9160133597262938296">"ಜನರು ತೊಡಗಿಕೊಂಡಿರುವ ಕಾರಣ ಇದು ಅತ್ಯಂತ ಪ್ರಮುಖವಾಗಿದೆ."</string>
     <string name="user_creation_account_exists" msgid="1942606193570143289">"<xliff:g id="ACCOUNT">%2$s</xliff:g> ಮೂಲಕ ಹೊಸ ಬಳಕೆದಾರರನ್ನು ರಚಿಸಲು <xliff:g id="APP">%1$s</xliff:g> ಗೆ ಅನುಮತಿಸುವುದೇ ?"</string>
     <string name="user_creation_adding" msgid="4482658054622099197">"<xliff:g id="ACCOUNT">%2$s</xliff:g> (ಈ ಖಾತೆಯ ಬಳಕೆದಾರರು ಈಗಾಗಲೇ ಅಸ್ತಿತ್ವದಲ್ಲಿದ್ದಾರೆ) ಮೂಲಕ ಹೊಸ ಬಳಕೆದಾರರನ್ನು ರಚಿಸಲು <xliff:g id="APP">%1$s</xliff:g> ಗೆ ಅನುಮತಿಸುವುದೇ ?"</string>
-    <string name="language_selection_title" msgid="7181332986330337171">"ಭಾಷೆಯ ಪ್ರಾಶಸ್ತ್ಯ"</string>
+    <string name="language_selection_title" msgid="2680677278159281088">"ಭಾಷೆ ಸೇರಿಸಿ"</string>
     <string name="country_selection_title" msgid="2954859441620215513">"ಪ್ರದೇಶ ಪ್ರಾಶಸ್ತ್ಯ"</string>
     <string name="search_language_hint" msgid="7042102592055108574">"ಭಾಷೆ ಹೆಸರನ್ನು ಟೈಪ್ ಮಾಡಿ"</string>
     <string name="language_picker_section_suggested" msgid="8414489646861640885">"ಸಲಹೆ ಮಾಡಿರುವುದು"</string>
@@ -1565,4 +1564,6 @@
     <string name="unpin_target" msgid="3556545602439143442">"ಅನ್‌ಪಿನ್"</string>
     <string name="app_info" msgid="6856026610594615344">"ಅಪ್ಲಿಕೇಶನ್ ಮಾಹಿತಿ"</string>
     <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="audit_safemode_notification" msgid="6351827251856877200">"ಈ ಸಾಧನವನ್ನು ಸಾಮಾನ್ಯ ರೀತಿಯಲ್ಲಿ ಬಳಸಲು ಫ್ಯಾಕ್ಟರಿ ರಿಸೆಟ್ ಮಾಡಿ"</string>
+    <string name="audit_safemode_notification_details" msgid="1860601176690176413">"ಇನ್ನಷ್ಟು ತಿಳಿಯಲು ಸ್ಪರ್ಶಿಸಿ."</string>
 </resources>
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index 908bacb..b236d39 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -229,7 +229,6 @@
     <string name="global_action_voice_assist" msgid="7751191495200504480">"음성 지원"</string>
     <string name="global_action_lockdown" msgid="8751542514724332873">"지금 잠그기"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
-    <string name="notification_children_count_bracketed" msgid="1769425473168347839">"(<xliff:g id="NOTIFICATIONCOUNT">%d</xliff:g>개)"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"숨겨진 콘텐츠"</string>
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"콘텐츠가 정책에 의해 숨겨졌습니다."</string>
     <string name="safeMode" msgid="2788228061547930246">"안전 모드"</string>
@@ -1052,13 +1051,12 @@
     <string name="usb_notification_message" msgid="7347368030849048437">"더 많은 옵션을 확인하려면 터치하세요."</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"USB 디버깅 연결됨"</string>
     <string name="adb_active_notification_message" msgid="1016654627626476142">"USB 디버깅을 사용하지 않으려면 터치하세요."</string>
+    <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"버그 보고서 가져오는 중..."</string>
     <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"버그 보고서를 공유하시겠습니까?"</string>
     <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"버그 신고서 공유 중..."</string>
-    <string name="share_remote_bugreport_notification_message" msgid="752583906074230920">"IT 관리자가 이 기기의 문제해결을 위해 버그 신고서를 요청했습니다. 앱과 데이터가 공유될 수 있으며 기기 속도가 일시적으로 느려질 수 있습니다."</string>
-    <string name="share_finished_remote_bugreport_notification_message" msgid="4627312060769912353">"IT 관리자가 이 기기의 문제해결을 위해 버그 보고서를 요청했습니다. 앱과 데이터가 공유될 수 있습니다."</string>
-    <string name="sharing_remote_bugreport_notification_message" msgid="673106383408474893">"이로 인해 일시적으로 기기 속도가 느려질 수 있습니다."</string>
-    <string name="share_remote_bugreport_notification_accept" msgid="8203856129078669677">"수락"</string>
-    <string name="share_remote_bugreport_notification_decline" msgid="6337969352057443969">"거절"</string>
+    <string name="share_remote_bugreport_notification_message_finished" msgid="8610614010660772643">"IT 관리자가 이 기기의 문제해결을 위해 버그 보고서를 요청했습니다. 앱과 데이터가 공유될 수 있습니다."</string>
+    <string name="share_remote_bugreport_action" msgid="6249476773913384948">"공유"</string>
+    <string name="decline_remote_bugreport_action" msgid="6230987241608770062">"거부"</string>
     <string name="select_input_method" msgid="8547250819326693584">"키보드 변경"</string>
     <string name="configure_input_methods" msgid="4769971288371946846">"키보드 선택"</string>
     <string name="show_ime" msgid="2506087537466597099">"물리적 키보드가 활성 상태인 경우 화면에 켜 둠"</string>
@@ -1137,8 +1135,9 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"배경화면"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"배경화면 변경"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"알림 수신기"</string>
+    <string name="vr_listener_binding_label" msgid="4316591939343607306">"가상 현실 리스너"</string>
     <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"조건 제공자"</string>
-    <string name="notification_assistant_binding_label" msgid="909456055569102952">"알림 어시스턴트"</string>
+    <string name="notification_ranker_binding_label" msgid="774540592299064747">"알림 순위 지정 서비스"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN이 활성화됨"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN이 <xliff:g id="APP">%s</xliff:g>에 의해 활성화됨"</string>
     <string name="vpn_text" msgid="3011306607126450322">"네트워크를 관리하려면 터치하세요."</string>
@@ -1467,7 +1466,7 @@
     <string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"고정 해제 이전에 PIN 요청"</string>
     <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"고정 해제 이전에 잠금해제 패턴 요청"</string>
     <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"고정 해제 이전에 비밀번호 요청"</string>
-    <string name="dock_cropped_windows_text" msgid="6378424064779004428">"앱에서 크기 조절이 불가능합니다. 두 손가락을 사용해 스크롤하세요."</string>
+    <string name="dock_forced_resizable" msgid="5914261505436217520">"앱이 분할 화면에서 작동하지 않을 수 있습니다."</string>
     <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"앱이 화면 분할을 지원하지 않습니다."</string>
     <string name="package_installed_device_owner" msgid="8420696545959087545">"관리자가 설치함"</string>
     <string name="package_updated_device_owner" msgid="8856631322440187071">"관리자에 의해 업데이트됨"</string>
@@ -1541,7 +1540,7 @@
     <string name="importance_from_person" msgid="9160133597262938296">"관련된 사용자가 있으므로 중요합니다."</string>
     <string name="user_creation_account_exists" msgid="1942606193570143289">"<xliff:g id="APP">%1$s</xliff:g>이(가) <xliff:g id="ACCOUNT">%2$s</xliff:g>(으)로 신규 사용자를 만들도록 허용하시겠습니까?"</string>
     <string name="user_creation_adding" msgid="4482658054622099197">"<xliff:g id="APP">%1$s</xliff:g>이(가) <xliff:g id="ACCOUNT">%2$s</xliff:g>(이 계정의 사용자가 이미 있음)(으)로 신규 사용자를 만들도록 허용하시겠습니까?"</string>
-    <string name="language_selection_title" msgid="7181332986330337171">"언어 환경설정"</string>
+    <string name="language_selection_title" msgid="2680677278159281088">"언어 추가"</string>
     <string name="country_selection_title" msgid="2954859441620215513">"지역 환경설정"</string>
     <string name="search_language_hint" msgid="7042102592055108574">"언어 이름 입력"</string>
     <string name="language_picker_section_suggested" msgid="8414489646861640885">"추천"</string>
@@ -1565,4 +1564,6 @@
     <string name="unpin_target" msgid="3556545602439143442">"고정 해제"</string>
     <string name="app_info" msgid="6856026610594615344">"앱 정보"</string>
     <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="audit_safemode_notification" msgid="6351827251856877200">"정상적인 기기 사용을 위한 초기화"</string>
+    <string name="audit_safemode_notification_details" msgid="1860601176690176413">"자세한 내용을 보려면 터치하세요."</string>
 </resources>
diff --git a/core/res/res/values-ky-rKG/strings.xml b/core/res/res/values-ky-rKG/strings.xml
index 2d46694..fe89bf9 100644
--- a/core/res/res/values-ky-rKG/strings.xml
+++ b/core/res/res/values-ky-rKG/strings.xml
@@ -229,7 +229,6 @@
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Үн жардамчысы"</string>
     <string name="global_action_lockdown" msgid="8751542514724332873">"Азыр кулпулоо"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
-    <string name="notification_children_count_bracketed" msgid="1769425473168347839">"(<xliff:g id="NOTIFICATIONCOUNT">%d</xliff:g>)"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"Мазмундар жашырылган"</string>
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Тийиштүү саясат боюнча жашырылган мазмундар"</string>
     <string name="safeMode" msgid="2788228061547930246">"Коопсуз режим"</string>
@@ -1053,13 +1052,12 @@
     <string name="usb_notification_message" msgid="7347368030849048437">"Көбүрөөк параметр үчүн тийип коюңуз."</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"USB мүчүлүштүктөрдү оңдоо туташтырылган"</string>
     <string name="adb_active_notification_message" msgid="1016654627626476142">"USB мүчүлүштүктөрдү жоюу мүмкүнчүлүгүн өчүрүү үчүн тийип коюңуз."</string>
+    <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Мүчүлүштүк тууралуу кабар алынууда…"</string>
     <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Мүчүлүштүк тууралуу баяндама бөлүшүлсүнбү?"</string>
     <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Мүчүлүштүк тууралуу баяндама бөлүшүлүүдө…"</string>
-    <string name="share_remote_bugreport_notification_message" msgid="752583906074230920">"Бул түзмөктүн бузулууларын аныктап оңдоо үчүн IT администраторуңуз мүчүлүштүктөр тууралуу маалыматты сурап жатат. Колдонмолор менен дайындар бөлүшүлүп, түзмөгүңүз жайыраак иштеп калышы мүмкүн."</string>
-    <string name="share_finished_remote_bugreport_notification_message" msgid="4627312060769912353">"Бул түзмөктүн бузулууларын аныктап оңдоо үчүн IT администраторуңуз мүчүлүштүктөр тууралуу маалыматты сурап жатат. Колдонмолор менен дайындар бөлүшүлүшү мүмкүн."</string>
-    <string name="sharing_remote_bugreport_notification_message" msgid="673106383408474893">"Ушуну менен түзмөгүңүздүн ылдамдыгы убактылуу төмөндөйт"</string>
-    <string name="share_remote_bugreport_notification_accept" msgid="8203856129078669677">"КАБЫЛ АЛУУ"</string>
-    <string name="share_remote_bugreport_notification_decline" msgid="6337969352057443969">"ЧЕТКЕ КАГУУ"</string>
+    <string name="share_remote_bugreport_notification_message_finished" msgid="8610614010660772643">"Бул түзмөктүн бузулууларын аныктап оңдоо үчүн IT администраторуңуз мүчүлүштүктөр тууралуу маалыматты сурап жатат. Колдонмолор менен дайындар бөлүшүлүшү мүмкүн."</string>
+    <string name="share_remote_bugreport_action" msgid="6249476773913384948">"БӨЛҮШҮҮ"</string>
+    <string name="decline_remote_bugreport_action" msgid="6230987241608770062">"ЧЕТКЕ КАГУУ"</string>
     <string name="select_input_method" msgid="8547250819326693584">"Баскычтопту өзгөртүү"</string>
     <string name="configure_input_methods" msgid="4769971288371946846">"Баскычтопторду тандаңыз"</string>
     <string name="show_ime" msgid="2506087537466597099">"Баскычтоп иштетилгенде экранда көрүнүп турсун"</string>
@@ -1138,8 +1136,9 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Тушкагаз"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Тушкагазды өзгөртүү"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Эскертүү тыңшагычы"</string>
+    <string name="vr_listener_binding_label" msgid="4316591939343607306">"Виртуалдык угуучу"</string>
     <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Шарт түзүүчү"</string>
-    <string name="notification_assistant_binding_label" msgid="909456055569102952">"Эскертме жардамчысы"</string>
+    <string name="notification_ranker_binding_label" msgid="774540592299064747">"Эскертмени баалоо кызматы"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN иштетилди"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN <xliff:g id="APP">%s</xliff:g> аркылуу жандырылды"</string>
     <string name="vpn_text" msgid="3011306607126450322">"желени башкаруу үчүн басыңыз."</string>
@@ -1468,7 +1467,7 @@
     <string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Бошотуудан мурун PIN суралсын"</string>
     <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Бошотуудан мурун кулпуну ачкан үлгү суралсын"</string>
     <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Бошотуудан мурун сырсөз суралсын"</string>
-    <string name="dock_cropped_windows_text" msgid="6378424064779004428">"Колдонмонун көлөмүн өзгөртүүгө болбойт, андыктан эки манжаңыз менен сыдырып караңыз."</string>
+    <string name="dock_forced_resizable" msgid="5914261505436217520">"Колдонмодо экран бөлүнбөшү мүмкүн."</string>
     <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"Колдонмодо экран бөлүнбөйт."</string>
     <string name="package_installed_device_owner" msgid="8420696545959087545">"Администраторуңуз тарабынан орнотулган"</string>
     <string name="package_updated_device_owner" msgid="8856631322440187071">"Администраторуңуз жаңырткан"</string>
@@ -1542,7 +1541,7 @@
     <string name="importance_from_person" msgid="9160133597262938296">"Булар сиз үчүн маанилүү адамдар."</string>
     <string name="user_creation_account_exists" msgid="1942606193570143289">"<xliff:g id="APP">%1$s</xliff:g> колдонмосу <xliff:g id="ACCOUNT">%2$s</xliff:g> каттоо эсеби менен жаңы колдонуучу түзө берсинби ?"</string>
     <string name="user_creation_adding" msgid="4482658054622099197">"<xliff:g id="APP">%1$s</xliff:g> колдонмосу <xliff:g id="ACCOUNT">%2$s</xliff:g> каттоо эсеби менен жаңы колдонуучу түзө берсинби (мындай каттоо эсеби бар колдонуучу мурунтан эле бар) ?"</string>
-    <string name="language_selection_title" msgid="7181332986330337171">"Тил жөндөөлөрү"</string>
+    <string name="language_selection_title" msgid="2680677278159281088">"Тил кошуңуз"</string>
     <string name="country_selection_title" msgid="2954859441620215513">"Чөлкөмдүк жөндөөлөр"</string>
     <string name="search_language_hint" msgid="7042102592055108574">"Тилди киргизиңиз"</string>
     <string name="language_picker_section_suggested" msgid="8414489646861640885">"Сунушталган"</string>
@@ -1565,6 +1564,7 @@
     <string name="pin_target" msgid="3052256031352291362">"Кадоо"</string>
     <string name="unpin_target" msgid="3556545602439143442">"Кадоодон алып коюу"</string>
     <string name="app_info" msgid="6856026610594615344">"Колдонмо тууралуу"</string>
-    <!-- no translation found for negative_duration (5688706061127375131) -->
-    <skip />
+    <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="audit_safemode_notification" msgid="6351827251856877200">"Бул түзмөктү кадимкидей колдонуу үчүн заводдук баштапкы абалына келтириңиз"</string>
+    <string name="audit_safemode_notification_details" msgid="1860601176690176413">"Көбүрөөк билүү үчүн тийип коюңуз."</string>
 </resources>
diff --git a/core/res/res/values-lo-rLA/strings.xml b/core/res/res/values-lo-rLA/strings.xml
index c001943..5ad1786 100644
--- a/core/res/res/values-lo-rLA/strings.xml
+++ b/core/res/res/values-lo-rLA/strings.xml
@@ -229,7 +229,6 @@
     <string name="global_action_voice_assist" msgid="7751191495200504480">"ຊ່ວຍ​ເຫຼືອ​ທາງ​ສຽງ"</string>
     <string name="global_action_lockdown" msgid="8751542514724332873">"ລັອກ​ດຽວ​ນີ້"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
-    <string name="notification_children_count_bracketed" msgid="1769425473168347839">"(<xliff:g id="NOTIFICATIONCOUNT">%d</xliff:g>)"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"ເນື້ອຫາ​ຖືກ​ເຊື່ອງ​ໄວ້"</string>
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"ເນື້ອຫາຖືກເຊື່ອງຕາມນະໂຍບາຍ"</string>
     <string name="safeMode" msgid="2788228061547930246">"Safe mode"</string>
@@ -1052,13 +1051,12 @@
     <string name="usb_notification_message" msgid="7347368030849048437">"ສຳ​ພັດ​ສຳ​ລັບ​ທາງ​ເລືອກ​ເພີ່ມ​ເຕີມ."</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"ເຊື່ອມຕໍ່ການດີບັ໊ກຜ່ານ USB ແລ້ວ"</string>
     <string name="adb_active_notification_message" msgid="1016654627626476142">"ແຕະເພື່ອປິດການດີບັ໊ກຜ່ານ USB."</string>
+    <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"ກຳລັງຂໍລາຍງານຂໍ້ຜິດພາດ…"</string>
     <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"ແບ່ງປັນລາຍງານບັນຫາບໍ?"</string>
     <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"ກຳລັງແບ່ງປັນລາຍງານບັນຫາ…"</string>
-    <string name="share_remote_bugreport_notification_message" msgid="752583906074230920">"ຜູ້ເບິ່ງແຍງລະບົບໄອທີຂອງທ່ານໄດ້ຮ້ອງຂໍລາຍງານຂໍ້ຜິດພາດເພື່ອຊ່ວຍແກ້ໄຂບັນຫາອຸປະກອນນີ້. ແອັບ ແລະ ຂໍ້ມູນອາດຖືກແບ່ງປັນ ແລະ ອຸປະກອນຂອງທ່ານອາດເຮັດວຽກຊ້າລົງຊົ່ວຄາວ."</string>
-    <string name="share_finished_remote_bugreport_notification_message" msgid="4627312060769912353">"ຜູ້ເບິ່ງແຍງລະບົບໄອທີຂອງທ່ານໄດ້ຮ້ອງຂໍເອົາລາຍງານບັນຫາ ເພື່ອຊ່ວຍແກ້ໄຂບັນຫາໃຫ້ອຸປະກອນນີ້. ອາດຈະມີການແບ່ງປັນແອັບ ແລະ ຂໍ້ມູນນຳ."</string>
-    <string name="sharing_remote_bugreport_notification_message" msgid="673106383408474893">"ນີ້ອາດຈະເຮັດໃຫ້ອຸປະກອນຂອງທ່ານຊ້າລົງຊົ່ວຄາວ"</string>
-    <string name="share_remote_bugreport_notification_accept" msgid="8203856129078669677">"ຍອມຮັບ"</string>
-    <string name="share_remote_bugreport_notification_decline" msgid="6337969352057443969">"ປະຕິເສດ"</string>
+    <string name="share_remote_bugreport_notification_message_finished" msgid="8610614010660772643">"ຜູ້ເບິ່ງແຍງລະບົບໄອທີຂອງທ່ານໄດ້ຮ້ອງຂໍເອົາລາຍງານບັນຫາ ເພື່ອຊ່ວຍແກ້ໄຂບັນຫາໃຫ້ອຸປະກອນນີ້. ອາດຈະມີການແບ່ງປັນແອັບ ແລະ ຂໍ້ມູນນຳ."</string>
+    <string name="share_remote_bugreport_action" msgid="6249476773913384948">"ແບ່ງປັນ"</string>
+    <string name="decline_remote_bugreport_action" msgid="6230987241608770062">"ປະຕິເສດ"</string>
     <string name="select_input_method" msgid="8547250819326693584">"​ປ່ຽນ​ແປ້ນ​ພິມ"</string>
     <string name="configure_input_methods" msgid="4769971288371946846">"​ເລືອກ​ແປ້ນ​ພິມ"</string>
     <string name="show_ime" msgid="2506087537466597099">"ເປີດໃຊ້ໃຫ້ມັນຢູ່ໃນໜ້າຈໍໃນຂະນະທີ່ໃຊ້ແປ້ນພິມພາຍນອກຢູ່"</string>
@@ -1137,8 +1135,9 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"ພາບພື້ນຫຼັງ"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"ປ່ຽນພາບພື້ນຫຼັງ"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"ໂຕຟັງການແຈ້ງເຕືອນ"</string>
+    <string name="vr_listener_binding_label" msgid="4316591939343607306">"ຕົວຟັງ VR"</string>
     <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"​ຜູ່​ສະ​ໜອງ​ເງື່ອນ​ໄຂ"</string>
-    <string name="notification_assistant_binding_label" msgid="909456055569102952">"ຕົວຊ່ວຍ​ການ​ແຈ້ງ​ເຕືອນ"</string>
+    <string name="notification_ranker_binding_label" msgid="774540592299064747">"ບໍລິການຈັດອັນດັບການແຈ້ງເຕືອນ"</string>
     <string name="vpn_title" msgid="19615213552042827">"ເປີດນຳໃຊ້ VPN ແລ້ວ"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"ເປີດໃຊ້ VPN ໂດຍ <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"ແຕະເພື່ອຈັດການເຄືອຂ່າຍ."</string>
@@ -1467,7 +1466,7 @@
     <string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"​ຖາມ​ຫາ PIN ກ່ອນ​ຍົກ​ເລີກ​ການປັກ​ໝຸດ"</string>
     <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"​ຖາມ​ຫາ​ຮູບ​ແບບ​ປົດ​ລັອກ​ກ່ອນ​ຍົກ​ເລີກ​ການ​ປັກ​ໝຸດ"</string>
     <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"​ຖາມ​ຫາ​ລະ​ຫັດ​ຜ່ານ​ກ່ອນ​ຍົກ​ເລີກ​ການ​ປັກ​ໝຸດ"</string>
-    <string name="dock_cropped_windows_text" msgid="6378424064779004428">"ບໍ່ສາມາດປັບຂະໜາດແອັບໄດ້, ໃຫ້ເລື່ອນມັນໂດຍໃຊ້ນິ້ວມືສອງນິ້ວ."</string>
+    <string name="dock_forced_resizable" msgid="5914261505436217520">"ແອັບອາດໃຊ້ບໍ່ໄດ້ກັບການແບ່ງໜ້າຈໍ."</string>
     <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"ແອັບບໍ່ຮອງຮັບໜ້າຈໍແບບແຍກກັນ."</string>
     <string name="package_installed_device_owner" msgid="8420696545959087545">"ຜູ້​ຄວບ​ຄຸມ​ຂອງ​ທ່ານ​ຕິດ​ຕັ້ງ​ໃສ່​ແລ້ວ"</string>
     <string name="package_updated_device_owner" msgid="8856631322440187071">"ອັບ​ເດດ​ໂດຍ​ຜູ້​ຄວບ​ຄຸມ​ຂອງ​ທ່ານ​ແລ້ວ"</string>
@@ -1541,7 +1540,7 @@
     <string name="importance_from_person" msgid="9160133597262938296">"ຂໍ້ຄວາມນີ້ສຳຄັນເນື່ອງຈາກບຸກຄົນທີ່ກ່ຽວຂ້ອງ."</string>
     <string name="user_creation_account_exists" msgid="1942606193570143289">"ອະນຸຍາດໃຫ້ <xliff:g id="APP">%1$s</xliff:g> ສ້າງຜູ້ໃຊ້ໃໝ່ສຳລັບ <xliff:g id="ACCOUNT">%2$s</xliff:g> ບໍ?"</string>
     <string name="user_creation_adding" msgid="4482658054622099197">"ອະນຸຍາດໃຫ້ <xliff:g id="APP">%1$s</xliff:g> ສ້າງຜູ້ໃຊ້ໃໝ່ສຳລັບ <xliff:g id="ACCOUNT">%2$s</xliff:g> (ຜູ້ໃຊ້ສຳລັບບັນຊີນີ້ມີຢູ່ແລ້ວ) ບໍ?"</string>
-    <string name="language_selection_title" msgid="7181332986330337171">"ການຕັ້ງຄ່າພາສາ"</string>
+    <string name="language_selection_title" msgid="2680677278159281088">"ເພີ່ມພາສາ"</string>
     <string name="country_selection_title" msgid="2954859441620215513">"ການຕັ້ງຄ່າພາກພື້ນ"</string>
     <string name="search_language_hint" msgid="7042102592055108574">"ພິມຊື່ພາສາ"</string>
     <string name="language_picker_section_suggested" msgid="8414489646861640885">"ແນະນຳ"</string>
@@ -1565,4 +1564,6 @@
     <string name="unpin_target" msgid="3556545602439143442">"ຖອນປັກໝຸດ"</string>
     <string name="app_info" msgid="6856026610594615344">"ຂໍ້ມູນແອັບ"</string>
     <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="audit_safemode_notification" msgid="6351827251856877200">"ຣີເຊັດເປັນຄ່າໂຮງງານເພື່ອໃຊ້ອຸປະກອນນີ້ປົກກະຕິ"</string>
+    <string name="audit_safemode_notification_details" msgid="1860601176690176413">"ແຕະເພື່ອສຶກສາເພີ່ມເຕີມ."</string>
 </resources>
diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml
index 8805c5a..5496ada 100644
--- a/core/res/res/values-lt/strings.xml
+++ b/core/res/res/values-lt/strings.xml
@@ -233,7 +233,6 @@
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Voice Assist"</string>
     <string name="global_action_lockdown" msgid="8751542514724332873">"Užrakinti dabar"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
-    <string name="notification_children_count_bracketed" msgid="1769425473168347839">"(<xliff:g id="NOTIFICATIONCOUNT">%d</xliff:g>)"</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>
     <string name="safeMode" msgid="2788228061547930246">"Saugos režimas"</string>
@@ -1068,13 +1067,12 @@
     <string name="usb_notification_message" msgid="7347368030849048437">"Palieskite, kad būtų rodoma daugiau parinkčių."</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"USB derinimas prijungtas"</string>
     <string name="adb_active_notification_message" msgid="1016654627626476142">"Neleisti USB derinimo."</string>
+    <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Pateikiamas pranešimas apie riktą…"</string>
     <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Bendrinti pranešimą apie riktą?"</string>
     <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Bendrinamas pranešimas apie riktą..."</string>
-    <string name="share_remote_bugreport_notification_message" msgid="752583906074230920">"Jūsų IT administratorius pateikė pranešimo apie riktą užklausą, kad galėtų padėti pašalinti triktis šiame įrenginyje. Programos bei duomenys gali būti bendrinami ir įrenginys gali laikinai lėčiau veikti."</string>
-    <string name="share_finished_remote_bugreport_notification_message" msgid="4627312060769912353">"Jūsų IT administratorius pateikė pranešimo apie riktą užklausą, kad galėtų padėti pašalinti triktis šiame įrenginyje. Programos ir duomenys gali būti bendrinami."</string>
-    <string name="sharing_remote_bugreport_notification_message" msgid="673106383408474893">"Dėl to įrenginys gali laikinai lėčiau veikti"</string>
-    <string name="share_remote_bugreport_notification_accept" msgid="8203856129078669677">"SUTIKTI"</string>
-    <string name="share_remote_bugreport_notification_decline" msgid="6337969352057443969">"ATMESTI"</string>
+    <string name="share_remote_bugreport_notification_message_finished" msgid="8610614010660772643">"Jūsų IT administratorius pateikė pranešimo apie riktą užklausą, kad galėtų padėti pašalinti triktis šiame įrenginyje. Programos ir duomenys gali būti bendrinami."</string>
+    <string name="share_remote_bugreport_action" msgid="6249476773913384948">"BENDRINTI"</string>
+    <string name="decline_remote_bugreport_action" msgid="6230987241608770062">"ATMESTI"</string>
     <string name="select_input_method" msgid="8547250819326693584">"Klaviatūros keitimas"</string>
     <string name="configure_input_methods" msgid="4769971288371946846">"Pasirinkti klaviatūras"</string>
     <string name="show_ime" msgid="2506087537466597099">"Palikti ekrane, kol fizinė klaviatūra aktyvi"</string>
@@ -1153,8 +1151,9 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Darbalaukio fonas"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Keisti darbalaukio foną"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Pranešimų skaitymo priemonė"</string>
+    <string name="vr_listener_binding_label" msgid="4316591939343607306">"Virtualiosios realybės apdorojimo priemonė"</string>
     <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Sąlygos teikėjas"</string>
-    <string name="notification_assistant_binding_label" msgid="909456055569102952">"Pranešimų pagelbiklis"</string>
+    <string name="notification_ranker_binding_label" msgid="774540592299064747">"Pranešimų reitingavimo paslauga"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN suaktyvintas"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN suaktyvino „<xliff:g id="APP">%s</xliff:g>“"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Palieskite, kad valdytumėte tinklą."</string>
@@ -1487,7 +1486,7 @@
     <string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Prašyti PIN kodo prieš atsegant"</string>
     <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Prašyti atrakinimo piešinio prieš atsegant"</string>
     <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Prašyti slaptažodžio prieš atsegant"</string>
-    <string name="dock_cropped_windows_text" msgid="6378424064779004428">"Programos dydis nekeičiamas, slinkite dviem pirštais."</string>
+    <string name="dock_forced_resizable" msgid="5914261505436217520">"Programa gali neveikti naudojant skaidytą ekraną."</string>
     <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"Programoje nepalaikomas skaidytas ekranas."</string>
     <string name="package_installed_device_owner" msgid="8420696545959087545">"Įdiegė administratorius"</string>
     <string name="package_updated_device_owner" msgid="8856631322440187071">"Atnaujino administratorius"</string>
@@ -1579,7 +1578,7 @@
     <string name="importance_from_person" msgid="9160133597262938296">"Tai svarbu dėl susijusių žmonių."</string>
     <string name="user_creation_account_exists" msgid="1942606193570143289">"Leisti „<xliff:g id="APP">%1$s</xliff:g>“ kurti naują <xliff:g id="ACCOUNT">%2$s</xliff:g> naudotoją?"</string>
     <string name="user_creation_adding" msgid="4482658054622099197">"Leisti „<xliff:g id="APP">%1$s</xliff:g>“ kurti naują <xliff:g id="ACCOUNT">%2$s</xliff:g> naudotoją (šią paskyrą naudojantis naudotojas jau yra)?"</string>
-    <string name="language_selection_title" msgid="7181332986330337171">"Kalbos nuostata"</string>
+    <string name="language_selection_title" msgid="2680677278159281088">"Pridėkite kalbą"</string>
     <string name="country_selection_title" msgid="2954859441620215513">"Regiono nuostata"</string>
     <string name="search_language_hint" msgid="7042102592055108574">"Įveskite kalbos pav."</string>
     <string name="language_picker_section_suggested" msgid="8414489646861640885">"Siūloma"</string>
@@ -1603,4 +1602,6 @@
     <string name="unpin_target" msgid="3556545602439143442">"Atsegti"</string>
     <string name="app_info" msgid="6856026610594615344">"Programos informacija"</string>
     <string name="negative_duration" msgid="5688706061127375131">"–<xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="audit_safemode_notification" msgid="6351827251856877200">"Atkurkite gamyklinius nustatymus, kad galėtumėte įprastai naudoti šį įrenginį"</string>
+    <string name="audit_safemode_notification_details" msgid="1860601176690176413">"Palieskite, kad sužinotumėte daugiau."</string>
 </resources>
diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml
index 1646342..59ffdc3 100644
--- a/core/res/res/values-lv/strings.xml
+++ b/core/res/res/values-lv/strings.xml
@@ -231,7 +231,6 @@
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Balss palīgs"</string>
     <string name="global_action_lockdown" msgid="8751542514724332873">"Bloķēt tūlīt"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"Pārsniedz"</string>
-    <string name="notification_children_count_bracketed" msgid="1769425473168347839">"(<xliff:g id="NOTIFICATIONCOUNT">%d</xliff:g>)"</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>
     <string name="safeMode" msgid="2788228061547930246">"Drošais režīms"</string>
@@ -1060,13 +1059,12 @@
     <string name="usb_notification_message" msgid="7347368030849048437">"Citas opcijas"</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"USB atkļūdošana ir pievienota."</string>
     <string name="adb_active_notification_message" msgid="1016654627626476142">"Iespējot USB atkļūdošanu."</string>
+    <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Notiek kļūdas pārskata izveide…"</string>
     <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Vai kopīgot kļūdas pārskatu?"</string>
     <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Notiek kļūdas pārskata kopīgošana…"</string>
-    <string name="share_remote_bugreport_notification_message" msgid="752583906074230920">"Jūsu IT administrators pieprasīja kļūdas pārskatu, lai palīdzētu novērst problēmu šajā ierīcē. Var tikt kopīgotas lietotnes un dati, un jūsu ierīces darbība var īslaicīgi palēnināties."</string>
-    <string name="share_finished_remote_bugreport_notification_message" msgid="4627312060769912353">"Jūsu IT administrators pieprasīja kļūdas pārskatu, lai palīdzētu novērst problēmu šajā ierīcē. Var tikt kopīgotas lietotnes un dati."</string>
-    <string name="sharing_remote_bugreport_notification_message" msgid="673106383408474893">"Jūsu ierīces darbība var īslaicīgi palēnināties."</string>
-    <string name="share_remote_bugreport_notification_accept" msgid="8203856129078669677">"APSTIPRINĀT"</string>
-    <string name="share_remote_bugreport_notification_decline" msgid="6337969352057443969">"NORAIDĪT"</string>
+    <string name="share_remote_bugreport_notification_message_finished" msgid="8610614010660772643">"Jūsu IT administrators pieprasīja kļūdas pārskatu, lai palīdzētu novērst problēmu šajā ierīcē. Var tikt kopīgotas lietotnes un dati."</string>
+    <string name="share_remote_bugreport_action" msgid="6249476773913384948">"KOPĪGOT"</string>
+    <string name="decline_remote_bugreport_action" msgid="6230987241608770062">"NORAIDĪT"</string>
     <string name="select_input_method" msgid="8547250819326693584">"Tastatūras maiņa"</string>
     <string name="configure_input_methods" msgid="4769971288371946846">"Izvēlēties tastatūru"</string>
     <string name="show_ime" msgid="2506087537466597099">"Paturēt ekrānā, kamēr ir aktīva fiziskā tastatūra"</string>
@@ -1145,8 +1143,9 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Fona tapete"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Tapetes maiņa"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Paziņojumu uztvērējs"</string>
+    <string name="vr_listener_binding_label" msgid="4316591939343607306">"VR klausītājs"</string>
     <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Nosacījumu sniedzējs"</string>
-    <string name="notification_assistant_binding_label" msgid="909456055569102952">"Paziņojumu palīgs"</string>
+    <string name="notification_ranker_binding_label" msgid="774540592299064747">"Paziņojumu ranžēšanas pakalpojums"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN ir aktivizēts."</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"Lietojumprogramma <xliff:g id="APP">%s</xliff:g> aktivizēja VPN."</string>
     <string name="vpn_text" msgid="3011306607126450322">"Pieskarieties, lai pārvaldītu tīklu."</string>
@@ -1477,7 +1476,7 @@
     <string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Prasīt PIN kodu pirms atspraušanas"</string>
     <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Pirms atspraušanas pieprasīt grafisko atslēgu"</string>
     <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Pirms atspraušanas pieprasīt paroli"</string>
-    <string name="dock_cropped_windows_text" msgid="6378424064779004428">"Lietotnes lielumu nevar mainīt. Ritiniet to ar diviem pirkstiem."</string>
+    <string name="dock_forced_resizable" msgid="5914261505436217520">"Iespējams, lietotnē nedarbosies ekrāna sadalīšana."</string>
     <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"Lietotnē netiek atbalstīta ekrāna sadalīšana."</string>
     <string name="package_installed_device_owner" msgid="8420696545959087545">"Instalēja jūsu administrators"</string>
     <string name="package_updated_device_owner" msgid="8856631322440187071">"Atjaunināja administrators"</string>
@@ -1560,7 +1559,7 @@
     <string name="importance_from_person" msgid="9160133597262938296">"Tas ir svarīgi iesaistīto personu dēļ."</string>
     <string name="user_creation_account_exists" msgid="1942606193570143289">"Vai atļaut lietotnei <xliff:g id="APP">%1$s</xliff:g> izveidot jaunu lietotāju, izmantojot e-pasta adresi <xliff:g id="ACCOUNT">%2$s</xliff:g>?"</string>
     <string name="user_creation_adding" msgid="4482658054622099197">"Vai atļaut lietotnei <xliff:g id="APP">%1$s</xliff:g> izveidot jaunu lietotāju, izmantojot e-pasta adresi <xliff:g id="ACCOUNT">%2$s</xliff:g> (lietotājs ar šādu kontu jau pastāv)?"</string>
-    <string name="language_selection_title" msgid="7181332986330337171">"Valodas preference"</string>
+    <string name="language_selection_title" msgid="2680677278159281088">"Pievienot valodu"</string>
     <string name="country_selection_title" msgid="2954859441620215513">"Reģiona preference"</string>
     <string name="search_language_hint" msgid="7042102592055108574">"Ierakstiet valodas nosaukumu"</string>
     <string name="language_picker_section_suggested" msgid="8414489646861640885">"Ieteiktās"</string>
@@ -1583,6 +1582,7 @@
     <string name="pin_target" msgid="3052256031352291362">"Piespraust"</string>
     <string name="unpin_target" msgid="3556545602439143442">"Atspraust"</string>
     <string name="app_info" msgid="6856026610594615344">"Lietotnes informācija"</string>
-    <!-- no translation found for negative_duration (5688706061127375131) -->
-    <skip />
+    <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="audit_safemode_notification" msgid="6351827251856877200">"Rūpnīcas datu atiestatīšana ierīces normālai darbībai"</string>
+    <string name="audit_safemode_notification_details" msgid="1860601176690176413">"Pieskarieties, lai uzzinātu vairāk."</string>
 </resources>
diff --git a/core/res/res/values-mcc232-mnc11/config.xml b/core/res/res/values-mcc232-mnc11/config.xml
new file mode 100644
index 0000000..91e37b4
--- /dev/null
+++ b/core/res/res/values-mcc232-mnc11/config.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+ ** Copyright 2016, The Android Open Source Project
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ **     http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ** See the License for the specific language governing permissions and
+ ** limitations under the License.
+ */
+-->
+
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <!-- Don't use roaming icon for considered operators -->
+    <string-array translatable="false" name="config_operatorConsideredNonRoaming">
+        <item>23201</item>
+    </string-array>
+</resources>
diff --git a/core/res/res/values-mcc232-mnc12/config.xml b/core/res/res/values-mcc232-mnc12/config.xml
new file mode 100644
index 0000000..91e37b4
--- /dev/null
+++ b/core/res/res/values-mcc232-mnc12/config.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+ ** Copyright 2016, The Android Open Source Project
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ **     http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ** See the License for the specific language governing permissions and
+ ** limitations under the License.
+ */
+-->
+
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <!-- Don't use roaming icon for considered operators -->
+    <string-array translatable="false" name="config_operatorConsideredNonRoaming">
+        <item>23201</item>
+    </string-array>
+</resources>
diff --git a/core/res/res/values-mk-rMK/strings.xml b/core/res/res/values-mk-rMK/strings.xml
index ff35dfd..d0a7b20 100644
--- a/core/res/res/values-mk-rMK/strings.xml
+++ b/core/res/res/values-mk-rMK/strings.xml
@@ -229,7 +229,6 @@
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Гласовна помош"</string>
     <string name="global_action_lockdown" msgid="8751542514724332873">"Заклучи сега"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
-    <string name="notification_children_count_bracketed" msgid="1769425473168347839">"(<xliff:g id="NOTIFICATIONCOUNT">%d</xliff:g>)"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"Содржините се скриени"</string>
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Содржините се скриени поради политиката"</string>
     <string name="safeMode" msgid="2788228061547930246">"Безбеден режим"</string>
@@ -1052,13 +1051,12 @@
     <string name="usb_notification_message" msgid="7347368030849048437">"Допри за повеќе опции."</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"Поврзано е отстранување грешки преку УСБ"</string>
     <string name="adb_active_notification_message" msgid="1016654627626476142">"Допрете за да се оневозможи отстранувањето грешки преку USB."</string>
+    <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Се зема извештајот за грешки…"</string>
     <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Да се сподели извештајот за грешки?"</string>
     <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Се споделува извештај за грешки…"</string>
-    <string name="share_remote_bugreport_notification_message" msgid="752583906074230920">"Администраторот за информатичка технологија побара извештај за грешки за да ви помогне во отстранувањето на грешките од уредот. Апликациите и податоците можеби ќе се споделат, а уредот можеби ќе биде привремено побавен при работата."</string>
-    <string name="share_finished_remote_bugreport_notification_message" msgid="4627312060769912353">"Вашиот администратор за информатичка технологија побара извештај за грешки за да помогне со отстранување на грешките на овој уред. Апликациите и податоците може да бидат споделени."</string>
-    <string name="sharing_remote_bugreport_notification_message" msgid="673106383408474893">"Ова може привремено да го забави уредот"</string>
-    <string name="share_remote_bugreport_notification_accept" msgid="8203856129078669677">"ПРИФАТИ"</string>
-    <string name="share_remote_bugreport_notification_decline" msgid="6337969352057443969">"ОДБИЈ"</string>
+    <string name="share_remote_bugreport_notification_message_finished" msgid="8610614010660772643">"Вашиот администратор за информатичка технологија побара извештај за грешки за да ви помогне во отстранувањето на грешките на овој уред. Апликациите и податоците може да бидат споделени."</string>
+    <string name="share_remote_bugreport_action" msgid="6249476773913384948">"СПОДЕЛИ"</string>
+    <string name="decline_remote_bugreport_action" msgid="6230987241608770062">"ОДБИЈ"</string>
     <string name="select_input_method" msgid="8547250819326693584">"Измени тастатура"</string>
     <string name="configure_input_methods" msgid="4769971288371946846">"Избери тастатури"</string>
     <string name="show_ime" msgid="2506087537466597099">"Прикажувај го на екранот додека е активна физичката тастатура"</string>
@@ -1137,8 +1135,9 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Тапет"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Промени тапет"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Слушател на известувања"</string>
+    <string name="vr_listener_binding_label" msgid="4316591939343607306">"VR слушател"</string>
     <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Давател на услов"</string>
-    <string name="notification_assistant_binding_label" msgid="909456055569102952">"Помошник за известувања"</string>
+    <string name="notification_ranker_binding_label" msgid="774540592299064747">"Услуга за рангирање известувања"</string>
     <string name="vpn_title" msgid="19615213552042827">"Активирана VPN"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN е активирана со <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Допри за да управуваш со мрежата."</string>
@@ -1469,7 +1468,7 @@
     <string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Прашај за ПИН пред откачување"</string>
     <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Прашај за шема за отклучување пред откачување"</string>
     <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Прашај за лозинка пред откачување"</string>
-    <string name="dock_cropped_windows_text" msgid="6378424064779004428">"Не може да се промени големината на апликацијата, лизгајте ја со два прста."</string>
+    <string name="dock_forced_resizable" msgid="5914261505436217520">"Апликацијата можеби нема да работи во поделен екран."</string>
     <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"Апликацијата не поддржува поделен екран."</string>
     <string name="package_installed_device_owner" msgid="8420696545959087545">"Инсталирано од администраторот"</string>
     <string name="package_updated_device_owner" msgid="8856631322440187071">"Ажурирано од администраторот"</string>
@@ -1543,7 +1542,7 @@
     <string name="importance_from_person" msgid="9160133597262938296">"Ова е важно заради луѓето кои се вклучени."</string>
     <string name="user_creation_account_exists" msgid="1942606193570143289">"Дозволувате ли <xliff:g id="APP">%1$s</xliff:g> да создаде нов корисник со <xliff:g id="ACCOUNT">%2$s</xliff:g>?"</string>
     <string name="user_creation_adding" msgid="4482658054622099197">"Дозволувате ли <xliff:g id="APP">%1$s</xliff:g> да создаде нов корисник со <xliff:g id="ACCOUNT">%2$s</xliff:g> (веќе постои корисник со оваа сметка)?"</string>
-    <string name="language_selection_title" msgid="7181332986330337171">"Претпочитувања за јазик"</string>
+    <string name="language_selection_title" msgid="2680677278159281088">"Додај јазик"</string>
     <string name="country_selection_title" msgid="2954859441620215513">"Претпочитувања за регион"</string>
     <string name="search_language_hint" msgid="7042102592055108574">"Внеси име на јазик"</string>
     <string name="language_picker_section_suggested" msgid="8414489646861640885">"Предложени"</string>
@@ -1566,6 +1565,7 @@
     <string name="pin_target" msgid="3052256031352291362">"Прикачете"</string>
     <string name="unpin_target" msgid="3556545602439143442">"Откачете"</string>
     <string name="app_info" msgid="6856026610594615344">"Информации за апликација"</string>
-    <!-- no translation found for negative_duration (5688706061127375131) -->
-    <skip />
+    <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="audit_safemode_notification" msgid="6351827251856877200">"Ресетирање на фабрички вредности за уредот да се користи нормално"</string>
+    <string name="audit_safemode_notification_details" msgid="1860601176690176413">"Допрете за да дознаете повеќе."</string>
 </resources>
diff --git a/core/res/res/values-ml-rIN/strings.xml b/core/res/res/values-ml-rIN/strings.xml
index 633611a..829e06a 100644
--- a/core/res/res/values-ml-rIN/strings.xml
+++ b/core/res/res/values-ml-rIN/strings.xml
@@ -229,7 +229,6 @@
     <string name="global_action_voice_assist" msgid="7751191495200504480">"വോയ്‌സ് സഹായം"</string>
     <string name="global_action_lockdown" msgid="8751542514724332873">"ഇപ്പോൾ ലോക്കുചെയ്യുക"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
-    <string name="notification_children_count_bracketed" msgid="1769425473168347839">"(<xliff:g id="NOTIFICATIONCOUNT">%d</xliff:g>)"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"കോൺടാക്‌റ്റുകൾ മറച്ചു"</string>
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"നയം അനുസരിച്ച് ഉള്ളടക്കം മറച്ചിരിക്കുന്നു"</string>
     <string name="safeMode" msgid="2788228061547930246">"സുരക്ഷിത മോഡ്"</string>
@@ -1052,13 +1051,12 @@
     <string name="usb_notification_message" msgid="7347368030849048437">"കൂടുതൽ ഓപ്‌ഷനുകൾക്ക് സ്‌പർശിക്കൂ."</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"USB ഡീബഗ്ഗിംഗ് കണക്‌റ്റുചെയ്‌തു"</string>
     <string name="adb_active_notification_message" msgid="1016654627626476142">"USB ഡീബഗ്ഗിംഗ് ഓഫാക്കാൻ സ്‌പർശിക്കൂ."</string>
+    <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"ബഗ് റിപ്പോർട്ട് എടുക്കുന്നു…"</string>
     <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"ബഗ് റിപ്പോർട്ട് പങ്കിടണോ?"</string>
     <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"ബഗ് റിപ്പോർട്ട് പങ്കിടുന്നു…"</string>
-    <string name="share_remote_bugreport_notification_message" msgid="752583906074230920">"ഈ ഉപകരണവുമായി ബന്ധപ്പെട്ട പ്രശ്നം പരിഹരിക്കുന്നതിന് നിങ്ങളുടെ ഐടി അഡ്‌മിൻ ഒരു ബഗ് റിപ്പോർട്ട് അഭ്യർത്ഥിച്ചു. ആപ്‌സും ഡാറ്റയും പങ്കിടപ്പെട്ടേക്കും, നിങ്ങളുടെ ഉപകരണത്തെ ഇത് താൽക്കാലികമായി മന്ദഗതിയിലാക്കിയേക്കാം."</string>
-    <string name="share_finished_remote_bugreport_notification_message" msgid="4627312060769912353">"ഈ ഉപകരണത്തിലെ പ്രശ്നം പരിഹരിക്കുന്നതിന് നിങ്ങളുടെ ഐടി അഡ്‌മിൻ ഒരു ബഗ് റിപ്പോർട്ട് അഭ്യർത്ഥിച്ചു. ആപ്‌സും ഡാറ്റയും പങ്കിടപ്പെട്ടേക്കും."</string>
-    <string name="sharing_remote_bugreport_notification_message" msgid="673106383408474893">"നിങ്ങളുടെ ഉപകരണത്തെ ഇത് താൽക്കാലികമായി മന്ദഗതിയിലാക്കിയേക്കാം"</string>
-    <string name="share_remote_bugreport_notification_accept" msgid="8203856129078669677">"അംഗീകരിക്കുക"</string>
-    <string name="share_remote_bugreport_notification_decline" msgid="6337969352057443969">"നിരസിക്കുക"</string>
+    <string name="share_remote_bugreport_notification_message_finished" msgid="8610614010660772643">"ഈ ഉപകരണത്തിലെ പ്രശ്നം പരിഹരിക്കുന്നതിന് നിങ്ങളുടെ ഐടി അഡ്‌മിൻ ഒരു ബഗ് റിപ്പോർട്ട് അഭ്യർത്ഥിച്ചു. ആപ്‌സും ഡാറ്റയും പങ്കിടപ്പെട്ടേക്കും."</string>
+    <string name="share_remote_bugreport_action" msgid="6249476773913384948">"പങ്കിടുക"</string>
+    <string name="decline_remote_bugreport_action" msgid="6230987241608770062">"നിരസിക്കുക"</string>
     <string name="select_input_method" msgid="8547250819326693584">"കീബോഡ് മാറ്റുക"</string>
     <string name="configure_input_methods" msgid="4769971288371946846">"കീബോർഡുകൾ തിരഞ്ഞെടുക്കുക"</string>
     <string name="show_ime" msgid="2506087537466597099">"ഫിസിക്കൽ കീബോർഡ് സജീവമായിരിക്കുമ്പോൾ സ്ക്രീനിൽ നിലനിർത്തുക"</string>
@@ -1137,8 +1135,9 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"വാൾപേപ്പർ"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"വാൾപേപ്പർ മാറ്റുക"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"അറിയിപ്പ് ലിസണർ"</string>
+    <string name="vr_listener_binding_label" msgid="4316591939343607306">"VR ലിസണർ"</string>
     <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"കണ്ടീഷൻ ദാതാവ്"</string>
-    <string name="notification_assistant_binding_label" msgid="909456055569102952">"അറിയിപ്പ് സഹായി"</string>
+    <string name="notification_ranker_binding_label" msgid="774540592299064747">"അറിയിപ്പ് റാങ്കർ സേവനം"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN സജീവമാക്കി"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"<xliff:g id="APP">%s</xliff:g> ഉപയോഗിച്ച് VPN പ്രവർത്തനക്ഷമമാക്കി"</string>
     <string name="vpn_text" msgid="3011306607126450322">"നെറ്റ്‌വർക്ക് നിയന്ത്രിക്കാൻ സ്‌പർശിക്കുക."</string>
@@ -1467,7 +1466,7 @@
     <string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"ചെയ്യുംമുമ്പ് പിൻ ചോദിക്കൂ"</string>
     <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"അൺപിൻ ചെയ്യുന്നതിനുമുമ്പ് അൺലോക്ക് പാറ്റേൺ ആവശ്യപ്പെടുക"</string>
     <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"അൺപിൻ ചെയ്യുന്നതിനുമുമ്പ് പാസ്‌വേഡ് ആവശ്യപ്പെടുക"</string>
-    <string name="dock_cropped_windows_text" msgid="6378424064779004428">"ആപ്പിന്റെ വലുപ്പം ക്രമീകരിക്കാൻ കഴിയില്ല, രണ്ട് വിരലുകൾ ഉപയോഗിച്ച് അത് സ്ക്രോൾ ചെയ്യുക."</string>
+    <string name="dock_forced_resizable" msgid="5914261505436217520">"സ്പ്ലിറ്റ്-സ്ക്രീനിനൊപ്പം ആപ്പ് പ്രവർത്തിച്ചേക്കില്ല."</string>
     <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"സ്പ്ലിറ്റ്-സ്ക്രീനിനെ ആപ്പ് പിന്തുണയ്ക്കുന്നില്ല."</string>
     <string name="package_installed_device_owner" msgid="8420696545959087545">"നിങ്ങളുടെ അഡ്‌മിനിസ്‌ട്രേറ്റർ ഇൻസ്റ്റാളുചെയ്‌തു"</string>
     <string name="package_updated_device_owner" msgid="8856631322440187071">"നിങ്ങളുടെ അഡ്‌മിനിസ്‌ട്രേറ്റർ അപ്‌ഡേറ്റുചെയ്‌തു"</string>
@@ -1541,7 +1540,7 @@
     <string name="importance_from_person" msgid="9160133597262938296">"ഉൾപ്പെട്ടിട്ടുള്ള ആളുകളെ കണക്കിലെടുക്കുമ്പോള്‍ ഇത് പ്രധാനപ്പെട്ടതാണ്‌."</string>
     <string name="user_creation_account_exists" msgid="1942606193570143289">"<xliff:g id="ACCOUNT">%2$s</xliff:g> എന്ന അക്കൗണ്ട് ഉപയോഗിച്ച് പുതിയൊരു ഉപയോക്താവിനെ സൃഷ്ടിക്കാൻ <xliff:g id="APP">%1$s</xliff:g> എന്ന ആപ്പിനെ അനുവദിക്കണോ?"</string>
     <string name="user_creation_adding" msgid="4482658054622099197">"<xliff:g id="ACCOUNT">%2$s</xliff:g> എന്ന അക്കൗണ്ട് (ഈ അക്കൗണ്ട് ഉപയോഗിച്ചുള്ള ഒരു ഉപയോക്താവ് ഇതിനകം തന്നെ നിലവിലുണ്ട്) ഉപയോഗിച്ച് പുതിയൊരു ഉപയോക്താവിനെ സൃഷ്ടിക്കാൻ <xliff:g id="APP">%1$s</xliff:g> എന്ന ആപ്പിനെ അനുവദിക്കണോ?"</string>
-    <string name="language_selection_title" msgid="7181332986330337171">"ഭാഷാ മുൻഗണന"</string>
+    <string name="language_selection_title" msgid="2680677278159281088">"ഒരു ഭാഷ ചേർക്കുക"</string>
     <string name="country_selection_title" msgid="2954859441620215513">"മേഖലാ മുൻഗണന"</string>
     <string name="search_language_hint" msgid="7042102592055108574">"ഭാഷയുടെ പേര് ടൈപ്പുചെയ്യുക"</string>
     <string name="language_picker_section_suggested" msgid="8414489646861640885">"നിര്‍‌ദ്ദേശിച്ചത്"</string>
@@ -1564,6 +1563,7 @@
     <string name="pin_target" msgid="3052256031352291362">"പിൻ ചെയ്യുക"</string>
     <string name="unpin_target" msgid="3556545602439143442">"അൺപിൻ ചെയ്യുക"</string>
     <string name="app_info" msgid="6856026610594615344">"ആപ്പ് വിവരം"</string>
-    <!-- no translation found for negative_duration (5688706061127375131) -->
-    <skip />
+    <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="audit_safemode_notification" msgid="6351827251856877200">"ഈ ഉപകരണം സാധാരണ നിലയിൽ ഉപയോഗിക്കാൻ ഫാക്‌ടറി പുനഃസജ്ജീകരണം നടത്തുക"</string>
+    <string name="audit_safemode_notification_details" msgid="1860601176690176413">"കൂടുതലറിയുന്നതിന് സ്‌പർശിക്കുക."</string>
 </resources>
diff --git a/core/res/res/values-mn-rMN/strings.xml b/core/res/res/values-mn-rMN/strings.xml
index 4d75b07..9414f4e 100644
--- a/core/res/res/values-mn-rMN/strings.xml
+++ b/core/res/res/values-mn-rMN/strings.xml
@@ -229,7 +229,6 @@
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Дуут туслах"</string>
     <string name="global_action_lockdown" msgid="8751542514724332873">"Одоо түгжих"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
-    <string name="notification_children_count_bracketed" msgid="1769425473168347839">"(<xliff:g id="NOTIFICATIONCOUNT">%d</xliff:g>)"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"Контентыг нуусан"</string>
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Удирдамжийн дагуу нуусан агуулга"</string>
     <string name="safeMode" msgid="2788228061547930246">"Аюулгүй горим"</string>
@@ -1052,13 +1051,12 @@
     <string name="usb_notification_message" msgid="7347368030849048437">"Нэмэлт сонголтыг харахын тулд дарна."</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"USB дебаг холбогдсон"</string>
     <string name="adb_active_notification_message" msgid="1016654627626476142">"USB дебагийг идэвхгүй болгох бол хүрнэ үү."</string>
+    <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Алдааны тайланг авч байна..."</string>
     <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Алдааны тайланг хуваалцах уу?"</string>
     <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Алдааны тайланг хуваалцаж байна..."</string>
-    <string name="share_remote_bugreport_notification_message" msgid="752583906074230920">"Энэ төхөөрөмжийн асуудлыг шийдвэрлэхийнт тулд таны IT админ алдааны тайланг хүслээ. Апп болон өгөгдлийг хуваалцаж, таны төхөөрөмж бага зэрэг удаан ажиллаж болзошгүй."</string>
-    <string name="share_finished_remote_bugreport_notification_message" msgid="4627312060769912353">"Энэ төхөөрөмжийн асуудлыг шийдвэрлэхийн тулд таны IT админ алдааны тайланг хүслээ. Апп болон өгөгдлийг хуваалцсан байж болзошгүй."</string>
-    <string name="sharing_remote_bugreport_notification_message" msgid="673106383408474893">"Энэ нь таны төхөөрөмжийг түр хугацаанд удаашруулж болзошгүй"</string>
-    <string name="share_remote_bugreport_notification_accept" msgid="8203856129078669677">"ЗӨВШӨӨРӨХ"</string>
-    <string name="share_remote_bugreport_notification_decline" msgid="6337969352057443969">"ТАТГАЛЗАХ"</string>
+    <string name="share_remote_bugreport_notification_message_finished" msgid="8610614010660772643">"Энэ төхөөрөмжийн асуудлыг шийдвэрлэхийн тулд таны IT админ алдааны тайланг хүслээ. Апп болон өгөгдлийг хуваалцсан байж болзошгүй."</string>
+    <string name="share_remote_bugreport_action" msgid="6249476773913384948">"ХУВААЛЦАХ"</string>
+    <string name="decline_remote_bugreport_action" msgid="6230987241608770062">"ТАТГАЛЗАХ"</string>
     <string name="select_input_method" msgid="8547250819326693584">"Гарыг өөрчлөх"</string>
     <string name="configure_input_methods" msgid="4769971288371946846">"Гар сонгох"</string>
     <string name="show_ime" msgid="2506087537466597099">"Бодит гар идэвхтэй үед үүнийг дэлгэцэнд харуулна уу"</string>
@@ -1137,8 +1135,9 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Ханын зураг"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Ханын зураг солих"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Мэдэгдэл сонсогч"</string>
+    <string name="vr_listener_binding_label" msgid="4316591939343607306">"VR сонсогч"</string>
     <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Нөхцөл нийлүүлэгч"</string>
-    <string name="notification_assistant_binding_label" msgid="909456055569102952">"Мэдэгдлийн туслагч"</string>
+    <string name="notification_ranker_binding_label" msgid="774540592299064747">"Мэдэгдлийг ангилах үйлчилгээ"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN идэвхтэй болов"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN-г <xliff:g id="APP">%s</xliff:g> идэвхтэй болгов"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Сүлжээг удирдах бол хүрнэ үү."</string>
@@ -1467,7 +1466,7 @@
     <string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Тогтоосныг суллахаас өмнө PIN асуух"</string>
     <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Тогтоосныг суллахаас өмнө түгжээ тайлах хээ асуух"</string>
     <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Тогтоосныг суллахаас өмнө нууц үг асуух"</string>
-    <string name="dock_cropped_windows_text" msgid="6378424064779004428">"Апп-ын хэмжээг өөрчлөх боломжгүй. Үүнийг 2 хуруугаар гүйлгэнэ үү."</string>
+    <string name="dock_forced_resizable" msgid="5914261505436217520">"Апп хуваагдсан дэлгэцэд ажиллахгүй."</string>
     <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"Энэ апп нь дэлгэц хуваах тохиргоог дэмждэггүй."</string>
     <string name="package_installed_device_owner" msgid="8420696545959087545">"Таны админ суулгасан байна"</string>
     <string name="package_updated_device_owner" msgid="8856631322440187071">"Танай админ шинэчилсэн"</string>
@@ -1539,7 +1538,7 @@
     <string name="importance_from_person" msgid="9160133597262938296">"Оролцсон хүмүүсээс шалтгаалан энэ нь өндөр ач холбогдолтой."</string>
     <string name="user_creation_account_exists" msgid="1942606193570143289">"<xliff:g id="APP">%1$s</xliff:g>-г <xliff:g id="ACCOUNT">%2$s</xliff:g>-р шинэ Хэрэглэгч үүсгэхийг зөвшөөрөх үү?"</string>
     <string name="user_creation_adding" msgid="4482658054622099197">"<xliff:g id="APP">%1$s</xliff:g>-г <xliff:g id="ACCOUNT">%2$s</xliff:g>-р шинэ хэрэглэгч үүсгэхийг зөвшөөрөх үү (ийм бүртгэлтэй хэрэглэгч аль хэдийн байна) ?"</string>
-    <string name="language_selection_title" msgid="7181332986330337171">"Хэлний тохиргоо"</string>
+    <string name="language_selection_title" msgid="2680677278159281088">"Хэл нэмэх"</string>
     <string name="country_selection_title" msgid="2954859441620215513">"Бүс нутгийн тохиргоо"</string>
     <string name="search_language_hint" msgid="7042102592055108574">"Улсын хэлийг бичнэ үү"</string>
     <string name="language_picker_section_suggested" msgid="8414489646861640885">"Санал болгосон"</string>
@@ -1563,4 +1562,6 @@
     <string name="unpin_target" msgid="3556545602439143442">"Unpin"</string>
     <string name="app_info" msgid="6856026610594615344">"Апп-н мэдээлэл"</string>
     <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="audit_safemode_notification" msgid="6351827251856877200">"Энэ төхөөрөмжийг хэвийн ашиглахын тулд үйлдвэрийн тохиргоонд дахин тохируулна уу"</string>
+    <string name="audit_safemode_notification_details" msgid="1860601176690176413">"Дэлгэрэнгүй үзэх бол дарна уу."</string>
 </resources>
diff --git a/core/res/res/values-mr-rIN/strings.xml b/core/res/res/values-mr-rIN/strings.xml
index 228daa5..67351ea 100644
--- a/core/res/res/values-mr-rIN/strings.xml
+++ b/core/res/res/values-mr-rIN/strings.xml
@@ -229,7 +229,6 @@
     <string name="global_action_voice_assist" msgid="7751191495200504480">"व्हॉइस सहाय्य"</string>
     <string name="global_action_lockdown" msgid="8751542514724332873">"आता लॉक करा"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
-    <string name="notification_children_count_bracketed" msgid="1769425473168347839">"(<xliff:g id="NOTIFICATIONCOUNT">%d</xliff:g>)"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"लपविलेली सामग्री"</string>
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"धोरणाद्वारे सामग्री लपविली"</string>
     <string name="safeMode" msgid="2788228061547930246">"सुरक्षित मोड"</string>
@@ -1052,13 +1051,12 @@
     <string name="usb_notification_message" msgid="7347368030849048437">"अधिक पर्यायांसाठी स्पर्श करा."</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"USB डीबग करणे कनेक्‍ट केले"</string>
     <string name="adb_active_notification_message" msgid="1016654627626476142">"USB डीबग करणे अक्षम करण्यासाठी स्पर्श करा."</string>
+    <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"दोष अहवाल घेत आहे..."</string>
     <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"बग अहवाल सामायिक करायचा?"</string>
     <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"दोष अहवाल सामायिक करीत आहे..."</string>
-    <string name="share_remote_bugreport_notification_message" msgid="752583906074230920">"आपल्या IT प्रशासकाने या डिव्हाइसची समस्या निवारण करण्यात मदत करण्यासाठी एका दोष अहवालाची विनंती केली. अॅप्स आणि डेटा सामायिक केले जाऊ शकतात आणि आपले डिव्हाइस तात्पुरते धीमे होऊ शकते."</string>
-    <string name="share_finished_remote_bugreport_notification_message" msgid="4627312060769912353">"आपल्या IT प्रशासकाने या डिव्हाइसच्या समस्येचे निवारण करण्यात मदत करण्यासाठी दोष अहवालाची विनंती केली. अॅप्स आणि डेटा सामायिक केला जाऊ शकतो."</string>
-    <string name="sharing_remote_bugreport_notification_message" msgid="673106383408474893">"हे तात्पुरता आपले डिव्हाइस धिमे करू शकते."</string>
-    <string name="share_remote_bugreport_notification_accept" msgid="8203856129078669677">"स्वीकार करा"</string>
-    <string name="share_remote_bugreport_notification_decline" msgid="6337969352057443969">"नकार द्या"</string>
+    <string name="share_remote_bugreport_notification_message_finished" msgid="8610614010660772643">"आपल्या IT प्रशासकाने या डिव्हाइसच्या समस्येचे निवारण करण्यात मदत करण्यासाठी दोष अहवालाची विनंती केली. अॅप्स आणि डेटा सामायिक केले जाऊ शकतात."</string>
+    <string name="share_remote_bugreport_action" msgid="6249476773913384948">"सामायिक करा"</string>
+    <string name="decline_remote_bugreport_action" msgid="6230987241608770062">"नकार द्या"</string>
     <string name="select_input_method" msgid="8547250819326693584">"कीबोर्ड बदला"</string>
     <string name="configure_input_methods" msgid="4769971288371946846">"कीबोर्ड निवडा"</string>
     <string name="show_ime" msgid="2506087537466597099">"भौतिक कीबोर्ड सक्रिय असताना त्यास स्क्रीनवर ठेवा"</string>
@@ -1137,8 +1135,9 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"वॉलपेपर"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"वॉलपेपर बदला"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"सूचना ऐकणारा"</string>
+    <string name="vr_listener_binding_label" msgid="4316591939343607306">"VR श्रोता"</string>
     <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"अट प्रदाता"</string>
-    <string name="notification_assistant_binding_label" msgid="909456055569102952">"सूचना सहाय्यक"</string>
+    <string name="notification_ranker_binding_label" msgid="774540592299064747">"सूचना रॅंकर सेवा"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN सक्रिय"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"<xliff:g id="APP">%s</xliff:g> द्वारे VPN सक्रिय केले आहे"</string>
     <string name="vpn_text" msgid="3011306607126450322">"नेटवर्क व्यवस्थापित करण्यासाठी स्पर्श करा."</string>
@@ -1467,7 +1466,7 @@
     <string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"अनपिन करण्‍यापूर्वी पिन साठी विचारा"</string>
     <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"अनपिन करण्‍यापूर्वी अनलॉक नमुन्यासाठी विचारा"</string>
     <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"अनपिन करण्‍यापूर्वी संकेतशब्दासाठी विचारा"</string>
-    <string name="dock_cropped_windows_text" msgid="6378424064779004428">"अॅपचा आकार बदलण्यायोग्य नाही, दोन बोटांनी तो स्क्रोल करा."</string>
+    <string name="dock_forced_resizable" msgid="5914261505436217520">"अॅप कदाचित विभाजित-स्क्रीनसह कार्य करू शकत नाही."</string>
     <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"अॅप स्क्रीन-विभाजनास समर्थन देत नाही."</string>
     <string name="package_installed_device_owner" msgid="8420696545959087545">"आपल्या प्रशासकाद्वारे स्थापित केले आहे"</string>
     <string name="package_updated_device_owner" msgid="8856631322440187071">"आपल्या प्रशासकाद्वारे अद्यतनित केले"</string>
@@ -1541,7 +1540,7 @@
     <string name="importance_from_person" msgid="9160133597262938296">"सामील असलेल्या लोकांमुळे हे महत्वाचे आहे."</string>
     <string name="user_creation_account_exists" msgid="1942606193570143289">"<xliff:g id="ACCOUNT">%2$s</xliff:g> सह नवीन वापरकर्ता तयार करण्याची <xliff:g id="APP">%1$s</xliff:g> ला अनुमती द्यायची?"</string>
     <string name="user_creation_adding" msgid="4482658054622099197">"<xliff:g id="ACCOUNT">%2$s</xliff:g> सह नवीन वापरकर्ता तयार करण्याची (हे खाते असलेला वापरकर्ता आधीपासून विद्यमान आहे) <xliff:g id="APP">%1$s</xliff:g> ला अनुमती द्यायची?"</string>
-    <string name="language_selection_title" msgid="7181332986330337171">"भाषा प्राधान्य"</string>
+    <string name="language_selection_title" msgid="2680677278159281088">"एक भाषा जोडा"</string>
     <string name="country_selection_title" msgid="2954859441620215513">"प्रदेश प्राधान्य"</string>
     <string name="search_language_hint" msgid="7042102592055108574">"भाषा नाव टाइप करा"</string>
     <string name="language_picker_section_suggested" msgid="8414489646861640885">"सूचित केलेले"</string>
@@ -1564,6 +1563,7 @@
     <string name="pin_target" msgid="3052256031352291362">"पिन"</string>
     <string name="unpin_target" msgid="3556545602439143442">"अनपिन करा"</string>
     <string name="app_info" msgid="6856026610594615344">"अॅप माहिती"</string>
-    <!-- no translation found for negative_duration (5688706061127375131) -->
-    <skip />
+    <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="audit_safemode_notification" msgid="6351827251856877200">"हे डिव्हाइस सामान्यपणे वापरण्यासाठी फॅक्टरी रीसेट करा"</string>
+    <string name="audit_safemode_notification_details" msgid="1860601176690176413">"अधिक जाणून घेण्यासाठी स्पर्श करा."</string>
 </resources>
diff --git a/core/res/res/values-ms-rMY/strings.xml b/core/res/res/values-ms-rMY/strings.xml
index 9ad8999..5c342f0 100644
--- a/core/res/res/values-ms-rMY/strings.xml
+++ b/core/res/res/values-ms-rMY/strings.xml
@@ -229,7 +229,6 @@
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Bantuan Suara"</string>
     <string name="global_action_lockdown" msgid="8751542514724332873">"Kunci sekarang"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
-    <string name="notification_children_count_bracketed" msgid="1769425473168347839">"(<xliff:g id="NOTIFICATIONCOUNT">%d</xliff:g>)"</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>
     <string name="safeMode" msgid="2788228061547930246">"Mod selamat"</string>
@@ -1052,13 +1051,12 @@
     <string name="usb_notification_message" msgid="7347368030849048437">"Sentuh untuk mendapatkan lagi pilihan."</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"Penyahpepijatan USB disambungkan"</string>
     <string name="adb_active_notification_message" msgid="1016654627626476142">"Sentuh untuk melumpuhkan penyahpepijatan USB."</string>
+    <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Mengambil laporan pepijat…"</string>
     <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Kongsi laporan pepijat?"</string>
     <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Berkongsi laporan pepijat…"</string>
-    <string name="share_remote_bugreport_notification_message" msgid="752583906074230920">"Pentadbir IT anda meminta laporan pepijat untuk membantu menyelesaikan masalah peranti ini. Apl dan data mungkin dikongsi dan peranti anda mungkin menjadi perlahan untuk sementara waktu."</string>
-    <string name="share_finished_remote_bugreport_notification_message" msgid="4627312060769912353">"Pentadbir IT anda meminta laporan pepijat untuk membantu menyelesaikan masalah peranti ini. Apl dan data mungkin dikongsi."</string>
-    <string name="sharing_remote_bugreport_notification_message" msgid="673106383408474893">"Proses ini mungkin memperlahankan peranti anda untuk sementara waktu"</string>
-    <string name="share_remote_bugreport_notification_accept" msgid="8203856129078669677">"TERIMA"</string>
-    <string name="share_remote_bugreport_notification_decline" msgid="6337969352057443969">"TOLAK"</string>
+    <string name="share_remote_bugreport_notification_message_finished" msgid="8610614010660772643">"Pentadbir IT anda meminta laporan pepijat untuk membantu menyelesaikan masalah peranti ini. Apl dan data mungkin dikongsi."</string>
+    <string name="share_remote_bugreport_action" msgid="6249476773913384948">"KONGSI"</string>
+    <string name="decline_remote_bugreport_action" msgid="6230987241608770062">"TOLAK"</string>
     <string name="select_input_method" msgid="8547250819326693584">"Tukar papan kekunci"</string>
     <string name="configure_input_methods" msgid="4769971288371946846">"Pilih papan kekunci"</string>
     <string name="show_ime" msgid="2506087537466597099">"Pastikannya pada skrin, semasa papan kekunci fizikal aktif"</string>
@@ -1137,8 +1135,9 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Kertas dinding"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Tukar kertas dinding"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Pendengar pemberitahuan"</string>
+    <string name="vr_listener_binding_label" msgid="4316591939343607306">"Pendengar VR"</string>
     <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Pembekal keadaan"</string>
-    <string name="notification_assistant_binding_label" msgid="909456055569102952">"Pembantu pemberitahuan"</string>
+    <string name="notification_ranker_binding_label" msgid="774540592299064747">"Perkhidmatan penentu kedudukan pemberitahuan"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN diaktifkan"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN diaktifkan oleh <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Sentuh untuk mengurus rangkaian."</string>
@@ -1467,7 +1466,7 @@
     <string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Minta PIN sebelum menyahsemat"</string>
     <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Minta corak buka kunci sebelum menyahsemat"</string>
     <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Minta kata laluan sebelum menyahsemat"</string>
-    <string name="dock_cropped_windows_text" msgid="6378424064779004428">"Apl tidak boleh ditukar saiznya, tatal apl itu menggunakan dua jari."</string>
+    <string name="dock_forced_resizable" msgid="5914261505436217520">"Apl mungkin tidak berfungsi dengan skrin pisah."</string>
     <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"Apl tidak menyokong skrin pisah."</string>
     <string name="package_installed_device_owner" msgid="8420696545959087545">"Dipasang oleh pentadbir anda"</string>
     <string name="package_updated_device_owner" msgid="8856631322440187071">"Dikemas kini oleh pentadbir anda"</string>
@@ -1541,7 +1540,7 @@
     <string name="importance_from_person" msgid="9160133597262938296">"Mesej ini penting disebabkan orang yang terlibat."</string>
     <string name="user_creation_account_exists" msgid="1942606193570143289">"Benarkan <xliff:g id="APP">%1$s</xliff:g> membuat Pengguna baharu dengan <xliff:g id="ACCOUNT">%2$s</xliff:g>?"</string>
     <string name="user_creation_adding" msgid="4482658054622099197">"Benarkan <xliff:g id="APP">%1$s</xliff:g> membuat Pengguna baharu dengan <xliff:g id="ACCOUNT">%2$s</xliff:g> (Pengguna dengan akaun ini sudah wujud)?"</string>
-    <string name="language_selection_title" msgid="7181332986330337171">"Pilihan bahasa"</string>
+    <string name="language_selection_title" msgid="2680677278159281088">"Tambahkan bahasa"</string>
     <string name="country_selection_title" msgid="2954859441620215513">"Pilihan wilayah"</string>
     <string name="search_language_hint" msgid="7042102592055108574">"Taipkan nama bahasa"</string>
     <string name="language_picker_section_suggested" msgid="8414489646861640885">"Dicadangkan"</string>
@@ -1564,6 +1563,7 @@
     <string name="pin_target" msgid="3052256031352291362">"Semat"</string>
     <string name="unpin_target" msgid="3556545602439143442">"Nyahsemat"</string>
     <string name="app_info" msgid="6856026610594615344">"Maklumat apl"</string>
-    <!-- no translation found for negative_duration (5688706061127375131) -->
-    <skip />
+    <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="audit_safemode_notification" msgid="6351827251856877200">"Lakukan tetapan semula kilang untuk menggunakan peranti ini seperti biasa"</string>
+    <string name="audit_safemode_notification_details" msgid="1860601176690176413">"Sentuh untuk mengetahui lebih lanjut."</string>
 </resources>
diff --git a/core/res/res/values-my-rMM/strings.xml b/core/res/res/values-my-rMM/strings.xml
index 22fd821..e66cf66 100644
--- a/core/res/res/values-my-rMM/strings.xml
+++ b/core/res/res/values-my-rMM/strings.xml
@@ -229,7 +229,6 @@
     <string name="global_action_voice_assist" msgid="7751191495200504480">"အသံ အကူအညီ"</string>
     <string name="global_action_lockdown" msgid="8751542514724332873">"ယခု သော့ပိတ်ရန်"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"၉၉၉+"</string>
-    <string name="notification_children_count_bracketed" msgid="1769425473168347839">"(<xliff:g id="NOTIFICATIONCOUNT">%d</xliff:g>)"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"အကြောင်းအရာများ ဝှက်ထား"</string>
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"မူဝါဒမှ အကြောင်းအရာများကို ဝှက်ထားသည်"</string>
     <string name="safeMode" msgid="2788228061547930246">"အန္တရာယ်ကင်းမှု စနစ်(Safe mode)"</string>
@@ -1052,13 +1051,12 @@
     <string name="usb_notification_message" msgid="7347368030849048437">"ထပ်မံရွေးချယ်စရာများအတွက် ထိပါ"</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"USB အမှားစစ်ခြင်းအား ချိတ်ဆက်ထားသည်"</string>
     <string name="adb_active_notification_message" msgid="1016654627626476142">"USB ဒီဘာဂင် ပိတ်ရန် ထိပါ။"</string>
+    <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"ချွတ်ယွင်းချက် အစီရင်ခံစာပြုစုနေသည်..."</string>
     <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"ချွတ်ယွင်းချက် အစီရင်ခံစာကို မျှဝေမလား။"</string>
     <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"ချွတ်ယွင်းမှုအစီရင်ခံစာ မျှဝေနေသည်…"</string>
-    <string name="share_remote_bugreport_notification_message" msgid="752583906074230920">"ဤစက်ပစ္စည်းကို ပြဿနာအဖြေရှာရာတွင် ကူညီရန် သင့်အိုင်တီစီမံခန့်ခွဲသူသည် ချွတ်ယွင်းချက်အစီရင်ခံစာကို တောင်းဆိုထားသည်။ အက်ပ်များနှင့် ဒေတာကိုမျှဝေထားနိုင်ပြီး သင့်စက်ပစ္စည်းကို ခေတ္တနှေးကွေးသွားစေနိုင်သည်။"</string>
-    <string name="share_finished_remote_bugreport_notification_message" msgid="4627312060769912353">"ဤစက်ပစ္စည်းကို ပြဿနာအဖြေရှာရာတွင် ကူညီရန် သင့်အိုင်တီစီမံခန့်ခွဲသူသည် ချွတ်ယွင်းချက်အစီရင်ခံစာကို တောင်းဆိုထားသည်။ အက်ပ်များနှင့် ဒေတာကိုမျှဝေထားနိုင်ပါသည်။"</string>
-    <string name="sharing_remote_bugreport_notification_message" msgid="673106383408474893">"၎င်းသည်သင့်စက်ပစ္စည်းကို ခေတ္တနှေးကွေးသွားစေနိုင်သည်"</string>
-    <string name="share_remote_bugreport_notification_accept" msgid="8203856129078669677">"လက်ခံပါ"</string>
-    <string name="share_remote_bugreport_notification_decline" msgid="6337969352057443969">"ငြင်းပယ်ပါ"</string>
+    <string name="share_remote_bugreport_notification_message_finished" msgid="8610614010660772643">"ဤစက်ပစ္စည်းကို ပြဿနာအဖြေရှာရာတွင် ကူညီရန် သင့်အိုင်တီစီမံခန့်ခွဲသူသည် ချွတ်ယွင်းချက်အစီရင်ခံစာကို တောင်းဆိုထားသည်။ အက်ပ်များနှင့် ဒေတာကိုမျှဝေထားနိုင်ပါသည်။"</string>
+    <string name="share_remote_bugreport_action" msgid="6249476773913384948">"မျှဝေပါ"</string>
+    <string name="decline_remote_bugreport_action" msgid="6230987241608770062">"ငြင်းပယ်ပါ"</string>
     <string name="select_input_method" msgid="8547250819326693584">"ကီးဘုတ် ပြောင်းလဲရန်"</string>
     <string name="configure_input_methods" msgid="4769971288371946846">"ကီးဘုတ်များကို ရွေးရန်"</string>
     <string name="show_ime" msgid="2506087537466597099">"စက်၏ကီးဘုတ်ကိုအသုံးပြုနေစဉ် ၎င်းကိုမျက်နှာပြင်ပေါ်တွင် ထားပါ"</string>
@@ -1137,8 +1135,9 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"နောက်ခံ"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"နောက်ခံပြောင်းခြင်း"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"အကြောင်းကြားချက် နားတောင်သူ"</string>
+    <string name="vr_listener_binding_label" msgid="4316591939343607306">"VR နားထောင်မှုစနစ်"</string>
     <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"အခြေအနေ စီမံပေးသူ"</string>
-    <string name="notification_assistant_binding_label" msgid="909456055569102952">"သတိပေးချက် အကူ"</string>
+    <string name="notification_ranker_binding_label" msgid="774540592299064747">"သတိပေးချက် အဆင့်သတ်မှတ်ခြင်းဝန်ဆောင်မှု"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN ဖွင့်ထားပါသည်"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"<xliff:g id="APP">%s</xliff:g>မှVPNအလုပ်လုပ်နေသည်"</string>
     <string name="vpn_text" msgid="3011306607126450322">"ကွန်ရက် ထိန်းသိမ်းရန် တို့ထိပါ"</string>
@@ -1467,7 +1466,7 @@
     <string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"ပင်မဖြုတ်မီမှာ PIN ကို မေးကြည့်ရန်"</string>
     <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"ပင်မဖြုတ်မီမှာ သော့ဖွင့် ရေးဆွဲမှုပုံစံကို မေးကြည့်ရန်"</string>
     <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"ပင်မဖြုတ်မီမှာ စကားဝှက်ကို မေးကြည့်ရန်"</string>
-    <string name="dock_cropped_windows_text" msgid="6378424064779004428">"အက်ပ်ကို အရွယ်အစားချိန်၍မရပါ၊ လက်ချောင်းနှစ်ချောင်းဖြင့် အပေါ်အောက်ဆွဲပါ။"</string>
+    <string name="dock_forced_resizable" msgid="5914261505436217520">"မျက်နှာပြင် ခွဲခြမ်းပြသမှုဖြင့် အက်ပ်သည် အလုပ်လုပ်မည် မဟုတ်ပါ။"</string>
     <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"အက်ပ်သည် မျက်နှာပြင်ခွဲပြရန် ပံ့ပိုးထားခြင်းမရှိပါ။"</string>
     <string name="package_installed_device_owner" msgid="8420696545959087545">"သင့် အက်ဒမင်မှ သွင်းယူထား၏"</string>
     <string name="package_updated_device_owner" msgid="8856631322440187071">"သင့်စီမံခန့်ခွဲသူမှ အဆင့်မြှင့်ထားပါသည်။"</string>
@@ -1541,7 +1540,7 @@
     <string name="importance_from_person" msgid="9160133597262938296">"ပါဝင်သည့်လူများကြောင့် အရေးပါပါသည်။"</string>
     <string name="user_creation_account_exists" msgid="1942606193570143289">"<xliff:g id="APP">%1$s</xliff:g> ကို <xliff:g id="ACCOUNT">%2$s</xliff:g> ဖြင့်အသုံးပြုသူအသစ်ဖန်တီးခွင့်ပြုမလား။"</string>
     <string name="user_creation_adding" msgid="4482658054622099197">"<xliff:g id="APP">%1$s</xliff:g> ကို <xliff:g id="ACCOUNT">%2$s</xliff:g> ဖြင့်အသုံးပြုသူအသစ် ဖန်တီးခွင့်ပြုမလား (ဤအကောင့်ဖြင့် အသုံးပြုသူ ရှိနှင့်ပြီးဖြစ်သည်)။"</string>
-    <string name="language_selection_title" msgid="7181332986330337171">"ဘာသာစကားရွေးချယ်မှု"</string>
+    <string name="language_selection_title" msgid="2680677278159281088">"ဘာသာစကားတစ်ခု ထည့်ပါ"</string>
     <string name="country_selection_title" msgid="2954859441620215513">"ဒေသရွေးချယ်မှု"</string>
     <string name="search_language_hint" msgid="7042102592055108574">"ဘာသာစကားအမည် ထည့်ပါ"</string>
     <string name="language_picker_section_suggested" msgid="8414489646861640885">"အကြံပြုထားသော"</string>
@@ -1564,6 +1563,7 @@
     <string name="pin_target" msgid="3052256031352291362">"တွဲပါ"</string>
     <string name="unpin_target" msgid="3556545602439143442">"ဖြုတ်ပါ"</string>
     <string name="app_info" msgid="6856026610594615344">"အက်ပ်အချက်အလက်"</string>
-    <!-- no translation found for negative_duration (5688706061127375131) -->
-    <skip />
+    <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="audit_safemode_notification" msgid="6351827251856877200">"ဤစက်ပစ္စည်းကို သာမန်အသုံးပြုနိုင်ရန် စက်ရုံထုတ်အတိုင်း ပြန်လည်သတ်မှတ်ပါ"</string>
+    <string name="audit_safemode_notification_details" msgid="1860601176690176413">"ပိုမိုလေ့လာရန် တို့ပါ။"</string>
 </resources>
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index 44b5599..6c2358b 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -229,7 +229,6 @@
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Talehjelp"</string>
     <string name="global_action_lockdown" msgid="8751542514724332873">"Lås nå"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
-    <string name="notification_children_count_bracketed" msgid="1769425473168347839">"(<xliff:g id="NOTIFICATIONCOUNT">%d</xliff:g>)"</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>
     <string name="safeMode" msgid="2788228061547930246">"Sikkermodus"</string>
@@ -1052,13 +1051,12 @@
     <string name="usb_notification_message" msgid="7347368030849048437">"Trykk for å se flere alternativer."</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"USB-feilsøking tilkoblet"</string>
     <string name="adb_active_notification_message" msgid="1016654627626476142">"Trykk for å slå av USB-feilsøking."</string>
+    <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Kjører feilrapport …"</string>
     <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Vil du dele feilrapporten?"</string>
     <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Deler feilrapporten …"</string>
-    <string name="share_remote_bugreport_notification_message" msgid="752583906074230920">"IT-administratoren har bedt om en feilrapport for å hjelpe med feilsøkingen på denne enheten. Appene og dataene kan bli delt. Dette kan midlertidig gjøre enheten din tregere."</string>
-    <string name="share_finished_remote_bugreport_notification_message" msgid="4627312060769912353">"IT-administratoren har bedt om en feilrapport for å hjelpe med feilsøkingen på denne enheten. Appene og dataene kan bli delt."</string>
-    <string name="sharing_remote_bugreport_notification_message" msgid="673106383408474893">"Dette kan midlertidig gjøre enheten din tregere"</string>
-    <string name="share_remote_bugreport_notification_accept" msgid="8203856129078669677">"GODTA"</string>
-    <string name="share_remote_bugreport_notification_decline" msgid="6337969352057443969">"AVSLÅ"</string>
+    <string name="share_remote_bugreport_notification_message_finished" msgid="8610614010660772643">"IT-administratoren har bedt om en feilrapport for å hjelpe med feilsøkingen på denne enheten. Apper og data kan bli delt."</string>
+    <string name="share_remote_bugreport_action" msgid="6249476773913384948">"DEL"</string>
+    <string name="decline_remote_bugreport_action" msgid="6230987241608770062">"AVSLÅ"</string>
     <string name="select_input_method" msgid="8547250819326693584">"Endre tastatur"</string>
     <string name="configure_input_methods" msgid="4769971288371946846">"Velg tastatur"</string>
     <string name="show_ime" msgid="2506087537466597099">"Ha den på skjermen mens det fysiske tastaturet er aktivt"</string>
@@ -1137,8 +1135,9 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Bakgrunnsbilde"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Velg bakgrunnsbilde"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Varsellytteren"</string>
+    <string name="vr_listener_binding_label" msgid="4316591939343607306">"Lyttetjeneste for virtuell virkelighet"</string>
     <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Betingelsesleverandør"</string>
-    <string name="notification_assistant_binding_label" msgid="909456055569102952">"Varselassistent"</string>
+    <string name="notification_ranker_binding_label" msgid="774540592299064747">"Tjeneste for rangering av varsler"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN er aktivert"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN er aktivert av <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Trykk for å administrere nettverket."</string>
@@ -1467,7 +1466,7 @@
     <string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"PIN-kode for å løsne apper"</string>
     <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Krev bruk av opplåsningsmønster for å løsne apper"</string>
     <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Krev passord for å løsne apper"</string>
-    <string name="dock_cropped_windows_text" msgid="6378424064779004428">"Du kan ikke endre størrelse på appen – rull med to fingre."</string>
+    <string name="dock_forced_resizable" msgid="5914261505436217520">"Det kan hende at appen ikke fungerer med delt skjerm."</string>
     <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"Appen støtter ikke delt skjerm."</string>
     <string name="package_installed_device_owner" msgid="8420696545959087545">"Installert av administratoren"</string>
     <string name="package_updated_device_owner" msgid="8856631322440187071">"Oppdatert av administratoren"</string>
@@ -1541,7 +1540,7 @@
     <string name="importance_from_person" msgid="9160133597262938296">"Dette er viktig på grunn av folkene som er involvert."</string>
     <string name="user_creation_account_exists" msgid="1942606193570143289">"Vil du la <xliff:g id="APP">%1$s</xliff:g> opprette en ny bruker med <xliff:g id="ACCOUNT">%2$s</xliff:g>?"</string>
     <string name="user_creation_adding" msgid="4482658054622099197">"Vil du la <xliff:g id="APP">%1$s</xliff:g> opprette en ny bruker med <xliff:g id="ACCOUNT">%2$s</xliff:g>? (Det finnes allerede en bruker med denne kontoen.)"</string>
-    <string name="language_selection_title" msgid="7181332986330337171">"Språkinnstilling"</string>
+    <string name="language_selection_title" msgid="2680677278159281088">"Legg til et språk"</string>
     <string name="country_selection_title" msgid="2954859441620215513">"Regionsinnstilling"</string>
     <string name="search_language_hint" msgid="7042102592055108574">"Skriv inn språknavn"</string>
     <string name="language_picker_section_suggested" msgid="8414489646861640885">"Foreslått"</string>
@@ -1566,6 +1565,7 @@
     <string name="pin_target" msgid="3052256031352291362">"Fest"</string>
     <string name="unpin_target" msgid="3556545602439143442">"Løsne"</string>
     <string name="app_info" msgid="6856026610594615344">"Info om appen"</string>
-    <!-- no translation found for negative_duration (5688706061127375131) -->
-    <skip />
+    <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="audit_safemode_notification" msgid="6351827251856877200">"Tilbakestill til fabrikkstandard for å bruke denne enheten som normalt"</string>
+    <string name="audit_safemode_notification_details" msgid="1860601176690176413">"Trykk for å finne ut mer."</string>
 </resources>
diff --git a/core/res/res/values-ne-rNP/strings.xml b/core/res/res/values-ne-rNP/strings.xml
index aa50778..40d13f0 100644
--- a/core/res/res/values-ne-rNP/strings.xml
+++ b/core/res/res/values-ne-rNP/strings.xml
@@ -229,7 +229,6 @@
     <string name="global_action_voice_assist" msgid="7751191495200504480">"आवाज सहायता"</string>
     <string name="global_action_lockdown" msgid="8751542514724332873">"अब बन्द गर्नुहोस्"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"९९९+"</string>
-    <string name="notification_children_count_bracketed" msgid="1769425473168347839">"(<xliff:g id="NOTIFICATIONCOUNT">%d</xliff:g>)"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"लुकेका सामाग्रीहरू"</string>
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"नीतिद्वारा लुकाइएका सामग्री"</string>
     <string name="safeMode" msgid="2788228061547930246">"सुरक्षित मोड"</string>
@@ -1058,13 +1057,12 @@
     <string name="usb_notification_message" msgid="7347368030849048437">"थप विकल्पहरूका लागि छुनुहोस्।"</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"USB डिबग गर्ने जडित छ"</string>
     <string name="adb_active_notification_message" msgid="1016654627626476142">"USB डिबग गर्ने असक्षम पार्न छुनुहोस्।"</string>
+    <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"बग रिपोर्ट लिँदै..."</string>
     <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"बग रिपोर्टलाई साझेदारी गर्ने हो?"</string>
     <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"बग रिपोर्टलाई साझेदारी गर्दै ..."</string>
-    <string name="share_remote_bugreport_notification_message" msgid="752583906074230920">"तपाईंको IT प्रशासकले यो यन्त्रको समस्या निवारण गर्नमा मद्दत गर्न बग रिपोर्टहरूका लागि अनुरोध गर्नु भएको छ । अनुप्रयोगहरू र डेटा साझेदारी गर्न सकिन्छ र तपाईंको यन्त्र अस्थायी रूपमा सुस्त हुन सक्छ।"</string>
-    <string name="share_finished_remote_bugreport_notification_message" msgid="4627312060769912353">"तपाईंको IT प्रशासकले यो यन्त्रको समस्या निवारण गर्नमा मदत गर्न बग रिपोर्टहरूका लागि अनुरोध गर्नु भएको छ । Apps र डेटा साझेदारी गर्न सक्नुहुन्छ ।"</string>
-    <string name="sharing_remote_bugreport_notification_message" msgid="673106383408474893">"यसले अस्थायी रूपमा तपाईंको यन्त्रलाई सुस्त बनाउन सक्छ"</string>
-    <string name="share_remote_bugreport_notification_accept" msgid="8203856129078669677">"स्वीकार गर्नुहोस्"</string>
-    <string name="share_remote_bugreport_notification_decline" msgid="6337969352057443969">"अस्वीकार गर्नुहोस्"</string>
+    <string name="share_remote_bugreport_notification_message_finished" msgid="8610614010660772643">"तपाईँको IT प्रशासकले यस यन्त्रको समस्या निवारण गर्नमा मद्दत गर्न बग रिपोर्टका लागि अनुरोध गर्नुभएको छ। अनुप्रयोग र डेटा साझेदारी हुन सक्छ।"</string>
+    <string name="share_remote_bugreport_action" msgid="6249476773913384948">"साझेदारी गर्नुहोस्"</string>
+    <string name="decline_remote_bugreport_action" msgid="6230987241608770062">"अस्वीकार गर्नुहोस्"</string>
     <string name="select_input_method" msgid="8547250819326693584">"कुञ्जीपाटी परिवर्तन गर्नुहोस्"</string>
     <string name="configure_input_methods" msgid="4769971288371946846">"कीबोर्ड छान्नुहोस्"</string>
     <string name="show_ime" msgid="2506087537466597099">"भौतिक किबोर्ड सक्रिय हुँदा यसलाई स्क्रिनमा राख्नुहोस्"</string>
@@ -1143,8 +1141,9 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"वालपेपर"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"वालपेपर परिवर्तन गर्नुहोस्"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"सूचना सुन्नेवाला"</string>
+    <string name="vr_listener_binding_label" msgid="4316591939343607306">"VR श्रोता"</string>
     <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"सर्त प्रदायक"</string>
-    <string name="notification_assistant_binding_label" msgid="909456055569102952">"सूचना सहायक"</string>
+    <string name="notification_ranker_binding_label" msgid="774540592299064747">"सूचनालाई श्रेणी प्रदान गर्ने सेवा"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN सक्रिय भयो"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN <xliff:g id="APP">%s</xliff:g>द्वारा सक्रिय गरिएको हो"</string>
     <string name="vpn_text" msgid="3011306607126450322">"नेटवर्क प्रबन्ध गर्न छुनुहोस्।"</string>
@@ -1473,7 +1472,7 @@
     <string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"पिन निकाल्नुअघि PIN सोध्नुहोस्"</string>
     <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"पिन निकाल्नुअघि खोल्ने रूपरेखा सोध्नुहोस्"</string>
     <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"पिन निकाल्नुअघि पासवर्ड सोध्नुहोस्"</string>
-    <string name="dock_cropped_windows_text" msgid="6378424064779004428">"अनुप्रयोगको आकार सानो-ठूलो बनाउन मिल्दैन, दुई औँलाले यसलाई स्क्रोल गर्नुहोस्।"</string>
+    <string name="dock_forced_resizable" msgid="5914261505436217520">"अनुप्रयोगले विभाजित-स्क्रिनमा काम नगर्न सक्छ।"</string>
     <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"अनुप्रयोगले विभाजित-स्क्रिनलाई समर्थन गर्दैन।"</string>
     <string name="package_installed_device_owner" msgid="8420696545959087545">"तपाईँको प्रशासकद्वारा स्थापना गरिएको"</string>
     <string name="package_updated_device_owner" msgid="8856631322440187071">"तपाईँको प्रशासकद्वारा अद्यावधिक गरिएको"</string>
@@ -1547,7 +1546,7 @@
     <string name="importance_from_person" msgid="9160133597262938296">"यसमा सङ्लग्न भएका मानिसहरूको कारणले गर्दा यो महत्वपूर्ण छ।"</string>
     <string name="user_creation_account_exists" msgid="1942606193570143289">"<xliff:g id="ACCOUNT">%2$s</xliff:g> सँगै नयाँ प्रयोगकर्ता सिर्जना गर्न <xliff:g id="APP">%1$s</xliff:g> लाई अनुमति दिने हो?"</string>
     <string name="user_creation_adding" msgid="4482658054622099197">"<xliff:g id="ACCOUNT">%2$s</xliff:g> सँगै नयाँ प्रयोगकर्ता सिर्जना गर्न <xliff:g id="APP">%1$s</xliff:g> लाई अनुमति दिने (यस खाताको प्रयोगकर्ता पहिले नै अवस्थित छ) ?"</string>
-    <string name="language_selection_title" msgid="7181332986330337171">"भाषाको प्राथमिकता"</string>
+    <string name="language_selection_title" msgid="2680677278159281088">"भाषा थप्नुहोस्"</string>
     <string name="country_selection_title" msgid="2954859441620215513">"क्षेत्रको प्राथमिकता"</string>
     <string name="search_language_hint" msgid="7042102592055108574">"भाषाको नाम टाइप गर्नुहोस्"</string>
     <string name="language_picker_section_suggested" msgid="8414489646861640885">"सुझाव दिइयो"</string>
@@ -1570,6 +1569,7 @@
     <string name="pin_target" msgid="3052256031352291362">"पिन गर्नुहोस्"</string>
     <string name="unpin_target" msgid="3556545602439143442">"अनपिन गर्नुहोस्"</string>
     <string name="app_info" msgid="6856026610594615344">"अनुप्रयोगका बारे जानकारी"</string>
-    <!-- no translation found for negative_duration (5688706061127375131) -->
-    <skip />
+    <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="audit_safemode_notification" msgid="6351827251856877200">"यस यन्त्रलाई सामान्य रूपमा प्रयोग गर्नका लागि फ्याक्ट्री रिसेट गर्नुहोस्"</string>
+    <string name="audit_safemode_notification_details" msgid="1860601176690176413">"थप जान्नका लागि स्पर्श गर्नुहोस्।"</string>
 </resources>
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index 5f0c123..b48fc33 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -229,7 +229,6 @@
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Spraakassistent"</string>
     <string name="global_action_lockdown" msgid="8751542514724332873">"Nu vergrendelen"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999 +"</string>
-    <string name="notification_children_count_bracketed" msgid="1769425473168347839">"(<xliff:g id="NOTIFICATIONCOUNT">%d</xliff:g>)"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"Inhoud verborgen"</string>
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Content verborgen op basis van beleid"</string>
     <string name="safeMode" msgid="2788228061547930246">"Veilige modus"</string>
@@ -1052,13 +1051,12 @@
     <string name="usb_notification_message" msgid="7347368030849048437">"Tik voor meer opties."</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"USB-foutopsporing verbonden"</string>
     <string name="adb_active_notification_message" msgid="1016654627626476142">"Tik om USB-foutopsporing uit te schakelen."</string>
+    <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Bugrapport genereren…"</string>
     <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Bugrapport delen?"</string>
     <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Bugrapport delen…"</string>
-    <string name="share_remote_bugreport_notification_message" msgid="752583906074230920">"Je IT-beheerder heeft een bugrapport aangevraagd om problemen met dit apparaat op te lossen. Apps en gegevens kunnen worden gedeeld en je apparaat kan hierdoor tijdelijk worden vertraagd."</string>
-    <string name="share_finished_remote_bugreport_notification_message" msgid="4627312060769912353">"Je IT-beheerder heeft een bugrapport aangevraagd om problemen met dit apparaat op te lossen. Apps en gegevens kunnen worden gedeeld."</string>
-    <string name="sharing_remote_bugreport_notification_message" msgid="673106383408474893">"Dit kan je apparaat tijdelijk vertragen"</string>
-    <string name="share_remote_bugreport_notification_accept" msgid="8203856129078669677">"ACCEPTEREN"</string>
-    <string name="share_remote_bugreport_notification_decline" msgid="6337969352057443969">"WEIGEREN"</string>
+    <string name="share_remote_bugreport_notification_message_finished" msgid="8610614010660772643">"Je IT-beheerder heeft een bugrapport aangevraagd om problemen met dit apparaat op te lossen. Apps en gegevens kunnen worden gedeeld."</string>
+    <string name="share_remote_bugreport_action" msgid="6249476773913384948">"DELEN"</string>
+    <string name="decline_remote_bugreport_action" msgid="6230987241608770062">"WEIGEREN"</string>
     <string name="select_input_method" msgid="8547250819326693584">"Toetsenbord wijzigen"</string>
     <string name="configure_input_methods" msgid="4769971288371946846">"Toetsenborden kiezen"</string>
     <string name="show_ime" msgid="2506087537466597099">"Dit op het scherm weergeven terwijl het fysieke toetsenbord actief is"</string>
@@ -1137,8 +1135,9 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Achtergrond"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Achtergrond wijzigen"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Listener voor meldingen"</string>
+    <string name="vr_listener_binding_label" msgid="4316591939343607306">"VR-listener"</string>
     <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Provider van voorwaarden"</string>
-    <string name="notification_assistant_binding_label" msgid="909456055569102952">"Meldingsassistent"</string>
+    <string name="notification_ranker_binding_label" msgid="774540592299064747">"Rangschikkingsservice voor meldingen"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN is geactiveerd"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN wordt geactiveerd door <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Raak aan om het netwerk te beheren."</string>
@@ -1467,7 +1466,7 @@
     <string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Vraag pin voor losmaken"</string>
     <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Vraag patroon voor losmaken"</string>
     <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Vraag wachtwoord voor losmaken"</string>
-    <string name="dock_cropped_windows_text" msgid="6378424064779004428">"Formaat van app kan niet worden aangepast, scrol met twee vingers."</string>
+    <string name="dock_forced_resizable" msgid="5914261505436217520">"App werkt mogelijk niet met gesplitst scherm."</string>
     <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"App biedt geen ondersteuning voor gesplitst scherm."</string>
     <string name="package_installed_device_owner" msgid="8420696545959087545">"Geïnstalleerd door je beheerder"</string>
     <string name="package_updated_device_owner" msgid="8856631322440187071">"Geüpdatet door je beheerder"</string>
@@ -1541,7 +1540,7 @@
     <string name="importance_from_person" msgid="9160133597262938296">"Dit is belangrijk vanwege de betrokken mensen."</string>
     <string name="user_creation_account_exists" msgid="1942606193570143289">"Toestaan dat <xliff:g id="APP">%1$s</xliff:g> een nieuwe gebruiker met <xliff:g id="ACCOUNT">%2$s</xliff:g> maakt?"</string>
     <string name="user_creation_adding" msgid="4482658054622099197">"Toestaan dat <xliff:g id="APP">%1$s</xliff:g> een nieuwe gebruiker met <xliff:g id="ACCOUNT">%2$s</xliff:g> maakt (er is al een gebruiker met dit account)?"</string>
-    <string name="language_selection_title" msgid="7181332986330337171">"Taalvoorkeur"</string>
+    <string name="language_selection_title" msgid="2680677278159281088">"Een taal toevoegen"</string>
     <string name="country_selection_title" msgid="2954859441620215513">"Regiovoorkeur"</string>
     <string name="search_language_hint" msgid="7042102592055108574">"Typ een taalnaam"</string>
     <string name="language_picker_section_suggested" msgid="8414489646861640885">"Voorgesteld"</string>
@@ -1565,4 +1564,6 @@
     <string name="unpin_target" msgid="3556545602439143442">"Losmaken"</string>
     <string name="app_info" msgid="6856026610594615344">"App-info"</string>
     <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="audit_safemode_notification" msgid="6351827251856877200">"Zet dit apparaat terug op de fabrieksinstellingen om het normaal te gebruiken"</string>
+    <string name="audit_safemode_notification_details" msgid="1860601176690176413">"Tik voor meer informatie."</string>
 </resources>
diff --git a/core/res/res/values-pa-rIN/strings.xml b/core/res/res/values-pa-rIN/strings.xml
index 80edf51..7ff2071 100644
--- a/core/res/res/values-pa-rIN/strings.xml
+++ b/core/res/res/values-pa-rIN/strings.xml
@@ -229,7 +229,6 @@
     <string name="global_action_voice_assist" msgid="7751191495200504480">"ਵੌਇਸ ਅਸਿਸਟ"</string>
     <string name="global_action_lockdown" msgid="8751542514724332873">"ਹੁਣ ਲੌਕ ਕਰੋ"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
-    <string name="notification_children_count_bracketed" msgid="1769425473168347839">"(<xliff:g id="NOTIFICATIONCOUNT">%d</xliff:g>)"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"ਸਮੱਗਰੀਆਂ ਲੁਕਾਈਆਂ ਗਈਆਂ"</string>
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"ਨੀਤੀ ਦੁਆਰਾ ਸਮੱਗਰੀ ਲੁਕਾਈ ਗਈ"</string>
     <string name="safeMode" msgid="2788228061547930246">"ਸੁਰੱਖਿਅਤ ਮੋਡ"</string>
@@ -1052,13 +1051,12 @@
     <string name="usb_notification_message" msgid="7347368030849048437">"ਹੋਰ ਵਿਕਲਪਾਂ ਲਈ ਸਪਰਸ਼ ਕਰੋ।"</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"USB ਡੀਬਗਿੰਗ ਕਨੈਕਟ ਕੀਤੀ"</string>
     <string name="adb_active_notification_message" msgid="1016654627626476142">"USB ਡੀਬਗਿੰਗ ਨੂੰ ਅਸਮਰੱਥ ਬਣਾਉਣ ਲਈ ਛੋਹਵੋ।"</string>
+    <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"ਬੱਗ ਰਿਪਰੋਟ ਪ੍ਰਾਪਤ ਕੀਤੀ ਜਾ ਰਹੀ ਹੈ..."</string>
     <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"ਕੀ ਬੱਗ ਰਿਪੋਰਟ ਸਾਂਝੀ ਕਰਨੀ ਹੈ?"</string>
     <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"ਬੱਗ ਰਿਪੋਰਟ ਸਾਂਝੀ ਕੀਤੀ ਜਾ ਰਹੀ ਹੈ…"</string>
-    <string name="share_remote_bugreport_notification_message" msgid="752583906074230920">"ਤੁਹਾਡੇ IT ਪ੍ਰਸ਼ਾਸਕ ਨੇ ਇਸ ਡੀਵਾਈਸ ਦੀ ਸਮੱਸਿਆ ਨੂੰ ਠੀਕ ਕਰਨ ਵਿੱਚ ਮਦਦ ਲਈ ਬੱਗ ਰਿਪੋਰਟ ਦੀ ਬੇਨਤੀ ਕੀਤੀ ਹੈ। ਐਪਾਂ ਅਤੇ ਡੈਟੇ ਨੂੰ ਸਾਂਝਾ ਕੀਤਾ ਜਾ ਸਕਦਾ ਹੈ ਅਤੇ ਤੁਹਾਡੀ ਡੀਵਾਈਸ ਆਰਜ਼ੀ ਤੌਰ \'ਤੇ ਹੌਲੀ ਹੋ ਸਕਦੀ ਹੈ।"</string>
-    <string name="share_finished_remote_bugreport_notification_message" msgid="4627312060769912353">"ਤੁਹਾਡੇ IT ਪ੍ਰਸ਼ਾਸਕ ਨੇ ਇਸ ਡੀਵਾਈਸ ਦੀ ਸਮੱਸਿਆ ਨੂੰ ਠੀਕ ਕਰਨ ਵਿੱੱਚ ਮਦਦ ਲਈ ਬੱਗ ਰਿਪੋਰਟ ਦੀ ਬੇਨਤੀ ਕੀਤੀ ਹੈ। ਐਪਾਂ ਅਤੇ ਡੈਟੇ ਨੂੰ ਸਾਂਝਾ ਕੀਤਾ ਜਾ ਸਕਦਾ ਹੈ।"</string>
-    <string name="sharing_remote_bugreport_notification_message" msgid="673106383408474893">"ਇਹ ਤੁਹਾਡੀ ਡੀਵਾਈਸ ਨੂੰ ਆਰਜ਼ੀ ਤੌਰ \'ਤੇ ਹੌਲੀ ਕਰ ਸਕਦਾ ਹੈ"</string>
-    <string name="share_remote_bugreport_notification_accept" msgid="8203856129078669677">"ਸਵੀਕਾਰ ਕਰੋ"</string>
-    <string name="share_remote_bugreport_notification_decline" msgid="6337969352057443969">"ਅਸਵੀਕਾਰ ਕਰੋ"</string>
+    <string name="share_remote_bugreport_notification_message_finished" msgid="8610614010660772643">"ਤੁਹਾਡੇ IT ਪ੍ਰਸ਼ਾਸਕ ਨੇ ਇਸ ਡੀਵਾਈਸ ਦੀ ਸਮੱਸਿਆ ਨੂੰ ਠੀਕ ਕਰਨ ਵਿੱੱਚ ਮਦਦ ਲਈ ਬੱਗ ਰਿਪੋਰਟ ਦੀ ਬੇਨਤੀ ਕੀਤੀ ਹੈ। ਐਪਾਂ ਅਤੇ ਡੈਟੇ ਨੂੰ ਸਾਂਝਾ ਕੀਤਾ ਜਾ ਸਕਦਾ ਹੈ।"</string>
+    <string name="share_remote_bugreport_action" msgid="6249476773913384948">"ਸਾਂਝੀ ਕਰੋ"</string>
+    <string name="decline_remote_bugreport_action" msgid="6230987241608770062">"ਅਸਵੀਕਾਰ ਕਰੋ"</string>
     <string name="select_input_method" msgid="8547250819326693584">"ਕੀਬੋਰਡ ਬਦਲੋ"</string>
     <string name="configure_input_methods" msgid="4769971288371946846">"ਕੀਬੋਰਡਸ ਚੁਣੋ"</string>
     <string name="show_ime" msgid="2506087537466597099">"ਭੌਤਿਕ ਕੀ-ਬੋਰਡ ਸਰਗਰਮ ਹੋਣ ਦੌਰਾਨ ਇਸ ਨੂੰ ਸਕ੍ਰੀਨ \'ਤੇ ਬਣਾਈ ਰੱਖੋ"</string>
@@ -1137,8 +1135,9 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"ਵਾਲਪੇਪਰ"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"ਵਾਲਪੇਪਰ ਬਦਲੋ"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"ਸੂਚਨਾ ਸੁਣਨ ਵਾਲਾ"</string>
+    <string name="vr_listener_binding_label" msgid="4316591939343607306">"VR ਸਰੋਤਾ"</string>
     <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"ਸਥਿਤੀ ਪ੍ਰਦਾਤਾ"</string>
-    <string name="notification_assistant_binding_label" msgid="909456055569102952">"ਸੂਚਨਾ ਸਹਾਇਕ"</string>
+    <string name="notification_ranker_binding_label" msgid="774540592299064747">"ਸੂਚਨਾ ਰੈਂਕਰ ਸੇਵਾ"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN ਸਕਿਰਿਆ ਕੀਤਾ"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN <xliff:g id="APP">%s</xliff:g> ਰਾਹੀਂ ਸਕਿਰਿਆ ਬਣਾਇਆ ਗਿਆ ਹੈ"</string>
     <string name="vpn_text" msgid="3011306607126450322">"ਨੈਟਵਰਕ ਵਿਵਸਥਿਤ ਕਰਨ ਲਈ ਛੋਹਵੋ।"</string>
@@ -1467,7 +1466,7 @@
     <string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"ਅਨਪਿਨ ਕਰਨ ਤੋਂ ਪਹਿਲਾਂ PIN ਮੰਗੋ"</string>
     <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"ਅਨਪਿਨ ਕਰਨ ਤੋਂ ਪਹਿਲਾਂ ਪੈਟਰਨ ਅਨਲੌਕ ਕਰਨ ਲਈ ਪੁੱਛੋ"</string>
     <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"ਅਨਪਿਨ ਕਰਨ ਤੋਂ ਪਹਿਲਾਂ ਪਾਸਵਰਡ ਮੰਗੋ"</string>
-    <string name="dock_cropped_windows_text" msgid="6378424064779004428">"ਐਪ ਦਾ ਆਕਾਰ ਬਦਲਿਆ ਨਹੀਂ ਜਾ ਸਕਦਾ, ਇਸ ਨੂੰ ਦੋ ਉਂਗਲਾਂ ਨਾਲ ਸਕਰੋਲ ਕਰੋ।"</string>
+    <string name="dock_forced_resizable" msgid="5914261505436217520">"ਹੋ ਸਕਦਾ ਹੈ ਕਿ ਐਪ ਸਪਲਿਟ-ਸਕ੍ਰੀਨ ਨਾਲ ਕੰਮ ਨਾ ਕਰੇ।"</string>
     <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"ਐਪ ਸਪਲਿਟ-ਸਕ੍ਰੀਨ ਨੂੰ ਸਮਰਥਨ ਨਹੀਂ ਕਰਦੀ।"</string>
     <string name="package_installed_device_owner" msgid="8420696545959087545">"ਤੁਹਾਡੇ ਪ੍ਰਬੰਧਕ ਵੱਲੋਂ ਇੰਸਟੌਲ ਕੀਤਾ ਗਿਆ"</string>
     <string name="package_updated_device_owner" msgid="8856631322440187071">"ਤੁਹਾਡੇ ਪ੍ਰਸ਼ਾਸਕ ਦੁਆਰਾ ਅਪਡੇਟ ਕੀਤਾ ਗਿਆ"</string>
@@ -1541,7 +1540,7 @@
     <string name="importance_from_person" msgid="9160133597262938296">"ਇਹ ਸ਼ਾਮਲ ਲੋਕਾਂ ਦੇ ਕਾਰਨ ਮਹੱਤਵਪੂਰਨ ਹੈ।"</string>
     <string name="user_creation_account_exists" msgid="1942606193570143289">"ਕੀ <xliff:g id="APP">%1$s</xliff:g> ਨੂੰ <xliff:g id="ACCOUNT">%2$s</xliff:g> ਨਾਲ ਇੱਕ ਨਵਾਂ ਵਰਤੋਂਕਾਰ ਬਣਾਉਣ ਦੀ ਮਨਜ਼ੂਰੀ ਦੇਣੀ ਹੈ?"</string>
     <string name="user_creation_adding" msgid="4482658054622099197">"ਕੀ <xliff:g id="APP">%1$s</xliff:g> ਨੂੰ <xliff:g id="ACCOUNT">%2$s</xliff:g> ਨਾਲ ਇੱਕ ਨਵਾਂ ਵਰਤੋਂਕਾਰ ਬਣਾਉਣ ਦੀ ਮਨਜ਼ੂਰੀ ਦੇਣੀ ਹੈ (ਇਸ ਖਾਤੇ ਨਾਲ ਇੱਕ ਵਰਤੋਂਕਾਰ ਪਹਿਲਾਂ ਤੋਂ ਹੀ ਮੌਜੂਦ ਹੈ) ?"</string>
-    <string name="language_selection_title" msgid="7181332986330337171">"ਭਾਸ਼ਾ ਤਰਜੀਹ"</string>
+    <string name="language_selection_title" msgid="2680677278159281088">"ਇੱਕ ਭਾਸ਼ਾ ਸ਼ਾਮਲ ਕਰੋ"</string>
     <string name="country_selection_title" msgid="2954859441620215513">"ਖੇਤਰ ਤਰਜੀਹ"</string>
     <string name="search_language_hint" msgid="7042102592055108574">"ਭਾਸ਼ਾ ਨਾਮ ਟਾਈਪ ਕਰੋ"</string>
     <string name="language_picker_section_suggested" msgid="8414489646861640885">"ਸੁਝਾਈਆਂ ਗਈਆਂ"</string>
@@ -1564,6 +1563,7 @@
     <string name="pin_target" msgid="3052256031352291362">"ਪਿੰਨ ਕਰੋ"</string>
     <string name="unpin_target" msgid="3556545602439143442">"ਅਨਪਿੰਨ ਕਰੋ"</string>
     <string name="app_info" msgid="6856026610594615344">"ਐਪ ਜਾਣਕਾਰੀ"</string>
-    <!-- no translation found for negative_duration (5688706061127375131) -->
-    <skip />
+    <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="audit_safemode_notification" msgid="6351827251856877200">"ਇਸ ਡੀਵਾਈਸ ਨੂੰ ਸਧਾਰਨ ਰੂਪ ਵਿੱਚ ਵਰਤਣ ਲਈ ਫੈਕਟਰੀ ਰੀਸੈੱਟ ਕਰੋ"</string>
+    <string name="audit_safemode_notification_details" msgid="1860601176690176413">"ਹੋਰ ਜਾਣਨ ਲਈ ਸਪਰਸ਼ ਕਰੋ।"</string>
 </resources>
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index 968151c..b68b45a 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -233,7 +233,6 @@
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Asystent głosowy"</string>
     <string name="global_action_lockdown" msgid="8751542514724332873">"Zablokuj teraz"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"&gt;999"</string>
-    <string name="notification_children_count_bracketed" msgid="1769425473168347839">"(<xliff:g id="NOTIFICATIONCOUNT">%d</xliff:g>)"</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>
     <string name="safeMode" msgid="2788228061547930246">"Tryb awaryjny"</string>
@@ -1068,13 +1067,12 @@
     <string name="usb_notification_message" msgid="7347368030849048437">"Kliknij, by zobaczyć więcej opcji."</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"Podłączono moduł debugowania USB"</string>
     <string name="adb_active_notification_message" msgid="1016654627626476142">"Dotknij, aby wyłączyć debugowanie USB."</string>
+    <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Zgłaszam błąd…"</string>
     <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Udostępnić raport o błędzie?"</string>
     <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Udostępniam raport o błędzie…"</string>
-    <string name="share_remote_bugreport_notification_message" msgid="752583906074230920">"Administrator poprosił o raport o błędzie, by szybciej rozwiązać problemy na tym urządzeniu. Raport może zawierać informacje o aplikacjach i inne dane. Urządzenie może przez chwilę działać wolniej."</string>
-    <string name="share_finished_remote_bugreport_notification_message" msgid="4627312060769912353">"Administrator poprosił o raport o błędzie, który pomoże w rozwiązaniu problemów na tym urządzeniu. Mogą zostać udostępnione aplikacje i dane."</string>
-    <string name="sharing_remote_bugreport_notification_message" msgid="673106383408474893">"Urządzenie może przez chwilę działać wolniej"</string>
-    <string name="share_remote_bugreport_notification_accept" msgid="8203856129078669677">"AKCEPTUJ"</string>
-    <string name="share_remote_bugreport_notification_decline" msgid="6337969352057443969">"ODRZUĆ"</string>
+    <string name="share_remote_bugreport_notification_message_finished" msgid="8610614010660772643">"Administrator poprosił o raport o błędzie, który pomoże w rozwiązaniu problemów na tym urządzeniu. Mogą zostać udostępnione aplikacje i dane."</string>
+    <string name="share_remote_bugreport_action" msgid="6249476773913384948">"UDOSTĘPNIJ"</string>
+    <string name="decline_remote_bugreport_action" msgid="6230987241608770062">"ODRZUĆ"</string>
     <string name="select_input_method" msgid="8547250819326693584">"Zmień klawiaturę"</string>
     <string name="configure_input_methods" msgid="4769971288371946846">"Wybierz klawiatury"</string>
     <string name="show_ime" msgid="2506087537466597099">"Pozostaw na ekranie, gdy aktywna jest klawiatura fizyczna"</string>
@@ -1153,8 +1151,9 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Tapeta"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Zmień tapetę"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Odbiornik powiadomień"</string>
+    <string name="vr_listener_binding_label" msgid="4316591939343607306">"Odbiornik rzeczywistości wirtualnej"</string>
     <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Dostawca warunków"</string>
-    <string name="notification_assistant_binding_label" msgid="909456055569102952">"Asystent powiadomień"</string>
+    <string name="notification_ranker_binding_label" msgid="774540592299064747">"Usługa rankingu powiadomień"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN aktywny"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"Obsługa sieci VPN została włączona przez aplikację <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Dotknij, aby zarządzać siecią."</string>
@@ -1487,7 +1486,7 @@
     <string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Podaj PIN, aby odpiąć"</string>
     <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Aby odpiąć, poproś o wzór odblokowania"</string>
     <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Aby odpiąć, poproś o hasło"</string>
-    <string name="dock_cropped_windows_text" msgid="6378424064779004428">"Rozmiaru tej aplikacji nie można zmienić. Przewiń ją dwoma palcami."</string>
+    <string name="dock_forced_resizable" msgid="5914261505436217520">"Aplikacja może nie działać przy podzielonym ekranie."</string>
     <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"Aplikacja nie obsługuje dzielonego ekranu."</string>
     <string name="package_installed_device_owner" msgid="8420696545959087545">"Zainstalowany przez administratora"</string>
     <string name="package_updated_device_owner" msgid="8856631322440187071">"Zaktualizowane przez administratora"</string>
@@ -1579,7 +1578,7 @@
     <string name="importance_from_person" msgid="9160133597262938296">"Ta wiadomość jest ważna ze względu na osoby uczestniczące w wątku."</string>
     <string name="user_creation_account_exists" msgid="1942606193570143289">"Zezwalasz aplikacji <xliff:g id="APP">%1$s</xliff:g> na utworzenie nowego użytkownika dla konta <xliff:g id="ACCOUNT">%2$s</xliff:g>?"</string>
     <string name="user_creation_adding" msgid="4482658054622099197">"Zezwalasz aplikacji <xliff:g id="APP">%1$s</xliff:g> na utworzenie nowego użytkownika dla konta <xliff:g id="ACCOUNT">%2$s</xliff:g>)? Użytkownik z tym kontem już istnieje."</string>
-    <string name="language_selection_title" msgid="7181332986330337171">"Ustawienie języka"</string>
+    <string name="language_selection_title" msgid="2680677278159281088">"Dodaj język"</string>
     <string name="country_selection_title" msgid="2954859441620215513">"Ustawienie regionu"</string>
     <string name="search_language_hint" msgid="7042102592055108574">"Wpisz nazwę języka"</string>
     <string name="language_picker_section_suggested" msgid="8414489646861640885">"Sugerowane"</string>
@@ -1602,6 +1601,7 @@
     <string name="pin_target" msgid="3052256031352291362">"Przypnij"</string>
     <string name="unpin_target" msgid="3556545602439143442">"Odepnij"</string>
     <string name="app_info" msgid="6856026610594615344">"O aplikacji"</string>
-    <!-- no translation found for negative_duration (5688706061127375131) -->
-    <skip />
+    <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="audit_safemode_notification" msgid="6351827251856877200">"Aby używać tego urządzenia normalnie, przywróć ustawienia fabryczne"</string>
+    <string name="audit_safemode_notification_details" msgid="1860601176690176413">"Kliknij, by dowiedzieć się więcej."</string>
 </resources>
diff --git a/core/res/res/values-pt-rBR/strings.xml b/core/res/res/values-pt-rBR/strings.xml
index 434934f..cd0de0e 100644
--- a/core/res/res/values-pt-rBR/strings.xml
+++ b/core/res/res/values-pt-rBR/strings.xml
@@ -229,7 +229,6 @@
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Ajuda de voz"</string>
     <string name="global_action_lockdown" msgid="8751542514724332873">"Bloquear agora"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"&gt;999"</string>
-    <string name="notification_children_count_bracketed" msgid="1769425473168347839">"(<xliff:g id="NOTIFICATIONCOUNT">%d</xliff:g>)"</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>
     <string name="safeMode" msgid="2788228061547930246">"Modo de segurança"</string>
@@ -243,7 +242,7 @@
     <string name="permgrouplab_calendar" msgid="5863508437783683902">"Agenda"</string>
     <string name="permgroupdesc_calendar" msgid="3889615280211184106">"acesse sua agenda"</string>
     <string name="permgrouplab_sms" msgid="228308803364967808">"SMS"</string>
-    <string name="permgroupdesc_sms" msgid="4656988620100940350">"enviar e ver mensagens SMS"</string>
+    <string name="permgroupdesc_sms" msgid="4656988620100940350">"envie e veja mensagens SMS"</string>
     <string name="permgrouplab_storage" msgid="1971118770546336966">"Armazenamento"</string>
     <string name="permgroupdesc_storage" msgid="637758554581589203">"acesse fotos, mídia e arquivos do dispositivo"</string>
     <string name="permgrouplab_microphone" msgid="171539900250043464">"Microfone"</string>
@@ -1052,13 +1051,12 @@
     <string name="usb_notification_message" msgid="7347368030849048437">"Toque para ver mais opções."</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"Depuração USB conectada"</string>
     <string name="adb_active_notification_message" msgid="1016654627626476142">"Toque para desativar a depuração do USB."</string>
+    <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Gerando relatório do bug..."</string>
     <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Compartilhar relatório do bug?"</string>
     <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Compartilhando relatório do bug…"</string>
-    <string name="share_remote_bugreport_notification_message" msgid="752583906074230920">"Seu administrador de TI solicitou um relatório de bug para ajudar a resolver problemas deste dispositivo. É possível que apps e dados sejam compartilhados, o que pode deixar seu dispositivo temporariamente mais lento."</string>
-    <string name="share_finished_remote_bugreport_notification_message" msgid="4627312060769912353">"Seu administrador de TI solicitou um relatório de bug para ajudar a resolver problemas deste dispositivo. É possível que apps e dados sejam compartilhados."</string>
-    <string name="sharing_remote_bugreport_notification_message" msgid="673106383408474893">"Isso pode deixar seu dispositivo temporariamente mais lento"</string>
-    <string name="share_remote_bugreport_notification_accept" msgid="8203856129078669677">"ACEITAR"</string>
-    <string name="share_remote_bugreport_notification_decline" msgid="6337969352057443969">"RECUSAR"</string>
+    <string name="share_remote_bugreport_notification_message_finished" msgid="8610614010660772643">"Seu administrador de TI solicitou um relatório de bug para ajudar a resolver problemas deste dispositivo. É possível que apps e dados sejam compartilhados."</string>
+    <string name="share_remote_bugreport_action" msgid="6249476773913384948">"COMPARTILHAR"</string>
+    <string name="decline_remote_bugreport_action" msgid="6230987241608770062">"RECUSAR"</string>
     <string name="select_input_method" msgid="8547250819326693584">"Alterar teclado"</string>
     <string name="configure_input_methods" msgid="4769971288371946846">"Escolher teclados"</string>
     <string name="show_ime" msgid="2506087537466597099">"Manter na tela enquanto o teclado físico estiver ativo"</string>
@@ -1137,8 +1135,9 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Plano de fundo"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Alterar plano de fundo"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Ouvinte de notificações"</string>
+    <string name="vr_listener_binding_label" msgid="4316591939343607306">"Ouvinte de RV"</string>
     <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Provedor de condições"</string>
-    <string name="notification_assistant_binding_label" msgid="909456055569102952">"Assistente de notificação"</string>
+    <string name="notification_ranker_binding_label" msgid="774540592299064747">"Serviço de classificação de notificação"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN ativada"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"A VPN está ativada por <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Toque para gerenciar a rede."</string>
@@ -1467,7 +1466,7 @@
     <string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Pedir PIN antes de liberar"</string>
     <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Pedir padrão de desbloqueio antes de liberar"</string>
     <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Pedir senha antes de liberar"</string>
-    <string name="dock_cropped_windows_text" msgid="6378424064779004428">"O app não é redimensionável. Desloque-o com dois dedos."</string>
+    <string name="dock_forced_resizable" msgid="5914261505436217520">"É possível que o app não funcione com o recurso de divisão de tela."</string>
     <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"O app não é compatível com a divisão de tela."</string>
     <string name="package_installed_device_owner" msgid="8420696545959087545">"Instalado pelo seu administrador"</string>
     <string name="package_updated_device_owner" msgid="8856631322440187071">"Atualizado pelo administrador"</string>
@@ -1541,7 +1540,7 @@
     <string name="importance_from_person" msgid="9160133597262938296">"Isso é importante por causa das pessoas envolvidas."</string>
     <string name="user_creation_account_exists" msgid="1942606193570143289">"Permitir que <xliff:g id="APP">%1$s</xliff:g> crie um novo usuário com <xliff:g id="ACCOUNT">%2$s</xliff:g>?"</string>
     <string name="user_creation_adding" msgid="4482658054622099197">"Permitir que <xliff:g id="APP">%1$s</xliff:g> crie um novo usuário com <xliff:g id="ACCOUNT">%2$s</xliff:g> (já existe um usuário com essa conta)?"</string>
-    <string name="language_selection_title" msgid="7181332986330337171">"Preferência de idioma"</string>
+    <string name="language_selection_title" msgid="2680677278159281088">"Adicionar um idioma"</string>
     <string name="country_selection_title" msgid="2954859441620215513">"Preferência de região"</string>
     <string name="search_language_hint" msgid="7042102592055108574">"Digitar nome do idioma"</string>
     <string name="language_picker_section_suggested" msgid="8414489646861640885">"Sugeridos"</string>
@@ -1564,6 +1563,7 @@
     <string name="pin_target" msgid="3052256031352291362">"Fixar guia"</string>
     <string name="unpin_target" msgid="3556545602439143442">"Liberar guia"</string>
     <string name="app_info" msgid="6856026610594615344">"Informações do app"</string>
-    <!-- no translation found for negative_duration (5688706061127375131) -->
-    <skip />
+    <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="audit_safemode_notification" msgid="6351827251856877200">"Redefinir para a configuração original para usar este dispositivo normalmente"</string>
+    <string name="audit_safemode_notification_details" msgid="1860601176690176413">"Toque para saber mais."</string>
 </resources>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index 318afe4..dde0131 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -229,7 +229,6 @@
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Assist. de voz"</string>
     <string name="global_action_lockdown" msgid="8751542514724332873">"Bloquear agora"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
-    <string name="notification_children_count_bracketed" msgid="1769425473168347839">"(<xliff:g id="NOTIFICATIONCOUNT">%d</xliff:g>)"</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>
     <string name="safeMode" msgid="2788228061547930246">"Modo seguro"</string>
@@ -338,7 +337,7 @@
     <string name="permdesc_writeCallLog" product="tablet" msgid="6661806062274119245">"Permite à aplicação modificar o registo de chamadas do tablet, incluindo os dados sobre as chamadas recebidas e efetuadas. As aplicações maliciosas podem utilizar esta funcionalidade para apagar ou modificar o registo de chamadas."</string>
     <string name="permdesc_writeCallLog" product="tv" msgid="4225034892248398019">"Permite à aplicação modificar o registo de chamadas da sua TV, incluindo os dados sobre as chamadas recebidas e efetuadas. As aplicações maliciosas podem utilizar esta funcionalidade para apagar ou modificar o registo de chamadas."</string>
     <string name="permdesc_writeCallLog" product="default" msgid="683941736352787842">"Permite à aplicação modificar o registo de chamadas do telemóvel, incluindo os dados sobre as chamadas recebidas e efetuadas. As aplicações maliciosas podem utilizar esta funcionalidade para apagar ou modificar o seu registo de chamadas."</string>
-    <string name="permlab_bodySensors" msgid="4683341291818520277">"aceder a sensores corp. (como monit. do ritmo cardíaco)"</string>
+    <string name="permlab_bodySensors" msgid="4683341291818520277">"aceder a sensores corporais (como monitores do ritmo cardíaco)"</string>
     <string name="permdesc_bodySensors" product="default" msgid="4380015021754180431">"Permite que a aplicação aceda a dados de sensores que monitorizam a sua condição física, como o ritmo cardíaco."</string>
     <string name="permlab_readCalendar" msgid="5972727560257612398">"ler eventos do calendário, para além de informações confidenciais"</string>
     <string name="permdesc_readCalendar" product="tablet" msgid="4216462049057658723">"Permite que a aplicação leia todos os eventos do calendário guardados no tablet, incluindo os de amigos ou colegas de trabalho. Pode permitir que a aplicação partilhe ou guarde dados do calendário, independentemente da confidencialidade ou sensibilidade."</string>
@@ -1052,13 +1051,12 @@
     <string name="usb_notification_message" msgid="7347368030849048437">"Toque para ver mais opções."</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"Depuração USB ligada"</string>
     <string name="adb_active_notification_message" msgid="1016654627626476142">"Toque para desat. a depuração USB."</string>
+    <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"A criar relatório de erro…"</string>
     <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Pretende partilhar o relatório de erro?"</string>
     <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"A partilhar relatório de erro…"</string>
-    <string name="share_remote_bugreport_notification_message" msgid="752583906074230920">"O seu administrador de TI solicitou um relatório de erro para ajudar na resolução de problemas deste dispositivo. As aplicações e os dados podem ser partilhados e o dispositivo pode tornar-se temporariamente mais lento."</string>
-    <string name="share_finished_remote_bugreport_notification_message" msgid="4627312060769912353">"O seu administrador de TI solicitou um relatório de erro para ajudar na resolução de problemas deste dispositivo. As aplicações e os dados podem ser partilhados."</string>
-    <string name="sharing_remote_bugreport_notification_message" msgid="673106383408474893">"Esta ação pode tornar o dispositivo mais lento temporariamente"</string>
-    <string name="share_remote_bugreport_notification_accept" msgid="8203856129078669677">"ACEITAR"</string>
-    <string name="share_remote_bugreport_notification_decline" msgid="6337969352057443969">"RECUSAR"</string>
+    <string name="share_remote_bugreport_notification_message_finished" msgid="8610614010660772643">"O seu administrador de TI solicitou um relatório de erro para ajudar na resolução de problemas deste dispositivo. As aplicações e os dados podem ser partilhados."</string>
+    <string name="share_remote_bugreport_action" msgid="6249476773913384948">"PARTILHAR"</string>
+    <string name="decline_remote_bugreport_action" msgid="6230987241608770062">"RECUSAR"</string>
     <string name="select_input_method" msgid="8547250819326693584">"Alterar teclado"</string>
     <string name="configure_input_methods" msgid="4769971288371946846">"Escolher teclados"</string>
     <string name="show_ime" msgid="2506087537466597099">"Manter no ecrã enquanto o teclado físico estiver ativo"</string>
@@ -1137,8 +1135,9 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Imagem de fundo"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Alterar imagem de fundo"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Serviço de escuta de notificações"</string>
+    <string name="vr_listener_binding_label" msgid="4316591939343607306">"Serviço de escuta de RV"</string>
     <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Fornecedor de condição"</string>
-    <string name="notification_assistant_binding_label" msgid="909456055569102952">"Assistente de notificações"</string>
+    <string name="notification_ranker_binding_label" msgid="774540592299064747">"Serviço de classificação de notificações"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN ativada"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"A VPN foi ativada pelo <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Toque para gerir a rede."</string>
@@ -1467,7 +1466,7 @@
     <string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Pedir PIN antes de soltar"</string>
     <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Pedir sequência de desbloqueio antes de soltar"</string>
     <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Pedir palavra-passe antes de soltar"</string>
-    <string name="dock_cropped_windows_text" msgid="6378424064779004428">"A aplicação não é redimensionável. Desloque-a com dois dedos."</string>
+    <string name="dock_forced_resizable" msgid="5914261505436217520">"A aplicação pode não funcionar com o ecrã dividido."</string>
     <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"A aplicação não é compatível com o ecrã dividido."</string>
     <string name="package_installed_device_owner" msgid="8420696545959087545">"Instalado pelo administrador"</string>
     <string name="package_updated_device_owner" msgid="8856631322440187071">"Atualizado pelo administrador"</string>
@@ -1541,7 +1540,7 @@
     <string name="importance_from_person" msgid="9160133597262938296">"É importante devido às pessoas envolvidas."</string>
     <string name="user_creation_account_exists" msgid="1942606193570143289">"Pretende permitir que o <xliff:g id="APP">%1$s</xliff:g> crie um novo utilizador com <xliff:g id="ACCOUNT">%2$s</xliff:g>?"</string>
     <string name="user_creation_adding" msgid="4482658054622099197">"Pretende permitir que o <xliff:g id="APP">%1$s</xliff:g> crie um novo utilizador com <xliff:g id="ACCOUNT">%2$s</xliff:g> (já existe um utilizador com esta conta)?"</string>
-    <string name="language_selection_title" msgid="7181332986330337171">"Preferência de idioma"</string>
+    <string name="language_selection_title" msgid="2680677278159281088">"Adicionar um idioma"</string>
     <string name="country_selection_title" msgid="2954859441620215513">"Preferência de região"</string>
     <string name="search_language_hint" msgid="7042102592055108574">"Intr. nome do idioma"</string>
     <string name="language_picker_section_suggested" msgid="8414489646861640885">"Sugeridos"</string>
@@ -1565,4 +1564,6 @@
     <string name="unpin_target" msgid="3556545602439143442">"Soltar"</string>
     <string name="app_info" msgid="6856026610594615344">"Informações da aplicação"</string>
     <string name="negative_duration" msgid="5688706061127375131">"-<xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="audit_safemode_notification" msgid="6351827251856877200">"Fazer uma reposição de dados de fábrica para utilizar este dispositivo normalmente"</string>
+    <string name="audit_safemode_notification_details" msgid="1860601176690176413">"Toque para saber mais."</string>
 </resources>
diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml
index 434934f..cd0de0e 100644
--- a/core/res/res/values-pt/strings.xml
+++ b/core/res/res/values-pt/strings.xml
@@ -229,7 +229,6 @@
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Ajuda de voz"</string>
     <string name="global_action_lockdown" msgid="8751542514724332873">"Bloquear agora"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"&gt;999"</string>
-    <string name="notification_children_count_bracketed" msgid="1769425473168347839">"(<xliff:g id="NOTIFICATIONCOUNT">%d</xliff:g>)"</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>
     <string name="safeMode" msgid="2788228061547930246">"Modo de segurança"</string>
@@ -243,7 +242,7 @@
     <string name="permgrouplab_calendar" msgid="5863508437783683902">"Agenda"</string>
     <string name="permgroupdesc_calendar" msgid="3889615280211184106">"acesse sua agenda"</string>
     <string name="permgrouplab_sms" msgid="228308803364967808">"SMS"</string>
-    <string name="permgroupdesc_sms" msgid="4656988620100940350">"enviar e ver mensagens SMS"</string>
+    <string name="permgroupdesc_sms" msgid="4656988620100940350">"envie e veja mensagens SMS"</string>
     <string name="permgrouplab_storage" msgid="1971118770546336966">"Armazenamento"</string>
     <string name="permgroupdesc_storage" msgid="637758554581589203">"acesse fotos, mídia e arquivos do dispositivo"</string>
     <string name="permgrouplab_microphone" msgid="171539900250043464">"Microfone"</string>
@@ -1052,13 +1051,12 @@
     <string name="usb_notification_message" msgid="7347368030849048437">"Toque para ver mais opções."</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"Depuração USB conectada"</string>
     <string name="adb_active_notification_message" msgid="1016654627626476142">"Toque para desativar a depuração do USB."</string>
+    <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Gerando relatório do bug..."</string>
     <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Compartilhar relatório do bug?"</string>
     <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Compartilhando relatório do bug…"</string>
-    <string name="share_remote_bugreport_notification_message" msgid="752583906074230920">"Seu administrador de TI solicitou um relatório de bug para ajudar a resolver problemas deste dispositivo. É possível que apps e dados sejam compartilhados, o que pode deixar seu dispositivo temporariamente mais lento."</string>
-    <string name="share_finished_remote_bugreport_notification_message" msgid="4627312060769912353">"Seu administrador de TI solicitou um relatório de bug para ajudar a resolver problemas deste dispositivo. É possível que apps e dados sejam compartilhados."</string>
-    <string name="sharing_remote_bugreport_notification_message" msgid="673106383408474893">"Isso pode deixar seu dispositivo temporariamente mais lento"</string>
-    <string name="share_remote_bugreport_notification_accept" msgid="8203856129078669677">"ACEITAR"</string>
-    <string name="share_remote_bugreport_notification_decline" msgid="6337969352057443969">"RECUSAR"</string>
+    <string name="share_remote_bugreport_notification_message_finished" msgid="8610614010660772643">"Seu administrador de TI solicitou um relatório de bug para ajudar a resolver problemas deste dispositivo. É possível que apps e dados sejam compartilhados."</string>
+    <string name="share_remote_bugreport_action" msgid="6249476773913384948">"COMPARTILHAR"</string>
+    <string name="decline_remote_bugreport_action" msgid="6230987241608770062">"RECUSAR"</string>
     <string name="select_input_method" msgid="8547250819326693584">"Alterar teclado"</string>
     <string name="configure_input_methods" msgid="4769971288371946846">"Escolher teclados"</string>
     <string name="show_ime" msgid="2506087537466597099">"Manter na tela enquanto o teclado físico estiver ativo"</string>
@@ -1137,8 +1135,9 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Plano de fundo"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Alterar plano de fundo"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Ouvinte de notificações"</string>
+    <string name="vr_listener_binding_label" msgid="4316591939343607306">"Ouvinte de RV"</string>
     <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Provedor de condições"</string>
-    <string name="notification_assistant_binding_label" msgid="909456055569102952">"Assistente de notificação"</string>
+    <string name="notification_ranker_binding_label" msgid="774540592299064747">"Serviço de classificação de notificação"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN ativada"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"A VPN está ativada por <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Toque para gerenciar a rede."</string>
@@ -1467,7 +1466,7 @@
     <string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Pedir PIN antes de liberar"</string>
     <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Pedir padrão de desbloqueio antes de liberar"</string>
     <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Pedir senha antes de liberar"</string>
-    <string name="dock_cropped_windows_text" msgid="6378424064779004428">"O app não é redimensionável. Desloque-o com dois dedos."</string>
+    <string name="dock_forced_resizable" msgid="5914261505436217520">"É possível que o app não funcione com o recurso de divisão de tela."</string>
     <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"O app não é compatível com a divisão de tela."</string>
     <string name="package_installed_device_owner" msgid="8420696545959087545">"Instalado pelo seu administrador"</string>
     <string name="package_updated_device_owner" msgid="8856631322440187071">"Atualizado pelo administrador"</string>
@@ -1541,7 +1540,7 @@
     <string name="importance_from_person" msgid="9160133597262938296">"Isso é importante por causa das pessoas envolvidas."</string>
     <string name="user_creation_account_exists" msgid="1942606193570143289">"Permitir que <xliff:g id="APP">%1$s</xliff:g> crie um novo usuário com <xliff:g id="ACCOUNT">%2$s</xliff:g>?"</string>
     <string name="user_creation_adding" msgid="4482658054622099197">"Permitir que <xliff:g id="APP">%1$s</xliff:g> crie um novo usuário com <xliff:g id="ACCOUNT">%2$s</xliff:g> (já existe um usuário com essa conta)?"</string>
-    <string name="language_selection_title" msgid="7181332986330337171">"Preferência de idioma"</string>
+    <string name="language_selection_title" msgid="2680677278159281088">"Adicionar um idioma"</string>
     <string name="country_selection_title" msgid="2954859441620215513">"Preferência de região"</string>
     <string name="search_language_hint" msgid="7042102592055108574">"Digitar nome do idioma"</string>
     <string name="language_picker_section_suggested" msgid="8414489646861640885">"Sugeridos"</string>
@@ -1564,6 +1563,7 @@
     <string name="pin_target" msgid="3052256031352291362">"Fixar guia"</string>
     <string name="unpin_target" msgid="3556545602439143442">"Liberar guia"</string>
     <string name="app_info" msgid="6856026610594615344">"Informações do app"</string>
-    <!-- no translation found for negative_duration (5688706061127375131) -->
-    <skip />
+    <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="audit_safemode_notification" msgid="6351827251856877200">"Redefinir para a configuração original para usar este dispositivo normalmente"</string>
+    <string name="audit_safemode_notification_details" msgid="1860601176690176413">"Toque para saber mais."</string>
 </resources>
diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml
index e85ee2d..1c6e024 100644
--- a/core/res/res/values-ro/strings.xml
+++ b/core/res/res/values-ro/strings.xml
@@ -231,7 +231,6 @@
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Asistent vocal"</string>
     <string name="global_action_lockdown" msgid="8751542514724332873">"Blocați acum"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"˃999"</string>
-    <string name="notification_children_count_bracketed" msgid="1769425473168347839">"(<xliff:g id="NOTIFICATIONCOUNT">%d</xliff:g>)"</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>
     <string name="safeMode" msgid="2788228061547930246">"Mod sigur"</string>
@@ -1060,13 +1059,12 @@
     <string name="usb_notification_message" msgid="7347368030849048437">"Atingeți pentru mai multe opțiuni."</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"Depanarea USB este conectată"</string>
     <string name="adb_active_notification_message" msgid="1016654627626476142">"Atingeți pentru a dezactiva depanarea USB."</string>
+    <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Se creează un raport de eroare…"</string>
     <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Trimiteți raportul de eroare?"</string>
     <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Se trimite raportul de eroare…"</string>
-    <string name="share_remote_bugreport_notification_message" msgid="752583906074230920">"Administratorul IT a solicitat un raport de eroare pentru a remedia problemele acestui dispozitiv. Este posibil să se permită accesul la date și aplicații, iar funcționarea dispozitivului poate fi încetinită temporar."</string>
-    <string name="share_finished_remote_bugreport_notification_message" msgid="4627312060769912353">"Administratorul IT a solicitat un raport de eroare pentru a remedia problemele acestui dispozitiv. Este posibil să se permită accesul la date și aplicații."</string>
-    <string name="sharing_remote_bugreport_notification_message" msgid="673106383408474893">"Acest proces poate încetini temporar funcționarea dispozitivului"</string>
-    <string name="share_remote_bugreport_notification_accept" msgid="8203856129078669677">"ACCEPTAȚI"</string>
-    <string name="share_remote_bugreport_notification_decline" msgid="6337969352057443969">"REFUZAȚI"</string>
+    <string name="share_remote_bugreport_notification_message_finished" msgid="8610614010660772643">"Administratorul IT a solicitat un raport de eroare pentru a remedia problemele acestui dispozitiv. Este posibil să se permită accesul la date și aplicații."</string>
+    <string name="share_remote_bugreport_action" msgid="6249476773913384948">"TRIMITEȚI"</string>
+    <string name="decline_remote_bugreport_action" msgid="6230987241608770062">"REFUZAȚI"</string>
     <string name="select_input_method" msgid="8547250819326693584">"Schimbați tastatura"</string>
     <string name="configure_input_methods" msgid="4769971288371946846">"Alegeți tastaturi"</string>
     <string name="show_ime" msgid="2506087537466597099">"Se păstrează pe ecran cât timp este activată tastatura fizică"</string>
@@ -1145,8 +1143,9 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Imagine de fundal"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Modificați imaginea de fundal"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Serviciu de citire a notificărilor"</string>
+    <string name="vr_listener_binding_label" msgid="4316591939343607306">"Instrument de ascultare pentru Realitatea virtuală"</string>
     <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Furnizor de condiții"</string>
-    <string name="notification_assistant_binding_label" msgid="909456055569102952">"Asistent pentru notificări"</string>
+    <string name="notification_ranker_binding_label" msgid="774540592299064747">"Serviciul de clasificare a notificărilor"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN activat"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN este activată de <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Atingeți pentru a gestiona rețeaua."</string>
@@ -1477,7 +1476,7 @@
     <string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Solicită codul PIN înainte de a anula fixarea"</string>
     <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Solicită modelul pentru deblocare înainte de a anula fixarea"</string>
     <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Solicită parola înainte de a anula fixarea"</string>
-    <string name="dock_cropped_windows_text" msgid="6378424064779004428">"Aplicația nu poate fi redimensionată. Derulați în ea cu două degete."</string>
+    <string name="dock_forced_resizable" msgid="5914261505436217520">"Este posibil ca aplicația să nu funcționeze cu ecranul împărțit."</string>
     <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"Aplicația nu acceptă ecranul împărțit."</string>
     <string name="package_installed_device_owner" msgid="8420696545959087545">"Instalat de administrator"</string>
     <string name="package_updated_device_owner" msgid="8856631322440187071">"Actualizat de un administrator"</string>
@@ -1560,7 +1559,7 @@
     <string name="importance_from_person" msgid="9160133597262938296">"Notificarea este importantă având în vedere persoanele implicate."</string>
     <string name="user_creation_account_exists" msgid="1942606193570143289">"Permiteți ca <xliff:g id="APP">%1$s</xliff:g> să creeze un nou utilizator folosind <xliff:g id="ACCOUNT">%2$s</xliff:g>?"</string>
     <string name="user_creation_adding" msgid="4482658054622099197">"Permiteți ca <xliff:g id="APP">%1$s</xliff:g> să creeze un nou utilizator folosind <xliff:g id="ACCOUNT">%2$s</xliff:g>? (există deja un utilizator cu acest cont)"</string>
-    <string name="language_selection_title" msgid="7181332986330337171">"Limba preferată"</string>
+    <string name="language_selection_title" msgid="2680677278159281088">"Adăugați o limbă"</string>
     <string name="country_selection_title" msgid="2954859441620215513">"Regiunea preferată"</string>
     <string name="search_language_hint" msgid="7042102592055108574">"Numele limbii"</string>
     <string name="language_picker_section_suggested" msgid="8414489646861640885">"Sugerate"</string>
@@ -1583,6 +1582,7 @@
     <string name="pin_target" msgid="3052256031352291362">"Fixați"</string>
     <string name="unpin_target" msgid="3556545602439143442">"Anulați fixarea"</string>
     <string name="app_info" msgid="6856026610594615344">"Informații despre aplicație"</string>
-    <!-- no translation found for negative_duration (5688706061127375131) -->
-    <skip />
+    <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="audit_safemode_notification" msgid="6351827251856877200">"Reveniți la setările din fabrică pentru a folosi acest dispozitiv ca de obicei"</string>
+    <string name="audit_safemode_notification_details" msgid="1860601176690176413">"Atingeți pentru a afla mai multe."</string>
 </resources>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index b7d264c..f134357 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -233,7 +233,6 @@
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Аудиоподсказки"</string>
     <string name="global_action_lockdown" msgid="8751542514724332873">"Заблокировать"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"&gt;999"</string>
-    <string name="notification_children_count_bracketed" msgid="1769425473168347839">"(<xliff:g id="NOTIFICATIONCOUNT">%d</xliff:g>)"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"Содержимое скрыто"</string>
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Содержимое скрыто в соответствии с заданными правилами"</string>
     <string name="safeMode" msgid="2788228061547930246">"Безопасный режим"</string>
@@ -1068,13 +1067,12 @@
     <string name="usb_notification_message" msgid="7347368030849048437">"Нажмите, чтобы настроить."</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"Отладка по USB разрешена"</string>
     <string name="adb_active_notification_message" msgid="1016654627626476142">"Нажмите, чтобы отключить отладку по USB."</string>
+    <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Подготовка отчета об ошибке"</string>
     <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Разрешить доступ к информации об ошибке?"</string>
     <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Отправка отчета об ошибке"</string>
-    <string name="share_remote_bugreport_notification_message" msgid="752583906074230920">"Администратор запросил отчет об ошибке, чтобы устранить неполадку. Он может получить доступ к приложениям и данным. Возможно временное снижение скорости работы вашего устройства."</string>
-    <string name="share_finished_remote_bugreport_notification_message" msgid="4627312060769912353">"Администратор запросил отчет об ошибке, чтобы устранить неполадку. Он может получить доступ к приложениям и данным."</string>
-    <string name="sharing_remote_bugreport_notification_message" msgid="673106383408474893">"Скорость работы устройства может быть временно снижена."</string>
-    <string name="share_remote_bugreport_notification_accept" msgid="8203856129078669677">"ПРИНЯТЬ"</string>
-    <string name="share_remote_bugreport_notification_decline" msgid="6337969352057443969">"ОТКЛОНИТЬ"</string>
+    <string name="share_remote_bugreport_notification_message_finished" msgid="8610614010660772643">"Администратор запросил отчет об ошибке, чтобы устранить неполадку. Он может получить доступ к приложениям и данным."</string>
+    <string name="share_remote_bugreport_action" msgid="6249476773913384948">"ПРЕДОСТАВИТЬ ДОСТУП"</string>
+    <string name="decline_remote_bugreport_action" msgid="6230987241608770062">"ОТКЛОНИТЬ"</string>
     <string name="select_input_method" msgid="8547250819326693584">"Выбор раскладки"</string>
     <string name="configure_input_methods" msgid="4769971288371946846">"Выбрать раскладку"</string>
     <string name="show_ime" msgid="2506087537466597099">"Показывать на экране, когда физическая клавиатура включена"</string>
@@ -1153,8 +1151,9 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Фоновый рисунок"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Сменить обои"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Служба просмотра уведомлений"</string>
+    <string name="vr_listener_binding_label" msgid="4316591939343607306">"VR-режим"</string>
     <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Поставщик условий"</string>
-    <string name="notification_assistant_binding_label" msgid="909456055569102952">"Ассистент уведомлений"</string>
+    <string name="notification_ranker_binding_label" msgid="774540592299064747">"Сервис для оценки важности уведомлений"</string>
     <string name="vpn_title" msgid="19615213552042827">"Сеть VPN активна"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"Сеть VPN активирована приложением <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Нажмите, чтобы открыть настройки."</string>
@@ -1487,7 +1486,7 @@
     <string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"PIN-код для отключения"</string>
     <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Запрашивать графический ключ для отключения блокировки"</string>
     <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Запрашивать пароль для отключения блокировки"</string>
-    <string name="dock_cropped_windows_text" msgid="6378424064779004428">"Размер окна нельзя изменить. Прокрутите страницу двумя пальцами."</string>
+    <string name="dock_forced_resizable" msgid="5914261505436217520">"Приложение не поддерживает разделение экрана."</string>
     <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"Приложение не поддерживает разделение экрана."</string>
     <string name="package_installed_device_owner" msgid="8420696545959087545">"Установлено администратором"</string>
     <string name="package_updated_device_owner" msgid="8856631322440187071">"Обновлено администратором"</string>
@@ -1579,7 +1578,7 @@
     <string name="importance_from_person" msgid="9160133597262938296">"Важное (люди)"</string>
     <string name="user_creation_account_exists" msgid="1942606193570143289">"Разрешить приложению \"<xliff:g id="APP">%1$s</xliff:g>\" создать пользователя для аккаунта <xliff:g id="ACCOUNT">%2$s</xliff:g>?"</string>
     <string name="user_creation_adding" msgid="4482658054622099197">"Разрешить приложению \"<xliff:g id="APP">%1$s</xliff:g>\" создать нового пользователя для аккаунта <xliff:g id="ACCOUNT">%2$s</xliff:g> (пользователь c таким аккаунтом уже есть)?"</string>
-    <string name="language_selection_title" msgid="7181332986330337171">"Языковые настройки"</string>
+    <string name="language_selection_title" msgid="2680677278159281088">"Добавьте язык"</string>
     <string name="country_selection_title" msgid="2954859441620215513">"Региональные настройки"</string>
     <string name="search_language_hint" msgid="7042102592055108574">"Введите язык"</string>
     <string name="language_picker_section_suggested" msgid="8414489646861640885">"Рекомендуемые"</string>
@@ -1602,6 +1601,7 @@
     <string name="pin_target" msgid="3052256031352291362">"Закрепить"</string>
     <string name="unpin_target" msgid="3556545602439143442">"Открепить"</string>
     <string name="app_info" msgid="6856026610594615344">"О приложении"</string>
-    <!-- no translation found for negative_duration (5688706061127375131) -->
-    <skip />
+    <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="audit_safemode_notification" msgid="6351827251856877200">"Сброс до заводских настроек в целях безопасности"</string>
+    <string name="audit_safemode_notification_details" msgid="1860601176690176413">"Нажмите, чтобы узнать больше."</string>
 </resources>
diff --git a/core/res/res/values-si-rLK/strings.xml b/core/res/res/values-si-rLK/strings.xml
index 7daba81..9a6d3af 100644
--- a/core/res/res/values-si-rLK/strings.xml
+++ b/core/res/res/values-si-rLK/strings.xml
@@ -229,7 +229,6 @@
     <string name="global_action_voice_assist" msgid="7751191495200504480">"හඬ සහායක"</string>
     <string name="global_action_lockdown" msgid="8751542514724332873">"දැන් අගුළු දමන්න"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
-    <string name="notification_children_count_bracketed" msgid="1769425473168347839">"(<xliff:g id="NOTIFICATIONCOUNT">%d</xliff:g>)"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"සැඟවුණු සම්බන්ධතා"</string>
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"ප්‍රතිපත්තිය විසින් අන්තර්ගතය සඟවන ලදී"</string>
     <string name="safeMode" msgid="2788228061547930246">"ආරක්‍ෂිත ආකාරය"</string>
@@ -1054,13 +1053,12 @@
     <string name="usb_notification_message" msgid="7347368030849048437">"වඩා වැඩි විකල්ප සඳහා ස්පර්ශ කරන්න."</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"USB නිදොස්කරණය සම්බන්ධිතයි"</string>
     <string name="adb_active_notification_message" msgid="1016654627626476142">"USB නිදොස්කරණය අබල කිරීමට ස්පර්ශ කරන්න."</string>
+    <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"දෝෂ වාර්තාවක් ගනිමින්…"</string>
     <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"දෝෂ වාර්තාව බෙදා ගන්නද?"</string>
     <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"දෝෂ වාර්තාවක් බෙදා ගනිමින්..."</string>
-    <string name="share_remote_bugreport_notification_message" msgid="752583906074230920">"මෙම උපාංගය දෝෂාවේක්ෂණය සඳහා උදවු කිරීමට ඔබේ IT පරිපාලක දෝෂ වාර්තාවක් ඉල්ලා ඇත. යෙදුම් සහ දත්ත බෙදා ගත හැකි අතර ඔබේ උපාංගය තාවකාලිකව මන්දගාමී විය හැකිය."</string>
-    <string name="share_finished_remote_bugreport_notification_message" msgid="4627312060769912353">"මෙම උපාංගය දෝෂාවේක්ෂණය සඳහා උදවු කිරීමට ඔබේ IT පරිපාලක දෝෂ වාර්තාවක් ඉල්ලා ඇත. යෙදුම් සහ දත්ත බෙදා ගත හැකිය."</string>
-    <string name="sharing_remote_bugreport_notification_message" msgid="673106383408474893">"මෙය ඔබේ උපාංගය තාවකාලිකව මන්දගාමී කළ හැකිය"</string>
-    <string name="share_remote_bugreport_notification_accept" msgid="8203856129078669677">"පිළිගන්න"</string>
-    <string name="share_remote_bugreport_notification_decline" msgid="6337969352057443969">"ප්‍රතික්ෂේප කරන්න"</string>
+    <string name="share_remote_bugreport_notification_message_finished" msgid="8610614010660772643">"මෙම උපාංගය දෝෂාවේක්ෂණය සඳහා උදවු කිරීමට ඔබේ IT පරිපාලක දෝෂ වාර්තාවක් ඉල්ලා ඇත. යෙදුම් සහ දත්ත බෙදා ගත හැකිය."</string>
+    <string name="share_remote_bugreport_action" msgid="6249476773913384948">"බෙදා ගන්න"</string>
+    <string name="decline_remote_bugreport_action" msgid="6230987241608770062">"ප්‍රතික්ෂේප කරන්න"</string>
     <string name="select_input_method" msgid="8547250819326693584">"යතුරු පුවරු වෙනස් කිරීම"</string>
     <string name="configure_input_methods" msgid="4769971288371946846">"යතුරු පුවරු තෝරන්න"</string>
     <string name="show_ime" msgid="2506087537466597099">"භෞතික යතුරු පුවරුව සක්‍රිය අතරතුර එය තිරය මත තබා ගන්න"</string>
@@ -1139,8 +1137,9 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"බිතුපත"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"බිතුපත වෙනස් කරන්න"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"දැනුම්දීම් අසන්නා"</string>
+    <string name="vr_listener_binding_label" msgid="4316591939343607306">"VR සවන් දෙන්නා"</string>
     <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"තත්ත්වය සපයන්නා"</string>
-    <string name="notification_assistant_binding_label" msgid="909456055569102952">"දැනුම්දීම් සහායක"</string>
+    <string name="notification_ranker_binding_label" msgid="774540592299064747">"දැනුම්දීම් ශ්‍රේණිගත කිරීමේ සේවාව"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN ක්‍රියාත්මකයි"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"<xliff:g id="APP">%s</xliff:g> මඟින් VPN සක්‍රීය කරන ලදි"</string>
     <string name="vpn_text" msgid="3011306607126450322">"ජාලය කළමනාකරණය කිරීමට ස්පර්ශ කරන්න."</string>
@@ -1469,7 +1468,7 @@
     <string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"ගැලවීමට පෙර PIN විමසන්න"</string>
     <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"ගැලවීමට පෙර අගුළු අරින රටාව සඳහා අසන්න"</string>
     <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"ගැලවීමට පෙර මුරපදය විමසන්න"</string>
-    <string name="dock_cropped_windows_text" msgid="6378424064779004428">"යෙදුම ප්‍රතිප්‍රමාණ කළ හැකි නොවේ, එය ඇඟිලි දෙකකින් අනුචලනය කරන්න."</string>
+    <string name="dock_forced_resizable" msgid="5914261505436217520">"යෙදුම බෙදුම්-තිරය සමග ක්‍රියා නොකළ හැකිය."</string>
     <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"යෙදුම බෙදුණු-තිරය සඳහා සහාය නොදක්වයි."</string>
     <string name="package_installed_device_owner" msgid="8420696545959087545">"ඔබගේ පරිපාලක විසින් ස්ථාපනය කරන ලද"</string>
     <string name="package_updated_device_owner" msgid="8856631322440187071">"ඔබගේ පරිපාලක විසින් යාවත්කාලීන කරන ලදී"</string>
@@ -1543,7 +1542,7 @@
     <string name="importance_from_person" msgid="9160133597262938296">"සම්බන්ධ වූ පුද්ගලයන් නිසා මෙය වැදගත් වේ."</string>
     <string name="user_creation_account_exists" msgid="1942606193570143289">"<xliff:g id="APP">%1$s</xliff:g> හට <xliff:g id="ACCOUNT">%2$s</xliff:g> සමගින් නව පරිශීලකයෙකු සෑදීමට ඉඩ දෙන්නද?"</string>
     <string name="user_creation_adding" msgid="4482658054622099197">"<xliff:g id="APP">%1$s</xliff:g> හට <xliff:g id="ACCOUNT">%2$s</xliff:g> සමගින් නව පරිශීලකයෙකු සෑදීමට ඉඩ දෙන්නද (මෙම ගිණුම සහිත පරිශීලකයෙකු දැනටමත් සිටී) ?"</string>
-    <string name="language_selection_title" msgid="7181332986330337171">"භාෂා මනාප"</string>
+    <string name="language_selection_title" msgid="2680677278159281088">"භාෂාවක් එක් කරන්න"</string>
     <string name="country_selection_title" msgid="2954859441620215513">"ප්‍රදේශ මනාපය"</string>
     <string name="search_language_hint" msgid="7042102592055108574">"භාෂා නම ටයිප් කරන්න"</string>
     <string name="language_picker_section_suggested" msgid="8414489646861640885">"යෝජිත"</string>
@@ -1566,6 +1565,7 @@
     <string name="pin_target" msgid="3052256031352291362">"අමුණන්න"</string>
     <string name="unpin_target" msgid="3556545602439143442">"ගලවන්න"</string>
     <string name="app_info" msgid="6856026610594615344">"යෙදුම් තොරතුරු"</string>
-    <!-- no translation found for negative_duration (5688706061127375131) -->
-    <skip />
+    <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="audit_safemode_notification" msgid="6351827251856877200">"මෙම උපාංගය සාමාන්‍ය ලෙස භාවිත කිරීමට කර්මාන්තශාලා යළි සැකසීම"</string>
+    <string name="audit_safemode_notification_details" msgid="1860601176690176413">"තව දැන ගැනීමට ස්පර්ශ කරන්න."</string>
 </resources>
diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml
index d3c1da2..f4794a6 100644
--- a/core/res/res/values-sk/strings.xml
+++ b/core/res/res/values-sk/strings.xml
@@ -233,7 +233,6 @@
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Hlasový asistent"</string>
     <string name="global_action_lockdown" msgid="8751542514724332873">"Uzamknúť"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
-    <string name="notification_children_count_bracketed" msgid="1769425473168347839">"(<xliff:g id="NOTIFICATIONCOUNT">%d</xliff:g>)"</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>
     <string name="safeMode" msgid="2788228061547930246">"Núdzový režim"</string>
@@ -1068,13 +1067,12 @@
     <string name="usb_notification_message" msgid="7347368030849048437">"Ďalšie možnosti zobrazíte klepnutím."</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"Ladenie cez USB pripojené"</string>
     <string name="adb_active_notification_message" msgid="1016654627626476142">"Klepnutím zakážete ladenie cez USB"</string>
+    <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Preberá sa hlásenie chyby…"</string>
     <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Chcete zdieľať hlásenie chyby?"</string>
     <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Zdieľa sa hlásenie chyby…"</string>
-    <string name="share_remote_bugreport_notification_message" msgid="752583906074230920">"Správca IT si vyžiadal hlásenie chyby, aby mohol vyriešiť problém na tomto zariadení. Aplikácie a dáta môžu byť zdieľané. Môže to dočasne spomaliť vaše zariadenie."</string>
-    <string name="share_finished_remote_bugreport_notification_message" msgid="4627312060769912353">"Správca IT si vyžiadal hlásenie chyby, aby mohol vyriešiť problém na tomto zariadení. Aplikácie a dáta môžu byť zdieľané."</string>
-    <string name="sharing_remote_bugreport_notification_message" msgid="673106383408474893">"Môže to dočasne spomaliť vaše zariadenie."</string>
-    <string name="share_remote_bugreport_notification_accept" msgid="8203856129078669677">"PRIJAŤ"</string>
-    <string name="share_remote_bugreport_notification_decline" msgid="6337969352057443969">"ODMIETNUŤ"</string>
+    <string name="share_remote_bugreport_notification_message_finished" msgid="8610614010660772643">"Správca IT si vyžiadal hlásenie chyby, aby mohol vyriešiť problém na tomto zariadení. Aplikácie a dáta môžu byť zdieľané."</string>
+    <string name="share_remote_bugreport_action" msgid="6249476773913384948">"ZDIEĽAŤ"</string>
+    <string name="decline_remote_bugreport_action" msgid="6230987241608770062">"ODMIETNUŤ"</string>
     <string name="select_input_method" msgid="8547250819326693584">"Zmeniť klávesnicu"</string>
     <string name="configure_input_methods" msgid="4769971288371946846">"Vybrať klávesnicu"</string>
     <string name="show_ime" msgid="2506087537466597099">"Ponechať na obrazovke, keď je aktívna fyzická klávesnica"</string>
@@ -1153,8 +1151,9 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Tapeta"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Zmeniť tapetu"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Aplikácia na počúvanie upozornení"</string>
+    <string name="vr_listener_binding_label" msgid="4316591939343607306">"Prijímač VR"</string>
     <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Poskytovateľ podmienky"</string>
-    <string name="notification_assistant_binding_label" msgid="909456055569102952">"Asistent upozornení"</string>
+    <string name="notification_ranker_binding_label" msgid="774540592299064747">"Služba na hodnotenie upozornení"</string>
     <string name="vpn_title" msgid="19615213552042827">"Sieť VPN je aktivovaná"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"Aplikáciu <xliff:g id="APP">%s</xliff:g> aktivovala sieť VPN"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Dotykom môžete spravovať sieť."</string>
@@ -1487,7 +1486,7 @@
     <string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Pred uvoľnením požiadať o číslo PIN"</string>
     <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Pred uvoľnením požiadať o bezpečnostný vzor"</string>
     <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Pred uvoľnením požiadať o heslo"</string>
-    <string name="dock_cropped_windows_text" msgid="6378424064779004428">"Veľkosť aplikácie nie je možné zmeniť. Zobrazenie môžete posúvať dvoma prstami."</string>
+    <string name="dock_forced_resizable" msgid="5914261505436217520">"Aplikácia nemusí fungovať so zapnutou rozdelenou obrazovkou."</string>
     <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"Aplikácia nepodporuje rozdelenú obrazovku."</string>
     <string name="package_installed_device_owner" msgid="8420696545959087545">"Inštalovaný správcom"</string>
     <string name="package_updated_device_owner" msgid="8856631322440187071">"Aktualizované správcom"</string>
@@ -1579,7 +1578,7 @@
     <string name="importance_from_person" msgid="9160133597262938296">"Táto správa je dôležitá vzhľadom na osoby, ktorých sa to týka."</string>
     <string name="user_creation_account_exists" msgid="1942606193570143289">"Povoliť aplikácii <xliff:g id="APP">%1$s</xliff:g> vytvoriť nového používateľa pomocou účtu <xliff:g id="ACCOUNT">%2$s</xliff:g>?"</string>
     <string name="user_creation_adding" msgid="4482658054622099197">"Povoliť aplikácii <xliff:g id="APP">%1$s</xliff:g> vytvoriť nového používateľa pomocou účtu <xliff:g id="ACCOUNT">%2$s</xliff:g> (používateľ s týmto účtom už existuje)?"</string>
-    <string name="language_selection_title" msgid="7181332986330337171">"Jazykové predvoľby"</string>
+    <string name="language_selection_title" msgid="2680677278159281088">"Pridať jazyk"</string>
     <string name="country_selection_title" msgid="2954859441620215513">"Preferovaný región"</string>
     <string name="search_language_hint" msgid="7042102592055108574">"Zadajte názov jazyka"</string>
     <string name="language_picker_section_suggested" msgid="8414489646861640885">"Navrhované"</string>
@@ -1602,6 +1601,7 @@
     <string name="pin_target" msgid="3052256031352291362">"Pripnúť"</string>
     <string name="unpin_target" msgid="3556545602439143442">"Uvoľniť"</string>
     <string name="app_info" msgid="6856026610594615344">"Info o aplikácii"</string>
-    <!-- no translation found for negative_duration (5688706061127375131) -->
-    <skip />
+    <string name="negative_duration" msgid="5688706061127375131">"-<xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="audit_safemode_notification" msgid="6351827251856877200">"Ak chcete toto zariadenie používať normálnym spôsobom, obnovte na ňom továrenské nastavenia"</string>
+    <string name="audit_safemode_notification_details" msgid="1860601176690176413">"Klepnutím získate ďalšie informácie."</string>
 </resources>
diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml
index bf0c961..3e0cfaf 100644
--- a/core/res/res/values-sl/strings.xml
+++ b/core/res/res/values-sl/strings.xml
@@ -233,7 +233,6 @@
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Glas. pomočnik"</string>
     <string name="global_action_lockdown" msgid="8751542514724332873">"Zakleni zdaj"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999 +"</string>
-    <string name="notification_children_count_bracketed" msgid="1769425473168347839">"(<xliff:g id="NOTIFICATIONCOUNT">%d</xliff:g>)"</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>
     <string name="safeMode" msgid="2788228061547930246">"Varni način"</string>
@@ -1068,13 +1067,12 @@
     <string name="usb_notification_message" msgid="7347368030849048437">"Za več možnosti se dotaknite."</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"Iskanje in odpravljanje napak USB je povezano"</string>
     <string name="adb_active_notification_message" msgid="1016654627626476142">"Dotaknite se, če želite onemogočiti iskanje in odpravljanje napak prek vrat USB."</string>
+    <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Zajemanje poročila o napakah …"</string>
     <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Želite poslati poročilo o napakah?"</string>
     <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Pošiljanje poročila o napakah …"</string>
-    <string name="share_remote_bugreport_notification_message" msgid="752583906074230920">"Skrbnik za IT je zahteval poročilo o napakah za pomoč pri odpravljanju napak v tej napravi. Aplikacije in podatki bodo morda dani v skupno rabo in delovanje naprave bo morda začasno upočasnjeno."</string>
-    <string name="share_finished_remote_bugreport_notification_message" msgid="4627312060769912353">"Skrbnik za IT je zahteval poročilo o napakah za pomoč pri odpravljanju napak v tej napravi. Aplikacije in podatki bodo morda dani v skupno rabo."</string>
-    <string name="sharing_remote_bugreport_notification_message" msgid="673106383408474893">"To bo morda začasno upočasnilo delovanje naprave"</string>
-    <string name="share_remote_bugreport_notification_accept" msgid="8203856129078669677">"SPREJMEM"</string>
-    <string name="share_remote_bugreport_notification_decline" msgid="6337969352057443969">"NE SPREJMEM"</string>
+    <string name="share_remote_bugreport_notification_message_finished" msgid="8610614010660772643">"Skrbnik za IT je zahteval poročilo o napakah za pomoč pri odpravljanju napak v tej napravi. Aplikacije in podatki bodo morda dani v skupno rabo."</string>
+    <string name="share_remote_bugreport_action" msgid="6249476773913384948">"SKUPNA RABA"</string>
+    <string name="decline_remote_bugreport_action" msgid="6230987241608770062">"NE SPREJMEM"</string>
     <string name="select_input_method" msgid="8547250819326693584">"Sprememba tipkovnice"</string>
     <string name="configure_input_methods" msgid="4769971288371946846">"Izbira tipkovnic"</string>
     <string name="show_ime" msgid="2506087537466597099">"Ohrani na zaslonu, dokler je aktivna fizična tipkovnica"</string>
@@ -1153,8 +1151,9 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Ozadje"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Spreminjanje ozadja"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Poslušalec obvestil"</string>
+    <string name="vr_listener_binding_label" msgid="4316591939343607306">"Poslušalec za navidezno resničnost"</string>
     <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Ponudnik pogojev"</string>
-    <string name="notification_assistant_binding_label" msgid="909456055569102952">"Pomočnik za obvestila"</string>
+    <string name="notification_ranker_binding_label" msgid="774540592299064747">"Storitev za določanje stopenj pomembnosti obvestil"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN aktiviran"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN je aktivirala aplikacija <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Dotaknite se, če želite upravljati omrežje."</string>
@@ -1487,7 +1486,7 @@
     <string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Zahtevaj PIN pred odpenjanjem"</string>
     <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Pred odpenjanjem vprašaj za vzorec za odklepanje"</string>
     <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Pred odpenjanjem vprašaj za geslo"</string>
-    <string name="dock_cropped_windows_text" msgid="6378424064779004428">"Velikosti aplikacije ni mogoče spremeniti. Po njej se pomikajte z dvema prstoma."</string>
+    <string name="dock_forced_resizable" msgid="5914261505436217520">"Aplikacija morda ne deluje v načinu razdeljenega zaslona."</string>
     <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"Aplikacija ne podpira načina razdeljenega zaslona."</string>
     <string name="package_installed_device_owner" msgid="8420696545959087545">"Namestil skrbnik"</string>
     <string name="package_updated_device_owner" msgid="8856631322440187071">"Posodobil skrbnik"</string>
@@ -1579,7 +1578,7 @@
     <string name="importance_from_person" msgid="9160133597262938296">"Pomembno zaradi udeleženih ljudi."</string>
     <string name="user_creation_account_exists" msgid="1942606193570143289">"Dovolite, da aplikacija <xliff:g id="APP">%1$s</xliff:g> ustvari novega uporabnika za račun <xliff:g id="ACCOUNT">%2$s</xliff:g>?"</string>
     <string name="user_creation_adding" msgid="4482658054622099197">"Dovolite aplikaciji <xliff:g id="APP">%1$s</xliff:g>, da ustvari novega uporabnika za račun <xliff:g id="ACCOUNT">%2$s</xliff:g> (uporabnik s tem računom že obstaja)?"</string>
-    <string name="language_selection_title" msgid="7181332986330337171">"Nastavitev jezika"</string>
+    <string name="language_selection_title" msgid="2680677278159281088">"Dodajanje jezika"</string>
     <string name="country_selection_title" msgid="2954859441620215513">"Nastavitev območja"</string>
     <string name="search_language_hint" msgid="7042102592055108574">"Vnesite ime jezika"</string>
     <string name="language_picker_section_suggested" msgid="8414489646861640885">"Predlagano"</string>
@@ -1602,6 +1601,7 @@
     <string name="pin_target" msgid="3052256031352291362">"Pripenjanje"</string>
     <string name="unpin_target" msgid="3556545602439143442">"Odpenjanje"</string>
     <string name="app_info" msgid="6856026610594615344">"Podatki o aplikaciji"</string>
-    <!-- no translation found for negative_duration (5688706061127375131) -->
-    <skip />
+    <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="audit_safemode_notification" msgid="6351827251856877200">"Napravo ponastavite na tovarniške nastavitve, če jo želite uporabljati brez težav"</string>
+    <string name="audit_safemode_notification_details" msgid="1860601176690176413">"Dotaknite se, če želite izvedeti več."</string>
 </resources>
diff --git a/core/res/res/values-sq-rAL/strings.xml b/core/res/res/values-sq-rAL/strings.xml
index f200acd..bc8bd2b 100644
--- a/core/res/res/values-sq-rAL/strings.xml
+++ b/core/res/res/values-sq-rAL/strings.xml
@@ -229,7 +229,6 @@
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Ndihma zanore"</string>
     <string name="global_action_lockdown" msgid="8751542514724332873">"Kyç tani"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
-    <string name="notification_children_count_bracketed" msgid="1769425473168347839">"(<xliff:g id="NOTIFICATIONCOUNT">%d</xliff:g>)"</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>
     <string name="safeMode" msgid="2788228061547930246">"Modaliteti i sigurisë"</string>
@@ -1052,13 +1051,12 @@
     <string name="usb_notification_message" msgid="7347368030849048437">"Prek për më shumë opsione."</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"Korrigjuesi i USB-së i lidhur"</string>
     <string name="adb_active_notification_message" msgid="1016654627626476142">"Prek për të çaktivizuar korrigjimin e gabimeve të USB-së."</string>
+    <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Po merret raporti i defekteve në kod…"</string>
     <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Të ndahet raporti i defektit në kod?"</string>
     <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Po ndan raportin e defekteve në kod..."</string>
-    <string name="share_remote_bugreport_notification_message" msgid="752583906074230920">"Administratori i teknologjisë së informacionit kërkoi një raport të defekteve në kod për të ndihmuar me zgjidhjen e problemeve. Aplikacioni dhe të dhënat mund të ndahen dhe kjo mund të ngadalësojë përkohësisht pajisjen tënde."</string>
-    <string name="share_finished_remote_bugreport_notification_message" msgid="4627312060769912353">"Administratori i teknologjisë së informacionit kërkoi një raport të defekteve në kod për të ndihmuar me zgjidhjen e problemeve. Aplikacioni dhe të dhënat mund të ndahen."</string>
-    <string name="sharing_remote_bugreport_notification_message" msgid="673106383408474893">"Kjo mund të ngadalësojë përkohësisht pajisjen tënde"</string>
-    <string name="share_remote_bugreport_notification_accept" msgid="8203856129078669677">"PRANO"</string>
-    <string name="share_remote_bugreport_notification_decline" msgid="6337969352057443969">"REFUZO"</string>
+    <string name="share_remote_bugreport_notification_message_finished" msgid="8610614010660772643">"Administratori i teknologjisë së informacionit kërkoi një raport të defekteve në kod për të ndihmuar me zgjidhjen e problemeve. Aplikacioni dhe të dhënat mund të ndahen."</string>
+    <string name="share_remote_bugreport_action" msgid="6249476773913384948">"SHPËRNDA"</string>
+    <string name="decline_remote_bugreport_action" msgid="6230987241608770062">"REFUZO"</string>
     <string name="select_input_method" msgid="8547250819326693584">"Ndërro tastierë"</string>
     <string name="configure_input_methods" msgid="4769971288371946846">"Zgjidh tastierat"</string>
     <string name="show_ime" msgid="2506087537466597099">"Mbaje në ekran ndërsa tastiera fizike është aktive"</string>
@@ -1137,8 +1135,9 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Imazhi i sfondit"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Ndrysho imazhin e sfondit"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Dëgjues njoftimesh"</string>
+    <string name="vr_listener_binding_label" msgid="4316591939343607306">"Dëgjues VR"</string>
     <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Ofrues kushtesh"</string>
-    <string name="notification_assistant_binding_label" msgid="909456055569102952">"Asistenti i njoftimeve"</string>
+    <string name="notification_ranker_binding_label" msgid="774540592299064747">"Shërbimi i klasifikimit të njoftimeve"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN-ja u aktivizua"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN-ja është aktivizuar nga <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Prek për të menaxhuar rrjetin."</string>
@@ -1467,7 +1466,7 @@
     <string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Zhgozhdimi kërkon PIN-in"</string>
     <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Kërko model shkyçjeje para heqjes së gozhdimit"</string>
     <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Kërko fjalëkalim para heqjes nga gozhdimi."</string>
-    <string name="dock_cropped_windows_text" msgid="6378424064779004428">"Përmasa e apl. nuk mund të ndryshohet, lëvize atë me të dy gishtat."</string>
+    <string name="dock_forced_resizable" msgid="5914261505436217520">"Aplikacioni mund të mos funksionojë me ekranin e ndarë."</string>
     <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"Aplikacioni nuk mbështet ekranin e ndarë."</string>
     <string name="package_installed_device_owner" msgid="8420696545959087545">"U instalua nga administratori yt"</string>
     <string name="package_updated_device_owner" msgid="8856631322440187071">"Përditësuar nga administratori"</string>
@@ -1541,7 +1540,7 @@
     <string name="importance_from_person" msgid="9160133597262938296">"Është i rëndësishëm për shkak të personave të përfshirë."</string>
     <string name="user_creation_account_exists" msgid="1942606193570143289">"Dëshiron të lejosh <xliff:g id="APP">%1$s</xliff:g> që të krijojë një përdorues të ri me <xliff:g id="ACCOUNT">%2$s</xliff:g> ?"</string>
     <string name="user_creation_adding" msgid="4482658054622099197">"Dëshiron të lejosh <xliff:g id="APP">%1$s</xliff:g> që të krijojë një përdorues të ri me <xliff:g id="ACCOUNT">%2$s</xliff:g> (një përdorues me këtë llogari ekziston tashmë) ?"</string>
-    <string name="language_selection_title" msgid="7181332986330337171">"Preferenca për gjuhën"</string>
+    <string name="language_selection_title" msgid="2680677278159281088">"Shto një gjuhë"</string>
     <string name="country_selection_title" msgid="2954859441620215513">"Preferenca e rajonit"</string>
     <string name="search_language_hint" msgid="7042102592055108574">"Shkruaj emrin e gjuhës"</string>
     <string name="language_picker_section_suggested" msgid="8414489646861640885">"Sugjeruar"</string>
@@ -1564,6 +1563,7 @@
     <string name="pin_target" msgid="3052256031352291362">"Gozhdo"</string>
     <string name="unpin_target" msgid="3556545602439143442">"Zhgozhdo"</string>
     <string name="app_info" msgid="6856026610594615344">"Informacioni mbi aplikacionin"</string>
-    <!-- no translation found for negative_duration (5688706061127375131) -->
-    <skip />
+    <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="audit_safemode_notification" msgid="6351827251856877200">"Rivendos cilësimet e fabrikës për ta përdorur normalisht këtë pajisje"</string>
+    <string name="audit_safemode_notification_details" msgid="1860601176690176413">"Prek për të mësuar më shumë."</string>
 </resources>
diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml
index c870c05..d14c166 100644
--- a/core/res/res/values-sr/strings.xml
+++ b/core/res/res/values-sr/strings.xml
@@ -163,7 +163,7 @@
     <string name="contentServiceTooManyDeletesNotificationDesc" msgid="8100981435080696431">"Превише <xliff:g id="CONTENT_TYPE">%s</xliff:g> избрисаних ставки."</string>
     <string name="low_memory" product="tablet" msgid="6494019234102154896">"Меморија таблета је пуна! Избришите неке датотеке да бисте ослободили простор."</string>
     <string name="low_memory" product="watch" msgid="4415914910770005166">"Меморија сата је пуна. Избришите неке датотеке да бисте ослободили простор."</string>
-    <string name="low_memory" product="tv" msgid="516619861191025923">"Складишни простор на ТВ-у је попуњен. Избришите неке датотеке да бисте ослободили простор."</string>
+    <string name="low_memory" product="tv" msgid="516619861191025923">"Меморијски простор на ТВ-у је попуњен. Избришите неке датотеке да бисте ослободили простор."</string>
     <string name="low_memory" product="default" msgid="3475999286680000541">"Складиште телефона је пуно! Избришите неке датотеке како бисте ослободили простор."</string>
     <string name="ssl_ca_cert_warning" msgid="5848402127455021714">"Мрежа се можда надгледа"</string>
     <string name="ssl_ca_cert_noti_by_unknown" msgid="4475437862189850602">"Од стране непознате треће стране"</string>
@@ -231,7 +231,6 @@
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Гласовна помоћ"</string>
     <string name="global_action_lockdown" msgid="8751542514724332873">"Закључај одмах"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
-    <string name="notification_children_count_bracketed" msgid="1769425473168347839">"(<xliff:g id="NOTIFICATIONCOUNT">%d</xliff:g>)"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"Садржај је сакривен"</string>
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Садржај је сакривен смерницама"</string>
     <string name="safeMode" msgid="2788228061547930246">"Безбедни режим"</string>
@@ -312,7 +311,7 @@
     <string name="permdesc_persistentActivity" product="tablet" msgid="8525189272329086137">"Дозвољава апликацији да учини сопствене компоненте трајним у меморији. Ово може да ограничи меморију доступну другим апликацијама и успори таблет."</string>
     <string name="permdesc_persistentActivity" product="tv" msgid="5086862529499103587">"Дозвољава апликацији да неке своје делове трајно задржи у меморији. То може да ограничи меморију доступну другим апликацијама и успори ТВ."</string>
     <string name="permdesc_persistentActivity" product="default" msgid="4384760047508278272">"Дозвољава апликацији да учини сопствене компоненте трајним у меморији. Ово може да ограничи меморију доступну другим апликацијама и успори телефон."</string>
-    <string name="permlab_getPackageSize" msgid="7472921768357981986">"мерење простора за складиштење у апликацији"</string>
+    <string name="permlab_getPackageSize" msgid="7472921768357981986">"мерење меморијског простора у апликацији"</string>
     <string name="permdesc_getPackageSize" msgid="3921068154420738296">"Дозвољава апликацији да преузме величине кôда, података и кеша."</string>
     <string name="permlab_writeSettings" msgid="2226195290955224730">"измена подешавања система"</string>
     <string name="permdesc_writeSettings" msgid="7775723441558907181">"Дозвољава апликацији да мења податке о подешавању система. Злонамерне апликације могу да оштете конфигурацију система."</string>
@@ -885,9 +884,9 @@
     <string name="deleteText" msgid="6979668428458199034">"Избриши"</string>
     <string name="inputMethod" msgid="1653630062304567879">"Метод уноса"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"Радње у вези са текстом"</string>
-    <string name="low_internal_storage_view_title" msgid="5576272496365684834">"Простор за складиштење је на измаку"</string>
+    <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>
+    <string name="low_internal_storage_view_text_no_boot" msgid="6935190099204693424">"Нема довољно меморијског простора за систем. Уверите се да имате 250 MB слободног простора и поново покрените."</string>
     <string name="app_running_notification_title" msgid="8718335121060787914">"Апликација <xliff:g id="APP_NAME">%1$s</xliff:g> је покренута"</string>
     <string name="app_running_notification_text" msgid="4653586947747330058">"Додирните за више информација или заустављање апликације."</string>
     <string name="ok" msgid="5970060430562524910">"Потврди"</string>
@@ -1060,13 +1059,12 @@
     <string name="usb_notification_message" msgid="7347368030849048437">"Додирните за још опција."</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"Отклањање грешака са USB-а је успостављено"</string>
     <string name="adb_active_notification_message" msgid="1016654627626476142">"Додирните да бисте онемогућили отклањање грешака са USB-а."</string>
+    <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Извештај о грешци се генерише…"</string>
     <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Желите ли да поделите извештај о грешци?"</string>
     <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Дели се извештај о грешци…"</string>
-    <string name="share_remote_bugreport_notification_message" msgid="752583906074230920">"ИТ администратор је затражио извештај о грешци ради лакшег решавања проблема у вези са овим уређајем. Апликације и подаци могу да се деле, а уређај ће се привремено успорити."</string>
-    <string name="share_finished_remote_bugreport_notification_message" msgid="4627312060769912353">"ИТ администратор је затражио извештај о грешци ради лакшег решавања проблема у вези са овим уређајем. Апликације и подаци могу да се деле."</string>
-    <string name="sharing_remote_bugreport_notification_message" msgid="673106383408474893">"Ово ће привремено успорити уређај"</string>
-    <string name="share_remote_bugreport_notification_accept" msgid="8203856129078669677">"ПРИХВАТИ"</string>
-    <string name="share_remote_bugreport_notification_decline" msgid="6337969352057443969">"ОДБИЈ"</string>
+    <string name="share_remote_bugreport_notification_message_finished" msgid="8610614010660772643">"ИТ администратор је затражио извештај о грешци ради лакшег решавања проблема у вези са овим уређајем. Апликације и подаци могу да се деле."</string>
+    <string name="share_remote_bugreport_action" msgid="6249476773913384948">"ДЕЛИ"</string>
+    <string name="decline_remote_bugreport_action" msgid="6230987241608770062">"ОДБИЈ"</string>
     <string name="select_input_method" msgid="8547250819326693584">"Промените тастатуру"</string>
     <string name="configure_input_methods" msgid="4769971288371946846">"Изаберите тастатуре"</string>
     <string name="show_ime" msgid="2506087537466597099">"Задржи га на екрану док је физичка тастатура активна"</string>
@@ -1145,8 +1143,9 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Позадина"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Промена позадине"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Монитор обавештења"</string>
+    <string name="vr_listener_binding_label" msgid="4316591939343607306">"Обрађивач за виртуелну реалност"</string>
     <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Добављач услова"</string>
-    <string name="notification_assistant_binding_label" msgid="909456055569102952">"Помоћник за обавештења"</string>
+    <string name="notification_ranker_binding_label" msgid="774540592299064747">"Услуга рангирања обавештења"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN је активиран"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"Апликација <xliff:g id="APP">%s</xliff:g> је активирала VPN"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Додирните да бисте управљали мрежом."</string>
@@ -1477,7 +1476,7 @@
     <string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Тражи PIN пре откачињања"</string>
     <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Тражи шаблон за откључавање пре откачињања"</string>
     <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Тражи лозинку пре откачињања"</string>
-    <string name="dock_cropped_windows_text" msgid="6378424064779004428">"Величина апликације не може да се мења. Померајте је помоћу два прста."</string>
+    <string name="dock_forced_resizable" msgid="5914261505436217520">"Апликација можда неће функционисати са подељеним екраном."</string>
     <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"Апликација не подржава подељени екран."</string>
     <string name="package_installed_device_owner" msgid="8420696545959087545">"Инсталирао је ваш администратор"</string>
     <string name="package_updated_device_owner" msgid="8856631322440187071">"Ажурирао је администратор"</string>
@@ -1560,7 +1559,7 @@
     <string name="importance_from_person" msgid="9160133597262938296">"Ово је важно због људи који учествују."</string>
     <string name="user_creation_account_exists" msgid="1942606193570143289">"Желите ли да дозволите апликацији <xliff:g id="APP">%1$s</xliff:g> да направи новог корисника за <xliff:g id="ACCOUNT">%2$s</xliff:g>?"</string>
     <string name="user_creation_adding" msgid="4482658054622099197">"Желите ли да дозволите апликацији <xliff:g id="APP">%1$s</xliff:g> да направи новог корисника за <xliff:g id="ACCOUNT">%2$s</xliff:g> (корисник са овим налогом већ постоји)?"</string>
-    <string name="language_selection_title" msgid="7181332986330337171">"Подешавање језика"</string>
+    <string name="language_selection_title" msgid="2680677278159281088">"Додајте језик"</string>
     <string name="country_selection_title" msgid="2954859441620215513">"Подешавање региона"</string>
     <string name="search_language_hint" msgid="7042102592055108574">"Унесите назив језика"</string>
     <string name="language_picker_section_suggested" msgid="8414489646861640885">"Предложени"</string>
@@ -1583,6 +1582,7 @@
     <string name="pin_target" msgid="3052256031352291362">"Закачи"</string>
     <string name="unpin_target" msgid="3556545602439143442">"Откачи"</string>
     <string name="app_info" msgid="6856026610594615344">"Информације о апликацији"</string>
-    <!-- no translation found for negative_duration (5688706061127375131) -->
-    <skip />
+    <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="audit_safemode_notification" msgid="6351827251856877200">"Ресетујте уређај на фабричка подешавања да бисте га нормално користили"</string>
+    <string name="audit_safemode_notification_details" msgid="1860601176690176413">"Додирните да бисте сазнали више."</string>
 </resources>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index 2ef1ac8..3eb4ae3 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -229,7 +229,6 @@
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Voice Assist"</string>
     <string name="global_action_lockdown" msgid="8751542514724332873">"Lås nu"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
-    <string name="notification_children_count_bracketed" msgid="1769425473168347839">"(<xliff:g id="NOTIFICATIONCOUNT">%d</xliff:g>)"</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>
     <string name="safeMode" msgid="2788228061547930246">"Säkert läge"</string>
@@ -1052,13 +1051,12 @@
     <string name="usb_notification_message" msgid="7347368030849048437">"Visa fler alternativ genom att trycka."</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"USB-felsökning ansluten"</string>
     <string name="adb_active_notification_message" msgid="1016654627626476142">"Tryck om du vill inaktivera USB-felsökning."</string>
+    <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Felrapporten överförs …"</string>
     <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Vill du dela felrapporten?"</string>
     <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Felrapporten delas …"</string>
-    <string name="share_remote_bugreport_notification_message" msgid="752583906074230920">"IT-administratören har bett om en felrapport som hjälp vid felsökningen av den här enheten. Appar och data kan komma att delas. Detta kan tillfälligt göra enheten långsammare."</string>
-    <string name="share_finished_remote_bugreport_notification_message" msgid="4627312060769912353">"IT-administratören har bett om en felrapport som hjälp vid felsökningen av den här enheten. Appar och data kan komma att delas."</string>
-    <string name="sharing_remote_bugreport_notification_message" msgid="673106383408474893">"Detta kan tillfälligt göra enheten långsammare"</string>
-    <string name="share_remote_bugreport_notification_accept" msgid="8203856129078669677">"GODKÄNN"</string>
-    <string name="share_remote_bugreport_notification_decline" msgid="6337969352057443969">"AVVISA"</string>
+    <string name="share_remote_bugreport_notification_message_finished" msgid="8610614010660772643">"IT-administratören har bett om en felrapport som hjälp vid felsökningen av den här enheten. Appar och data kan komma att delas."</string>
+    <string name="share_remote_bugreport_action" msgid="6249476773913384948">"DELA"</string>
+    <string name="decline_remote_bugreport_action" msgid="6230987241608770062">"AVVISA"</string>
     <string name="select_input_method" msgid="8547250819326693584">"Byt tangentbord"</string>
     <string name="configure_input_methods" msgid="4769971288371946846">"Välj tangentbord"</string>
     <string name="show_ime" msgid="2506087537466597099">"Ha kvar den på skärmen när det fysiska tangentbordet används"</string>
@@ -1137,8 +1135,9 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Bakgrund"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Ändra bakgrund"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Meddelandelyssnare"</string>
+    <string name="vr_listener_binding_label" msgid="4316591939343607306">"Lyssnare för virtuell verklighet"</string>
     <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Leverantör"</string>
-    <string name="notification_assistant_binding_label" msgid="909456055569102952">"Aviseringsassistent"</string>
+    <string name="notification_ranker_binding_label" msgid="774540592299064747">"Rankningstjänst för aviseringar"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN är aktiverat"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN aktiveras av <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Tryck om du vill hantera nätverket."</string>
@@ -1467,7 +1466,7 @@
     <string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Be om pinkod innan skärmen slutar fästas"</string>
     <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Be om upplåsningsmönster innan skärmen slutar fästas"</string>
     <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Be om lösenord innan skärmen slutar fästas"</string>
-    <string name="dock_cropped_windows_text" msgid="6378424064779004428">"Det går inte att ändra appens storlek. Rulla med två fingrar."</string>
+    <string name="dock_forced_resizable" msgid="5914261505436217520">"Appen kanske inte fungerar med delad skärm."</string>
     <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"Appen har inte stöd för delad skärm."</string>
     <string name="package_installed_device_owner" msgid="8420696545959087545">"Paketet har installerats av administratören"</string>
     <string name="package_updated_device_owner" msgid="8856631322440187071">"Uppdaterat av administratören"</string>
@@ -1541,7 +1540,7 @@
     <string name="importance_from_person" msgid="9160133597262938296">"Detta är viktigt på grund av personerna som deltar."</string>
     <string name="user_creation_account_exists" msgid="1942606193570143289">"Tillåter du att <xliff:g id="APP">%1$s</xliff:g> skapar en ny användare för <xliff:g id="ACCOUNT">%2$s</xliff:g>?"</string>
     <string name="user_creation_adding" msgid="4482658054622099197">"Tillåter du att <xliff:g id="APP">%1$s</xliff:g> skapar en ny användare för <xliff:g id="ACCOUNT">%2$s</xliff:g> (det finns redan en användare med det här kontot)?"</string>
-    <string name="language_selection_title" msgid="7181332986330337171">"Språkinställning"</string>
+    <string name="language_selection_title" msgid="2680677278159281088">"Lägg till ett språk"</string>
     <string name="country_selection_title" msgid="2954859441620215513">"Regionsinställningar"</string>
     <string name="search_language_hint" msgid="7042102592055108574">"Ange språket"</string>
     <string name="language_picker_section_suggested" msgid="8414489646861640885">"Förslag"</string>
@@ -1564,6 +1563,7 @@
     <string name="pin_target" msgid="3052256031352291362">"Fäst"</string>
     <string name="unpin_target" msgid="3556545602439143442">"Lossa"</string>
     <string name="app_info" msgid="6856026610594615344">"Info om appen"</string>
-    <!-- no translation found for negative_duration (5688706061127375131) -->
-    <skip />
+    <string name="negative_duration" msgid="5688706061127375131">"-<xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="audit_safemode_notification" msgid="6351827251856877200">"Återställ standardinställningarna om du vill använda enheten normalt"</string>
+    <string name="audit_safemode_notification_details" msgid="1860601176690176413">"Tryck här om du vill läsa mer."</string>
 </resources>
diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml
index f3bd2d3..04994d5 100644
--- a/core/res/res/values-sw/strings.xml
+++ b/core/res/res/values-sw/strings.xml
@@ -231,7 +231,6 @@
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Usaidizi wa Sauti"</string>
     <string name="global_action_lockdown" msgid="8751542514724332873">"Funga sasa"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
-    <string name="notification_children_count_bracketed" msgid="1769425473168347839">"(<xliff:g id="NOTIFICATIONCOUNT">%d</xliff:g>)"</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>
     <string name="safeMode" msgid="2788228061547930246">"Mtindo salama"</string>
@@ -1054,13 +1053,12 @@
     <string name="usb_notification_message" msgid="7347368030849048437">"Gusa kwa chaguo zaidi."</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"Utatuaji wa USB umeunganishwa"</string>
     <string name="adb_active_notification_message" msgid="1016654627626476142">"Gusa ili uzime utatuaji wa USB."</string>
+    <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Inatayarisha ripoti ya hitilafu…"</string>
     <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Ungependa kushiriki ripoti ya hitilafu?"</string>
     <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Inashiriki ripoti ya hitilafu…"</string>
-    <string name="share_remote_bugreport_notification_message" msgid="752583906074230920">"Msimamizi wako wa Teknolojia ya Habari ameomba ripoti ya hitilafu ili kusaidia katika utatuzi wa kifaa hiki. Huenda hatua hii ikasababisha programu na data kushirikiwa na kupunguza kasi ya kifaa chako kwa muda."</string>
-    <string name="share_finished_remote_bugreport_notification_message" msgid="4627312060769912353">"Msimamizi wako wa TEHAMA ameomba ripoti ya hitilafu ili kusaidia katika utatuzi wa hitilafu kwenye kifaa hiki. Programu na data zinaweza kushirikiwa."</string>
-    <string name="sharing_remote_bugreport_notification_message" msgid="673106383408474893">"Hatua hii inaweza kupunguza kasi ya kifaa chako kwa muda"</string>
-    <string name="share_remote_bugreport_notification_accept" msgid="8203856129078669677">"KUBALI"</string>
-    <string name="share_remote_bugreport_notification_decline" msgid="6337969352057443969">"KATAA"</string>
+    <string name="share_remote_bugreport_notification_message_finished" msgid="8610614010660772643">"Msimamizi wako wa TEHAMA ameomba ripoti ya hitilafu ili kusaidia katika utatuzi wa hitilafu kwenye kifaa hiki. Programu na data zinaweza kushirikiwa."</string>
+    <string name="share_remote_bugreport_action" msgid="6249476773913384948">"SHIRIKI"</string>
+    <string name="decline_remote_bugreport_action" msgid="6230987241608770062">"KATAA"</string>
     <string name="select_input_method" msgid="8547250819326693584">"Badilisha kibodi"</string>
     <string name="configure_input_methods" msgid="4769971288371946846">"Chagua kibodi"</string>
     <string name="show_ime" msgid="2506087537466597099">"Iweke kwenye skrini wakati kibodi inapotumika"</string>
@@ -1139,8 +1137,9 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Mandhari"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Badilisha mandhari"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Kisikilizi cha arifa"</string>
+    <string name="vr_listener_binding_label" msgid="4316591939343607306">"Kisikilizaji cha Uhalisia Pepe"</string>
     <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Mtoa masharti"</string>
-    <string name="notification_assistant_binding_label" msgid="909456055569102952">"Mratibu wa arifa"</string>
+    <string name="notification_ranker_binding_label" msgid="774540592299064747">"Huduma ya kupanga arifa"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN imewezeshwa"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN imeamilishwa na <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Gusa ili kudhibiti mtandao."</string>
@@ -1469,7 +1468,7 @@
     <string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Omba PIN kabla hujabandua"</string>
     <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Omba mchoro wa kufungua kabla hujabandua"</string>
     <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Omba nenosiri kabla hujabandua"</string>
-    <string name="dock_cropped_windows_text" msgid="6378424064779004428">"Programu haiwezi kurekebishwa ukubwa, sogeza kwa kutumia vidole viwili."</string>
+    <string name="dock_forced_resizable" msgid="5914261505436217520">"Huenda programu isifanye kazi kwenye skrini inayogawanywa."</string>
     <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"Programu haiwezi kutumia skrini iliyogawanywa."</string>
     <string name="package_installed_device_owner" msgid="8420696545959087545">"Kilisakinishwa na msimamizi wako"</string>
     <string name="package_updated_device_owner" msgid="8856631322440187071">"Kimesasiswa na msimamizi wako"</string>
@@ -1543,7 +1542,7 @@
     <string name="importance_from_person" msgid="9160133597262938296">"Hii ni muhimu kwa sababu ya watu waliohusika."</string>
     <string name="user_creation_account_exists" msgid="1942606193570143289">"Ungependa kuruhusu <xliff:g id="APP">%1$s</xliff:g> iunde Mtumiaji mpya ikitumia <xliff:g id="ACCOUNT">%2$s</xliff:g>?"</string>
     <string name="user_creation_adding" msgid="4482658054622099197">"Ungependa kuruhusu <xliff:g id="APP">%1$s</xliff:g> iunde Mtumiaji mpya ikitumia <xliff:g id="ACCOUNT">%2$s</xliff:g> (Je, akaunti hii tayari ina Mtumiaji)?"</string>
-    <string name="language_selection_title" msgid="7181332986330337171">"Lugha ninayopendelea"</string>
+    <string name="language_selection_title" msgid="2680677278159281088">"Ongeza lugha"</string>
     <string name="country_selection_title" msgid="2954859441620215513">"Mapendeleo ya eneo"</string>
     <string name="search_language_hint" msgid="7042102592055108574">"Weka jina la lugha"</string>
     <string name="language_picker_section_suggested" msgid="8414489646861640885">"Inayopendekezwa"</string>
@@ -1566,6 +1565,7 @@
     <string name="pin_target" msgid="3052256031352291362">"Bandika"</string>
     <string name="unpin_target" msgid="3556545602439143442">"Bandua"</string>
     <string name="app_info" msgid="6856026610594615344">"Maelezo ya programu"</string>
-    <!-- no translation found for negative_duration (5688706061127375131) -->
-    <skip />
+    <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="audit_safemode_notification" msgid="6351827251856877200">"Rejesha mipangilio ya kiwandani katika kifaa hiki ili ukitumie kwa njia ya kawaida"</string>
+    <string name="audit_safemode_notification_details" msgid="1860601176690176413">"Gusa ili kupata maelezo zaidi."</string>
 </resources>
diff --git a/core/res/res/values-ta-rIN/strings.xml b/core/res/res/values-ta-rIN/strings.xml
index f4c2ef0..2cb08c9 100644
--- a/core/res/res/values-ta-rIN/strings.xml
+++ b/core/res/res/values-ta-rIN/strings.xml
@@ -229,7 +229,6 @@
     <string name="global_action_voice_assist" msgid="7751191495200504480">"குரல் உதவி"</string>
     <string name="global_action_lockdown" msgid="8751542514724332873">"இப்போது பூட்டு"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
-    <string name="notification_children_count_bracketed" msgid="1769425473168347839">"(<xliff:g id="NOTIFICATIONCOUNT">%d</xliff:g>)"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"மறைந்துள்ள உள்ளடக்கம்"</string>
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"கொள்கையின்படி உள்ளடக்கம் மறைக்கப்பட்டது"</string>
     <string name="safeMode" msgid="2788228061547930246">"பாதுகாப்பு பயன்முறை"</string>
@@ -1052,13 +1051,12 @@
     <string name="usb_notification_message" msgid="7347368030849048437">"கூடுதல் விருப்பங்களுக்காகத் தொடவும்."</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"USB பிழைதிருத்தம் இணைக்கப்பட்டது"</string>
     <string name="adb_active_notification_message" msgid="1016654627626476142">"USB பிழைத்திருத்தத்தை முடக்க, தொடவும்."</string>
+    <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"பிழை அறிக்கையை எடுக்கிறது…"</string>
     <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"பிழை அறிக்கையைப் பகிரவா?"</string>
     <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"பிழை அறிக்கையைப் பகிர்கிறது…"</string>
-    <string name="share_remote_bugreport_notification_message" msgid="752583906074230920">"இந்தச் சாதனத்தின் பிழைகாண்பதற்கு உதவ, உங்கள் ஐடி நிர்வாகி பிழை அறிக்கையைக் கோரியுள்ளார். பயன்பாடுகளும் தரவும் பகிரப்படலாம். தற்காலிகமாக சாதனத்தின் வேகம் குறையலாம்."</string>
-    <string name="share_finished_remote_bugreport_notification_message" msgid="4627312060769912353">"இந்தச் சாதனத்தின் பிழைகாண்பதற்கு உதவ, உங்கள் ஐடி நிர்வாகி பிழை அறிக்கையைக் கோரியுள்ளார். பயன்பாடுகளும் தரவும் பகிரப்படலாம்."</string>
-    <string name="sharing_remote_bugreport_notification_message" msgid="673106383408474893">"இது தற்காலிகமாக சாதனத்தின் வேகத்தைக் குறைக்கலாம்"</string>
-    <string name="share_remote_bugreport_notification_accept" msgid="8203856129078669677">"சரி"</string>
-    <string name="share_remote_bugreport_notification_decline" msgid="6337969352057443969">"வேண்டாம்"</string>
+    <string name="share_remote_bugreport_notification_message_finished" msgid="8610614010660772643">"இந்தச் சாதனத்தின் பிழைகாண்பதற்கு உதவ, உங்கள் ஐடி நிர்வாகி பிழை அறிக்கையைக் கோரியுள்ளார். பயன்பாடுகளும் தரவும் பகிரப்படலாம்."</string>
+    <string name="share_remote_bugreport_action" msgid="6249476773913384948">"பகிர்"</string>
+    <string name="decline_remote_bugreport_action" msgid="6230987241608770062">"வேண்டாம்"</string>
     <string name="select_input_method" msgid="8547250819326693584">"விசைப்பலகையை மாற்று"</string>
     <string name="configure_input_methods" msgid="4769971288371946846">"விசைப்பலகைகளைத் தேர்வுசெய்க"</string>
     <string name="show_ime" msgid="2506087537466597099">"கைமுறை விசைப்பலகை இயக்கத்தில் இருக்கும் போது IMEஐ திரையில் வைத்திரு"</string>
@@ -1137,8 +1135,9 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"வால்பேப்பர்"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"வால்பேப்பரை மாற்று"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"அறிவிப்புகளைக் கண்காணிக்கும் சேவை"</string>
+    <string name="vr_listener_binding_label" msgid="4316591939343607306">"VR லிஷனர்"</string>
     <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"நிபந்தனை வழங்குநர்"</string>
-    <string name="notification_assistant_binding_label" msgid="909456055569102952">"அறிவிப்பு உதவி"</string>
+    <string name="notification_ranker_binding_label" msgid="774540592299064747">"அறிவிப்பை மதிப்பீடு செய்யும் சேவை"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN செயல்படுத்தப்பட்டது"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"<xliff:g id="APP">%s</xliff:g> ஆல் VPN செயல்படுத்தப்பட்டது"</string>
     <string name="vpn_text" msgid="3011306607126450322">"நெட்வொர்க்கை நிர்வகிக்கத் தொடவும்."</string>
@@ -1467,7 +1466,7 @@
     <string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"அகற்றும் முன் PINஐக் கேள்"</string>
     <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"அகற்றும் முன் திறத்தல் வடிவத்தைக் கேள்"</string>
     <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"அகற்றும் முன் கடவுச்சொல்லைக் கேள்"</string>
-    <string name="dock_cropped_windows_text" msgid="6378424064779004428">"பயன்பாட்டின் அளவை மாற்ற முடியாது. இருவிரல்களைப் பயன்படுத்தி, அதை உருட்டவும்."</string>
+    <string name="dock_forced_resizable" msgid="5914261505436217520">"திரைப் பிரிப்பில் பயன்பாடு வேலைசெய்யாமல் போகக்கூடும்."</string>
     <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"திரையைப் பிரிப்பதைப் பயன்பாடு ஆதரிக்கவில்லை."</string>
     <string name="package_installed_device_owner" msgid="8420696545959087545">"நிர்வாகி நிறுவினார்"</string>
     <string name="package_updated_device_owner" msgid="8856631322440187071">"உங்கள் நிர்வாகி புதுப்பித்துள்ளார்"</string>
@@ -1541,7 +1540,7 @@
     <string name="importance_from_person" msgid="9160133597262938296">"ஈடுபட்டுள்ளவர்களின் காரணமாக, இது முக்கியமானது."</string>
     <string name="user_creation_account_exists" msgid="1942606193570143289">"<xliff:g id="ACCOUNT">%2$s</xliff:g> மூலம் புதிய பயனரை உருவாக்க <xliff:g id="APP">%1$s</xliff:g>ஐ அனுமதிக்கவா?"</string>
     <string name="user_creation_adding" msgid="4482658054622099197">"<xliff:g id="ACCOUNT">%2$s</xliff:g> (இந்தக் கணக்கில் ஏற்கனவே ஒரு பயனர் உள்ளார்) மூலம் புதிய பயனரை உருவாக்க <xliff:g id="APP">%1$s</xliff:g>ஐ அனுமதிக்கவா?"</string>
-    <string name="language_selection_title" msgid="7181332986330337171">"மொழி விருப்பம்"</string>
+    <string name="language_selection_title" msgid="2680677278159281088">"மொழியைச் சேர்"</string>
     <string name="country_selection_title" msgid="2954859441620215513">"மண்டல விருப்பம்"</string>
     <string name="search_language_hint" msgid="7042102592055108574">"மொழி பெயரை உள்ளிடுக"</string>
     <string name="language_picker_section_suggested" msgid="8414489646861640885">"பரிந்துரைகள்"</string>
@@ -1564,6 +1563,7 @@
     <string name="pin_target" msgid="3052256031352291362">"பின் செய்"</string>
     <string name="unpin_target" msgid="3556545602439143442">"பின்னை அகற்று"</string>
     <string name="app_info" msgid="6856026610594615344">"பயன்பாட்டுத் தகவல்"</string>
-    <!-- no translation found for negative_duration (5688706061127375131) -->
-    <skip />
+    <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="audit_safemode_notification" msgid="6351827251856877200">"சாதாரணமாக இந்தச் சாதனத்தைப் பயன்படுத்த, ஆரம்ப நிலைக்கு மீட்டமைக்கவும்"</string>
+    <string name="audit_safemode_notification_details" msgid="1860601176690176413">"மேலும் அறிய தொடவும்."</string>
 </resources>
diff --git a/core/res/res/values-te-rIN/strings.xml b/core/res/res/values-te-rIN/strings.xml
index cbd7776..4fd8aad 100644
--- a/core/res/res/values-te-rIN/strings.xml
+++ b/core/res/res/values-te-rIN/strings.xml
@@ -229,7 +229,6 @@
     <string name="global_action_voice_assist" msgid="7751191495200504480">"వాయిస్ సహాయకం"</string>
     <string name="global_action_lockdown" msgid="8751542514724332873">"ఇప్పుడు లాక్ చేయండి"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
-    <string name="notification_children_count_bracketed" msgid="1769425473168347839">"(<xliff:g id="NOTIFICATIONCOUNT">%d</xliff:g>)"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"కంటెంట్‌లు దాచబడ్డాయి"</string>
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"విధానం ద్వారా కంటెంట్‌లు దాచబడ్డాయి"</string>
     <string name="safeMode" msgid="2788228061547930246">"సురక్షిత మోడ్"</string>
@@ -1052,13 +1051,12 @@
     <string name="usb_notification_message" msgid="7347368030849048437">"మరిన్ని ఎంపికల కోసం తాకండి."</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"USB డీబగ్గింగ్ కనెక్ట్ చేయబడింది"</string>
     <string name="adb_active_notification_message" msgid="1016654627626476142">"USB డీబగ్గింగ్‌ను నిలిపివేయడానికి తాకండి."</string>
+    <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"బగ్ నివేదికను తీస్తోంది…"</string>
     <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"బగ్ నివేదికను భాగస్వామ్యం చేయాలా?"</string>
     <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"బగ్ నివేదికను భాగస్వామ్యం చేస్తోంది..."</string>
-    <string name="share_remote_bugreport_notification_message" msgid="752583906074230920">"మీ ఐటి నిర్వాహకులు ఈ పరికరం సమస్యకు పరిష్కారాన్ని కనుగొనడంలో సహాయం కోసం బగ్ నివేదికను అభ్యర్థించారు. అనువర్తనాలు మరియు డేటా భాగస్వామ్యం చేయబడవచ్చు మరియు మీ పరికరం పనితీరు తాత్కాలికంగా నెమ్మదించవచ్చు."</string>
-    <string name="share_finished_remote_bugreport_notification_message" msgid="4627312060769912353">"మీ ఐటి నిర్వాహకులు ఈ పరికరం సమస్యకు పరిష్కారాన్ని కనుగొనడంలో సహాయం కోసం బగ్ నివేదికను అభ్యర్థించారు. అనువర్తనాలు మరియు డేటా భాగస్వామ్యం చేయబడవచ్చు."</string>
-    <string name="sharing_remote_bugreport_notification_message" msgid="673106383408474893">"దీని వల్ల మీ పరికరం పనితీరు తాత్కాలికంగా నెమ్మదించవచ్చు"</string>
-    <string name="share_remote_bugreport_notification_accept" msgid="8203856129078669677">"ఆమోదిస్తున్నాను"</string>
-    <string name="share_remote_bugreport_notification_decline" msgid="6337969352057443969">"తిరస్కరిస్తున్నాను"</string>
+    <string name="share_remote_bugreport_notification_message_finished" msgid="8610614010660772643">"మీ ఐటి నిర్వాహకులు ఈ పరికరం సమస్యకు పరిష్కారాన్ని కనుగొనడంలో సహాయం కోసం బగ్ నివేదికను అభ్యర్థించారు. అనువర్తనాలు మరియు డేటా భాగస్వామ్యం చేయబడవచ్చు."</string>
+    <string name="share_remote_bugreport_action" msgid="6249476773913384948">"భాగస్వామ్యం చేయి"</string>
+    <string name="decline_remote_bugreport_action" msgid="6230987241608770062">"తిరస్కరిస్తున్నాను"</string>
     <string name="select_input_method" msgid="8547250819326693584">"కీబోర్డ్‌ను మార్చు"</string>
     <string name="configure_input_methods" msgid="4769971288371946846">"కీబోర్డ్‌లను ఎంచుకోండి"</string>
     <string name="show_ime" msgid="2506087537466597099">"దీన్ని భౌతిక కీబోర్డ్ సక్రియంగా ఉన్నప్పుడు స్క్రీన్‌పై ఉంచుతుంది"</string>
@@ -1137,8 +1135,9 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"వాల్‌పేపర్"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"వాల్‌పేపర్‌ను మార్చండి"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"నోటిఫికేషన్ పరిశీలన"</string>
+    <string name="vr_listener_binding_label" msgid="4316591939343607306">"VR పరిశీలన"</string>
     <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"షరతు ప్రదాత"</string>
-    <string name="notification_assistant_binding_label" msgid="909456055569102952">"నోటిఫికేషన్ సహాయకం"</string>
+    <string name="notification_ranker_binding_label" msgid="774540592299064747">"నోటిఫికేషన్ ర్యాంకర్ సేవ"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN సక్రియం చేయబడింది"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"<xliff:g id="APP">%s</xliff:g> ద్వారా VPN సక్రియం చేయబడింది"</string>
     <string name="vpn_text" msgid="3011306607126450322">"నెట్‌వర్క్‌ను నిర్వహించడానికి తాకండి."</string>
@@ -1467,7 +1466,7 @@
     <string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"అన్‌పిన్ చేయడానికి ముందు పిన్‌ కోసం అడుగు"</string>
     <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"అన్‌పిన్ చేయడానికి ముందు అన్‌లాక్ నమూనా కోసం అడుగు"</string>
     <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"అన్‌పిన్ చేయడానికి ముందు పాస్‌వర్డ్ కోసం అడుగు"</string>
-    <string name="dock_cropped_windows_text" msgid="6378424064779004428">"అనువర్తన పరిమాణాన్ని మార్చడం సాధ్యపడదు, రెండు వేళ్లతో దీన్ని స్క్రోల్ చేయండి."</string>
+    <string name="dock_forced_resizable" msgid="5914261505436217520">"స్క్రీన్ విభజనతో అనువర్తనం పని చేయకపోవచ్చు."</string>
     <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"అనువర్తనంలో స్క్రీన్ విభజనకు మద్దతు లేదు."</string>
     <string name="package_installed_device_owner" msgid="8420696545959087545">"మీ నిర్వాహకులు ఇన్‌స్టాల్ చేసారు"</string>
     <string name="package_updated_device_owner" msgid="8856631322440187071">"మీ నిర్వాహకుడు నవీకరించారు"</string>
@@ -1541,7 +1540,7 @@
     <string name="importance_from_person" msgid="9160133597262938296">"ఇందులో పేర్కొనబడిన వ్యక్తులను బట్టి ఇది చాలా ముఖ్యమైనది."</string>
     <string name="user_creation_account_exists" msgid="1942606193570143289">"<xliff:g id="ACCOUNT">%2$s</xliff:g>తో కొత్త వినియోగదారుని సృష్టించడానికి <xliff:g id="APP">%1$s</xliff:g>ని అనుమతించాలా ?"</string>
     <string name="user_creation_adding" msgid="4482658054622099197">"<xliff:g id="ACCOUNT">%2$s</xliff:g>తో (ఈ ఖాతాతో ఇప్పటికే ఒక వినియోగదారు ఉన్నారు) కొత్త వినియోగదారుని సృష్టించడానికి <xliff:g id="APP">%1$s</xliff:g>ని అనుమతించాలా?"</string>
-    <string name="language_selection_title" msgid="7181332986330337171">"భాష ప్రాధాన్యత"</string>
+    <string name="language_selection_title" msgid="2680677278159281088">"భాషను జోడించండి"</string>
     <string name="country_selection_title" msgid="2954859441620215513">"ప్రాంతం ప్రాధాన్యత"</string>
     <string name="search_language_hint" msgid="7042102592055108574">"భాష పేరును టైప్ చేయండి"</string>
     <string name="language_picker_section_suggested" msgid="8414489646861640885">"సూచించినవి"</string>
@@ -1565,4 +1564,6 @@
     <string name="unpin_target" msgid="3556545602439143442">"అన్‌‌పిన్‌ ‌చేయి"</string>
     <string name="app_info" msgid="6856026610594615344">"అనువర్తన సమాచారం"</string>
     <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="audit_safemode_notification" msgid="6351827251856877200">"ఈ పరికరాన్ని సాధారణంగా ఉపయోగించడానికి ఫ్యాక్టరీ రీసెట్ చేయండి"</string>
+    <string name="audit_safemode_notification_details" msgid="1860601176690176413">"మరింత తెలుసుకోవడానికి తాకండి."</string>
 </resources>
diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml
index ca08fd5..fabecc3 100644
--- a/core/res/res/values-th/strings.xml
+++ b/core/res/res/values-th/strings.xml
@@ -229,7 +229,6 @@
     <string name="global_action_voice_assist" msgid="7751191495200504480">"ตัวช่วยเสียง"</string>
     <string name="global_action_lockdown" msgid="8751542514724332873">"ล็อกเลย"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
-    <string name="notification_children_count_bracketed" msgid="1769425473168347839">"(<xliff:g id="NOTIFICATIONCOUNT">%d</xliff:g>)"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"เนื้อหาถูกซ่อนไว้"</string>
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"มีการซ่อนเนื้อหาโดยนโยบาย"</string>
     <string name="safeMode" msgid="2788228061547930246">"โหมดปลอดภัย"</string>
@@ -1052,13 +1051,12 @@
     <string name="usb_notification_message" msgid="7347368030849048437">"แตะเพื่อดูตัวเลือกเพิ่มเติม"</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"เชื่อมต่อการแก้ไขข้อบกพร่อง USB แล้ว"</string>
     <string name="adb_active_notification_message" msgid="1016654627626476142">"แตะเพื่อปิดใช้งานการแก้ไขข้อบกพร่อง USB"</string>
+    <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"กำลังสร้างรายงานข้อบกพร่อง…"</string>
     <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"แชร์รายงานข้อบกพร่องไหม"</string>
     <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"กำลังแชร์รายงานข้อบกพร่อง…"</string>
-    <string name="share_remote_bugreport_notification_message" msgid="752583906074230920">"ผู้ดูแลระบบไอทีของคุณขอรายงานข้อบกพร่องเพื่อช่วยในการแก้ปัญหาอุปกรณ์นี้ อาจมีการแชร์แอปและข้อมูล ซึ่งอาจทำให้อุปกรณ์ทำงานช้าลงชั่วคราว"</string>
-    <string name="share_finished_remote_bugreport_notification_message" msgid="4627312060769912353">"ผู้ดูแลระบบไอทีของคุณขอรายงานข้อบกพร่องเพื่อช่วยในการแก้ปัญหาอุปกรณ์นี้ อาจมีการแชร์แอปและข้อมูล"</string>
-    <string name="sharing_remote_bugreport_notification_message" msgid="673106383408474893">"การดำเนินการนี้อาจทำให้อุปกรณ์ทำงานช้าลงชั่วคราว"</string>
-    <string name="share_remote_bugreport_notification_accept" msgid="8203856129078669677">"ยอมรับ"</string>
-    <string name="share_remote_bugreport_notification_decline" msgid="6337969352057443969">"ปฏิเสธ"</string>
+    <string name="share_remote_bugreport_notification_message_finished" msgid="8610614010660772643">"ผู้ดูแลระบบไอทีของคุณขอรายงานข้อบกพร่องเพื่อช่วยในการแก้ปัญหาอุปกรณ์นี้ อาจมีการแชร์แอปและข้อมูล"</string>
+    <string name="share_remote_bugreport_action" msgid="6249476773913384948">"แชร์"</string>
+    <string name="decline_remote_bugreport_action" msgid="6230987241608770062">"ปฏิเสธ"</string>
     <string name="select_input_method" msgid="8547250819326693584">"เปลี่ยนแป้นพิมพ์"</string>
     <string name="configure_input_methods" msgid="4769971288371946846">"เลือกแป้นพิมพ์"</string>
     <string name="show_ime" msgid="2506087537466597099">"เปิดทิ้งไว้บนหน้าจอในระหว่างใช้งานแป้นพิมพ์จริง"</string>
@@ -1137,8 +1135,9 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"วอลเปเปอร์"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"เปลี่ยนวอลเปเปอร์"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"ตัวฟังการแจ้งเตือน"</string>
+    <string name="vr_listener_binding_label" msgid="4316591939343607306">"Listener ความเป็นจริงเสมือน"</string>
     <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"ผู้เสนอเงื่อนไข"</string>
-    <string name="notification_assistant_binding_label" msgid="909456055569102952">"ผู้ช่วยการแจ้งเตือน"</string>
+    <string name="notification_ranker_binding_label" msgid="774540592299064747">"บริการตัวจัดอันดับการแจ้งเตือน"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN เปิดใช้งานแล้ว"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"เปิดใช้งาน VPN โดย <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"แตะเพื่อจัดการเครือข่าย"</string>
@@ -1467,7 +1466,7 @@
     <string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"ขอ PIN ก่อนเลิกตรึง"</string>
     <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"ขอรูปแบบการปลดล็อกก่อนเลิกตรึง"</string>
     <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"ขอรหัสผ่านก่อนเลิกตรึง"</string>
-    <string name="dock_cropped_windows_text" msgid="6378424064779004428">"แอปไม่สามารถปรับขนาดได้ เลื่อนแอปด้วยนิ้ว 2 นิ้ว"</string>
+    <string name="dock_forced_resizable" msgid="5914261505436217520">"แอปอาจใช้ไม่ได้กับโหมดแยกหน้าจอ"</string>
     <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"แอปไม่สนับสนุนการแยกหน้าจอ"</string>
     <string name="package_installed_device_owner" msgid="8420696545959087545">"ติดตั้งโดยผู้ดูแลระบบของคุณ"</string>
     <string name="package_updated_device_owner" msgid="8856631322440187071">"อัปเดตโดยผู้ดูแลระบบ"</string>
@@ -1541,7 +1540,7 @@
     <string name="importance_from_person" msgid="9160133597262938296">"ข้อความนี้สำคัญเนื่องจากบุคคลที่เกี่ยวข้อง"</string>
     <string name="user_creation_account_exists" msgid="1942606193570143289">"อนุญาตให้ <xliff:g id="APP">%1$s</xliff:g> สร้างผู้ใช้ใหม่ด้วย <xliff:g id="ACCOUNT">%2$s</xliff:g> ไหม"</string>
     <string name="user_creation_adding" msgid="4482658054622099197">"อนุญาตให้ <xliff:g id="APP">%1$s</xliff:g> สร้างผู้ใช้ใหม่ด้วย <xliff:g id="ACCOUNT">%2$s</xliff:g> (มีผู้ใช้ที่มีบัญชีนี้อยู่แล้ว) ไหม"</string>
-    <string name="language_selection_title" msgid="7181332986330337171">"ค่ากำหนดภาษา"</string>
+    <string name="language_selection_title" msgid="2680677278159281088">"เพิ่มภาษา"</string>
     <string name="country_selection_title" msgid="2954859441620215513">"ค่ากำหนดภูมิภาค"</string>
     <string name="search_language_hint" msgid="7042102592055108574">"พิมพ์ชื่อภาษา"</string>
     <string name="language_picker_section_suggested" msgid="8414489646861640885">"แนะนำ"</string>
@@ -1565,4 +1564,6 @@
     <string name="unpin_target" msgid="3556545602439143442">"เลิกปักหมุด"</string>
     <string name="app_info" msgid="6856026610594615344">"ข้อมูลแอป"</string>
     <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="audit_safemode_notification" msgid="6351827251856877200">"รีเซ็ตเป็นค่าเริ่มต้นเพื่อใช้อุปกรณ์นี้ตามปกติ"</string>
+    <string name="audit_safemode_notification_details" msgid="1860601176690176413">"แตะเพื่อเรียนรู้เพิ่มเติม"</string>
 </resources>
diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml
index 72034d1..981567d 100644
--- a/core/res/res/values-tl/strings.xml
+++ b/core/res/res/values-tl/strings.xml
@@ -229,7 +229,6 @@
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Voice Assist"</string>
     <string name="global_action_lockdown" msgid="8751542514724332873">"I-lock ngayon"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
-    <string name="notification_children_count_bracketed" msgid="1769425473168347839">"(<xliff:g id="NOTIFICATIONCOUNT">%d</xliff:g>)"</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>
     <string name="safeMode" msgid="2788228061547930246">"Safe mode"</string>
@@ -1052,13 +1051,12 @@
     <string name="usb_notification_message" msgid="7347368030849048437">"Pindutin para sa higit pang mga opsyon."</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"Konektado ang debugging ng USB"</string>
     <string name="adb_active_notification_message" msgid="1016654627626476142">"Pindutin upang i-disable ang pagde-debug ng USB."</string>
+    <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Kinukuha ang ulat ng bug…"</string>
     <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Gusto mo bang ibahagi ang ulat ng bug?"</string>
     <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Ibinabahagi ang ulat ng bug…"</string>
-    <string name="share_remote_bugreport_notification_message" msgid="752583906074230920">"Humiling ang iyong IT admin ng isang ulat ng bug upang makatulong sa pag-troubleshoot sa device na ito. Maaaring ibahagi ang mga app at data at maaaring pansamantalang bumagal ang iyong device."</string>
-    <string name="share_finished_remote_bugreport_notification_message" msgid="4627312060769912353">"Humiling ang iyong IT admin ng isang ulat ng bug upang makatulong sa pag-troubleshoot sa device na ito. Maaaring ibahagi ang mga app at data."</string>
-    <string name="sharing_remote_bugreport_notification_message" msgid="673106383408474893">"Maaaring pansamantalang bumagal ang iyong device dahil dito"</string>
-    <string name="share_remote_bugreport_notification_accept" msgid="8203856129078669677">"TANGGAPIN"</string>
-    <string name="share_remote_bugreport_notification_decline" msgid="6337969352057443969">"TANGGIHAN"</string>
+    <string name="share_remote_bugreport_notification_message_finished" msgid="8610614010660772643">"Humiling ang iyong IT admin ng isang ulat ng bug upang makatulong sa pag-troubleshoot sa device na ito. Maaaring ibahagi ang mga app at data."</string>
+    <string name="share_remote_bugreport_action" msgid="6249476773913384948">"IBAHAGI"</string>
+    <string name="decline_remote_bugreport_action" msgid="6230987241608770062">"TANGGIHAN"</string>
     <string name="select_input_method" msgid="8547250819326693584">"Baguhin ang keyboard"</string>
     <string name="configure_input_methods" msgid="4769971288371946846">"Pumili ng mga keyboard"</string>
     <string name="show_ime" msgid="2506087537466597099">"Panatilihin ito sa screen habang aktibo ang pisikal na keyboard"</string>
@@ -1137,8 +1135,9 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Wallpaper"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Baguhin ang wallpaper"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Notification listener"</string>
+    <string name="vr_listener_binding_label" msgid="4316591939343607306">"VR listener"</string>
     <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Nagbibigay ng kundisyon"</string>
-    <string name="notification_assistant_binding_label" msgid="909456055569102952">"Notification assistant"</string>
+    <string name="notification_ranker_binding_label" msgid="774540592299064747">"Serbisyo sa pag-rank ng notification"</string>
     <string name="vpn_title" msgid="19615213552042827">"Naka-activate ang VPN"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"Isinaaktibo ang VPN ng <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Pindutin upang pamahalaan ang network."</string>
@@ -1467,7 +1466,7 @@
     <string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Humingi ng PIN bago mag-unpin"</string>
     <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Humingi ng pattern sa pag-unlock bago mag-unpin"</string>
     <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Humingi ng password bago mag-unpin"</string>
-    <string name="dock_cropped_windows_text" msgid="6378424064779004428">"Hindi nare-resize ang app, mag-scroll dito gamit ang dalawang daliri."</string>
+    <string name="dock_forced_resizable" msgid="5914261505436217520">"Maaaring hindi gumana ang app sa split-screen."</string>
     <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"Hindi sinusuportahan ng app ang split-screen."</string>
     <string name="package_installed_device_owner" msgid="8420696545959087545">"Na-install ng iyong administrator"</string>
     <string name="package_updated_device_owner" msgid="8856631322440187071">"Na-update ng iyong administrator"</string>
@@ -1541,7 +1540,7 @@
     <string name="importance_from_person" msgid="9160133597262938296">"Mahalaga ito dahil sa mga taong kasangkot."</string>
     <string name="user_creation_account_exists" msgid="1942606193570143289">"Payagan ang <xliff:g id="APP">%1$s</xliff:g> na gumawa ng bagong User sa <xliff:g id="ACCOUNT">%2$s</xliff:g> ?"</string>
     <string name="user_creation_adding" msgid="4482658054622099197">"Payagan ang <xliff:g id="APP">%1$s</xliff:g> na gumawa ng bagong User sa <xliff:g id="ACCOUNT">%2$s</xliff:g> (mayroon nang User sa account na ito) ?"</string>
-    <string name="language_selection_title" msgid="7181332986330337171">"Kagustuhan sa wika"</string>
+    <string name="language_selection_title" msgid="2680677278159281088">"Magdagdag ng wika"</string>
     <string name="country_selection_title" msgid="2954859441620215513">"Kagustuhan sa rehiyon"</string>
     <string name="search_language_hint" msgid="7042102592055108574">"I-type ang wika"</string>
     <string name="language_picker_section_suggested" msgid="8414489646861640885">"Iminumungkahi"</string>
@@ -1565,4 +1564,6 @@
     <string name="unpin_target" msgid="3556545602439143442">"I-unpin"</string>
     <string name="app_info" msgid="6856026610594615344">"Impormasyon ng app"</string>
     <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="audit_safemode_notification" msgid="6351827251856877200">"Mag-factory reset upang magamit nang normal ang device na ito"</string>
+    <string name="audit_safemode_notification_details" msgid="1860601176690176413">"Pindutin upang matuto nang higit pa."</string>
 </resources>
diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml
index e2c751e..af5652b 100644
--- a/core/res/res/values-tr/strings.xml
+++ b/core/res/res/values-tr/strings.xml
@@ -229,7 +229,6 @@
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Sesli Yardım"</string>
     <string name="global_action_lockdown" msgid="8751542514724332873">"Şimdi kilitle"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
-    <string name="notification_children_count_bracketed" msgid="1769425473168347839">"(<xliff:g id="NOTIFICATIONCOUNT">%d</xliff:g>)"</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>
     <string name="safeMode" msgid="2788228061547930246">"Güvenli mod"</string>
@@ -1052,13 +1051,12 @@
     <string name="usb_notification_message" msgid="7347368030849048437">"Daha fazla seçenek için dokunun."</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"USB hata ayıklaması bağlandı"</string>
     <string name="adb_active_notification_message" msgid="1016654627626476142">"USB hata ayıklama özelliğini devre dışı bırakmak için dokunun."</string>
+    <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Hata raporu alınıyor…"</string>
     <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Hata raporu paylaşılsın mı?"</string>
     <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Hata raporu paylaşılıyor..."</string>
-    <string name="share_remote_bugreport_notification_message" msgid="752583906074230920">"BT yöneticiniz, bu cihazda sorun gidermeye yardımcı olması için bir hata raporu istedi. Uygulamalar ve veriler paylaşılabilir. Bu durum, cihazınızı geçici olarak yavaşlatabilir."</string>
-    <string name="share_finished_remote_bugreport_notification_message" msgid="4627312060769912353">"BT yöneticiniz, bu cihazda sorun gidermeye yardımcı olması için bir hata raporu istedi. Uygulamalar ve veriler paylaşılabilir."</string>
-    <string name="sharing_remote_bugreport_notification_message" msgid="673106383408474893">"Bu durum, cihazınızı geçici olarak yavaşlatabilir"</string>
-    <string name="share_remote_bugreport_notification_accept" msgid="8203856129078669677">"KABUL ET"</string>
-    <string name="share_remote_bugreport_notification_decline" msgid="6337969352057443969">"REDDET"</string>
+    <string name="share_remote_bugreport_notification_message_finished" msgid="8610614010660772643">"BT yöneticiniz, bu cihazda sorun gidermeye yardımcı olması için bir hata raporu istedi. Uygulamalar ve veriler paylaşılabilir."</string>
+    <string name="share_remote_bugreport_action" msgid="6249476773913384948">"PAYLAŞ"</string>
+    <string name="decline_remote_bugreport_action" msgid="6230987241608770062">"REDDET"</string>
     <string name="select_input_method" msgid="8547250819326693584">"Klavyeyi değiştir"</string>
     <string name="configure_input_methods" msgid="4769971288371946846">"Klavyeyi seç"</string>
     <string name="show_ime" msgid="2506087537466597099">"Fiziksel klavye etkin durumdayken ekranda tut"</string>
@@ -1137,8 +1135,9 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Duvar Kağıdı"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Duvar kağıdını değiştir"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Bildirim dinleyici"</string>
+    <string name="vr_listener_binding_label" msgid="4316591939343607306">"Sanal Gerçeklik dinleyici"</string>
     <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Durum sağlayıcı"</string>
-    <string name="notification_assistant_binding_label" msgid="909456055569102952">"Bildirim yardımcısı"</string>
+    <string name="notification_ranker_binding_label" msgid="774540592299064747">"Bildirim sıralama hizmeti"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN etkinleştirildi"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN, <xliff:g id="APP">%s</xliff:g> tarafından etkinleştirildi"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Ağı yönetmek için dokunun."</string>
@@ -1467,7 +1466,7 @@
     <string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Sabitlemeyi kaldırmadan önce PIN\'i sor"</string>
     <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Sabitlemeyi kaldırmadan önce kilit açma desenini sor"</string>
     <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Sabitlemeyi kaldırmadan önce şifre sor"</string>
-    <string name="dock_cropped_windows_text" msgid="6378424064779004428">"Uygulama yeniden boyutlandırılamaz. İki parmağınızla kaydırın."</string>
+    <string name="dock_forced_resizable" msgid="5914261505436217520">"Uygulama bölünmüş ekranda çalışmayabilir."</string>
     <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"Uygulama bölünmüş ekranı desteklemiyor."</string>
     <string name="package_installed_device_owner" msgid="8420696545959087545">"Yöneticiniz tarafından yüklendi"</string>
     <string name="package_updated_device_owner" msgid="8856631322440187071">"Yöneticiniz tarafından güncellendi"</string>
@@ -1541,7 +1540,7 @@
     <string name="importance_from_person" msgid="9160133597262938296">"Bu, dahil olan kişiler nedeniyle önemlidir."</string>
     <string name="user_creation_account_exists" msgid="1942606193570143289">"<xliff:g id="APP">%1$s</xliff:g> uygulamasının <xliff:g id="ACCOUNT">%2$s</xliff:g> hesabına sahip yeni bir Kullanıcı eklemesine izin verilsin mi?"</string>
     <string name="user_creation_adding" msgid="4482658054622099197">"<xliff:g id="APP">%1$s</xliff:g> uygulamasının <xliff:g id="ACCOUNT">%2$s</xliff:g> hesabına sahip yeni bir Kullanıcı eklemesine izin verilsin mi (bu hesaba sahip bir kullanıcı zaten var)?"</string>
-    <string name="language_selection_title" msgid="7181332986330337171">"Dil tercihi"</string>
+    <string name="language_selection_title" msgid="2680677278159281088">"Dil ekleyin"</string>
     <string name="country_selection_title" msgid="2954859441620215513">"Bölge tercihi"</string>
     <string name="search_language_hint" msgid="7042102592055108574">"Dil adını yazın"</string>
     <string name="language_picker_section_suggested" msgid="8414489646861640885">"Önerilen"</string>
@@ -1564,6 +1563,7 @@
     <string name="pin_target" msgid="3052256031352291362">"Sabitle"</string>
     <string name="unpin_target" msgid="3556545602439143442">"Sabitlemeyi kaldır"</string>
     <string name="app_info" msgid="6856026610594615344">"Uygulama bilgileri"</string>
-    <!-- no translation found for negative_duration (5688706061127375131) -->
-    <skip />
+    <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="audit_safemode_notification" msgid="6351827251856877200">"Cihazı normal olarak kullanmak için fabrika ayarlarına sıfırlayın"</string>
+    <string name="audit_safemode_notification_details" msgid="1860601176690176413">"Daha fazla bilgi edinmek için dokunun."</string>
 </resources>
diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml
index e805a99..344797f 100644
--- a/core/res/res/values-uk/strings.xml
+++ b/core/res/res/values-uk/strings.xml
@@ -233,7 +233,6 @@
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Голос. підказки"</string>
     <string name="global_action_lockdown" msgid="8751542514724332873">"Блокувати зараз"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
-    <string name="notification_children_count_bracketed" msgid="1769425473168347839">"(<xliff:g id="NOTIFICATIONCOUNT">%d</xliff:g>)"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"Вміст сховано"</string>
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Вміст сховано згідно з правилом"</string>
     <string name="safeMode" msgid="2788228061547930246">"Безп. режим"</string>
@@ -1068,13 +1067,12 @@
     <string name="usb_notification_message" msgid="7347368030849048437">"Торкніться, щоб побачити більше опцій."</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"Налагодження USB завершено"</string>
     <string name="adb_active_notification_message" msgid="1016654627626476142">"Торкніться, щоб вимкнути налагодження USB."</string>
+    <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Створюється повідомлення про помилку…"</string>
     <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Надіслати звіт про помилку?"</string>
     <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Надсилається звіт про помилку…"</string>
-    <string name="share_remote_bugreport_notification_message" msgid="752583906074230920">"Ваш IT-адміністратор просить надіслати повідомлення про помилку, щоб вирішити проблему з пристроєм. Він може отримати доступ до ваших додатків і даних. Це також може тимчасово сповільнити роботу вашого пристрою."</string>
-    <string name="share_finished_remote_bugreport_notification_message" msgid="4627312060769912353">"Ваш IT-адміністратор просить надіслати повідомлення про помилку, щоб вирішити проблему з пристроєм. Він може отримати доступ до ваших додатків і даних."</string>
-    <string name="sharing_remote_bugreport_notification_message" msgid="673106383408474893">"Це може тимчасово сповільнити роботу вашого пристрою"</string>
-    <string name="share_remote_bugreport_notification_accept" msgid="8203856129078669677">"ПРИЙНЯТИ"</string>
-    <string name="share_remote_bugreport_notification_decline" msgid="6337969352057443969">"ВІДХИЛИТИ"</string>
+    <string name="share_remote_bugreport_notification_message_finished" msgid="8610614010660772643">"Ваш IT-адміністратор просить надіслати повідомлення про помилку, щоб вирішити проблему з пристроєм. Він може отримати доступ до ваших додатків і даних."</string>
+    <string name="share_remote_bugreport_action" msgid="6249476773913384948">"ПОДІЛИТИСЯ"</string>
+    <string name="decline_remote_bugreport_action" msgid="6230987241608770062">"ВІДХИЛИТИ"</string>
     <string name="select_input_method" msgid="8547250819326693584">"Змінити клавіатуру"</string>
     <string name="configure_input_methods" msgid="4769971288371946846">"Вибрати клавіатури"</string>
     <string name="show_ime" msgid="2506087537466597099">"Утримуйте на екрані, коли активна фізична клавіатура"</string>
@@ -1153,8 +1151,9 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Фоновий мал."</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Змінити фоновий малюнок"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Служба читання сповіщень"</string>
+    <string name="vr_listener_binding_label" msgid="4316591939343607306">"Обробник віртуальної реальності"</string>
     <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Постачальник умов"</string>
-    <string name="notification_assistant_binding_label" msgid="909456055569102952">"Диспетчер сповіщень"</string>
+    <string name="notification_ranker_binding_label" msgid="774540592299064747">"Служба позиціонування сповіщень"</string>
     <string name="vpn_title" msgid="19615213552042827">"Мережу VPN активовано"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"Мережу VPN активовано програмою <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Торкніться, щоб керувати мережею."</string>
@@ -1487,7 +1486,7 @@
     <string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"PIN-код для відкріплення"</string>
     <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Запитувати ключ розблокування перед відкріпленням"</string>
     <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Запитувати пароль перед відкріпленням"</string>
-    <string name="dock_cropped_windows_text" msgid="6378424064779004428">"Розмір додатка не можна змінити. Прокручуйте його двома пальцями."</string>
+    <string name="dock_forced_resizable" msgid="5914261505436217520">"Додаток може не працювати в режимі розділеного екрана."</string>
     <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"Додаток не підтримує розділення екрана."</string>
     <string name="package_installed_device_owner" msgid="8420696545959087545">"Установив адміністратор"</string>
     <string name="package_updated_device_owner" msgid="8856631322440187071">"Оновлено адміністратором"</string>
@@ -1579,7 +1578,7 @@
     <string name="importance_from_person" msgid="9160133597262938296">"Важливе з огляду на учасників."</string>
     <string name="user_creation_account_exists" msgid="1942606193570143289">"Дозволити додатку <xliff:g id="APP">%1$s</xliff:g> створити нового користувача з обліковим записом <xliff:g id="ACCOUNT">%2$s</xliff:g>?"</string>
     <string name="user_creation_adding" msgid="4482658054622099197">"Дозволити додатку <xliff:g id="APP">%1$s</xliff:g> створити нового користувача з обліковим записом <xliff:g id="ACCOUNT">%2$s</xliff:g> (користувач із таким обліковим записом уже існує)?"</string>
-    <string name="language_selection_title" msgid="7181332986330337171">"Вибір мови"</string>
+    <string name="language_selection_title" msgid="2680677278159281088">"Додати мову"</string>
     <string name="country_selection_title" msgid="2954859441620215513">"Вибір регіону"</string>
     <string name="search_language_hint" msgid="7042102592055108574">"Введіть назву мови"</string>
     <string name="language_picker_section_suggested" msgid="8414489646861640885">"Пропозиції"</string>
@@ -1603,4 +1602,6 @@
     <string name="unpin_target" msgid="3556545602439143442">"Відкріпити"</string>
     <string name="app_info" msgid="6856026610594615344">"Про додаток"</string>
     <string name="negative_duration" msgid="5688706061127375131">"-<xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="audit_safemode_notification" msgid="6351827251856877200">"Відновлення заводських налаштувань для належної роботи пристрою"</string>
+    <string name="audit_safemode_notification_details" msgid="1860601176690176413">"Торкніться, щоб дізнатися більше."</string>
 </resources>
diff --git a/core/res/res/values-ur-rPK/strings.xml b/core/res/res/values-ur-rPK/strings.xml
index b33cde0..a58f5c2 100644
--- a/core/res/res/values-ur-rPK/strings.xml
+++ b/core/res/res/values-ur-rPK/strings.xml
@@ -229,7 +229,6 @@
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Voice Assist"</string>
     <string name="global_action_lockdown" msgid="8751542514724332873">"ابھی مقفل کریں"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"‎999+‎"</string>
-    <string name="notification_children_count_bracketed" msgid="1769425473168347839">"(<xliff:g id="NOTIFICATIONCOUNT">%d</xliff:g>)"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"مواد مخفی ہیں"</string>
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"مواد پالیسی کے تحت مخفی ہے"</string>
     <string name="safeMode" msgid="2788228061547930246">"حفاظتی وضع"</string>
@@ -1052,13 +1051,12 @@
     <string name="usb_notification_message" msgid="7347368030849048437">"مزید اختیارات کیلئے ٹچ کریں۔"</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"‏USB ڈیبگ کرنا مربوط ہو گیا"</string>
     <string name="adb_active_notification_message" msgid="1016654627626476142">"‏USB ڈیبگنگ کو غیر فعال کرنے کیلئے ٹچ کریں۔"</string>
+    <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"بگ رپورٹ لی جا رہی ہے…"</string>
     <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"بگ رپورٹ کا اشتراک کریں؟"</string>
     <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"بگ رپورٹ کا اشتراک ہو رہا ہے…"</string>
-    <string name="share_remote_bugreport_notification_message" msgid="752583906074230920">"‏آپ کے IT منتظم نے اس آلہ کا مسئلہ حل کرنے میں مدد کیلئے ایک بگ رپورٹ کی درخواست کی ہے۔ ایپس اور ڈیٹا کا اشتراک ہو سکتا ہے اور آپ کا آلہ عارضی طور پر سست ہو سکتا ہے۔"</string>
-    <string name="share_finished_remote_bugreport_notification_message" msgid="4627312060769912353">"‏آپ کے IT منتظم نے اس آلہ کا مسئلہ حل کرنے میں مدد کیلئے ایک بگ رپورٹ کی درخواست کی ہے۔ ایپس اور ڈیٹا کا اشتراک ہو سکتا ہے۔"</string>
-    <string name="sharing_remote_bugreport_notification_message" msgid="673106383408474893">"اس سے آپ کا آلہ عارضی طور پر سست ہو سکتا ہے"</string>
-    <string name="share_remote_bugreport_notification_accept" msgid="8203856129078669677">"قبول کریں"</string>
-    <string name="share_remote_bugreport_notification_decline" msgid="6337969352057443969">"مسترد کریں"</string>
+    <string name="share_remote_bugreport_notification_message_finished" msgid="8610614010660772643">"‏آپ کے IT منتظم نے اس آلہ کا مسئلہ حل کرنے میں مدد کیلئے ایک بگ رپورٹ کی درخواست کی ہے۔ ایپس اور ڈیٹا کا اشتراک ہو سکتا ہے۔"</string>
+    <string name="share_remote_bugreport_action" msgid="6249476773913384948">"اشتراک کریں"</string>
+    <string name="decline_remote_bugreport_action" msgid="6230987241608770062">"مسترد کریں"</string>
     <string name="select_input_method" msgid="8547250819326693584">"کی بورڈ تبدیل کریں"</string>
     <string name="configure_input_methods" msgid="4769971288371946846">"کی بورڈز منتخب کریں"</string>
     <string name="show_ime" msgid="2506087537466597099">"‏جب فزیکل کی بورڈ فعال ہو تو IME کو اسکرین پر رکھیں"</string>
@@ -1137,8 +1135,9 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"وال پیپر"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"وال پیپر تبدیل کریں"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"اطلاع سننے والا"</string>
+    <string name="vr_listener_binding_label" msgid="4316591939343607306">"‏VR سامع"</string>
     <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"شرط فراہم کنندہ"</string>
-    <string name="notification_assistant_binding_label" msgid="909456055569102952">"اطلاع کا معاون"</string>
+    <string name="notification_ranker_binding_label" msgid="774540592299064747">"اطلاع کی درجہ بندی سروس"</string>
     <string name="vpn_title" msgid="19615213552042827">"‏VPN فعال ہوگیا"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"‏<xliff:g id="APP">%s</xliff:g> کے ذریعہ VPN فعال ہے"</string>
     <string name="vpn_text" msgid="3011306607126450322">"نیٹ ورک کا نظم کرنے کیلئے چھوئیں۔"</string>
@@ -1467,7 +1466,7 @@
     <string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"‏پن ہٹانے سے پہلے PIN طلب کریں"</string>
     <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"پن ہٹانے سے پہلے غیر مقفل کرنے کا پیٹرن طلب کریں"</string>
     <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"پن ہٹانے سے پہلے پاس ورڈ طلب کریں"</string>
-    <string name="dock_cropped_windows_text" msgid="6378424064779004428">"ایپ ری سائز ایبل نہیں ہے، اسے دو انگلیوں کے ساتھ سکرول کریں۔"</string>
+    <string name="dock_forced_resizable" msgid="5914261505436217520">"ممکن ہے کہ ایپ سپلٹ اسکرین کے ساتھ کام نہ کرے۔"</string>
     <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"ایپ سپلٹ اسکرین کو سپورٹ نہیں کرتی۔"</string>
     <string name="package_installed_device_owner" msgid="8420696545959087545">"آپ کے منتظم کی جانب سے انسٹال کر دیا گیا"</string>
     <string name="package_updated_device_owner" msgid="8856631322440187071">"آپ کے منتظم نے اپ ڈيٹ کر دیا"</string>
@@ -1541,7 +1540,7 @@
     <string name="importance_from_person" msgid="9160133597262938296">"اس میں موجود لوگوں کی وجہ سے یہ اہم ہے۔"</string>
     <string name="user_creation_account_exists" msgid="1942606193570143289">"<xliff:g id="APP">%1$s</xliff:g> کو <xliff:g id="ACCOUNT">%2$s</xliff:g> کے ساتھ ایک نیا صارف بنانے کی اجازت دیں؟"</string>
     <string name="user_creation_adding" msgid="4482658054622099197">"<xliff:g id="APP">%1$s</xliff:g> کو <xliff:g id="ACCOUNT">%2$s</xliff:g> کے ساتھ ایک نیا صارف بنانے کی اجازت دیں (اس اکاؤنٹ کے ساتھ ایک صارف پہلے سے موجود ہے) ؟"</string>
-    <string name="language_selection_title" msgid="7181332986330337171">"زبان کی ترجیح"</string>
+    <string name="language_selection_title" msgid="2680677278159281088">"ایک زبان شامل کریں"</string>
     <string name="country_selection_title" msgid="2954859441620215513">"علاقہ کی ترجیح"</string>
     <string name="search_language_hint" msgid="7042102592055108574">"زبان کا نام ٹائپ کریں"</string>
     <string name="language_picker_section_suggested" msgid="8414489646861640885">"تجویز کردہ"</string>
@@ -1564,6 +1563,7 @@
     <string name="pin_target" msgid="3052256031352291362">"پن کریں"</string>
     <string name="unpin_target" msgid="3556545602439143442">"پن ہٹائیں"</string>
     <string name="app_info" msgid="6856026610594615344">"ایپ کی معلومات"</string>
-    <!-- no translation found for negative_duration (5688706061127375131) -->
-    <skip />
+    <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="audit_safemode_notification" msgid="6351827251856877200">"اس آلہ کو معمولاً استعمال کرنے کیلئے فیکٹری ری سیٹ کریں"</string>
+    <string name="audit_safemode_notification_details" msgid="1860601176690176413">"مزید جاننے کیلئے ٹچ کریں۔"</string>
 </resources>
diff --git a/core/res/res/values-uz-rUZ/strings.xml b/core/res/res/values-uz-rUZ/strings.xml
index 6558214..4ca1825 100644
--- a/core/res/res/values-uz-rUZ/strings.xml
+++ b/core/res/res/values-uz-rUZ/strings.xml
@@ -229,7 +229,6 @@
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Ovozli yordam"</string>
     <string name="global_action_lockdown" msgid="8751542514724332873">"Qulflash"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
-    <string name="notification_children_count_bracketed" msgid="1769425473168347839">"(<xliff:g id="NOTIFICATIONCOUNT">%d</xliff:g>)"</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>
     <string name="safeMode" msgid="2788228061547930246">"Xavfsiz usul"</string>
@@ -893,9 +892,9 @@
     <string name="capital_on" msgid="1544682755514494298">"I"</string>
     <string name="capital_off" msgid="6815870386972805832">"O"</string>
     <string name="whichApplication" msgid="4533185947064773386">"Ilovani tanlang"</string>
-    <string name="whichApplicationNamed" msgid="8260158865936942783">"“%1$s” ilovasi yordamida bajarish"</string>
+    <string name="whichApplicationNamed" msgid="8260158865936942783">"“%1$s” bilan ochish"</string>
     <string name="whichViewApplication" msgid="3272778576700572102">"Ochish…"</string>
-    <string name="whichViewApplicationNamed" msgid="2286418824011249620">"“%1$s” yordamida ochish"</string>
+    <string name="whichViewApplicationNamed" msgid="2286418824011249620">"%1$s bilan ochish"</string>
     <string name="whichEditApplication" msgid="144727838241402655">"Tahrirlash…"</string>
     <string name="whichEditApplicationNamed" msgid="1775815530156447790">"“%1$s” yordamida tahrirlash"</string>
     <string name="whichSendApplication" msgid="6902512414057341668">"Ulashish…"</string>
@@ -1052,13 +1051,12 @@
     <string name="usb_notification_message" msgid="7347368030849048437">"Sozlash uchun bosing."</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"USB orqali nosozliklarni tuzatish"</string>
     <string name="adb_active_notification_message" msgid="1016654627626476142">"O‘chirib qo‘yish uchun bosing."</string>
+    <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Xatoliklar hisoboti olinmoqda…"</string>
     <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Xatoliklar hisoboti yuborilsinmi?"</string>
     <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Xatoliklar hisoboti yuborilmoqda…"</string>
-    <string name="share_remote_bugreport_notification_message" msgid="752583906074230920">"Administratoringiz bu qurilma nosozliklarini tuzatish uchun xatoliklar hisobotini so‘ramoqda. Ilova va ma’lumotlardan foydalanilishi va bu vaqtincha qurilmangizni sekinlashtirishi ham mumkin."</string>
-    <string name="share_finished_remote_bugreport_notification_message" msgid="4627312060769912353">"Administratoringiz bu qurilma nosozliklarini tuzatish uchun xatoliklar hisobotini so‘ramoqda. Ilova va ma’lumotlardan foydalanilishi mumkin."</string>
-    <string name="sharing_remote_bugreport_notification_message" msgid="673106383408474893">"Qurilmaning ishlash tezligi vaqtincha pasayishi mumkin."</string>
-    <string name="share_remote_bugreport_notification_accept" msgid="8203856129078669677">"QABUL QILISH"</string>
-    <string name="share_remote_bugreport_notification_decline" msgid="6337969352057443969">"RAD ETISH"</string>
+    <string name="share_remote_bugreport_notification_message_finished" msgid="8610614010660772643">"Administratoringiz bu qurilma nosozliklarini tuzatish uchun xatoliklar hisobotini so‘ramoqda. Ilova va ma’lumotlardan foydalanilishi mumkin."</string>
+    <string name="share_remote_bugreport_action" msgid="6249476773913384948">"ULASHISH"</string>
+    <string name="decline_remote_bugreport_action" msgid="6230987241608770062">"RAD ETISH"</string>
     <string name="select_input_method" msgid="8547250819326693584">"Klaviaturani o‘zgartirish"</string>
     <string name="configure_input_methods" msgid="4769971288371946846">"Klaviaturani tanlash"</string>
     <string name="show_ime" msgid="2506087537466597099">"Tashqi klaviaturadan foydalanilayotganda buni ekranda saqlab turish"</string>
@@ -1137,8 +1135,9 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Fon rasmi"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Fon rasmini o‘zgartirish"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Bildirishnoma tinglovchisi"</string>
+    <string name="vr_listener_binding_label" msgid="4316591939343607306">"VR tinglovchisi"</string>
     <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Shartlarni taqdim etuvchi"</string>
-    <string name="notification_assistant_binding_label" msgid="909456055569102952">"Bildirishnoma yordamchisi"</string>
+    <string name="notification_ranker_binding_label" msgid="774540592299064747">"Bildirishnomalarni baholash xizmati"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN faollashtirildi"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN <xliff:g id="APP">%s</xliff:g> tomonidan faollashtirilgan"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Tarmoqni boshqarish uchun bosing."</string>
@@ -1467,7 +1466,7 @@
     <string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Yechishda PIN-kod so‘ralsin"</string>
     <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Bo‘shatishdan oldin chizmali parol so‘ralsin"</string>
     <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Bo‘shatishdan oldin parol so‘ralsin"</string>
-    <string name="dock_cropped_windows_text" msgid="6378424064779004428">"Oyna o‘lchamini o‘zgartirib bo‘lmaydi. Sahifani ikkita barmoq bilan aylantiring."</string>
+    <string name="dock_forced_resizable" msgid="5914261505436217520">"Ilova ekranni ikkiga bo‘lish rejimini qo‘llab-quvvatlamaydi."</string>
     <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"Bu ilova ekranni bo‘lish xususiyatini qo‘llab-quvvatlamaydi."</string>
     <string name="package_installed_device_owner" msgid="8420696545959087545">"Administratoringiz tomonidan o‘rnatilgan"</string>
     <string name="package_updated_device_owner" msgid="8856631322440187071">"Administratoringiz tomonidan yangilandi"</string>
@@ -1505,7 +1504,7 @@
       <item quantity="other">%d soat</item>
       <item quantity="one">1 soat</item>
     </plurals>
-    <string name="zen_mode_until" msgid="7336308492289875088">"Ushbu vaqtgacha: <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
+    <string name="zen_mode_until" msgid="7336308492289875088">"<xliff:g id="FORMATTEDTIME">%1$s</xliff:g> gacha"</string>
     <string name="zen_mode_alarm" msgid="9128205721301330797">"<xliff:g id="FORMATTEDTIME">%1$s</xliff:g> gacha (keyingi signal)"</string>
     <string name="zen_mode_forever" msgid="7420011936770086993">"Men o‘chirmaguncha"</string>
     <string name="zen_mode_forever_dnd" msgid="3792132696572189081">"“Bezovta qilinmasin” rejimi o‘chirilmaguncha"</string>
@@ -1541,7 +1540,7 @@
     <string name="importance_from_person" msgid="9160133597262938296">"Bu odamlar siz uchun muhim."</string>
     <string name="user_creation_account_exists" msgid="1942606193570143289">"<xliff:g id="APP">%1$s</xliff:g> ilovasiga <xliff:g id="ACCOUNT">%2$s</xliff:g> hisobi bilan yangi foydalanuvchi yaratishiga ruxsat berilsinmi ?"</string>
     <string name="user_creation_adding" msgid="4482658054622099197">"<xliff:g id="APP">%1$s</xliff:g> ilovasiga <xliff:g id="ACCOUNT">%2$s</xliff:g> hisobi bilan yangi foydalanuvchi yaratishiga ruxsat berilsinmi (bunday hisobdagi foydalanuvchi allaqachon mavjud) ?"</string>
-    <string name="language_selection_title" msgid="7181332986330337171">"Til sozlamalari"</string>
+    <string name="language_selection_title" msgid="2680677278159281088">"Tilni qo‘shing"</string>
     <string name="country_selection_title" msgid="2954859441620215513">"Hudud sozlamalari"</string>
     <string name="search_language_hint" msgid="7042102592055108574">"Til nomini kiriting"</string>
     <string name="language_picker_section_suggested" msgid="8414489646861640885">"Taklif etiladi"</string>
@@ -1564,6 +1563,7 @@
     <string name="pin_target" msgid="3052256031352291362">"Qadash"</string>
     <string name="unpin_target" msgid="3556545602439143442">"Olib tashlash"</string>
     <string name="app_info" msgid="6856026610594615344">"Ilova haqida"</string>
-    <!-- no translation found for negative_duration (5688706061127375131) -->
-    <skip />
+    <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="audit_safemode_notification" msgid="6351827251856877200">"Bu qurilmadan odatdagidek foydalanish uchun zavod sozlamalarini tiklang"</string>
+    <string name="audit_safemode_notification_details" msgid="1860601176690176413">"Ko‘proq o‘rganish uchun bosing."</string>
 </resources>
diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml
index 0133d48..283198f 100644
--- a/core/res/res/values-vi/strings.xml
+++ b/core/res/res/values-vi/strings.xml
@@ -229,7 +229,6 @@
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Trợ lý thoại"</string>
     <string name="global_action_lockdown" msgid="8751542514724332873">"Khóa ngay"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
-    <string name="notification_children_count_bracketed" msgid="1769425473168347839">"(<xliff:g id="NOTIFICATIONCOUNT">%d</xliff:g>)"</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>
     <string name="safeMode" msgid="2788228061547930246">"Chế độ an toàn"</string>
@@ -1052,13 +1051,12 @@
     <string name="usb_notification_message" msgid="7347368030849048437">"Chạm để có các tùy chọn khác."</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"Gỡ lỗi USB đã được kết nối"</string>
     <string name="adb_active_notification_message" msgid="1016654627626476142">"Chạm để vô hiệu hóa gỡ lỗi USB."</string>
+    <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Đang thu thập báo cáo lỗi…"</string>
     <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Chia sẻ báo cáo lỗi?"</string>
     <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Đang chia sẻ báo cáo lỗi…"</string>
-    <string name="share_remote_bugreport_notification_message" msgid="752583906074230920">"Quản trị viên CNTT của bạn đã yêu cầu báo cáo lỗi để giúp khắc phục sự cố thiết bị này. Bạn có thể chia sẻ ứng dụng, đồng thời dữ liệu và thiết bị của bạn tạm thời có thể bị chậm."</string>
-    <string name="share_finished_remote_bugreport_notification_message" msgid="4627312060769912353">"Quản trị viên CNTT của bạn đã yêu cầu báo cáo lỗi để giúp khắc phục sự cố thiết bị này. Bạn có thể chia sẻ ứng dụng và dữ liệu."</string>
-    <string name="sharing_remote_bugreport_notification_message" msgid="673106383408474893">"Tác vụ này tạm thời có thể làm chậm thiết bị của bạn"</string>
-    <string name="share_remote_bugreport_notification_accept" msgid="8203856129078669677">"CHẤP NHẬN"</string>
-    <string name="share_remote_bugreport_notification_decline" msgid="6337969352057443969">"TỪ CHỐI"</string>
+    <string name="share_remote_bugreport_notification_message_finished" msgid="8610614010660772643">"Quản trị viên CNTT của bạn đã yêu cầu báo cáo lỗi để giúp khắc phục sự cố thiết bị này. Bạn có thể chia sẻ ứng dụng và dữ liệu."</string>
+    <string name="share_remote_bugreport_action" msgid="6249476773913384948">"CHIA SẺ"</string>
+    <string name="decline_remote_bugreport_action" msgid="6230987241608770062">"TỪ CHỐI"</string>
     <string name="select_input_method" msgid="8547250819326693584">"Thay đổi bàn phím"</string>
     <string name="configure_input_methods" msgid="4769971288371946846">"Chọn bàn phím"</string>
     <string name="show_ime" msgid="2506087537466597099">"Tiếp tục sử dụng ứng dụng trên màn hình trong khi bàn phím thực đang hoạt động"</string>
@@ -1137,8 +1135,9 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Hình nền"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Thay đổi hình nền"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Trình xử lý thông báo"</string>
+    <string name="vr_listener_binding_label" msgid="4316591939343607306">"Trình nghe VR"</string>
     <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Trình cung cấp điều kiện"</string>
-    <string name="notification_assistant_binding_label" msgid="909456055569102952">"Trợ lý thông báo"</string>
+    <string name="notification_ranker_binding_label" msgid="774540592299064747">"Dịch vụ xếp hạng thông báo"</string>
     <string name="vpn_title" msgid="19615213552042827">"Đã kích hoạt VPN"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN được <xliff:g id="APP">%s</xliff:g> kích hoạt"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Chạm để quản lý mạng."</string>
@@ -1467,7 +1466,7 @@
     <string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Hỏi mã PIN trước khi bỏ ghim"</string>
     <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Hỏi hình mở khóa trước khi bỏ ghim"</string>
     <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Hỏi mật khẩu trước khi bỏ ghim"</string>
-    <string name="dock_cropped_windows_text" msgid="6378424064779004428">"Ứng dụng không đổi kích thước được, hãy cuộn ứng dụng bằng hai ngón tay."</string>
+    <string name="dock_forced_resizable" msgid="5914261505436217520">"Ứng dụng có thể không hoạt động với tính năng chia đôi màn hình."</string>
     <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"Ứng dụng không hỗ trợ chia đôi màn hình."</string>
     <string name="package_installed_device_owner" msgid="8420696545959087545">"Được cài đặt bởi quản trị viên của bạn"</string>
     <string name="package_updated_device_owner" msgid="8856631322440187071">"Được cập nhật bởi quản trị viên của bạn"</string>
@@ -1541,7 +1540,7 @@
     <string name="importance_from_person" msgid="9160133597262938296">"Thông báo này quan trọng vì những người có liên quan."</string>
     <string name="user_creation_account_exists" msgid="1942606193570143289">"Cho phép <xliff:g id="APP">%1$s</xliff:g> tạo người dùng mới bằng <xliff:g id="ACCOUNT">%2$s</xliff:g>?"</string>
     <string name="user_creation_adding" msgid="4482658054622099197">"Cho phép <xliff:g id="APP">%1$s</xliff:g> tạo người dùng mới bằng <xliff:g id="ACCOUNT">%2$s</xliff:g> (người dùng có tài khoản này đã tồn tại)?"</string>
-    <string name="language_selection_title" msgid="7181332986330337171">"Tùy chọn ngôn ngữ"</string>
+    <string name="language_selection_title" msgid="2680677278159281088">"Thêm ngôn ngữ"</string>
     <string name="country_selection_title" msgid="2954859441620215513">"Tùy chọn khu vực"</string>
     <string name="search_language_hint" msgid="7042102592055108574">"Nhập tên ngôn ngữ"</string>
     <string name="language_picker_section_suggested" msgid="8414489646861640885">"Ðược đề xuất"</string>
@@ -1565,4 +1564,6 @@
     <string name="unpin_target" msgid="3556545602439143442">"Bỏ ghim"</string>
     <string name="app_info" msgid="6856026610594615344">"Thông tin ứng dụng"</string>
     <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="audit_safemode_notification" msgid="6351827251856877200">"Thiết lập cài đặt gốc để sử dụng thiết bị này một cách bình thường"</string>
+    <string name="audit_safemode_notification_details" msgid="1860601176690176413">"Chạm để tìm hiểu thêm."</string>
 </resources>
diff --git a/media/java/android/media/AudioRecordConfiguration.aidl b/core/res/res/values-w426dp-land/integers.xml
similarity index 70%
copy from media/java/android/media/AudioRecordConfiguration.aidl
copy to core/res/res/values-w426dp-land/integers.xml
index afe912b..94abbec 100644
--- a/media/java/android/media/AudioRecordConfiguration.aidl
+++ b/core/res/res/values-w426dp-land/integers.xml
@@ -1,4 +1,7 @@
-/* Copyright 2016, The Android Open Source Project
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2016, The Android Open Source Project
 **
 ** Licensed under the Apache License, Version 2.0 (the "License");
 ** you may not use this file except in compliance with the License.
@@ -12,7 +15,8 @@
 ** See the License for the specific language governing permissions and
 ** limitations under the License.
 */
-
-package android.media;
-
-parcelable AudioRecordConfiguration;
+-->
+<resources>
+    <integer name="date_picker_mode">2</integer>
+    <integer name="time_picker_mode">2</integer>
+</resources>
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index 5324132..8dfbaed 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -229,7 +229,6 @@
     <string name="global_action_voice_assist" msgid="7751191495200504480">"语音助理"</string>
     <string name="global_action_lockdown" msgid="8751542514724332873">"立即锁定"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
-    <string name="notification_children_count_bracketed" msgid="1769425473168347839">"(<xliff:g id="NOTIFICATIONCOUNT">%d</xliff:g> 条)"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"内容已隐藏"</string>
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"内容已隐藏(根据政策规定)"</string>
     <string name="safeMode" msgid="2788228061547930246">"安全模式"</string>
@@ -1052,13 +1051,12 @@
     <string name="usb_notification_message" msgid="7347368030849048437">"触摸以查看更多选项。"</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"已连接到USB调试"</string>
     <string name="adb_active_notification_message" msgid="1016654627626476142">"触摸可停用USB调试。"</string>
+    <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"正在生成错误报告…"</string>
     <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"要分享错误报告吗?"</string>
     <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"正在分享错误报告…"</string>
-    <string name="share_remote_bugreport_notification_message" msgid="752583906074230920">"您的 IT 管理员希望获取错误报告,以便排查此设备的问题。报告可能会透露您设备上的应用和数据,设备运行速度也可能会因此而暂时减慢。"</string>
-    <string name="share_finished_remote_bugreport_notification_message" msgid="4627312060769912353">"您的 IT 管理员希望获取错误报告,以便排查此设备的问题。报告可能会透露您设备上的应用和数据。"</string>
-    <string name="sharing_remote_bugreport_notification_message" msgid="673106383408474893">"这可能会暂时减慢您设备的运行速度"</string>
-    <string name="share_remote_bugreport_notification_accept" msgid="8203856129078669677">"接受"</string>
-    <string name="share_remote_bugreport_notification_decline" msgid="6337969352057443969">"拒绝"</string>
+    <string name="share_remote_bugreport_notification_message_finished" msgid="8610614010660772643">"您的 IT 管理员希望获取错误报告,以便排查此设备的问题。报告可能会透露您设备上的应用和数据。"</string>
+    <string name="share_remote_bugreport_action" msgid="6249476773913384948">"分享"</string>
+    <string name="decline_remote_bugreport_action" msgid="6230987241608770062">"拒绝"</string>
     <string name="select_input_method" msgid="8547250819326693584">"更改键盘"</string>
     <string name="configure_input_methods" msgid="4769971288371946846">"选择键盘"</string>
     <string name="show_ime" msgid="2506087537466597099">"连接到实体键盘时使其在屏幕上保持显示状态"</string>
@@ -1137,8 +1135,9 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"壁纸"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"更改壁纸"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"通知侦听器"</string>
+    <string name="vr_listener_binding_label" msgid="4316591939343607306">"VR 监听器"</string>
     <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"条件提供程序"</string>
-    <string name="notification_assistant_binding_label" msgid="909456055569102952">"通知助手"</string>
+    <string name="notification_ranker_binding_label" msgid="774540592299064747">"通知重要性排序服务"</string>
     <string name="vpn_title" msgid="19615213552042827">"已激活VPN"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"<xliff:g id="APP">%s</xliff:g>已激活VPN"</string>
     <string name="vpn_text" msgid="3011306607126450322">"触摸可管理网络。"</string>
@@ -1333,9 +1332,9 @@
     <string name="kg_text_message_separator" product="default" msgid="4160700433287233771">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="7899202978204438708">"删除"</string>
     <string name="safe_media_volume_warning" product="default" msgid="2276318909314492312">"要将音量调高到推荐水平以上吗?\n\n长时间保持高音量可能会损伤听力。"</string>
-    <string name="continue_to_enable_accessibility" msgid="1626427372316070258">"持续按住双指即可启用无障碍功能。"</string>
-    <string name="accessibility_enabled" msgid="1381972048564547685">"无障碍功能已启用。"</string>
-    <string name="enable_accessibility_canceled" msgid="3833923257966635673">"已取消无障碍功能。"</string>
+    <string name="continue_to_enable_accessibility" msgid="1626427372316070258">"持续按住双指即可启用辅助功能。"</string>
+    <string name="accessibility_enabled" msgid="1381972048564547685">"辅助功能已启用。"</string>
+    <string name="enable_accessibility_canceled" msgid="3833923257966635673">"已取消辅助功能。"</string>
     <string name="user_switched" msgid="3768006783166984410">"当前用户是<xliff:g id="NAME">%1$s</xliff:g>。"</string>
     <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>
@@ -1467,7 +1466,7 @@
     <string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"取消时要求输入PIN码"</string>
     <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"取消时要求绘制解锁图案"</string>
     <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"取消时要求输入密码"</string>
-    <string name="dock_cropped_windows_text" msgid="6378424064779004428">"无法调整该应用的大小,请用双指滚动该应用。"</string>
+    <string name="dock_forced_resizable" msgid="5914261505436217520">"应用可能无法在分屏模式下正常运行。"</string>
     <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"应用不支持分屏。"</string>
     <string name="package_installed_device_owner" msgid="8420696545959087545">"已由管理员安装"</string>
     <string name="package_updated_device_owner" msgid="8856631322440187071">"由您单位的管理员更新"</string>
@@ -1541,7 +1540,7 @@
     <string name="importance_from_person" msgid="9160133597262938296">"这条通知涉及特定的人,因此被归为重要通知。"</string>
     <string name="user_creation_account_exists" msgid="1942606193570143289">"允许<xliff:g id="APP">%1$s</xliff:g>使用 <xliff:g id="ACCOUNT">%2$s</xliff:g> 创建新用户吗?"</string>
     <string name="user_creation_adding" msgid="4482658054622099197">"允许<xliff:g id="APP">%1$s</xliff:g>使用 <xliff:g id="ACCOUNT">%2$s</xliff:g>(目前已有用户使用此帐号)创建新用户吗?"</string>
-    <string name="language_selection_title" msgid="7181332986330337171">"语言偏好设置"</string>
+    <string name="language_selection_title" msgid="2680677278159281088">"添加语言"</string>
     <string name="country_selection_title" msgid="2954859441620215513">"区域偏好设置"</string>
     <string name="search_language_hint" msgid="7042102592055108574">"输入语言名称"</string>
     <string name="language_picker_section_suggested" msgid="8414489646861640885">"建议语言"</string>
@@ -1564,6 +1563,7 @@
     <string name="pin_target" msgid="3052256031352291362">"固定"</string>
     <string name="unpin_target" msgid="3556545602439143442">"取消固定"</string>
     <string name="app_info" msgid="6856026610594615344">"应用信息"</string>
-    <!-- no translation found for negative_duration (5688706061127375131) -->
-    <skip />
+    <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="audit_safemode_notification" msgid="6351827251856877200">"恢复出厂设置即可正常使用此设备"</string>
+    <string name="audit_safemode_notification_details" msgid="1860601176690176413">"触摸即可了解详情。"</string>
 </resources>
diff --git a/core/res/res/values-zh-rHK/strings.xml b/core/res/res/values-zh-rHK/strings.xml
index c80e4ba..c52d843 100644
--- a/core/res/res/values-zh-rHK/strings.xml
+++ b/core/res/res/values-zh-rHK/strings.xml
@@ -229,7 +229,6 @@
     <string name="global_action_voice_assist" msgid="7751191495200504480">"語音助手"</string>
     <string name="global_action_lockdown" msgid="8751542514724332873">"立即鎖定"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
-    <string name="notification_children_count_bracketed" msgid="1769425473168347839">"(<xliff:g id="NOTIFICATIONCOUNT">%d</xliff:g>)"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"內容已隱藏"</string>
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"已根據政策隱藏內容"</string>
     <string name="safeMode" msgid="2788228061547930246">"安全模式"</string>
@@ -1052,13 +1051,12 @@
     <string name="usb_notification_message" msgid="7347368030849048437">"輕觸以瀏覽更多選項。"</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"已連接 USB 偵錯工具"</string>
     <string name="adb_active_notification_message" msgid="1016654627626476142">"輕觸即可停用 USB 偵錯。"</string>
+    <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"正在取得錯誤報告…"</string>
     <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"要分享錯誤報告嗎?"</string>
     <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"正在分享錯誤報告…"</string>
-    <string name="share_remote_bugreport_notification_message" msgid="752583906074230920">"您的 IT 管理員要求您提供錯誤報告,以協助解決此裝置的問題。報告可能包含應用程式和相關資料,裝置的運作速度也可能暫時減慢。"</string>
-    <string name="share_finished_remote_bugreport_notification_message" msgid="4627312060769912353">"您的 IT 管理員要求您提供錯誤報告,以協助解決此裝置的問題。報告可能會披露裝置中的應用程式和相關資料。"</string>
-    <string name="sharing_remote_bugreport_notification_message" msgid="673106383408474893">"裝置的運作速度可能因而減慢"</string>
-    <string name="share_remote_bugreport_notification_accept" msgid="8203856129078669677">"接受"</string>
-    <string name="share_remote_bugreport_notification_decline" msgid="6337969352057443969">"拒絕"</string>
+    <string name="share_remote_bugreport_notification_message_finished" msgid="8610614010660772643">"您的 IT 管理員要求您提供錯誤報告,以協助解決此裝置的問題。報告可能包含應用程式和相關資料。"</string>
+    <string name="share_remote_bugreport_action" msgid="6249476773913384948">"分享"</string>
+    <string name="decline_remote_bugreport_action" msgid="6230987241608770062">"拒絕"</string>
     <string name="select_input_method" msgid="8547250819326693584">"變更鍵盤"</string>
     <string name="configure_input_methods" msgid="4769971288371946846">"選擇鍵盤"</string>
     <string name="show_ime" msgid="2506087537466597099">"在實體鍵盤處於連接狀態時保持顯示"</string>
@@ -1137,8 +1135,9 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"桌布"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"變更桌布"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"通知接聽器"</string>
+    <string name="vr_listener_binding_label" msgid="4316591939343607306">"虛擬現實接聽器"</string>
     <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"條件供應商"</string>
-    <string name="notification_assistant_binding_label" msgid="909456055569102952">"通知小幫手"</string>
+    <string name="notification_ranker_binding_label" msgid="774540592299064747">"通知排序服務"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN 已啟用。"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"<xliff:g id="APP">%s</xliff:g> 已啟用 VPN"</string>
     <string name="vpn_text" msgid="3011306607126450322">"輕觸即可管理網絡。"</string>
@@ -1467,7 +1466,7 @@
     <string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"取消固定時必須輸入 PIN"</string>
     <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"取消固定時必須畫出解鎖圖案"</string>
     <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"取消固定時必須輸入密碼"</string>
-    <string name="dock_cropped_windows_text" msgid="6378424064779004428">"無法調整應用程式的大小,請用兩隻手指捲動此應用程式。"</string>
+    <string name="dock_forced_resizable" msgid="5914261505436217520">"應用程式可能無法在分割畫面中運作。"</string>
     <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"應用程式不支援分割畫面。"</string>
     <string name="package_installed_device_owner" msgid="8420696545959087545">"已由管理員安裝"</string>
     <string name="package_updated_device_owner" msgid="8856631322440187071">"已由您的管理員更新"</string>
@@ -1541,7 +1540,7 @@
     <string name="importance_from_person" msgid="9160133597262938296">"列為重要的原因:涉及的人。"</string>
     <string name="user_creation_account_exists" msgid="1942606193570143289">"要允許 <xliff:g id="APP">%1$s</xliff:g> 使用 <xliff:g id="ACCOUNT">%2$s</xliff:g> 建立新使用者嗎?"</string>
     <string name="user_creation_adding" msgid="4482658054622099197">"要允許 <xliff:g id="APP">%1$s</xliff:g> 使用 <xliff:g id="ACCOUNT">%2$s</xliff:g> 建立新使用者 (此帳戶目前已有此使用者) 嗎?"</string>
-    <string name="language_selection_title" msgid="7181332986330337171">"語言偏好設定"</string>
+    <string name="language_selection_title" msgid="2680677278159281088">"新增語言"</string>
     <string name="country_selection_title" msgid="2954859441620215513">"地區偏好設定"</string>
     <string name="search_language_hint" msgid="7042102592055108574">"輸入語言名稱"</string>
     <string name="language_picker_section_suggested" msgid="8414489646861640885">"推薦"</string>
@@ -1565,4 +1564,6 @@
     <string name="unpin_target" msgid="3556545602439143442">"取消固定"</string>
     <string name="app_info" msgid="6856026610594615344">"應用程式資料"</string>
     <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="audit_safemode_notification" msgid="6351827251856877200">"將此裝置回復至原廠設定,方可正常使用"</string>
+    <string name="audit_safemode_notification_details" msgid="1860601176690176413">"輕觸以瞭解詳情。"</string>
 </resources>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index ba49232..8ff0fed 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -229,7 +229,6 @@
     <string name="global_action_voice_assist" msgid="7751191495200504480">"語音小幫手"</string>
     <string name="global_action_lockdown" msgid="8751542514724332873">"立即鎖定"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"超過 999"</string>
-    <string name="notification_children_count_bracketed" msgid="1769425473168347839">"(<xliff:g id="NOTIFICATIONCOUNT">%d</xliff:g>)"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"內容已隱藏"</string>
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"內容已依據政策隱藏"</string>
     <string name="safeMode" msgid="2788228061547930246">"安全模式"</string>
@@ -1052,13 +1051,12 @@
     <string name="usb_notification_message" msgid="7347368030849048437">"輕觸即可顯示更多選項。"</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"已連接 USB 偵錯工具"</string>
     <string name="adb_active_notification_message" msgid="1016654627626476142">"輕觸即可停用 USB 偵錯。"</string>
+    <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"正在接收錯誤報告…"</string>
     <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"要分享錯誤報告嗎?"</string>
     <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"正在分享錯誤報告…"</string>
-    <string name="share_remote_bugreport_notification_message" msgid="752583906074230920">"您的 IT 管理員要求您提供錯誤報告,以便排解這個裝置發生的問題。報告可能會揭露裝置中的應用程式和相關資料,裝置運行速度也可能會因此暫時減慢。"</string>
-    <string name="share_finished_remote_bugreport_notification_message" msgid="4627312060769912353">"您的 IT 管理員要求您提供錯誤報告,以便排解這個裝置發生的問題。報告可能會揭露裝置中的應用程式和相關資料。"</string>
-    <string name="sharing_remote_bugreport_notification_message" msgid="673106383408474893">"這可能會暫時減慢裝置運行速度"</string>
-    <string name="share_remote_bugreport_notification_accept" msgid="8203856129078669677">"接受"</string>
-    <string name="share_remote_bugreport_notification_decline" msgid="6337969352057443969">"拒絕"</string>
+    <string name="share_remote_bugreport_notification_message_finished" msgid="8610614010660772643">"您的 IT 管理員要求您提供錯誤報告,以便排解這個裝置發生的問題。報告可能會揭露裝置中的應用程式和相關資料。"</string>
+    <string name="share_remote_bugreport_action" msgid="6249476773913384948">"分享"</string>
+    <string name="decline_remote_bugreport_action" msgid="6230987241608770062">"拒絕"</string>
     <string name="select_input_method" msgid="8547250819326693584">"變更鍵盤"</string>
     <string name="configure_input_methods" msgid="4769971288371946846">"選擇鍵盤"</string>
     <string name="show_ime" msgid="2506087537466597099">"有連接的實體鍵盤時保持顯示"</string>
@@ -1137,8 +1135,9 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"桌布"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"變更桌布"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"通知接聽器"</string>
+    <string name="vr_listener_binding_label" msgid="4316591939343607306">"VR 接聽器"</string>
     <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"條件提供者"</string>
-    <string name="notification_assistant_binding_label" msgid="909456055569102952">"通知小幫手"</string>
+    <string name="notification_ranker_binding_label" msgid="774540592299064747">"通知重要性排序服務"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN 已啟用"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"<xliff:g id="APP">%s</xliff:g> 已啟用 VPN"</string>
     <string name="vpn_text" msgid="3011306607126450322">"輕觸即可管理網路。"</string>
@@ -1467,7 +1466,7 @@
     <string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"取消固定時必須輸入 PIN"</string>
     <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"取消固定時必須畫出解鎖圖案"</string>
     <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"取消固定時必須輸入密碼"</string>
-    <string name="dock_cropped_windows_text" msgid="6378424064779004428">"無法調整這個應用程式的大小,請用雙指捲動該應用程式。"</string>
+    <string name="dock_forced_resizable" msgid="5914261505436217520">"應用程式可能無法在分割畫面中運作。"</string>
     <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"這個應用程式不支援分割畫面。"</string>
     <string name="package_installed_device_owner" msgid="8420696545959087545">"已由管理員安裝"</string>
     <string name="package_updated_device_owner" msgid="8856631322440187071">"由您的管理員更新"</string>
@@ -1541,7 +1540,7 @@
     <string name="importance_from_person" msgid="9160133597262938296">"這則通知涉及特定人士,因此被歸為重要通知。"</string>
     <string name="user_creation_account_exists" msgid="1942606193570143289">"要允許 <xliff:g id="APP">%1$s</xliff:g> 為 <xliff:g id="ACCOUNT">%2$s</xliff:g> 建立新使用者嗎?"</string>
     <string name="user_creation_adding" msgid="4482658054622099197">"要允許 <xliff:g id="APP">%1$s</xliff:g> 為 <xliff:g id="ACCOUNT">%2$s</xliff:g> 建立新使用者嗎 (這個帳戶目前已有使用者)?"</string>
-    <string name="language_selection_title" msgid="7181332986330337171">"語言偏好設定"</string>
+    <string name="language_selection_title" msgid="2680677278159281088">"新增語言"</string>
     <string name="country_selection_title" msgid="2954859441620215513">"地區偏好設定"</string>
     <string name="search_language_hint" msgid="7042102592055108574">"請輸入語言名稱"</string>
     <string name="language_picker_section_suggested" msgid="8414489646861640885">"建議語言"</string>
@@ -1565,4 +1564,6 @@
     <string name="unpin_target" msgid="3556545602439143442">"取消固定"</string>
     <string name="app_info" msgid="6856026610594615344">"應用程式資訊"</string>
     <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="audit_safemode_notification" msgid="6351827251856877200">"恢復原廠設定即可正常使用這個裝置"</string>
+    <string name="audit_safemode_notification_details" msgid="1860601176690176413">"輕觸即可瞭解詳情。"</string>
 </resources>
diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml
index 22d167d..fe2c8a6 100644
--- a/core/res/res/values-zu/strings.xml
+++ b/core/res/res/values-zu/strings.xml
@@ -229,7 +229,6 @@
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Isisekeli sezwi"</string>
     <string name="global_action_lockdown" msgid="8751542514724332873">"Khiya manje"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
-    <string name="notification_children_count_bracketed" msgid="1769425473168347839">"(<xliff:g id="NOTIFICATIONCOUNT">%d</xliff:g>)"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"Okuqukethwe kufihliwe"</string>
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Okuqukethwe kufihlwe inqubomgomo"</string>
     <string name="safeMode" msgid="2788228061547930246">"Imodi ephephile"</string>
@@ -1052,13 +1051,12 @@
     <string name="usb_notification_message" msgid="7347368030849048437">"Thinta ukuze uthole ezinye izinketho."</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"Ukulungisa iphutha le-USB kuxhunyiwe"</string>
     <string name="adb_active_notification_message" msgid="1016654627626476142">"Thinta ukwenza ukuthi ukudibhaga kwe-USB kungasebenzi."</string>
+    <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Ithatha umbiko wesiphazamisi..."</string>
     <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Yabelana ngombiko wesiphazamisi?"</string>
     <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Yabelana ngombiko wesiphazamisi..."</string>
-    <string name="share_remote_bugreport_notification_message" msgid="752583906074230920">"Umlawuli wakho we-IT ucele umbiko wesiphazamisi ukusiza ukuxazulula inkinga yale divayisi. Izinhlelo zokusebenza zingabelwana futhi idivayisi yakho ingahle yehle kancane."</string>
-    <string name="share_finished_remote_bugreport_notification_message" msgid="4627312060769912353">"Umqondisi wakho we-IT ucele umbiko wesiphazamisi ukukusiza ukuxazulula inkinga kule divayisi. Izinhlelo zokusebenza nedatha ingabiwa."</string>
-    <string name="sharing_remote_bugreport_notification_message" msgid="673106383408474893">"Lokhu kungahambisa kancane idivayisi yakho okwesikhashana"</string>
-    <string name="share_remote_bugreport_notification_accept" msgid="8203856129078669677">"YAMUKELA"</string>
-    <string name="share_remote_bugreport_notification_decline" msgid="6337969352057443969">"YENQABA"</string>
+    <string name="share_remote_bugreport_notification_message_finished" msgid="8610614010660772643">"Umqondisi wakho we-IT ucele umbiko wesiphazamisi ukukusiza ukuxazulula inkinga kule divayisi. Izinhlelo zokusebenza nedatha ingabiwa."</string>
+    <string name="share_remote_bugreport_action" msgid="6249476773913384948">"YABELANA"</string>
+    <string name="decline_remote_bugreport_action" msgid="6230987241608770062">"YENQABA"</string>
     <string name="select_input_method" msgid="8547250819326693584">"Shintsha ikhibhodi"</string>
     <string name="configure_input_methods" msgid="4769971288371946846">"Khetha amakhibhodi"</string>
     <string name="show_ime" msgid="2506087537466597099">"Yigcine kusikrini ngenkathi kusebenza ikhibhodi ephathekayo"</string>
@@ -1137,8 +1135,9 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Iphephadonga"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Shintsha iphephadonga"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Umlaleli wesaziso"</string>
+    <string name="vr_listener_binding_label" msgid="4316591939343607306">"Isilaleli se-VR"</string>
     <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Umhlinzeki wesimo"</string>
-    <string name="notification_assistant_binding_label" msgid="909456055569102952">"Umsizi wesaziso"</string>
+    <string name="notification_ranker_binding_label" msgid="774540592299064747">"Isevisi yesilinganisi sesaziso"</string>
     <string name="vpn_title" msgid="19615213552042827">"I-VPN isiyasebenza"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"i-VPN ivuswe ngu <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Thinta ukuze wengamele inethiwekhi."</string>
@@ -1467,7 +1466,7 @@
     <string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Cela iphinikhodi ngaphambi kokuphina"</string>
     <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Cela iphethini yokuvula ngaphambi kokususa ukuphina"</string>
     <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Cela iphasiwedi ngaphambi kokususa ukuphina"</string>
-    <string name="dock_cropped_windows_text" msgid="6378424064779004428">"Uhlelo lokusebenza alukwazi ukunikezwa usayizi omusha, liskrole ngeminwe emibili."</string>
+    <string name="dock_forced_resizable" msgid="5914261505436217520">"Izinhlelo zokusebenza kungenzeka zingasebenzi ngesikrini esihlukanisiwe."</string>
     <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"Uhlelo lokusebenza alusekeli isikrini esihlukanisiwe."</string>
     <string name="package_installed_device_owner" msgid="8420696545959087545">"Ifakwe ngumlawuli wakho"</string>
     <string name="package_updated_device_owner" msgid="8856631322440187071">"Ibuyekezwe ngumqondisi wakho"</string>
@@ -1541,7 +1540,7 @@
     <string name="importance_from_person" msgid="9160133597262938296">"Lokhu kubalulekile ngenxa yabantu ababandakanyekayo."</string>
     <string name="user_creation_account_exists" msgid="1942606193570143289">"Vumela i-<xliff:g id="APP">%1$s</xliff:g> ukudala umsebenzisi omusha nge-<xliff:g id="ACCOUNT">%2$s</xliff:g> ?"</string>
     <string name="user_creation_adding" msgid="4482658054622099197">"Vumela i-<xliff:g id="APP">%1$s</xliff:g> ukudala umsebenzisi omusha nge-<xliff:g id="ACCOUNT">%2$s</xliff:g> (umsebenzisi onale akhawunti usuvel ukhona) ?"</string>
-    <string name="language_selection_title" msgid="7181332986330337171">"Okuncamelayo kolimi"</string>
+    <string name="language_selection_title" msgid="2680677278159281088">"Engeza ulwimi"</string>
     <string name="country_selection_title" msgid="2954859441620215513">"Okuncamelayo kwesifunda"</string>
     <string name="search_language_hint" msgid="7042102592055108574">"Thayipha igama lolimi"</string>
     <string name="language_picker_section_suggested" msgid="8414489646861640885">"Okuphakanyisiwe"</string>
@@ -1564,6 +1563,7 @@
     <string name="pin_target" msgid="3052256031352291362">"Phina"</string>
     <string name="unpin_target" msgid="3556545602439143442">"Susa ukuphina"</string>
     <string name="app_info" msgid="6856026610594615344">"Ulwazi lohlelo lokusebenza"</string>
-    <!-- no translation found for negative_duration (5688706061127375131) -->
-    <skip />
+    <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="audit_safemode_notification" msgid="6351827251856877200">"Setha kabusha ngokwefekthri ukuze usebenzise le divayisi ngokuvamile"</string>
+    <string name="audit_safemode_notification_details" msgid="1860601176690176413">"Thinta ukuze ufunde kabanzi."</string>
 </resources>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 7c02128..50c7bfb 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -593,6 +593,9 @@
              the appearance matches the branding of the app requesting the fingerprint scan.-->
         <attr name="fingerprintAuthDrawable" format="reference" />
 
+	<!-- Asset that should be used to show users the position of the NFC antenna on the device. -->
+	<attr name="nfcAntennaPositionDrawable" format="reference" />
+
         <!-- ============ -->
         <!-- Panel styles -->
         <!-- ============ -->
@@ -8170,6 +8173,8 @@
              Defined in same coordinates as the path itself -->
         <attr name="endY" format="float" />
 
+        <!-- Defines the tile mode of the gradient. SweepGradient don't support tiling. -->
+        <attr name="tileMode"/>
     </declare-styleable>
 
     <!-- Describes an item of a GradientColor. Minimally need 2 items to define the gradient
@@ -8189,11 +8194,8 @@
         <!-- @hide From Theme.colorPrimary, used for the TaskDescription primary 
                    color. -->
         <attr name="colorPrimary" />
-        <!-- @hide From Theme.windowBackground, used for calculating the 
-                   TaskDescription background color. -->
-        <attr name="windowBackground" />
-        <!-- @hide From Theme.windowBackgroundFallback, used for calculating the 
-                   TaskDescription background color. -->
-        <attr name="windowBackgroundFallback" />
+        <!-- @hide From Theme.colorBackground, used for the TaskDescription background 
+                   color. -->
+        <attr name="colorBackground" />
     </declare-styleable>
 </resources>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 9552820..ce5d07c 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -443,6 +443,9 @@
     <!-- Boolean indicating whether or not wifi firmware debugging is enabled -->
     <bool translatable="false" name="config_wifi_enable_wifi_firmware_debugging">true</bool>
 
+    <!-- Integer size limit, in KB, for a single WifiLogger ringbuffer -->
+    <integer translatable="false" name="config_wifi_logger_ring_buffer_size_limit_kb">32</integer>
+
     <!-- Boolean indicating whether or not wifi should turn off when emergency call is made -->
     <bool translatable="false" name="config_wifi_turn_off_during_emergency_call">false</bool>
 
@@ -2437,6 +2440,14 @@
          flag). -->
     <bool name="config_forceWindowDrawsStatusBarBackground">true</bool>
 
+    <!-- Controls the opacity of the navigation bar depending on the visibility of the
+         various workspace stacks.
+         0 - Nav bar is always opaque when either the freeform stack or docked stack is visible.
+         1 - Nav bar is always translucent when the freeform stack is visible, otherwise always
+         opaque.
+         -->
+    <integer name="config_navBarOpacityMode">0</integer>
+
     <!-- Default bounds [left top right bottom] on screen for picture-in-picture windows. -->
     <string translatable="false" name="config_defaultPictureInPictureBounds">"0 0 100 100"</string>
 
@@ -2474,4 +2485,13 @@
          much in the way of user data.
     -->
     <bool name="config_strongAuthRequiredOnBoot">true</bool>
+
+    <!-- Wallpaper cropper package. Used as the default cropper if the active launcher doesn't
+         handle wallpaper cropping.
+    -->
+    <string name="config_wallpaperCropperPackage" translatable="false">com.android.wallpapercropper</string>
+
+    <!-- True if the device supports at least one form of multi-window.
+         E.g. freeform, split-screen, picture-in-picture. -->
+    <bool name="config_supportsMultiWindow">true</bool>
 </resources>
diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml
index 1005704..081d613 100644
--- a/core/res/res/values/dimens.xml
+++ b/core/res/res/values/dimens.xml
@@ -151,16 +151,13 @@
     <dimen name="notification_content_picture_margin">56dp</dimen>
 
     <!-- height of the content margin to accomodate for the header -->
-    <dimen name="notification_content_margin_top">30dp</dimen>
+    <dimen name="notification_content_margin_top">37.5dp</dimen>
 
     <!-- height of the content margin on the bottom -->
-    <dimen name="notification_content_margin_bottom">13dp</dimen>
-
-    <!-- height of notification header view if present -->
-    <dimen name="notification_header_height">32dp</dimen>
+    <dimen name="notification_content_margin_bottom">16dp</dimen>
 
     <!-- Height of a small notification in the status bar -->
-    <dimen name="notification_min_height">84dp</dimen>
+    <dimen name="notification_min_height">92dp</dimen>
 
     <!-- The width of the big icons in notifications. -->
     <dimen name="notification_large_icon_width">64dp</dimen>
@@ -177,7 +174,7 @@
     <dimen name="media_notification_expanded_image_max_size">94dp</dimen>
 
     <!-- The maximum size of the image in the expanded media notification -->
-    <dimen name="media_notification_expanded_image_margin_bottom">16dp</dimen>
+    <dimen name="media_notification_expanded_image_margin_bottom">20dp</dimen>
 
     <!-- The margin of the content to an image-->
     <dimen name="notification_content_image_margin_end">8dp</dimen>
@@ -268,7 +265,7 @@
     <!-- Size of notification text (see TextAppearance.StatusBar.EventContent) -->
     <dimen name="notification_text_size">14sp</dimen>
     <!-- Size of notification text titles (see TextAppearance.StatusBar.EventContent.Title) -->
-    <dimen name="notification_title_text_size">16sp</dimen>
+    <dimen name="notification_title_text_size">14sp</dimen>
     <!-- Size of smaller notification text (see TextAppearance.StatusBar.EventContent.Line2, Info, Time) -->
     <dimen name="notification_subtext_size">12sp</dimen>
 
diff --git a/core/res/res/values/integers.xml b/core/res/res/values/integers.xml
index 8e27226..8f8d59e 100644
--- a/core/res/res/values/integers.xml
+++ b/core/res/res/values/integers.xml
@@ -23,4 +23,7 @@
     <integer name="button_pressed_animation_delay">100</integer>
     <integer name="disabled_alpha_animation_duration">100</integer>
     <integer name="dock_enter_exit_duration">250</integer>
+
+    <integer name="date_picker_mode">1</integer>
+    <integer name="time_picker_mode">1</integer>
 </resources>
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 06e2248..2b0ef42 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2705,6 +2705,7 @@
     <public type="attr" name="countDown" />
     <public type="attr" name="canRecord" />
     <public type="attr" name="tunerCount" />
+    <public type="attr" name="nfcAntennaPositionDrawable" />
 
     <public type="style" name="Theme.Material.Light.DialogWhenLarge.DarkActionBar" />
     <public type="style" name="Widget.Material.SeekBar.Discrete" />
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 7b11302..17afd92 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -548,9 +548,6 @@
          [CHAR LIMIT=4] -->
     <string name="status_bar_notification_info_overflow">999+</string>
 
-    <!-- The number of notifications in the notification header. An example would be (2) or (12) -->
-    <string name="notification_children_count_bracketed">(<xliff:g id="notificationCount" example="1">%d</xliff:g>)</string>
-
     <!-- The divider symbol between different parts of the notification header. not translatable [CHAR LIMIT=1] -->
     <string name="notification_header_divider_symbol" translatable="false">•</string>
 
@@ -2917,20 +2914,18 @@
     <!-- Message of notification shown when ADB is actively connected to the phone. -->
     <string name="adb_active_notification_message">Touch to disable USB debugging.</string>
 
+    <!-- Title of notification shown to indicate that bug report is being collected. -->
+    <string name="taking_remote_bugreport_notification_title">Taking bug report\u2026</string>
     <!-- Title of notification shown to ask for user consent for sharing a bugreport that was requested remotely by the IT administrator. -->
     <string name="share_remote_bugreport_notification_title">Share bug report?</string>
     <!-- Title of notification shown to indicate that bug report is still being collected after sharing was accepted. -->
     <string name="sharing_remote_bugreport_notification_title">Sharing bug report\u2026</string>
-    <!-- Message of notification shown to ask for user consent for sharing a bugreport that was requested remotely by the IT administrator. -->
-    <string name="share_remote_bugreport_notification_message">Your IT admin requested a bug report to help troubleshoot this device. Apps and data may be shared and your device may temporarily slow down.</string>
-    <!-- Message of notification shown to ask for user consent for sharing a bugreport that was requested remotely by the IT administrator. -->
-    <string name="share_finished_remote_bugreport_notification_message">Your IT admin requested a bug report to help troubleshoot this device. Apps and data may be shared.</string>
-    <!-- Message of notification shown to shown to indicate that bug report is still being collected after sharing was accepted. -->
-    <string name="sharing_remote_bugreport_notification_message">This may temporarily slow down your device</string>
+    <!-- Message of a notification shown to ask for user consent for sharing a bugreport that was requested remotely by the IT administrator. -->
+    <string name="share_remote_bugreport_notification_message_finished">Your IT admin requested a bug report to help troubleshoot this device. Apps and data may be shared.</string>
     <!-- Acceptance label of notification shown to ask for user consent for sharing the remote bugreport. -->
-    <string name="share_remote_bugreport_notification_accept">ACCEPT</string>
+    <string name="share_remote_bugreport_action">SHARE</string>
     <!-- Decline label of notification shown to ask for user consent for sharing the remote bugreport. -->
-    <string name="share_remote_bugreport_notification_decline">DECLINE</string>
+    <string name="decline_remote_bugreport_action">DECLINE</string>
 
     <!-- Used to replace %s in urls retreived from the signin server with locales.  For Some        -->
     <!-- devices we don't support all the locales we ship to and need to replace the '%s' with a    -->
@@ -3137,11 +3132,13 @@
     <!-- Label to show for a service that is running because it is observing
          the user's notifications. -->
     <string name="notification_listener_binding_label">Notification listener</string>
+    <!-- Label to show for a service that is running because the system is in VR mode. -->
+    <string name="vr_listener_binding_label">VR listener</string>
     <!-- Label to show for a service that is running because it is providing conditions. -->
     <string name="condition_provider_service_binding_label">Condition provider</string>
     <!-- Label to show for a service that is running because it is observing and modifying the
          importance of the user's notifications. -->
-    <string name="notification_assistant_binding_label">Notification assistant</string>
+    <string name="notification_ranker_binding_label">Notification ranker service</string>
 
     <!-- Do Not Translate: Alternate eri.xml -->
     <string name="alternate_eri_file">/data/eri.xml</string>
@@ -4231,4 +4228,9 @@
     <!-- The representation of a time duration when negative. An example is -1:14. This can be used with a countdown timer for example.-->
     <string name="negative_duration">\u2212<xliff:g id="time" example="1:14">%1$s</xliff:g></string>
 
+    <!-- Title of notification shown when device has been forced to safe mode after a security compromise. -->
+    <string name="audit_safemode_notification">Factory reset to use this device normally</string>
+    <!-- Description of notification shown when device has been forced to safe mode after a security compromise. -->
+    <string name="audit_safemode_notification_details">Touch to learn more.</string>
+
 </resources>
diff --git a/core/res/res/values/styles_material.xml b/core/res/res/values/styles_material.xml
index db418f7..a65a813 100644
--- a/core/res/res/values/styles_material.xml
+++ b/core/res/res/values/styles_material.xml
@@ -652,7 +652,7 @@
     </style>
 
     <style name="Widget.Material.TimePicker">
-        <item name="timePickerMode">clock</item>
+        <item name="timePickerMode">@integer/time_picker_mode</item>
         <item name="legacyLayout">@layout/time_picker_legacy_material</item>
         <!-- Attributes for new-style TimePicker. -->
         <item name="internalLayout">@layout/time_picker_material</item>
@@ -666,7 +666,7 @@
     </style>
 
     <style name="Widget.Material.DatePicker">
-        <item name="datePickerMode">calendar</item>
+        <item name="datePickerMode">@integer/date_picker_mode</item>
         <item name="legacyLayout">@layout/date_picker_legacy_holo</item>
         <item name="calendarViewShown">true</item>
         <!-- Attributes for new-style DatePicker. -->
@@ -993,8 +993,7 @@
     </style>
 
     <style name="Widget.Material.SuggestionItem" parent="@android:style/TextAppearance.Material.Body1">
-        <item name="alpha">.87</item>
-        <item name="textColor">@color/black</item>
+        <item name="textColor">#8a000000</item>  <!-- alpha=.54, textColor=@color/black -->
         <item name="drawablePadding">8dip</item>
         <item name="gravity">start|center_vertical</item>
         <item name="layout_gravity">start|center_vertical</item>
@@ -1009,12 +1008,11 @@
     </style>
 
     <style name="TextAppearance.Material.TextSuggestionHighlight" parent="Widget.Material.SuggestionItem">
-        <item name="textColor">#009688</item>
+        <item name="textColor">#de000000</item>  <!-- alpha=.87, textColor=@color/black -->
     </style>
 
     <style name="Widget.Material.SuggestionButton" parent="@android:style/TextAppearance.Material.Button">
-        <item name="alpha">.87</item>
-        <item name="textColor">#009688</item>
+        <item name="textColor">#de009688</item>  <!-- alpha=.87, textColor=#009688 -->
         <item name="drawablePadding">8dip</item>
         <item name="gravity">start|center_vertical</item>
         <item name="layout_gravity">start|center_vertical</item>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index ff247b5..70f4f54 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -298,11 +298,13 @@
   <java-symbol type="bool" name="config_wifi_enable_5GHz_preference" />
   <java-symbol type="bool" name="config_wifi_revert_country_code_on_cellular_loss" />
   <java-symbol type="bool" name="config_wifi_enable_wifi_firmware_debugging" />
+  <java-symbol type="integer" name="config_wifi_logger_ring_buffer_size_limit_kb" />
   <java-symbol type="bool" name="config_wifi_turn_off_during_emergency_call" />
   <java-symbol type="bool" name="config_supportMicNearUltrasound" />
   <java-symbol type="bool" name="config_supportSpeakerNearUltrasound" />
   <java-symbol type="bool" name="config_supportAudioSourceUnprocessed" />
   <java-symbol type="bool" name="config_freeformWindowManagement" />
+  <java-symbol type="bool" name="config_supportsMultiWindow" />
   <java-symbol type="bool" name="config_guestUserEphemeral" />
   <java-symbol type="string" name="config_defaultPictureInPictureBounds" />
   <java-symbol type="string" name="config_centeredPictureInPictureBounds" />
@@ -1769,13 +1771,12 @@
   <java-symbol type="string" name="accessibility_binding_label" />
   <java-symbol type="string" name="adb_active_notification_message" />
   <java-symbol type="string" name="adb_active_notification_title" />
+  <java-symbol type="string" name="taking_remote_bugreport_notification_title" />
   <java-symbol type="string" name="share_remote_bugreport_notification_title" />
-  <java-symbol type="string" name="share_remote_bugreport_notification_message" />
-  <java-symbol type="string" name="share_finished_remote_bugreport_notification_message" />
   <java-symbol type="string" name="sharing_remote_bugreport_notification_title" />
-  <java-symbol type="string" name="sharing_remote_bugreport_notification_message" />
-  <java-symbol type="string" name="share_remote_bugreport_notification_accept" />
-  <java-symbol type="string" name="share_remote_bugreport_notification_decline" />
+  <java-symbol type="string" name="share_remote_bugreport_notification_message_finished" />
+  <java-symbol type="string" name="share_remote_bugreport_action" />
+  <java-symbol type="string" name="decline_remote_bugreport_action" />
   <java-symbol type="string" name="aerr_application" />
   <java-symbol type="string" name="aerr_process" />
   <java-symbol type="string" name="aerr_application_repeated" />
@@ -1841,8 +1842,9 @@
   <java-symbol type="string" name="low_internal_storage_view_text_no_boot" />
   <java-symbol type="string" name="low_internal_storage_view_title" />
   <java-symbol type="string" name="notification_listener_binding_label" />
+  <java-symbol type="string" name="vr_listener_binding_label" />
   <java-symbol type="string" name="condition_provider_service_binding_label" />
-  <java-symbol type="string" name="notification_assistant_binding_label" />
+  <java-symbol type="string" name="notification_ranker_binding_label" />
   <java-symbol type="string" name="report" />
   <java-symbol type="string" name="select_input_method" />
   <java-symbol type="string" name="select_keyboard_layout_notification_title" />
@@ -1893,6 +1895,8 @@
   <java-symbol type="string" name="config_customVpnConfirmDialogComponent" />
   <java-symbol type="string" name="config_defaultNetworkScorerPackageName" />
   <java-symbol type="string" name="config_persistentDataPackageName" />
+  <java-symbol type="string" name="audit_safemode_notification" />
+  <java-symbol type="string" name="audit_safemode_notification_details" />
 
   <java-symbol type="layout" name="resolver_list" />
   <java-symbol type="id" name="resolver_list" />
@@ -2390,6 +2394,7 @@
 
   <java-symbol type="string" name="config_packagedKeyboardName" />
   <java-symbol type="bool" name="config_forceWindowDrawsStatusBarBackground" />
+  <java-symbol type="integer" name="config_navBarOpacityMode" />
   <java-symbol type="color" name="system_bar_background_semi_transparent" />
 
   <!-- EditText suggestion popup. -->
@@ -2403,11 +2408,9 @@
   <java-symbol type="id" name="notification_material_reply_text_2" />
   <java-symbol type="id" name="notification_material_reply_text_3" />
 
-  <java-symbol type="string" name="notification_children_count_bracketed" />
   <java-symbol type="string" name="notification_hidden_text" />
   <java-symbol type="string" name="notification_hidden_by_policy_text" />
   <java-symbol type="id" name="app_name_text" />
-  <java-symbol type="id" name="number_of_children" />
   <java-symbol type="id" name="header_sub_text" />
   <java-symbol type="id" name="expand_button" />
   <java-symbol type="id" name="notification_header" />
@@ -2420,19 +2423,20 @@
   <java-symbol type="drawable" name="ic_collapse_notification" />
   <java-symbol type="drawable" name="ic_expand_bundle" />
   <java-symbol type="drawable" name="ic_collapse_bundle" />
-  <java-symbol type="dimen" name="notification_header_height" />
   <java-symbol type="dimen" name="notification_min_content_height" />
   <java-symbol type="dimen" name="notification_header_shrink_min_width" />
   <java-symbol type="dimen" name="notification_content_margin_start" />
   <java-symbol type="dimen" name="notification_content_margin_end" />
   <java-symbol type="dimen" name="notification_content_picture_margin" />
   <java-symbol type="dimen" name="notification_content_margin_top" />
+  <java-symbol type="dimen" name="notification_content_margin_bottom" />
   <java-symbol type="string" name="importance_from_user" />
   <java-symbol type="string" name="importance_from_person" />
 
   <java-symbol type="layout" name="work_widget_mask_view" />
+  <java-symbol type="id" name="work_widget_mask_frame" />
   <java-symbol type="id" name="work_widget_app_icon" />
-  <java-symbol type="drawable" name="work_widget_mask_view_background" />
+  <java-symbol type="id" name="work_widget_badge_icon" />
 
   <java-symbol type="id" name="aerr_report" />
   <java-symbol type="id" name="aerr_reset" />
@@ -2541,4 +2545,7 @@
   <java-symbol type="string" name="carrier_app_notification_title" />
   <java-symbol type="string" name="carrier_app_notification_text" />
   <java-symbol type="string" name="negative_duration" />
+
+  <!-- WallpaperManager config -->
+  <java-symbol type="string" name="config_wallpaperCropperPackage" />
 </resources>
diff --git a/core/res/res/values/themes_device_defaults.xml b/core/res/res/values/themes_device_defaults.xml
index dd8baa7..11bb106 100644
--- a/core/res/res/values/themes_device_defaults.xml
+++ b/core/res/res/values/themes_device_defaults.xml
@@ -544,9 +544,7 @@
         <item name="windowNoTitle">true</item>
         <item name="windowBackground">@color/transparent</item>
         <item name="backgroundDimEnabled">true</item>
-        <item name="windowTranslucentStatus">false</item>
-        <item name="windowTranslucentNavigation">false</item>
-        <item name="windowDrawsSystemBarBackgrounds">false</item>
+        <item name="statusBarColor">@color/transparent</item>
         <item name="windowContentOverlay">@null</item>
         <item name="colorControlActivated">?attr/colorControlHighlight</item>
         <item name="listPreferredItemPaddingStart">?attr/dialogPreferredPadding</item>
diff --git a/core/res/res/values/themes_micro.xml b/core/res/res/values/themes_micro.xml
index 8bf635e..478d66c 100644
--- a/core/res/res/values/themes_micro.xml
+++ b/core/res/res/values/themes_micro.xml
@@ -24,7 +24,6 @@
         <item name="windowBackground">@color/black</item>
         <item name="windowContentOverlay">@null</item>
         <item name="windowIsFloating">false</item>
-        <item name="windowSwipeToDismiss">true</item>
         <!-- Required to force windowInsets dispatch through application UI. -->
         <item name="windowOverscan">true</item>
     </style>
@@ -42,7 +41,6 @@
         <item name="windowBackground">@color/white</item>
         <item name="windowContentOverlay">@null</item>
         <item name="windowIsFloating">false</item>
-        <item name="windowSwipeToDismiss">true</item>
         <!-- Required to force windowInsets dispatch through application UI. -->
         <item name="windowOverscan">true</item>
     </style>
diff --git a/core/tests/coretests/src/android/animation/ValueAnimatorTests.java b/core/tests/coretests/src/android/animation/ValueAnimatorTests.java
index aa21b1d..b908d92 100644
--- a/core/tests/coretests/src/android/animation/ValueAnimatorTests.java
+++ b/core/tests/coretests/src/android/animation/ValueAnimatorTests.java
@@ -328,7 +328,12 @@
         // Only a1's pause listener should be called.
         assertTrue(l1.pauseCalled);
         assertFalse(l1.resumeCalled);
-        a1.resume();
+        runTestOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                a1.resume();
+            }
+        });
 
         Thread.sleep(a1.getTotalDuration());
 
diff --git a/core/tests/coretests/src/android/app/DownloadManagerBaseTest.java b/core/tests/coretests/src/android/app/DownloadManagerBaseTest.java
index af2a944..bae4ecc 100644
--- a/core/tests/coretests/src/android/app/DownloadManagerBaseTest.java
+++ b/core/tests/coretests/src/android/app/DownloadManagerBaseTest.java
@@ -81,8 +81,7 @@
     protected static final int DEFAULT_WAIT_POLL_TIME = 5 * 1000;  // 5 seconds
 
     protected static final int WAIT_FOR_DOWNLOAD_POLL_TIME = 1 * 1000;  // 1 second
-    protected static final int MAX_WAIT_FOR_DOWNLOAD_TIME = 5 * 60 * 1000; // 5 minutes
-    protected static final int MAX_WAIT_FOR_LARGE_DOWNLOAD_TIME = 15 * 60 * 1000; // 15 minutes
+    protected static final int MAX_WAIT_FOR_DOWNLOAD_TIME = 30 * 1000; // 30 seconds
 
     protected static final int DOWNLOAD_TO_SYSTEM_CACHE = 1;
     protected static final int DOWNLOAD_TO_DOWNLOAD_CACHE_DIR = 2;
@@ -970,7 +969,7 @@
     protected void verifyInt(Cursor cursor, String columnName, int expected) {
         int index = cursor.getColumnIndex(columnName);
         int actual = cursor.getInt(index);
-        assertEquals(expected, actual);
+        assertEquals(String.format("Expected = %d : Actual = %d", expected, actual), expected, actual);
     }
 
     /**
diff --git a/core/tests/coretests/src/android/app/DownloadManagerFunctionalTest.java b/core/tests/coretests/src/android/app/DownloadManagerFunctionalTest.java
index 7019980..4a53852 100644
--- a/core/tests/coretests/src/android/app/DownloadManagerFunctionalTest.java
+++ b/core/tests/coretests/src/android/app/DownloadManagerFunctionalTest.java
@@ -23,18 +23,16 @@
 import android.os.Environment;
 import android.os.ParcelFileDescriptor;
 import android.test.suitebuilder.annotation.LargeTest;
-
-import android.test.suitebuilder.annotation.Suppress;
 import com.google.mockwebserver.MockResponse;
 
 import java.io.File;
+import java.util.concurrent.TimeoutException;
 import java.util.Iterator;
 import java.util.Set;
 
 /**
  * Integration tests of the DownloadManager API.
  */
-@Suppress  // Failing.
 public class DownloadManagerFunctionalTest extends DownloadManagerBaseTest {
     private static final String TAG = "DownloadManagerFunctionalTest";
     private final static String CACHE_DIR =
@@ -79,7 +77,11 @@
         request.setTitle(DEFAULT_FILENAME);
 
         long dlRequest = mDownloadManager.enqueue(request);
-        waitForDownloadOrTimeout(dlRequest);
+        try {
+            waitForDownloadOrTimeout(dlRequest);
+        } catch (TimeoutException ex) {
+            // it is expected to timeout as download never finishes
+        }
 
         Cursor cursor = getCursor(dlRequest);
         try {
@@ -114,7 +116,7 @@
         verifyDownload(dlRequest, blobData);
         mDownloadManager.remove(dlRequest);
     }
-    
+
     /**
      * Helper to verify a standard single-file download from the mock server, and clean up after
      * verification
@@ -135,9 +137,7 @@
 
             verifyFileSize(pfd, fileSize);
             verifyFileContents(pfd, fileData);
-            int colIndex = cursor.getColumnIndex(DownloadManager.COLUMN_LOCAL_FILENAME);
-            String fileName = cursor.getString(colIndex);
-            assertTrue(fileName.startsWith(CACHE_DIR));
+            assertTrue(new File(CACHE_DIR + "/" + DEFAULT_FILENAME).exists());
         } finally {
             pfd.close();
             cursor.close();
@@ -161,7 +161,6 @@
 
             Uri localUri = Uri.fromFile(existentFile);
             request.setDestinationUri(localUri);
-
             long dlRequest = mDownloadManager.enqueue(request);
 
             // wait for the download to complete
diff --git a/core/tests/coretests/src/android/content/pm/ContainerEncryptionParamsTest.java b/core/tests/coretests/src/android/content/pm/ContainerEncryptionParamsTest.java
deleted file mode 100644
index 7deaa9a..0000000
--- a/core/tests/coretests/src/android/content/pm/ContainerEncryptionParamsTest.java
+++ /dev/null
@@ -1,370 +0,0 @@
-/*
- * 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.content.pm;
-
-import android.os.Parcel;
-import android.test.AndroidTestCase;
-
-import java.util.Arrays;
-
-import javax.crypto.SecretKey;
-import javax.crypto.spec.IvParameterSpec;
-import javax.crypto.spec.SecretKeySpec;
-
-public class ContainerEncryptionParamsTest extends AndroidTestCase {
-    private static final String ENC_ALGORITHM = "AES/CBC/PKCS7Padding";
-
-    private static final byte[] IV_BYTES = "FOOBAR".getBytes();
-
-    private static final IvParameterSpec ENC_PARAMS = new IvParameterSpec(IV_BYTES);
-
-    private static final byte[] ENC_KEY_BYTES = "abcd1234wxyz7890".getBytes();
-
-    private static final SecretKey ENC_KEY = new SecretKeySpec(ENC_KEY_BYTES, "RAW");
-
-    private static final String MAC_ALGORITHM = "HMAC-SHA1";
-
-    private static final byte[] MAC_KEY_BYTES = "4wxyzabcd1237890".getBytes();
-
-    private static final SecretKey MAC_KEY = new SecretKeySpec(MAC_KEY_BYTES, "RAW");
-
-    private static final byte[] MAC_TAG = "faketag".getBytes();
-
-    private static final int AUTHENTICATED_START = 5;
-
-    private static final int ENCRYPTED_START = 11;
-
-    private static final int DATA_END = 19;
-
-    public void testParcel() throws Exception {
-        ContainerEncryptionParams expected = new ContainerEncryptionParams(ENC_ALGORITHM,
-                ENC_PARAMS, ENC_KEY, MAC_ALGORITHM, null, MAC_KEY, MAC_TAG, AUTHENTICATED_START,
-                ENCRYPTED_START, DATA_END);
-
-        Parcel parcel = Parcel.obtain();
-        expected.writeToParcel(parcel, 0);
-        parcel.setDataPosition(0);
-
-        ContainerEncryptionParams actual = ContainerEncryptionParams.CREATOR
-                .createFromParcel(parcel);
-
-        assertEquals(ENC_ALGORITHM, actual.getEncryptionAlgorithm());
-
-        if (!(actual.getEncryptionSpec() instanceof IvParameterSpec)) {
-            fail("encryption parameters should be IvParameterSpec");
-        } else {
-            IvParameterSpec actualParams = (IvParameterSpec) actual.getEncryptionSpec();
-            assertTrue(Arrays.equals(IV_BYTES, actualParams.getIV()));
-        }
-
-        assertEquals(ENC_KEY, actual.getEncryptionKey());
-
-        assertEquals(MAC_ALGORITHM, actual.getMacAlgorithm());
-
-        assertNull(actual.getMacSpec());
-
-        assertEquals(MAC_KEY, actual.getMacKey());
-
-        assertTrue(Arrays.equals(MAC_TAG, actual.getMacTag()));
-
-        assertEquals(AUTHENTICATED_START, actual.getAuthenticatedDataStart());
-
-        assertEquals(ENCRYPTED_START, actual.getEncryptedDataStart());
-
-        assertEquals(DATA_END, actual.getDataEnd());
-    }
-
-    public void testEquals_Success() throws Exception {
-        ContainerEncryptionParams params1 = new ContainerEncryptionParams(ENC_ALGORITHM,
-                ENC_PARAMS, ENC_KEY, MAC_ALGORITHM, null, MAC_KEY, MAC_TAG, AUTHENTICATED_START,
-                ENCRYPTED_START, DATA_END);
-
-        ContainerEncryptionParams params2 = new ContainerEncryptionParams(
-                new String(ENC_ALGORITHM), new IvParameterSpec(IV_BYTES.clone()),
-                new SecretKeySpec(ENC_KEY_BYTES.clone(), "RAW"), new String(MAC_ALGORITHM), null,
-                new SecretKeySpec(MAC_KEY_BYTES.clone(), "RAW"), MAC_TAG, AUTHENTICATED_START,
-                ENCRYPTED_START, DATA_END);
-
-        assertEquals(params1, params2);
-    }
-
-    public void testEquals_EncAlgo_Failure() throws Exception {
-        ContainerEncryptionParams params1 = new ContainerEncryptionParams(ENC_ALGORITHM,
-                ENC_PARAMS, ENC_KEY, MAC_ALGORITHM, null, MAC_KEY, MAC_TAG, AUTHENTICATED_START,
-                ENCRYPTED_START, DATA_END);
-
-        ContainerEncryptionParams params2 = new ContainerEncryptionParams(new String(
-                "AES-256/CBC/PKCS7Padding"), new IvParameterSpec(IV_BYTES.clone()),
-                new SecretKeySpec(ENC_KEY_BYTES.clone(), "RAW"), new String(MAC_ALGORITHM), null,
-                new SecretKeySpec(MAC_KEY_BYTES.clone(), "RAW"), MAC_TAG, AUTHENTICATED_START,
-                ENCRYPTED_START, DATA_END);
-
-        assertFalse(params1.equals(params2));
-    }
-
-    public void testEquals_EncParams_Failure() throws Exception {
-        ContainerEncryptionParams params1 = new ContainerEncryptionParams(ENC_ALGORITHM,
-                ENC_PARAMS, ENC_KEY, MAC_ALGORITHM, null, MAC_KEY, MAC_TAG, AUTHENTICATED_START,
-                ENCRYPTED_START, DATA_END);
-
-        ContainerEncryptionParams params2 = new ContainerEncryptionParams(
-                new String(ENC_ALGORITHM), new IvParameterSpec("BLAHBLAH".getBytes()),
-                new SecretKeySpec(ENC_KEY_BYTES.clone(), "RAW"), new String(MAC_ALGORITHM), null,
-                new SecretKeySpec(MAC_KEY_BYTES.clone(), "RAW"), MAC_TAG, AUTHENTICATED_START,
-                ENCRYPTED_START, DATA_END);
-
-        assertFalse(params1.equals(params2));
-    }
-
-    public void testEquals_EncKey_Failure() throws Exception {
-        ContainerEncryptionParams params1 = new ContainerEncryptionParams(ENC_ALGORITHM,
-                ENC_PARAMS, ENC_KEY, MAC_ALGORITHM, null, MAC_KEY, MAC_TAG, AUTHENTICATED_START,
-                ENCRYPTED_START, DATA_END);
-
-        ContainerEncryptionParams params2 = new ContainerEncryptionParams(
-                new String(ENC_ALGORITHM), new IvParameterSpec(IV_BYTES.clone()),
-                new SecretKeySpec("BLAHBLAH".getBytes(), "RAW"), new String(MAC_ALGORITHM), null,
-                new SecretKeySpec(MAC_KEY_BYTES.clone(), "RAW"), MAC_TAG, AUTHENTICATED_START,
-                ENCRYPTED_START, DATA_END);
-
-        assertFalse(params1.equals(params2));
-    }
-
-    public void testEquals_MacAlgo_Failure() throws Exception {
-        ContainerEncryptionParams params1 = new ContainerEncryptionParams(ENC_ALGORITHM,
-                ENC_PARAMS, ENC_KEY, MAC_ALGORITHM, null, MAC_KEY, MAC_TAG, AUTHENTICATED_START,
-                ENCRYPTED_START, DATA_END);
-
-        ContainerEncryptionParams params2 = new ContainerEncryptionParams(
-                new String(ENC_ALGORITHM), new IvParameterSpec(IV_BYTES.clone()),
-                new SecretKeySpec(ENC_KEY_BYTES.clone(), "RAW"), "BLAHBLAH", null,
-                new SecretKeySpec(MAC_KEY_BYTES.clone(), "RAW"), MAC_TAG, AUTHENTICATED_START,
-                ENCRYPTED_START, DATA_END);
-
-        assertFalse(params1.equals(params2));
-    }
-
-    public void testEquals_MacKey_Failure() throws Exception {
-        ContainerEncryptionParams params1 = new ContainerEncryptionParams(ENC_ALGORITHM,
-                ENC_PARAMS, ENC_KEY, MAC_ALGORITHM, null, MAC_KEY, MAC_TAG, AUTHENTICATED_START,
-                ENCRYPTED_START, DATA_END);
-
-        ContainerEncryptionParams params2 = new ContainerEncryptionParams(
-                new String(ENC_ALGORITHM), new IvParameterSpec(IV_BYTES.clone()),
-                new SecretKeySpec(ENC_KEY_BYTES.clone(), "RAW"), new String(MAC_ALGORITHM), null,
-                new SecretKeySpec("FAKE_MAC_KEY".getBytes(), "RAW"), MAC_TAG, AUTHENTICATED_START,
-                ENCRYPTED_START, DATA_END);
-
-        assertFalse(params1.equals(params2));
-    }
-
-    public void testEquals_MacTag_Failure() throws Exception {
-        ContainerEncryptionParams params1 = new ContainerEncryptionParams(ENC_ALGORITHM,
-                ENC_PARAMS, ENC_KEY, MAC_ALGORITHM, null, MAC_KEY, MAC_TAG, AUTHENTICATED_START,
-                ENCRYPTED_START, DATA_END);
-
-        ContainerEncryptionParams params2 = new ContainerEncryptionParams(
-                new String(ENC_ALGORITHM), new IvParameterSpec(IV_BYTES.clone()),
-                new SecretKeySpec(ENC_KEY_BYTES.clone(), "RAW"), new String(MAC_ALGORITHM), null,
-                new SecretKeySpec(MAC_KEY_BYTES.clone(), "RAW"), "broken".getBytes(),
-                AUTHENTICATED_START, ENCRYPTED_START, DATA_END);
-
-        assertFalse(params1.equals(params2));
-    }
-
-    public void testEquals_AuthenticatedStart_Failure() throws Exception {
-        ContainerEncryptionParams params1 = new ContainerEncryptionParams(ENC_ALGORITHM,
-                ENC_PARAMS, ENC_KEY, MAC_ALGORITHM, null, MAC_KEY, MAC_TAG, AUTHENTICATED_START,
-                ENCRYPTED_START, DATA_END);
-
-        ContainerEncryptionParams params2 = new ContainerEncryptionParams(
-                new String(ENC_ALGORITHM), new IvParameterSpec(IV_BYTES.clone()),
-                new SecretKeySpec(ENC_KEY_BYTES.clone(), "RAW"), new String(MAC_ALGORITHM), null,
-                new SecretKeySpec(MAC_KEY_BYTES.clone(), "RAW"), MAC_TAG, AUTHENTICATED_START - 1,
-                ENCRYPTED_START, DATA_END);
-
-        assertFalse(params1.equals(params2));
-    }
-
-    public void testEquals_EncryptedStart_Failure() throws Exception {
-        ContainerEncryptionParams params1 = new ContainerEncryptionParams(ENC_ALGORITHM,
-                ENC_PARAMS, ENC_KEY, MAC_ALGORITHM, null, MAC_KEY, MAC_TAG, AUTHENTICATED_START,
-                ENCRYPTED_START, DATA_END);
-
-        ContainerEncryptionParams params2 = new ContainerEncryptionParams(
-                new String(ENC_ALGORITHM), new IvParameterSpec(IV_BYTES.clone()),
-                new SecretKeySpec(ENC_KEY_BYTES.clone(), "RAW"), new String(MAC_ALGORITHM), null,
-                new SecretKeySpec(MAC_KEY_BYTES.clone(), "RAW"), MAC_TAG, AUTHENTICATED_START,
-                ENCRYPTED_START - 1, DATA_END);
-
-        assertFalse(params1.equals(params2));
-    }
-
-    public void testEquals_DataEnd_Failure() throws Exception {
-        ContainerEncryptionParams params1 = new ContainerEncryptionParams(ENC_ALGORITHM,
-                ENC_PARAMS, ENC_KEY, MAC_ALGORITHM, null, MAC_KEY, MAC_TAG, AUTHENTICATED_START,
-                ENCRYPTED_START, DATA_END);
-
-        ContainerEncryptionParams params2 = new ContainerEncryptionParams(
-                new String(ENC_ALGORITHM), new IvParameterSpec(IV_BYTES.clone()),
-                new SecretKeySpec(ENC_KEY_BYTES.clone(), "RAW"), new String(MAC_ALGORITHM), null,
-                new SecretKeySpec(MAC_KEY_BYTES.clone(), "RAW"), MAC_TAG, AUTHENTICATED_START,
-                ENCRYPTED_START, DATA_END + 1);
-
-        assertFalse(params1.equals(params2));
-    }
-
-    public void testHashCode_Success() throws Exception {
-        ContainerEncryptionParams params1 = new ContainerEncryptionParams(ENC_ALGORITHM,
-                ENC_PARAMS, ENC_KEY, MAC_ALGORITHM, null, MAC_KEY, MAC_TAG, AUTHENTICATED_START,
-                ENCRYPTED_START, DATA_END);
-
-        ContainerEncryptionParams params2 = new ContainerEncryptionParams(
-                new String(ENC_ALGORITHM), new IvParameterSpec(IV_BYTES.clone()),
-                new SecretKeySpec(ENC_KEY_BYTES.clone(), "RAW"), new String(MAC_ALGORITHM), null,
-                new SecretKeySpec(MAC_KEY_BYTES.clone(), "RAW"), MAC_TAG, AUTHENTICATED_START,
-                ENCRYPTED_START, DATA_END);
-
-        assertEquals(params1.hashCode(), params2.hashCode());
-    }
-
-    public void testHashCode_EncAlgo_Failure() throws Exception {
-        ContainerEncryptionParams params1 = new ContainerEncryptionParams(ENC_ALGORITHM,
-                ENC_PARAMS, ENC_KEY, MAC_ALGORITHM, null, MAC_KEY, MAC_TAG, AUTHENTICATED_START,
-                ENCRYPTED_START, DATA_END);
-
-        ContainerEncryptionParams params2 = new ContainerEncryptionParams(new String(
-                "AES-256/CBC/PKCS7Padding"), new IvParameterSpec(IV_BYTES.clone()),
-                new SecretKeySpec(ENC_KEY_BYTES.clone(), "RAW"), new String(MAC_ALGORITHM), null,
-                new SecretKeySpec(MAC_KEY_BYTES.clone(), "RAW"), MAC_TAG, AUTHENTICATED_START,
-                ENCRYPTED_START, DATA_END);
-
-        assertFalse(params1.hashCode() == params2.hashCode());
-    }
-
-    public void testHashCode_EncParams_Failure() throws Exception {
-        ContainerEncryptionParams params1 = new ContainerEncryptionParams(ENC_ALGORITHM,
-                ENC_PARAMS, ENC_KEY, MAC_ALGORITHM, null, MAC_KEY, MAC_TAG, AUTHENTICATED_START,
-                ENCRYPTED_START, DATA_END);
-
-        ContainerEncryptionParams params2 = new ContainerEncryptionParams(
-                new String(ENC_ALGORITHM), new IvParameterSpec("BLAHBLAH".getBytes()),
-                new SecretKeySpec(ENC_KEY_BYTES.clone(), "RAW"), new String(MAC_ALGORITHM), null,
-                new SecretKeySpec(MAC_KEY_BYTES.clone(), "RAW"), MAC_TAG, AUTHENTICATED_START,
-                ENCRYPTED_START, DATA_END);
-
-        assertFalse(params1.hashCode() == params2.hashCode());
-    }
-
-    public void testHashCode_EncKey_Failure() throws Exception {
-        ContainerEncryptionParams params1 = new ContainerEncryptionParams(ENC_ALGORITHM,
-                ENC_PARAMS, ENC_KEY, MAC_ALGORITHM, null, MAC_KEY, MAC_TAG, AUTHENTICATED_START,
-                ENCRYPTED_START, DATA_END);
-
-        ContainerEncryptionParams params2 = new ContainerEncryptionParams(
-                new String(ENC_ALGORITHM), new IvParameterSpec(IV_BYTES.clone()),
-                new SecretKeySpec("BLAHBLAH".getBytes(), "RAW"), new String(MAC_ALGORITHM), null,
-                new SecretKeySpec(MAC_KEY_BYTES.clone(), "RAW"), MAC_TAG, AUTHENTICATED_START,
-                ENCRYPTED_START, DATA_END);
-
-        assertFalse(params1.hashCode() == params2.hashCode());
-    }
-
-    public void testHashCode_MacAlgo_Failure() throws Exception {
-        ContainerEncryptionParams params1 = new ContainerEncryptionParams(ENC_ALGORITHM,
-                ENC_PARAMS, ENC_KEY, MAC_ALGORITHM, null, MAC_KEY, MAC_TAG, AUTHENTICATED_START,
-                ENCRYPTED_START, DATA_END);
-
-        ContainerEncryptionParams params2 = new ContainerEncryptionParams(
-                new String(ENC_ALGORITHM), new IvParameterSpec(IV_BYTES.clone()),
-                new SecretKeySpec(ENC_KEY_BYTES.clone(), "RAW"), "BLAHBLAH", null,
-                new SecretKeySpec(MAC_KEY_BYTES.clone(), "RAW"), MAC_TAG, AUTHENTICATED_START,
-                ENCRYPTED_START, DATA_END);
-
-        assertFalse(params1.hashCode() == params2.hashCode());
-    }
-
-    public void testHashCode_MacKey_Failure() throws Exception {
-        ContainerEncryptionParams params1 = new ContainerEncryptionParams(ENC_ALGORITHM,
-                ENC_PARAMS, ENC_KEY, MAC_ALGORITHM, null, MAC_KEY, MAC_TAG, AUTHENTICATED_START,
-                ENCRYPTED_START, DATA_END);
-
-        ContainerEncryptionParams params2 = new ContainerEncryptionParams(
-                new String(ENC_ALGORITHM), new IvParameterSpec(IV_BYTES.clone()),
-                new SecretKeySpec(ENC_KEY_BYTES.clone(), "RAW"), new String(MAC_ALGORITHM), null,
-                new SecretKeySpec("FAKE_MAC_KEY".getBytes(), "RAW"), MAC_TAG, AUTHENTICATED_START,
-                ENCRYPTED_START, DATA_END);
-
-        assertFalse(params1.hashCode() == params2.hashCode());
-    }
-
-    public void testHashCode_MacTag_Failure() throws Exception {
-        ContainerEncryptionParams params1 = new ContainerEncryptionParams(ENC_ALGORITHM,
-                ENC_PARAMS, ENC_KEY, MAC_ALGORITHM, null, MAC_KEY, MAC_TAG, AUTHENTICATED_START,
-                ENCRYPTED_START, DATA_END);
-
-        ContainerEncryptionParams params2 = new ContainerEncryptionParams(
-                new String(ENC_ALGORITHM), new IvParameterSpec(IV_BYTES.clone()),
-                new SecretKeySpec(ENC_KEY_BYTES.clone(), "RAW"), new String(MAC_ALGORITHM), null,
-                new SecretKeySpec(MAC_KEY_BYTES.clone(), "RAW"), "broken".getBytes(),
-                AUTHENTICATED_START, ENCRYPTED_START, DATA_END);
-
-        assertFalse(params1.hashCode() == params2.hashCode());
-    }
-
-    public void testHashCode_AuthenticatedStart_Failure() throws Exception {
-        ContainerEncryptionParams params1 = new ContainerEncryptionParams(ENC_ALGORITHM,
-                ENC_PARAMS, ENC_KEY, MAC_ALGORITHM, null, MAC_KEY, MAC_TAG, AUTHENTICATED_START,
-                ENCRYPTED_START, DATA_END);
-
-        ContainerEncryptionParams params2 = new ContainerEncryptionParams(
-                new String(ENC_ALGORITHM), new IvParameterSpec(IV_BYTES.clone()),
-                new SecretKeySpec(ENC_KEY_BYTES.clone(), "RAW"), new String(MAC_ALGORITHM), null,
-                new SecretKeySpec(MAC_KEY_BYTES.clone(), "RAW"), MAC_TAG, AUTHENTICATED_START - 1,
-                ENCRYPTED_START, DATA_END);
-
-        assertFalse(params1.hashCode() == params2.hashCode());
-    }
-
-    public void testHashCode_EncryptedStart_Failure() throws Exception {
-        ContainerEncryptionParams params1 = new ContainerEncryptionParams(ENC_ALGORITHM,
-                ENC_PARAMS, ENC_KEY, MAC_ALGORITHM, null, MAC_KEY, MAC_TAG, AUTHENTICATED_START,
-                ENCRYPTED_START, DATA_END);
-
-        ContainerEncryptionParams params2 = new ContainerEncryptionParams(
-                new String(ENC_ALGORITHM), new IvParameterSpec(IV_BYTES.clone()),
-                new SecretKeySpec(ENC_KEY_BYTES.clone(), "RAW"), new String(MAC_ALGORITHM), null,
-                new SecretKeySpec(MAC_KEY_BYTES.clone(), "RAW"), MAC_TAG, AUTHENTICATED_START,
-                ENCRYPTED_START - 1, DATA_END);
-
-        assertFalse(params1.hashCode() == params2.hashCode());
-    }
-
-    public void testHashCode_DataEnd_Failure() throws Exception {
-        ContainerEncryptionParams params1 = new ContainerEncryptionParams(ENC_ALGORITHM,
-                ENC_PARAMS, ENC_KEY, MAC_ALGORITHM, null, MAC_KEY, MAC_TAG, AUTHENTICATED_START,
-                ENCRYPTED_START, DATA_END);
-
-        ContainerEncryptionParams params2 = new ContainerEncryptionParams(
-                new String(ENC_ALGORITHM), new IvParameterSpec(IV_BYTES.clone()),
-                new SecretKeySpec(ENC_KEY_BYTES.clone(), "RAW"), new String(MAC_ALGORITHM), null,
-                new SecretKeySpec(MAC_KEY_BYTES.clone(), "RAW"), MAC_TAG, AUTHENTICATED_START,
-                ENCRYPTED_START, DATA_END + 1);
-
-        assertFalse(params1.hashCode() == params2.hashCode());
-    }
-}
diff --git a/core/tests/coretests/src/android/content/res/ConfigurationBoundResourceCacheTest.java b/core/tests/coretests/src/android/content/res/ConfigurationBoundResourceCacheTest.java
index e9fd5fb..47554a6 100644
--- a/core/tests/coretests/src/android/content/res/ConfigurationBoundResourceCacheTest.java
+++ b/core/tests/coretests/src/android/content/res/ConfigurationBoundResourceCacheTest.java
@@ -17,20 +17,18 @@
 package android.content.res;
 
 import android.test.ActivityInstrumentationTestCase2;
+import android.test.suitebuilder.annotation.SmallTest;
 import android.util.TypedValue;
 
 import com.android.frameworks.coretests.R;
 
 import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
 
 public class ConfigurationBoundResourceCacheTest
         extends ActivityInstrumentationTestCase2<ResourceCacheActivity> {
 
     ConfigurationBoundResourceCache<Float> mCache;
 
-    Method mCalcConfigChanges;
-
     public ConfigurationBoundResourceCacheTest() {
         super(ResourceCacheActivity.class);
     }
@@ -38,36 +36,45 @@
     @Override
     protected void setUp() throws Exception {
         super.setUp();
-        mCache = new ConfigurationBoundResourceCache<Float>(getActivity().getResources());
+        mCache = new ConfigurationBoundResourceCache<>();
     }
 
+    @SmallTest
     public void testGetEmpty() {
-        assertNull(mCache.get(-1, null));
+        final Resources res = getActivity().getResources();
+        assertNull(mCache.getInstance(-1, res, null));
     }
 
+    @SmallTest
     public void testSetGet() {
         mCache.put(1, null, new DummyFloatConstantState(5f));
-        assertEquals(5f, mCache.get(1, null));
-        assertNotSame(5f, mCache.get(1, null));
-        assertEquals(null, mCache.get(1, getActivity().getTheme()));
+        final Resources res = getActivity().getResources();
+        assertEquals(5f, mCache.getInstance(1, res, null));
+        assertNotSame(5f, mCache.getInstance(1, res, null));
+        assertEquals(null, mCache.getInstance(1, res, getActivity().getTheme()));
     }
 
+    @SmallTest
     public void testSetGetThemed() {
         mCache.put(1, getActivity().getTheme(), new DummyFloatConstantState(5f));
-        assertEquals(null, mCache.get(1, null));
-        assertEquals(5f, mCache.get(1, getActivity().getTheme()));
-        assertNotSame(5f, mCache.get(1, getActivity().getTheme()));
+        final Resources res = getActivity().getResources();
+        assertEquals(null, mCache.getInstance(1, res, null));
+        assertEquals(5f, mCache.getInstance(1, res, getActivity().getTheme()));
+        assertNotSame(5f, mCache.getInstance(1, res, getActivity().getTheme()));
     }
 
+    @SmallTest
     public void testMultiThreadPutGet() {
         mCache.put(1, getActivity().getTheme(), new DummyFloatConstantState(5f));
         mCache.put(1, null, new DummyFloatConstantState(10f));
-        assertEquals(10f, mCache.get(1, null));
-        assertNotSame(10f, mCache.get(1, null));
-        assertEquals(5f, mCache.get(1, getActivity().getTheme()));
-        assertNotSame(5f, mCache.get(1, getActivity().getTheme()));
+        final Resources res = getActivity().getResources();
+        assertEquals(10f, mCache.getInstance(1, res, null));
+        assertNotSame(10f, mCache.getInstance(1, res, null));
+        assertEquals(5f, mCache.getInstance(1, res, getActivity().getTheme()));
+        assertNotSame(5f, mCache.getInstance(1, res, getActivity().getTheme()));
     }
 
+    @SmallTest
     public void testVoidConfigChange()
             throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
         TypedValue staticValue = new TypedValue();
@@ -83,11 +90,12 @@
                 Configuration.ORIENTATION_PORTRAIT
                 : Configuration.ORIENTATION_LANDSCAPE;
         int changes = calcConfigChanges(res, newCnf);
-        assertEquals(staticDim, mCache.get(key, getActivity().getTheme()));
+        assertEquals(staticDim, mCache.getInstance(key, res, getActivity().getTheme()));
         mCache.onConfigurationChange(changes);
-        assertEquals(staticDim, mCache.get(key, getActivity().getTheme()));
+        assertEquals(staticDim, mCache.getInstance(key, res, getActivity().getTheme()));
     }
 
+    @SmallTest
     public void testEffectiveConfigChange()
             throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
         TypedValue changingValue = new TypedValue();
@@ -105,11 +113,12 @@
                 Configuration.ORIENTATION_PORTRAIT
                 : Configuration.ORIENTATION_LANDSCAPE;
         int changes = calcConfigChanges(res, newCnf);
-        assertEquals(changingDim, mCache.get(key, getActivity().getTheme()));
+        assertEquals(changingDim, mCache.getInstance(key, res, getActivity().getTheme()));
         mCache.onConfigurationChange(changes);
         assertNull(mCache.get(key, getActivity().getTheme()));
     }
 
+    @SmallTest
     public void testConfigChangeMultipleResources()
             throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
         TypedValue staticValue = new TypedValue();
@@ -130,17 +139,19 @@
                 Configuration.ORIENTATION_PORTRAIT
                 : Configuration.ORIENTATION_LANDSCAPE;
         int changes = calcConfigChanges(res, newCnf);
-        assertEquals(staticDim, mCache.get(R.dimen.resource_cache_test_generic,
+        assertEquals(staticDim, mCache.getInstance(R.dimen.resource_cache_test_generic, res,
                 getActivity().getTheme()));
-        assertEquals(changingDim, mCache.get(R.dimen.resource_cache_test_orientation_dependent,
-                getActivity().getTheme()));
+        assertEquals(changingDim,
+                mCache.getInstance(R.dimen.resource_cache_test_orientation_dependent, res,
+                        getActivity().getTheme()));
         mCache.onConfigurationChange(changes);
-        assertEquals(staticDim, mCache.get(R.dimen.resource_cache_test_generic,
+        assertEquals(staticDim, mCache.getInstance(R.dimen.resource_cache_test_generic, res,
                 getActivity().getTheme()));
-        assertNull(mCache.get(R.dimen.resource_cache_test_orientation_dependent,
+        assertNull(mCache.getInstance(R.dimen.resource_cache_test_orientation_dependent, res,
                 getActivity().getTheme()));
     }
 
+    @SmallTest
     public void testConfigChangeMultipleThemes()
             throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
         TypedValue[] staticValues = new TypedValue[]{new TypedValue(), new TypedValue()};
@@ -172,31 +183,27 @@
         int changes = calcConfigChanges(res, newCnf);
         for (int i = 0; i < 2; i++) {
             final Resources.Theme theme = i == 0 ? getActivity().getTheme() : null;
-            assertEquals(staticDim, mCache.get(R.dimen.resource_cache_test_generic, theme));
+            assertEquals(staticDim,
+                    mCache.getInstance(R.dimen.resource_cache_test_generic, res, theme));
             assertEquals(changingDim,
-                    mCache.get(R.dimen.resource_cache_test_orientation_dependent, theme));
+                    mCache.getInstance(R.dimen.resource_cache_test_orientation_dependent, res,
+                            theme));
         }
         mCache.onConfigurationChange(changes);
         for (int i = 0; i < 2; i++) {
             final Resources.Theme theme = i == 0 ? getActivity().getTheme() : null;
-            assertEquals(staticDim, mCache.get(R.dimen.resource_cache_test_generic, theme));
-            assertNull(mCache.get(R.dimen.resource_cache_test_orientation_dependent, theme));
+            assertEquals(staticDim,
+                    mCache.getInstance(R.dimen.resource_cache_test_generic, res, theme));
+            assertNull(mCache.getInstance(R.dimen.resource_cache_test_orientation_dependent, res,
+                    theme));
         }
     }
 
-    private int calcConfigChanges(Resources resources, Configuration configuration)
-            throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
-        if (mCalcConfigChanges == null) {
-            mCalcConfigChanges = Resources.class.getDeclaredMethod("calcConfigChanges",
-                    Configuration.class);
-            mCalcConfigChanges.setAccessible(true);
-        }
-        return (Integer) mCalcConfigChanges.invoke(resources, configuration);
-
+    private static int calcConfigChanges(Resources resources, Configuration configuration) {
+        return resources.calcConfigChanges(configuration);
     }
 
-    static class DummyFloatConstantState extends
-            ConstantState<Float> {
+    static class DummyFloatConstantState extends ConstantState<Float> {
 
         final Float mObj;
 
diff --git a/core/tests/coretests/src/android/content/res/ResourcesManagerTest.java b/core/tests/coretests/src/android/content/res/ResourcesManagerTest.java
new file mode 100644
index 0000000..3cadbf6
--- /dev/null
+++ b/core/tests/coretests/src/android/content/res/ResourcesManagerTest.java
@@ -0,0 +1,222 @@
+/*
+ * 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.res;
+
+import android.annotation.NonNull;
+import android.app.ResourcesManager;
+import android.os.Binder;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.util.DisplayMetrics;
+import android.util.LocaleList;
+import android.util.TypedValue;
+import android.view.Display;
+import junit.framework.TestCase;
+
+public class ResourcesManagerTest extends TestCase {
+    private static final String APP_ONE_RES_DIR = "app_one.apk";
+    private static final String APP_ONE_RES_SPLIT_DIR = "app_one_split.apk";
+    private static final String APP_TWO_RES_DIR = "app_two.apk";
+    private static final String LIB_RES_DIR = "lib.apk";
+
+    private ResourcesManager mResourcesManager;
+    private DisplayMetrics mDisplayMetrics;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        mDisplayMetrics = new DisplayMetrics();
+        mDisplayMetrics.setToDefaults();
+
+        // Override defaults (which take device specific properties).
+        mDisplayMetrics.density = 1.0f;
+        mDisplayMetrics.densityDpi = DisplayMetrics.DENSITY_DEFAULT;
+        mDisplayMetrics.xdpi = DisplayMetrics.DENSITY_DEFAULT;
+        mDisplayMetrics.ydpi = DisplayMetrics.DENSITY_DEFAULT;
+        mDisplayMetrics.noncompatDensity = mDisplayMetrics.density;
+        mDisplayMetrics.noncompatDensityDpi = mDisplayMetrics.densityDpi;
+        mDisplayMetrics.noncompatXdpi = DisplayMetrics.DENSITY_DEFAULT;
+        mDisplayMetrics.noncompatYdpi = DisplayMetrics.DENSITY_DEFAULT;
+
+        mResourcesManager = new ResourcesManager() {
+            @Override
+            protected AssetManager createAssetManager(@NonNull ResourcesKey key) {
+                return new AssetManager();
+            }
+
+            @Override
+            protected DisplayMetrics getDisplayMetricsLocked(int displayId) {
+                return mDisplayMetrics;
+            }
+        };
+    }
+
+    @SmallTest
+    public void testMultipleCallsWithIdenticalParametersCacheReference() {
+        Resources resources = mResourcesManager.getResources(
+                null, APP_ONE_RES_DIR, null, null, null, Display.DEFAULT_DISPLAY, null,
+                CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO, null);
+        assertNotNull(resources);
+
+        Resources newResources = mResourcesManager.getResources(
+                null, APP_ONE_RES_DIR, null, null, null, Display.DEFAULT_DISPLAY, null,
+                CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO, null);
+        assertNotNull(newResources);
+        assertSame(resources, newResources);
+    }
+
+    @SmallTest
+    public void testMultipleCallsWithDifferentParametersReturnDifferentReferences() {
+        Resources resources = mResourcesManager.getResources(
+                null, APP_ONE_RES_DIR, null, null, null, Display.DEFAULT_DISPLAY, null,
+                CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO, null);
+        assertNotNull(resources);
+
+        Configuration overrideConfig = new Configuration();
+        overrideConfig.smallestScreenWidthDp = 200;
+        Resources newResources = mResourcesManager.getResources(
+                null, APP_ONE_RES_DIR, null, null, null, Display.DEFAULT_DISPLAY, overrideConfig,
+                CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO, null);
+        assertNotNull(newResources);
+        assertNotSame(resources, newResources);
+    }
+
+    @SmallTest
+    public void testAddingASplitCreatesANewImpl() {
+        Resources resources1 = mResourcesManager.getResources(
+                null, APP_ONE_RES_DIR, null, null, null, Display.DEFAULT_DISPLAY, null,
+                CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO, null);
+        assertNotNull(resources1);
+
+        Resources resources2 = mResourcesManager.getResources(
+                null, APP_ONE_RES_DIR, new String[] { APP_ONE_RES_SPLIT_DIR }, null, null,
+                Display.DEFAULT_DISPLAY, null, CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO, null);
+        assertNotNull(resources2);
+
+        assertNotSame(resources1, resources2);
+        assertNotSame(resources1.getImpl(), resources2.getImpl());
+    }
+
+    @SmallTest
+    public void testUpdateConfigurationUpdatesAllAssetManagers() {
+        Resources resources1 = mResourcesManager.getResources(
+                null, APP_ONE_RES_DIR, null, null, null, Display.DEFAULT_DISPLAY, null,
+                CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO, null);
+        assertNotNull(resources1);
+
+        Resources resources2 = mResourcesManager.getResources(
+                null, APP_TWO_RES_DIR, null, null, null, Display.DEFAULT_DISPLAY, null,
+                CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO, null);
+        assertNotNull(resources2);
+
+        Binder activity = new Binder();
+        final Configuration overrideConfig = new Configuration();
+        overrideConfig.orientation = Configuration.ORIENTATION_LANDSCAPE;
+        Resources resources3 = mResourcesManager.getResources(
+                activity, APP_ONE_RES_DIR, null, null, null, Display.DEFAULT_DISPLAY,
+                overrideConfig, CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO, null);
+        assertNotNull(resources3);
+
+        // No Resources object should be the same.
+        assertNotSame(resources1, resources2);
+        assertNotSame(resources1, resources3);
+        assertNotSame(resources2, resources3);
+
+        // Each ResourcesImpl should be different.
+        assertNotSame(resources1.getImpl(), resources2.getImpl());
+        assertNotSame(resources1.getImpl(), resources3.getImpl());
+        assertNotSame(resources2.getImpl(), resources3.getImpl());
+
+        Configuration newConfig = new Configuration();
+        newConfig.orientation = Configuration.ORIENTATION_LANDSCAPE;
+        mResourcesManager.applyConfigurationToResourcesLocked(newConfig, null);
+
+        final Configuration expectedConfig = new Configuration();
+        expectedConfig.setLocales(LocaleList.getAdjustedDefault());
+        expectedConfig.densityDpi = mDisplayMetrics.densityDpi;
+        expectedConfig.orientation = Configuration.ORIENTATION_LANDSCAPE;
+
+        assertEquals(expectedConfig, resources1.getConfiguration());
+        assertEquals(expectedConfig, resources2.getConfiguration());
+        assertEquals(expectedConfig, resources3.getConfiguration());
+    }
+
+    @SmallTest
+    public void testTwoActivitiesWithIdenticalParametersShareImpl() {
+        Binder activity1 = new Binder();
+        Resources resources1 = mResourcesManager.getResources(
+                activity1, APP_ONE_RES_DIR, null, null, null, Display.DEFAULT_DISPLAY, null,
+                CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO, null);
+        assertNotNull(resources1);
+
+        Binder activity2 = new Binder();
+        Resources resources2 = mResourcesManager.getResources(
+                activity2, APP_ONE_RES_DIR, null, null, null, Display.DEFAULT_DISPLAY, null,
+                CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO, null);
+        assertNotNull(resources1);
+
+        // The references themselves should be unique.
+        assertNotSame(resources1, resources2);
+
+        // The implementations should be the same.
+        assertSame(resources1.getImpl(), resources2.getImpl());
+
+        final Configuration overrideConfig = new Configuration();
+        overrideConfig.orientation = Configuration.ORIENTATION_LANDSCAPE;
+        Resources resources3 = mResourcesManager.getResources(
+                activity2, APP_ONE_RES_DIR, null, null, null, Display.DEFAULT_DISPLAY,
+                overrideConfig, CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO, null);
+
+        // Since we requested new resources for activity2, the resource should be the same
+        // as the one returned before for activity2.
+        assertSame(resources2, resources3);
+
+        // But the implementation has changed.
+        assertNotSame(resources1.getImpl(), resources2.getImpl());
+    }
+
+    @SmallTest
+    public void testThemesGetUpdatedWithNewImpl() {
+        Binder activity1 = new Binder();
+        Resources resources1 = mResourcesManager.getResources(
+                activity1, APP_ONE_RES_DIR, null, null, null, Display.DEFAULT_DISPLAY, null,
+                CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO, null);
+        assertNotNull(resources1);
+
+        Resources.Theme theme = resources1.newTheme();
+        assertSame(resources1, theme.getResources());
+        theme.applyStyle(android.R.style.Theme_NoTitleBar, false);
+
+        TypedValue value = new TypedValue();
+        assertTrue(theme.resolveAttribute(android.R.attr.windowNoTitle, value, true));
+        assertEquals(TypedValue.TYPE_INT_BOOLEAN, value.type);
+        assertTrue(value.data != 0);
+
+        final Configuration overrideConfig = new Configuration();
+        overrideConfig.orientation = Configuration.ORIENTATION_LANDSCAPE;
+        Resources resources2 = mResourcesManager.getResources(
+                activity1, APP_ONE_RES_DIR, null, null, null, Display.DEFAULT_DISPLAY,
+                overrideConfig, CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO, null);
+        assertNotNull(resources2);
+        assertSame(resources1, resources2);
+        assertSame(resources2, theme.getResources());
+
+        // Make sure we can still access the data.
+        assertTrue(theme.resolveAttribute(android.R.attr.windowNoTitle, value, true));
+        assertEquals(TypedValue.TYPE_INT_BOOLEAN, value.type);
+        assertTrue(value.data != 0);
+    }
+}
diff --git a/core/tests/coretests/src/android/print/BasePrintTest.java b/core/tests/coretests/src/android/print/BasePrintTest.java
index 3feb0e9..c9bc8aa 100644
--- a/core/tests/coretests/src/android/print/BasePrintTest.java
+++ b/core/tests/coretests/src/android/print/BasePrintTest.java
@@ -61,7 +61,6 @@
 public abstract class BasePrintTest extends InstrumentationTestCase {
 
     private static final long OPERATION_TIMEOUT = 30000;
-    private static final String PRINT_SPOOLER_PACKAGE_NAME = "com.android.printspooler";
     private static final String PM_CLEAR_SUCCESS_OUTPUT = "Success";
     private static final String COMMAND_LIST_ENABLED_IME_COMPONENTS = "ime list -s";
     private static final String COMMAND_PREFIX_ENABLE_IME = "ime enable ";
@@ -249,8 +248,9 @@
     protected void clearPrintSpoolerData() throws Exception {
         assertTrue("failed to clear print spooler data",
                 runShellCommand(getInstrumentation(), String.format(
-                        "pm clear --user %d %s", CURRENT_USER_ID, PRINT_SPOOLER_PACKAGE_NAME))
-                                .contains(PM_CLEAR_SUCCESS_OUTPUT));
+                        "pm clear --user %d %s", CURRENT_USER_ID,
+                        PrintManager.PRINT_SPOOLER_PACKAGE_NAME))
+                        .contains(PM_CLEAR_SUCCESS_OUTPUT));
     }
 
     @SuppressWarnings("unchecked")
diff --git a/core/tests/coretests/src/android/print/IPrintManagerParametersTest.java b/core/tests/coretests/src/android/print/IPrintManagerParametersTest.java
index 5179b42..cbf17a4 100644
--- a/core/tests/coretests/src/android/print/IPrintManagerParametersTest.java
+++ b/core/tests/coretests/src/android/print/IPrintManagerParametersTest.java
@@ -27,24 +27,9 @@
 import android.os.Process;
 import android.os.ServiceManager;
 import android.os.UserHandle;
-import android.print.IPrintDocumentAdapter;
-import android.print.IPrintJobStateChangeListener;
-import android.print.IPrintManager;
-import android.print.IPrinterDiscoveryObserver;
-import android.print.PageRange;
-import android.print.PrintAttributes;
 import android.print.PrintAttributes.Margins;
 import android.print.PrintAttributes.MediaSize;
 import android.print.PrintAttributes.Resolution;
-import android.print.PrintDocumentAdapter;
-import android.print.PrintJob;
-import android.print.PrintJobId;
-import android.print.PrintJobInfo;
-import android.print.PrintManager;
-import android.print.PrinterCapabilitiesInfo;
-import android.print.PrinterDiscoverySession;
-import android.print.PrinterId;
-import android.print.PrinterInfo;
 import android.printservice.PrintServiceInfo;
 
 import android.print.mockservice.MockPrintService;
@@ -134,7 +119,7 @@
 
                                 if (session.getPrinters().isEmpty()) {
                                     final String PRINTER_NAME = "good printer";
-                                    List<PrinterInfo> printers = new ArrayList<PrinterInfo>();
+                                    List<PrinterInfo> printers = new ArrayList<>();
 
                                     // Add the printer.
                                     mGoodPrinterId = session.getService()
@@ -184,6 +169,18 @@
     }
 
     /**
+     * Create a IPrintServicesChangeListener object.
+     *
+     * @return the object
+     * @throws Exception if the object could not be created.
+     */
+    private IPrintServicesChangeListener createMockIPrintServicesChangeListener() throws Exception {
+        return new PrintManager.PrintServicesChangeListenerWrapper(null,
+                new Handler(Looper.getMainLooper()));
+    }
+
+
+    /**
      * Create a IPrinterDiscoveryObserver object.
      *
      * @return the object
@@ -193,6 +190,16 @@
         return new PrinterDiscoverySession.PrinterDiscoveryObserver(null);
     }
 
+    private void startPrinting() {
+        mGoodPrintJob = print(createMockAdapter(), null);
+
+        // Wait for PrintActivity to be ready
+        waitForStartAdapterCallbackCalled();
+
+        // Wait for printer discovery session to be ready
+        waitForPrinterDiscoverySessionStartCallbackCalled();
+    }
+
     @Override
     public void setUp() throws Exception {
         super.setUp();
@@ -201,20 +208,12 @@
 
         mGoodComponentName = getActivity().getComponentName();
 
-        mGoodPrintJob = print(createMockAdapter(), null);
-
         mIPrintManager = IPrintManager.Stub
                 .asInterface(ServiceManager.getService(Context.PRINT_SERVICE));
 
         // Generate dummy printerId which is a valid PrinterId object, but does not correspond to a
         // printer
         mBadPrinterId = new PrinterId(mGoodComponentName, "dummy printer");
-
-        // Wait for PrintActivity to be ready
-        waitForStartAdapterCallbackCalled();
-
-        // Wait for printer discovery session to be ready
-        waitForPrinterDiscoverySessionStartCallbackCalled();
     }
 
     /**
@@ -222,11 +221,11 @@
      */
     private interface Invokable {
         /**
-         * Execute the {@link Invokable}
+         * Execute the invokable
          *
          * @throws Exception
          */
-        public void run() throws Exception;
+        void run() throws Exception;
     }
 
     /**
@@ -255,6 +254,8 @@
      * test IPrintManager.getPrintJobInfo
      */
     public void testGetPrintJobInfo() throws Exception {
+        startPrinting();
+
         assertEquals(mGoodPrintJob.getId(), mIPrintManager.getPrintJobInfo(mGoodPrintJob.getId(),
                         mAppId, mUserId).getId());
         assertEquals(null, mIPrintManager.getPrintJobInfo(mBadPrintJobId, mAppId, mUserId));
@@ -274,6 +275,8 @@
      * test IPrintManager.getPrintJobInfos
      */
     public void testGetPrintJobInfos() throws Exception {
+        startPrinting();
+
         List<PrintJobInfo> infos = mIPrintManager.getPrintJobInfos(mAppId, mUserId);
 
         boolean foundPrintJob = false;
@@ -304,7 +307,7 @@
         final IPrintDocumentAdapter adapter = new PrintManager
                 .PrintDocumentAdapterDelegate(getActivity(), createMockAdapter());
 
-        // Valid parameters are tested in setUp()
+        startPrinting();
 
         assertException(new Invokable() {
             @Override
@@ -352,6 +355,8 @@
      * test IPrintManager.cancelPrintJob
      */
     public void testCancelPrintJob() throws Exception {
+        startPrinting();
+
         // Invalid print jobs IDs do not produce an exception
         mIPrintManager.cancelPrintJob(mBadPrintJobId, mAppId, mUserId);
         mIPrintManager.cancelPrintJob(null, mAppId, mUserId);
@@ -373,6 +378,8 @@
      * test IPrintManager.restartPrintJob
      */
     public void testRestartPrintJob() throws Exception {
+        startPrinting();
+
         mIPrintManager.restartPrintJob(mGoodPrintJob.getId(), mAppId, mUserId);
 
         // Invalid print jobs IDs do not produce an exception
@@ -438,22 +445,103 @@
     }
 
     /**
-     * test IPrintManager.getInstalledPrintServices
+     * test IPrintManager.addPrintServicesChangeListener
      */
-    public void testGetInstalledPrintServices() throws Exception {
-        List<PrintServiceInfo> printServices = mIPrintManager.getInstalledPrintServices(mUserId);
-        assertTrue(printServices.size() >= 2);
+    public void testAddPrintServicesChangeListener() throws Exception {
+        final IPrintServicesChangeListener listener = createMockIPrintServicesChangeListener();
+
+        mIPrintManager.addPrintServicesChangeListener(listener, mUserId);
+
+        assertException(new Invokable() {
+            @Override
+            public void run() throws Exception {
+                mIPrintManager.addPrintServicesChangeListener(null, mUserId);
+            }
+        }, NullPointerException.class);
 
         // Cannot test bad user Id as these tests are allowed to call across users
     }
 
     /**
-     * test IPrintManager.getEnabledPrintServices
+     * test IPrintManager.removePrintServicesChangeListener
      */
-    public void testGetEnabledPrintServices() throws Exception {
-        List<PrintServiceInfo> printServices = mIPrintManager.getEnabledPrintServices(mUserId);
+    public void testRemovePrintServicesChangeListener() throws Exception {
+        final IPrintServicesChangeListener listener = createMockIPrintServicesChangeListener();
+
+        mIPrintManager.addPrintServicesChangeListener(listener, mUserId);
+        mIPrintManager.removePrintServicesChangeListener(listener, mUserId);
+
+        // Removing unknown listeners is a no-op
+        mIPrintManager.removePrintServicesChangeListener(listener, mUserId);
+
+        mIPrintManager.addPrintServicesChangeListener(listener, mUserId);
+        assertException(new Invokable() {
+            @Override
+            public void run() throws Exception {
+                mIPrintManager.removePrintServicesChangeListener(null, mUserId);
+            }
+        }, NullPointerException.class);
+
+        // Cannot test bad user Id as these tests are allowed to call across users
+    }
+
+    /**
+     * test IPrintManager.getPrintServices
+     */
+    public void testGetPrintServices() throws Exception {
+        List<PrintServiceInfo> printServices = mIPrintManager.getPrintServices(
+                PrintManager.ALL_SERVICES, mUserId);
         assertTrue(printServices.size() >= 2);
 
+        printServices = mIPrintManager.getPrintServices(0, mUserId);
+        assertEquals(printServices, null);
+
+        assertException(new Invokable() {
+            @Override
+            public void run() throws Exception {
+                mIPrintManager.getPrintServices(~PrintManager.ALL_SERVICES, mUserId);
+            }
+        }, IllegalArgumentException.class);
+
+        // Cannot test bad user Id as these tests are allowed to call across users
+    }
+
+    /**
+     * test IPrintManager.setPrintServiceEnabled
+     */
+    public void testSetPrintServiceEnabled() throws Exception {
+        final ComponentName printService = mIPrintManager.getPrintServices(
+                PrintManager.ALL_SERVICES, mUserId).get(0).getComponentName();
+
+        assertException(new Invokable() {
+            @Override
+            public void run() throws Exception {
+                mIPrintManager.setPrintServiceEnabled(printService, false, mUserId);
+            }
+        }, SecurityException.class);
+
+        assertException(new Invokable() {
+            @Override
+            public void run() throws Exception {
+                mIPrintManager.setPrintServiceEnabled(printService, true, mUserId);
+            }
+        }, SecurityException.class);
+
+        assertException(new Invokable() {
+            @Override
+            public void run() throws Exception {
+                mIPrintManager.setPrintServiceEnabled(new ComponentName("bad", "name"), true,
+                                mUserId);
+            }
+        }, SecurityException.class);
+
+        assertException(new Invokable() {
+            @Override
+            public void run() throws Exception {
+                mIPrintManager.setPrintServiceEnabled(null, true, mUserId);
+            }
+        }, SecurityException.class);
+
         // Cannot test bad user Id as these tests are allowed to call across users
     }
 
@@ -486,6 +574,8 @@
      * test IPrintManager.startPrinterDiscovery
      */
     public void testStartPrinterDiscovery() throws Exception {
+        startPrinting();
+
         final IPrinterDiscoveryObserver listener = createMockIPrinterDiscoveryObserver();
         final List<PrinterId> goodPrinters = new ArrayList<>();
         goodPrinters.add(mGoodPrinterId);
@@ -549,6 +639,8 @@
      * test IPrintManager.validatePrinters
      */
     public void testValidatePrinters() throws Exception {
+        startPrinting();
+
         final List<PrinterId> goodPrinters = new ArrayList<>();
         goodPrinters.add(mGoodPrinterId);
 
@@ -587,6 +679,8 @@
      * test IPrintManager.startPrinterStateTracking
      */
     public void testStartPrinterStateTracking() throws Exception {
+        startPrinting();
+
         mIPrintManager.startPrinterStateTracking(mGoodPrinterId, mUserId);
 
         // Bad printers do no cause exceptions
@@ -606,6 +700,8 @@
      * test IPrintManager.getCustomPrinterIcon
      */
     public void testGetCustomPrinterIcon() throws Exception {
+        startPrinting();
+
         mIPrintManager.getCustomPrinterIcon(mGoodPrinterId, mUserId);
 
         // Bad printers do no cause exceptions
@@ -625,6 +721,8 @@
      * test IPrintManager.stopPrinterStateTracking
      */
     public void testStopPrinterStateTracking() throws Exception {
+        startPrinting();
+
         mIPrintManager.startPrinterStateTracking(mGoodPrinterId, mUserId);
         mIPrintManager.stopPrinterStateTracking(mGoodPrinterId, mUserId);
 
diff --git a/core/tests/coretests/src/android/text/method/ForwardDeleteTest.java b/core/tests/coretests/src/android/text/method/ForwardDeleteTest.java
new file mode 100644
index 0000000..da17045
--- /dev/null
+++ b/core/tests/coretests/src/android/text/method/ForwardDeleteTest.java
@@ -0,0 +1,472 @@
+/*
+ * 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.text.method;
+
+import android.app.Activity;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.test.suitebuilder.annotation.Suppress;
+import android.text.InputType;
+import android.text.method.BaseKeyListener;
+import android.text.method.KeyListenerTestCase;
+import android.view.KeyEvent;
+import android.widget.EditText;
+import android.widget.TextView.BufferType;
+
+/**
+ * Test forward delete key handling of  {@link android.text.method.BaseKeyListener}.
+ *
+ * TODO: Move some of test cases to the CTS.
+ */
+public class ForwardDeleteTest extends KeyListenerTestCase {
+    private static final BaseKeyListener mKeyListener = new BaseKeyListener() {
+        public int getInputType() {
+            return InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_NORMAL;
+        }
+    };
+
+    // Sync the state to the TextView and call onKeyDown with KEYCODE_FORWARD_DEL key event.
+    // Then update the state to the result of TextView.
+    private void forwardDelete(final EditorState state, int modifiers) {
+        mActivity.runOnUiThread(new Runnable() {
+            public void run() {
+                mTextView.setText(state.mText, BufferType.EDITABLE);
+                mTextView.setKeyListener(mKeyListener);
+                mTextView.setSelection(state.mSelectionStart, state.mSelectionEnd);
+            }
+        });
+        mInstrumentation.waitForIdleSync();
+        assertTrue(mTextView.hasWindowFocus());
+
+        final KeyEvent keyEvent = getKey(KeyEvent.KEYCODE_FORWARD_DEL, modifiers);
+        mActivity.runOnUiThread(new Runnable() {
+            public void run() {
+                mTextView.onKeyDown(keyEvent.getKeyCode(), keyEvent);
+            }
+        });
+        mInstrumentation.waitForIdleSync();
+
+        state.mText = mTextView.getText();
+        state.mSelectionStart = mTextView.getSelectionStart();
+        state.mSelectionEnd = mTextView.getSelectionEnd();
+    }
+
+    @SmallTest
+    public void testSurrogatePairs() {
+        EditorState state = new EditorState();
+
+        // U+1F441 is EYE
+        state.setByString("| U+1F441");
+        forwardDelete(state, 0);
+        state.assertEquals("|");
+
+        // U+1F5E8 is LEFT SPEECH BUBBLE
+        state.setByString("| U+1F441 U+1F5E8");
+        forwardDelete(state, 0);
+        state.assertEquals("| U+1F5E8");
+        forwardDelete(state, 0);
+        state.assertEquals("|");
+
+        // TODO: introduce edge cases.
+    }
+
+    @SmallTest
+    public void testReplacementSpan() {
+        EditorState state = new EditorState();
+
+        state.setByString("| 'abc' ( 'de' ) 'fg'");
+        forwardDelete(state, 0);
+        state.assertEquals("| 'bc' ( 'de' ) 'fg'");
+        forwardDelete(state, 0);
+        state.assertEquals("| 'c' ( 'de' ) 'fg'");
+        forwardDelete(state, 0);
+        state.assertEquals("| ( 'de' ) 'fg'");
+        forwardDelete(state, 0);
+        state.assertEquals("| 'fg'");
+        forwardDelete(state, 0);
+        state.assertEquals("| 'g'");
+        forwardDelete(state, 0);
+        state.assertEquals("|");
+
+        state.setByString("'abc' [ ( 'de' ) ] 'fg'");
+        forwardDelete(state, 0);
+        state.assertEquals("'abc' | 'fg'");
+        forwardDelete(state, 0);
+        state.assertEquals("'abc' | 'g'");
+        forwardDelete(state, 0);
+        state.assertEquals("'abc' |");
+        forwardDelete(state, 0);
+        state.assertEquals("'abc' |");
+
+        state.setByString("'ab' [ 'c' ( 'de' ) 'f' ] 'g'");
+        forwardDelete(state, 0);
+        state.assertEquals("'ab' | 'g'");
+        forwardDelete(state, 0);
+        state.assertEquals("'ab' |");
+        forwardDelete(state, 0);
+        state.assertEquals("'ab' |");
+
+        // TODO: introduce edge cases.
+    }
+
+    @SmallTest
+    public void testCombiningEnclosingKeycaps() {
+        EditorState state = new EditorState();
+
+        // U+20E3 is COMBINING ENCLOSING KEYCAP.
+        state.setByString("| '1' U+20E3");
+        forwardDelete(state, 0);
+        state.assertEquals("|");
+
+        // Edge cases
+        // multiple COMBINING ENCLOSING KEYCAP
+        state.setByString("| '1' U+20E3 U+20E3");
+        forwardDelete(state, 0);
+        state.assertEquals("|");
+
+        // Isolated COMBINING ENCLOSING KEYCAP
+        state.setByString("| U+20E3");
+        forwardDelete(state, 0);
+        state.assertEquals("|");
+
+        // Isolated multiple COMBINING ENCLOSING KEYCAP
+        state.setByString("| U+20E3 U+20E3");
+        forwardDelete(state, 0);
+        state.assertEquals("|");
+    }
+
+    @SmallTest
+    public void testVariationSelector() {
+        EditorState state = new EditorState();
+
+        // U+FE0F is VARIATION SELECTOR-16.
+        state.setByString("| '#' U+FE0F");
+        forwardDelete(state, 0);
+        state.assertEquals("|");
+
+        // U+E0100 is VARIATION SELECTOR-17.
+        state.setByString("| U+845B U+E0100");
+        forwardDelete(state, 0);
+        state.assertEquals("|");
+
+        // Edge cases
+        // Isolated variation selectors
+        state.setByString("| U+FE0F");
+        forwardDelete(state, 0);
+        state.assertEquals("|");
+
+        state.setByString("| U+E0100");
+        forwardDelete(state, 0);
+        state.assertEquals("|");
+
+        // Isolated multiple variation selectors
+        state.setByString("| U+FE0F U+FE0F");
+        forwardDelete(state, 0);
+        state.assertEquals("|");
+
+        state.setByString("| U+FE0F U+E0100");
+        forwardDelete(state, 0);
+        state.assertEquals("|");
+
+        state.setByString("| U+E0100 U+FE0F");
+        forwardDelete(state, 0);
+        state.assertEquals("|");
+
+        state.setByString("| U+E0100 U+E0100");
+        forwardDelete(state, 0);
+        state.assertEquals("|");
+
+        // Multiple variation selectors
+        state.setByString("| '#' U+FE0F U+FE0F");
+        forwardDelete(state, 0);
+        state.assertEquals("|");
+
+        state.setByString("| '#' U+FE0F U+E0100");
+        forwardDelete(state, 0);
+        state.assertEquals("|");
+
+        state.setByString("| U+845B U+E0100 U+FE0F");
+        forwardDelete(state, 0);
+        state.assertEquals("|");
+
+        state.setByString("| U+845B U+E0100 U+E0100");
+        forwardDelete(state, 0);
+        state.assertEquals("|");
+    }
+
+    @SmallTest
+    public void testEmojiZeroWidthJoinerSequence() {
+        EditorState state = new EditorState();
+
+        // U+200D is ZERO WIDTH JOINER.
+        state.setByString("| U+1F441 U+200D U+1F5E8");
+        forwardDelete(state, 0);
+        state.assertEquals("|");
+
+        state.setByString("| U+1F468 U+200D U+2764 U+FE0F U+200D U+1F48B U+200D U+1F468");
+        forwardDelete(state, 0);
+        state.assertEquals("|");
+
+        // Edge cases
+        // End with ZERO WIDTH JOINER
+        state.setByString("| U+1F441 U+200D");
+        forwardDelete(state, 0);
+        state.assertEquals("|");
+
+        // Start with ZERO WIDTH JOINER
+        state.setByString("| U+200D U+1F5E8");
+        forwardDelete(state, 0);
+        state.assertEquals("| U+1F5E8");
+        forwardDelete(state, 0);
+        state.assertEquals("|");
+
+        // Multiple ZERO WIDTH JOINER
+        state.setByString("| U+1F441 U+200D U+200D U+1F5E8");
+        forwardDelete(state, 0);
+        state.assertEquals("| U+1F5E8");
+        forwardDelete(state, 0);
+        state.assertEquals("|");
+
+        // Isolated ZERO WIDTH JOINER
+        state.setByString("| U+200D");
+        forwardDelete(state, 0);
+        state.assertEquals("|");
+
+        // Isolated multiple ZERO WIDTH JOINER
+        state.setByString("| U+200D U+200D");
+        forwardDelete(state, 0);
+        state.assertEquals("|");
+    }
+
+    @SmallTest
+    public void testFlags() {
+        EditorState state = new EditorState();
+
+        // U+1F1FA is REGIONAL INDICATOR SYMBOL LETTER U.
+        // U+1F1F8 is REGIONAL INDICATOR SYMBOL LETTER S.
+        state.setByString("| U+1F1FA U+1F1F8");
+        forwardDelete(state, 0);
+        state.assertEquals("|");
+
+        state.setByString("| U+1F1FA U+1F1F8 U+1F1FA U+1F1F8");
+        forwardDelete(state, 0);
+        state.assertEquals("| U+1F1FA U+1F1F8");
+        forwardDelete(state, 0);
+        state.assertEquals("|");
+
+        // Edge cases
+        // Isolated regional indicator symbol
+        state.setByString("| U+1F1FA");
+        forwardDelete(state, 0);
+        state.assertEquals("|");
+
+        // Odd numbered regional indicator symbols
+        state.setByString("| U+1F1FA U+1F1F8 U+1F1FA");
+        forwardDelete(state, 0);
+        state.assertEquals("| U+1F1FA");
+        forwardDelete(state, 0);
+        state.assertEquals("|");
+    }
+
+    @SmallTest
+    public void testEmojiModifier() {
+        EditorState state = new EditorState();
+
+        // U+1F3FB is EMOJI MODIFIER FITZPATRICK TYPE-1-2.
+        state.setByString("| U+1F466 U+1F3FB");
+        forwardDelete(state, 0);
+        state.assertEquals("|");
+
+        // Edge cases
+        // Isolated emoji modifier
+        state.setByString("| U+1F3FB");
+        forwardDelete(state, 0);
+        state.assertEquals("|");
+
+        // Isolated multiple emoji modifier
+        state.setByString("| U+1F3FB U+1F3FB");
+        forwardDelete(state, 0);
+        state.assertEquals("| U+1F3FB");
+        forwardDelete(state, 0);
+        state.assertEquals("|");
+
+        // Multiple emoji modifiers
+        state.setByString("| U+1F466 U+1F3FB U+1F3FB");
+        forwardDelete(state, 0);
+        state.assertEquals("| U+1F3FB");
+        forwardDelete(state, 0);
+        state.assertEquals("|");
+    }
+
+    @SmallTest
+    public void testMixedEdgeCases() {
+        EditorState state = new EditorState();
+
+        // COMBINING ENCLOSING KEYCAP + variation selector
+        state.setByString("| '1' U+20E3 U+FE0F");
+        forwardDelete(state, 0);
+        state.assertEquals("|");
+
+        // Variation selector + COMBINING ENCLOSING KEYCAP
+        state.setByString("| U+2665 U+FE0F U+20E3");
+        forwardDelete(state, 0);
+        state.assertEquals("|");
+
+        // COMBINING ENCLOSING KEYCAP + ending with ZERO WIDTH JOINER
+        state.setByString("| '1' U+20E3 U+200D");
+        forwardDelete(state, 0);
+        state.assertEquals("|");
+
+        // COMBINING ENCLOSING KEYCAP + ZERO WIDTH JOINER
+        state.setByString("| '1' U+20E3 U+200D U+1F5E8");
+        forwardDelete(state, 0);
+        state.assertEquals("| U+1F5E8 ");
+
+        // Start with ZERO WIDTH JOINER + COMBINING ENCLOSING KEYCAP
+        state.setByString("| U+200D U+20E3");
+        forwardDelete(state, 0);
+        state.assertEquals("|");
+
+        // ZERO WIDTH JOINER + COMBINING ENCLOSING KEYCAP
+        state.setByString("| U+1F441 U+200D U+20E3");
+        forwardDelete(state, 0);
+        state.assertEquals("|");
+
+        // COMBINING ENCLOSING KEYCAP + regional indicator symbol
+        state.setByString("| '1' U+20E3 U+1F1FA");
+        forwardDelete(state, 0);
+        state.assertEquals("| U+1F1FA");
+        forwardDelete(state, 0);
+        state.assertEquals("|");
+
+        // Regional indicator symbol + COMBINING ENCLOSING KEYCAP
+        state.setByString("| U+1F1FA U+20E3");
+        forwardDelete(state, 0);
+        state.assertEquals("|");
+
+        // COMBINING ENCLOSING KEYCAP + emoji modifier
+        state.setByString("| '1' U+20E3 U+1F3FB");
+        forwardDelete(state, 0);
+        state.assertEquals("| U+1F3FB");
+
+        // Emoji modifier + COMBINING ENCLOSING KEYCAP
+        state.setByString("| U+1F466 U+1F3FB U+20E3");
+        forwardDelete(state, 0);
+        state.assertEquals("|");
+
+        // Variation selector + end with ZERO WIDTH JOINER
+        state.setByString("| U+2665 U+FE0F U+200D");
+        forwardDelete(state, 0);
+        state.assertEquals("|");
+
+        // Variation selector + ZERO WIDTH JOINER
+        state.setByString("| U+1F469 U+200D U+2764 U+FE0F U+200D U+1F469");
+        forwardDelete(state, 0);
+        state.assertEquals("|");
+
+        // Start with ZERO WIDTH JOINER + variation selector
+        state.setByString("| U+200D U+FE0F");
+        forwardDelete(state, 0);
+        state.assertEquals("|");
+
+        // ZERO WIDTH JOINER + variation selector
+        state.setByString("| U+1F469 U+200D U+FE0F");
+        forwardDelete(state, 0);
+        state.assertEquals("|");
+
+        // Variation selector + regional indicator symbol
+        state.setByString("| U+2665 U+FE0F U+1F1FA");
+        forwardDelete(state, 0);
+        state.assertEquals("| U+1F1FA");
+        forwardDelete(state, 0);
+        state.assertEquals("|");
+
+        // Regional indicator symbol + variation selector
+        state.setByString("| U+1F1FA U+FE0F");
+        forwardDelete(state, 0);
+        state.assertEquals("|");
+
+        // Variation selector + emoji modifier
+        state.setByString("| U+2665 U+FE0F U+1F3FB");
+        forwardDelete(state, 0);
+        state.assertEquals("| U+1F3FB");
+
+        // Emoji modifier + variation selector
+        state.setByString("| U+1F466 U+1F3FB U+FE0F");
+        forwardDelete(state, 0);
+        state.assertEquals("|");
+
+        // Start with ZERO WIDTH JOINER + regional indicator symbol
+        state.setByString("| U+200D U+1F1FA");
+        forwardDelete(state, 0);
+        state.assertEquals("| U+1F1FA");
+        forwardDelete(state, 0);
+        state.assertEquals("|");
+
+        // ZERO WIDTH JOINER + regional indicator symbol
+        state.setByString("| U+1F469 U+200D U+1F1FA");
+        forwardDelete(state, 0);
+        state.assertEquals("| U+1F1FA");
+
+        // Regional indicator symbol + end with ZERO WIDTH JOINER
+        state.setByString("| U+1F1FA U+200D");
+        forwardDelete(state, 0);
+        state.assertEquals("|");
+
+        // Regional indicator symbol + ZERO WIDTH JOINER
+        state.setByString("| U+1F1FA U+200D U+1F469");
+        forwardDelete(state, 0);
+        state.assertEquals("| U+1F469");
+        forwardDelete(state, 0);
+        state.assertEquals("|");
+
+        // Start with ZERO WIDTH JOINER + emoji modifier
+        state.setByString("| U+200D U+1F3FB");
+        forwardDelete(state, 0);
+        state.assertEquals("| U+1F3FB");
+
+        // ZERO WIDTH JOINER + emoji modifier
+        state.setByString("| U+1F469 U+200D U+1F3FB");
+        forwardDelete(state, 0);
+        state.assertEquals("| U+1F3FB");
+
+        // Emoji modifier + end with ZERO WIDTH JOINER
+        state.setByString("| U+1F466 U+1F3FB U+200D");
+        forwardDelete(state, 0);
+        state.assertEquals("|");
+
+        // Emoji modifier + ZERO WIDTH JOINER
+        state.setByString("| U+1F466 U+1F3FB U+200D U+1F469");
+        forwardDelete(state, 0);
+        state.assertEquals("| U+1F469");
+        forwardDelete(state, 0);
+        state.assertEquals("|");
+
+        // Regional indicator symbol + emoji modifier
+        state.setByString("| U+1F1FA U+1F3FB");
+        forwardDelete(state, 0);
+        state.assertEquals("| U+1F3FB");
+        forwardDelete(state, 0);
+        state.assertEquals("|");
+
+        // Emoji modifier + regional indicator symbol
+        state.setByString("| U+1F466 U+1F3FB U+1F1FA");
+        forwardDelete(state, 0);
+        state.assertEquals("| U+1F1FA");
+        forwardDelete(state, 0);
+        state.assertEquals("|");
+    }
+}
diff --git a/core/tests/coretests/src/android/transition/SlideTransitionTest.java b/core/tests/coretests/src/android/transition/SlideTransitionTest.java
new file mode 100644
index 0000000..8b9ec74
--- /dev/null
+++ b/core/tests/coretests/src/android/transition/SlideTransitionTest.java
@@ -0,0 +1,174 @@
+/*
+ * 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.transition;
+
+import android.animation.AnimatorSetActivity;
+import android.app.Activity;
+import android.test.ActivityInstrumentationTestCase2;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.view.Gravity;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.ViewTreeObserver;
+
+import com.android.frameworks.coretests.R;
+
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+
+public class SlideTransitionTest extends ActivityInstrumentationTestCase2<AnimatorSetActivity> {
+
+    Activity mActivity;
+
+    public SlideTransitionTest() {
+        super(AnimatorSetActivity.class);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        mActivity = getActivity();
+    }
+
+    @SmallTest
+    public void testShortSlide() throws Throwable {
+        final float slideFraction = 0.5f;
+        final View square1 = mActivity.findViewById(R.id.square1);
+        final View sceneRoot = mActivity.findViewById(R.id.container);
+        final SlideTranslationValueRatchet ratchet = new SlideTranslationValueRatchet(square1);
+        square1.getViewTreeObserver().addOnPreDrawListener(ratchet);
+
+        final Slide slideOut = new Slide(Gravity.BOTTOM);
+        final float finalOffsetOut = sceneRoot.getHeight() * slideFraction;
+        slideOut.setSlideFraction(slideFraction);
+        TransitionLatch latch = setVisibilityInTransition(slideOut, R.id.square1, View.INVISIBLE);
+        assertTrue(latch.startLatch.await(200, TimeUnit.MILLISECONDS));
+        assertEquals(0f, square1.getTranslationY(), 0.1f);
+        assertEquals(View.VISIBLE, square1.getVisibility());
+        Thread.sleep(100);
+        assertFalse(square1.getTranslationY() < 0.1
+                || square1.getTranslationY() > finalOffsetOut - 0.1);
+        assertTrue(latch.endLatch.await(400, TimeUnit.MILLISECONDS));
+        // Give this 20% slop in case some frames get dropped.
+        assertTrue(finalOffsetOut * 0.8 < ratchet.maxY);
+        assertTrue(finalOffsetOut + 0.1 > ratchet.maxY);
+        assertEquals(View.INVISIBLE, square1.getVisibility());
+
+        ratchet.reset();
+        final Slide slideIn = new Slide(Gravity.BOTTOM);
+        final float initialOffsetIn = sceneRoot.getHeight() * slideFraction;
+        slideIn.setSlideFraction(slideFraction);
+        latch = setVisibilityInTransition(slideIn, R.id.square1, View.VISIBLE);
+        assertTrue(latch.startLatch.await(200, TimeUnit.MILLISECONDS));
+        assertEquals(initialOffsetIn, square1.getTranslationY(), 0.1f);
+        assertEquals(View.VISIBLE, square1.getVisibility());
+        Thread.sleep(100);
+        assertFalse(square1.getTranslationY() < 0.1
+                || square1.getTranslationY() > initialOffsetIn - 0.1);
+        assertTrue(latch.endLatch.await(400, TimeUnit.MILLISECONDS));
+        assertEquals(0f, ratchet.minY, 0.1);
+        assertEquals(0f, square1.getTranslationY(), 0.1);
+        assertEquals(View.VISIBLE, square1.getVisibility());
+
+        square1.getViewTreeObserver().removeOnPreDrawListener(ratchet);
+    }
+
+    public TransitionLatch setVisibilityInTransition(final Transition transition, int viewId,
+            final int visibility) throws Throwable {
+        final ViewGroup sceneRoot = (ViewGroup) mActivity.findViewById(R.id.container);
+        final View view = sceneRoot.findViewById(viewId);
+        TransitionLatch latch = new TransitionLatch();
+        transition.addListener(latch);
+        runTestOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                TransitionManager.beginDelayedTransition(sceneRoot, transition);
+                view.setVisibility(visibility);
+            }
+        });
+        return latch;
+    }
+
+    public static class TransitionLatch implements Transition.TransitionListener {
+        public CountDownLatch startLatch = new CountDownLatch(1);
+        public CountDownLatch endLatch = new CountDownLatch(1);
+        public CountDownLatch cancelLatch = new CountDownLatch(1);
+        public CountDownLatch pauseLatch = new CountDownLatch(1);
+        public CountDownLatch resumeLatch = new CountDownLatch(1);
+
+        @Override
+        public void onTransitionStart(Transition transition) {
+            startLatch.countDown();
+        }
+
+        @Override
+        public void onTransitionEnd(Transition transition) {
+            endLatch.countDown();
+            transition.removeListener(this);
+        }
+
+        @Override
+        public void onTransitionCancel(Transition transition) {
+            cancelLatch.countDown();
+        }
+
+        @Override
+        public void onTransitionPause(Transition transition) {
+            pauseLatch.countDown();
+        }
+
+        @Override
+        public void onTransitionResume(Transition transition) {
+            resumeLatch.countDown();
+        }
+    }
+
+    private static class SlideTranslationValueRatchet
+            implements ViewTreeObserver.OnPreDrawListener {
+
+        private final View mView;
+        private boolean mInitialized;
+        public float minX = Float.NaN;
+        public float minY = Float.NaN;
+        public float maxX = Float.NaN;
+        public float maxY = Float.NaN;
+
+        public SlideTranslationValueRatchet(View view) {
+            mView = view;
+        }
+
+        public void reset() {
+            minX = minY = maxX = maxY = Float.NaN;
+            mInitialized = false;
+        }
+
+        @Override
+        public boolean onPreDraw() {
+            if (!mInitialized) {
+                minX = maxX = mView.getTranslationX();
+                minY = maxY = mView.getTranslationY();
+                mInitialized = true;
+            } else {
+                minX = Math.min(minX, mView.getTranslationX());
+                minY = Math.min(minY, mView.getTranslationY());
+                maxX = Math.max(maxX, mView.getTranslationX());
+                maxY = Math.max(maxY, mView.getTranslationY());
+            }
+            return true;
+        }
+    }
+}
diff --git a/core/tests/coretests/src/android/transition/TransitionTest.java b/core/tests/coretests/src/android/transition/TransitionTest.java
new file mode 100644
index 0000000..7e72e25
--- /dev/null
+++ b/core/tests/coretests/src/android/transition/TransitionTest.java
@@ -0,0 +1,103 @@
+/*
+ * 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.transition;
+
+import android.animation.AnimatorSetActivity;
+import android.app.Activity;
+import android.graphics.Rect;
+import android.test.ActivityInstrumentationTestCase2;
+import android.transition.Transition.EpicenterCallback;
+import android.util.ArrayMap;
+import android.view.View;
+import android.view.animation.AccelerateInterpolator;
+import android.widget.TextView;
+
+import com.android.frameworks.coretests.R;
+
+public class TransitionTest extends ActivityInstrumentationTestCase2<AnimatorSetActivity> {
+    Activity mActivity;
+    public TransitionTest() {
+        super(AnimatorSetActivity.class);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        mActivity = getActivity();
+    }
+
+    public void testClone() throws Throwable {
+        View square1 = mActivity.findViewById(R.id.square1);
+        View square2 = mActivity.findViewById(R.id.square2);
+        View square3 = mActivity.findViewById(R.id.square3);
+        Fade fade = new Fade();
+        fade.setStartDelay(1000);
+        fade.setDuration(1001);
+
+        fade.addTarget(square1);
+        fade.excludeTarget(square2, true);
+        fade.excludeChildren(square3, true);
+
+        fade.addTarget(R.id.square4);
+        fade.excludeTarget(R.id.square3, true);
+        fade.excludeChildren(R.id.square2, true);
+
+        fade.addTarget("hello");
+        fade.excludeTarget("world", true);
+
+        fade.addTarget(View.class);
+        fade.excludeTarget(TextView.class, true);
+
+        fade.setMatchOrder(Transition.MATCH_ID);
+        fade.setPropagation(new CircularPropagation());
+        fade.setPathMotion(new ArcMotion());
+        fade.setInterpolator(new AccelerateInterpolator());
+        fade.setNameOverrides(new ArrayMap<>());
+
+        EpicenterCallback epicenterCallback = new EpicenterCallback() {
+            @Override
+            public Rect onGetEpicenter(Transition transition) {
+                return null;
+            }
+        };
+
+        fade.setEpicenterCallback(epicenterCallback);
+
+        Fade clone = (Fade) fade.clone();
+        assertEquals(fade.mStartDelay, clone.mStartDelay);
+        assertEquals(fade.mDuration, clone.mDuration);
+        assertEquals(fade.mInterpolator, clone.mInterpolator);
+        assertEquals(fade.mPropagation, clone.mPropagation);
+        assertEquals(fade.getPathMotion(), clone.getPathMotion());
+        assertEquals(fade.getEpicenterCallback(), clone.getEpicenterCallback());
+        assertEquals(fade.mNameOverrides, clone.mNameOverrides);
+        assertEquals(fade.mMatchOrder, clone.mMatchOrder);
+
+        assertEquals(fade.mTargets, clone.mTargets);
+        assertEquals(fade.mTargetExcludes, clone.mTargetExcludes);
+        assertEquals(fade.mTargetChildExcludes, clone.mTargetChildExcludes);
+
+        assertEquals(fade.mTargetIds, clone.mTargetIds);
+        assertEquals(fade.mTargetIdExcludes, clone.mTargetIdExcludes);
+        assertEquals(fade.mTargetIdChildExcludes, clone.mTargetIdChildExcludes);
+
+        assertEquals(fade.mTargetNames, clone.mTargetNames);
+        assertEquals(fade.mTargetNameExcludes, clone.mTargetNameExcludes);
+
+        assertEquals(fade.mTargetTypes, clone.mTargetTypes);
+        assertEquals(fade.mTargetTypeExcludes, clone.mTargetTypeExcludes);
+    }
+}
diff --git a/core/tests/coretests/src/android/util/PatternsTest.java b/core/tests/coretests/src/android/util/PatternsTest.java
index d383775..348f8fd 100644
--- a/core/tests/coretests/src/android/util/PatternsTest.java
+++ b/core/tests/coretests/src/android/util/PatternsTest.java
@@ -25,7 +25,7 @@
 
 public class PatternsTest extends TestCase {
 
-    //Tests for Patterns.TOP_LEVEL_DOMAIN
+    // Tests for Patterns.TOP_LEVEL_DOMAIN
 
     @SmallTest
     public void testTldPattern() throws Exception {
@@ -56,7 +56,7 @@
         assertFalse("Matched invalid TLD!", t);
     }
 
-    //Tests for Patterns.IANA_TOP_LEVEL_DOMAINS
+    // Tests for Patterns.IANA_TOP_LEVEL_DOMAINS
 
     @SmallTest
     public void testIanaTopLevelDomains_matchesValidTld() throws Exception {
@@ -94,7 +94,7 @@
         assertFalse("Should not match invalid Punycode TLD", pattern.matcher("xn").matches());
     }
 
-    //Tests for Patterns.WEB_URL
+    // Tests for Patterns.WEB_URL
 
     @SmallTest
     public void testWebUrl_matchesValidUrlWithSchemeAndHostname() throws Exception {
@@ -208,7 +208,7 @@
                 Patterns.WEB_URL.matcher(url).matches());
     }
 
-    //Tests for Patterns.AUTOLINK_WEB_URL
+    // Tests for Patterns.AUTOLINK_WEB_URL
 
     @SmallTest
     public void testAutoLinkWebUrl_matchesValidUrlWithSchemeAndHostname() throws Exception {
@@ -419,7 +419,7 @@
                 Patterns.AUTOLINK_WEB_URL.matcher(url).matches());
     }
 
-    //Tests for Patterns.IP_ADDRESS
+    // Tests for Patterns.IP_ADDRESS
 
     @SmallTest
     public void testIpPattern() throws Exception {
@@ -432,7 +432,7 @@
         assertFalse("Invalid IP", t);
     }
 
-    //Tests for Patterns.DOMAIN_NAME
+    // Tests for Patterns.DOMAIN_NAME
 
     @SmallTest
     public void testDomain_matchesPunycodeTld() throws Exception {
@@ -508,7 +508,227 @@
                 Patterns.DOMAIN_NAME.matcher(domain).matches());
     }
 
-    //Tests for Patterns.PHONE
+    // Tests for Patterns.AUTOLINK_EMAIL_ADDRESS
+
+    public void testAutoLinkEmailAddress_matchesShortValidEmail() throws Exception {
+        String email = "a@a.co";
+        assertTrue("Should match short valid email: " + email,
+                Patterns.AUTOLINK_EMAIL_ADDRESS.matcher(email).matches());
+    }
+
+    public void testAutoLinkEmailAddress_matchesRegularEmail() throws Exception {
+        String email = "email@android.com";
+        assertTrue("Should match email: " + email,
+                Patterns.AUTOLINK_EMAIL_ADDRESS.matcher(email).matches());
+    }
+
+    public void testAutoLinkEmailAddress_matchesEmailWithMultipleSubdomains() throws Exception {
+        String email = "email@e.somelongdomainnameforandroid.abc.uk";
+        assertTrue("Should match email: " + email,
+                Patterns.AUTOLINK_EMAIL_ADDRESS.matcher(email).matches());
+    }
+
+    public void testAutoLinkEmailAddress_matchesLocalPartWithDot() throws Exception {
+        String email = "e.mail@android.com";
+        assertTrue("Should match email: " + email,
+                Patterns.AUTOLINK_EMAIL_ADDRESS.matcher(email).matches());
+    }
+
+    public void testAutoLinkEmailAddress_matchesLocalPartWithPlus() throws Exception {
+        String email = "e+mail@android.com";
+        assertTrue("Should match email: " + email,
+                Patterns.AUTOLINK_EMAIL_ADDRESS.matcher(email).matches());
+    }
+
+    public void testAutoLinkEmailAddress_matchesLocalPartWithUnderscore() throws Exception {
+        String email = "e_mail@android.com";
+        assertTrue("Should match email: " + email,
+                Patterns.AUTOLINK_EMAIL_ADDRESS.matcher(email).matches());
+    }
+
+    public void testAutoLinkEmailAddress_matchesLocalPartWithDash() throws Exception {
+        String email = "e-mail@android.com";
+        assertTrue("Should match email: " + email,
+                Patterns.AUTOLINK_EMAIL_ADDRESS.matcher(email).matches());
+    }
+
+    public void testAutoLinkEmailAddress_matchesLocalPartWithApostrophe() throws Exception {
+        String email = "e'mail@android.com";
+        assertTrue("Should match email: " + email,
+                Patterns.AUTOLINK_EMAIL_ADDRESS.matcher(email).matches());
+    }
+
+    public void testAutoLinkEmailAddress_matchesLocalPartWithDigits() throws Exception {
+        String email = "123@android.com";
+        assertTrue("Should match email: " + email,
+                Patterns.AUTOLINK_EMAIL_ADDRESS.matcher(email).matches());
+    }
+
+    public void testAutoLinkEmailAddress_matchesUnicodeLocalPart() throws Exception {
+        String email = "\uD604\uAE08\uC601\uC218\uC99D@android.kr";
+        assertTrue("Should match email: " + email,
+                Patterns.AUTOLINK_EMAIL_ADDRESS.matcher(email).matches());
+    }
+
+    public void testAutoLinkEmailAddress_matchesLocalPartWithEmoji() throws Exception {
+        String email = "smiley\u263A@android.com";
+        assertTrue("Should match email: " + email,
+                Patterns.AUTOLINK_EMAIL_ADDRESS.matcher(email).matches());
+    }
+
+    public void testAutoLinkEmailAddress_matchesLocalPartWithSurrogatePairs() throws Exception {
+        String email = "\uD83C\uDF38@android.com";
+        assertTrue("Should match email: " + email,
+                Patterns.AUTOLINK_EMAIL_ADDRESS.matcher(email).matches());
+    }
+
+    public void testAutoLinkEmailAddress_matchesDomainWithDash() throws Exception {
+        String email = "email@an-droid.com";
+        assertTrue("Should match email: " + email,
+                Patterns.AUTOLINK_EMAIL_ADDRESS.matcher(email).matches());
+    }
+
+    public void testAutoLinkEmailAddress_matchesUnicodeDomain() throws Exception {
+        String email = "email@\uD604\uAE08\uC601\uC218\uC99D.kr";
+        assertTrue("Should match email: " + email,
+                Patterns.AUTOLINK_EMAIL_ADDRESS.matcher(email).matches());
+    }
+
+    public void testAutoLinkEmailAddress_matchesUnicodeLocalPartAndDomain() throws Exception {
+        String email = "\uD604\uAE08\uC601\uC218\uC99D@\uD604\uAE08\uC601\uC218\uC99D.kr";
+        assertTrue("Should match email: " + email,
+                Patterns.AUTOLINK_EMAIL_ADDRESS.matcher(email).matches());
+    }
+
+    public void testAutoLinkEmailAddress_matchesDomainWithEmoji() throws Exception {
+        String email = "smiley@\u263Aandroid.com";
+        assertTrue("Should match email: " + email,
+                Patterns.AUTOLINK_EMAIL_ADDRESS.matcher(email).matches());
+    }
+
+    public void testAutoLinkEmailAddress_matchesDomainWithSurrogatePairs() throws Exception {
+        String email = "email@\uD83C\uDF38android.com";
+        assertTrue("Should match email: " + email,
+                Patterns.AUTOLINK_EMAIL_ADDRESS.matcher(email).matches());
+    }
+
+    public void testAutoLinkEmailAddress_matchesLocalPartAndDomainWithSurrogatePairs()
+            throws Exception {
+        String email = "\uD83C\uDF38@\uD83C\uDF38android.com";
+        assertTrue("Should match email: " + email,
+                Patterns.AUTOLINK_EMAIL_ADDRESS.matcher(email).matches());
+    }
+
+    public void testAutoLinkEmailAddress_doesNotMatchStringWithoutAtSign() throws Exception {
+        String email = "android.com";
+        assertFalse("Should not match email: " + email,
+                Patterns.AUTOLINK_EMAIL_ADDRESS.matcher(email).matches());
+    }
+
+    public void testAutoLinkEmailAddress_doesNotMatchPlainString() throws Exception {
+        String email = "email";
+        assertFalse("Should not match email: " + email,
+                Patterns.AUTOLINK_EMAIL_ADDRESS.matcher(email).matches());
+    }
+
+    public void testAutoLinkEmailAddress_doesNotMatchStringWithMultipleAtSigns() throws Exception {
+        String email = "email@android@android.com";
+        assertFalse("Should not match email: " + email,
+                Patterns.AUTOLINK_EMAIL_ADDRESS.matcher(email).matches());
+    }
+
+    public void testAutoLinkEmailAddress_doesNotMatchEmailWithoutTld() throws Exception {
+        String email = "email@android";
+        assertFalse("Should not match email: " + email,
+                Patterns.AUTOLINK_EMAIL_ADDRESS.matcher(email).matches());
+    }
+
+    public void testAutoLinkEmailAddress_doesNotMatchLocalPartEndingWithDot() throws Exception {
+        String email = "email.@android.com";
+        assertFalse("Should not match email: " + email,
+                Patterns.AUTOLINK_EMAIL_ADDRESS.matcher(email).matches());
+    }
+
+    public void testAutoLinkEmailAddress_doesNotMatchLocalPartStartingWithDot() throws Exception {
+        String email = ".email@android.com";
+        assertFalse("Should not match email: " + email,
+                Patterns.AUTOLINK_EMAIL_ADDRESS.matcher(email).matches());
+    }
+
+    public void testAutoLinkEmailAddress_doesNotMatchDomainStartingWithDash() throws Exception {
+        String email = "email@-android.com";
+        assertFalse("Should not match email: " + email,
+                Patterns.AUTOLINK_EMAIL_ADDRESS.matcher(email).matches());
+    }
+
+    public void testAutoLinkEmailAddress_doesNotMatchDomainWithConsecutiveDots() throws Exception {
+        String email = "email@android..com";
+        assertFalse("Should not match email: " + email,
+                Patterns.AUTOLINK_EMAIL_ADDRESS.matcher(email).matches());
+    }
+
+    public void testAutoLinkEmailAddress_doesNotMatchEmailWithIpAsDomain() throws Exception {
+        String email = "email@127.0.0.1";
+        assertFalse("Should not match email: " + email,
+                Patterns.AUTOLINK_EMAIL_ADDRESS.matcher(email).matches());
+    }
+
+    public void testAutoLinkEmailAddress_doesNotMatchEmailWithInvalidTld() throws Exception {
+        String email = "email@android.c";
+        assertFalse("Should not match email: " + email,
+                Patterns.AUTOLINK_EMAIL_ADDRESS.matcher(email).matches());
+    }
+
+    public void testAutoLinkEmailAddress_matchesLocalPartUpTo64Chars() throws Exception {
+        String localPart = "";
+        for (int i = 0; i < 64; i++) {
+            localPart += "a";
+        }
+        String email = localPart + "@android.com";
+
+        assertTrue("Should match local part of length: " + localPart.length(),
+                Patterns.AUTOLINK_EMAIL_ADDRESS.matcher(email).matches());
+
+        email = localPart + "a@android.com";
+        assertFalse("Should not match local part of length: " + localPart.length(),
+                Patterns.AUTOLINK_EMAIL_ADDRESS.matcher(email).matches());
+    }
+
+    public void testAutoLinkEmailAddress_matchesSubdomainUpTo63Chars() throws Exception {
+        String subdomain = "";
+        for (int i = 0; i < 63; i++) {
+            subdomain += "a";
+        }
+        String email = "email@" + subdomain + ".com";
+
+        assertTrue("Should match subdomain of length: " + subdomain.length(),
+                Patterns.AUTOLINK_EMAIL_ADDRESS.matcher(email).matches());
+
+        subdomain += "a";
+        email = "email@" + subdomain + ".com";
+        assertFalse("Should not match local part of length: " + subdomain.length(),
+                Patterns.AUTOLINK_EMAIL_ADDRESS.matcher(email).matches());
+    }
+
+    public void testAutoLinkEmailAddress_matchesDomainUpTo255Chars() throws Exception {
+        String longDomain = "";
+        while (longDomain.length() <= 250) {
+            longDomain += "d.";
+        }
+        longDomain += "com";
+        assertEquals(255, longDomain.length());
+        String email = "a@" + longDomain;
+
+        assertTrue("Should match domain of length: " + longDomain.length(),
+                Patterns.AUTOLINK_EMAIL_ADDRESS.matcher(email).matches());
+
+        email = email + "m";
+        assertEquals(258, email.length());
+        assertFalse("Should not match domain of length: " + longDomain.length(),
+                Patterns.AUTOLINK_EMAIL_ADDRESS.matcher(email).matches());
+    }
+
+    // Tests for Patterns.PHONE
 
     @SmallTest
     public void testPhonePattern() throws Exception {
diff --git a/core/tests/coretests/src/android/widget/TextViewActivityMouseTest.java b/core/tests/coretests/src/android/widget/TextViewActivityMouseTest.java
index 00df87d..923b829 100644
--- a/core/tests/coretests/src/android/widget/TextViewActivityMouseTest.java
+++ b/core/tests/coretests/src/android/widget/TextViewActivityMouseTest.java
@@ -143,6 +143,8 @@
 
         onView(withId(R.id.textview)).check(hasSelection(""));
         onView(withId(R.id.textview)).check(hasInsertionPointerAtIndex(text.indexOf("i")));
+
+        // TODO: Add tests for suggestions
     }
 
     @SmallTest
diff --git a/core/tests/coretests/src/android/widget/TextViewActivityTest.java b/core/tests/coretests/src/android/widget/TextViewActivityTest.java
index 5dae4a8..844eadb 100644
--- a/core/tests/coretests/src/android/widget/TextViewActivityTest.java
+++ b/core/tests/coretests/src/android/widget/TextViewActivityTest.java
@@ -44,6 +44,7 @@
 
 import com.android.frameworks.coretests.R;
 
+import android.support.test.espresso.action.EspressoKey;
 import android.test.ActivityInstrumentationTestCase2;
 import android.test.suitebuilder.annotation.SmallTest;
 import android.view.KeyEvent;
@@ -172,6 +173,12 @@
         onView(withId(R.id.textview)).check(hasSelection(""));
         assertNoSelectionHandles();
         onView(withId(R.id.textview)).check(hasInsertionPointerAtIndex("abc ghi.def".length()));
+
+        // Test undo returns to the original state.
+        onView(withId(R.id.textview)).perform(pressKey(
+                (new EspressoKey.Builder()).withCtrlPressed(true).withKeyCode(KeyEvent.KEYCODE_Z)
+                        .build()));
+        onView(withId(R.id.textview)).check(matches(withText(text)));
     }
 
     @SmallTest
diff --git a/core/tests/coretests/src/com/android/internal/inputmethod/InputMethodUtilsTest.java b/core/tests/coretests/src/com/android/internal/inputmethod/InputMethodUtilsTest.java
index ac020e4..6b5e4ad 100644
--- a/core/tests/coretests/src/com/android/internal/inputmethod/InputMethodUtilsTest.java
+++ b/core/tests/coretests/src/com/android/internal/inputmethod/InputMethodUtilsTest.java
@@ -70,6 +70,7 @@
     private static final Locale LOCALE_TH_TH_TH = new Locale("ht", "TH", "TH");
     private static final String SUBTYPE_MODE_KEYBOARD = "keyboard";
     private static final String SUBTYPE_MODE_VOICE = "voice";
+    private static final String SUBTYPE_MODE_HANDWRITING = "handwriting";
     private static final String SUBTYPE_MODE_ANY = null;
     private static final String EXTRA_VALUE_PAIR_SEPARATOR = ",";
     private static final String EXTRA_VALUE_ASCII_CAPABLE = "AsciiCapable";
@@ -215,6 +216,31 @@
         final InputMethodSubtype nonAutoJa = createDummyInputMethodSubtype("ja",
                 SUBTYPE_MODE_KEYBOARD, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE,
                 !IS_ASCII_CAPABLE, !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE);
+        final InputMethodSubtype nonAutoHi = createDummyInputMethodSubtype("hi",
+                SUBTYPE_MODE_KEYBOARD, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE,
+                !IS_ASCII_CAPABLE, !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE);
+        final InputMethodSubtype nonAutoSrCyrl = createDummyInputMethodSubtype("sr",
+                "sr-Cyrl", SUBTYPE_MODE_KEYBOARD, !IS_AUX,
+                !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, !IS_ASCII_CAPABLE,
+                !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE);
+        final InputMethodSubtype nonAutoSrLatn = createDummyInputMethodSubtype("sr_ZZ",
+                "sr-Latn", SUBTYPE_MODE_KEYBOARD, !IS_AUX,
+                !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, IS_ASCII_CAPABLE,
+                !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE);
+        final InputMethodSubtype nonAutoHandwritingEn = createDummyInputMethodSubtype("en",
+                SUBTYPE_MODE_HANDWRITING, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE,
+                !IS_ASCII_CAPABLE, !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE);
+        final InputMethodSubtype nonAutoHandwritingFr = createDummyInputMethodSubtype("fr",
+                SUBTYPE_MODE_HANDWRITING, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE,
+                !IS_ASCII_CAPABLE, !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE);
+        final InputMethodSubtype nonAutoHandwritingSrCyrl = createDummyInputMethodSubtype("sr",
+                "sr-Cyrl", SUBTYPE_MODE_HANDWRITING, !IS_AUX,
+                !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, !IS_ASCII_CAPABLE,
+                !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE);
+        final InputMethodSubtype nonAutoHandwritingSrLatn = createDummyInputMethodSubtype("sr_ZZ",
+                "sr-Latn", SUBTYPE_MODE_HANDWRITING, !IS_AUX,
+                !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, !IS_ASCII_CAPABLE,
+                !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE);
         final InputMethodSubtype nonAutoEnabledWhenDefaultIsNotAsciiCalableSubtype =
                 createDummyInputMethodSubtype("zz", SUBTYPE_MODE_KEYBOARD, !IS_AUX,
                         !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, !IS_ASCII_CAPABLE,
@@ -235,6 +261,8 @@
             subtypes.add(autoSubtype);  // overridesImplicitlyEnabledSubtype == true
             subtypes.add(nonAutoEnabledWhenDefaultIsNotAsciiCalableSubtype);
             subtypes.add(nonAutoEnabledWhenDefaultIsNotAsciiCalableSubtype2);
+            subtypes.add(nonAutoHandwritingEn);
+            subtypes.add(nonAutoHandwritingFr);
             final InputMethodInfo imi = createDummyInputMethodInfo(
                     "com.android.apps.inputmethod.latin",
                     "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT,
@@ -257,6 +285,8 @@
             subtypes.add(nonAutoFil);
             subtypes.add(nonAutoEnabledWhenDefaultIsNotAsciiCalableSubtype);
             subtypes.add(nonAutoEnabledWhenDefaultIsNotAsciiCalableSubtype2);
+            subtypes.add(nonAutoHandwritingEn);
+            subtypes.add(nonAutoHandwritingFr);
             final InputMethodInfo imi = createDummyInputMethodInfo(
                     "com.android.apps.inputmethod.latin",
                     "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT,
@@ -264,7 +294,9 @@
             final ArrayList<InputMethodSubtype> result =
                     InputMethodUtils.getImplicitlyApplicableSubtypesLocked(
                             getResourcesForLocales(LOCALE_EN_US), imi);
+            assertEquals(2, result.size());
             verifyEquality(nonAutoEnUS, result.get(0));
+            verifyEquality(nonAutoHandwritingEn, result.get(1));
         }
 
         // Make sure that a subtype whose locale is exactly equal to the specified locale is
@@ -277,6 +309,8 @@
             subtypes.add(nonAutoJa);
             subtypes.add(nonAutoFil);
             subtypes.add(nonAutoEnabledWhenDefaultIsNotAsciiCalableSubtype);
+            subtypes.add(nonAutoHandwritingEn);
+            subtypes.add(nonAutoHandwritingFr);
             final InputMethodInfo imi = createDummyInputMethodInfo(
                     "com.android.apps.inputmethod.latin",
                     "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT,
@@ -284,8 +318,9 @@
             final ArrayList<InputMethodSubtype> result =
                     InputMethodUtils.getImplicitlyApplicableSubtypesLocked(
                             getResourcesForLocales(LOCALE_EN_GB), imi);
-            assertEquals(1, result.size());
+            assertEquals(2, result.size());
             verifyEquality(nonAutoEnGB, result.get(0));
+            verifyEquality(nonAutoHandwritingEn, result.get(1));
         }
 
         // If there is no automatic subtype (overridesImplicitlyEnabledSubtype:true) and
@@ -299,6 +334,8 @@
             subtypes.add(nonAutoFil);
             subtypes.add(nonAutoEnabledWhenDefaultIsNotAsciiCalableSubtype);
             subtypes.add(nonAutoEnabledWhenDefaultIsNotAsciiCalableSubtype2);
+            subtypes.add(nonAutoHandwritingEn);
+            subtypes.add(nonAutoHandwritingFr);
             final InputMethodInfo imi = createDummyInputMethodInfo(
                     "com.android.apps.inputmethod.latin",
                     "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT,
@@ -306,8 +343,9 @@
             final ArrayList<InputMethodSubtype> result =
                     InputMethodUtils.getImplicitlyApplicableSubtypesLocked(
                             getResourcesForLocales(LOCALE_FR), imi);
-            assertEquals(1, result.size());
+            assertEquals(2, result.size());
             verifyEquality(nonAutoFrCA, result.get(0));
+            verifyEquality(nonAutoHandwritingFr, result.get(1));
         }
         // Then make sure that a subtype (locale: "fr") can be found with locale: "fr_CA".
         {
@@ -317,6 +355,8 @@
             subtypes.add(nonAutoFil);
             subtypes.add(nonAutoEnabledWhenDefaultIsNotAsciiCalableSubtype);
             subtypes.add(nonAutoEnabledWhenDefaultIsNotAsciiCalableSubtype2);
+            subtypes.add(nonAutoHandwritingEn);
+            subtypes.add(nonAutoHandwritingFr);
             final InputMethodInfo imi = createDummyInputMethodInfo(
                     "com.android.apps.inputmethod.latin",
                     "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT,
@@ -324,8 +364,9 @@
             final ArrayList<InputMethodSubtype> result =
                     InputMethodUtils.getImplicitlyApplicableSubtypesLocked(
                             getResourcesForLocales(LOCALE_FR_CA), imi);
-            assertEquals(1, result.size());
+            assertEquals(2, result.size());
             verifyEquality(nonAutoFrCA, result.get(0));
+            verifyEquality(nonAutoHandwritingFr, result.get(1));
         }
 
         // Make sure that subtypes which have "EnabledWhenDefaultIsNotAsciiCapable" in its
@@ -336,6 +377,8 @@
             subtypes.add(nonAutoJa);    // not ASCII capable
             subtypes.add(nonAutoEnabledWhenDefaultIsNotAsciiCalableSubtype);
             subtypes.add(nonAutoEnabledWhenDefaultIsNotAsciiCalableSubtype2);
+            subtypes.add(nonAutoHandwritingEn);
+            subtypes.add(nonAutoHandwritingFr);
             final InputMethodInfo imi = createDummyInputMethodInfo(
                     "com.android.apps.inputmethod.latin",
                     "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT,
@@ -349,6 +392,139 @@
             verifyEquality(nonAutoEnabledWhenDefaultIsNotAsciiCalableSubtype2, result.get(2));
         }
 
+        // Make sure that if there is no subtype that matches the language requested, then we just
+        // use the first keyboard subtype.
+        {
+            final ArrayList<InputMethodSubtype> subtypes = new ArrayList<>();
+            subtypes.add(nonAutoHi);
+            subtypes.add(nonAutoEnUS);
+            subtypes.add(nonAutoHandwritingEn);
+            subtypes.add(nonAutoHandwritingFr);
+            subtypes.add(nonAutoEnabledWhenDefaultIsNotAsciiCalableSubtype);
+            final InputMethodInfo imi = createDummyInputMethodInfo(
+                    "com.android.apps.inputmethod.latin",
+                    "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT,
+                    subtypes);
+            final ArrayList<InputMethodSubtype> result =
+                    InputMethodUtils.getImplicitlyApplicableSubtypesLocked(
+                            getResourcesForLocales(LOCALE_JA_JP), imi);
+            assertEquals(1, result.size());
+            verifyEquality(nonAutoHi, result.get(0));
+        }
+        {
+            final ArrayList<InputMethodSubtype> subtypes = new ArrayList<>();
+            subtypes.add(nonAutoEnUS);
+            subtypes.add(nonAutoHi);
+            subtypes.add(nonAutoHandwritingEn);
+            subtypes.add(nonAutoHandwritingFr);
+            subtypes.add(nonAutoEnabledWhenDefaultIsNotAsciiCalableSubtype);
+            final InputMethodInfo imi = createDummyInputMethodInfo(
+                    "com.android.apps.inputmethod.latin",
+                    "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT,
+                    subtypes);
+            final ArrayList<InputMethodSubtype> result =
+                    InputMethodUtils.getImplicitlyApplicableSubtypesLocked(
+                            getResourcesForLocales(LOCALE_JA_JP), imi);
+            assertEquals(1, result.size());
+            verifyEquality(nonAutoEnUS, result.get(0));
+        }
+        {
+            final ArrayList<InputMethodSubtype> subtypes = new ArrayList<>();
+            subtypes.add(nonAutoHandwritingEn);
+            subtypes.add(nonAutoHandwritingFr);
+            subtypes.add(nonAutoEnUS);
+            subtypes.add(nonAutoHi);
+            subtypes.add(nonAutoEnabledWhenDefaultIsNotAsciiCalableSubtype);
+            final InputMethodInfo imi = createDummyInputMethodInfo(
+                    "com.android.apps.inputmethod.latin",
+                    "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT,
+                    subtypes);
+            final ArrayList<InputMethodSubtype> result =
+                    InputMethodUtils.getImplicitlyApplicableSubtypesLocked(
+                            getResourcesForLocales(LOCALE_JA_JP), imi);
+            assertEquals(1, result.size());
+            verifyEquality(nonAutoEnUS, result.get(0));
+        }
+
+        // Make sure that both language and script are taken into account to find the best matching
+        // subtype.
+        {
+            final ArrayList<InputMethodSubtype> subtypes = new ArrayList<>();
+            subtypes.add(nonAutoEnUS);
+            subtypes.add(nonAutoSrCyrl);
+            subtypes.add(nonAutoSrLatn);
+            subtypes.add(nonAutoHandwritingEn);
+            subtypes.add(nonAutoHandwritingFr);
+            subtypes.add(nonAutoHandwritingSrCyrl);
+            subtypes.add(nonAutoHandwritingSrLatn);
+            final InputMethodInfo imi = createDummyInputMethodInfo(
+                    "com.android.apps.inputmethod.latin",
+                    "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT,
+                    subtypes);
+            final ArrayList<InputMethodSubtype> result =
+                    InputMethodUtils.getImplicitlyApplicableSubtypesLocked(
+                            getResourcesForLocales(Locale.forLanguageTag("sr-Latn-RS")), imi);
+            assertEquals(2, result.size());
+            assertThat(nonAutoSrLatn, isIn(result));
+            assertThat(nonAutoHandwritingSrLatn, isIn(result));
+        }
+        {
+            final ArrayList<InputMethodSubtype> subtypes = new ArrayList<>();
+            subtypes.add(nonAutoEnUS);
+            subtypes.add(nonAutoSrCyrl);
+            subtypes.add(nonAutoSrLatn);
+            subtypes.add(nonAutoHandwritingEn);
+            subtypes.add(nonAutoHandwritingFr);
+            subtypes.add(nonAutoHandwritingSrCyrl);
+            subtypes.add(nonAutoHandwritingSrLatn);
+            final InputMethodInfo imi = createDummyInputMethodInfo(
+                    "com.android.apps.inputmethod.latin",
+                    "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT,
+                    subtypes);
+            final ArrayList<InputMethodSubtype> result =
+                    InputMethodUtils.getImplicitlyApplicableSubtypesLocked(
+                            getResourcesForLocales(Locale.forLanguageTag("sr-Cyrl-RS")), imi);
+            assertEquals(2, result.size());
+            assertThat(nonAutoSrCyrl, isIn(result));
+            assertThat(nonAutoHandwritingSrCyrl, isIn(result));
+        }
+
+        // Make sure that secondary locales are taken into account to find the best matching
+        // subtype.
+        {
+            final ArrayList<InputMethodSubtype> subtypes = new ArrayList<>();
+            subtypes.add(nonAutoEnUS);
+            subtypes.add(nonAutoEnGB);
+            subtypes.add(nonAutoSrCyrl);
+            subtypes.add(nonAutoSrLatn);
+            subtypes.add(nonAutoFr);
+            subtypes.add(nonAutoFrCA);
+            subtypes.add(nonAutoHandwritingEn);
+            subtypes.add(nonAutoHandwritingFr);
+            subtypes.add(nonAutoHandwritingSrCyrl);
+            subtypes.add(nonAutoHandwritingSrLatn);
+            final InputMethodInfo imi = createDummyInputMethodInfo(
+                    "com.android.apps.inputmethod.latin",
+                    "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT,
+                    subtypes);
+            final ArrayList<InputMethodSubtype> result =
+                    InputMethodUtils.getImplicitlyApplicableSubtypesLocked(
+                            getResourcesForLocales(
+                                    Locale.forLanguageTag("sr-Latn-RS-x-android"),
+                                    Locale.forLanguageTag("ja-JP"),
+                                    Locale.forLanguageTag("fr-FR"),
+                                    Locale.forLanguageTag("en-GB"),
+                                    Locale.forLanguageTag("en-US")),
+                            imi);
+            assertEquals(6, result.size());
+            assertThat(nonAutoEnGB, isIn(result));
+            assertThat(nonAutoFr, isIn(result));
+            assertThat(nonAutoSrLatn, isIn(result));
+            assertThat(nonAutoHandwritingEn, isIn(result));
+            assertThat(nonAutoHandwritingFr, isIn(result));
+            assertThat(nonAutoHandwritingSrLatn, isIn(result));
+        }
+
         // Make sure that 3-letter language code can be handled.
         {
             final ArrayList<InputMethodSubtype> subtypes = new ArrayList<>();
@@ -697,7 +873,15 @@
     private static InputMethodSubtype createDummyInputMethodSubtype(String locale, String mode,
             boolean isAuxiliary, boolean overridesImplicitlyEnabledSubtype,
             boolean isAsciiCapable, boolean isEnabledWhenDefaultIsNotAsciiCapable) {
+        return createDummyInputMethodSubtype(locale, null /* languageTag */, mode, isAuxiliary,
+                overridesImplicitlyEnabledSubtype, isAsciiCapable,
+                isEnabledWhenDefaultIsNotAsciiCapable);
+    }
 
+    private static InputMethodSubtype createDummyInputMethodSubtype(String locale,
+            String languageTag, String mode, boolean isAuxiliary,
+            boolean overridesImplicitlyEnabledSubtype, boolean isAsciiCapable,
+            boolean isEnabledWhenDefaultIsNotAsciiCapable) {
         final StringBuilder subtypeExtraValue = new StringBuilder();
         if (isEnabledWhenDefaultIsNotAsciiCapable) {
             subtypeExtraValue.append(EXTRA_VALUE_PAIR_SEPARATOR);
@@ -715,6 +899,7 @@
                 .setSubtypeNameResId(0)
                 .setSubtypeIconResId(0)
                 .setSubtypeLocale(locale)
+                .setLanguageTag(languageTag)
                 .setSubtypeMode(mode)
                 .setSubtypeExtraValue(subtypeExtraValue.toString())
                 .setIsAuxiliary(isAuxiliary)
diff --git a/core/tests/coretests/src/com/android/internal/inputmethod/LocaleUtilsTest.java b/core/tests/coretests/src/com/android/internal/inputmethod/LocaleUtilsTest.java
index b9c2da7..deba40f 100644
--- a/core/tests/coretests/src/com/android/internal/inputmethod/LocaleUtilsTest.java
+++ b/core/tests/coretests/src/com/android/internal/inputmethod/LocaleUtilsTest.java
@@ -50,6 +50,22 @@
     }
 
     @SmallTest
+    public void testFilterDoesNotMatchAnything() throws Exception {
+        final ArrayList<Locale> availableLocales = new ArrayList<>();
+        availableLocales.add(Locale.forLanguageTag("en-US"));
+        availableLocales.add(Locale.forLanguageTag("fr-CA"));
+        availableLocales.add(Locale.forLanguageTag("in"));
+        availableLocales.add(Locale.forLanguageTag("ja"));
+        availableLocales.add(Locale.forLanguageTag("fil"));
+
+        final LocaleList preferredLocales = LocaleList.forLanguageTags("zh-Hans-TW");
+
+        final ArrayList<Locale> dest = new ArrayList<>();
+        LocaleUtils.filterByLanguage(availableLocales, sIdentityMapper, preferredLocales, dest);
+        assertEquals(0, dest.size());
+    }
+
+    @SmallTest
     public void testFilterByLanguageEmptySource() throws Exception {
         final ArrayList<Locale> availableLocales = new ArrayList<>();
 
@@ -124,21 +140,36 @@
 
     @SmallTest
     public void testFilterByLanguage() throws Exception {
-        final ArrayList<Locale> availableLocales = new ArrayList<>();
-        availableLocales.add(Locale.forLanguageTag("en-US"));
-        availableLocales.add(Locale.forLanguageTag("fr-CA"));
-        availableLocales.add(Locale.forLanguageTag("in"));
-        availableLocales.add(Locale.forLanguageTag("ja"));
-        availableLocales.add(Locale.forLanguageTag("fil"));
+        {
+            final ArrayList<Locale> availableLocales = new ArrayList<>();
+            availableLocales.add(Locale.forLanguageTag("en-US"));
+            availableLocales.add(Locale.forLanguageTag("fr-CA"));
+            availableLocales.add(Locale.forLanguageTag("in"));
+            availableLocales.add(Locale.forLanguageTag("ja"));
+            availableLocales.add(Locale.forLanguageTag("fil"));
 
-        final LocaleList preferredLocales = LocaleList.forLanguageTags("fr,en-US,ja-JP");
+            final LocaleList preferredLocales = LocaleList.forLanguageTags("fr,en-US,ja-JP");
 
-        final ArrayList<Locale> dest = new ArrayList<>();
-        LocaleUtils.filterByLanguage(availableLocales, sIdentityMapper, preferredLocales, dest);
-        assertEquals(3, dest.size());
-        assertEquals(availableLocales.get(1), dest.get(0));  // "fr-CA"
-        assertEquals(availableLocales.get(0), dest.get(1));  // "en-US"
-        assertEquals(availableLocales.get(3), dest.get(2));  // "ja"
+            final ArrayList<Locale> dest = new ArrayList<>();
+            LocaleUtils.filterByLanguage(availableLocales, sIdentityMapper, preferredLocales, dest);
+            assertEquals(3, dest.size());
+            assertEquals(availableLocales.get(1), dest.get(0));  // "fr-CA"
+            assertEquals(availableLocales.get(0), dest.get(1));  // "en-US"
+            assertEquals(availableLocales.get(3), dest.get(2));  // "ja"
+        }
+        {
+            final ArrayList<Locale> availableLocales = new ArrayList<>();
+            availableLocales.add(Locale.forLanguageTag("en-US"));
+            availableLocales.add(Locale.forLanguageTag("en-GB"));
+            availableLocales.add(Locale.forLanguageTag("en-IN"));
+
+            final LocaleList preferredLocales = LocaleList.forLanguageTags("en-US");
+
+            final ArrayList<Locale> dest = new ArrayList<>();
+            LocaleUtils.filterByLanguage(availableLocales, sIdentityMapper, preferredLocales, dest);
+            assertEquals(1, dest.size());
+            assertEquals(availableLocales.get(0), dest.get(0));  // "en-US"
+        }
     }
 
     @SmallTest
@@ -191,4 +222,165 @@
             assertEquals(availableLocales.get(1), dest.get(0));  // "en-CA"
         }
     }
+
+    @SmallTest
+    public void testFilterByLanguageFallbackRules() throws Exception {
+        {
+            final LocaleList preferredLocales = LocaleList.forLanguageTags("sr-Latn-RS");
+            final ArrayList<Locale> availableLocales = new ArrayList<>();
+            availableLocales.add(Locale.forLanguageTag("sr-Cyrl-BA"));
+            availableLocales.add(Locale.forLanguageTag("sr-Cyrl-CS"));
+            availableLocales.add(Locale.forLanguageTag("sr-Cyrl-ME"));
+            availableLocales.add(Locale.forLanguageTag("sr-Cyrl-RS"));
+            availableLocales.add(Locale.forLanguageTag("sr-Latn-BA"));
+            availableLocales.add(Locale.forLanguageTag("sr-Latn-CS"));
+            availableLocales.add(Locale.forLanguageTag("sr-Latn-ME"));
+            availableLocales.add(Locale.forLanguageTag("sr-Latn-RS"));
+            final ArrayList<Locale> dest = new ArrayList<>();
+            LocaleUtils.filterByLanguage(availableLocales, sIdentityMapper, preferredLocales, dest);
+            assertEquals(1, dest.size());
+            assertEquals(availableLocales.get(7), dest.get(0));  // "sr-Latn-RS"
+        }
+        {
+            final LocaleList preferredLocales = LocaleList.forLanguageTags("sr-Latn-RS-x-android");
+            final ArrayList<Locale> availableLocales = new ArrayList<>();
+            availableLocales.add(Locale.forLanguageTag("sr-Cyrl-BA"));
+            availableLocales.add(Locale.forLanguageTag("sr-Cyrl-CS"));
+            availableLocales.add(Locale.forLanguageTag("sr-Cyrl-ME"));
+            availableLocales.add(Locale.forLanguageTag("sr-Cyrl-RS"));
+            availableLocales.add(Locale.forLanguageTag("sr-Latn-BA"));
+            availableLocales.add(Locale.forLanguageTag("sr-Latn-CS"));
+            availableLocales.add(Locale.forLanguageTag("sr-Latn-ME"));
+            availableLocales.add(Locale.forLanguageTag("sr-Latn-RS"));
+            final ArrayList<Locale> dest = new ArrayList<>();
+            LocaleUtils.filterByLanguage(availableLocales, sIdentityMapper, preferredLocales, dest);
+            assertEquals(1, dest.size());
+            assertEquals(availableLocales.get(7), dest.get(0));  // "sr-Latn-RS"
+        }
+        {
+            final LocaleList preferredLocales = LocaleList.forLanguageTags("sr-Latn-RS");
+            final ArrayList<Locale> availableLocales = new ArrayList<>();
+            availableLocales.add(Locale.forLanguageTag("sr-Cyrl-BA-x-android"));
+            availableLocales.add(Locale.forLanguageTag("sr-Cyrl-CS-x-android"));
+            availableLocales.add(Locale.forLanguageTag("sr-Cyrl-ME-x-android"));
+            availableLocales.add(Locale.forLanguageTag("sr-Cyrl-RS-x-android"));
+            availableLocales.add(Locale.forLanguageTag("sr-Latn-BA-x-android"));
+            availableLocales.add(Locale.forLanguageTag("sr-Latn-CS-x-android"));
+            availableLocales.add(Locale.forLanguageTag("sr-Latn-ME-x-android"));
+            availableLocales.add(Locale.forLanguageTag("sr-Latn-RS-x-android"));
+            final ArrayList<Locale> dest = new ArrayList<>();
+            LocaleUtils.filterByLanguage(availableLocales, sIdentityMapper, preferredLocales, dest);
+            assertEquals(1, dest.size());
+            assertEquals(availableLocales.get(7), dest.get(0));  // "sr-Latn-RS-x-android"
+        }
+
+        {
+            final LocaleList preferredLocales = LocaleList.forLanguageTags("sr-Latn-RS");
+            final ArrayList<Locale> availableLocales = new ArrayList<>();
+            availableLocales.add(Locale.forLanguageTag("sr"));
+            availableLocales.add(Locale.forLanguageTag("sr-Cyrl"));
+            availableLocales.add(Locale.forLanguageTag("sr-Latn"));
+            final ArrayList<Locale> dest = new ArrayList<>();
+            LocaleUtils.filterByLanguage(availableLocales, sIdentityMapper, preferredLocales, dest);
+            assertEquals(1, dest.size());
+            assertEquals(availableLocales.get(2), dest.get(0));  // "sr-Latn"
+        }
+
+        {
+            final LocaleList preferredLocales = LocaleList.forLanguageTags("sr-RS");
+            final ArrayList<Locale> availableLocales = new ArrayList<>();
+            availableLocales.add(Locale.forLanguageTag("sr"));
+            availableLocales.add(Locale.forLanguageTag("sr-RS"));
+            availableLocales.add(Locale.forLanguageTag("sr-Latn"));
+            final ArrayList<Locale> dest = new ArrayList<>();
+            LocaleUtils.filterByLanguage(availableLocales, sIdentityMapper, preferredLocales, dest);
+            assertEquals(1, dest.size());
+            assertEquals(availableLocales.get(0), dest.get(0));  // "sr"
+        }
+
+        {
+            final LocaleList preferredLocales = LocaleList.forLanguageTags("sr-Latn");
+            final ArrayList<Locale> availableLocales = new ArrayList<>();
+            availableLocales.add(Locale.forLanguageTag("sr"));
+            availableLocales.add(Locale.forLanguageTag("sr-RS"));
+            availableLocales.add(Locale.forLanguageTag("sr-Latn"));
+            final ArrayList<Locale> dest = new ArrayList<>();
+            LocaleUtils.filterByLanguage(availableLocales, sIdentityMapper, preferredLocales, dest);
+            assertEquals(1, dest.size());
+            assertEquals(availableLocales.get(2), dest.get(0));  // "sr-Latn"
+        }
+
+        {
+            final LocaleList preferredLocales = LocaleList.forLanguageTags("sr");
+            final ArrayList<Locale> availableLocales = new ArrayList<>();
+            availableLocales.add(Locale.forLanguageTag("sr"));
+            availableLocales.add(Locale.forLanguageTag("sr-RS"));
+            availableLocales.add(Locale.forLanguageTag("sr-Latn"));
+            final ArrayList<Locale> dest = new ArrayList<>();
+            LocaleUtils.filterByLanguage(availableLocales, sIdentityMapper, preferredLocales, dest);
+            assertEquals(1, dest.size());
+            assertEquals(availableLocales.get(0), dest.get(0));  // "sr"
+        }
+        {
+            final LocaleList preferredLocales = LocaleList.forLanguageTags("sr");
+            final ArrayList<Locale> availableLocales = new ArrayList<>();
+            availableLocales.add(Locale.forLanguageTag("sr-Latn"));
+            availableLocales.add(Locale.forLanguageTag("sr-RS"));
+            availableLocales.add(Locale.forLanguageTag("sr"));
+            final ArrayList<Locale> dest = new ArrayList<>();
+            LocaleUtils.filterByLanguage(availableLocales, sIdentityMapper, preferredLocales, dest);
+            assertEquals(1, dest.size());
+            assertEquals(availableLocales.get(1), dest.get(0));  // "sr-RS"
+        }
+
+        {
+            final LocaleList preferredLocales = LocaleList.forLanguageTags("sr");
+            final ArrayList<Locale> availableLocales = new ArrayList<>();
+            availableLocales.add(Locale.forLanguageTag("sr-Cyrl-RS"));
+            availableLocales.add(Locale.forLanguageTag("sr-Latn-RS"));
+            final ArrayList<Locale> dest = new ArrayList<>();
+            LocaleUtils.filterByLanguage(availableLocales, sIdentityMapper, preferredLocales, dest);
+            assertEquals(1, dest.size());
+            assertEquals(availableLocales.get(0), dest.get(0));  // "sr-Cyrl-RS"
+        }
+        {
+            final LocaleList preferredLocales = LocaleList.forLanguageTags("sr-Latn");
+            final ArrayList<Locale> availableLocales = new ArrayList<>();
+            availableLocales.add(Locale.forLanguageTag("sr-Latn-RS"));
+            availableLocales.add(Locale.forLanguageTag("sr-Cyrl-RS"));
+            final ArrayList<Locale> dest = new ArrayList<>();
+            LocaleUtils.filterByLanguage(availableLocales, sIdentityMapper, preferredLocales, dest);
+            assertEquals(1, dest.size());
+            assertEquals(availableLocales.get(0), dest.get(0));  // "sr-Latn-RS"
+        }
+    }
+
+    public void testFilterKnownLimitation() throws Exception {
+        // Following test cases are not for intentional behavior but checks for preventing the
+        // behavior from becoming worse.
+        {
+            final LocaleList preferredLocales = LocaleList.forLanguageTags("ja-Hrkt");
+            final ArrayList<Locale> availableLocales = new ArrayList<>();
+            availableLocales.add(Locale.forLanguageTag("ja-Jpan"));
+            availableLocales.add(Locale.forLanguageTag("ja-Hrkt"));
+            final ArrayList<Locale> dest = new ArrayList<>();
+            LocaleUtils.filterByLanguage(availableLocales, sIdentityMapper, preferredLocales, dest);
+            assertEquals(1, dest.size());
+            // Should be ja-Jpan since it supports ja-Hrkt and listed before ja-Hrkt.
+            assertEquals(availableLocales.get(1), dest.get(0));
+        }
+        {
+            final LocaleList preferredLocales = LocaleList.forLanguageTags("zh-Hani");
+            final ArrayList<Locale> availableLocales = new ArrayList<>();
+            availableLocales.add(Locale.forLanguageTag("zh-Hans"));
+            availableLocales.add(Locale.forLanguageTag("zh-Hant"));
+            availableLocales.add(Locale.forLanguageTag("zh-Hanb"));
+            availableLocales.add(Locale.forLanguageTag("zh-Hani"));
+            final ArrayList<Locale> dest = new ArrayList<>();
+            LocaleUtils.filterByLanguage(availableLocales, sIdentityMapper, preferredLocales, dest);
+            assertEquals(1, dest.size());
+            // Should be zh-Hans since it supports zh-Hani. Also zh-Hant, zh-Hanb supports zh-Hani.
+            assertEquals(availableLocales.get(3), dest.get(0));
+        }
+    }
 }
diff --git a/core/tests/coretests/src/com/android/internal/util/ArrayUtilsTest.java b/core/tests/coretests/src/com/android/internal/util/ArrayUtilsTest.java
new file mode 100644
index 0000000..b3897ce
--- /dev/null
+++ b/core/tests/coretests/src/com/android/internal/util/ArrayUtilsTest.java
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.android.internal.util;
+
+import android.test.suitebuilder.annotation.SmallTest;
+import junit.framework.TestCase;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+
+public class ArrayUtilsTest extends TestCase {
+
+    @SmallTest
+    public void testUnstableRemoveIf() throws Exception {
+        java.util.function.Predicate<Object> isNull = new java.util.function.Predicate<Object>() {
+            @Override
+            public boolean test(Object o) {
+                return o == null;
+            }
+        };
+
+        final Object a = new Object();
+        final Object b = new Object();
+        final Object c = new Object();
+
+        ArrayList<Object> collection = null;
+        assertEquals(0, ArrayUtils.unstableRemoveIf(collection, isNull));
+
+        collection = new ArrayList<>();
+        assertEquals(0, ArrayUtils.unstableRemoveIf(collection, isNull));
+
+        collection = new ArrayList<>(Collections.singletonList(a));
+        assertEquals(0, ArrayUtils.unstableRemoveIf(collection, isNull));
+        assertEquals(1, collection.size());
+        assertTrue(collection.contains(a));
+
+        collection = new ArrayList<>(Collections.singletonList(null));
+        assertEquals(1, ArrayUtils.unstableRemoveIf(collection, isNull));
+        assertEquals(0, collection.size());
+
+        collection = new ArrayList<>(Arrays.asList(a, b));
+        assertEquals(0, ArrayUtils.unstableRemoveIf(collection, isNull));
+        assertEquals(2, collection.size());
+        assertTrue(collection.contains(a));
+        assertTrue(collection.contains(b));
+
+        collection = new ArrayList<>(Arrays.asList(a, null));
+        assertEquals(1, ArrayUtils.unstableRemoveIf(collection, isNull));
+        assertEquals(1, collection.size());
+        assertTrue(collection.contains(a));
+
+        collection = new ArrayList<>(Arrays.asList(null, a));
+        assertEquals(1, ArrayUtils.unstableRemoveIf(collection, isNull));
+        assertEquals(1, collection.size());
+        assertTrue(collection.contains(a));
+
+        collection = new ArrayList<>(Arrays.asList(null, null));
+        assertEquals(2, ArrayUtils.unstableRemoveIf(collection, isNull));
+        assertEquals(0, collection.size());
+
+        collection = new ArrayList<>(Arrays.asList(a, b, c));
+        assertEquals(0, ArrayUtils.unstableRemoveIf(collection, isNull));
+        assertEquals(3, collection.size());
+        assertTrue(collection.contains(a));
+        assertTrue(collection.contains(b));
+        assertTrue(collection.contains(c));
+
+        collection = new ArrayList<>(Arrays.asList(a, b, null));
+        assertEquals(1, ArrayUtils.unstableRemoveIf(collection, isNull));
+        assertEquals(2, collection.size());
+        assertTrue(collection.contains(a));
+        assertTrue(collection.contains(b));
+
+        collection = new ArrayList<>(Arrays.asList(a, null, b));
+        assertEquals(1, ArrayUtils.unstableRemoveIf(collection, isNull));
+        assertEquals(2, collection.size());
+        assertTrue(collection.contains(a));
+        assertTrue(collection.contains(b));
+
+        collection = new ArrayList<>(Arrays.asList(null, a, b));
+        assertEquals(1, ArrayUtils.unstableRemoveIf(collection, isNull));
+        assertEquals(2, collection.size());
+        assertTrue(collection.contains(a));
+        assertTrue(collection.contains(b));
+
+        collection = new ArrayList<>(Arrays.asList(a, null, null));
+        assertEquals(2, ArrayUtils.unstableRemoveIf(collection, isNull));
+        assertEquals(1, collection.size());
+        assertTrue(collection.contains(a));
+
+        collection = new ArrayList<>(Arrays.asList(null, null, a));
+        assertEquals(2, ArrayUtils.unstableRemoveIf(collection, isNull));
+        assertEquals(1, collection.size());
+        assertTrue(collection.contains(a));
+
+        collection = new ArrayList<>(Arrays.asList(null, a, null));
+        assertEquals(2, ArrayUtils.unstableRemoveIf(collection, isNull));
+        assertEquals(1, collection.size());
+        assertTrue(collection.contains(a));
+
+        collection = new ArrayList<>(Arrays.asList(null, null, null));
+        assertEquals(3, ArrayUtils.unstableRemoveIf(collection, isNull));
+        assertEquals(0, collection.size());
+    }
+}
diff --git a/core/tests/systemproperties/Android.mk b/core/tests/systemproperties/Android.mk
index 0c20876..b512396 100644
--- a/core/tests/systemproperties/Android.mk
+++ b/core/tests/systemproperties/Android.mk
@@ -9,7 +9,7 @@
 	$(call all-java-files-under, src)
 
 LOCAL_DX_FLAGS := --core-library
-LOCAL_STATIC_JAVA_LIBRARIES := core-tests android-common frameworks-core-util-lib
+LOCAL_STATIC_JAVA_LIBRARIES := android-common frameworks-core-util-lib
 LOCAL_JAVA_LIBRARIES := android.test.runner
 LOCAL_PACKAGE_NAME := FrameworksCoreSystemPropertiesTests
 LOCAL_JAVA_LANGUAGE_VERSION := 1.8
diff --git a/data/fonts/fonts.xml b/data/fonts/fonts.xml
index dc302c7..bcac6a1 100644
--- a/data/fonts/fonts.xml
+++ b/data/fonts/fonts.xml
@@ -88,242 +88,246 @@
     </family>
 
     <!-- fallback fonts -->
-    <family variant="elegant">
+    <family lang="und-Arab" variant="elegant">
         <font weight="400" style="normal">NotoNaskhArabic-Regular.ttf</font>
         <font weight="700" style="normal">NotoNaskhArabic-Bold.ttf</font>
     </family>
-    <family variant="compact">
+    <family lang="und-Arab" variant="compact">
         <font weight="400" style="normal">NotoNaskhArabicUI-Regular.ttf</font>
         <font weight="700" style="normal">NotoNaskhArabicUI-Bold.ttf</font>
     </family>
-    <family>
+    <family lang="und-Ethi">
         <font weight="400" style="normal">NotoSansEthiopic-Regular.ttf</font>
         <font weight="700" style="normal">NotoSansEthiopic-Bold.ttf</font>
     </family>
-    <family>
+    <family lang="und-Hebr">
         <font weight="400" style="normal">NotoSansHebrew-Regular.ttf</font>
         <font weight="700" style="normal">NotoSansHebrew-Bold.ttf</font>
     </family>
-    <family variant="elegant">
+    <family lang="und-Thai" variant="elegant">
         <font weight="400" style="normal">NotoSansThai-Regular.ttf</font>
         <font weight="700" style="normal">NotoSansThai-Bold.ttf</font>
     </family>
-    <family variant="compact">
+    <family lang="und-Thai" variant="compact">
         <font weight="400" style="normal">NotoSansThaiUI-Regular.ttf</font>
         <font weight="700" style="normal">NotoSansThaiUI-Bold.ttf</font>
     </family>
-    <family>
+    <family lang="und-Armn">
         <font weight="400" style="normal">NotoSansArmenian-Regular.ttf</font>
         <font weight="700" style="normal">NotoSansArmenian-Bold.ttf</font>
     </family>
-    <family>
+    <!-- TODO: add Geok -->
+    <family lang="und-Geor">
         <font weight="400" style="normal">NotoSansGeorgian-Regular.ttf</font>
         <font weight="700" style="normal">NotoSansGeorgian-Bold.ttf</font>
     </family>
-    <family variant="elegant">
+    <family lang="und-Deva" variant="elegant">
         <font weight="400" style="normal">NotoSansDevanagari-Regular.ttf</font>
         <font weight="700" style="normal">NotoSansDevanagari-Bold.ttf</font>
     </family>
-    <family variant="compact">
+    <family lang="und-Deva" variant="compact">
         <font weight="400" style="normal">NotoSansDevanagariUI-Regular.ttf</font>
         <font weight="700" style="normal">NotoSansDevanagariUI-Bold.ttf</font>
     </family>
-    <!-- Gujarati should come after Devanagari -->
-    <family variant="elegant">
+
+    <!-- All scripts of India should come after Devanagari, due to shared
+         danda characters.
+    -->
+    <family lang="und-Gujr" variant="elegant">
         <font weight="400" style="normal">NotoSansGujarati-Regular.ttf</font>
         <font weight="700" style="normal">NotoSansGujarati-Bold.ttf</font>
     </family>
-    <family variant="compact">
+    <family lang="und-Gujr" variant="compact">
         <font weight="400" style="normal">NotoSansGujaratiUI-Regular.ttf</font>
         <font weight="700" style="normal">NotoSansGujaratiUI-Bold.ttf</font>
     </family>
-    <!-- Gurmukhi should come after Devanagari -->
-    <family variant="elegant">
+    <family lang="und-Guru" variant="elegant">
         <font weight="400" style="normal">NotoSansGurmukhi-Regular.ttf</font>
         <font weight="700" style="normal">NotoSansGurmukhi-Bold.ttf</font>
     </family>
-    <family variant="compact">
+    <family lang="und-Guru" variant="compact">
         <font weight="400" style="normal">NotoSansGurmukhiUI-Regular.ttf</font>
         <font weight="700" style="normal">NotoSansGurmukhiUI-Bold.ttf</font>
     </family>
-    <family variant="elegant">
+    <family lang="und-Taml" variant="elegant">
         <font weight="400" style="normal">NotoSansTamil-Regular.ttf</font>
         <font weight="700" style="normal">NotoSansTamil-Bold.ttf</font>
     </family>
-    <family variant="compact">
+    <family lang="und-Taml" variant="compact">
         <font weight="400" style="normal">NotoSansTamilUI-Regular.ttf</font>
         <font weight="700" style="normal">NotoSansTamilUI-Bold.ttf</font>
     </family>
-    <family variant="elegant">
+    <family lang="und-Mlym" variant="elegant">
         <font weight="400" style="normal">NotoSansMalayalam-Regular.ttf</font>
         <font weight="700" style="normal">NotoSansMalayalam-Bold.ttf</font>
     </family>
-    <family variant="compact">
+    <family lang="und-Mlym" variant="compact">
         <font weight="400" style="normal">NotoSansMalayalamUI-Regular.ttf</font>
         <font weight="700" style="normal">NotoSansMalayalamUI-Bold.ttf</font>
     </family>
-    <family variant="elegant">
+    <family lang="und-Beng" variant="elegant">
         <font weight="400" style="normal">NotoSansBengali-Regular.ttf</font>
         <font weight="700" style="normal">NotoSansBengali-Bold.ttf</font>
     </family>
-    <family variant="compact">
+    <family lang="und-Beng" variant="compact">
         <font weight="400" style="normal">NotoSansBengaliUI-Regular.ttf</font>
         <font weight="700" style="normal">NotoSansBengaliUI-Bold.ttf</font>
     </family>
-    <family variant="elegant">
+    <family lang="und-Telu" variant="elegant">
         <font weight="400" style="normal">NotoSansTelugu-Regular.ttf</font>
         <font weight="700" style="normal">NotoSansTelugu-Bold.ttf</font>
     </family>
-    <family variant="compact">
+    <family lang="und-Telu" variant="compact">
         <font weight="400" style="normal">NotoSansTeluguUI-Regular.ttf</font>
         <font weight="700" style="normal">NotoSansTeluguUI-Bold.ttf</font>
     </family>
-    <family variant="elegant">
+    <family lang="und-Knda" variant="elegant">
         <font weight="400" style="normal">NotoSansKannada-Regular.ttf</font>
         <font weight="700" style="normal">NotoSansKannada-Bold.ttf</font>
     </family>
-    <family variant="compact">
+    <family lang="und-Knda" variant="compact">
         <font weight="400" style="normal">NotoSansKannadaUI-Regular.ttf</font>
         <font weight="700" style="normal">NotoSansKannadaUI-Bold.ttf</font>
     </family>
-    <family variant="elegant">
+    <family lang="und-Orya" variant="elegant">
         <font weight="400" style="normal">NotoSansOriya-Regular.ttf</font>
         <font weight="700" style="normal">NotoSansOriya-Bold.ttf</font>
     </family>
-    <family variant="compact">
+    <family lang="und-Orya" variant="compact">
         <font weight="400" style="normal">NotoSansOriyaUI-Regular.ttf</font>
         <font weight="700" style="normal">NotoSansOriyaUI-Bold.ttf</font>
     </family>
-    <family>
+
+    <family lang="und-Sinh">
         <font weight="400" style="normal">NotoSansSinhala-Regular.ttf</font>
         <font weight="700" style="normal">NotoSansSinhala-Bold.ttf</font>
     </family>
-    <family variant="elegant">
+    <family lang="und-Khmr" variant="elegant">
         <font weight="400" style="normal">NotoSansKhmer-Regular.ttf</font>
         <font weight="700" style="normal">NotoSansKhmer-Bold.ttf</font>
     </family>
-    <family variant="compact">
+    <family lang="und-Khmr" variant="compact">
         <font weight="400" style="normal">NotoSansKhmerUI-Regular.ttf</font>
         <font weight="700" style="normal">NotoSansKhmerUI-Bold.ttf</font>
     </family>
-    <family variant="elegant">
+    <family lang="und-Laoo" variant="elegant">
         <font weight="400" style="normal">NotoSansLao-Regular.ttf</font>
         <font weight="700" style="normal">NotoSansLao-Bold.ttf</font>
     </family>
-    <family variant="compact">
+    <family lang="und-Laoo" variant="compact">
         <font weight="400" style="normal">NotoSansLaoUI-Regular.ttf</font>
         <font weight="700" style="normal">NotoSansLaoUI-Bold.ttf</font>
     </family>
-    <family variant="elegant">
+    <family lang="und-Mymr" variant="elegant">
         <font weight="400" style="normal">NotoSansMyanmar-Regular.ttf</font>
         <font weight="700" style="normal">NotoSansMyanmar-Bold.ttf</font>
     </family>
-    <family variant="compact">
+    <family lang="und-Mymr" variant="compact">
         <font weight="400" style="normal">NotoSansMyanmarUI-Regular.ttf</font>
         <font weight="700" style="normal">NotoSansMyanmarUI-Bold.ttf</font>
     </family>
-    <family>
+    <family lang="und-Thaa">
         <font weight="400" style="normal">NotoSansThaana-Regular.ttf</font>
         <font weight="700" style="normal">NotoSansThaana-Bold.ttf</font>
     </family>
-    <family>
+    <family lang="und-Cham">
         <font weight="400" style="normal">NotoSansCham-Regular.ttf</font>
         <font weight="700" style="normal">NotoSansCham-Bold.ttf</font>
     </family>
-    <family>
+    <family lang="und-Bali">
         <font weight="400" style="normal">NotoSansBalinese-Regular.ttf</font>
     </family>
-    <family>
+    <family lang="und-Bamu">
         <font weight="400" style="normal">NotoSansBamum-Regular.ttf</font>
     </family>
-    <family>
+    <family lang="und-Batk">
         <font weight="400" style="normal">NotoSansBatak-Regular.ttf</font>
     </family>
-    <family>
+    <family lang="und-Bugi">
         <font weight="400" style="normal">NotoSansBuginese-Regular.ttf</font>
     </family>
-    <family>
+    <family lang="und-Buhd">
         <font weight="400" style="normal">NotoSansBuhid-Regular.ttf</font>
     </family>
-    <family>
+    <family lang="und-Cans">
         <font weight="400" style="normal">NotoSansCanadianAboriginal-Regular.ttf</font>
     </family>
-    <family>
+    <family lang="und-Cher">
         <font weight="400" style="normal">NotoSansCherokee-Regular.ttf</font>
     </family>
-    <family>
+    <family lang="und-Copt">
         <font weight="400" style="normal">NotoSansCoptic-Regular.ttf</font>
     </family>
-    <family>
+    <family lang="und-Glag">
         <font weight="400" style="normal">NotoSansGlagolitic-Regular.ttf</font>
     </family>
-    <family>
+    <family lang="und-Hano">
         <font weight="400" style="normal">NotoSansHanunoo-Regular.ttf</font>
     </family>
-    <family>
+    <family lang="und-Java">
         <font weight="400" style="normal">NotoSansJavanese-Regular.ttf</font>
     </family>
-    <family>
+    <family lang="und-Kali">
         <font weight="400" style="normal">NotoSansKayahLi-Regular.ttf</font>
     </family>
-    <family>
+    <family lang="und-Lepc">
         <font weight="400" style="normal">NotoSansLepcha-Regular.ttf</font>
     </family>
-    <family>
+    <family lang="und-Limb">
         <font weight="400" style="normal">NotoSansLimbu-Regular.ttf</font>
     </family>
-    <family>
+    <family lang="und-Lisu">
         <font weight="400" style="normal">NotoSansLisu-Regular.ttf</font>
     </family>
-    <family>
+    <family lang="und-Mand">
         <font weight="400" style="normal">NotoSansMandaic-Regular.ttf</font>
     </family>
-    <family>
+    <family lang="und-Mtei">
         <font weight="400" style="normal">NotoSansMeeteiMayek-Regular.ttf</font>
     </family>
-    <family>
+    <family lang="und-Talu">
         <font weight="400" style="normal">NotoSansNewTaiLue-Regular.ttf</font>
     </family>
-    <family>
+    <family lang="und-Nkoo">
         <font weight="400" style="normal">NotoSansNKo-Regular.ttf</font>
     </family>
-    <family>
+    <family lang="und-Olck">
         <font weight="400" style="normal">NotoSansOlChiki-Regular.ttf</font>
     </family>
-    <family>
+    <family lang="und-Rjng">
         <font weight="400" style="normal">NotoSansRejang-Regular.ttf</font>
     </family>
-    <family>
+    <family lang="und-Saur">
         <font weight="400" style="normal">NotoSansSaurashtra-Regular.ttf</font>
     </family>
-    <family>
+    <family lang="und-Sund">
         <font weight="400" style="normal">NotoSansSundanese-Regular.ttf</font>
     </family>
-    <family>
+    <family lang="und-Sylo">
         <font weight="400" style="normal">NotoSansSylotiNagri-Regular.ttf</font>
     </family>
-    <family>
+    <family lang="und-Syre">
         <font weight="400" style="normal">NotoSansSyriacEstrangela-Regular.ttf</font>
     </family>
-    <family>
+    <family lang="und-Tagb">
         <font weight="400" style="normal">NotoSansTagbanwa-Regular.ttf</font>
     </family>
-    <family>
+    <family lang="und-Lana">
         <font weight="400" style="normal">NotoSansTaiTham-Regular.ttf</font>
     </family>
-    <family>
+    <family lang="und-Tavt">
         <font weight="400" style="normal">NotoSansTaiViet-Regular.ttf</font>
     </family>
-    <family>
+    <family lang="und-Tibt">
         <font weight="400" style="normal">NotoSansTibetan-Regular.ttf</font>
     </family>
-    <family>
+    <family lang="und-Tfng">
         <font weight="400" style="normal">NotoSansTifinagh-Regular.ttf</font>
     </family>
-    <family>
+    <family lang="und-Vaii">
         <font weight="400" style="normal">NotoSansVai-Regular.ttf</font>
     </family>
-    <family>
+    <family lang="und-Yiii">
         <font weight="400" style="normal">NotoSansYi-Regular.ttf</font>
     </family>
     <family>
@@ -332,6 +336,7 @@
     <family lang="zh-Hans">
         <font weight="400" style="normal" index="2">NotoSansCJK-Regular.ttc</font>
     </family>
+    <!-- TODO: Add Bopo -->
     <family lang="zh-Hant">
         <font weight="400" style="normal" index="3">NotoSansCJK-Regular.ttc</font>
     </family>
@@ -351,10 +356,10 @@
         Tai Le and Mongolian are intentionally kept last, to make sure they don't override
         the East Asian punctuation for Chinese.
     -->
-    <family>
+    <family lang="und-Tale">
         <font weight="400" style="normal">NotoSansTaiLe-Regular.ttf</font>
     </family>
-    <family>
+    <family lang="und-Mong">
         <font weight="400" style="normal">NotoSansMongolian-Regular.ttf</font>
     </family>
 </familyset>
diff --git a/data/keyboards/qwerty2.kcm b/data/keyboards/qwerty2.kcm
index d96914f..b981d83 100644
--- a/data/keyboards/qwerty2.kcm
+++ b/data/keyboards/qwerty2.kcm
@@ -23,8 +23,8 @@
     number:                             '2'
     base:                               'a'
     shift, capslock:                    'A'
-    alt:                                'a'
-    shift+alt, capslock+alt:            'A'
+    alt:                                '\u00e1'
+    shift+alt, capslock+alt:            '\u00c1'
 }
 
 key B {
@@ -41,8 +41,8 @@
     number:                             '2'
     base:                               'c'
     shift, capslock:                    'C'
-    alt:                                '\u00e7'
-    shift+alt, capslock+alt:            '\u00e7'
+    alt:                                '\u00a9'
+    shift+alt, capslock+alt:            '\u00a2'
 }
 
 key D {
@@ -50,8 +50,8 @@
     number:                             '3'
     base:                               'd'
     shift, capslock:                    'D'
-    alt:                                '\''
-    shift+alt, capslock+alt:            '\''
+    alt:                                '\u00f0'
+    shift+alt, capslock+alt:            '\u00d0'
 }
 
 key E {
@@ -59,8 +59,8 @@
     number:                             '3'
     base:                               'e'
     shift, capslock:                    'E'
-    alt:                                '"'
-    shift+alt, capslock+alt:            '\u0301'
+    alt:                                '\u00e9'
+    shift+alt, capslock+alt:            '\u00c9'
 }
 
 key F {
@@ -95,8 +95,8 @@
     number:                             '4'
     base:                               'i'
     shift, capslock:                    'I'
-    alt:                                '-'
-    shift+alt, capslock+alt:            '\u0302'
+    alt:                                '\u00ed'
+    shift+alt, capslock+alt:            '\u00cd'
 }
 
 key J {
@@ -122,8 +122,8 @@
     number:                             '5'
     base:                               'l'
     shift, capslock:                    'L'
-    alt:                                ':'
-    shift+alt, capslock+alt:            '`'
+    alt:                                '\u00f8'
+    shift+alt, capslock+alt:            '\u00d8'
 }
 
 key M {
@@ -131,7 +131,7 @@
     number:                             '6'
     base:                               'm'
     shift, capslock:                    'M'
-    alt:                                '%'
+    alt:                                '\u00b5'
     shift+alt, capslock+alt:            none
 }
 
@@ -140,8 +140,8 @@
     number:                             '6'
     base:                               'n'
     shift, capslock:                    'N'
-    alt:                                none
-    shift+alt, capslock+alt:            '\u0303'
+    alt:                                '\u00f1'
+    shift+alt, capslock+alt:            '\u00d1'
 }
 
 key O {
@@ -149,8 +149,8 @@
     number:                             '6'
     base:                               'o'
     shift, capslock:                    'O'
-    alt:                                '+'
-    shift+alt, capslock+alt:            '+'
+    alt:                                '\u00f3'
+    shift+alt, capslock+alt:            '\u00d3'
 }
 
 key P {
@@ -158,8 +158,8 @@
     number:                             '7'
     base:                               'p'
     shift, capslock:                    'P'
-    alt:                                '='
-    shift+alt, capslock+alt:            '\u00a5'
+    alt:                                '\u00f6'
+    shift+alt, capslock+alt:            '\u00d6'
 }
 
 key Q {
@@ -167,8 +167,8 @@
     number:                             '7'
     base:                               'q'
     shift, capslock:                    'Q'
-    alt:                                '|'
-    shift+alt, capslock+alt:            '\u0300'
+    alt:                                '\u00e4'
+    shift+alt, capslock+alt:            '\u00c4'
 }
 
 key R {
@@ -176,8 +176,8 @@
     number:                             '7'
     base:                               'r'
     shift, capslock:                    'R'
-    alt:                                '`'
-    shift+alt, capslock+alt:            '\u20ac'
+    alt:                                '\u00ae'
+    shift+alt, capslock+alt:            'R'
 }
 
 key S {
@@ -185,8 +185,8 @@
     number:                             '7'
     base:                               's'
     shift, capslock:                    'S'
-    alt:                                '\\'
-    shift+alt, capslock+alt:            '\u00df'
+    alt:                                '\u00df'
+    shift+alt, capslock+alt:            '\u00a7'
 }
 
 key T {
@@ -194,8 +194,8 @@
     number:                             '8'
     base:                               't'
     shift, capslock:                    'T'
-    alt:                                '{'
-    shift+alt, capslock+alt:            '\u00a3'
+    alt:                                '\u00fe'
+    shift+alt, capslock+alt:            '\u00de'
 }
 
 key U {
@@ -203,8 +203,8 @@
     number:                             '8'
     base:                               'u'
     shift, capslock:                    'U'
-    alt:                                '_'
-    shift+alt, capslock+alt:            '\u0308'
+    alt:                                '\u00fa'
+    shift+alt, capslock+alt:            '\u00da'
 }
 
 key V {
@@ -221,8 +221,8 @@
     number:                             '9'
     base:                               'w'
     shift, capslock:                    'W'
-    alt:                                '~'
-    shift+alt, capslock+alt:            '~'
+    alt:                                '\u00e5'
+    shift+alt, capslock+alt:            '\u00c5'
 }
 
 key X {
@@ -239,8 +239,8 @@
     number:                             '9'
     base:                               'y'
     shift, capslock:                    'Y'
-    alt:                                '}'
-    shift+alt, capslock+alt:            '\u00a1'
+    alt:                                '\u00fc'
+    shift+alt, capslock+alt:            '\u00dc'
 }
 
 key Z {
@@ -248,8 +248,8 @@
     number:                             '9'
     base:                               'z'
     shift, capslock:                    'Z'
-    alt:                                'z'
-    shift+alt, capslock+alt:            'Z'
+    alt:                                '\u00e6'
+    shift+alt, capslock+alt:            '\u00c6'
 }
 
 key COMMA {
@@ -257,8 +257,8 @@
     number:                             ','
     base:                               ','
     shift:                              '<'
-    alt:                                ','
-    shift+alt:                          ','
+    alt:                                '\u00e7'
+    shift+alt:                          '\u00c7'
 }
 
 key PERIOD {
@@ -284,7 +284,7 @@
     number:                             '/'
     base:                               '/'
     shift:                              '?'
-    alt:                                '?'
+    alt:                                '\u00bf'
     shift+alt:                          '?'
 }
 
@@ -320,7 +320,7 @@
     number:                             '0'
     base:                               '0'
     shift:                              ')'
-    alt:                                ')'
+    alt:                                '\u02bc'
     shift+alt:                          ')'
 }
 
@@ -329,8 +329,8 @@
     number:                             '1'
     base:                               '1'
     shift:                              '!'
-    alt:                                '!'
-    shift+alt:                          '!'
+    alt:                                '\u00a1'
+    shift+alt:                          '\u00b9'
 }
 
 key 2 {
@@ -338,7 +338,7 @@
     number:                             '2'
     base:                               '2'
     shift:                              '@'
-    alt:                                '@'
+    alt:                                '\u00b2'
     shift+alt:                          '@'
 }
 
@@ -347,7 +347,7 @@
     number:                             '3'
     base:                               '3'
     shift:                              '#'
-    alt:                                '#'
+    alt:                                '\u00b3'
     shift+alt:                          '#'
 }
 
@@ -356,8 +356,8 @@
     number:                             '4'
     base:                               '4'
     shift:                              '$'
-    alt:                                '$'
-    shift+alt:                          '$'
+    alt:                                '\u00a4'
+    shift+alt:                          '\u00a3'
 }
 
 key 5 {
@@ -365,7 +365,7 @@
     number:                             '5'
     base:                               '5'
     shift:                              '%'
-    alt:                                '%'
+    alt:                                '\u20ac'
     shift+alt:                          '%'
 }
 
@@ -374,8 +374,8 @@
     number:                             '6'
     base:                               '6'
     shift:                              '^'
-    alt:                                '^'
-    shift+alt:                          '^'
+    alt:                                '\u00bc'
+    shift+alt:                          '\u0302'
 }
 
 key 7 {
@@ -383,7 +383,7 @@
     number:                             '7'
     base:                               '7'
     shift:                              '&'
-    alt:                                '&'
+    alt:                                '\u00bd'
     shift+alt:                          '&'
 }
 
@@ -392,7 +392,7 @@
     number:                             '8'
     base:                               '8'
     shift:                              '*'
-    alt:                                '*'
+    alt:                                '\u00be'
     shift+alt:                          '*'
 }
 
@@ -401,7 +401,7 @@
     number:                             '9'
     base:                               '9'
     shift:                              '('
-    alt:                                '('
+    alt:                                '\u02bb'
     shift+alt:                          '('
 }
 
@@ -410,8 +410,8 @@
     number:                             '`'
     base:                               '`'
     shift:                              '~'
-    alt:                                '`'
-    shift+alt:                          '~'
+    alt:                                '\u0300'
+    shift+alt:                          '\u0303'
 }
 
 key MINUS {
@@ -419,7 +419,7 @@
     number:                             '-'
     base:                               '-'
     shift:                              '_'
-    alt:                                '-'
+    alt:                                '\u00a5'
     shift+alt:                          '_'
 }
 
@@ -428,8 +428,8 @@
     number:                             '='
     base:                               '='
     shift:                              '+'
-    alt:                                '='
-    shift+alt:                          '+'
+    alt:                                '\u00d7'
+    shift+alt:                          '\u00f7'
 }
 
 key LEFT_BRACKET {
@@ -437,7 +437,7 @@
     number:                             '['
     base:                               '['
     shift:                              '{'
-    alt:                                '['
+    alt:                                '\u00ab'
     shift+alt:                          '{'
 }
 
@@ -446,7 +446,7 @@
     number:                             ']'
     base:                               ']'
     shift:                              '}'
-    alt:                                ']'
+    alt:                                '\u00bb'
     shift+alt:                          '}'
 }
 
@@ -455,8 +455,8 @@
     number:                             '\\'
     base:                               '\\'
     shift:                              '|'
-    alt:                                '\\'
-    shift+alt:                          '|'
+    alt:                                '\u00ac'
+    shift+alt:                          '\u00a6'
 }
 
 key SEMICOLON {
@@ -464,8 +464,8 @@
     number:                             ';'
     base:                               ';'
     shift:                              ':'
-    alt:                                ';'
-    shift+alt:                          ':'
+    alt:                                '\u00b6'
+    shift+alt:                          '\u00b0'
 }
 
 key APOSTROPHE {
@@ -473,8 +473,8 @@
     number:                             '\''
     base:                               '\''
     shift:                              '"'
-    alt:                                '\''
-    shift+alt:                          '"'
+    alt:                                '\u0301'
+    shift+alt:                          '\u0308'
 }
 
 key STAR {
diff --git a/docs/docs-documentation-redirect.html b/docs/docs-documentation-redirect.html
index 98a265e..dbdf8b4 100644
--- a/docs/docs-documentation-redirect.html
+++ b/docs/docs-documentation-redirect.html
@@ -1,9 +1,9 @@
 <html>
 <head>
-<meta http-equiv="refresh" content="0;url=documentation.html">
+<meta http-equiv="refresh" content="0;url=reference/packages.html">
 </head>
 <body>
-<a href="documentation.html">click here if you are not redirected</a>
+<a href="reference/packages.html">click here if you are not redirected</a>
 </body>
 </html>
 
diff --git a/docs/docs-preview-index.html b/docs/docs-preview-index.html
new file mode 100644
index 0000000..e26b57c
--- /dev/null
+++ b/docs/docs-preview-index.html
@@ -0,0 +1,103 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<meta name="viewport" content="width=device-width,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no" />
+<meta content="IE=edge" http-equiv="X-UA-Compatible">
+<link rel="shortcut icon" type="image/x-icon" href="favicon.ico" />
+
+<title>Android N Developer Preview</title>
+
+<!-- STYLESHEETS -->
+<link rel="stylesheet"
+href="http://fonts.googleapis.com/css?family=Roboto+Condensed">
+<link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Roboto:light,regular,medium,thin,italic,mediumitalic,bold"
+  title="roboto">
+<link href="assets/css/default.css?v=17" rel="stylesheet" type="text/css">
+<!-- JAVASCRIPT -->
+<script src="https://www.google.com/jsapi" type="text/javascript"></script>
+<script src="assets/js/android_3p-bundle.js" type="text/javascript"></script>
+<script type="text/javascript">
+  var toRoot = "../";
+  var metaTags = ["develop, getstarted, sdk, appquality, landing"];
+  var devsite = false;
+</script>
+<script src="assets/js/docs.js?v=3" type="text/javascript"></script>
+</head>
+
+<body>
+<div id="header-wrapper">
+  <div class="dac-header" id="header">
+    <div class="dac-header-inner">
+      <a class="dac-nav-toggle" data-dac-toggle-nav="" href="javascript:;"
+        title="Open navigation">
+        <span class="dac-nav-hamburger">
+          <span class="dac-nav-hamburger-top"></span>
+          <span class="dac-nav-hamburger-mid"></span>
+          <span class="dac-nav-hamburger-bot"></span>
+        </span>
+      </a>
+      <a class="dac-header-logo" href="index.html">
+        <img class="dac-header-logo-image" src="assets/images/android_logo.png"
+          srcset="assets/images/android_logo@2x.png 2x" width="32" height="36"
+          alt="Android"> Developers
+        </a>
+    </div>
+  </div>
+</div>
+<nav class="dac-nav">
+  <div class="dac-nav-dimmer" data-dac-toggle-nav=""></div>
+  <ul class="dac-nav-list" data-dac-nav="">
+    <li class="dac-nav-item dac-nav-head">
+      <a class="dac-nav-link dac-nav-logo" data-dac-toggle-nav=""
+        href="javascript:;" title="Close navigation">
+        <img class="dac-logo-image" src="assets/images/android_logo.png"
+          srcset="assets/images/android_logo@2x.png 2x" width="32" height="36"
+          alt="Android"> Developers
+      </a>
+    </li>
+    <li class="dac-nav-item develop">
+      <a class="dac-nav-link" href="reference/packages.html"
+        >API Reference</a>
+    </li>
+  </ul>
+</nav>
+
+<section class="dac-expand" style="padding-top:40px;background-color:#eee">
+  <div class="wrap" style="max-width:1100px;margin-top:0;height:100%">
+    <div class="cols dac-hero-content" style="padding-bottom:1em;">
+      <div class="col-11of16">
+
+
+<h1>Android N Developer Preview</h1>
+<p>
+  Get ready for Android N!
+  <strong>Test your apps</strong> on Nexus devices. Support new system
+  behaviors to <strong>save power and memory</strong>.
+  Extend your apps with <strong>multi-window UI</strong>,
+  <strong>direct reply notifications</strong> and more.
+</p>
+
+<h2>Get Started</h2>
+<ul>
+  <li>View the <a href="reference/packages.html">API Reference</a></li>
+  <li>Read Diff Reports:</a>
+    <ul>
+      <li><a href="sdk/api_diff/n-preview-1/changes.html"
+        >API 23 --> Preview 1</a></li>
+    </ul>
+  </li>
+  <li>Downloads and additional documentation are available at the
+    <a href="http://developer.android.com/preview/index.html">
+      Android N Developer Preview site</a></li>
+  <li>For information about Developer Preview 1, visit the
+    <a href="http://developer.android.com/preview/support.html">Support</a>
+    page.</li>
+</ul>
+
+
+      </div>
+    </div>
+  </div>
+</section>
+</body>
+</html>
diff --git a/docs/html/guide/topics/sensors/sensors_overview.jd b/docs/html/guide/topics/sensors/sensors_overview.jd
index 0b3cb2b..53faca0 100644
--- a/docs/html/guide/topics/sensors/sensors_overview.jd
+++ b/docs/html/guide/topics/sensors/sensors_overview.jd
@@ -465,6 +465,7 @@
 ...
 
 mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
+mSensor = null;
 
 if (mSensorManager.getDefaultSensor(Sensor.TYPE_GRAVITY) != null){
   List&lt;Sensor&gt; gravSensors = mSensorManager.getSensorList(Sensor.TYPE_GRAVITY);
@@ -476,7 +477,7 @@
     }
   }
 }
-else{
+if (mSensor == null){
   // Use the accelerometer.
   if (mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER) != null){
     mSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
diff --git a/graphics/java/android/graphics/Canvas.java b/graphics/java/android/graphics/Canvas.java
index d4f745d..af99f79 100644
--- a/graphics/java/android/graphics/Canvas.java
+++ b/graphics/java/android/graphics/Canvas.java
@@ -91,8 +91,11 @@
     // a Canvas object.
     private static final long NATIVE_ALLOCATION_SIZE = 525;
 
-    private static final NativeAllocationRegistry sRegistry = new NativeAllocationRegistry(
-        getNativeFinalizer(), NATIVE_ALLOCATION_SIZE);
+    // Use a Holder to allow static initialization of Canvas in the boot image.
+    private static class NoImagePreloadHolder {
+        public static final NativeAllocationRegistry sRegistry = new NativeAllocationRegistry(
+                getNativeFinalizer(), NATIVE_ALLOCATION_SIZE);
+    }
 
     // This field is used to finalize the native Canvas properly
     private Runnable mFinalizer;
@@ -107,7 +110,8 @@
         if (!isHardwareAccelerated()) {
             // 0 means no native bitmap
             mNativeCanvasWrapper = initRaster(null);
-            mFinalizer = sRegistry.registerNativeAllocation(this, mNativeCanvasWrapper);
+            mFinalizer = NoImagePreloadHolder.sRegistry.registerNativeAllocation(
+                    this, mNativeCanvasWrapper);
         } else {
             mFinalizer = null;
         }
@@ -128,7 +132,8 @@
         }
         throwIfCannotDraw(bitmap);
         mNativeCanvasWrapper = initRaster(bitmap);
-        mFinalizer = sRegistry.registerNativeAllocation(this, mNativeCanvasWrapper);
+        mFinalizer = NoImagePreloadHolder.sRegistry.registerNativeAllocation(
+                this, mNativeCanvasWrapper);
         mBitmap = bitmap;
         mDensity = bitmap.mDensity;
     }
@@ -139,7 +144,8 @@
             throw new IllegalStateException();
         }
         mNativeCanvasWrapper = nativeCanvas;
-        mFinalizer = sRegistry.registerNativeAllocation(this, mNativeCanvasWrapper);
+        mFinalizer = NoImagePreloadHolder.sRegistry.registerNativeAllocation(
+                this, mNativeCanvasWrapper);
         mDensity = Bitmap.getDefaultDensity();
     }
 
diff --git a/graphics/java/android/graphics/Outline.java b/graphics/java/android/graphics/Outline.java
index 99fa9fe..d312454 100644
--- a/graphics/java/android/graphics/Outline.java
+++ b/graphics/java/android/graphics/Outline.java
@@ -32,13 +32,15 @@
  * @see Drawable#getOutline(Outline)
  */
 public final class Outline {
+    private static final float RADIUS_UNDEFINED = -1.0f;
+
     /** @hide */
     public Path mPath;
 
     /** @hide */
     public Rect mRect;
     /** @hide */
-    public float mRadius;
+    public float mRadius = RADIUS_UNDEFINED;
     /** @hide */
     public float mAlpha;
 
@@ -63,7 +65,7 @@
     public void setEmpty() {
         mPath = null;
         mRect = null;
-        mRadius = 0;
+        mRadius = RADIUS_UNDEFINED;
     }
 
     /**
@@ -223,6 +225,7 @@
         mPath.reset();
         mPath.addOval(left, top, right, bottom, Path.Direction.CW);
         mRect = null;
+        mRadius = RADIUS_UNDEFINED;
     }
 
     /**
@@ -249,7 +252,7 @@
 
         mPath.set(convexPath);
         mRect = null;
-        mRadius = -1.0f;
+        mRadius = RADIUS_UNDEFINED;
     }
 
     /**
diff --git a/graphics/java/android/graphics/Paint.java b/graphics/java/android/graphics/Paint.java
index 534121a..291fdc4 100644
--- a/graphics/java/android/graphics/Paint.java
+++ b/graphics/java/android/graphics/Paint.java
@@ -44,8 +44,11 @@
     // The approximate size of a native paint object.
     private static final long NATIVE_PAINT_SIZE = 98;
 
-    private static final NativeAllocationRegistry sRegistry = new NativeAllocationRegistry(
-        nGetNativeFinalizer(), NATIVE_PAINT_SIZE);
+    // Use a Holder to allow static initialization of Paint in the boot image.
+    private static class NoImagePreloadHolder {
+        public static final NativeAllocationRegistry sRegistry = new NativeAllocationRegistry(
+                nGetNativeFinalizer(), NATIVE_PAINT_SIZE);
+    }
 
     /**
      * @hide
@@ -452,7 +455,7 @@
      */
     public Paint(int flags) {
         mNativePaint = nInit();
-        sRegistry.registerNativeAllocation(this, mNativePaint);
+        NoImagePreloadHolder.sRegistry.registerNativeAllocation(this, mNativePaint);
         setFlags(flags | HIDDEN_DEFAULT_PAINT_FLAGS);
         // TODO: Turning off hinting has undesirable side effects, we need to
         //       revisit hinting once we add support for subpixel positioning
@@ -471,7 +474,7 @@
      */
     public Paint(Paint paint) {
         mNativePaint = nInitWithPaint(paint.getNativeInstance());
-        sRegistry.registerNativeAllocation(this, mNativePaint);
+        NoImagePreloadHolder.sRegistry.registerNativeAllocation(this, mNativePaint);
         setClassVariablesFrom(paint);
     }
 
diff --git a/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java b/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java
index 3901af3..39ea205 100644
--- a/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java
+++ b/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java
@@ -35,11 +35,13 @@
 import android.graphics.ColorFilter;
 import android.graphics.Insets;
 import android.graphics.Outline;
+import android.graphics.PixelFormat;
 import android.graphics.PorterDuff;
 import android.graphics.Rect;
 import android.os.Build;
 import android.util.ArrayMap;
 import android.util.AttributeSet;
+import android.util.IntArray;
 import android.util.Log;
 import android.util.LongArray;
 import android.util.PathParser;
@@ -258,6 +260,13 @@
         return mAnimatedVectorState.mVectorDrawable.setLayoutDirection(layoutDirection);
     }
 
+    /**
+     * AnimatedVectorDrawable is running on render thread now. Therefore, if the root alpha is being
+     * animated, then the root alpha value we get from this call could be out of sync with alpha
+     * value used in the render thread. Otherwise, the root alpha should be always the same value.
+     *
+     * @return the containing vector drawable's root alpha value.
+     */
     @Override
     public int getAlpha() {
         return mAnimatedVectorState.mVectorDrawable.getAlpha();
@@ -274,6 +283,11 @@
     }
 
     @Override
+    public ColorFilter getColorFilter() {
+        return mAnimatedVectorState.mVectorDrawable.getColorFilter();
+    }
+
+    @Override
     public void setTintList(ColorStateList tint) {
         mAnimatedVectorState.mVectorDrawable.setTintList(tint);
     }
@@ -306,7 +320,7 @@
 
     @Override
     public int getOpacity() {
-        return mAnimatedVectorState.mVectorDrawable.getOpacity();
+        return PixelFormat.TRANSLUCENT;
     }
 
     @Override
@@ -629,12 +643,24 @@
      */
     public void reset() {
         ensureAnimatorSet();
+        if (DBG_ANIMATION_VECTOR_DRAWABLE) {
+            Log.w(LOGTAG, "calling reset on AVD: " +
+                    ((VectorDrawable.VectorDrawableState) ((AnimatedVectorDrawableState)
+                    getConstantState()).mVectorDrawable.getConstantState()).mRootName
+                    + ", at: " + this);
+        }
         mAnimatorSet.reset();
     }
 
     @Override
     public void start() {
         ensureAnimatorSet();
+        if (DBG_ANIMATION_VECTOR_DRAWABLE) {
+            Log.w(LOGTAG, "calling start on AVD: " +
+                    ((VectorDrawable.VectorDrawableState) ((AnimatedVectorDrawableState)
+                    getConstantState()).mVectorDrawable.getConstantState()).mRootName
+                    + ", at: " + this);
+        }
         mAnimatorSet.start();
     }
 
@@ -652,6 +678,12 @@
 
     @Override
     public void stop() {
+        if (DBG_ANIMATION_VECTOR_DRAWABLE) {
+            Log.w(LOGTAG, "calling stop on AVD: " +
+                    ((VectorDrawable.VectorDrawableState) ((AnimatedVectorDrawableState)
+                            getConstantState()).mVectorDrawable.getConstantState())
+                            .mRootName + ", at: " + this);
+        }
         mAnimatorSet.end();
     }
 
@@ -683,17 +715,17 @@
 
     private final Callback mCallback = new Callback() {
         @Override
-        public void invalidateDrawable(Drawable who) {
+        public void invalidateDrawable(@NonNull Drawable who) {
             invalidateSelf();
         }
 
         @Override
-        public void scheduleDrawable(Drawable who, Runnable what, long when) {
+        public void scheduleDrawable(@NonNull Drawable who, @NonNull Runnable what, long when) {
             scheduleSelf(what, when);
         }
 
         @Override
-        public void unscheduleDrawable(Drawable who, Runnable what) {
+        public void unscheduleDrawable(@NonNull Drawable who, @NonNull Runnable what) {
             unscheduleSelf(what);
         }
     };
@@ -864,9 +896,10 @@
      * @hide
      */
     public static class VectorDrawableAnimatorRT implements VectorDrawableAnimator {
-        private static final int NONE = 0;
         private static final int START_ANIMATION = 1;
         private static final int REVERSE_ANIMATION = 2;
+        private static final int RESET_ANIMATION = 3;
+        private static final int END_ANIMATION = 4;
         private AnimatorListener mListener = null;
         private final LongArray mStartDelays = new LongArray();
         private PropertyValuesHolder.PropertyValues mTmpValues =
@@ -882,7 +915,7 @@
         private final VirtualRefBasePtr mSetRefBasePtr;
         private WeakReference<RenderNode> mLastSeenTarget = null;
         private int mLastListenerId = 0;
-        private int mPendingAnimationAction = NONE;
+        private final IntArray mPendingAnimationActions = new IntArray();
         private final Drawable mDrawable;
 
         VectorDrawableAnimatorRT(AnimatedVectorDrawable drawable) {
@@ -1139,16 +1172,29 @@
         protected void recordLastSeenTarget(DisplayListCanvas canvas) {
             mLastSeenTarget = new WeakReference<RenderNode>(
                     RenderNodeAnimatorSetHelper.getTarget(canvas));
-            if (mPendingAnimationAction != NONE) {
+            if (mPendingAnimationActions.size() > 0 && useLastSeenTarget()) {
                 if (DBG_ANIMATION_VECTOR_DRAWABLE) {
                     Log.d(LOGTAG, "Target is set in the next frame");
                 }
-                if (mPendingAnimationAction == START_ANIMATION) {
-                    start();
-                } else if (mPendingAnimationAction == REVERSE_ANIMATION) {
-                    reverse();
+                for (int i = 0; i < mPendingAnimationActions.size(); i++) {
+                    handlePendingAction(mPendingAnimationActions.get(i));
                 }
-                mPendingAnimationAction = NONE;
+                mPendingAnimationActions.clear();
+            }
+        }
+
+        private void handlePendingAction(int pendingAnimationAction) {
+            if (pendingAnimationAction == START_ANIMATION) {
+                startAnimation();
+            } else if (pendingAnimationAction == REVERSE_ANIMATION) {
+                reverseAnimation();
+            } else if (pendingAnimationAction == RESET_ANIMATION) {
+                resetAnimation();
+            } else if (pendingAnimationAction == END_ANIMATION) {
+                endAnimation();
+            } else {
+                throw new UnsupportedOperationException("Animation action " +
+                        pendingAnimationAction + "is not supported");
             }
         }
 
@@ -1167,45 +1213,51 @@
             mDrawable.invalidateSelf();
         }
 
+        private void addPendingAction(int pendingAnimationAction) {
+            invalidateOwningView();
+            mPendingAnimationActions.add(pendingAnimationAction);
+        }
+
         @Override
         public void start() {
             if (!mInitialized) {
                 return;
             }
 
-            if (!useLastSeenTarget()) {
-                invalidateOwningView();
-                mPendingAnimationAction = START_ANIMATION;
-                return;
+            if (useLastSeenTarget()) {
+                if (DBG_ANIMATION_VECTOR_DRAWABLE) {
+                    Log.d(LOGTAG, "Target is set. Starting VDAnimatorSet from java");
+                }
+                startAnimation();
+            } else {
+                addPendingAction(START_ANIMATION);
             }
 
-            if (DBG_ANIMATION_VECTOR_DRAWABLE) {
-                Log.d(LOGTAG, "Target is set. Starting VDAnimatorSet from java");
-            }
-
-            mStarted = true;
-            nStart(mSetPtr, this, ++mLastListenerId);
-            invalidateOwningView();
-            if (mListener != null) {
-                mListener.onAnimationStart(null);
-            }
         }
 
         @Override
         public void end() {
-            if (mInitialized && useLastSeenTarget()) {
-                // If no target has ever been set, no-op
-                nEnd(mSetPtr);
-                invalidateOwningView();
+            if (!mInitialized) {
+                return;
+            }
+
+            if (useLastSeenTarget()) {
+                endAnimation();
+            } else {
+                addPendingAction(END_ANIMATION);
             }
         }
 
         @Override
         public void reset() {
-            if (mInitialized && useLastSeenTarget()) {
-                // If no target has ever been set, no-op
-                nReset(mSetPtr);
-                invalidateOwningView();
+            if (!mInitialized) {
+                return;
+            }
+
+            if (useLastSeenTarget()) {
+                resetAnimation();
+            } else {
+                addPendingAction(RESET_ANIMATION);
             }
         }
 
@@ -1216,15 +1268,53 @@
             if (!mIsReversible || !mInitialized) {
                 return;
             }
-            if (!useLastSeenTarget()) {
-                invalidateOwningView();
-                mPendingAnimationAction = REVERSE_ANIMATION;
-                return;
+            if (useLastSeenTarget()) {
+                if (DBG_ANIMATION_VECTOR_DRAWABLE) {
+                    Log.d(LOGTAG, "Target is set. Reversing VDAnimatorSet from java");
+                }
+                reverseAnimation();
+            } else {
+                addPendingAction(REVERSE_ANIMATION);
             }
+        }
+
+        // This should only be called after animator has been added to the RenderNode target.
+        private void startAnimation() {
             if (DBG_ANIMATION_VECTOR_DRAWABLE) {
-                Log.d(LOGTAG, "Target is set. Reversing VDAnimatorSet from java");
+                Log.w(LOGTAG, "starting animation on VD: " +
+                        ((VectorDrawable.VectorDrawableState) ((AnimatedVectorDrawableState)
+                                mDrawable.getConstantState()).mVectorDrawable.getConstantState())
+                                .mRootName);
             }
             mStarted = true;
+            nStart(mSetPtr, this, ++mLastListenerId);
+            invalidateOwningView();
+            if (mListener != null) {
+                mListener.onAnimationStart(null);
+            }
+        }
+
+        // This should only be called after animator has been added to the RenderNode target.
+        private void endAnimation() {
+            if (DBG_ANIMATION_VECTOR_DRAWABLE) {
+                Log.w(LOGTAG, "ending animation on VD: " +
+                        ((VectorDrawable.VectorDrawableState) ((AnimatedVectorDrawableState)
+                                mDrawable.getConstantState()).mVectorDrawable.getConstantState())
+                                .mRootName);
+            }
+            nEnd(mSetPtr);
+            invalidateOwningView();
+        }
+
+        // This should only be called after animator has been added to the RenderNode target.
+        private void resetAnimation() {
+            nReset(mSetPtr);
+            invalidateOwningView();
+        }
+
+        // This should only be called after animator has been added to the RenderNode target.
+        private void reverseAnimation() {
+            mStarted = true;
             nReverse(mSetPtr, this, ++mLastListenerId);
             invalidateOwningView();
             if (mListener != null) {
diff --git a/graphics/java/android/graphics/drawable/Drawable.java b/graphics/java/android/graphics/drawable/Drawable.java
index 3d8437d..f106c68 100644
--- a/graphics/java/android/graphics/drawable/Drawable.java
+++ b/graphics/java/android/graphics/drawable/Drawable.java
@@ -308,7 +308,7 @@
      * to supply your implementation of the interface to the drawable; it uses
      * this interface to schedule and execute animation changes.
      */
-    public static interface Callback {
+    public interface Callback {
         /**
          * Called when the drawable needs to be redrawn.  A view at this point
          * should invalidate itself (or at least the part of itself where the
@@ -316,7 +316,7 @@
          *
          * @param who The drawable that is requesting the update.
          */
-        public void invalidateDrawable(Drawable who);
+        void invalidateDrawable(@NonNull Drawable who);
 
         /**
          * A Drawable can call this to schedule the next frame of its
@@ -330,7 +330,7 @@
          * @param when The time (in milliseconds) to run.  The timebase is
          *             {@link android.os.SystemClock#uptimeMillis}
          */
-        public void scheduleDrawable(Drawable who, Runnable what, long when);
+        void scheduleDrawable(@NonNull Drawable who, @NonNull Runnable what, long when);
 
         /**
          * A Drawable can call this to unschedule an action previously
@@ -342,7 +342,7 @@
          * @param who The drawable being unscheduled.
          * @param what The action being unscheduled.
          */
-        public void unscheduleDrawable(Drawable who, Runnable what);
+        void unscheduleDrawable(@NonNull Drawable who, @NonNull Runnable what);
     }
 
     /**
diff --git a/graphics/java/android/graphics/drawable/DrawableContainer.java b/graphics/java/android/graphics/drawable/DrawableContainer.java
index 3b0e7e8..a91d1f0 100644
--- a/graphics/java/android/graphics/drawable/DrawableContainer.java
+++ b/graphics/java/android/graphics/drawable/DrawableContainer.java
@@ -373,21 +373,21 @@
     }
 
     @Override
-    public void invalidateDrawable(Drawable who) {
+    public void invalidateDrawable(@NonNull Drawable who) {
         if (who == mCurrDrawable && getCallback() != null) {
             getCallback().invalidateDrawable(this);
         }
     }
 
     @Override
-    public void scheduleDrawable(Drawable who, Runnable what, long when) {
+    public void scheduleDrawable(@NonNull Drawable who, @NonNull Runnable what, long when) {
         if (who == mCurrDrawable && getCallback() != null) {
             getCallback().scheduleDrawable(this, what, when);
         }
     }
 
     @Override
-    public void unscheduleDrawable(Drawable who, Runnable what) {
+    public void unscheduleDrawable(@NonNull Drawable who, @NonNull Runnable what) {
         if (who == mCurrDrawable && getCallback() != null) {
             getCallback().unscheduleDrawable(this, what);
         }
@@ -804,6 +804,7 @@
             mConstantPadding = null;
             mCheckedPadding = false;
             mCheckedConstantSize = false;
+            mCheckedConstantState = false;
 
             return pos;
         }
diff --git a/graphics/java/android/graphics/drawable/DrawableWrapper.java b/graphics/java/android/graphics/drawable/DrawableWrapper.java
index c427870..4df2d57 100644
--- a/graphics/java/android/graphics/drawable/DrawableWrapper.java
+++ b/graphics/java/android/graphics/drawable/DrawableWrapper.java
@@ -198,7 +198,7 @@
     }
 
     @Override
-    public void invalidateDrawable(Drawable who) {
+    public void invalidateDrawable(@NonNull Drawable who) {
         final Callback callback = getCallback();
         if (callback != null) {
             callback.invalidateDrawable(this);
@@ -206,7 +206,7 @@
     }
 
     @Override
-    public void scheduleDrawable(Drawable who, Runnable what, long when) {
+    public void scheduleDrawable(@NonNull Drawable who, @NonNull Runnable what, long when) {
         final Callback callback = getCallback();
         if (callback != null) {
             callback.scheduleDrawable(this, what, when);
@@ -214,7 +214,7 @@
     }
 
     @Override
-    public void unscheduleDrawable(Drawable who, Runnable what) {
+    public void unscheduleDrawable(@NonNull Drawable who, @NonNull Runnable what) {
         final Callback callback = getCallback();
         if (callback != null) {
             callback.unscheduleDrawable(this, what);
diff --git a/graphics/java/android/graphics/drawable/GradientDrawable.java b/graphics/java/android/graphics/drawable/GradientDrawable.java
index f9208cd..7b1e62a 100644
--- a/graphics/java/android/graphics/drawable/GradientDrawable.java
+++ b/graphics/java/android/graphics/drawable/GradientDrawable.java
@@ -17,6 +17,7 @@
 package android.graphics.drawable;
 
 import android.annotation.ColorInt;
+import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.content.res.ColorStateList;
@@ -51,6 +52,8 @@
 import org.xmlpull.v1.XmlPullParserException;
 
 import java.io.IOException;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 
 /**
  * A Drawable with a color gradient for buttons, backgrounds, etc.
@@ -108,6 +111,11 @@
      */
     public static final int RING = 3;
 
+    /** @hide */
+    @IntDef({RECTANGLE, OVAL, LINE, RING})
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface Shape {}
+
     /**
      * Gradient is linear (default.)
      */
@@ -123,6 +131,11 @@
      */
     public static final int SWEEP_GRADIENT  = 2;
 
+    /** @hide */
+    @IntDef({LINEAR_GRADIENT, RADIAL_GRADIENT, SWEEP_GRADIENT})
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface GradientType {}
+
     /** Radius is in pixels. */
     private static final int RADIUS_TYPE_PIXELS = 0;
 
@@ -132,6 +145,11 @@
     /** Radius is a fraction of the bounds size. */
     private static final int RADIUS_TYPE_FRACTION_PARENT = 2;
 
+    /** @hide */
+    @IntDef({RADIUS_TYPE_PIXELS, RADIUS_TYPE_FRACTION, RADIUS_TYPE_FRACTION_PARENT})
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface RadiusType {}
+
     private static final float DEFAULT_INNER_RADIUS_RATIO = 3.0f;
     private static final float DEFAULT_THICKNESS_RATIO = 9.0f;
 
@@ -404,7 +422,7 @@
      *
      * @see #mutate()
      */
-    public void setShape(int shape) {
+    public void setShape(@Shape int shape) {
         mRingPath = null;
         mPathIsDirty = true;
         mGradientState.setShape(shape);
@@ -412,6 +430,18 @@
     }
 
     /**
+     * Returns the type of shape used by this drawable, one of {@link #LINE},
+     * {@link #OVAL}, {@link #RECTANGLE} or {@link #RING}.
+     *
+     * @return the type of shape used by this drawable
+     * @see #setShape(int)
+     */
+    @Shape
+    public int getShape() {
+        return mGradientState.mShape;
+    }
+
+    /**
      * Sets the type of gradient used by this drawable.
      * <p>
      * <strong>Note</strong>: changing this property will affect all instances
@@ -424,7 +454,7 @@
      * @see #mutate()
      * @see #getGradientType()
      */
-    public void setGradientType(int gradient) {
+    public void setGradientType(@GradientType int gradient) {
         mGradientState.setGradientType(gradient);
         mGradientIsDirty = true;
         invalidateSelf();
@@ -438,6 +468,7 @@
      * @return the type of gradient used by this drawable
      * @see #setGradientType(int)
      */
+    @GradientType
     public int getGradientType() {
         return mGradientState.mGradient;
     }
@@ -534,7 +565,7 @@
      * @see #mutate()
      * @see #setLevel(int)
      * @see #getLevel()
-     * @see #isUseLevel()
+     * @see #getUseLevel()
      */
     public void setUseLevel(boolean useLevel) {
         mGradientState.mUseLevel = useLevel;
@@ -550,7 +581,7 @@
      *         {@code false} otherwise
      * @see #setUseLevel(boolean)
      */
-    public boolean isUseLevel() {
+    public boolean getUseLevel() {
         return mGradientState.mUseLevel;
     }
 
@@ -616,7 +647,8 @@
      */
     @Nullable
     public int[] getColors() {
-        return mGradientState.mGradientColors.clone();
+        return mGradientState.mGradientColors == null ?
+                null : mGradientState.mGradientColors.clone();
     }
 
     @Override
@@ -848,7 +880,7 @@
      * @see #mutate()
      * @see #getColor
      */
-    public void setColor(ColorStateList colorStateList) {
+    public void setColor(@Nullable ColorStateList colorStateList) {
         mGradientState.setSolidColors(colorStateList);
         final int color;
         if (colorStateList == null) {
@@ -870,6 +902,7 @@
      * @see #setColor(int)
      * @see #setColor(ColorStateList)
      */
+    @Nullable
     public ColorStateList getColor() {
         return mGradientState.mSolidColors;
     }
@@ -951,12 +984,13 @@
     }
 
     @Override
+    @Nullable
     public ColorFilter getColorFilter() {
         return mColorFilter;
     }
 
     @Override
-    public void setColorFilter(ColorFilter colorFilter) {
+    public void setColorFilter(@Nullable ColorFilter colorFilter) {
         if (colorFilter != mColorFilter) {
             mColorFilter = colorFilter;
             invalidateSelf();
@@ -964,14 +998,14 @@
     }
 
     @Override
-    public void setTintList(ColorStateList tint) {
+    public void setTintList(@Nullable ColorStateList tint) {
         mGradientState.mTint = tint;
         mTintFilter = updateTintFilter(mTintFilter, tint, mGradientState.mTintMode);
         invalidateSelf();
     }
 
     @Override
-    public void setTintMode(PorterDuff.Mode tintMode) {
+    public void setTintMode(@Nullable PorterDuff.Mode tintMode) {
         mGradientState.mTintMode = tintMode;
         mTintFilter = updateTintFilter(mTintFilter, mGradientState.mTint, tintMode);
         invalidateSelf();
@@ -1543,7 +1577,7 @@
             final TypedValue tv = a.peekValue(R.styleable.GradientDrawableGradient_gradientRadius);
             if (tv != null) {
                 final float radius;
-                final int radiusType;
+                final @RadiusType int radiusType;
                 if (tv.type == TypedValue.TYPE_FRACTION) {
                     radius = tv.getFraction(1.0f, 1.0f);
 
@@ -1624,7 +1658,9 @@
             return false;
         }
 
-        if (!isOpaque(mFillPaint.getColor())) {
+        // Don't check opacity if we're using a gradient, as we've already
+        // checked the gradient opacity in mOpaqueOverShape.
+        if (mGradientState.mGradientColors == null && !isOpaque(mFillPaint.getColor())) {
             return false;
         }
 
@@ -1699,14 +1735,14 @@
 
     final static class GradientState extends ConstantState {
         public int mChangingConfigurations;
-        public int mShape = RECTANGLE;
-        public int mGradient = LINEAR_GRADIENT;
+        public @Shape int mShape = RECTANGLE;
+        public @GradientType int mGradient = LINEAR_GRADIENT;
         public int mAngle = 0;
         public Orientation mOrientation;
         public ColorStateList mSolidColors;
         public ColorStateList mStrokeColors;
-        public int[] mGradientColors;
-        public int[] mTempColors; // no need to copy
+        public @ColorInt int[] mGradientColors;
+        public @ColorInt int[] mTempColors; // no need to copy
         public float[] mTempPositions; // no need to copy
         public float[] mPositions;
         public int mStrokeWidth = -1; // if >= 0 use stroking.
@@ -1727,7 +1763,7 @@
         float mCenterX = 0.5f;
         float mCenterY = 0.5f;
         float mGradientRadius = 0.5f;
-        int mGradientRadiusType = RADIUS_TYPE_PIXELS;
+        @RadiusType int mGradientRadiusType = RADIUS_TYPE_PIXELS;
         boolean mUseLevel = false;
         boolean mUseLevelForShape = true;
 
@@ -1933,12 +1969,12 @@
                     | (mTint != null ? mTint.getChangingConfigurations() : 0);
         }
 
-        public void setShape(int shape) {
+        public void setShape(@Shape int shape) {
             mShape = shape;
             computeOpacity();
         }
 
-        public void setGradientType(int gradient) {
+        public void setGradientType(@GradientType int gradient) {
             mGradient = gradient;
         }
 
@@ -1947,13 +1983,13 @@
             mCenterY = y;
         }
 
-        public void setGradientColors(int[] colors) {
+        public void setGradientColors(@Nullable int[] colors) {
             mGradientColors = colors;
             mSolidColors = null;
             computeOpacity();
         }
 
-        public void setSolidColors(ColorStateList colors) {
+        public void setSolidColors(@Nullable ColorStateList colors) {
             mGradientColors = null;
             mSolidColors = colors;
             computeOpacity();
@@ -1984,7 +2020,8 @@
                     && mRadiusArray == null;
         }
 
-        public void setStroke(int width, ColorStateList colors, float dashWidth, float dashGap) {
+        public void setStroke(int width, @Nullable ColorStateList colors, float dashWidth,
+                float dashGap) {
             mStrokeWidth = width;
             mStrokeColors = colors;
             mStrokeDashWidth = dashWidth;
@@ -2012,7 +2049,7 @@
             mHeight = height;
         }
 
-        public void setGradientRadius(float gradientRadius, int type) {
+        public void setGradientRadius(float gradientRadius, @RadiusType int type) {
             mGradientRadius = gradientRadius;
             mGradientRadiusType = type;
         }
diff --git a/graphics/java/android/graphics/drawable/Icon.java b/graphics/java/android/graphics/drawable/Icon.java
index 0de4c2c..51221b4 100644
--- a/graphics/java/android/graphics/drawable/Icon.java
+++ b/graphics/java/android/graphics/drawable/Icon.java
@@ -627,6 +627,11 @@
         return this;
     }
 
+    /** @hide */
+    public boolean hasTint() {
+        return (mTintList != null) || (mTintMode != DEFAULT_TINT_MODE);
+    }
+
     /**
      * Create an Icon pointing to an image file specified by path.
      *
diff --git a/graphics/java/android/graphics/drawable/LayerDrawable.java b/graphics/java/android/graphics/drawable/LayerDrawable.java
index e2150c0..d142f95 100644
--- a/graphics/java/android/graphics/drawable/LayerDrawable.java
+++ b/graphics/java/android/graphics/drawable/LayerDrawable.java
@@ -944,17 +944,17 @@
     }
 
     @Override
-    public void invalidateDrawable(Drawable who) {
+    public void invalidateDrawable(@NonNull Drawable who) {
         invalidateSelf();
     }
 
     @Override
-    public void scheduleDrawable(Drawable who, Runnable what, long when) {
+    public void scheduleDrawable(@NonNull Drawable who, @NonNull Runnable what, long when) {
         scheduleSelf(what, when);
     }
 
     @Override
-    public void unscheduleDrawable(Drawable who, Runnable what) {
+    public void unscheduleDrawable(@NonNull Drawable who, @NonNull Runnable what) {
         unscheduleSelf(what);
     }
 
diff --git a/graphics/java/android/graphics/drawable/VectorDrawable.java b/graphics/java/android/graphics/drawable/VectorDrawable.java
index 9e0f1b4..44a91fe 100644
--- a/graphics/java/android/graphics/drawable/VectorDrawable.java
+++ b/graphics/java/android/graphics/drawable/VectorDrawable.java
@@ -364,7 +364,9 @@
 
     @Override
     public int getOpacity() {
-        return PixelFormat.TRANSLUCENT;
+        // We can't tell whether the drawable is fully opaque unless we examine all the pixels,
+        // but we could tell it is transparent if the root alpha is 0.
+        return getAlpha() == 0 ? PixelFormat.TRANSPARENT : PixelFormat.TRANSLUCENT;
     }
 
     @Override
diff --git a/graphics/java/android/graphics/drawable/shapes/ArcShape.java b/graphics/java/android/graphics/drawable/shapes/ArcShape.java
index 84731b0..c4b239f 100644
--- a/graphics/java/android/graphics/drawable/shapes/ArcShape.java
+++ b/graphics/java/android/graphics/drawable/shapes/ArcShape.java
@@ -17,6 +17,7 @@
 package android.graphics.drawable.shapes;
 
 import android.graphics.Canvas;
+import android.graphics.Outline;
 import android.graphics.Paint;
 
 /**
@@ -46,5 +47,11 @@
     public void draw(Canvas canvas, Paint paint) {
         canvas.drawArc(rect(), mStart, mSweep, true, paint);
     }
+
+    @Override
+    public void getOutline(Outline outline) {
+        // Since we don't support concave outlines, arc shape does not attempt
+        // to provide an outline.
+    }
 }
 
diff --git a/include/androidfw/ResourceTypes.h b/include/androidfw/ResourceTypes.h
index d8801b8..05596f0 100644
--- a/include/androidfw/ResourceTypes.h
+++ b/include/androidfw/ResourceTypes.h
@@ -35,6 +35,8 @@
 
 #include <android/configuration.h>
 
+#include <memory>
+
 namespace android {
 
 /**
@@ -1151,9 +1153,13 @@
         uint32_t screenConfig2;
     };
 
-    // If true, it means that the script of the locale was explicitly provided.
-    // If false, it means that the script was automatically computed.
-    bool localeScriptWasProvided;
+    // If false and localeScript is set, it means that the script of the locale
+    // was explicitly provided.
+    //
+    // If true, it means that localeScript was automatically computed.
+    // localeScript may still not be set in this case, which means that we
+    // tried but could not compute a script.
+    bool localeScriptWasComputed;
 
     void copyFromDeviceNoSwap(const ResTable_config& o);
     
@@ -1233,7 +1239,7 @@
 
     inline void clearLocale() {
         locale = 0;
-        localeScriptWasProvided = false;
+        localeScriptWasComputed = false;
         memset(localeScript, 0, sizeof(localeScript));
         memset(localeVariant, 0, sizeof(localeVariant));
     }
@@ -1872,9 +1878,30 @@
     struct Entry;
     struct Package;
     struct PackageGroup;
-    struct bag_set;
     typedef Vector<Type*> TypeList;
 
+    struct bag_set {
+        size_t numAttrs;    // number in array
+        size_t availAttrs;  // total space in array
+        uint32_t typeSpecFlags;
+        // Followed by 'numAttr' bag_entry structures.
+    };
+
+    /**
+     * Configuration dependent cached data. This must be cleared when the configuration is
+     * changed (setParameters).
+     */
+    struct TypeCacheEntry {
+        TypeCacheEntry() : cachedBags(NULL) {}
+
+        // Computed attribute bags for this type.
+        bag_set** cachedBags;
+
+        // Pre-filtered list of configurations (per asset path) that match the parameters set on this
+        // ResTable.
+        Vector<std::shared_ptr<Vector<const ResTable_type*>>> filteredConfigs;
+    };
+
     status_t addInternal(const void* data, size_t size, const void* idmapData, size_t idmapDataSize,
             bool appAsLib, const int32_t cookie, bool copyData, bool isSystemAsset=false);
 
@@ -1896,6 +1923,13 @@
 
     mutable Mutex               mLock;
 
+    // Mutex that controls access to the list of pre-filtered configurations
+    // to check when looking up entries.
+    // When iterating over a bag, the mLock mutex is locked. While mLock is locked,
+    // we do resource lookups.
+    // Mutex is not reentrant, so we must use a different lock than mLock.
+    mutable Mutex               mFilteredConfigLock;
+
     status_t                    mError;
 
     ResTable_config             mParams;
diff --git a/keystore/java/android/security/Credentials.java b/keystore/java/android/security/Credentials.java
index 302b0bd..6830a74 100644
--- a/keystore/java/android/security/Credentials.java
+++ b/keystore/java/android/security/Credentials.java
@@ -217,42 +217,42 @@
     }
 
     /**
-     * Delete all types (private key, certificate, CA certificate) for a
+     * Delete all types (private key, user certificate, CA certificate) for a
      * particular {@code alias}. All three can exist for any given alias.
-     * Returns {@code true} if there was at least one of those types.
+     * Returns {@code true} if the alias no longer contains any types.
      */
     public static boolean deleteAllTypesForAlias(KeyStore keystore, String alias) {
         return deleteAllTypesForAlias(keystore, alias, KeyStore.UID_SELF);
     }
 
     /**
-     * Delete all types (private key, certificate, CA certificate) for a
+     * Delete all types (private key, user certificate, CA certificate) for a
      * particular {@code alias}. All three can exist for any given alias.
-     * Returns {@code true} if there was at least one of those types.
+     * Returns {@code true} if the alias no longer contains any types.
      */
     public static boolean deleteAllTypesForAlias(KeyStore keystore, String alias, int uid) {
         /*
          * Make sure every type is deleted. There can be all three types, so
          * don't use a conditional here.
          */
-        return keystore.delete(Credentials.USER_PRIVATE_KEY + alias, uid)
-                | keystore.delete(Credentials.USER_SECRET_KEY + alias, uid)
-                | deleteCertificateTypesForAlias(keystore, alias, uid);
+        return deletePrivateKeyTypeForAlias(keystore, alias, uid)
+                & deleteSecretKeyTypeForAlias(keystore, alias, uid)
+                & deleteCertificateTypesForAlias(keystore, alias, uid);
     }
 
     /**
-     * Delete all types (private key, certificate, CA certificate) for a
-     * particular {@code alias}. All three can exist for any given alias.
-     * Returns {@code true} if there was at least one of those types.
+     * Delete certificate types (user certificate, CA certificate) for a
+     * particular {@code alias}. Both can exist for any given alias.
+     * Returns {@code true} if the alias no longer contains either type.
      */
     public static boolean deleteCertificateTypesForAlias(KeyStore keystore, String alias) {
         return deleteCertificateTypesForAlias(keystore, alias, KeyStore.UID_SELF);
     }
 
     /**
-     * Delete all types (private key, certificate, CA certificate) for a
-     * particular {@code alias}. All three can exist for any given alias.
-     * Returns {@code true} if there was at least one of those types.
+     * Delete certificate types (user certificate, CA certificate) for a
+     * particular {@code alias}. Both can exist for any given alias.
+     * Returns {@code true} if the alias no longer contains either type.
      */
     public static boolean deleteCertificateTypesForAlias(KeyStore keystore, String alias, int uid) {
         /*
@@ -260,12 +260,12 @@
          * so don't use a conditional here.
          */
         return keystore.delete(Credentials.USER_CERTIFICATE + alias, uid)
-                | keystore.delete(Credentials.CA_CERTIFICATE + alias, uid);
+                & keystore.delete(Credentials.CA_CERTIFICATE + alias, uid);
     }
 
     /**
      * Delete private key for a particular {@code alias}.
-     * Returns {@code true} if an entry was was deleted.
+     * Returns {@code true} if the entry no longer exists.
      */
     static boolean deletePrivateKeyTypeForAlias(KeyStore keystore, String alias) {
         return deletePrivateKeyTypeForAlias(keystore, alias, KeyStore.UID_SELF);
@@ -273,7 +273,7 @@
 
     /**
      * Delete private key for a particular {@code alias}.
-     * Returns {@code true} if an entry was was deleted.
+     * Returns {@code true} if the entry no longer exists.
      */
     static boolean deletePrivateKeyTypeForAlias(KeyStore keystore, String alias, int uid) {
         return keystore.delete(Credentials.USER_PRIVATE_KEY + alias, uid);
@@ -281,7 +281,7 @@
 
     /**
      * Delete secret key for a particular {@code alias}.
-     * Returns {@code true} if an entry was was deleted.
+     * Returns {@code true} if the entry no longer exists.
      */
     public static boolean deleteSecretKeyTypeForAlias(KeyStore keystore, String alias) {
         return deleteSecretKeyTypeForAlias(keystore, alias, KeyStore.UID_SELF);
@@ -289,7 +289,7 @@
 
     /**
      * Delete secret key for a particular {@code alias}.
-     * Returns {@code true} if an entry was was deleted.
+     * Returns {@code true} if the entry no longer exists.
      */
     public static boolean deleteSecretKeyTypeForAlias(KeyStore keystore, String alias, int uid) {
         return keystore.delete(Credentials.USER_SECRET_KEY + alias, uid);
diff --git a/keystore/java/android/security/KeyChain.java b/keystore/java/android/security/KeyChain.java
index 7adad8a..0886487 100644
--- a/keystore/java/android/security/KeyChain.java
+++ b/keystore/java/android/security/KeyChain.java
@@ -547,11 +547,8 @@
         Intent intent = new Intent(IKeyChainService.class.getName());
         ComponentName comp = intent.resolveSystemService(context.getPackageManager(), 0);
         intent.setComponent(comp);
-        boolean isBound = context.bindServiceAsUser(intent,
-                                                    keyChainServiceConnection,
-                                                    Context.BIND_AUTO_CREATE,
-                                                    user);
-        if (!isBound) {
+        if (comp == null || !context.bindServiceAsUser(
+                intent, keyChainServiceConnection, Context.BIND_AUTO_CREATE, user)) {
             throw new AssertionError("could not bind to KeyChainService");
         }
         return new KeyChainConnection(context, keyChainServiceConnection, q.take());
diff --git a/keystore/java/android/security/KeyStore.java b/keystore/java/android/security/KeyStore.java
index 3090ac1..70e4b6f 100644
--- a/keystore/java/android/security/KeyStore.java
+++ b/keystore/java/android/security/KeyStore.java
@@ -183,7 +183,8 @@
 
     public boolean delete(String key, int uid) {
         try {
-            return mBinder.del(key, uid) == NO_ERROR;
+            int ret = mBinder.del(key, uid);
+            return (ret == NO_ERROR || ret == KEY_NOT_FOUND);
         } catch (RemoteException e) {
             Log.w(TAG, "Cannot connect to keystore", e);
             return false;
diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreSpi.java b/keystore/java/android/security/keystore/AndroidKeyStoreSpi.java
index d7d4f1c..fcbb553 100644
--- a/keystore/java/android/security/keystore/AndroidKeyStoreSpi.java
+++ b/keystore/java/android/security/keystore/AndroidKeyStoreSpi.java
@@ -765,11 +765,6 @@
 
     @Override
     public void engineDeleteEntry(String alias) throws KeyStoreException {
-        if (!engineContainsAlias(alias)) {
-            return;
-        }
-        // At least one entry corresponding to this alias exists in keystore
-
         if (!Credentials.deleteAllTypesForAlias(mKeyStore, alias, mUid)) {
             throw new KeyStoreException("Failed to delete entry: " + alias);
         }
diff --git a/libs/androidfw/ResourceTypes.cpp b/libs/androidfw/ResourceTypes.cpp
index 3277c36..52fe973 100644
--- a/libs/androidfw/ResourceTypes.cpp
+++ b/libs/androidfw/ResourceTypes.cpp
@@ -25,6 +25,7 @@
 #include <string.h>
 
 #include <limits>
+#include <memory>
 #include <type_traits>
 
 #include <androidfw/ByteBucketArray.h>
@@ -1869,8 +1870,8 @@
 
     // The language & region are equal, so compare the scripts and variants.
     const char emptyScript[sizeof(l.localeScript)] = {'\0', '\0', '\0', '\0'};
-    const char *lScript = l.localeScriptWasProvided ? l.localeScript : emptyScript;
-    const char *rScript = r.localeScriptWasProvided ? r.localeScript : emptyScript;
+    const char *lScript = l.localeScriptWasComputed ? emptyScript : l.localeScript;
+    const char *rScript = r.localeScriptWasComputed ? emptyScript : r.localeScript;
     int script = memcmp(lScript, rScript, sizeof(l.localeScript));
     if (script) {
         return script;
@@ -2015,11 +2016,11 @@
     // scripts since it seems more useful to do so. We will consider
     // "en-US-POSIX" to be more specific than "en-Latn-US".
 
-    const int score = (localeScriptWasProvided ? 1 : 0) +
-        ((localeVariant[0] != 0) ? 2 : 0);
+    const int score = ((localeScript[0] != '\0' && !localeScriptWasComputed) ? 1 : 0) +
+        ((localeVariant[0] != '\0') ? 2 : 0);
 
-    const int oScore = (o.localeScriptWasProvided ? 1 : 0) +
-        ((o.localeVariant[0] != 0) ? 2 : 0);
+    const int oScore = (o.localeScript[0] != '\0' && !o.localeScriptWasComputed ? 1 : 0) +
+        ((o.localeVariant[0] != '\0') ? 2 : 0);
 
     return score - oScore;
 
@@ -2534,7 +2535,8 @@
         if (settings.localeScript[0] == '\0') { // could not determine the request's script
             countriesMustMatch = true;
         } else {
-            if (localeScript[0] == '\0') { // script was not provided, so we try to compute it
+            if (localeScript[0] == '\0' && !localeScriptWasComputed) {
+                // script was not provided or computed, so we try to compute it
                 localeDataComputeScript(computed_script, language, country);
                 if (computed_script[0] == '\0') { // we could not compute the script
                     countriesMustMatch = true;
@@ -2683,8 +2685,8 @@
     if (!language[0]) {
         return;
     }
-
-    if (!localeScriptWasProvided && !localeVariant[0]) {
+    const bool scriptWasProvided = localeScript[0] != '\0' && !localeScriptWasComputed;
+    if (!scriptWasProvided && !localeVariant[0]) {
         // Legacy format.
         if (out.size() > 0) {
             out.append("-");
@@ -2714,7 +2716,7 @@
     size_t len = unpackLanguage(buf);
     out.append(buf, len);
 
-    if (localeScriptWasProvided) {
+    if (scriptWasProvided) {
         out.append("+");
         out.append(localeScript, sizeof(localeScript));
     }
@@ -2745,7 +2747,7 @@
         charsWritten += unpackLanguage(str);
     }
 
-    if (localeScriptWasProvided) {
+    if (localeScript[0] && !localeScriptWasComputed) {
         if (charsWritten) {
             str[charsWritten++] = '-';
         }
@@ -2786,7 +2788,6 @@
                for (size_t i = 1; i < 4; ++i) {
                    config->localeScript[i] = tolower(start[i]);
                }
-               config->localeScriptWasProvided = true;
                break;
            }
        case 5:
@@ -2806,7 +2807,6 @@
 
 void ResTable_config::setBcp47Locale(const char* in) {
     locale = 0;
-    localeScriptWasProvided = false;
     memset(localeScript, 0, sizeof(localeScript));
     memset(localeVariant, 0, sizeof(localeVariant));
 
@@ -2823,9 +2823,10 @@
 
     const size_t size = in + strlen(in) - start;
     assignLocaleComponent(this, start, size);
-    if (localeScript[0] == '\0') {
+    localeScriptWasComputed = (localeScript[0] == '\0');
+    if (localeScriptWasComputed) {
         computeScript();
-    };
+    }
 }
 
 String8 ResTable_config::toString() const {
@@ -3193,7 +3194,6 @@
         , name(_name)
         , id(_id)
         , largestTypeId(0)
-        , bags(NULL)
         , dynamicRefTable(static_cast<uint8_t>(_id), appAsLib)
         , isSystemAsset(_isSystemAsset)
     { }
@@ -3220,36 +3220,41 @@
         }
     }
 
+    /**
+     * Clear all cache related data that depends on parameters/configuration.
+     * This includes the bag caches and filtered types.
+     */
     void clearBagCache() {
-        if (bags) {
+        for (size_t i = 0; i < typeCacheEntries.size(); i++) {
             if (kDebugTableNoisy) {
-                printf("bags=%p\n", bags);
+                printf("type=%zu\n", i);
             }
-            for (size_t i = 0; i < bags->size(); i++) {
+            const TypeList& typeList = types[i];
+            if (!typeList.isEmpty()) {
+                TypeCacheEntry& cacheEntry = typeCacheEntries.editItemAt(i);
+
+                // Reset the filtered configurations.
+                cacheEntry.filteredConfigs.clear();
+
+                bag_set** typeBags = cacheEntry.cachedBags;
                 if (kDebugTableNoisy) {
-                    printf("type=%zu\n", i);
+                    printf("typeBags=%p\n", typeBags);
                 }
-                const TypeList& typeList = types[i];
-                if (!typeList.isEmpty()) {
-                    bag_set** typeBags = bags->get(i);
+
+                if (typeBags) {
+                    const size_t N = typeList[0]->entryCount;
                     if (kDebugTableNoisy) {
-                        printf("typeBags=%p\n", typeBags);
+                        printf("type->entryCount=%zu\n", N);
                     }
-                    if (typeBags) {
-                        const size_t N = typeList[0]->entryCount;
-                        if (kDebugTableNoisy) {
-                            printf("type->entryCount=%zu\n", N);
+                    for (size_t j = 0; j < N; j++) {
+                        if (typeBags[j] && typeBags[j] != (bag_set*)0xFFFFFFFF) {
+                            free(typeBags[j]);
                         }
-                        for (size_t j = 0; j < N; j++) {
-                            if (typeBags[j] && typeBags[j] != (bag_set*)0xFFFFFFFF)
-                                free(typeBags[j]);
-                        }
-                        free(typeBags);
                     }
+                    free(typeBags);
+                    cacheEntry.cachedBags = NULL;
                 }
             }
-            delete bags;
-            bags = NULL;
         }
     }
 
@@ -3277,9 +3282,11 @@
 
     uint8_t                         largestTypeId;
 
-    // Computed attribute bags, first indexed by the type and second
-    // by the entry in that type.
-    ByteBucketArray<bag_set**>*     bags;
+    // Cached objects dependent on the parameters/configuration of this ResTable.
+    // Gets cleared whenever the parameters/configuration changes.
+    // These are stored here in a parallel structure because the data in `types` may
+    // be shared by other ResTable's (framework resources are shared this way).
+    ByteBucketArray<TypeCacheEntry> typeCacheEntries;
 
     // The table mapping dynamic references to resolved references for
     // this package group.
@@ -3293,14 +3300,6 @@
     const bool                      isSystemAsset;
 };
 
-struct ResTable::bag_set
-{
-    size_t numAttrs;    // number in array
-    size_t availAttrs;  // total space in array
-    uint32_t typeSpecFlags;
-    // Followed by 'numAttr' bag_entry structures.
-};
-
 ResTable::Theme::Theme(const ResTable& table)
     : mTable(table)
     , mTypeSpecFlags(0)
@@ -4192,39 +4191,32 @@
     }
 
     // First see if we've already computed this bag...
-    if (grp->bags) {
-        bag_set** typeSet = grp->bags->get(t);
-        if (typeSet) {
-            bag_set* set = typeSet[e];
-            if (set) {
-                if (set != (bag_set*)0xFFFFFFFF) {
-                    if (outTypeSpecFlags != NULL) {
-                        *outTypeSpecFlags = set->typeSpecFlags;
-                    }
-                    *outBag = (bag_entry*)(set+1);
-                    if (kDebugTableSuperNoisy) {
-                        ALOGI("Found existing bag for: 0x%x\n", resID);
-                    }
-                    return set->numAttrs;
+    TypeCacheEntry& cacheEntry = grp->typeCacheEntries.editItemAt(t);
+    bag_set** typeSet = cacheEntry.cachedBags;
+    if (typeSet) {
+        bag_set* set = typeSet[e];
+        if (set) {
+            if (set != (bag_set*)0xFFFFFFFF) {
+                if (outTypeSpecFlags != NULL) {
+                    *outTypeSpecFlags = set->typeSpecFlags;
                 }
-                ALOGW("Attempt to retrieve bag 0x%08x which is invalid or in a cycle.",
-                     resID);
-                return BAD_INDEX;
+                *outBag = (bag_entry*)(set+1);
+                if (kDebugTableSuperNoisy) {
+                    ALOGI("Found existing bag for: 0x%x\n", resID);
+                }
+                return set->numAttrs;
             }
+            ALOGW("Attempt to retrieve bag 0x%08x which is invalid or in a cycle.",
+                 resID);
+            return BAD_INDEX;
         }
     }
 
     // Bag not found, we need to compute it!
-    if (!grp->bags) {
-        grp->bags = new ByteBucketArray<bag_set**>();
-        if (!grp->bags) return NO_MEMORY;
-    }
-
-    bag_set** typeSet = grp->bags->get(t);
     if (!typeSet) {
         typeSet = (bag_set**)calloc(NENTRY, sizeof(bag_set*));
         if (!typeSet) return NO_MEMORY;
-        grp->bags->set(t, typeSet);
+        cacheEntry.cachedBags = typeSet;
     }
 
     // Mark that we are currently working on this one.
@@ -4430,18 +4422,56 @@
 
 void ResTable::setParameters(const ResTable_config* params)
 {
-    mLock.lock();
+    AutoMutex _lock(mLock);
+    AutoMutex _lock2(mFilteredConfigLock);
+
     if (kDebugTableGetEntry) {
         ALOGI("Setting parameters: %s\n", params->toString().string());
     }
     mParams = *params;
-    for (size_t i=0; i<mPackageGroups.size(); i++) {
+    for (size_t p = 0; p < mPackageGroups.size(); p++) {
+        PackageGroup* packageGroup = mPackageGroups.editItemAt(p);
         if (kDebugTableNoisy) {
-            ALOGI("CLEARING BAGS FOR GROUP %zu!", i);
+            ALOGI("CLEARING BAGS FOR GROUP %zu!", p);
         }
-        mPackageGroups[i]->clearBagCache();
+        packageGroup->clearBagCache();
+
+        // Find which configurations match the set of parameters. This allows for a much
+        // faster lookup in getEntry() if the set of values is narrowed down.
+        for (size_t t = 0; t < packageGroup->types.size(); t++) {
+            if (packageGroup->types[t].isEmpty()) {
+                continue;
+            }
+
+            TypeList& typeList = packageGroup->types.editItemAt(t);
+
+            // Retrieve the cache entry for this type.
+            TypeCacheEntry& cacheEntry = packageGroup->typeCacheEntries.editItemAt(t);
+
+            for (size_t ts = 0; ts < typeList.size(); ts++) {
+                Type* type = typeList.editItemAt(ts);
+
+                std::shared_ptr<Vector<const ResTable_type*>> newFilteredConfigs =
+                        std::make_shared<Vector<const ResTable_type*>>();
+
+                for (size_t ti = 0; ti < type->configs.size(); ti++) {
+                    ResTable_config config;
+                    config.copyFromDtoH(type->configs[ti]->config);
+
+                    if (config.match(mParams)) {
+                        newFilteredConfigs->add(type->configs[ti]);
+                    }
+                }
+
+                if (kDebugTableNoisy) {
+                    ALOGD("Updating pkg=%zu type=%zu with %zu filtered configs",
+                          p, t, newFilteredConfigs->size());
+                }
+
+                cacheEntry.filteredConfigs.add(newFilteredConfigs);
+            }
+        }
     }
-    mLock.unlock();
 }
 
 void ResTable::getParameters(ResTable_config* params) const
@@ -5974,9 +6004,32 @@
             specFlags = -1;
         }
 
-        const size_t numConfigs = typeSpec->configs.size();
+        const Vector<const ResTable_type*>* candidateConfigs = &typeSpec->configs;
+
+        std::shared_ptr<Vector<const ResTable_type*>> filteredConfigs;
+        if (config && memcmp(&mParams, config, sizeof(mParams)) == 0) {
+            // Grab the lock first so we can safely get the current filtered list.
+            AutoMutex _lock(mFilteredConfigLock);
+
+            // This configuration is equal to the one we have previously cached for,
+            // so use the filtered configs.
+
+            const TypeCacheEntry& cacheEntry = packageGroup->typeCacheEntries[typeIndex];
+            if (i < cacheEntry.filteredConfigs.size()) {
+                if (cacheEntry.filteredConfigs[i]) {
+                    // Grab a reference to the shared_ptr so it doesn't get destroyed while
+                    // going through this list.
+                    filteredConfigs = cacheEntry.filteredConfigs[i];
+
+                    // Use this filtered list.
+                    candidateConfigs = filteredConfigs.get();
+                }
+            }
+        }
+
+        const size_t numConfigs = candidateConfigs->size();
         for (size_t c = 0; c < numConfigs; c++) {
-            const ResTable_type* const thisType = typeSpec->configs[c];
+            const ResTable_type* const thisType = candidateConfigs->itemAt(c);
             if (thisType == NULL) {
                 continue;
             }
diff --git a/libs/androidfw/tests/ConfigLocale_test.cpp b/libs/androidfw/tests/ConfigLocale_test.cpp
index 4b8d65c..2bf9b12 100644
--- a/libs/androidfw/tests/ConfigLocale_test.cpp
+++ b/libs/androidfw/tests/ConfigLocale_test.cpp
@@ -125,10 +125,10 @@
 
      if (script != NULL) {
          memcpy(out->localeScript, script, 4);
-         out->localeScriptWasProvided = true;
+         out->localeScriptWasComputed = false;
      } else {
          out->computeScript();
-         out->localeScriptWasProvided = false;
+         out->localeScriptWasComputed = true;
      }
 
      if (variant != NULL) {
@@ -182,7 +182,7 @@
     EXPECT_EQ('n', test.language[1]);
     EXPECT_EQ('U', test.country[0]);
     EXPECT_EQ('S', test.country[1]);
-    EXPECT_FALSE(test.localeScriptWasProvided);
+    EXPECT_TRUE(test.localeScriptWasComputed);
     EXPECT_EQ(0, memcmp("Latn", test.localeScript, 4));
     EXPECT_EQ(0, test.localeVariant[0]);
 
@@ -203,7 +203,7 @@
     EXPECT_EQ('e', test.language[0]);
     EXPECT_EQ('n', test.language[1]);
     EXPECT_EQ(0, memcmp("Latn", test.localeScript, 4));
-    EXPECT_TRUE(test.localeScriptWasProvided);
+    EXPECT_FALSE(test.localeScriptWasComputed);
     memset(out, 1, 4);
     test.unpackRegion(out);
     EXPECT_EQ('4', out[0]);
@@ -216,7 +216,7 @@
     EXPECT_EQ('d', out[0]);
     EXPECT_EQ('e', out[1]);
     EXPECT_EQ('\0', out[2]);
-    EXPECT_FALSE(test.localeScriptWasProvided);
+    EXPECT_TRUE(test.localeScriptWasComputed);
     EXPECT_EQ(0, memcmp("Latn", test.localeScript, 4));
     memset(out, 1, 4);
     test.unpackRegion(out);
@@ -229,7 +229,7 @@
     EXPECT_EQ('d', out[0]);
     EXPECT_EQ('e', out[1]);
     EXPECT_EQ('\0', out[2]);
-    EXPECT_TRUE(test.localeScriptWasProvided);
+    EXPECT_FALSE(test.localeScriptWasComputed);
     EXPECT_EQ(0, memcmp("Latn", test.localeScript, 4));
     memset(out, 1, 4);
     test.unpackRegion(out);
@@ -270,11 +270,11 @@
     fillIn("en", NULL, "Latn", NULL, &config);
 
     char out[RESTABLE_MAX_LOCALE_LEN];
-    config.localeScriptWasProvided = true;
+    config.localeScriptWasComputed = false;
     config.getBcp47Locale(out);
     EXPECT_EQ(0, strcmp("en-Latn", out));
 
-    config.localeScriptWasProvided = false;
+    config.localeScriptWasComputed = true;
     config.getBcp47Locale(out);
     EXPECT_EQ(0, strcmp("en", out));
 }
@@ -379,7 +379,7 @@
 
     // emulate packages built with older AAPT
     memset(supported.localeScript, '\0', 4);
-    supported.localeScriptWasProvided = false;
+    supported.localeScriptWasComputed = false;
 
     EXPECT_TRUE(supported.match(requested));
 }
diff --git a/libs/androidfw/tests/ResTable_test.cpp b/libs/androidfw/tests/ResTable_test.cpp
index dcfe91e..7cd7fb5 100644
--- a/libs/androidfw/tests/ResTable_test.cpp
+++ b/libs/androidfw/tests/ResTable_test.cpp
@@ -282,4 +282,46 @@
     testU16StringToInt(u"0x1ffffffff", 0U, false, true);
 }
 
+TEST(ResTableTest, ShareButDontModifyResTable) {
+    ResTable sharedTable;
+    ASSERT_EQ(NO_ERROR, sharedTable.add(basic_arsc, basic_arsc_len));
+
+    ResTable_config param;
+    memset(&param, 0, sizeof(param));
+    param.language[0] = 'v';
+    param.language[1] = 's';
+    sharedTable.setParameters(&param);
+
+    // Check that we get the default value for @integer:number1
+    Res_value val;
+    ssize_t block = sharedTable.getResource(base::R::integer::number1, &val, MAY_NOT_BE_BAG);
+    ASSERT_GE(block, 0);
+    ASSERT_EQ(Res_value::TYPE_INT_DEC, val.dataType);
+    ASSERT_EQ(uint32_t(600), val.data);
+
+    // Create a new table that shares the entries of the shared table.
+    ResTable table;
+    ASSERT_EQ(NO_ERROR, table.add(&sharedTable, false));
+
+    // Set a new configuration on the new table.
+    memset(&param, 0, sizeof(param));
+    param.language[0] = 's';
+    param.language[1] = 'v';
+    param.country[0] = 'S';
+    param.country[1] = 'E';
+    table.setParameters(&param);
+
+    // Check that we get a new value in the new table.
+    block = table.getResource(base::R::integer::number1, &val, MAY_NOT_BE_BAG);
+    ASSERT_GE(block, 0);
+    ASSERT_EQ(Res_value::TYPE_INT_DEC, val.dataType);
+    ASSERT_EQ(uint32_t(400), val.data);
+
+    // Check that we still get the old value in the shared table.
+    block = sharedTable.getResource(base::R::integer::number1, &val, MAY_NOT_BE_BAG);
+    ASSERT_GE(block, 0);
+    ASSERT_EQ(Res_value::TYPE_INT_DEC, val.dataType);
+    ASSERT_EQ(uint32_t(600), val.data);
 }
+
+} // namespace
diff --git a/libs/androidfw/tests/data/basic/R.h b/libs/androidfw/tests/data/basic/R.h
index aaac740..6694dd0 100644
--- a/libs/androidfw/tests/data/basic/R.h
+++ b/libs/androidfw/tests/data/basic/R.h
@@ -46,7 +46,7 @@
 
 namespace integer {
     enum {
-        number1     = 0x7f040000,   // default, sv
+        number1     = 0x7f040000,   // default, sv, vs
         number2     = 0x7f040001,   // default
 
         test3       = 0x7f090000,   // default (in feature)
diff --git a/libs/androidfw/tests/data/basic/basic_arsc.h b/libs/androidfw/tests/data/basic/basic_arsc.h
index 13ab4fa..e497401 100644
--- a/libs/androidfw/tests/data/basic/basic_arsc.h
+++ b/libs/androidfw/tests/data/basic/basic_arsc.h
@@ -1,5 +1,5 @@
 unsigned char basic_arsc[] = {
-  0x02, 0x00, 0x0c, 0x00, 0x68, 0x07, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0x02, 0x00, 0x0c, 0x00, 0x0c, 0x08, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
   0x01, 0x00, 0x1c, 0x00, 0xbc, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x00,
@@ -16,7 +16,7 @@
   0x00, 0x00, 0x05, 0x00, 0x74, 0x00, 0x65, 0x00, 0x73, 0x00, 0x74, 0x00,
   0x31, 0x00, 0x00, 0x00, 0x05, 0x00, 0x74, 0x00, 0x65, 0x00, 0x73, 0x00,
   0x74, 0x00, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x01,
-  0xa0, 0x06, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x63, 0x00, 0x6f, 0x00,
+  0x44, 0x07, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x63, 0x00, 0x6f, 0x00,
   0x6d, 0x00, 0x2e, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x64, 0x00, 0x72, 0x00,
   0x6f, 0x00, 0x69, 0x00, 0x64, 0x00, 0x2e, 0x00, 0x74, 0x00, 0x65, 0x00,
   0x73, 0x00, 0x74, 0x00, 0x2e, 0x00, 0x62, 0x00, 0x61, 0x00, 0x73, 0x00,
@@ -73,68 +73,81 @@
   0x41, 0x00, 0x72, 0x00, 0x72, 0x00, 0x61, 0x00, 0x79, 0x00, 0x31, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00, 0x18, 0x00, 0x00, 0x00,
   0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x44, 0x00, 0x84, 0x00, 0x00, 0x00,
-  0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00,
-  0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x4c, 0x00, 0x8c, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00,
+  0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x1c, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+  0x08, 0x00, 0x00, 0x10, 0x05, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x10, 0x05, 0x00, 0x00, 0x00,
-  0x10, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x10,
-  0x05, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00, 0x14, 0x00, 0x00, 0x00,
-  0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x24, 0x00, 0x00,
-  0x01, 0x02, 0x44, 0x00, 0x58, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
-  0x01, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
+  0x02, 0x02, 0x10, 0x00, 0x14, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0x04, 0x24, 0x00, 0x00, 0x01, 0x02, 0x4c, 0x00,
+  0x60, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0x50, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x08, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x03,
-  0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x44, 0x00, 0x58, 0x00, 0x00, 0x00,
-  0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00,
-  0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x72, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x58, 0x02, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+  0x08, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x4c, 0x00,
+  0x60, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0x50, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x66, 0x72, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x58, 0x02,
+  0x00, 0x00, 0x00, 0x00, 0x4c, 0x61, 0x74, 0x6e, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
   0x08, 0x00, 0x00, 0x03, 0x01, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00,
   0x1c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x01, 0x02, 0x44, 0x00, 0x70, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
-  0x03, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
+  0x01, 0x02, 0x4c, 0x00, 0x78, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+  0x03, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x10, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x08, 0x00, 0x00, 0x00,
-  0x03, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x03, 0x02, 0x00, 0x00, 0x00,
-  0x08, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x03,
-  0x03, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00, 0x18, 0x00, 0x00, 0x00,
-  0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x44, 0x00, 0x6c, 0x00, 0x00, 0x00,
-  0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00,
-  0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+  0xff, 0xff, 0xff, 0xff, 0x08, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+  0x08, 0x00, 0x00, 0x03, 0x02, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
+  0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x03, 0x03, 0x00, 0x00, 0x00,
+  0x02, 0x02, 0x10, 0x00, 0x18, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+  0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x01, 0x02, 0x4c, 0x00, 0x74, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+  0x02, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
-  0x05, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x10, 0xc8, 0x00, 0x00, 0x00,
-  0x08, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x01,
-  0x00, 0x00, 0x06, 0x7f, 0x01, 0x02, 0x44, 0x00, 0x5c, 0x00, 0x00, 0x00,
-  0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00,
-  0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x73, 0x76, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+  0x08, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x10,
+  0xc8, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
+  0x08, 0x00, 0x00, 0x01, 0x00, 0x00, 0x06, 0x7f, 0x01, 0x02, 0x4c, 0x00,
+  0x64, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+  0x54, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x76, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x08, 0x00, 0x00, 0x00,
-  0x05, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x10, 0x90, 0x01, 0x00, 0x00,
-  0x02, 0x02, 0x10, 0x00, 0x18, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
-  0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x01, 0x02, 0x44, 0x00, 0x90, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
-  0x02, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
+  0x05, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x10, 0x58, 0x02, 0x00, 0x00,
+  0x01, 0x02, 0x4c, 0x00, 0x64, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+  0x02, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x73, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4c, 0x61, 0x74, 0x6e,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
+  0x08, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x10,
+  0x90, 0x01, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00, 0x18, 0x00, 0x00, 0x00,
+  0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x4c, 0x00, 0x98, 0x00, 0x00, 0x00,
+  0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00,
+  0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -146,16 +159,17 @@
   0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x7f, 0x01, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x01, 0x7f, 0x08, 0x00, 0x00, 0x10, 0x2c, 0x01, 0x00, 0x00,
   0x02, 0x02, 0x10, 0x00, 0x14, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
-  0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x44, 0x00,
-  0x7c, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
-  0x48, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x4c, 0x00,
+  0x84, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0x50, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00,
-  0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x02, 0x08, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00,
-  0x01, 0x00, 0x00, 0x02, 0x08, 0x00, 0x00, 0x10, 0x02, 0x00, 0x00, 0x00,
-  0x02, 0x00, 0x00, 0x02, 0x08, 0x00, 0x00, 0x10, 0x03, 0x00, 0x00, 0x00
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00, 0x09, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+  0x08, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02,
+  0x08, 0x00, 0x00, 0x10, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02,
+  0x08, 0x00, 0x00, 0x10, 0x03, 0x00, 0x00, 0x00
 };
-unsigned int basic_arsc_len = 1896;
+unsigned int basic_arsc_len = 2060;
diff --git a/packages/SystemUI/res/drawable/qs_background_secondary.xml b/libs/androidfw/tests/data/basic/res/values-vs/values.xml
similarity index 74%
copy from packages/SystemUI/res/drawable/qs_background_secondary.xml
copy to libs/androidfw/tests/data/basic/res/values-vs/values.xml
index 31c0162..4a5a640 100644
--- a/packages/SystemUI/res/drawable/qs_background_secondary.xml
+++ b/libs/androidfw/tests/data/basic/res/values-vs/values.xml
@@ -13,9 +13,7 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-<shape xmlns:android="http://schemas.android.com/apk/res/android">
-    <solid android:color="@color/system_secondary_color" />
-    <corners
-        android:topLeftRadius="0dp"
-        android:topRightRadius="0dp" />
-</shape>
+
+<resources>
+    <integer name="number1">600</integer>
+</resources>
diff --git a/libs/androidfw/tests/data/basic/split_de_fr_arsc.h b/libs/androidfw/tests/data/basic/split_de_fr_arsc.h
index b742d28..a2aa598 100644
--- a/libs/androidfw/tests/data/basic/split_de_fr_arsc.h
+++ b/libs/androidfw/tests/data/basic/split_de_fr_arsc.h
@@ -1,5 +1,5 @@
 unsigned char split_de_fr_arsc[] = {
-  0x02, 0x00, 0x0c, 0x00, 0xe4, 0x03, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0x02, 0x00, 0x0c, 0x00, 0xf4, 0x03, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
   0x01, 0x00, 0x1c, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00,
@@ -10,7 +10,7 @@
   0x32, 0x00, 0x00, 0x00, 0x07, 0x00, 0x65, 0x00, 0x73, 0x00, 0x73, 0x00,
   0x61, 0x00, 0x69, 0x00, 0x20, 0x00, 0x31, 0x00, 0x00, 0x00, 0x07, 0x00,
   0x65, 0x00, 0x73, 0x00, 0x73, 0x00, 0x61, 0x00, 0x69, 0x00, 0x20, 0x00,
-  0x32, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x01, 0x5c, 0x03, 0x00, 0x00,
+  0x32, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x01, 0x6c, 0x03, 0x00, 0x00,
   0x7f, 0x00, 0x00, 0x00, 0x63, 0x00, 0x6f, 0x00, 0x6d, 0x00, 0x2e, 0x00,
   0x61, 0x00, 0x6e, 0x00, 0x64, 0x00, 0x72, 0x00, 0x6f, 0x00, 0x69, 0x00,
   0x64, 0x00, 0x2e, 0x00, 0x74, 0x00, 0x65, 0x00, 0x73, 0x00, 0x74, 0x00,
@@ -57,30 +57,32 @@
   0x14, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00, 0x1c, 0x00, 0x00, 0x00,
   0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
-  0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x44, 0x00,
-  0x70, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
-  0x50, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x4c, 0x00,
+  0x78, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+  0x58, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x64, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x4c, 0x61, 0x74, 0x6e, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
+  0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x03,
+  0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0x08, 0x00, 0x00, 0x03, 0x01, 0x00, 0x00, 0x00, 0x01, 0x02, 0x4c, 0x00,
+  0x78, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+  0x58, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x66, 0x72, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
-  0xff, 0xff, 0xff, 0xff, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x08, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
-  0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x03, 0x01, 0x00, 0x00, 0x00,
-  0x01, 0x02, 0x44, 0x00, 0x70, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
-  0x03, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x66, 0x72, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x10, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x08, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x03, 0x02, 0x00, 0x00, 0x00,
-  0x08, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x03,
-  0x03, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00, 0x18, 0x00, 0x00, 0x00,
-  0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00, 0x18, 0x00, 0x00, 0x00,
-  0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00, 0x14, 0x00, 0x00, 0x00,
-  0x06, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+  0x00, 0x00, 0x00, 0x00, 0x4c, 0x61, 0x74, 0x6e, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
+  0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x03,
+  0x02, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0x08, 0x00, 0x00, 0x03, 0x03, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00,
+  0x18, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00,
+  0x18, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00,
+  0x14, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00
 };
-unsigned int split_de_fr_arsc_len = 996;
+unsigned int split_de_fr_arsc_len = 1012;
diff --git a/libs/androidfw/tests/data/basic/split_hdpi_v4_arsc.h b/libs/androidfw/tests/data/basic/split_hdpi_v4_arsc.h
index e9fb7ea..0cc3915 100644
--- a/libs/androidfw/tests/data/basic/split_hdpi_v4_arsc.h
+++ b/libs/androidfw/tests/data/basic/split_hdpi_v4_arsc.h
@@ -1,10 +1,10 @@
 unsigned char split_hdpi_v4_arsc[] = {
-  0x02, 0x00, 0x0c, 0x00, 0x08, 0x03, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0x02, 0x00, 0x0c, 0x00, 0x10, 0x03, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
   0x01, 0x00, 0x1c, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x68, 0x00,
   0x64, 0x00, 0x70, 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x01,
-  0xd0, 0x02, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x63, 0x00, 0x6f, 0x00,
+  0xd8, 0x02, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x63, 0x00, 0x6f, 0x00,
   0x6d, 0x00, 0x2e, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x64, 0x00, 0x72, 0x00,
   0x6f, 0x00, 0x69, 0x00, 0x64, 0x00, 0x2e, 0x00, 0x74, 0x00, 0x65, 0x00,
   0x73, 0x00, 0x74, 0x00, 0x2e, 0x00, 0x62, 0x00, 0x61, 0x00, 0x73, 0x00,
@@ -50,19 +50,20 @@
   0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00,
   0x1c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x01, 0x02, 0x44, 0x00, 0x60, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
-  0x03, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
+  0x01, 0x02, 0x4c, 0x00, 0x68, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+  0x03, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
-  0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00,
-  0x02, 0x02, 0x10, 0x00, 0x18, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
-  0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x02, 0x02, 0x10, 0x00, 0x18, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
-  0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x02, 0x02, 0x10, 0x00, 0x14, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
-  0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x08, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00,
+  0x18, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00,
+  0x18, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00,
+  0x14, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00
 };
-unsigned int split_hdpi_v4_arsc_len = 776;
+unsigned int split_hdpi_v4_arsc_len = 784;
diff --git a/libs/androidfw/tests/data/basic/split_xhdpi_v4_arsc.h b/libs/androidfw/tests/data/basic/split_xhdpi_v4_arsc.h
index 7835f71..d44ba96 100644
--- a/libs/androidfw/tests/data/basic/split_xhdpi_v4_arsc.h
+++ b/libs/androidfw/tests/data/basic/split_xhdpi_v4_arsc.h
@@ -1,10 +1,10 @@
 unsigned char split_xhdpi_v4_arsc[] = {
-  0x02, 0x00, 0x0c, 0x00, 0x0c, 0x03, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0x02, 0x00, 0x0c, 0x00, 0x14, 0x03, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
   0x01, 0x00, 0x1c, 0x00, 0x30, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x78, 0x00,
   0x68, 0x00, 0x64, 0x00, 0x70, 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x02, 0x20, 0x01, 0xd0, 0x02, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00,
+  0x00, 0x02, 0x20, 0x01, 0xd8, 0x02, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00,
   0x63, 0x00, 0x6f, 0x00, 0x6d, 0x00, 0x2e, 0x00, 0x61, 0x00, 0x6e, 0x00,
   0x64, 0x00, 0x72, 0x00, 0x6f, 0x00, 0x69, 0x00, 0x64, 0x00, 0x2e, 0x00,
   0x74, 0x00, 0x65, 0x00, 0x73, 0x00, 0x74, 0x00, 0x2e, 0x00, 0x62, 0x00,
@@ -50,19 +50,20 @@
   0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x02, 0x02, 0x10, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
   0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x44, 0x00, 0x60, 0x00, 0x00, 0x00,
-  0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00,
-  0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x4c, 0x00, 0x68, 0x00, 0x00, 0x00,
+  0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00,
+  0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x40, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
-  0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x03,
-  0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00, 0x18, 0x00, 0x00, 0x00,
-  0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00, 0x18, 0x00, 0x00, 0x00,
-  0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00, 0x14, 0x00, 0x00, 0x00,
-  0x06, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00,
+  0x02, 0x02, 0x10, 0x00, 0x18, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+  0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x02, 0x02, 0x10, 0x00, 0x18, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
+  0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x02, 0x02, 0x10, 0x00, 0x14, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
 };
-unsigned int split_xhdpi_v4_arsc_len = 780;
+unsigned int split_xhdpi_v4_arsc_len = 788;
diff --git a/libs/androidfw/tests/data/basic/split_xxhdpi_v4_arsc.h b/libs/androidfw/tests/data/basic/split_xxhdpi_v4_arsc.h
index f805db1..2f3f682 100644
--- a/libs/androidfw/tests/data/basic/split_xxhdpi_v4_arsc.h
+++ b/libs/androidfw/tests/data/basic/split_xxhdpi_v4_arsc.h
@@ -1,10 +1,10 @@
 unsigned char split_xxhdpi_v4_arsc[] = {
-  0x02, 0x00, 0x0c, 0x00, 0x0c, 0x03, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0x02, 0x00, 0x0c, 0x00, 0x14, 0x03, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
   0x01, 0x00, 0x1c, 0x00, 0x30, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x78, 0x00,
   0x78, 0x00, 0x68, 0x00, 0x64, 0x00, 0x70, 0x00, 0x69, 0x00, 0x00, 0x00,
-  0x00, 0x02, 0x20, 0x01, 0xd0, 0x02, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00,
+  0x00, 0x02, 0x20, 0x01, 0xd8, 0x02, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00,
   0x63, 0x00, 0x6f, 0x00, 0x6d, 0x00, 0x2e, 0x00, 0x61, 0x00, 0x6e, 0x00,
   0x64, 0x00, 0x72, 0x00, 0x6f, 0x00, 0x69, 0x00, 0x64, 0x00, 0x2e, 0x00,
   0x74, 0x00, 0x65, 0x00, 0x73, 0x00, 0x74, 0x00, 0x2e, 0x00, 0x62, 0x00,
@@ -50,19 +50,20 @@
   0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x02, 0x02, 0x10, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
   0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x44, 0x00, 0x60, 0x00, 0x00, 0x00,
-  0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00,
-  0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x4c, 0x00, 0x68, 0x00, 0x00, 0x00,
+  0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00,
+  0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
-  0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x03,
-  0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00, 0x18, 0x00, 0x00, 0x00,
-  0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00, 0x18, 0x00, 0x00, 0x00,
-  0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00, 0x14, 0x00, 0x00, 0x00,
-  0x06, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00,
+  0x02, 0x02, 0x10, 0x00, 0x18, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+  0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x02, 0x02, 0x10, 0x00, 0x18, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
+  0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x02, 0x02, 0x10, 0x00, 0x14, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
 };
-unsigned int split_xxhdpi_v4_arsc_len = 780;
+unsigned int split_xxhdpi_v4_arsc_len = 788;
diff --git a/libs/hwui/Android.mk b/libs/hwui/Android.mk
index 8831baf..936c7e8 100644
--- a/libs/hwui/Android.mk
+++ b/libs/hwui/Android.mk
@@ -2,7 +2,7 @@
 include $(CLEAR_VARS)
 LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
 
-HWUI_NEW_OPS := false
+HWUI_NEW_OPS := true
 
 # Enables fine-grained GLES error checking
 # If set to true, every GLES call is wrapped & error checked
@@ -227,21 +227,23 @@
 LOCAL_MODULE := hwui_unit_tests
 LOCAL_MODULE_TAGS := tests
 LOCAL_STATIC_LIBRARIES := libhwui_static_null_gpu
+LOCAL_SHARED_LIBRARIES := libmemunreachable
 LOCAL_CFLAGS := \
         $(hwui_cflags) \
         -DHWUI_NULL_GPU
 
 LOCAL_SRC_FILES += \
     $(hwui_test_common_src_files) \
+    tests/unit/main.cpp \
     tests/unit/CanvasStateTests.cpp \
     tests/unit/ClipAreaTests.cpp \
-    tests/unit/CrashHandlerInjector.cpp \
     tests/unit/DamageAccumulatorTests.cpp \
     tests/unit/DeviceInfoTests.cpp \
     tests/unit/FatVectorTests.cpp \
     tests/unit/GpuMemoryTrackerTests.cpp \
     tests/unit/LayerUpdateQueueTests.cpp \
     tests/unit/LinearAllocatorTests.cpp \
+    tests/unit/MatrixTests.cpp \
     tests/unit/OffscreenBufferPoolTests.cpp \
     tests/unit/SkiaBehaviorTests.cpp \
     tests/unit/StringUtilsTests.cpp \
@@ -251,6 +253,7 @@
 
 ifeq (true, $(HWUI_NEW_OPS))
     LOCAL_SRC_FILES += \
+        tests/unit/BakedOpDispatcherTests.cpp \
         tests/unit/BakedOpStateTests.cpp \
         tests/unit/FrameBuilderTests.cpp \
         tests/unit/LeakCheckTests.cpp \
@@ -302,13 +305,13 @@
 LOCAL_CFLAGS := \
         $(hwui_cflags) \
         -DHWUI_NULL_GPU
-LOCAL_C_INCLUDES += bionic/benchmarks/
 
 LOCAL_WHOLE_STATIC_LIBRARIES := libhwui_static_null_gpu
-LOCAL_STATIC_LIBRARIES := libbenchmark libbase
+LOCAL_STATIC_LIBRARIES := libgoogle-benchmark
 
 LOCAL_SRC_FILES += \
     $(hwui_test_common_src_files) \
+    tests/microbench/main.cpp \
     tests/microbench/DisplayListCanvasBench.cpp \
     tests/microbench/LinearAllocatorBench.cpp \
     tests/microbench/PathParserBench.cpp \
diff --git a/libs/hwui/AnimatorManager.cpp b/libs/hwui/AnimatorManager.cpp
index 2198fcc..f170e9c 100644
--- a/libs/hwui/AnimatorManager.cpp
+++ b/libs/hwui/AnimatorManager.cpp
@@ -95,11 +95,11 @@
 
 class AnimateFunctor {
 public:
-    AnimateFunctor(TreeInfo& info, AnimationContext& context)
-            : dirtyMask(0), mInfo(info), mContext(context) {}
+    AnimateFunctor(TreeInfo& info, AnimationContext& context, uint32_t* outDirtyMask)
+            : mInfo(info), mContext(context), mDirtyMask(outDirtyMask) {}
 
     bool operator() (sp<BaseRenderNodeAnimator>& animator) {
-        dirtyMask |= animator->dirtyMask();
+        *mDirtyMask |= animator->dirtyMask();
         bool remove = animator->animate(mContext);
         if (remove) {
             animator->detach();
@@ -114,11 +114,10 @@
         return remove;
     }
 
-    uint32_t dirtyMask;
-
 private:
     TreeInfo& mInfo;
     AnimationContext& mContext;
+    uint32_t* mDirtyMask;
 };
 
 uint32_t AnimatorManager::animate(TreeInfo& info) {
@@ -143,12 +142,13 @@
 }
 
 uint32_t AnimatorManager::animateCommon(TreeInfo& info) {
-    AnimateFunctor functor(info, mAnimationHandle->context());
+    uint32_t dirtyMask;
+    AnimateFunctor functor(info, mAnimationHandle->context(), &dirtyMask);
     auto newEnd = std::remove_if(mAnimators.begin(), mAnimators.end(), functor);
     mAnimators.erase(newEnd, mAnimators.end());
     mAnimationHandle->notifyAnimationsRan();
     mParent.mProperties.updateMatrix();
-    return functor.dirtyMask;
+    return dirtyMask;
 }
 
 static void endStagingAnimator(sp<BaseRenderNodeAnimator>& animator) {
diff --git a/libs/hwui/BakedOpDispatcher.cpp b/libs/hwui/BakedOpDispatcher.cpp
index 78764b5..06b712e 100644
--- a/libs/hwui/BakedOpDispatcher.cpp
+++ b/libs/hwui/BakedOpDispatcher.cpp
@@ -30,6 +30,7 @@
 #include <algorithm>
 #include <math.h>
 #include <SkPaintDefaults.h>
+#include <SkPathOps.h>
 
 namespace android {
 namespace uirenderer {
@@ -60,7 +61,10 @@
     for (size_t i = 0; i < opList.count; i++) {
         const BakedOpState& state = *(opList.states[i]);
         TextureVertex* rectVerts = &vertices[i * 4];
-        Rect opBounds = state.computedState.clippedBounds;
+
+        // calculate unclipped bounds, since they'll determine texture coordinates
+        Rect opBounds = state.op->unmappedBounds;
+        state.computedState.transform.mapRect(opBounds);
         if (CC_LIKELY(state.computedState.transform.isPureTranslate())) {
             // pure translate, so snap (same behavior as onBitmapOp)
             opBounds.snapToPixelBoundaries();
@@ -368,7 +372,7 @@
                 op.startAngle, op.sweepAngle, op.useCenter, op.paint);
         const AutoTexture holder(texture);
         if (CC_LIKELY(holder.texture)) {
-            renderPathTexture(renderer, state, op.unmappedBounds.left, op.unmappedBounds.right,
+            renderPathTexture(renderer, state, op.unmappedBounds.left, op.unmappedBounds.top,
                     *texture, *(op.paint));
         }
     } else {
@@ -527,6 +531,12 @@
         SkPath path;
         SkRect rect = getBoundsOfFill(op);
         path.addOval(rect);
+
+        if (state.computedState.localProjectionPathMask != nullptr) {
+            // Mask the ripple path by the local space projection mask in local space.
+            // Note that this can create CCW paths.
+            Op(path, *state.computedState.localProjectionPathMask, kIntersect_SkPathOp, &path);
+        }
         renderConvexPath(renderer, state, path, *(op.paint));
     }
 }
diff --git a/libs/hwui/BakedOpRenderer.cpp b/libs/hwui/BakedOpRenderer.cpp
index 5f689b4..da5ecca 100644
--- a/libs/hwui/BakedOpRenderer.cpp
+++ b/libs/hwui/BakedOpRenderer.cpp
@@ -135,17 +135,7 @@
         mRenderState.stencil().disable();
     }
 
-    mCaches.clearGarbage();
-    mCaches.pathCache.trim();
-    mCaches.tessellationCache.trim();
-
-#if DEBUG_MEMORY_USAGE
-    mCaches.dumpMemoryUsage();
-#else
-    if (Properties::debugLevel & kDebugMemory) {
-        mCaches.dumpMemoryUsage();
-    }
-#endif
+    // Note: we leave FBO 0 renderable here, for post-frame-content decoration
 }
 
 void BakedOpRenderer::setViewport(uint32_t width, uint32_t height) {
@@ -179,6 +169,38 @@
     return texture;
 }
 
+void BakedOpRenderer::drawRects(const float* rects, int count, const SkPaint* paint) {
+    std::vector<Vertex> vertices;
+    vertices.reserve(count);
+    Vertex* vertex = vertices.data();
+
+    for (int index = 0; index < count; index += 4) {
+        float l = rects[index + 0];
+        float t = rects[index + 1];
+        float r = rects[index + 2];
+        float b = rects[index + 3];
+
+        Vertex::set(vertex++, l, t);
+        Vertex::set(vertex++, r, t);
+        Vertex::set(vertex++, l, b);
+        Vertex::set(vertex++, r, b);
+    }
+
+    LOG_ALWAYS_FATAL_IF(mRenderTarget.frameBufferId != 0, "decoration only supported for FBO 0");
+    // TODO: Currently assume full FBO damage, due to FrameInfoVisualizer::unionDirty.
+    // Should should scissor safely.
+    mRenderState.scissor().setEnabled(false);
+    Glop glop;
+    GlopBuilder(mRenderState, mCaches, &glop)
+            .setRoundRectClipState(nullptr)
+            .setMeshIndexedQuads(vertices.data(), count / 4)
+            .setFillPaint(*paint, 1.0f)
+            .setTransform(Matrix4::identity(), TransformFlags::None)
+            .setModelViewIdentityEmptyBounds()
+            .build();
+    mRenderState.render(glop, mRenderTarget.orthoMatrix);
+}
+
 // clears and re-fills stencil with provided rendertarget space quads,
 // and then put stencil into test mode
 void BakedOpRenderer::setupStencilQuads(std::vector<Vertex>& quadVertices,
@@ -296,16 +318,13 @@
         }
     }
 
-    // dirty offscreenbuffer
-    if (dirtyBounds && mRenderTarget.offscreenBuffer) {
-        // register layer damage to draw-back region
-        android::Rect dirty(dirtyBounds->left, dirtyBounds->top,
-                dirtyBounds->right, dirtyBounds->bottom);
-        mRenderTarget.offscreenBuffer->region.orSelf(dirty);
+    if (dirtyBounds) {
+        // dirty offscreenbuffer if present
+        dirtyRenderTarget(*dirtyBounds);
     }
 }
 
-void BakedOpRenderer::renderGlop(const Rect* dirtyBounds, const ClipBase* clip,
+void BakedOpRenderer::renderGlopImpl(const Rect* dirtyBounds, const ClipBase* clip,
         const Glop& glop) {
     prepareRender(dirtyBounds, clip);
     mRenderState.render(glop, mRenderTarget.orthoMatrix);
@@ -329,29 +348,9 @@
     mRenderState.invokeFunctor(op.functor, DrawGlInfo::kModeDraw, &info);
 }
 
-#define VALIDATE_RECT_ARG(rect, arg) \
-        ((isnanf(rect.arg) || rect.arg < -10000 || rect.arg > 10000) ? (\
-            ALOGW("suspicious " #rect "." #arg "! %f", rect.arg),\
-            false) : true)
-
-#define VALIDATE_RECT(rect) \
-    VALIDATE_RECT_ARG(rect, bottom) & \
-    VALIDATE_RECT_ARG(rect, left) & \
-    VALIDATE_RECT_ARG(rect, top) & \
-    VALIDATE_RECT_ARG(rect, right)
-
 void BakedOpRenderer::dirtyRenderTarget(const Rect& uiDirty) {
     if (mRenderTarget.offscreenBuffer) {
-        bool valid = VALIDATE_RECT(uiDirty);
-        android::Rect dirty;
-        if (valid) {
-            dirty = android::Rect(uiDirty.left, uiDirty.top, uiDirty.right, uiDirty.bottom);
-        } else {
-            dirty = android::Rect(
-                    mRenderTarget.offscreenBuffer->viewportWidth,
-                    mRenderTarget.offscreenBuffer->viewportHeight);
-        }
-        mRenderTarget.offscreenBuffer->region.orSelf(dirty);
+        mRenderTarget.offscreenBuffer->dirty(uiDirty);
     }
 }
 
diff --git a/libs/hwui/BakedOpRenderer.h b/libs/hwui/BakedOpRenderer.h
index 55ea935..1b4065a 100644
--- a/libs/hwui/BakedOpRenderer.h
+++ b/libs/hwui/BakedOpRenderer.h
@@ -14,8 +14,7 @@
  * limitations under the License.
  */
 
-#ifndef ANDROID_HWUI_BAKED_OP_RENDERER_H
-#define ANDROID_HWUI_BAKED_OP_RENDERER_H
+#pragma once
 
 #include "BakedOpState.h"
 #include "Matrix.h"
@@ -41,6 +40,7 @@
  */
 class BakedOpRenderer {
 public:
+    typedef void (*GlopReceiver)(BakedOpRenderer&, const Rect*, const ClipBase*, const Glop&);
     /**
      * Position agnostic shadow lighting info. Used with all shadow ops in scene.
      */
@@ -54,8 +54,10 @@
         uint8_t spotShadowAlpha;
     };
 
-    BakedOpRenderer(Caches& caches, RenderState& renderState, bool opaque, const LightInfo& lightInfo)
-            : mRenderState(renderState)
+    BakedOpRenderer(Caches& caches, RenderState& renderState, bool opaque,
+            const LightInfo& lightInfo)
+            : mGlopReceiver(DefaultGlopReceiver)
+            , mRenderState(renderState)
             , mCaches(caches)
             , mOpaque(opaque)
             , mLightInfo(lightInfo) {
@@ -81,11 +83,30 @@
     }
     void renderFunctor(const FunctorOp& op, const BakedOpState& state);
 
-    void renderGlop(const Rect* dirtyBounds, const ClipBase* clip, const Glop& glop);
+    void renderGlop(const Rect* dirtyBounds, const ClipBase* clip, const Glop& glop) {
+        mGlopReceiver(*this, dirtyBounds, clip, glop);
+    }
     bool offscreenRenderTarget() { return mRenderTarget.offscreenBuffer != nullptr; }
     void dirtyRenderTarget(const Rect& dirtyRect);
     bool didDraw() const { return mHasDrawn; }
+
+    uint32_t getViewportWidth() const { return mRenderTarget.viewportWidth; }
+    uint32_t getViewportHeight() const { return mRenderTarget.viewportHeight; }
+
+    // simple draw methods, to be used for end frame decoration
+    void drawRect(float left, float top, float right, float bottom, const SkPaint* paint) {
+        float ltrb[4] = { left, top, right, bottom };
+        drawRects(ltrb, 4, paint);
+    }
+    void drawRects(const float* rects, int count, const SkPaint* paint);
+protected:
+    GlopReceiver mGlopReceiver;
 private:
+    static void DefaultGlopReceiver(BakedOpRenderer& renderer, const Rect* dirtyBounds,
+            const ClipBase* clip, const Glop& glop) {
+        renderer.renderGlopImpl(dirtyBounds, clip, glop);
+    }
+    void renderGlopImpl(const Rect* dirtyBounds, const ClipBase* clip, const Glop& glop);
     void setViewport(uint32_t width, uint32_t height);
     void clearColorBuffer(const Rect& clearRect);
     void prepareRender(const Rect* dirtyBounds, const ClipBase* clip);
@@ -126,5 +147,3 @@
 
 }; // namespace uirenderer
 }; // namespace android
-
-#endif // ANDROID_HWUI_BAKED_OP_RENDERER_H
diff --git a/libs/hwui/BakedOpState.cpp b/libs/hwui/BakedOpState.cpp
index 682bd04..26653f7 100644
--- a/libs/hwui/BakedOpState.cpp
+++ b/libs/hwui/BakedOpState.cpp
@@ -63,9 +63,22 @@
         clipState = nullptr;
         clippedBounds.setEmpty();
     } else {
-        // Not rejected! compute true clippedBounds and clipSideFlags
+        // Not rejected! compute true clippedBounds, clipSideFlags, and path mask
         clipSideFlags = computeClipSideFlags(clipRect, clippedBounds);
         clippedBounds.doIntersect(clipRect);
+
+        if (CC_UNLIKELY(snapshot.projectionPathMask)) {
+            // map projection path mask from render target space into op space,
+            // so intersection with op geometry is possible
+            Matrix4 inverseTransform;
+            inverseTransform.loadInverse(transform);
+            SkMatrix skInverseTransform;
+            inverseTransform.copyTo(skInverseTransform);
+
+            auto localMask = allocator.create<SkPath>();
+            snapshot.projectionPathMask->transform(skInverseTransform, localMask);
+            localProjectionPathMask = localMask;
+        }
     }
 }
 
@@ -73,13 +86,15 @@
         : transform(*snapshot.transform)
         , clipState(snapshot.mutateClipArea().serializeClip(allocator))
         , clippedBounds(clipState->rect)
-        , clipSideFlags(OpClipSideFlags::Full) {}
+        , clipSideFlags(OpClipSideFlags::Full)
+        , localProjectionPathMask(nullptr) {}
 
 ResolvedRenderState::ResolvedRenderState(const ClipRect* clipRect, const Rect& dstRect)
         : transform(Matrix4::identity())
         , clipState(clipRect)
         , clippedBounds(dstRect)
-        , clipSideFlags(computeClipSideFlags(clipRect->rect, dstRect)) {
+        , clipSideFlags(computeClipSideFlags(clipRect->rect, dstRect))
+        , localProjectionPathMask(nullptr) {
     clippedBounds.doIntersect(clipRect->rect);
 }
 
diff --git a/libs/hwui/BakedOpState.h b/libs/hwui/BakedOpState.h
index 4365ef8..ffe2901 100644
--- a/libs/hwui/BakedOpState.h
+++ b/libs/hwui/BakedOpState.h
@@ -88,6 +88,7 @@
     const ClipBase* clipState = nullptr;
     Rect clippedBounds;
     int clipSideFlags = 0;
+    const SkPath* localProjectionPathMask = nullptr;
 };
 
 /**
@@ -154,7 +155,6 @@
     // simple state (straight pointer/value storage):
     const float alpha;
     const RoundRectClipState* roundRectClipState;
-    const ProjectionPathMask* projectionPathMask;
     const RecordedOp* op;
 
 private:
@@ -165,21 +165,18 @@
             : computedState(allocator, snapshot, recordedOp, expandForStroke)
             , alpha(snapshot.alpha)
             , roundRectClipState(snapshot.roundRectClipState)
-            , projectionPathMask(snapshot.projectionPathMask)
             , op(&recordedOp) {}
 
     BakedOpState(LinearAllocator& allocator, Snapshot& snapshot, const ShadowOp* shadowOpPtr)
             : computedState(allocator, snapshot)
             , alpha(snapshot.alpha)
             , roundRectClipState(snapshot.roundRectClipState)
-            , projectionPathMask(snapshot.projectionPathMask)
             , op(shadowOpPtr) {}
 
     BakedOpState(const ClipRect* clipRect, const Rect& dstRect, const RecordedOp& recordedOp)
             : computedState(clipRect, dstRect)
             , alpha(1.0f)
             , roundRectClipState(nullptr)
-            , projectionPathMask(nullptr)
             , op(&recordedOp) {}
 };
 
diff --git a/libs/hwui/ClipArea.cpp b/libs/hwui/ClipArea.cpp
index e368537..afe9807 100644
--- a/libs/hwui/ClipArea.cpp
+++ b/libs/hwui/ClipArea.cpp
@@ -375,15 +375,13 @@
             serialization->rect.set(mClipRegion.getBounds());
             break;
         }
+        // TODO: this is only done for draw time, should eventually avoid for record time
+        serialization->rect.snapToPixelBoundaries();
         mLastSerialization = serialization;
     }
     return mLastSerialization;
 }
 
-inline static const Rect& getRect(const ClipBase* scb) {
-    return reinterpret_cast<const ClipRect*>(scb)->rect;
-}
-
 inline static const RectangleList& getRectList(const ClipBase* scb) {
     return reinterpret_cast<const ClipRectList*>(scb)->rectList;
 }
@@ -404,11 +402,17 @@
     return currentRectCount + recordedRectCount > RectangleList::kMaxTransformedRectangles;
 }
 
+static const ClipRect sEmptyClipRect(Rect(0, 0));
+
 const ClipBase* ClipArea::serializeIntersectedClip(LinearAllocator& allocator,
         const ClipBase* recordedClip, const Matrix4& recordedClipTransform) {
+
     // if no recordedClip passed, just serialize current state
     if (!recordedClip) return serializeClip(allocator);
 
+    // if either is empty, clip is empty
+    if (CC_UNLIKELY(recordedClip->rect.isEmpty())|| mClipRect.isEmpty()) return &sEmptyClipRect;
+
     if (!mLastResolutionResult
             || recordedClip != mLastResolutionClip
             || recordedClipTransform != mLastResolutionTransform) {
@@ -419,9 +423,10 @@
                 && recordedClip->mode == ClipMode::Rectangle
                 && recordedClipTransform.rectToRect())) {
             // common case - result is a single rectangle
-            auto rectClip = allocator.create<ClipRect>(getRect(recordedClip));
+            auto rectClip = allocator.create<ClipRect>(recordedClip->rect);
             recordedClipTransform.mapRect(rectClip->rect);
             rectClip->rect.doIntersect(mClipRect);
+            rectClip->rect.snapToPixelBoundaries();
             mLastResolutionResult = rectClip;
         } else if (CC_UNLIKELY(mMode == ClipMode::Region
                 || recordedClip->mode == ClipMode::Region
@@ -432,11 +437,11 @@
             case ClipMode::Rectangle:
                 if (CC_LIKELY(recordedClipTransform.rectToRect())) {
                     // simple transform, skip creating SkPath
-                    Rect resultClip(getRect(recordedClip));
+                    Rect resultClip(recordedClip->rect);
                     recordedClipTransform.mapRect(resultClip);
                     other.setRect(resultClip.toSkIRect());
                 } else {
-                    SkPath transformedRect = pathFromTransformedRectangle(getRect(recordedClip),
+                    SkPath transformedRect = pathFromTransformedRectangle(recordedClip->rect,
                             recordedClipTransform);
                     other.setPath(transformedRect, createViewportRegion());
                 }
@@ -468,6 +473,7 @@
                 regionClip->region.op(mClipRegion, other, SkRegion::kIntersect_Op);
                 break;
             }
+            // Don't need to snap, since region's in int bounds
             regionClip->rect.set(regionClip->region.getBounds());
             mLastResolutionResult = regionClip;
         } else {
@@ -478,7 +484,7 @@
             }
 
             if (recordedClip->mode == ClipMode::Rectangle) {
-                rectList.intersectWith(getRect(recordedClip), recordedClipTransform);
+                rectList.intersectWith(recordedClip->rect, recordedClipTransform);
             } else {
                 const RectangleList& other = getRectList(recordedClip);
                 for (int i = 0; i < other.getTransformedRectanglesCount(); i++) {
@@ -489,6 +495,7 @@
                 }
             }
             rectListClip->rect = rectList.calculateBounds();
+            rectListClip->rect.snapToPixelBoundaries();
             mLastResolutionResult = rectListClip;
         }
     }
@@ -499,7 +506,7 @@
     if (!clip) return; // nothing to do
 
     if (CC_LIKELY(clip->mode == ClipMode::Rectangle)) {
-        clipRectWithTransform(getRect(clip), &transform, SkRegion::kIntersect_Op);
+        clipRectWithTransform(clip->rect, &transform, SkRegion::kIntersect_Op);
     } else if (CC_LIKELY(clip->mode == ClipMode::RectangleList)) {
         auto&& rectList = getRectList(clip);
         for (int i = 0; i < rectList.getTransformedRectanglesCount(); i++) {
diff --git a/libs/hwui/DisplayListCanvas.cpp b/libs/hwui/DisplayListCanvas.cpp
index 00560d7..a14bdc4 100644
--- a/libs/hwui/DisplayListCanvas.cpp
+++ b/libs/hwui/DisplayListCanvas.cpp
@@ -415,12 +415,7 @@
 
 void DisplayListCanvas::drawVectorDrawable(VectorDrawableRoot* tree) {
     mDisplayList->ref(tree);
-    const SkBitmap& bitmap = tree->getBitmapUpdateIfDirty();
-    SkPaint* paint = tree->getPaint();
-    const SkRect bounds = tree->getBounds();
-    addDrawOp(new (alloc()) DrawBitmapRectOp(refBitmap(bitmap),
-            0, 0, bitmap.width(), bitmap.height(),
-            bounds.left(), bounds.top(), bounds.right(), bounds.bottom(), refPaint(paint)));
+    addDrawOp(new (alloc()) DrawVectorDrawableOp(tree));
 }
 
 void DisplayListCanvas::drawTextOnPath(const uint16_t* glyphs, int count,
diff --git a/libs/hwui/DisplayListOp.h b/libs/hwui/DisplayListOp.h
index 98315d0..516e619 100644
--- a/libs/hwui/DisplayListOp.h
+++ b/libs/hwui/DisplayListOp.h
@@ -28,6 +28,7 @@
 #include "UvMapper.h"
 #include "utils/LinearAllocator.h"
 #include "utils/PaintUtils.h"
+#include "VectorDrawable.h"
 
 #include <algorithm>
 
@@ -1107,6 +1108,30 @@
     float* mRadius;
 };
 
+class DrawVectorDrawableOp : public DrawOp {
+public:
+    DrawVectorDrawableOp(VectorDrawableRoot* tree)
+            : DrawOp(nullptr), mTree(tree) {}
+
+    virtual void applyDraw(OpenGLRenderer& renderer, Rect& dirty) override {
+        const SkBitmap& bitmap = mTree->getBitmapUpdateIfDirty();
+        SkPaint* paint = mTree->getPaint();
+        const SkRect bounds = mTree->getBounds();
+        renderer.drawBitmap(&bitmap, Rect(0, 0, bitmap.width(), bitmap.height()),
+                bounds, paint);
+    }
+
+    virtual void output(int level, uint32_t logFlags) const override {
+        OP_LOG("Draw Vector Drawable %p", mTree);
+    }
+
+    virtual const char* name() override { return "DrawVectorDrawable"; }
+
+private:
+    VectorDrawableRoot* mTree;
+
+};
+
 class DrawOvalOp : public DrawStrokableOp {
 public:
     DrawOvalOp(float left, float top, float right, float bottom, const SkPaint* paint)
diff --git a/libs/hwui/FrameBuilder.cpp b/libs/hwui/FrameBuilder.cpp
index 04de98a..fd5856a 100644
--- a/libs/hwui/FrameBuilder.cpp
+++ b/libs/hwui/FrameBuilder.cpp
@@ -203,8 +203,9 @@
         mCanvasState.setClippingOutline(mAllocator, &(properties.getOutline()));
     }
 
-    bool quickRejected = properties.getClipToBounds()
-            && mCanvasState.quickRejectConservative(0, 0, width, height);
+    bool quickRejected = mCanvasState.currentSnapshot()->getRenderTargetClip().isEmpty()
+            || (properties.getClipToBounds()
+                    && mCanvasState.quickRejectConservative(0, 0, width, height));
     if (!quickRejected) {
         // not rejected, so defer render as either Layer, or direct (possibly wrapped in saveLayer)
         if (node.getLayer()) {
@@ -389,34 +390,38 @@
 }
 
 void FrameBuilder::deferProjectedChildren(const RenderNode& renderNode) {
-    const SkPath* projectionReceiverOutline = renderNode.properties().getOutline().getPath();
     int count = mCanvasState.save(SaveFlags::MatrixClip);
+    const SkPath* projectionReceiverOutline = renderNode.properties().getOutline().getPath();
 
-    // can't be null, since DL=null node rejection happens before deferNodePropsAndOps
-    const DisplayList& displayList = *(renderNode.getDisplayList());
-
-    const RecordedOp* op = (displayList.getOps()[displayList.projectionReceiveIndex]);
-    const RenderNodeOp* backgroundOp = static_cast<const RenderNodeOp*>(op);
-    const RenderProperties& backgroundProps = backgroundOp->renderNode->properties();
-
-    // Transform renderer to match background we're projecting onto
-    // (by offsetting canvas by translationX/Y of background rendernode, since only those are set)
-    mCanvasState.translate(backgroundProps.getTranslationX(), backgroundProps.getTranslationY());
-
-    // If the projection receiver has an outline, we mask projected content to it
-    // (which we know, apriori, are all tessellated paths)
-    mCanvasState.setProjectionPathMask(mAllocator, projectionReceiverOutline);
-
-    // draw projected nodes
-    for (size_t i = 0; i < renderNode.mProjectedNodes.size(); i++) {
-        RenderNodeOp* childOp = renderNode.mProjectedNodes[i];
-
-        int restoreTo = mCanvasState.save(SaveFlags::Matrix);
-        mCanvasState.concatMatrix(childOp->transformFromCompositingAncestor);
-        deferRenderNodeOpImpl(*childOp);
-        mCanvasState.restoreToCount(restoreTo);
+    SkPath transformedMaskPath; // on stack, since BakedOpState makes a deep copy
+    if (projectionReceiverOutline) {
+        // transform the mask for this projector into render target space
+        // TODO: consider combining both transforms by stashing transform instead of applying
+        SkMatrix skCurrentTransform;
+        mCanvasState.currentTransform()->copyTo(skCurrentTransform);
+        projectionReceiverOutline->transform(
+                skCurrentTransform,
+                &transformedMaskPath);
+        mCanvasState.setProjectionPathMask(mAllocator, &transformedMaskPath);
     }
 
+    for (size_t i = 0; i < renderNode.mProjectedNodes.size(); i++) {
+        RenderNodeOp* childOp = renderNode.mProjectedNodes[i];
+        RenderNode& childNode = *childOp->renderNode;
+
+        // Draw child if it has content, but ignore state in childOp - matrix already applied to
+        // transformFromCompositingAncestor, and record-time clip is ignored when projecting
+        if (!childNode.nothingToDraw()) {
+            int restoreTo = mCanvasState.save(SaveFlags::MatrixClip);
+
+            // Apply transform between ancestor and projected descendant
+            mCanvasState.concatMatrix(childOp->transformFromCompositingAncestor);
+
+            deferNodePropsAndOps(childNode);
+
+            mCanvasState.restoreToCount(restoreTo);
+        }
+    }
     mCanvasState.restoreToCount(count);
 }
 
@@ -513,10 +518,6 @@
     BakedOpState* bakedState = tryBakeOpState(op);
     if (!bakedState) return; // quick rejected
 
-    currentLayer().deferUnmergeableOp(mAllocator, bakedState, OpBatchType::Bitmap);
-
-    // TODO: Fix this ( b/26569206 )
-/*
     // Don't merge non-simply transformed or neg scale ops, SET_TEXTURE doesn't handle rotation
     // Don't merge A8 bitmaps - the paint's color isn't compared by mergeId, or in
     // MergingDrawBatch::canMergeWith()
@@ -531,7 +532,6 @@
     } else {
         currentLayer().deferUnmergeableOp(mAllocator, bakedState, OpBatchType::Bitmap);
     }
-*/
 }
 
 void FrameBuilder::deferBitmapMeshOp(const BitmapMeshOp& op) {
diff --git a/libs/hwui/FrameInfoVisualizer.cpp b/libs/hwui/FrameInfoVisualizer.cpp
index b7dd3b7..adadd32 100644
--- a/libs/hwui/FrameInfoVisualizer.cpp
+++ b/libs/hwui/FrameInfoVisualizer.cpp
@@ -15,7 +15,11 @@
  */
 #include "FrameInfoVisualizer.h"
 
+#if HWUI_NEW_OPS
+#include "BakedOpRenderer.h"
+#else
 #include "OpenGLRenderer.h"
+#endif
 #include "utils/Color.h"
 
 #include <cutils/compiler.h>
@@ -88,7 +92,7 @@
     }
 }
 
-void FrameInfoVisualizer::draw(OpenGLRenderer* canvas) {
+void FrameInfoVisualizer::draw(ContentRenderer* renderer) {
     RETURN_IF_DISABLED();
 
     if (mShowDirtyRegions) {
@@ -96,7 +100,7 @@
         if (mFlashToggle) {
             SkPaint paint;
             paint.setColor(0x7fff0000);
-            canvas->drawRect(mDirtyRegion.fLeft, mDirtyRegion.fTop,
+            renderer->drawRect(mDirtyRegion.fLeft, mDirtyRegion.fTop,
                     mDirtyRegion.fRight, mDirtyRegion.fBottom, &paint);
         }
     }
@@ -111,9 +115,9 @@
         info.markSwapBuffers();
         info.markFrameCompleted();
 
-        initializeRects(canvas->getViewportHeight(), canvas->getViewportWidth());
-        drawGraph(canvas);
-        drawThreshold(canvas);
+        initializeRects(renderer->getViewportHeight(), renderer->getViewportWidth());
+        drawGraph(renderer);
+        drawThreshold(renderer);
     }
 }
 
@@ -194,27 +198,26 @@
     }
 }
 
-void FrameInfoVisualizer::drawGraph(OpenGLRenderer* canvas) {
+void FrameInfoVisualizer::drawGraph(ContentRenderer* renderer) {
     SkPaint paint;
     for (size_t i = 0; i < Bar.size(); i++) {
         nextBarSegment(Bar[i].start, Bar[i].end);
         paint.setColor(Bar[i].color & BAR_FAST_MASK);
-        canvas->drawRects(mFastRects.get(), mNumFastRects * 4, &paint);
+        renderer->drawRects(mFastRects.get(), mNumFastRects * 4, &paint);
         paint.setColor(Bar[i].color & BAR_JANKY_MASK);
-        canvas->drawRects(mJankyRects.get(), mNumJankyRects * 4, &paint);
+        renderer->drawRects(mJankyRects.get(), mNumJankyRects * 4, &paint);
     }
 }
 
-void FrameInfoVisualizer::drawThreshold(OpenGLRenderer* canvas) {
+void FrameInfoVisualizer::drawThreshold(ContentRenderer* renderer) {
     SkPaint paint;
     paint.setColor(THRESHOLD_COLOR);
-    paint.setStrokeWidth(mThresholdStroke);
-
-    float pts[4];
-    pts[0] = 0.0f;
-    pts[1] = pts[3] = canvas->getViewportHeight() - (FRAME_THRESHOLD * mVerticalUnit);
-    pts[2] = canvas->getViewportWidth();
-    canvas->drawLines(pts, 4, &paint);
+    float yLocation = renderer->getViewportHeight() - (FRAME_THRESHOLD * mVerticalUnit);
+    renderer->drawRect(0.0f,
+            yLocation - mThresholdStroke/2,
+            renderer->getViewportWidth(),
+            yLocation + mThresholdStroke/2,
+            &paint);
 }
 
 bool FrameInfoVisualizer::consumeProperties() {
diff --git a/libs/hwui/FrameInfoVisualizer.h b/libs/hwui/FrameInfoVisualizer.h
index cf877c4..83adf19 100644
--- a/libs/hwui/FrameInfoVisualizer.h
+++ b/libs/hwui/FrameInfoVisualizer.h
@@ -28,7 +28,13 @@
 namespace android {
 namespace uirenderer {
 
+#if HWUI_NEW_OPS
+class BakedOpRenderer;
+typedef BakedOpRenderer ContentRenderer;
+#else
 class OpenGLRenderer;
+typedef OpenGLRenderer ContentRenderer;
+#endif
 
 // TODO: This is a bit awkward as it needs to match the thing in CanvasContext
 // A better abstraction here would be nice but iterators are painful
@@ -46,7 +52,7 @@
     void setDensity(float density);
 
     void unionDirty(SkRect* dirty);
-    void draw(OpenGLRenderer* canvas);
+    void draw(ContentRenderer* renderer);
 
     void dumpData(int fd);
 
@@ -56,8 +62,8 @@
 
     void initializeRects(const int baseline, const int width);
     void nextBarSegment(FrameInfoIndex start, FrameInfoIndex end);
-    void drawGraph(OpenGLRenderer* canvas);
-    void drawThreshold(OpenGLRenderer* canvas);
+    void drawGraph(ContentRenderer* renderer);
+    void drawThreshold(ContentRenderer* renderer);
 
     inline float durationMS(size_t index, FrameInfoIndex start, FrameInfoIndex end) {
         float duration = mFrameSource[index].duration(start, end) * 0.000001f;
diff --git a/libs/hwui/LayerBuilder.cpp b/libs/hwui/LayerBuilder.cpp
index bc39621..c5af279 100644
--- a/libs/hwui/LayerBuilder.cpp
+++ b/libs/hwui/LayerBuilder.cpp
@@ -140,7 +140,10 @@
         // Identical round rect clip state means both ops will clip in the same way, or not at all.
         // As the state objects are const, we can compare their pointers to determine mergeability
         if (lhs->roundRectClipState != rhs->roundRectClipState) return false;
-        if (lhs->projectionPathMask != rhs->projectionPathMask) return false;
+
+        // Local masks prevent merge, since they're potentially in different coordinate spaces
+        if (lhs->computedState.localProjectionPathMask
+                || rhs->computedState.localProjectionPathMask) return false;
 
         /* Clipping compatibility check
          *
diff --git a/libs/hwui/LayerRenderer.cpp b/libs/hwui/LayerRenderer.cpp
index e04b9a2..5bce8ac 100644
--- a/libs/hwui/LayerRenderer.cpp
+++ b/libs/hwui/LayerRenderer.cpp
@@ -353,7 +353,7 @@
 
 bool LayerRenderer::copyLayer(RenderState& renderState, Layer* layer, SkBitmap* bitmap) {
     Caches& caches = Caches::getInstance();
-    if (layer
+    if (layer && layer->getRenderTarget() != GL_NONE
             && bitmap->width() <= caches.maxTextureSize
             && bitmap->height() <= caches.maxTextureSize) {
 
diff --git a/libs/hwui/Matrix.cpp b/libs/hwui/Matrix.cpp
index 73ebd1304..709156c 100644
--- a/libs/hwui/Matrix.cpp
+++ b/libs/hwui/Matrix.cpp
@@ -437,6 +437,14 @@
     y = dy * dz;
 }
 
+/**
+ * Set the contents of the rect to be the bounding rect around each of the corners, mapped by the
+ * matrix.
+ *
+ * NOTE: an empty rect to an arbitrary matrix isn't guaranteed to have an empty output, since that's
+ * important for conservative bounds estimation (e.g. rotate45Matrix.mapRect of Rect(0, 10) should
+ * result in non-empty.
+ */
 void Matrix4::mapRect(Rect& r) const {
     if (isIdentity()) return;
 
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index b7a5923..7693fdc 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -1148,7 +1148,9 @@
 
     // always store/restore, since these are just pointers
     state.mRoundRectClipState = currentSnapshot()->roundRectClipState;
+#if !HWUI_NEW_OPS
     state.mProjectionPathMask = currentSnapshot()->projectionPathMask;
+#endif
     return false;
 }
 
@@ -1156,7 +1158,9 @@
     setGlobalMatrix(state.mMatrix);
     writableSnapshot()->alpha = state.mAlpha;
     writableSnapshot()->roundRectClipState = state.mRoundRectClipState;
+#if !HWUI_NEW_OPS
     writableSnapshot()->projectionPathMask = state.mProjectionPathMask;
+#endif
 
     if (state.mClipValid && !skipClipRestore) {
         writableSnapshot()->setClip(state.mClip.left, state.mClip.top,
@@ -1833,6 +1837,7 @@
         path.addCircle(x, y, radius);
     }
 
+#if !HWUI_NEW_OPS
     if (CC_UNLIKELY(currentSnapshot()->projectionPathMask != nullptr)) {
         // mask ripples with projection mask
         SkPath maskPath = *(currentSnapshot()->projectionPathMask->projectionMask);
@@ -1852,6 +1857,7 @@
         // in local space. Note that this can create CCW paths.
         Op(path, maskPath, kIntersect_SkPathOp, &path);
     }
+#endif
     drawConvexPath(path, p);
 }
 
diff --git a/libs/hwui/RecordingCanvas.cpp b/libs/hwui/RecordingCanvas.cpp
index 31de305..f0c79d7 100644
--- a/libs/hwui/RecordingCanvas.cpp
+++ b/libs/hwui/RecordingCanvas.cpp
@@ -24,6 +24,14 @@
 namespace android {
 namespace uirenderer {
 
+#define MIL_PIX 1000000
+static Rect sUnreasonablyLargeBounds(-MIL_PIX, -MIL_PIX, MIL_PIX, MIL_PIX);
+
+static const Rect& getConservativeOpBounds(const ClipBase* clip) {
+    // if op is clipped, that rect can be used, but otherwise just use a conservatively large rect
+    return clip ? clip->rect : sUnreasonablyLargeBounds;
+}
+
 RecordingCanvas::RecordingCanvas(size_t width, size_t height)
         : mState(*this)
         , mResourceCache(ResourceCache::getInstance()) {
@@ -242,10 +250,8 @@
 
 void RecordingCanvas::drawPaint(const SkPaint& paint) {
     const ClipBase* clip = getRecordedClip();
-    // if there's no current clip, draw a big rect and hope we cover the eventual clip bounds
-    Rect bounds = clip ? clip->rect : Rect(-10000, -10000, 10000, 10000);
     addOp(alloc().create_trivial<RectOp>(
-            bounds,
+            getConservativeOpBounds(clip),
             Matrix4::identity(),
             clip,
             refPaint(&paint)));
@@ -534,10 +540,11 @@
             float hOffset, float vOffset, const SkPaint& paint) {
     if (!glyphs || glyphCount <= 0 || PaintUtils::paintWillNotDrawText(paint)) return;
     glyphs = refBuffer<glyph_t>(glyphs, glyphCount);
+    auto clip = getRecordedClip();
     addOp(alloc().create_trivial<TextOnPathOp>(
-            mState.getLocalClipBounds(), // TODO: explicitly define bounds
+            getConservativeOpBounds(clip), // TODO: explicitly define bounds
             *(mState.currentSnapshot()->transform),
-            getRecordedClip(),
+            clip,
             refPaint(&paint), glyphs, glyphCount, refPath(&path), hOffset, vOffset));
 }
 
@@ -557,15 +564,17 @@
             getRecordedClip(),
             renderNode);
     int opIndex = addOp(op);
-    int childIndex = mDisplayList->addChild(op);
+    if (CC_LIKELY(opIndex >= 0)) {
+        int childIndex = mDisplayList->addChild(op);
 
-    // update the chunk's child indices
-    DisplayList::Chunk& chunk = mDisplayList->chunks.back();
-    chunk.endChildIndex = childIndex + 1;
+        // update the chunk's child indices
+        DisplayList::Chunk& chunk = mDisplayList->chunks.back();
+        chunk.endChildIndex = childIndex + 1;
 
-    if (renderNode->stagingProperties().isProjectionReceiver()) {
-        // use staging property, since recording on UI thread
-        mDisplayList->projectionReceiveIndex = opIndex;
+        if (renderNode->stagingProperties().isProjectionReceiver()) {
+            // use staging property, since recording on UI thread
+            mDisplayList->projectionReceiveIndex = opIndex;
+        }
     }
 }
 
@@ -586,15 +595,23 @@
 
 void RecordingCanvas::callDrawGLFunction(Functor* functor) {
     mDisplayList->functors.push_back(functor);
+    auto clip = getRecordedClip();
     addOp(alloc().create_trivial<FunctorOp>(
-            mState.getLocalClipBounds(), // TODO: explicitly define bounds
+            getConservativeOpBounds(clip),
             *(mState.currentSnapshot()->transform),
-            getRecordedClip(),
+            clip,
             functor));
 }
 
 size_t RecordingCanvas::addOp(RecordedOp* op) {
-    // TODO: validate if "addDrawOp" quickrejection logic is useful before adding
+    // skip op with empty clip
+    if (op->localClip && op->localClip->rect.isEmpty()) {
+        // NOTE: this rejection happens after op construction/content ref-ing, so content ref'd
+        // and held by renderthread isn't affected by clip rejection.
+        // Could rewind alloc here if desired, but callers would have to not touch op afterwards.
+        return -1;
+    }
+
     int insertIndex = mDisplayList->ops.size();
     mDisplayList->ops.push_back(op);
     if (mDeferredBarrierType != DeferredBarrierType::None) {
diff --git a/libs/hwui/Rect.h b/libs/hwui/Rect.h
index d9fce9b..de4fa55 100644
--- a/libs/hwui/Rect.h
+++ b/libs/hwui/Rect.h
@@ -286,7 +286,8 @@
 
     friend std::ostream& operator<<(std::ostream& os, const Rect& rect) {
         if (rect.isEmpty()) {
-            return os << "empty";
+            // Print empty, but continue, since empty rects may still have useful coordinate info
+            os << "(empty)";
         }
 
         if (rect.left == 0 && rect.top == 0) {
diff --git a/libs/hwui/Snapshot.cpp b/libs/hwui/Snapshot.cpp
index 27fea1f..cf5e69a 100644
--- a/libs/hwui/Snapshot.cpp
+++ b/libs/hwui/Snapshot.cpp
@@ -146,6 +146,9 @@
 }
 
 void Snapshot::buildScreenSpaceTransform(Matrix4* outTransform) const {
+#if HWUI_NEW_OPS
+    LOG_ALWAYS_FATAL("not supported - not needed by new ops");
+#else
     // build (reverse ordered) list of the stack of snapshots, terminated with a NULL
     Vector<const Snapshot*> snapshotList;
     snapshotList.push(nullptr);
@@ -171,6 +174,7 @@
             outTransform->multiply(*(current->transform));
         }
     }
+#endif
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -223,15 +227,19 @@
 }
 
 void Snapshot::setProjectionPathMask(LinearAllocator& allocator, const SkPath* path) {
+#if HWUI_NEW_OPS
+    // TODO: remove allocator param for HWUI_NEW_OPS
+    projectionPathMask = path;
+#else
     if (path) {
         ProjectionPathMask* mask = new (allocator) ProjectionPathMask;
         mask->projectionMask = path;
         buildScreenSpaceTransform(&(mask->projectionMaskTransform));
-
         projectionPathMask = mask;
     } else {
         projectionPathMask = nullptr;
     }
+#endif
 }
 
 ///////////////////////////////////////////////////////////////////////////////
diff --git a/libs/hwui/Snapshot.h b/libs/hwui/Snapshot.h
index b03643f..3a01d04 100644
--- a/libs/hwui/Snapshot.h
+++ b/libs/hwui/Snapshot.h
@@ -63,6 +63,7 @@
     float radius;
 };
 
+// TODO: remove for HWUI_NEW_OPS
 class ProjectionPathMask {
 public:
     static void* operator new(size_t size) = delete;
@@ -219,6 +220,7 @@
      * Fills outTransform with the current, total transform to screen space,
      * across layer boundaries.
      */
+    // TODO: remove for HWUI_NEW_OPS
     void buildScreenSpaceTransform(Matrix4* outTransform) const;
 
     /**
@@ -294,9 +296,13 @@
     const RoundRectClipState* roundRectClipState;
 
     /**
-     * Current projection masking path - used exclusively to mask tessellated circles.
+     * Current projection masking path - used exclusively to mask projected, tessellated circles.
      */
+#if HWUI_NEW_OPS
+    const SkPath* projectionPathMask;
+#else
     const ProjectionPathMask* projectionPathMask;
+#endif
 
     void dump() const;
 
diff --git a/libs/hwui/renderstate/OffscreenBufferPool.cpp b/libs/hwui/renderstate/OffscreenBufferPool.cpp
index 54f38e8..5f984b5 100644
--- a/libs/hwui/renderstate/OffscreenBufferPool.cpp
+++ b/libs/hwui/renderstate/OffscreenBufferPool.cpp
@@ -54,6 +54,14 @@
     return Rect(0, viewportHeight * texY, viewportWidth * texX, 0);
 }
 
+void OffscreenBuffer::dirty(Rect dirtyArea) {
+    dirtyArea.doIntersect(0, 0, viewportWidth, viewportHeight);
+    if (!dirtyArea.isEmpty()) {
+        region.orSelf(android::Rect(dirtyArea.left, dirtyArea.top,
+                dirtyArea.right, dirtyArea.bottom));
+    }
+}
+
 void OffscreenBuffer::updateMeshFromRegion() {
     // avoid T-junctions as they cause artifacts in between the resultant
     // geometry when complex transforms occur.
diff --git a/libs/hwui/renderstate/OffscreenBufferPool.h b/libs/hwui/renderstate/OffscreenBufferPool.h
index 94155ef..089f131 100644
--- a/libs/hwui/renderstate/OffscreenBufferPool.h
+++ b/libs/hwui/renderstate/OffscreenBufferPool.h
@@ -48,6 +48,8 @@
 
     Rect getTextureCoordinates();
 
+    void dirty(Rect dirtyArea);
+
     // must be called prior to rendering, to construct/update vertex buffer
     void updateMeshFromRegion();
 
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index 4f528b1..a496b49 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -348,12 +348,26 @@
     FrameBuilder frameBuilder(mLayerUpdateQueue, dirty, frame.width(), frame.height(),
             mRenderNodes, mLightGeometry, mContentDrawBounds, &Caches::getInstance());
     mLayerUpdateQueue.clear();
-    BakedOpRenderer renderer(Caches::getInstance(), mRenderThread.renderState(),
+    auto&& caches = Caches::getInstance();
+    BakedOpRenderer renderer(caches, mRenderThread.renderState(),
             mOpaque, mLightInfo);
-    // TODO: profiler().draw(mCanvas);
     frameBuilder.replayBakedOps<BakedOpDispatcher>(renderer);
+    profiler().draw(&renderer);
     bool drew = renderer.didDraw();
 
+    // post frame cleanup
+    caches.clearGarbage();
+    caches.pathCache.trim();
+    caches.tessellationCache.trim();
+
+#if DEBUG_MEMORY_USAGE
+    mCaches.dumpMemoryUsage();
+#else
+    if (CC_UNLIKELY(Properties::debugLevel & kDebugMemory)) {
+        caches.dumpMemoryUsage();
+    }
+#endif
+
 #else
     mCanvas->prepareDirty(frame.width(), frame.height(),
             dirty.fLeft, dirty.fTop, dirty.fRight, dirty.fBottom, mOpaque);
@@ -476,7 +490,7 @@
     // metrics the frame was swapped at this point
     mCurrentFrameInfo->markSwapBuffers();
 
-    if (drew) {
+    if (drew || mEglManager.damageRequiresSwap()) {
         if (CC_UNLIKELY(!mEglManager.swapBuffers(frame, screenDirty))) {
             setSurface(nullptr);
         }
diff --git a/libs/hwui/renderthread/EglManager.cpp b/libs/hwui/renderthread/EglManager.cpp
index 364d4dd..8def7ad 100644
--- a/libs/hwui/renderthread/EglManager.cpp
+++ b/libs/hwui/renderthread/EglManager.cpp
@@ -270,6 +270,12 @@
         // Ensure we always have a valid surface & context
         surface = mPBufferSurface;
     }
+    // TODO: Temporary to help diagnose b/27286867
+    if (mCurrentSurface == mPBufferSurface || surface == mPBufferSurface) {
+        ALOGD("Switching from surface %p%s to %p%s", mCurrentSurface,
+                mCurrentSurface == mPBufferSurface ? " (pbuffer)" : "",
+                        surface, surface == mPBufferSurface ? " (pbuffer)" : "");
+    }
     if (!eglMakeCurrent(mEglDisplay, surface, surface, mEglContext)) {
         if (errOut) {
             *errOut = eglGetError();
@@ -324,6 +330,10 @@
 #endif
 }
 
+bool EglManager::damageRequiresSwap() {
+    return EglExtensions.setDamage && mSwapBehavior == SwapBehavior::BufferAge;
+}
+
 bool EglManager::swapBuffers(const Frame& frame, const SkRect& screenDirty) {
 
     if (CC_UNLIKELY(Properties::waitForGpuCompletion)) {
diff --git a/libs/hwui/renderthread/EglManager.h b/libs/hwui/renderthread/EglManager.h
index 62b5b99..459baed 100644
--- a/libs/hwui/renderthread/EglManager.h
+++ b/libs/hwui/renderthread/EglManager.h
@@ -70,6 +70,10 @@
     bool makeCurrent(EGLSurface surface, EGLint* errOut = nullptr);
     Frame beginFrame(EGLSurface surface);
     void damageFrame(const Frame& frame, const SkRect& dirty);
+    // If this returns true it is mandatory that swapBuffers is called
+    // if damageFrame is called without subsequent calls to damageFrame().
+    // See EGL_KHR_partial_update for more information
+    bool damageRequiresSwap();
     bool swapBuffers(const Frame& frame, const SkRect& screenDirty);
 
     // Returns true iff the surface is now preserving buffers.
diff --git a/libs/hwui/tests/common/TestUtils.cpp b/libs/hwui/tests/common/TestUtils.cpp
index 9595a85..c809ff4 100644
--- a/libs/hwui/tests/common/TestUtils.cpp
+++ b/libs/hwui/tests/common/TestUtils.cpp
@@ -19,9 +19,6 @@
 #include "DeferredLayerUpdater.h"
 #include "LayerRenderer.h"
 
-#include <unistd.h>
-#include <signal.h>
-
 namespace android {
 namespace uirenderer {
 
@@ -136,27 +133,7 @@
     canvas->drawTextOnPath(glyphs.data(), glyphs.size(), path, 0, 0, paint);
 }
 
-static void defaultCrashHandler() {
-    fprintf(stderr, "RenderThread crashed!");
-}
-
-static std::function<void()> gCrashHandler = defaultCrashHandler;
-static sighandler_t gPreviousSignalHandler;
-
-static void signalHandler(int sig) {
-    gCrashHandler();
-    if (gPreviousSignalHandler) {
-        gPreviousSignalHandler(sig);
-    }
-}
-
-void TestUtils::setRenderThreadCrashHandler(std::function<void()> crashHandler) {
-    gCrashHandler = crashHandler;
-}
-
 void TestUtils::TestTask::run() {
-    gPreviousSignalHandler = signal(SIGABRT, signalHandler);
-
     // RenderState only valid once RenderThread is running, so queried here
     RenderState& renderState = renderthread::RenderThread::getInstance().renderState();
 
@@ -164,9 +141,6 @@
     rtCallback(renderthread::RenderThread::getInstance());
     renderState.flush(Caches::FlushMode::Full);
     renderState.onGLContextDestroyed();
-
-    // Restore the previous signal handler
-    signal(SIGABRT, gPreviousSignalHandler);
 }
 
 } /* namespace uirenderer */
diff --git a/libs/hwui/tests/common/TestUtils.h b/libs/hwui/tests/common/TestUtils.h
index 6f23705..28ac116 100644
--- a/libs/hwui/tests/common/TestUtils.h
+++ b/libs/hwui/tests/common/TestUtils.h
@@ -180,8 +180,6 @@
 
     typedef std::function<void(renderthread::RenderThread& thread)> RtCallback;
 
-    static void setRenderThreadCrashHandler(std::function<void()> crashHandler);
-
     class TestTask : public renderthread::RenderTask {
     public:
         TestTask(RtCallback rtCallback)
diff --git a/libs/hwui/tests/microbench/DisplayListCanvasBench.cpp b/libs/hwui/tests/microbench/DisplayListCanvasBench.cpp
index b317c12..06b68d1 100644
--- a/libs/hwui/tests/microbench/DisplayListCanvasBench.cpp
+++ b/libs/hwui/tests/microbench/DisplayListCanvasBench.cpp
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-#include <benchmark/Benchmark.h>
+#include <benchmark/benchmark.h>
 
 #include "DisplayList.h"
 #if HWUI_NEW_OPS
@@ -23,7 +23,6 @@
 #include "DisplayListCanvas.h"
 #endif
 #include "tests/common/TestUtils.h"
-#include "tests/microbench/MicroBench.h"
 
 using namespace android;
 using namespace android::uirenderer;
@@ -34,74 +33,64 @@
 typedef DisplayListCanvas TestCanvas;
 #endif
 
-BENCHMARK_NO_ARG(BM_DisplayList_alloc);
-void BM_DisplayList_alloc::Run(int iters) {
-    StartBenchmarkTiming();
-    for (int i = 0; i < iters; ++i) {
+void BM_DisplayList_alloc(benchmark::State& benchState) {
+    while (benchState.KeepRunning()) {
         auto displayList = new DisplayList();
-        MicroBench::DoNotOptimize(displayList);
+        benchmark::DoNotOptimize(displayList);
         delete displayList;
     }
-    StopBenchmarkTiming();
 }
+BENCHMARK(BM_DisplayList_alloc);
 
-BENCHMARK_NO_ARG(BM_DisplayList_alloc_theoretical);
-void BM_DisplayList_alloc_theoretical::Run(int iters) {
-    StartBenchmarkTiming();
-    for (int i = 0; i < iters; ++i) {
+void BM_DisplayList_alloc_theoretical(benchmark::State& benchState) {
+    while (benchState.KeepRunning()) {
         auto displayList = new char[sizeof(DisplayList)];
-        MicroBench::DoNotOptimize(displayList);
+        benchmark::DoNotOptimize(displayList);
         delete[] displayList;
     }
-    StopBenchmarkTiming();
 }
+BENCHMARK(BM_DisplayList_alloc_theoretical);
 
-BENCHMARK_NO_ARG(BM_DisplayListCanvas_record_empty);
-void BM_DisplayListCanvas_record_empty::Run(int iters) {
+void BM_DisplayListCanvas_record_empty(benchmark::State& benchState) {
     TestCanvas canvas(100, 100);
     delete canvas.finishRecording();
 
-    StartBenchmarkTiming();
-    for (int i = 0; i < iters; ++i) {
+    while (benchState.KeepRunning()) {
         canvas.resetRecording(100, 100);
-        MicroBench::DoNotOptimize(&canvas);
+        benchmark::DoNotOptimize(&canvas);
         delete canvas.finishRecording();
     }
-    StopBenchmarkTiming();
 }
+BENCHMARK(BM_DisplayListCanvas_record_empty);
 
-BENCHMARK_NO_ARG(BM_DisplayListCanvas_record_saverestore);
-void BM_DisplayListCanvas_record_saverestore::Run(int iters) {
+void BM_DisplayListCanvas_record_saverestore(benchmark::State& benchState) {
     TestCanvas canvas(100, 100);
     delete canvas.finishRecording();
 
-    StartBenchmarkTiming();
-    for (int i = 0; i < iters; ++i) {
+    while (benchState.KeepRunning()) {
         canvas.resetRecording(100, 100);
         canvas.save(SaveFlags::MatrixClip);
         canvas.save(SaveFlags::MatrixClip);
-        MicroBench::DoNotOptimize(&canvas);
+        benchmark::DoNotOptimize(&canvas);
         canvas.restore();
         canvas.restore();
         delete canvas.finishRecording();
     }
-    StopBenchmarkTiming();
 }
+BENCHMARK(BM_DisplayListCanvas_record_saverestore);
 
-BENCHMARK_NO_ARG(BM_DisplayListCanvas_record_translate);
-void BM_DisplayListCanvas_record_translate::Run(int iters) {
+void BM_DisplayListCanvas_record_translate(benchmark::State& benchState) {
     TestCanvas canvas(100, 100);
     delete canvas.finishRecording();
 
-    StartBenchmarkTiming();
-    for (int i = 0; i < iters; ++i) {
+    while (benchState.KeepRunning()) {
         canvas.resetRecording(100, 100);
         canvas.scale(10, 10);
-        MicroBench::DoNotOptimize(&canvas);
+        benchmark::DoNotOptimize(&canvas);
         delete canvas.finishRecording();
     }
-    StopBenchmarkTiming();
 }
+BENCHMARK(BM_DisplayListCanvas_record_translate);
 
 /**
  * Simulate a simple view drawing a background, overlapped by an image.
@@ -109,16 +98,14 @@
  * Note that the recording commands are intentionally not perfectly efficient, as the
  * View system frequently produces unneeded save/restores.
  */
-BENCHMARK_NO_ARG(BM_DisplayListCanvas_record_simpleBitmapView);
-void BM_DisplayListCanvas_record_simpleBitmapView::Run(int iters) {
+void BM_DisplayListCanvas_record_simpleBitmapView(benchmark::State& benchState) {
     TestCanvas canvas(100, 100);
     delete canvas.finishRecording();
 
     SkPaint rectPaint;
     SkBitmap iconBitmap = TestUtils::createSkBitmap(80, 80);
 
-    StartBenchmarkTiming();
-    for (int i = 0; i < iters; ++i) {
+    while (benchState.KeepRunning()) {
         canvas.resetRecording(100, 100);
         {
             canvas.save(SaveFlags::MatrixClip);
@@ -131,11 +118,11 @@
             canvas.drawBitmap(iconBitmap, 0, 0, nullptr);
             canvas.restore();
         }
-        MicroBench::DoNotOptimize(&canvas);
+        benchmark::DoNotOptimize(&canvas);
         delete canvas.finishRecording();
     }
-    StopBenchmarkTiming();
 }
+BENCHMARK(BM_DisplayListCanvas_record_simpleBitmapView);
 
 class NullClient: public CanvasStateClient {
     void onViewportInitialized() override {}
@@ -143,48 +130,42 @@
     GLuint getTargetFbo() const override { return 0; }
 };
 
-BENCHMARK_NO_ARG(BM_CanvasState_saverestore);
-void BM_CanvasState_saverestore::Run(int iters) {
+void BM_CanvasState_saverestore(benchmark::State& benchState) {
     NullClient client;
     CanvasState state(client);
     state.initializeSaveStack(100, 100, 0, 0, 100, 100, Vector3());
 
-    StartBenchmarkTiming();
-    for (int i = 0; i < iters; ++i) {
+    while (benchState.KeepRunning()) {
         state.save(SaveFlags::MatrixClip);
         state.save(SaveFlags::MatrixClip);
-        MicroBench::DoNotOptimize(&state);
+        benchmark::DoNotOptimize(&state);
         state.restore();
         state.restore();
     }
-    StopBenchmarkTiming();
 }
+BENCHMARK(BM_CanvasState_saverestore);
 
-BENCHMARK_NO_ARG(BM_CanvasState_init);
-void BM_CanvasState_init::Run(int iters) {
+void BM_CanvasState_init(benchmark::State& benchState) {
     NullClient client;
     CanvasState state(client);
     state.initializeSaveStack(100, 100, 0, 0, 100, 100, Vector3());
 
-    StartBenchmarkTiming();
-    for (int i = 0; i < iters; ++i) {
+    while (benchState.KeepRunning()) {
         state.initializeSaveStack(100, 100, 0, 0, 100, 100, Vector3());
-        MicroBench::DoNotOptimize(&state);
+        benchmark::DoNotOptimize(&state);
     }
-    StopBenchmarkTiming();
 }
+BENCHMARK(BM_CanvasState_init);
 
-BENCHMARK_NO_ARG(BM_CanvasState_translate);
-void BM_CanvasState_translate::Run(int iters) {
+void BM_CanvasState_translate(benchmark::State& benchState) {
     NullClient client;
     CanvasState state(client);
     state.initializeSaveStack(100, 100, 0, 0, 100, 100, Vector3());
 
-    StartBenchmarkTiming();
-    for (int i = 0; i < iters; ++i) {
+    while (benchState.KeepRunning()) {
         state.translate(5, 5, 0);
-        MicroBench::DoNotOptimize(&state);
+        benchmark::DoNotOptimize(&state);
         state.translate(-5, -5, 0);
     }
-    StopBenchmarkTiming();
 }
+BENCHMARK(BM_CanvasState_translate);
diff --git a/libs/hwui/tests/microbench/FrameBuilderBench.cpp b/libs/hwui/tests/microbench/FrameBuilderBench.cpp
index 7845eb4..7816f0f 100644
--- a/libs/hwui/tests/microbench/FrameBuilderBench.cpp
+++ b/libs/hwui/tests/microbench/FrameBuilderBench.cpp
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-#include <benchmark/Benchmark.h>
+#include <benchmark/benchmark.h>
 
 #include "BakedOpState.h"
 #include "BakedOpDispatcher.h"
@@ -27,7 +27,6 @@
 #include "tests/common/TestScene.h"
 #include "tests/common/TestUtils.h"
 #include "Vector.h"
-#include "tests/microbench/MicroBench.h"
 
 #include <vector>
 
@@ -62,38 +61,34 @@
     return vec;
 }
 
-BENCHMARK_NO_ARG(BM_FrameBuilder_defer);
-void BM_FrameBuilder_defer::Run(int iters) {
+void BM_FrameBuilder_defer(benchmark::State& state) {
     auto nodes = createTestNodeList();
-    StartBenchmarkTiming();
-    for (int i = 0; i < iters; i++) {
+    while (state.KeepRunning()) {
         FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(100, 200), 100, 200,
                 nodes, sLightGeometry, nullptr);
-        MicroBench::DoNotOptimize(&frameBuilder);
+        benchmark::DoNotOptimize(&frameBuilder);
     }
-    StopBenchmarkTiming();
 }
+BENCHMARK(BM_FrameBuilder_defer);
 
-BENCHMARK_NO_ARG(BM_FrameBuilder_deferAndRender);
-void BM_FrameBuilder_deferAndRender::Run(int iters) {
-    TestUtils::runOnRenderThread([this, iters](RenderThread& thread) {
+void BM_FrameBuilder_deferAndRender(benchmark::State& state) {
+    TestUtils::runOnRenderThread([&state](RenderThread& thread) {
         auto nodes = createTestNodeList();
 
         RenderState& renderState = thread.renderState();
         Caches& caches = Caches::getInstance();
 
-        StartBenchmarkTiming();
-        for (int i = 0; i < iters; i++) {
+        while (state.KeepRunning()) {
             FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(100, 200), 100, 200,
                     nodes, sLightGeometry, nullptr);
 
             BakedOpRenderer renderer(caches, renderState, true, sLightInfo);
             frameBuilder.replayBakedOps<BakedOpDispatcher>(renderer);
-            MicroBench::DoNotOptimize(&renderer);
+            benchmark::DoNotOptimize(&renderer);
         }
-        StopBenchmarkTiming();
     });
 }
+BENCHMARK(BM_FrameBuilder_deferAndRender);
 
 static std::vector<sp<RenderNode>> getSyncedSceneNodes(const char* sceneName) {
     gDisplay = getBuiltInDisplay(); // switch to real display if present
@@ -113,47 +108,41 @@
     return nodes;
 }
 
-static void benchDeferScene(testing::Benchmark& benchmark, int iters, const char* sceneName) {
+static auto SCENES = {
+        "listview",
+};
+
+void BM_FrameBuilder_defer_scene(benchmark::State& state) {
+    const char* sceneName = *(SCENES.begin() + state.range_x());
+    state.SetLabel(sceneName);
     auto nodes = getSyncedSceneNodes(sceneName);
-    benchmark.StartBenchmarkTiming();
-    for (int i = 0; i < iters; i++) {
+    while (state.KeepRunning()) {
         FrameBuilder frameBuilder(sEmptyLayerUpdateQueue,
                 SkRect::MakeWH(gDisplay.w, gDisplay.h), gDisplay.w, gDisplay.h,
                 nodes, sLightGeometry, nullptr);
-        MicroBench::DoNotOptimize(&frameBuilder);
+        benchmark::DoNotOptimize(&frameBuilder);
     }
-    benchmark.StopBenchmarkTiming();
 }
+BENCHMARK(BM_FrameBuilder_defer_scene)->DenseRange(0, SCENES.size() - 1);
 
-static void benchDeferAndRenderScene(testing::Benchmark& benchmark,
-        int iters, const char* sceneName) {
-    TestUtils::runOnRenderThread([&benchmark, iters, sceneName](RenderThread& thread) {
+void BM_FrameBuilder_deferAndRender_scene(benchmark::State& state) {
+    TestUtils::runOnRenderThread([&state](RenderThread& thread) {
+        const char* sceneName = *(SCENES.begin() + state.range_x());
+        state.SetLabel(sceneName);
         auto nodes = getSyncedSceneNodes(sceneName);
 
         RenderState& renderState = thread.renderState();
         Caches& caches = Caches::getInstance();
 
-        benchmark.StartBenchmarkTiming();
-        for (int i = 0; i < iters; i++) {
+        while (state.KeepRunning()) {
             FrameBuilder frameBuilder(sEmptyLayerUpdateQueue,
                     SkRect::MakeWH(gDisplay.w, gDisplay.h), gDisplay.w, gDisplay.h,
                     nodes, sLightGeometry, nullptr);
 
             BakedOpRenderer renderer(caches, renderState, true, sLightInfo);
             frameBuilder.replayBakedOps<BakedOpDispatcher>(renderer);
-            MicroBench::DoNotOptimize(&renderer);
+            benchmark::DoNotOptimize(&renderer);
         }
-        benchmark.StopBenchmarkTiming();
     });
 }
-
-BENCHMARK_NO_ARG(BM_FrameBuilder_listview_defer);
-void BM_FrameBuilder_listview_defer::Run(int iters) {
-    benchDeferScene(*this, iters, "listview");
-}
-
-BENCHMARK_NO_ARG(BM_FrameBuilder_listview_deferAndRender);
-void BM_FrameBuilder_listview_deferAndRender::Run(int iters) {
-    benchDeferAndRenderScene(*this, iters, "listview");
-}
-
+BENCHMARK(BM_FrameBuilder_deferAndRender_scene)->DenseRange(0, SCENES.size() - 1);
diff --git a/libs/hwui/tests/microbench/LinearAllocatorBench.cpp b/libs/hwui/tests/microbench/LinearAllocatorBench.cpp
index 28513e4..3c0a6c5 100644
--- a/libs/hwui/tests/microbench/LinearAllocatorBench.cpp
+++ b/libs/hwui/tests/microbench/LinearAllocatorBench.cpp
@@ -14,9 +14,8 @@
  * limitations under the License.
  */
 
-#include <benchmark/Benchmark.h>
+#include <benchmark/benchmark.h>
 
-#include "tests/microbench/MicroBench.h"
 #include "utils/LinearAllocator.h"
 
 #include <vector>
@@ -24,30 +23,26 @@
 using namespace android;
 using namespace android::uirenderer;
 
-BENCHMARK_NO_ARG(BM_LinearStdAllocator_vectorBaseline);
-void BM_LinearStdAllocator_vectorBaseline::Run(int iters) {
-    StartBenchmarkTiming();
-    for (int i = 0; i < iters; i++) {
+static void BM_LinearStdAllocator_vectorBaseline(benchmark::State& state) {
+    while (state.KeepRunning()) {
         std::vector<char> v;
         for (int j = 0; j < 200; j++) {
             v.push_back(j);
         }
-        MicroBench::DoNotOptimize(&v);
+        benchmark::DoNotOptimize(&v);
     }
-    StopBenchmarkTiming();
 }
+BENCHMARK(BM_LinearStdAllocator_vectorBaseline);
 
-BENCHMARK_NO_ARG(BM_LinearStdAllocator_vector);
-void BM_LinearStdAllocator_vector::Run(int iters) {
-    StartBenchmarkTiming();
-    for (int i = 0; i < iters; i++) {
+static void BM_LinearStdAllocator_vector(benchmark::State& state) {
+    while (state.KeepRunning()) {
         LinearAllocator la;
         LinearStdAllocator<void*> stdAllocator(la);
         std::vector<char, LinearStdAllocator<char> > v(stdAllocator);
         for (int j = 0; j < 200; j++) {
             v.push_back(j);
         }
-        MicroBench::DoNotOptimize(&v);
+        benchmark::DoNotOptimize(&v);
     }
-    StopBenchmarkTiming();
 }
+BENCHMARK(BM_LinearStdAllocator_vector);
diff --git a/libs/hwui/tests/microbench/MicroBench.h b/libs/hwui/tests/microbench/MicroBench.h
deleted file mode 100644
index f05e92c..0000000
--- a/libs/hwui/tests/microbench/MicroBench.h
+++ /dev/null
@@ -1,35 +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.
- */
-#ifndef MICROBENCH_MICROBENCH_H
-#define MICROBENCH_MICROBENCH_H
-
-namespace android {
-namespace uirenderer {
-
-#define NO_INLINE __attribute__ ((noinline))
-
-class MicroBench {
-public:
-    template <class Tp>
-    static inline void DoNotOptimize(Tp const& value) {
-        asm volatile("" : "+rm" (const_cast<Tp&>(value)));
-    }
-};
-
-} /* namespace uirenderer */
-} /* namespace android */
-
-#endif /* MICROBENCH_MICROBENCH_H */
diff --git a/libs/hwui/tests/microbench/PathParserBench.cpp b/libs/hwui/tests/microbench/PathParserBench.cpp
index bd742c6..4186539 100644
--- a/libs/hwui/tests/microbench/PathParserBench.cpp
+++ b/libs/hwui/tests/microbench/PathParserBench.cpp
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-#include <benchmark/Benchmark.h>
+#include <benchmark/benchmark.h>
 
 #include "PathParser.h"
 #include "VectorDrawable.h"
@@ -26,26 +26,26 @@
 
 static const char* sPathString = "M 1 1 m 2 2, l 3 3 L 3 3 H 4 h4 V5 v5, Q6 6 6 6 q 6 6 6 6t 7 7 T 7 7 C 8 8 8 8 8 8 c 8 8 8 8 8 8 S 9 9 9 9 s 9 9 9 9 A 10 10 0 1 1 10 10 a 10 10 0 1 1 10 10";
 
-BENCHMARK_NO_ARG(BM_PathParser_parseStringPathForSkPath);
-void BM_PathParser_parseStringPathForSkPath::Run(int iter) {
+void BM_PathParser_parseStringPathForSkPath(benchmark::State& state) {
     SkPath skPath;
     size_t length = strlen(sPathString);
     PathParser::ParseResult result;
-    StartBenchmarkTiming();
-    for (int i = 0; i < iter; i++) {
+    while (state.KeepRunning()) {
         PathParser::parseStringForSkPath(&skPath, &result, sPathString, length);
+        benchmark::DoNotOptimize(&result);
+        benchmark::DoNotOptimize(&skPath);
     }
-    StopBenchmarkTiming();
 }
+BENCHMARK(BM_PathParser_parseStringPathForSkPath);
 
-BENCHMARK_NO_ARG(BM_PathParser_parseStringPathForPathData);
-void BM_PathParser_parseStringPathForPathData::Run(int iter) {
+void BM_PathParser_parseStringPathForPathData(benchmark::State& state) {
     size_t length = strlen(sPathString);
     PathData outData;
     PathParser::ParseResult result;
-    StartBenchmarkTiming();
-    for (int i = 0; i < iter; i++) {
+    while (state.KeepRunning()) {
         PathParser::getPathDataFromString(&outData, &result, sPathString, length);
+        benchmark::DoNotOptimize(&result);
+        benchmark::DoNotOptimize(&outData);
     }
-    StopBenchmarkTiming();
 }
+BENCHMARK(BM_PathParser_parseStringPathForPathData);
diff --git a/libs/hwui/tests/microbench/ShadowBench.cpp b/libs/hwui/tests/microbench/ShadowBench.cpp
index 98ec4d9..a0fc6e8 100644
--- a/libs/hwui/tests/microbench/ShadowBench.cpp
+++ b/libs/hwui/tests/microbench/ShadowBench.cpp
@@ -14,14 +14,13 @@
  * limitations under the License.
  */
 
-#include <benchmark/Benchmark.h>
+#include <benchmark/benchmark.h>
 
 #include "Matrix.h"
 #include "Rect.h"
 #include "Vector.h"
 #include "VertexBuffer.h"
 #include "TessellationCache.h"
-#include "tests/microbench/MicroBench.h"
 
 #include <SkPath.h>
 
@@ -78,39 +77,35 @@
             testData.lightRadius, *ambient, *spot);
 }
 
-BENCHMARK_NO_ARG(BM_TessellateShadows_roundrect_opaque);
-void BM_TessellateShadows_roundrect_opaque::Run(int iters) {
+void BM_TessellateShadows_roundrect_opaque(benchmark::State& state) {
     ShadowTestData shadowData;
     createShadowTestData(&shadowData);
     SkPath path;
     path.addRoundRect(SkRect::MakeWH(100, 100), 5, 5);
 
-    StartBenchmarkTiming();
-    for (int i = 0; i < iters; i++) {
+    while (state.KeepRunning()) {
         VertexBuffer ambient;
         VertexBuffer spot;
         tessellateShadows(shadowData, true, path, &ambient, &spot);
-        MicroBench::DoNotOptimize(&ambient);
-        MicroBench::DoNotOptimize(&spot);
+        benchmark::DoNotOptimize(&ambient);
+        benchmark::DoNotOptimize(&spot);
     }
-    StopBenchmarkTiming();
 }
+BENCHMARK(BM_TessellateShadows_roundrect_opaque);
 
-BENCHMARK_NO_ARG(BM_TessellateShadows_roundrect_translucent);
-void BM_TessellateShadows_roundrect_translucent::Run(int iters) {
+void BM_TessellateShadows_roundrect_translucent(benchmark::State& state) {
     ShadowTestData shadowData;
     createShadowTestData(&shadowData);
     SkPath path;
     path.reset();
     path.addRoundRect(SkRect::MakeLTRB(0, 0, 100, 100), 5, 5);
 
-    StartBenchmarkTiming();
-    for (int i = 0; i < iters; i++) {
+    while (state.KeepRunning()) {
         std::unique_ptr<VertexBuffer> ambient(new VertexBuffer);
         std::unique_ptr<VertexBuffer> spot(new VertexBuffer);
         tessellateShadows(shadowData, false, path, ambient.get(), spot.get());
-        MicroBench::DoNotOptimize(ambient.get());
-        MicroBench::DoNotOptimize(spot.get());
+        benchmark::DoNotOptimize(ambient.get());
+        benchmark::DoNotOptimize(spot.get());
     }
-    StopBenchmarkTiming();
 }
+BENCHMARK(BM_TessellateShadows_roundrect_translucent);
diff --git a/libs/hwui/tests/microbench/TaskManagerBench.cpp b/libs/hwui/tests/microbench/TaskManagerBench.cpp
index 0ea30e47..c6b9f3b 100644
--- a/libs/hwui/tests/microbench/TaskManagerBench.cpp
+++ b/libs/hwui/tests/microbench/TaskManagerBench.cpp
@@ -14,12 +14,11 @@
  * limitations under the License.
  */
 
-#include <benchmark/Benchmark.h>
+#include <benchmark/benchmark.h>
 
 #include "thread/Task.h"
 #include "thread/TaskManager.h"
 #include "thread/TaskProcessor.h"
-#include "tests/microbench/MicroBench.h"
 
 #include <vector>
 
@@ -39,55 +38,51 @@
     }
 };
 
-BENCHMARK_NO_ARG(BM_TaskManager_allocateTask);
-void BM_TaskManager_allocateTask::Run(int iters) {
+void BM_TaskManager_allocateTask(benchmark::State& state) {
     std::vector<sp<TrivialTask> > tasks;
-    tasks.reserve(iters);
+    tasks.reserve(state.max_iterations);
 
-    StartBenchmarkTiming();
-    for (int i = 0; i < iters; i++) {
+    while (state.KeepRunning()) {
         tasks.emplace_back(new TrivialTask);
-        MicroBench::DoNotOptimize(tasks.back());
+        benchmark::DoNotOptimize(tasks.back());
     }
-    StopBenchmarkTiming();
 }
+BENCHMARK(BM_TaskManager_allocateTask);
 
-BENCHMARK_NO_ARG(BM_TaskManager_enqueueTask);
-void BM_TaskManager_enqueueTask::Run(int iters) {
+void BM_TaskManager_enqueueTask(benchmark::State& state) {
     TaskManager taskManager;
     sp<TrivialProcessor> processor(new TrivialProcessor(&taskManager));
     std::vector<sp<TrivialTask> > tasks;
-    tasks.reserve(iters);
+    tasks.reserve(state.max_iterations);
 
-    StartBenchmarkTiming();
-    for (int i = 0; i < iters; i++) {
+    while (state.KeepRunning()) {
         tasks.emplace_back(new TrivialTask);
-        MicroBench::DoNotOptimize(tasks.back());
+        benchmark::DoNotOptimize(tasks.back());
         processor->add(tasks.back());
     }
-    StopBenchmarkTiming();
 
     for (sp<TrivialTask>& task : tasks) {
         task->getResult();
     }
 }
+BENCHMARK(BM_TaskManager_enqueueTask);
 
-BENCHMARK_NO_ARG(BM_TaskManager_enqueueRunDeleteTask);
-void BM_TaskManager_enqueueRunDeleteTask::Run(int iters) {
+void BM_TaskManager_enqueueRunDeleteTask(benchmark::State& state) {
     TaskManager taskManager;
     sp<TrivialProcessor> processor(new TrivialProcessor(&taskManager));
     std::vector<sp<TrivialTask> > tasks;
-    tasks.reserve(iters);
+    tasks.reserve(state.max_iterations);
 
-    StartBenchmarkTiming();
-    for (int i = 0; i < iters; i++) {
+    while (state.KeepRunning()) {
         tasks.emplace_back(new TrivialTask);
-        MicroBench::DoNotOptimize(tasks.back());
+        benchmark::DoNotOptimize(tasks.back());
         processor->add(tasks.back());
     }
+    state.ResumeTiming();
     for (sp<TrivialTask>& task : tasks) {
-        MicroBench::DoNotOptimize(task->getResult());
+        benchmark::DoNotOptimize(task->getResult());
     }
     tasks.clear();
-    StopBenchmarkTiming();
+    state.PauseTiming();
 }
+BENCHMARK(BM_TaskManager_enqueueRunDeleteTask);
diff --git a/core/java/android/hardware/CameraInfo.aidl b/libs/hwui/tests/microbench/main.cpp
similarity index 82%
copy from core/java/android/hardware/CameraInfo.aidl
copy to libs/hwui/tests/microbench/main.cpp
index e21e694..a0157bc 100644
--- a/core/java/android/hardware/CameraInfo.aidl
+++ b/libs/hwui/tests/microbench/main.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2013 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.
@@ -14,7 +14,6 @@
  * limitations under the License.
  */
 
-package android.hardware;
+#include <benchmark/benchmark.h>
 
-/** @hide */
-parcelable CameraInfo;
+BENCHMARK_MAIN();
diff --git a/libs/hwui/tests/unit/BakedOpDispatcherTests.cpp b/libs/hwui/tests/unit/BakedOpDispatcherTests.cpp
new file mode 100644
index 0000000..654ddc6
--- /dev/null
+++ b/libs/hwui/tests/unit/BakedOpDispatcherTests.cpp
@@ -0,0 +1,109 @@
+/*
+ * 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 <RecordedOp.h>
+#include <BakedOpDispatcher.h>
+#include <BakedOpRenderer.h>
+#include <tests/common/TestUtils.h>
+
+using namespace android::uirenderer;
+
+static BakedOpRenderer::LightInfo sLightInfo;
+static Rect sBaseClip(100, 100);
+
+class ValidatingBakedOpRenderer : public BakedOpRenderer {
+public:
+    ValidatingBakedOpRenderer(RenderState& renderState, std::function<void(const Glop& glop)> validator)
+            : BakedOpRenderer(Caches::getInstance(), renderState, true, sLightInfo)
+            , mValidator(validator) {
+        mGlopReceiver = ValidatingGlopReceiver;
+    }
+private:
+    static void ValidatingGlopReceiver(BakedOpRenderer& renderer, const Rect* dirtyBounds,
+            const ClipBase* clip, const Glop& glop) {
+
+        auto vbor = reinterpret_cast<ValidatingBakedOpRenderer*>(&renderer);
+        vbor->mValidator(glop);
+    }
+    std::function<void(const Glop& glop)> mValidator;
+};
+
+typedef void (*BakedOpReceiver)(BakedOpRenderer&, const BakedOpState&);
+
+static void testUnmergedGlopDispatch(renderthread::RenderThread& renderThread, RecordedOp* op,
+        std::function<void(const Glop& glop)> glopVerifier) {
+    // Create op, and wrap with basic state.
+    LinearAllocator allocator;
+    auto snapshot = TestUtils::makeSnapshot(Matrix4::identity(), sBaseClip);
+    auto state = BakedOpState::tryConstruct(allocator, *snapshot, *op);
+    ASSERT_NE(nullptr, state);
+
+    int glopCount = 0;
+    auto glopReceiver = [&glopVerifier, &glopCount] (const Glop& glop) {
+        ASSERT_EQ(glopCount++, 0) << "Only one Glop expected";
+        glopVerifier(glop);
+    };
+    ValidatingBakedOpRenderer renderer(renderThread.renderState(), glopReceiver);
+
+    // Dispatch based on op type created, similar to Frame/LayerBuilder dispatch behavior
+#define X(Type) \
+        [](BakedOpRenderer& renderer, const BakedOpState& state) { \
+            BakedOpDispatcher::on##Type(renderer, static_cast<const Type&>(*(state.op)), state); \
+        },
+    static BakedOpReceiver unmergedReceivers[] = BUILD_RENDERABLE_OP_LUT(X);
+#undef X
+    unmergedReceivers[op->opId](renderer, *state);
+    ASSERT_EQ(1, glopCount) << "Exactly one Glop expected";
+}
+
+RENDERTHREAD_TEST(BakedOpDispatcher, onArc_position) {
+    SkPaint strokePaint;
+    strokePaint.setStyle(SkPaint::kStroke_Style);
+    strokePaint.setStrokeWidth(4);
+    ArcOp op(Rect(10, 15, 20, 25), Matrix4::identity(), nullptr, &strokePaint, 0, 270, true);
+    testUnmergedGlopDispatch(renderThread, &op, [] (const Glop& glop) {
+        // validate glop produced by renderPathTexture (so texture, unit quad)
+        auto texture = glop.fill.texture.texture;
+        ASSERT_NE(nullptr, texture);
+        float expectedOffset = floor(4 * 1.5f + 0.5f);
+        EXPECT_EQ(expectedOffset, reinterpret_cast<PathTexture*>(texture)->offset)
+                << "Should see conservative offset from PathCache::computeBounds";
+        Rect expectedBounds(10, 15, 20, 25);
+        expectedBounds.outset(expectedOffset);
+        EXPECT_EQ(expectedBounds, glop.bounds) << "bounds outset by stroke 'offset'";
+        Matrix4 expectedModelView;
+        expectedModelView.loadTranslate(10 - expectedOffset, 15 - expectedOffset, 0);
+        expectedModelView.scale(10 + 2 * expectedOffset, 10 + 2 * expectedOffset, 1);
+        EXPECT_EQ(expectedModelView, glop.transform.modelView)
+                << "X and Y offsets, and scale both applied to model view";
+    });
+}
+
+RENDERTHREAD_TEST(BakedOpDispatcher, onLayerOp_bufferless) {
+    SkPaint layerPaint;
+    layerPaint.setAlpha(128);
+    OffscreenBuffer* buffer = nullptr; // no providing a buffer, should hit rect fallback case
+    LayerOp op(Rect(10, 10), Matrix4::identity(), nullptr, &layerPaint, &buffer);
+    testUnmergedGlopDispatch(renderThread, &op, [&renderThread] (const Glop& glop) {
+        // rect glop is dispatched with paint props applied
+        EXPECT_EQ(renderThread.renderState().meshState().getUnitQuadVBO(),
+                glop.mesh.vertices.bufferObject) << "Unit quad should be drawn";
+        EXPECT_EQ(nullptr, glop.fill.texture.texture) << "Should be no texture when layer is null";
+        EXPECT_FLOAT_EQ(128 / 255.0f, glop.fill.color.a) << "Rect quad should use op alpha";
+    });
+}
diff --git a/libs/hwui/tests/unit/ClipAreaTests.cpp b/libs/hwui/tests/unit/ClipAreaTests.cpp
index 679569e..822d04f 100644
--- a/libs/hwui/tests/unit/ClipAreaTests.cpp
+++ b/libs/hwui/tests/unit/ClipAreaTests.cpp
@@ -27,7 +27,7 @@
 namespace android {
 namespace uirenderer {
 
-static Rect kViewportBounds(0, 0, 2048, 2048);
+static Rect kViewportBounds(2048, 2048);
 
 static ClipArea createClipArea() {
     ClipArea area;
@@ -140,17 +140,15 @@
 
     // rect list
     Matrix4 rotate;
-    rotate.loadRotate(2.0f);
-    area.clipRectWithTransform(Rect(200, 200), &rotate, SkRegion::kIntersect_Op);
+    rotate.loadRotate(5.0f);
+    area.clipRectWithTransform(Rect(50, 50, 150, 150), &rotate, SkRegion::kIntersect_Op);
     {
         auto serializedClip = area.serializeClip(allocator);
         ASSERT_NE(nullptr, serializedClip);
         ASSERT_EQ(ClipMode::RectangleList, serializedClip->mode);
         auto clipRectList = reinterpret_cast<const ClipRectList*>(serializedClip);
         EXPECT_EQ(2, clipRectList->rectList.getTransformedRectanglesCount());
-        EXPECT_FALSE(clipRectList->rect.isEmpty());
-        EXPECT_FLOAT_EQ(199.87817f, clipRectList->rect.right)
-            << "Right side should be clipped by rotated rect";
+        EXPECT_EQ(Rect(37, 54, 145, 163), clipRectList->rect);
         EXPECT_EQ(serializedClip, area.serializeClip(allocator))
                 << "Requery of clip on unmodified ClipArea must return same pointer.";
     }
@@ -228,6 +226,7 @@
 
         ClipRegion recordedClip;
         recordedClip.region.setPath(ovalPath, SkRegion(SkIRect::MakeWH(200, 200)));
+        recordedClip.rect = Rect(200, 200);
 
         Matrix4 translate10x20;
         translate10x20.loadTranslate(10, 20, 0);
@@ -240,5 +239,28 @@
     }
 }
 
+TEST(ClipArea, serializeIntersectedClip_snap) {
+    ClipArea area(createClipArea());
+    area.setClip(100.2, 100.4, 500.6, 500.8);
+    LinearAllocator allocator;
+
+    {
+        // no recorded clip case
+        auto resolvedClip = area.serializeIntersectedClip(allocator, nullptr, Matrix4::identity());
+        EXPECT_EQ(Rect(100, 100, 501, 501), resolvedClip->rect);
+    }
+    {
+        // recorded clip case
+        ClipRect recordedClip(Rect(100.12, 100.74));
+        Matrix4 translateScale;
+        translateScale.loadTranslate(100, 100, 0);
+        translateScale.scale(2, 3, 1); // recorded clip will have non-int coords, even after transform
+        auto resolvedClip = area.serializeIntersectedClip(allocator, &recordedClip, translateScale);
+        ASSERT_NE(nullptr, resolvedClip);
+        EXPECT_EQ(ClipMode::Rectangle, resolvedClip->mode);
+        EXPECT_EQ(Rect(100, 100, 300, 402), resolvedClip->rect);
+    }
+}
+
 } // namespace uirenderer
 } // namespace android
diff --git a/libs/hwui/tests/unit/CrashHandlerInjector.cpp b/libs/hwui/tests/unit/CrashHandlerInjector.cpp
deleted file mode 100644
index b1c678d..0000000
--- a/libs/hwui/tests/unit/CrashHandlerInjector.cpp
+++ /dev/null
@@ -1,41 +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.
- */
-
-#include "tests/common/TestUtils.h"
-
-#include <gtest/gtest.h>
-#include <cstdio>
-
-using namespace android::uirenderer;
-
-static void gunitCrashHandler() {
-    auto testinfo = ::testing::UnitTest::GetInstance()->current_test_info();
-    printf("[  FAILED  ] %s.%s\n", testinfo->test_case_name(),
-            testinfo->name());
-    printf("[  FATAL!  ] RenderThread crashed, aborting tests!\n");
-    fflush(stdout);
-}
-
-static void hookError() {
-    TestUtils::setRenderThreadCrashHandler(gunitCrashHandler);
-}
-
-class HookErrorInit {
-public:
-    HookErrorInit() { hookError(); }
-};
-
-static HookErrorInit sInit;
diff --git a/libs/hwui/tests/unit/FrameBuilderTests.cpp b/libs/hwui/tests/unit/FrameBuilderTests.cpp
index f86898f..f147fd4 100644
--- a/libs/hwui/tests/unit/FrameBuilderTests.cpp
+++ b/libs/hwui/tests/unit/FrameBuilderTests.cpp
@@ -216,8 +216,7 @@
             << "Expect number of ops = 2 * loop count";
 }
 
-// TODO: Disabled due to b/26793764
-TEST(FrameBuilder, DISABLED_clippedMerging) {
+TEST(FrameBuilder, clippedMerging) {
     class ClippedMergingTestRenderer : public TestRendererBase {
     public:
         void onMergedBitmapOps(const MergedBakedOpList& opList) override {
@@ -350,6 +349,29 @@
     EXPECT_EQ(1, renderer.getIndex());
 }
 
+TEST(FrameBuilder, functor_reject) {
+    class FunctorTestRenderer : public TestRendererBase {
+    public:
+        void onFunctorOp(const FunctorOp& op, const BakedOpState& state) override {
+            EXPECT_EQ(0, mIndex++);
+        }
+    };
+    Functor noopFunctor;
+
+    // 1 million pixel tall view, scrolled down 80%
+    auto scrolledFunctorView = TestUtils::createNode(0, 0, 400, 1000000,
+            [&noopFunctor](RenderProperties& props, RecordingCanvas& canvas) {
+        canvas.translate(0, -800000);
+        canvas.callDrawGLFunction(&noopFunctor);
+    });
+
+    FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200,
+            TestUtils::createSyncedNodeList(scrolledFunctorView), sLightGeometry, nullptr);
+    FunctorTestRenderer renderer;
+    frameBuilder.replayBakedOps<TestDispatcher>(renderer);
+    EXPECT_EQ(1, renderer.getIndex()) << "Functor should not be rejected";
+}
+
 TEST(FrameBuilder, renderNode) {
     class RenderNodeTestRenderer : public TestRendererBase {
     public:
@@ -392,6 +414,7 @@
             TestUtils::createSyncedNodeList(parent), sLightGeometry, nullptr);
     RenderNodeTestRenderer renderer;
     frameBuilder.replayBakedOps<TestDispatcher>(renderer);
+    EXPECT_EQ(2, renderer.getIndex());
 }
 
 TEST(FrameBuilder, clipped) {
@@ -990,21 +1013,26 @@
                 EXPECT_EQ(Rect(100, 100), op.unmappedBounds);
                 EXPECT_EQ(SK_ColorWHITE, op.paint->getColor());
                 expectedMatrix.loadIdentity();
+                EXPECT_EQ(nullptr, state.computedState.localProjectionPathMask);
                 break;
             case 1:
                 EXPECT_EQ(Rect(-10, -10, 60, 60), op.unmappedBounds);
                 EXPECT_EQ(SK_ColorDKGRAY, op.paint->getColor());
-                expectedMatrix.loadTranslate(50, 50, 0); // TODO: should scroll be respected here?
+                expectedMatrix.loadTranslate(50 - scrollX, 50 - scrollY, 0);
+                ASSERT_NE(nullptr, state.computedState.localProjectionPathMask);
+                EXPECT_EQ(Rect(-35, -30, 45, 50),
+                        Rect(state.computedState.localProjectionPathMask->getBounds()));
                 break;
             case 2:
                 EXPECT_EQ(Rect(100, 50), op.unmappedBounds);
                 EXPECT_EQ(SK_ColorBLUE, op.paint->getColor());
                 expectedMatrix.loadTranslate(-scrollX, 50 - scrollY, 0);
+                EXPECT_EQ(nullptr, state.computedState.localProjectionPathMask);
                 break;
             default:
                 ADD_FAILURE();
             }
-            EXPECT_MATRIX_APPROX_EQ(expectedMatrix, state.computedState.transform);
+            EXPECT_EQ(expectedMatrix, state.computedState.transform);
         }
     };
 
@@ -1045,6 +1073,9 @@
     });
     auto parent = TestUtils::createNode(0, 0, 100, 100,
             [&receiverBackground, &child](RenderProperties& properties, RecordingCanvas& canvas) {
+        // Set a rect outline for the projecting ripple to be masked against.
+        properties.mutableOutline().setRoundRect(10, 10, 90, 90, 5, 1.0f);
+
         canvas.save(SaveFlags::MatrixClip);
         canvas.translate(-scrollX, -scrollY); // Apply scroll (note: bg undoes this internally)
         canvas.drawRenderNode(receiverBackground.get());
@@ -1059,6 +1090,145 @@
     EXPECT_EQ(3, renderer.getIndex());
 }
 
+RENDERTHREAD_TEST(FrameBuilder, projectionHwLayer) {
+    static const int scrollX = 5;
+    static const int scrollY = 10;
+    class ProjectionHwLayerTestRenderer : public TestRendererBase {
+    public:
+        void startRepaintLayer(OffscreenBuffer* offscreenBuffer, const Rect& repaintRect) override {
+            EXPECT_EQ(0, mIndex++);
+        }
+        void onArcOp(const ArcOp& op, const BakedOpState& state) override {
+            EXPECT_EQ(1, mIndex++);
+            ASSERT_EQ(nullptr, state.computedState.localProjectionPathMask);
+        }
+        void endLayer() override {
+            EXPECT_EQ(2, mIndex++);
+        }
+        void onRectOp(const RectOp& op, const BakedOpState& state) override {
+            EXPECT_EQ(3, mIndex++);
+            ASSERT_EQ(nullptr, state.computedState.localProjectionPathMask);
+        }
+        void onOvalOp(const OvalOp& op, const BakedOpState& state) override {
+            EXPECT_EQ(4, mIndex++);
+            ASSERT_NE(nullptr, state.computedState.localProjectionPathMask);
+            Matrix4 expected;
+            expected.loadTranslate(100 - scrollX, 100 - scrollY, 0);
+            EXPECT_EQ(expected, state.computedState.transform);
+            EXPECT_EQ(Rect(-85, -80, 295, 300),
+                    Rect(state.computedState.localProjectionPathMask->getBounds()));
+        }
+        void onLayerOp(const LayerOp& op, const BakedOpState& state) override {
+            EXPECT_EQ(5, mIndex++);
+            ASSERT_EQ(nullptr, state.computedState.localProjectionPathMask);
+        }
+    };
+    auto receiverBackground = TestUtils::createNode(0, 0, 400, 400,
+            [](RenderProperties& properties, RecordingCanvas& canvas) {
+        properties.setProjectionReceiver(true);
+        // scroll doesn't apply to background, so undone via translationX/Y
+        // NOTE: translationX/Y only! no other transform properties may be set for a proj receiver!
+        properties.setTranslationX(scrollX);
+        properties.setTranslationY(scrollY);
+
+        canvas.drawRect(0, 0, 400, 400, SkPaint());
+    });
+    auto projectingRipple = TestUtils::createNode(0, 0, 200, 200,
+            [](RenderProperties& properties, RecordingCanvas& canvas) {
+        properties.setProjectBackwards(true);
+        properties.setClipToBounds(false);
+        canvas.drawOval(100, 100, 300, 300, SkPaint()); // drawn mostly out of layer bounds
+    });
+    auto child = TestUtils::createNode(100, 100, 300, 300,
+            [&projectingRipple](RenderProperties& properties, RecordingCanvas& canvas) {
+        properties.mutateLayerProperties().setType(LayerType::RenderLayer);
+        canvas.drawRenderNode(projectingRipple.get());
+        canvas.drawArc(0, 0, 200, 200, 0.0f, 280.0f, true, SkPaint());
+    });
+    auto parent = TestUtils::createNode(0, 0, 400, 400,
+            [&receiverBackground, &child](RenderProperties& properties, RecordingCanvas& canvas) {
+        // Set a rect outline for the projecting ripple to be masked against.
+        properties.mutableOutline().setRoundRect(10, 10, 390, 390, 0, 1.0f);
+        canvas.translate(-scrollX, -scrollY); // Apply scroll (note: bg undoes this internally)
+        canvas.drawRenderNode(receiverBackground.get());
+        canvas.drawRenderNode(child.get());
+    });
+
+    OffscreenBuffer** layerHandle = child->getLayerHandle();
+
+    // create RenderNode's layer here in same way prepareTree would, setting windowTransform
+    OffscreenBuffer layer(renderThread.renderState(), Caches::getInstance(), 200, 200);
+    Matrix4 windowTransform;
+    windowTransform.loadTranslate(100, 100, 0); // total transform of layer's origin
+    layer.setWindowTransform(windowTransform);
+    *layerHandle = &layer;
+
+    auto syncedList = TestUtils::createSyncedNodeList(parent);
+    LayerUpdateQueue layerUpdateQueue; // Note: enqueue damage post-sync, so bounds are valid
+    layerUpdateQueue.enqueueLayerWithDamage(child.get(), Rect(200, 200));
+    FrameBuilder frameBuilder(layerUpdateQueue, SkRect::MakeWH(400, 400), 400, 400,
+            syncedList, sLightGeometry, nullptr);
+    ProjectionHwLayerTestRenderer renderer;
+    frameBuilder.replayBakedOps<TestDispatcher>(renderer);
+    EXPECT_EQ(6, renderer.getIndex());
+
+    // clean up layer pointer, so we can safely destruct RenderNode
+    *layerHandle = nullptr;
+}
+
+RENDERTHREAD_TEST(FrameBuilder, projectionChildScroll) {
+    static const int scrollX = 500000;
+    static const int scrollY = 0;
+    class ProjectionChildScrollTestRenderer : public TestRendererBase {
+    public:
+        void onRectOp(const RectOp& op, const BakedOpState& state) override {
+            EXPECT_EQ(0, mIndex++);
+            EXPECT_TRUE(state.computedState.transform.isIdentity());
+        }
+        void onOvalOp(const OvalOp& op, const BakedOpState& state) override {
+            EXPECT_EQ(1, mIndex++);
+            ASSERT_NE(nullptr, state.computedState.clipState);
+            ASSERT_EQ(ClipMode::Rectangle, state.computedState.clipState->mode);
+            ASSERT_EQ(Rect(400, 400), state.computedState.clipState->rect);
+            EXPECT_TRUE(state.computedState.transform.isIdentity());
+        }
+    };
+    auto receiverBackground = TestUtils::createNode(0, 0, 400, 400,
+            [](RenderProperties& properties, RecordingCanvas& canvas) {
+        properties.setProjectionReceiver(true);
+        canvas.drawRect(0, 0, 400, 400, SkPaint());
+    });
+    auto projectingRipple = TestUtils::createNode(0, 0, 200, 200,
+            [](RenderProperties& properties, RecordingCanvas& canvas) {
+        // scroll doesn't apply to background, so undone via translationX/Y
+        // NOTE: translationX/Y only! no other transform properties may be set for a proj receiver!
+        properties.setTranslationX(scrollX);
+        properties.setTranslationY(scrollY);
+        properties.setProjectBackwards(true);
+        properties.setClipToBounds(false);
+        canvas.drawOval(0, 0, 200, 200, SkPaint());
+    });
+    auto child = TestUtils::createNode(0, 0, 400, 400,
+            [&projectingRipple](RenderProperties& properties, RecordingCanvas& canvas) {
+        // Record time clip will be ignored by projectee
+        canvas.clipRect(100, 100, 300, 300, SkRegion::kIntersect_Op);
+
+        canvas.translate(-scrollX, -scrollY); // Apply scroll (note: bg undoes this internally)
+        canvas.drawRenderNode(projectingRipple.get());
+    });
+    auto parent = TestUtils::createNode(0, 0, 400, 400,
+            [&receiverBackground, &child](RenderProperties& properties, RecordingCanvas& canvas) {
+        canvas.drawRenderNode(receiverBackground.get());
+        canvas.drawRenderNode(child.get());
+    });
+
+    FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(400, 400), 400, 400,
+            TestUtils::createSyncedNodeList(parent), sLightGeometry, nullptr);
+    ProjectionChildScrollTestRenderer renderer;
+    frameBuilder.replayBakedOps<TestDispatcher>(renderer);
+    EXPECT_EQ(2, renderer.getIndex());
+}
+
 // creates a 100x100 shadow casting node with provided translationZ
 static sp<RenderNode> createWhiteRectShadowCaster(float translationZ) {
     return TestUtils::createNode(0, 0, 100, 100,
diff --git a/libs/hwui/tests/unit/LinearAllocatorTests.cpp b/libs/hwui/tests/unit/LinearAllocatorTests.cpp
index 402a09c..ffcbf12 100644
--- a/libs/hwui/tests/unit/LinearAllocatorTests.cpp
+++ b/libs/hwui/tests/unit/LinearAllocatorTests.cpp
@@ -113,3 +113,21 @@
     EXPECT_GT(lastLocation + 20, &v[0]);
 
 }
+
+TEST(LsaVector, dtorCheck) {
+    LinearAllocator allocator;
+    LinearStdAllocator<void*> stdAllocator(allocator);
+
+    for (int size : {1, 2, 3, 500}) {
+        int destroyed = 0;
+        {
+            LsaVector<std::unique_ptr<TestUtils::SignalingDtor> > vector(stdAllocator);
+            for (int i = 0; i < size; i++) {
+                vector.emplace_back(new TestUtils::SignalingDtor(&destroyed));
+            }
+            EXPECT_EQ(0, destroyed);
+            EXPECT_EQ(size, (int) vector.size());
+        }
+        EXPECT_EQ(size, destroyed);
+    }
+}
diff --git a/libs/hwui/tests/unit/MatrixTests.cpp b/libs/hwui/tests/unit/MatrixTests.cpp
new file mode 100644
index 0000000..eddab87
--- /dev/null
+++ b/libs/hwui/tests/unit/MatrixTests.cpp
@@ -0,0 +1,50 @@
+/*
+ * 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 "Matrix.h"
+#include "Rect.h"
+
+using namespace android::uirenderer;
+
+TEST(Matrix, mapRect_emptyScaleSkew) {
+    // Skew, so we don't hit identity/translate/simple fast paths
+    Matrix4 scaleMatrix;
+    scaleMatrix.loadScale(10, 10, 1);
+    scaleMatrix.skew(0.1f, 0.1f);
+
+    // non-zero empty rect, so sorting x/y would make rect non-empty
+    Rect empty(15, 20, 15, 100);
+    ASSERT_TRUE(empty.isEmpty());
+    scaleMatrix.mapRect(empty);
+    EXPECT_EQ(Rect(170, 215, 250, 1015), empty);
+    EXPECT_FALSE(empty.isEmpty())
+        << "Empty 'line' rect doesn't remain empty when skewed.";
+}
+
+TEST(Matrix, mapRect_emptyRotate) {
+    // Skew, so we don't hit identity/translate/simple fast paths
+    Matrix4 skewMatrix;
+    skewMatrix.loadRotate(45);
+
+    // non-zero empty rect, so sorting x/y would make rect non-empty
+    Rect lineRect(0, 100);
+    ASSERT_TRUE(lineRect.isEmpty());
+    skewMatrix.mapRect(lineRect);
+    EXPECT_FALSE(lineRect.isEmpty())
+        << "Empty 'line' rect doesn't remain empty when rotated.";
+}
diff --git a/libs/hwui/tests/unit/OffscreenBufferPoolTests.cpp b/libs/hwui/tests/unit/OffscreenBufferPoolTests.cpp
index 2fd8795..0c6eb57 100644
--- a/libs/hwui/tests/unit/OffscreenBufferPoolTests.cpp
+++ b/libs/hwui/tests/unit/OffscreenBufferPoolTests.cpp
@@ -55,6 +55,14 @@
     });
 }
 
+TEST(OffscreenBuffer, dirty) {
+    TestUtils::runOnRenderThread([] (renderthread::RenderThread& thread) {
+        OffscreenBuffer buffer(thread.renderState(), Caches::getInstance(), 256u, 256u);
+        buffer.dirty(Rect(-100, -100, 100, 100));
+        EXPECT_EQ(android::Rect(100, 100), buffer.region.getBounds());
+    });
+}
+
 TEST(OffscreenBufferPool, construct) {
     TestUtils::runOnRenderThread([] (renderthread::RenderThread& thread) {
         OffscreenBufferPool pool;
diff --git a/libs/hwui/tests/unit/RecordingCanvasTests.cpp b/libs/hwui/tests/unit/RecordingCanvasTests.cpp
index f988da3..c3165bb 100644
--- a/libs/hwui/tests/unit/RecordingCanvasTests.cpp
+++ b/libs/hwui/tests/unit/RecordingCanvasTests.cpp
@@ -58,6 +58,17 @@
             << "Clip should be serialized once";
 }
 
+TEST(RecordingCanvas, emptyClipRect) {
+    auto dl = TestUtils::createDisplayList<RecordingCanvas>(200, 200, [](RecordingCanvas& canvas) {
+        canvas.save(SaveFlags::MatrixClip);
+        canvas.clipRect(0, 0, 100, 100, SkRegion::kIntersect_Op);
+        canvas.clipRect(100, 100, 200, 200, SkRegion::kIntersect_Op);
+        canvas.drawRect(0, 0, 50, 50, SkPaint()); // rejected at record time
+        canvas.restore();
+    });
+    ASSERT_EQ(0u, dl->getOps().size()) << "Must be zero ops. Rect should be rejected.";
+}
+
 TEST(RecordingCanvas, drawArc) {
     auto dl = TestUtils::createDisplayList<RecordingCanvas>(200, 200, [](RecordingCanvas& canvas) {
         canvas.drawArc(0, 0, 200, 200, 0, 180, true, SkPaint());
@@ -431,9 +442,7 @@
             // since the same clip will be computed at draw time. If such a change is made, this
             // check could be done at record time by querying the clip, or the clip could be altered
             // slightly so that it is serialized.
-            EXPECT_RECT_APPROX_EQ(Rect(58.57864, 58.57864, 341.42136, 341.42136),
-                    (reinterpret_cast<const ClipRect*>(op.localClip))->rect);
-
+            EXPECT_EQ(Rect(59, 59, 341, 341), op.localClip->rect);
             EXPECT_EQ(Rect(400, 400), op.unmappedBounds);
             expectedMatrix.loadIdentity();
             EXPECT_MATRIX_APPROX_EQ(expectedMatrix, op.localMatrix);
@@ -442,6 +451,21 @@
     EXPECT_EQ(3, count);
 }
 
+TEST(RecordingCanvas, drawRenderNode_rejection) {
+    auto child = TestUtils::createNode(50, 50, 150, 150,
+            [](RenderProperties& props, RecordingCanvas& canvas) {
+        SkPaint paint;
+        paint.setColor(SK_ColorWHITE);
+        canvas.drawRect(0, 0, 100, 100, paint);
+    });
+
+    auto dl = TestUtils::createDisplayList<RecordingCanvas>(200, 200, [&child](RecordingCanvas& canvas) {
+        canvas.clipRect(0, 0, 0, 0, SkRegion::kIntersect_Op); // empty clip, reject node
+        canvas.drawRenderNode(child.get()); // shouldn't crash when rejecting node...
+    });
+    ASSERT_TRUE(dl->isEmpty());
+}
+
 TEST(RecordingCanvas, drawRenderNode_projection) {
     sp<RenderNode> background = TestUtils::createNode(50, 50, 150, 150,
             [](RenderProperties& props, RecordingCanvas& canvas) {
diff --git a/libs/hwui/tests/unit/main.cpp b/libs/hwui/tests/unit/main.cpp
new file mode 100644
index 0000000..409a12d
--- /dev/null
+++ b/libs/hwui/tests/unit/main.cpp
@@ -0,0 +1,136 @@
+/*
+ * 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 "Caches.h"
+#include "thread/TaskManager.h"
+#include "tests/common/TestUtils.h"
+
+#include <memunreachable/memunreachable.h>
+
+#include <cstdio>
+#include <iostream>
+#include <map>
+#include <unordered_set>
+#include <signal.h>
+#include <unistd.h>
+
+using namespace std;
+using namespace android;
+using namespace android::uirenderer;
+
+static auto CRASH_SIGNALS = {
+        SIGABRT,
+        SIGSEGV,
+        SIGBUS,
+};
+
+static map<int, struct sigaction> gSigChain;
+
+static void gtestSigHandler(int sig, siginfo_t* siginfo, void* context) {
+    auto testinfo = ::testing::UnitTest::GetInstance()->current_test_info();
+    printf("[  FAILED  ] %s.%s\n", testinfo->test_case_name(),
+            testinfo->name());
+    printf("[  FATAL!  ] Process crashed, aborting tests!\n");
+    fflush(stdout);
+
+    // restore the default sighandler and re-raise
+    struct sigaction sa = gSigChain[sig];
+    sigaction(sig, &sa, nullptr);
+    raise(sig);
+}
+
+static void logUnreachable(initializer_list<UnreachableMemoryInfo> infolist) {
+    // merge them all
+    UnreachableMemoryInfo merged;
+    unordered_set<uintptr_t> addrs;
+    merged.allocation_bytes = 0;
+    merged.leak_bytes = 0;
+    merged.num_allocations = 0;
+    merged.num_leaks = 0;
+    for (auto& info : infolist) {
+        // We'll be a little hazzy about these ones and just hope the biggest
+        // is the most accurate
+        merged.allocation_bytes = max(merged.allocation_bytes, info.allocation_bytes);
+        merged.num_allocations = max(merged.num_allocations, info.num_allocations);
+        for (auto& leak : info.leaks) {
+             if (addrs.find(leak.begin) == addrs.end()) {
+                 merged.leaks.push_back(leak);
+                 merged.num_leaks++;
+                 merged.leak_bytes += leak.size;
+                 addrs.insert(leak.begin);
+             }
+        }
+    }
+
+    // Now log the result
+    if (merged.num_leaks) {
+        cout << endl << "Leaked memory!" << endl;
+        if (!merged.leaks[0].backtrace.num_frames) {
+            cout << "Re-run with 'setprop libc.debug.malloc.program hwui_unit_test'"
+                    << endl << "and 'setprop libc.debug.malloc.options backtrace=8'"
+                    << " to get backtraces" << endl;
+        }
+        cout << merged.ToString(false);
+    }
+}
+
+static void checkForLeaks() {
+    // TODO: Until we can shutdown the RT thread we need to do this in
+    // two passes as GetUnreachableMemory has limited insight into
+    // thread-local caches so some leaks will not be properly tagged as leaks
+    nsecs_t before = systemTime();
+    UnreachableMemoryInfo rtMemInfo;
+    TestUtils::runOnRenderThread([&rtMemInfo](renderthread::RenderThread& thread) {
+        if (Caches::hasInstance()) {
+            Caches::getInstance().tasks.stop();
+        }
+        // Check for leaks
+        if (!GetUnreachableMemory(rtMemInfo)) {
+            cerr << "Failed to get unreachable memory!" << endl;
+            return;
+        }
+    });
+    UnreachableMemoryInfo uiMemInfo;
+    if (!GetUnreachableMemory(uiMemInfo)) {
+        cerr << "Failed to get unreachable memory!" << endl;
+        return;
+    }
+    logUnreachable({rtMemInfo, uiMemInfo});
+    nsecs_t after = systemTime();
+    cout << "Leak check took " << ns2ms(after - before) << "ms" << endl;
+}
+
+int main(int argc, char* argv[]) {
+    // Register a crash handler
+    struct sigaction sa;
+    memset(&sa, 0, sizeof(sa));
+    sa.sa_sigaction = &gtestSigHandler;
+    sa.sa_flags = SA_SIGINFO;
+    for (auto sig : CRASH_SIGNALS) {
+        struct sigaction old_sa;
+        sigaction(sig, &sa, &old_sa);
+        gSigChain.insert(pair<int, struct sigaction>(sig, old_sa));
+    }
+
+    // Run the tests
+    testing::InitGoogleTest(&argc, argv);
+    int ret = RUN_ALL_TESTS();
+    checkForLeaks();
+    return ret;
+}
+
diff --git a/location/java/android/location/GnssClock.java b/location/java/android/location/GnssClock.java
index 3c8a78d..2af4790 100644
--- a/location/java/android/location/GnssClock.java
+++ b/location/java/android/location/GnssClock.java
@@ -16,6 +16,7 @@
 
 package android.location;
 
+import android.annotation.TestApi;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -26,51 +27,59 @@
 public final class GnssClock implements Parcelable {
     // The following enumerations must be in sync with the values declared in gps.h
 
-    private static final short HAS_NO_FLAGS = 0;
-    private static final short HAS_LEAP_SECOND = (1<<0);
-    private static final short HAS_TIME_UNCERTAINTY = (1<<1);
-    private static final short HAS_FULL_BIAS = (1<<2);
-    private static final short HAS_BIAS = (1<<3);
-    private static final short HAS_BIAS_UNCERTAINTY = (1<<4);
-    private static final short HAS_DRIFT = (1<<5);
-    private static final short HAS_DRIFT_UNCERTAINTY = (1<<6);
+    private static final int HAS_NO_FLAGS = 0;
+    private static final int HAS_LEAP_SECOND = (1<<0);
+    private static final int HAS_TIME_UNCERTAINTY = (1<<1);
+    private static final int HAS_FULL_BIAS = (1<<2);
+    private static final int HAS_BIAS = (1<<3);
+    private static final int HAS_BIAS_UNCERTAINTY = (1<<4);
+    private static final int HAS_DRIFT = (1<<5);
+    private static final int HAS_DRIFT_UNCERTAINTY = (1<<6);
 
     // End enumerations in sync with gps.h
 
-    private short mFlags;
-    private short mLeapSecond;
-    private long mTimeInNs;
-    private double mTimeUncertaintyInNs;
-    private long mFullBiasInNs;
-    private double mBiasInNs;
-    private double mBiasUncertaintyInNs;
-    private double mDriftInNsPerSec;
-    private double mDriftUncertaintyInNsPerSec;
+    private int mFlags;
+    private int mLeapSecond;
+    private long mTimeNanos;
+    private double mTimeUncertaintyNanos;
+    private long mFullBiasNanos;
+    private double mBiasNanos;
+    private double mBiasUncertaintyNanos;
+    private double mDriftNanosPerSecond;
+    private double mDriftUncertaintyNanosPerSecond;
     private int mHardwareClockDiscontinuityCount;
 
-    GnssClock() {
+    /**
+     * @hide
+     */
+    @TestApi
+    public GnssClock() {
         initialize();
     }
 
     /**
      * Sets all contents to the values stored in the provided object.
+     * @hide
      */
+    @TestApi
     public void set(GnssClock clock) {
         mFlags = clock.mFlags;
         mLeapSecond = clock.mLeapSecond;
-        mTimeInNs = clock.mTimeInNs;
-        mTimeUncertaintyInNs = clock.mTimeUncertaintyInNs;
-        mFullBiasInNs = clock.mFullBiasInNs;
-        mBiasInNs = clock.mBiasInNs;
-        mBiasUncertaintyInNs = clock.mBiasUncertaintyInNs;
-        mDriftInNsPerSec = clock.mDriftInNsPerSec;
-        mDriftUncertaintyInNsPerSec = clock.mDriftUncertaintyInNsPerSec;
+        mTimeNanos = clock.mTimeNanos;
+        mTimeUncertaintyNanos = clock.mTimeUncertaintyNanos;
+        mFullBiasNanos = clock.mFullBiasNanos;
+        mBiasNanos = clock.mBiasNanos;
+        mBiasUncertaintyNanos = clock.mBiasUncertaintyNanos;
+        mDriftNanosPerSecond = clock.mDriftNanosPerSecond;
+        mDriftUncertaintyNanosPerSecond = clock.mDriftUncertaintyNanosPerSecond;
         mHardwareClockDiscontinuityCount = clock.mHardwareClockDiscontinuityCount;
     }
 
     /**
      * Resets all the contents to its original state.
+     * @hide
      */
+    @TestApi
     public void reset() {
         initialize();
     }
@@ -89,24 +98,28 @@
      *
      * The value is only available if {@link #hasLeapSecond()} is true.
      */
-    public short getLeapSecond() {
+    public int getLeapSecond() {
         return mLeapSecond;
     }
 
     /**
      * Sets the leap second associated with the clock's time.
+     * @hide
      */
-    public void setLeapSecond(short leapSecond) {
+    @TestApi
+    public void setLeapSecond(int leapSecond) {
         setFlag(HAS_LEAP_SECOND);
         mLeapSecond = leapSecond;
     }
 
     /**
      * Resets the leap second associated with the clock's time.
+     * @hide
      */
+    @TestApi
     public void resetLeapSecond() {
         resetFlag(HAS_LEAP_SECOND);
-        mLeapSecond = Short.MIN_VALUE;
+        mLeapSecond = Integer.MIN_VALUE;
     }
 
     /**
@@ -114,30 +127,32 @@
      *
      * For 'local hardware clock' this value is expected to be monotonically increasing during the
      * reporting session. The real GPS time can be derived by compensating
-     * {@link #getFullBiasInNs()} (when it is available) from this value.
+     * {@link #getFullBiasNanos()} (when it is available) from this value.
      *
      * For 'GPS time' this value is expected to be the best estimation of current GPS time that GPS
-     * receiver can achieve. {@link #getTimeUncertaintyInNs()} should be available when GPS time is
+     * receiver can achieve. {@link #getTimeUncertaintyNanos()} should be available when GPS time is
      * specified.
      *
-     * Sub-nanosecond accuracy can be provided by means of {@link #getBiasInNs()}.
-     * The reported time includes {@link #getTimeUncertaintyInNs()}.
+     * Sub-nanosecond accuracy can be provided by means of {@link #getBiasNanos()}.
+     * The reported time includes {@link #getTimeUncertaintyNanos()}.
      */
-    public long getTimeInNs() {
-        return mTimeInNs;
+    public long getTimeNanos() {
+        return mTimeNanos;
     }
 
     /**
-     * Sets the GPS receiver internal clock in nanoseconds.
+     * Sets the GNSS receiver internal clock in nanoseconds.
+     * @hide
      */
-    public void setTimeInNs(long timeInNs) {
-        mTimeInNs = timeInNs;
+    @TestApi
+    public void setTimeNanos(long timeNanos) {
+        mTimeNanos = timeNanos;
     }
 
     /**
-     * Returns true if {@link #getTimeUncertaintyInNs()} is available, false otherwise.
+     * Returns true if {@link #getTimeUncertaintyNanos()} is available, false otherwise.
      */
-    public boolean hasTimeUncertaintyInNs() {
+    public boolean hasTimeUncertaintyNanos() {
         return isFlagSet(HAS_TIME_UNCERTAINTY);
     }
 
@@ -145,189 +160,211 @@
      * Gets the clock's time Uncertainty (1-Sigma) in nanoseconds.
      * The uncertainty is represented as an absolute (single sided) value.
      *
-     * The value is only available if {@link #hasTimeUncertaintyInNs()} is true.
+     * The value is only available if {@link #hasTimeUncertaintyNanos()} is true.
      */
-    public double getTimeUncertaintyInNs() {
-        return mTimeUncertaintyInNs;
+    public double getTimeUncertaintyNanos() {
+        return mTimeUncertaintyNanos;
     }
 
     /**
      * Sets the clock's Time Uncertainty (1-Sigma) in nanoseconds.
+     * @hide
      */
-    public void setTimeUncertaintyInNs(double timeUncertaintyInNs) {
+    @TestApi
+    public void setTimeUncertaintyNanos(double timeUncertaintyNanos) {
         setFlag(HAS_TIME_UNCERTAINTY);
-        mTimeUncertaintyInNs = timeUncertaintyInNs;
+        mTimeUncertaintyNanos = timeUncertaintyNanos;
     }
 
     /**
      * Resets the clock's Time Uncertainty (1-Sigma) in nanoseconds.
+     * @hide
      */
-    public void resetTimeUncertaintyInNs() {
+    @TestApi
+    public void resetTimeUncertaintyNanos() {
         resetFlag(HAS_TIME_UNCERTAINTY);
-        mTimeUncertaintyInNs = Double.NaN;
+        mTimeUncertaintyNanos = Double.NaN;
     }
 
     /**
-     * Returns true if {@link #getFullBiasInNs()} is available, false otherwise.
+     * Returns true if {@link #getFullBiasNanos()} is available, false otherwise.
      */
-    public boolean hasFullBiasInNs() {
+    public boolean hasFullBiasNanos() {
         return isFlagSet(HAS_FULL_BIAS);
     }
 
     /**
-     * Gets the difference between hardware clock ({@link #getTimeInNs()}) inside GPS receiver and
+     * Gets the difference between hardware clock ({@link #getTimeNanos()}) inside GPS receiver and
      * the true GPS time since 0000Z, January 6, 1980, in nanoseconds.
      *
      * This value is available if the receiver has estimated GPS time. If the computed time is for a
      * non-GPS constellation, the time offset of that constellation to GPS has to be applied to fill
-     * this value. The value contains the 'bias uncertainty' {@link #getBiasUncertaintyInNs()} in
+     * this value. The value contains the 'bias uncertainty' {@link #getBiasUncertaintyNanos()} in
      * it, and it should be used for quality check. The value is only available if
-     * {@link #hasFullBiasInNs()} is true.
+     * {@link #hasFullBiasNanos()} is true.
      *
      * The sign of the value is defined by the following equation:
      *      local estimate of GPS time = time_ns + (full_bias_ns + bias_ns)
      */
-    public long getFullBiasInNs() {
-        return mFullBiasInNs;
+    public long getFullBiasNanos() {
+        return mFullBiasNanos;
     }
 
     /**
      * Sets the full bias in nanoseconds.
+     * @hide
      */
-    public void setFullBiasInNs(long value) {
+    @TestApi
+    public void setFullBiasNanos(long value) {
         setFlag(HAS_FULL_BIAS);
-        mFullBiasInNs = value;
+        mFullBiasNanos = value;
     }
 
     /**
      * Resets the full bias in nanoseconds.
+     * @hide
      */
-    public void resetFullBiasInNs() {
+    @TestApi
+    public void resetFullBiasNanos() {
         resetFlag(HAS_FULL_BIAS);
-        mFullBiasInNs = Long.MIN_VALUE;
+        mFullBiasNanos = Long.MIN_VALUE;
     }
 
     /**
-     * Returns true if {@link #getBiasInNs()} is available, false otherwise.
+     * Returns true if {@link #getBiasNanos()} is available, false otherwise.
      */
-    public boolean hasBiasInNs() {
+    public boolean hasBiasNanos() {
         return isFlagSet(HAS_BIAS);
     }
 
     /**
      * Gets the clock's sub-nanosecond bias.
-     * The reported bias includes {@link #getBiasUncertaintyInNs()}.
+     * The reported bias includes {@link #getBiasUncertaintyNanos()}.
      *
-     * The value is only available if {@link #hasBiasInNs()} is true.
+     * The value is only available if {@link #hasBiasNanos()} is true.
      */
-    public double getBiasInNs() {
-        return mBiasInNs;
+    public double getBiasNanos() {
+        return mBiasNanos;
     }
 
     /**
      * Sets the sub-nanosecond bias.
+     * @hide
      */
-    public void setBiasInNs(double biasInNs) {
+    @TestApi
+    public void setBiasNanos(double biasNanos) {
         setFlag(HAS_BIAS);
-        mBiasInNs = biasInNs;
+        mBiasNanos = biasNanos;
     }
 
     /**
      * Resets the clock's Bias in nanoseconds.
+     * @hide
      */
-    public void resetBiasInNs() {
+    @TestApi
+    public void resetBiasNanos() {
         resetFlag(HAS_BIAS);
-        mBiasInNs = Double.NaN;
+        mBiasNanos = Double.NaN;
     }
 
     /**
-     * Returns true if {@link #getBiasUncertaintyInNs()} is available, false otherwise.
+     * Returns true if {@link #getBiasUncertaintyNanos()} is available, false otherwise.
      */
-    public boolean hasBiasUncertaintyInNs() {
+    public boolean hasBiasUncertaintyNanos() {
         return isFlagSet(HAS_BIAS_UNCERTAINTY);
     }
 
     /**
      * Gets the clock's Bias Uncertainty (1-Sigma) in nanoseconds.
      *
-     * The value is only available if {@link #hasBiasUncertaintyInNs()} is true.
+     * The value is only available if {@link #hasBiasUncertaintyNanos()} is true.
      */
-    public double getBiasUncertaintyInNs() {
-        return mBiasUncertaintyInNs;
+    public double getBiasUncertaintyNanos() {
+        return mBiasUncertaintyNanos;
     }
 
     /**
      * Sets the clock's Bias Uncertainty (1-Sigma) in nanoseconds.
+     * @hide
      */
-    public void setBiasUncertaintyInNs(double biasUncertaintyInNs) {
+    @TestApi
+    public void setBiasUncertaintyNanos(double biasUncertaintyNanos) {
         setFlag(HAS_BIAS_UNCERTAINTY);
-        mBiasUncertaintyInNs = biasUncertaintyInNs;
+        mBiasUncertaintyNanos = biasUncertaintyNanos;
     }
 
     /**
      * Resets the clock's Bias Uncertainty (1-Sigma) in nanoseconds.
+     * @hide
      */
-    public void resetBiasUncertaintyInNs() {
+    @TestApi
+    public void resetBiasUncertaintyNanos() {
         resetFlag(HAS_BIAS_UNCERTAINTY);
-        mBiasUncertaintyInNs = Double.NaN;
+        mBiasUncertaintyNanos = Double.NaN;
     }
 
     /**
-     * Returns true if {@link #getDriftInNsPerSec()} is available, false otherwise.
+     * Returns true if {@link #getDriftNanosPerSecond()} is available, false otherwise.
      */
-    public boolean hasDriftInNsPerSec() {
+    public boolean hasDriftNanosPerSecond() {
         return isFlagSet(HAS_DRIFT);
     }
 
     /**
      * Gets the clock's Drift in nanoseconds per second.
      * A positive value indicates that the frequency is higher than the nominal frequency.
-     * The reported drift includes {@link #getDriftUncertaintyInNsPerSec()}.
+     * The reported drift includes {@link #getDriftUncertaintyNanosPerSecond()}.
      *
-     * The value is only available if {@link #hasDriftInNsPerSec()} is true.
+     * The value is only available if {@link #hasDriftNanosPerSecond()} is true.
      */
-    public double getDriftInNsPerSec() {
-        return mDriftInNsPerSec;
+    public double getDriftNanosPerSecond() {
+        return mDriftNanosPerSecond;
     }
 
     /**
      * Sets the clock's Drift in nanoseconds per second.
+     * @hide
      */
-    public void setDriftInNsPerSec(double driftInNsPerSec) {
+    @TestApi
+    public void setDriftNanosPerSecond(double driftNanosPerSecond) {
         setFlag(HAS_DRIFT);
-        mDriftInNsPerSec = driftInNsPerSec;
+        mDriftNanosPerSecond = driftNanosPerSecond;
     }
 
     /**
      * Resets the clock's Drift in nanoseconds per second.
+     * @hide
      */
-    public void resetDriftInNsPerSec() {
+    @TestApi
+    public void resetDriftNanosPerSecond() {
         resetFlag(HAS_DRIFT);
-        mDriftInNsPerSec = Double.NaN;
+        mDriftNanosPerSecond = Double.NaN;
     }
 
     /**
-     * Returns true if {@link #getDriftUncertaintyInNsPerSec()} is available, false otherwise.
+     * Returns true if {@link #getDriftUncertaintyNanosPerSecond()} is available, false otherwise.
      */
-    public boolean hasDriftUncertaintyInNsPerSec() {
+    public boolean hasDriftUncertaintyNanosPerSecond() {
         return isFlagSet(HAS_DRIFT_UNCERTAINTY);
     }
 
     /**
      * Gets the clock's Drift Uncertainty (1-Sigma) in nanoseconds per second.
      *
-     * The value is only available if {@link #hasDriftUncertaintyInNsPerSec()} is true.
+     * The value is only available if {@link #hasDriftUncertaintyNanosPerSecond()} is true.
      */
-    public double getDriftUncertaintyInNsPerSec() {
-        return mDriftUncertaintyInNsPerSec;
+    public double getDriftUncertaintyNanosPerSecond() {
+        return mDriftUncertaintyNanosPerSecond;
     }
 
     /**
      * Sets the clock's Drift Uncertainty (1-Sigma) in nanoseconds per second.
+     * @hide
      */
-    public void setDriftUncertaintyInNsPerSec(double driftUncertaintyInNsPerSec) {
+    @TestApi
+    public void setDriftUncertaintyNanosPerSecond(double driftUncertaintyNanosPerSecond) {
         setFlag(HAS_DRIFT_UNCERTAINTY);
-        mDriftUncertaintyInNsPerSec = driftUncertaintyInNsPerSec;
+        mDriftUncertaintyNanosPerSecond = driftUncertaintyNanosPerSecond;
     }
 
     /**
@@ -339,17 +376,21 @@
 
     /**
      * Sets count of last hardware clock discontinuity.
+     * @hide
      */
+    @TestApi
     public void setHardwareClockDiscontinuityCount(int value) {
         mHardwareClockDiscontinuityCount = value;
     }
 
     /**
      * Resets the clock's Drift Uncertainty (1-Sigma) in nanoseconds per second.
+     * @hide
      */
-    public void resetDriftUncertaintyInNsPerSec() {
+    @TestApi
+    public void resetDriftUncertaintyNanosPerSecond() {
         resetFlag(HAS_DRIFT_UNCERTAINTY);
-        mDriftUncertaintyInNsPerSec = Double.NaN;
+        mDriftUncertaintyNanosPerSecond = Double.NaN;
     }
 
     public static final Creator<GnssClock> CREATOR = new Creator<GnssClock>() {
@@ -357,15 +398,15 @@
         public GnssClock createFromParcel(Parcel parcel) {
             GnssClock gpsClock = new GnssClock();
 
-            gpsClock.mFlags = (short) parcel.readInt();
-            gpsClock.mLeapSecond = (short) parcel.readInt();
-            gpsClock.mTimeInNs = parcel.readLong();
-            gpsClock.mTimeUncertaintyInNs = parcel.readDouble();
-            gpsClock.mFullBiasInNs = parcel.readLong();
-            gpsClock.mBiasInNs = parcel.readDouble();
-            gpsClock.mBiasUncertaintyInNs = parcel.readDouble();
-            gpsClock.mDriftInNsPerSec = parcel.readDouble();
-            gpsClock.mDriftUncertaintyInNsPerSec = parcel.readDouble();
+            gpsClock.mFlags = parcel.readInt();
+            gpsClock.mLeapSecond = parcel.readInt();
+            gpsClock.mTimeNanos = parcel.readLong();
+            gpsClock.mTimeUncertaintyNanos = parcel.readDouble();
+            gpsClock.mFullBiasNanos = parcel.readLong();
+            gpsClock.mBiasNanos = parcel.readDouble();
+            gpsClock.mBiasUncertaintyNanos = parcel.readDouble();
+            gpsClock.mDriftNanosPerSecond = parcel.readDouble();
+            gpsClock.mDriftUncertaintyNanosPerSecond = parcel.readDouble();
             gpsClock.mHardwareClockDiscontinuityCount = parcel.readInt();
 
             return gpsClock;
@@ -381,13 +422,13 @@
     public void writeToParcel(Parcel parcel, int flags) {
         parcel.writeInt(mFlags);
         parcel.writeInt(mLeapSecond);
-        parcel.writeLong(mTimeInNs);
-        parcel.writeDouble(mTimeUncertaintyInNs);
-        parcel.writeLong(mFullBiasInNs);
-        parcel.writeDouble(mBiasInNs);
-        parcel.writeDouble(mBiasUncertaintyInNs);
-        parcel.writeDouble(mDriftInNsPerSec);
-        parcel.writeDouble(mDriftUncertaintyInNsPerSec);
+        parcel.writeLong(mTimeNanos);
+        parcel.writeDouble(mTimeUncertaintyNanos);
+        parcel.writeLong(mFullBiasNanos);
+        parcel.writeDouble(mBiasNanos);
+        parcel.writeDouble(mBiasUncertaintyNanos);
+        parcel.writeDouble(mDriftNanosPerSecond);
+        parcel.writeDouble(mDriftUncertaintyNanosPerSecond);
         parcel.writeInt(mHardwareClockDiscontinuityCount);
     }
 
@@ -406,29 +447,29 @@
 
         builder.append(String.format(
                 formatWithUncertainty,
-                "TimeInNs",
-                mTimeInNs,
-                "TimeUncertaintyInNs",
-                hasTimeUncertaintyInNs() ? mTimeUncertaintyInNs : null));
+                "TimeNanos",
+                mTimeNanos,
+                "TimeUncertaintyNanos",
+                hasTimeUncertaintyNanos() ? mTimeUncertaintyNanos : null));
 
         builder.append(String.format(
                 format,
-                "FullBiasInNs",
-                hasFullBiasInNs() ? mFullBiasInNs : null));
+                "FullBiasNanos",
+                hasFullBiasNanos() ? mFullBiasNanos : null));
 
         builder.append(String.format(
                 formatWithUncertainty,
-                "BiasInNs",
-                hasBiasInNs() ? mBiasInNs : null,
-                "BiasUncertaintyInNs",
-                hasBiasUncertaintyInNs() ? mBiasUncertaintyInNs : null));
+                "BiasNanos",
+                hasBiasNanos() ? mBiasNanos : null,
+                "BiasUncertaintyNanos",
+                hasBiasUncertaintyNanos() ? mBiasUncertaintyNanos : null));
 
         builder.append(String.format(
                 formatWithUncertainty,
-                "DriftInNsPerSec",
-                hasDriftInNsPerSec() ? mDriftInNsPerSec : null,
-                "DriftUncertaintyInNsPerSec",
-                hasDriftUncertaintyInNsPerSec() ? mDriftUncertaintyInNsPerSec : null));
+                "DriftNanosPerSecond",
+                hasDriftNanosPerSecond() ? mDriftNanosPerSecond : null,
+                "DriftUncertaintyNanosPerSecond",
+                hasDriftUncertaintyNanosPerSecond() ? mDriftUncertaintyNanosPerSecond : null));
 
         return builder.toString();
     }
@@ -436,25 +477,25 @@
     private void initialize() {
         mFlags = HAS_NO_FLAGS;
         resetLeapSecond();
-        setTimeInNs(Long.MIN_VALUE);
-        resetTimeUncertaintyInNs();
-        resetFullBiasInNs();
-        resetBiasInNs();
-        resetBiasUncertaintyInNs();
-        resetDriftInNsPerSec();
-        resetDriftUncertaintyInNsPerSec();
+        setTimeNanos(Long.MIN_VALUE);
+        resetTimeUncertaintyNanos();
+        resetFullBiasNanos();
+        resetBiasNanos();
+        resetBiasUncertaintyNanos();
+        resetDriftNanosPerSecond();
+        resetDriftUncertaintyNanosPerSecond();
         setHardwareClockDiscontinuityCount(Integer.MIN_VALUE);
     }
 
-    private void setFlag(short flag) {
+    private void setFlag(int flag) {
         mFlags |= flag;
     }
 
-    private void resetFlag(short flag) {
+    private void resetFlag(int flag) {
         mFlags &= ~flag;
     }
 
-    private boolean isFlagSet(short flag) {
+    private boolean isFlagSet(int flag) {
         return (mFlags & flag) == flag;
     }
 }
diff --git a/location/java/android/location/GnssMeasurement.java b/location/java/android/location/GnssMeasurement.java
index abdc13c..11fecfb 100644
--- a/location/java/android/location/GnssMeasurement.java
+++ b/location/java/android/location/GnssMeasurement.java
@@ -16,6 +16,7 @@
 
 package android.location;
 
+import android.annotation.TestApi;
 import android.annotation.IntDef;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -28,81 +29,34 @@
  */
 public final class GnssMeasurement implements Parcelable {
     private int mFlags;
-    private short mSvid;
-    private byte mConstellationType;
-    private double mTimeOffsetInNs;
-    private short mState;
-    private long mReceivedSvTimeInNs;
-    private long mReceivedSvTimeUncertaintyInNs;
-    private double mCn0InDbHz;
-    private double mPseudorangeRateInMetersPerSec;
-    private double mPseudorangeRateUncertaintyInMetersPerSec;
-    private short mAccumulatedDeltaRangeState;
-    private double mAccumulatedDeltaRangeInMeters;
-    private double mAccumulatedDeltaRangeUncertaintyInMeters;
-    private double mPseudorangeInMeters;
-    private double mPseudorangeUncertaintyInMeters;
-    private double mCodePhaseInChips;
-    private double mCodePhaseUncertaintyInChips;
-    private float mCarrierFrequencyInHz;
+    private int mSvid;
+    private int mConstellationType;
+    private double mTimeOffsetNanos;
+    private int mState;
+    private long mReceivedSvTimeNanos;
+    private long mReceivedSvTimeUncertaintyNanos;
+    private double mCn0DbHz;
+    private double mPseudorangeRateMetersPerSecond;
+    private double mPseudorangeRateUncertaintyMetersPerSecond;
+    private int mAccumulatedDeltaRangeState;
+    private double mAccumulatedDeltaRangeMeters;
+    private double mAccumulatedDeltaRangeUncertaintyMeters;
+    private float mCarrierFrequencyHz;
     private long mCarrierCycles;
     private double mCarrierPhase;
     private double mCarrierPhaseUncertainty;
-    private byte mLossOfLock;
-    private int mBitNumber;
-    private short mTimeFromLastBitInMs;
-    private double mDopplerShiftInHz;
-    private double mDopplerShiftUncertaintyInHz;
-    private byte mMultipathIndicator;
+    private int mMultipathIndicator;
     private double mSnrInDb;
-    private double mElevationInDeg;
-    private double mElevationUncertaintyInDeg;
-    private double mAzimuthInDeg;
-    private double mAzimuthUncertaintyInDeg;
-    private boolean mUsedInFix;
+    private boolean mPseudorangeRateCorrected;
 
     // The following enumerations must be in sync with the values declared in gps.h
 
     private static final int HAS_NO_FLAGS = 0;
     private static final int HAS_SNR = (1<<0);
-    private static final int HAS_ELEVATION = (1<<1);
-    private static final int HAS_ELEVATION_UNCERTAINTY = (1<<2);
-    private static final int HAS_AZIMUTH = (1<<3);
-    private static final int HAS_AZIMUTH_UNCERTAINTY = (1<<4);
-    private static final int HAS_PSEUDORANGE = (1<<5);
-    private static final int HAS_PSEUDORANGE_UNCERTAINTY = (1<<6);
-    private static final int HAS_CODE_PHASE = (1<<7);
-    private static final int HAS_CODE_PHASE_UNCERTAINTY = (1<<8);
     private static final int HAS_CARRIER_FREQUENCY = (1<<9);
     private static final int HAS_CARRIER_CYCLES = (1<<10);
     private static final int HAS_CARRIER_PHASE = (1<<11);
     private static final int HAS_CARRIER_PHASE_UNCERTAINTY = (1<<12);
-    private static final int HAS_BIT_NUMBER = (1<<13);
-    private static final int HAS_TIME_FROM_LAST_BIT = (1<<14);
-    private static final int HAS_DOPPLER_SHIFT = (1<<15);
-    private static final int HAS_DOPPLER_SHIFT_UNCERTAINTY = (1<<16);
-    // private static final int HAS_USED_IN_FIX = (1<<17);
-    private static final int HAS_UNCORRECTED_PSEUDORANGE_RATE = (1<<18);
-
-    /** The status of 'loss of lock'. */
-    @Retention(RetentionPolicy.SOURCE)
-    @IntDef({LOSS_OF_LOCK_UNKNOWN, LOSS_OF_LOCK_OK, LOSS_OF_LOCK_CYCLE_SLIP})
-    public @interface LossOfLockStatus {}
-
-    /**
-     * The indicator is not available or it is unknown.
-     */
-    public static final byte LOSS_OF_LOCK_UNKNOWN = 0;
-
-    /**
-     * The measurement does not present any indication of 'loss of lock'.
-     */
-    public static final byte LOSS_OF_LOCK_OK = 1;
-
-    /**
-     * 'Loss of lock' detected between the previous and current observation: cycle slip possible.
-     */
-    public static final byte LOSS_OF_LOCK_CYCLE_SLIP = 2;
 
     /** The status of multipath. */
     @Retention(RetentionPolicy.SOURCE)
@@ -113,129 +67,123 @@
     /**
      * The indicator is not available or it is unknown.
      */
-    public static final byte MULTIPATH_INDICATOR_UNKNOWN = 0;
+    public static final int MULTIPATH_INDICATOR_UNKNOWN = 0;
 
     /**
      * The measurement has been indicated to use multi-path.
      */
-    public static final byte MULTIPATH_INDICATOR_DETECTED = 1;
+    public static final int MULTIPATH_INDICATOR_DETECTED = 1;
 
     /**
      * The measurement has been indicated not tu use multi-path.
      */
-    public static final byte MULTIPATH_INDICATOR_NOT_USED = 2;
+    public static final int MULTIPATH_INDICATOR_NOT_USED = 2;
 
     /**
      * The state of GNSS receiver the measurement is invalid or unknown.
      */
-    public static final short STATE_UNKNOWN = 0;
+    public static final int STATE_UNKNOWN = 0;
 
     /**
      * The state of the GNSS receiver is ranging code lock.
      */
-    public static final short STATE_CODE_LOCK = (1<<0);
+    public static final int STATE_CODE_LOCK = (1<<0);
 
     /**
      * The state of the GNSS receiver is in bit sync.
      */
-    public static final short STATE_BIT_SYNC = (1<<1);
+    public static final int STATE_BIT_SYNC = (1<<1);
 
     /**
      *The state of the GNSS receiver is in sub-frame sync.
      */
-    public static final short STATE_SUBFRAME_SYNC = (1<<2);
+    public static final int STATE_SUBFRAME_SYNC = (1<<2);
 
     /**
      * The state of the GNSS receiver has TOW decoded.
      */
-    public static final short STATE_TOW_DECODED = (1<<3);
+    public static final int STATE_TOW_DECODED = (1<<3);
 
     /**
      * The state of the GNSS receiver contains millisecond ambiguity.
      */
-    public static final short STATE_MSEC_AMBIGUOUS = (1<<4);
+    public static final int STATE_MSEC_AMBIGUOUS = (1<<4);
 
     /**
      * All the GNSS receiver state flags.
      */
-    private static final short STATE_ALL = STATE_CODE_LOCK | STATE_BIT_SYNC | STATE_SUBFRAME_SYNC
+    private static final int STATE_ALL = STATE_CODE_LOCK | STATE_BIT_SYNC | STATE_SUBFRAME_SYNC
             | STATE_TOW_DECODED | STATE_MSEC_AMBIGUOUS;
 
     /**
      * The state of the 'Accumulated Delta Range' is invalid or unknown.
      */
-    public static final short ADR_STATE_UNKNOWN = 0;
+    public static final int ADR_STATE_UNKNOWN = 0;
 
     /**
      * The state of the 'Accumulated Delta Range' is valid.
      */
-    public static final short ADR_STATE_VALID = (1<<0);
+    public static final int ADR_STATE_VALID = (1<<0);
 
     /**
      * The state of the 'Accumulated Delta Range' has detected a reset.
      */
-    public static final short ADR_STATE_RESET = (1<<1);
+    public static final int ADR_STATE_RESET = (1<<1);
 
     /**
      * The state of the 'Accumulated Delta Range' has a cycle slip detected.
      */
-    public static final short ADR_STATE_CYCLE_SLIP = (1<<2);
+    public static final int ADR_STATE_CYCLE_SLIP = (1<<2);
 
     /**
      * All the 'Accumulated Delta Range' flags.
      */
-    private static final short ADR_ALL = ADR_STATE_VALID | ADR_STATE_RESET | ADR_STATE_CYCLE_SLIP;
+    private static final int ADR_ALL = ADR_STATE_VALID | ADR_STATE_RESET | ADR_STATE_CYCLE_SLIP;
 
     // End enumerations in sync with gps.h
 
-    GnssMeasurement() {
+    /**
+     * @hide
+     */
+    @TestApi
+    public GnssMeasurement() {
         initialize();
     }
 
     /**
      * Sets all contents to the values stored in the provided object.
+     * @hide
      */
+    @TestApi
     public void set(GnssMeasurement measurement) {
         mFlags = measurement.mFlags;
         mSvid = measurement.mSvid;
         mConstellationType = measurement.mConstellationType;
-        mTimeOffsetInNs = measurement.mTimeOffsetInNs;
+        mTimeOffsetNanos = measurement.mTimeOffsetNanos;
         mState = measurement.mState;
-        mReceivedSvTimeInNs = measurement.mReceivedSvTimeInNs;
-        mReceivedSvTimeUncertaintyInNs = measurement.mReceivedSvTimeUncertaintyInNs;
-        mCn0InDbHz = measurement.mCn0InDbHz;
-        mPseudorangeRateInMetersPerSec = measurement.mPseudorangeRateInMetersPerSec;
-        mPseudorangeRateUncertaintyInMetersPerSec =
-                measurement.mPseudorangeRateUncertaintyInMetersPerSec;
+        mReceivedSvTimeNanos = measurement.mReceivedSvTimeNanos;
+        mReceivedSvTimeUncertaintyNanos = measurement.mReceivedSvTimeUncertaintyNanos;
+        mCn0DbHz = measurement.mCn0DbHz;
+        mPseudorangeRateMetersPerSecond = measurement.mPseudorangeRateMetersPerSecond;
+        mPseudorangeRateUncertaintyMetersPerSecond =
+                measurement.mPseudorangeRateUncertaintyMetersPerSecond;
         mAccumulatedDeltaRangeState = measurement.mAccumulatedDeltaRangeState;
-        mAccumulatedDeltaRangeInMeters = measurement.mAccumulatedDeltaRangeInMeters;
-        mAccumulatedDeltaRangeUncertaintyInMeters =
-                measurement.mAccumulatedDeltaRangeUncertaintyInMeters;
-        mPseudorangeInMeters = measurement.mPseudorangeInMeters;
-        mPseudorangeUncertaintyInMeters = measurement.mPseudorangeUncertaintyInMeters;
-        mCodePhaseInChips = measurement.mCodePhaseInChips;
-        mCodePhaseUncertaintyInChips = measurement.mCodePhaseUncertaintyInChips;
-        mCarrierFrequencyInHz = measurement.mCarrierFrequencyInHz;
+        mAccumulatedDeltaRangeMeters = measurement.mAccumulatedDeltaRangeMeters;
+        mAccumulatedDeltaRangeUncertaintyMeters =
+                measurement.mAccumulatedDeltaRangeUncertaintyMeters;
+        mCarrierFrequencyHz = measurement.mCarrierFrequencyHz;
         mCarrierCycles = measurement.mCarrierCycles;
         mCarrierPhase = measurement.mCarrierPhase;
         mCarrierPhaseUncertainty = measurement.mCarrierPhaseUncertainty;
-        mLossOfLock = measurement.mLossOfLock;
-        mBitNumber = measurement.mBitNumber;
-        mTimeFromLastBitInMs = measurement.mTimeFromLastBitInMs;
-        mDopplerShiftInHz = measurement.mDopplerShiftInHz;
-        mDopplerShiftUncertaintyInHz = measurement.mDopplerShiftUncertaintyInHz;
         mMultipathIndicator = measurement.mMultipathIndicator;
         mSnrInDb = measurement.mSnrInDb;
-        mElevationInDeg = measurement.mElevationInDeg;
-        mElevationUncertaintyInDeg = measurement.mElevationUncertaintyInDeg;
-        mAzimuthInDeg = measurement.mAzimuthInDeg;
-        mAzimuthUncertaintyInDeg = measurement.mAzimuthUncertaintyInDeg;
-        mUsedInFix = measurement.mUsedInFix;
     }
 
     /**
      * Resets all the contents to its original state.
+     * @hide
      */
+    @TestApi
     public void reset() {
         initialize();
     }
@@ -244,14 +192,16 @@
      * Gets the Pseudo-random number (PRN).
      * Range: [1, 32]
      */
-    public short getSvid() {
+    public int getSvid() {
         return mSvid;
     }
 
     /**
      * Sets the Pseud-random number (PRN).
+     * @hide
      */
-    public void setSvid(short value) {
+    @TestApi
+    public void setSvid(int value) {
         mSvid = value;
     }
 
@@ -259,14 +209,16 @@
      * Getst the constellation type.
      */
     @GnssStatus.ConstellationType
-    public byte getConstellationType() {
+    public int getConstellationType() {
         return mConstellationType;
     }
 
     /**
      * Sets the constellation type.
+     * @hide
      */
-    public void setConstellationType(@GnssStatus.ConstellationType byte value) {
+    @TestApi
+    public void setConstellationType(@GnssStatus.ConstellationType int value) {
         mConstellationType = value;
     }
 
@@ -274,7 +226,7 @@
      * Gets the time offset at which the measurement was taken in nanoseconds.
      *
      * The reference receiver's time from which this is offset is specified by
-     * {@link GnssClock#getTimeInNs()}.
+     * {@link GnssClock#getTimeNanos()}.
      *
      * The sign of this value is given by the following equation:
      *      measurement time = time_ns + time_offset_ns
@@ -282,31 +234,35 @@
      * The value provides an individual time-stamp for the measurement, and allows sub-nanosecond
      * accuracy.
      */
-    public double getTimeOffsetInNs() {
-        return mTimeOffsetInNs;
+    public double getTimeOffsetNanos() {
+        return mTimeOffsetNanos;
     }
 
     /**
      * Sets the time offset at which the measurement was taken in nanoseconds.
+     * @hide
      */
-    public void setTimeOffsetInNs(double value) {
-        mTimeOffsetInNs = value;
+    @TestApi
+    public void setTimeOffsetNanos(double value) {
+        mTimeOffsetNanos = value;
     }
 
     /**
      * Gets per-satellite sync state.
      * It represents the current sync state for the associated satellite.
      *
-     * This value helps interpret {@link #getReceivedSvTimeInNs()}.
+     * This value helps interpret {@link #getReceivedSvTimeNanos()}.
      */
-    public short getState() {
+    public int getState() {
         return mState;
     }
 
     /**
      * Sets the sync state.
+     * @hide
      */
-    public void setState(short value) {
+    @TestApi
+    public void setState(int value) {
         mState = value;
     }
 
@@ -408,29 +364,33 @@
      *     Symbol sync     : [ 0   2ms ]   : STATE_SYMBOL_SYNC is set
      *     Message         : [ 0    1s ]   : STATE_SBAS_SYNC is set
      */
-    public long getReceivedSvTimeInNs() {
-        return mReceivedSvTimeInNs;
+    public long getReceivedSvTimeNanos() {
+        return mReceivedSvTimeNanos;
     }
 
     /**
      * Sets the received GNSS time in nanoseconds.
+     * @hide
      */
-    public void setReceivedSvTimeInNs(long value) {
-        mReceivedSvTimeInNs = value;
+    @TestApi
+    public void setReceivedSvTimeNanos(long value) {
+        mReceivedSvTimeNanos = value;
     }
 
     /**
      * Gets the received GNSS time uncertainty (1-Sigma) in nanoseconds.
      */
-    public long getReceivedSvTimeUncertaintyInNs() {
-        return mReceivedSvTimeUncertaintyInNs;
+    public long getReceivedSvTimeUncertaintyNanos() {
+        return mReceivedSvTimeUncertaintyNanos;
     }
 
     /**
      * Sets the received GNSS time uncertainty (1-Sigma) in nanoseconds.
+     * @hide
      */
-    public void setReceivedSvTimeUncertaintyInNs(long value) {
-        mReceivedSvTimeUncertaintyInNs = value;
+    @TestApi
+    public void setReceivedSvTimeUncertaintyNanos(long value) {
+        mReceivedSvTimeUncertaintyNanos = value;
     }
 
     /**
@@ -439,79 +399,97 @@
      *
      * The value contains the measured C/N0 for the signal at the antenna input.
      */
-    public double getCn0InDbHz() {
-        return mCn0InDbHz;
+    public double getCn0DbHz() {
+        return mCn0DbHz;
     }
 
     /**
      * Sets the carrier-to-noise density in dB-Hz.
+     * @hide
      */
-    public void setCn0InDbHz(double value) {
-        mCn0InDbHz = value;
+    @TestApi
+    public void setCn0DbHz(double value) {
+        mCn0DbHz = value;
     }
 
     /**
      * Gets the Pseudorange rate at the timestamp in m/s.
-     * The reported value includes {@link #getPseudorangeRateUncertaintyInMetersPerSec()}.
      *
-     * The correction of a given Pseudorange Rate value includes corrections from receiver and
-     * satellite clock frequency errors.
-     * {@link #isPseudorangeRateCorrected()} identifies the type of value reported.
+     * The reported value includes {@link #getPseudorangeRateUncertaintyMetersPerSecond()}.
      *
-     * A positive 'uncorrected' value indicates that the SV is moving away from the receiver.
-     * The sign of the 'uncorrected' Pseudorange Rate and its relation to the sign of
-     * {@link #getDopplerShiftInHz()} is given by the equation:
+     * The value is uncorrected, hence corrections for receiver and satellite clock frequency errors
+     * should not be included.
+     *
+     * A positive 'uncorrected' value indicates that the SV is moving away from the receiver. The
+     * sign of the 'uncorrected' 'pseudorange rate' and its relation to the sign of 'doppler shift'
+     * is given by the equation:
+     *
      *      pseudorange rate = -k * doppler shift   (where k is a constant)
      */
-    public double getPseudorangeRateInMetersPerSec() {
-        return mPseudorangeRateInMetersPerSec;
+    public double getPseudorangeRateMetersPerSecond() {
+        return mPseudorangeRateMetersPerSecond;
     }
 
     /**
      * Sets the pseudorange rate at the timestamp in m/s.
+     * @hide
      */
-    public void setPseudorangeRateInMetersPerSec(double value) {
-        mPseudorangeRateInMetersPerSec = value;
+    @TestApi
+    public void setPseudorangeRateMetersPerSecond(double value) {
+        mPseudorangeRateMetersPerSecond = value;
     }
 
     /**
-     * See {@link #getPseudorangeRateInMetersPerSec()} for more details.
+     * See {@link #getPseudorangeRateMetersPerSecond()} for more details.
      *
-     * @return {@code true} if {@link #getPseudorangeRateInMetersPerSec()} contains a corrected
+     * @return {@code true} if {@link #getPseudorangeRateMetersPerSecond()} contains a corrected
      *         value, {@code false} if it contains an uncorrected value.
      */
     public boolean isPseudorangeRateCorrected() {
-        return !isFlagSet(HAS_UNCORRECTED_PSEUDORANGE_RATE);
+        return mPseudorangeRateCorrected;
+    }
+
+    /**
+     * Sets whether the pseudorange corrected.
+     * @hide
+     */
+    @TestApi
+    public void setPseudorangeRateCorrected(boolean value) {
+        mPseudorangeRateCorrected = value;
     }
 
     /**
      * Gets the pseudorange's rate uncertainty (1-Sigma) in m/s.
      * The uncertainty is represented as an absolute (single sided) value.
      */
-    public double getPseudorangeRateUncertaintyInMetersPerSec() {
-        return mPseudorangeRateUncertaintyInMetersPerSec;
+    public double getPseudorangeRateUncertaintyMetersPerSecond() {
+        return mPseudorangeRateUncertaintyMetersPerSecond;
     }
 
     /**
      * Sets the pseudorange's rate uncertainty (1-Sigma) in m/s.
+     * @hide
      */
-    public void setPseudorangeRateUncertaintyInMetersPerSec(double value) {
-        mPseudorangeRateUncertaintyInMetersPerSec = value;
+    @TestApi
+    public void setPseudorangeRateUncertaintyMetersPerSecond(double value) {
+        mPseudorangeRateUncertaintyMetersPerSecond = value;
     }
 
     /**
      * Gets 'Accumulated Delta Range' state.
-     * It indicates whether {@link #getAccumulatedDeltaRangeInMeters()} is reset or there is a
+     * It indicates whether {@link #getAccumulatedDeltaRangeMeters()} is reset or there is a
      * cycle slip (indicating 'loss of lock').
      */
-    public short getAccumulatedDeltaRangeState() {
+    public int getAccumulatedDeltaRangeState() {
         return mAccumulatedDeltaRangeState;
     }
 
     /**
      * Sets the 'Accumulated Delta Range' state.
+     * @hide
      */
-    public void setAccumulatedDeltaRangeState(short value) {
+    @TestApi
+    public void setAccumulatedDeltaRangeState(int value) {
         mAccumulatedDeltaRangeState = value;
     }
 
@@ -545,24 +523,26 @@
 
     /**
      * Gets the accumulated delta range since the last channel reset, in meters.
-     * The reported value includes {@link #getAccumulatedDeltaRangeUncertaintyInMeters()}.
+     * The reported value includes {@link #getAccumulatedDeltaRangeUncertaintyMeters()}.
      *
      * The availability of the value is represented by {@link #getAccumulatedDeltaRangeState()}.
      *
      * A positive value indicates that the SV is moving away from the receiver.
-     * The sign of {@link #getAccumulatedDeltaRangeInMeters()} and its relation to the sign of
+     * The sign of {@link #getAccumulatedDeltaRangeMeters()} and its relation to the sign of
      * {@link #getCarrierPhase()} is given by the equation:
      *          accumulated delta range = -k * carrier phase    (where k is a constant)
      */
-    public double getAccumulatedDeltaRangeInMeters() {
-        return mAccumulatedDeltaRangeInMeters;
+    public double getAccumulatedDeltaRangeMeters() {
+        return mAccumulatedDeltaRangeMeters;
     }
 
     /**
      * Sets the accumulated delta range in meters.
+     * @hide
      */
-    public void setAccumulatedDeltaRangeInMeters(double value) {
-        mAccumulatedDeltaRangeInMeters = value;
+    @TestApi
+    public void setAccumulatedDeltaRangeMeters(double value) {
+        mAccumulatedDeltaRangeMeters = value;
     }
 
     /**
@@ -571,158 +551,26 @@
      *
      * The status of the value is represented by {@link #getAccumulatedDeltaRangeState()}.
      */
-    public double getAccumulatedDeltaRangeUncertaintyInMeters() {
-        return mAccumulatedDeltaRangeUncertaintyInMeters;
+    public double getAccumulatedDeltaRangeUncertaintyMeters() {
+        return mAccumulatedDeltaRangeUncertaintyMeters;
     }
 
     /**
      * Sets the accumulated delta range's uncertainty (1-sigma) in meters.
      *
      * The status of the value is represented by {@link #getAccumulatedDeltaRangeState()}.
-     */
-    public void setAccumulatedDeltaRangeUncertaintyInMeters(double value) {
-        mAccumulatedDeltaRangeUncertaintyInMeters = value;
-    }
-
-    /**
-     * Returns true if {@link #getPseudorangeInMeters()} is available, false otherwise.
-     */
-    public boolean hasPseudorangeInMeters() {
-        return isFlagSet(HAS_PSEUDORANGE);
-    }
-
-    /**
-     * Gets the best derived pseudorange by the chipset, in meters.
-     * The reported pseudorange includes {@link #getPseudorangeUncertaintyInMeters()}.
      *
-     * The value is only available if {@link #hasPseudorangeInMeters()} is true.
+     * @hide
      */
-    public double getPseudorangeInMeters() {
-        return mPseudorangeInMeters;
+    @TestApi
+    public void setAccumulatedDeltaRangeUncertaintyMeters(double value) {
+        mAccumulatedDeltaRangeUncertaintyMeters = value;
     }
 
     /**
-     * Sets the Pseudo-range in meters.
+     * Returns true if {@link #getCarrierFrequencyHz()} is available, false otherwise.
      */
-    public void setPseudorangeInMeters(double value) {
-        setFlag(HAS_PSEUDORANGE);
-        mPseudorangeInMeters = value;
-    }
-
-    /**
-     * Resets the Pseudo-range in meters.
-     */
-    public void resetPseudorangeInMeters() {
-        resetFlag(HAS_PSEUDORANGE);
-        mPseudorangeInMeters = Double.NaN;
-    }
-
-    /**
-     * Returns true if {@link #getPseudorangeUncertaintyInMeters()} is available, false otherwise.
-     */
-    public boolean hasPseudorangeUncertaintyInMeters() {
-        return isFlagSet(HAS_PSEUDORANGE_UNCERTAINTY);
-    }
-
-    /**
-     * Gets the pseudorange's uncertainty (1-Sigma) in meters.
-     * The value contains the 'pseudorange' and 'clock' uncertainty in it.
-     * The uncertainty is represented as an absolute (single sided) value.
-     *
-     * The value is only available if {@link #hasPseudorangeUncertaintyInMeters()} is true.
-     */
-    public double getPseudorangeUncertaintyInMeters() {
-        return mPseudorangeUncertaintyInMeters;
-    }
-
-    /**
-     * Sets the pseudo-range's uncertainty (1-Sigma) in meters.
-     */
-    public void setPseudorangeUncertaintyInMeters(double value) {
-        setFlag(HAS_PSEUDORANGE_UNCERTAINTY);
-        mPseudorangeUncertaintyInMeters = value;
-    }
-
-    /**
-     * Resets the pseudo-range's uncertainty (1-Sigma) in meters.
-     */
-    public void resetPseudorangeUncertaintyInMeters() {
-        resetFlag(HAS_PSEUDORANGE_UNCERTAINTY);
-        mPseudorangeUncertaintyInMeters = Double.NaN;
-    }
-
-    /**
-     * Returns true if {@link #getCodePhaseInChips()} is available, false otherwise.
-     */
-    public boolean hasCodePhaseInChips() {
-        return isFlagSet(HAS_CODE_PHASE);
-    }
-
-    /**
-     * Gets the fraction of the current C/A code cycle.
-     * Range: [0, 1023]
-     * The reference frequency is given by the value of {@link #getCarrierFrequencyInHz()}.
-     * The reported code-phase includes {@link #getCodePhaseUncertaintyInChips()}.
-     *
-     * The value is only available if {@link #hasCodePhaseInChips()} is true.
-     */
-    public double getCodePhaseInChips() {
-        return mCodePhaseInChips;
-    }
-
-    /**
-     * Sets the Code-phase in chips.
-     */
-    public void setCodePhaseInChips(double value) {
-        setFlag(HAS_CODE_PHASE);
-        mCodePhaseInChips = value;
-    }
-
-    /**
-     * Resets the Code-phase in chips.
-     */
-    public void resetCodePhaseInChips() {
-        resetFlag(HAS_CODE_PHASE);
-        mCodePhaseInChips = Double.NaN;
-    }
-
-    /**
-     * Returns true if {@link #getCodePhaseUncertaintyInChips()} is available, false otherwise.
-     */
-    public boolean hasCodePhaseUncertaintyInChips() {
-        return isFlagSet(HAS_CODE_PHASE_UNCERTAINTY);
-    }
-
-    /**
-     * Gets the code-phase's uncertainty (1-Sigma) as a fraction of chips.
-     * The uncertainty is represented as an absolute (single sided) value.
-     *
-     * The value is only available if {@link #hasCodePhaseUncertaintyInChips()} is true.
-     */
-    public double getCodePhaseUncertaintyInChips() {
-        return mCodePhaseUncertaintyInChips;
-    }
-
-    /**
-     * Sets the Code-phase's uncertainty (1-Sigma) in fractions of chips.
-     */
-    public void setCodePhaseUncertaintyInChips(double value) {
-        setFlag(HAS_CODE_PHASE_UNCERTAINTY);
-        mCodePhaseUncertaintyInChips = value;
-    }
-
-    /**
-     * Resets the Code-phase's uncertainty (1-Sigma) in fractions of chips.
-     */
-    public void resetCodePhaseUncertaintyInChips() {
-        resetFlag(HAS_CODE_PHASE_UNCERTAINTY);
-        mCodePhaseUncertaintyInChips = Double.NaN;
-    }
-
-    /**
-     * Returns true if {@link #getCarrierFrequencyInHz()} is available, false otherwise.
-     */
-    public boolean hasCarrierFrequencyInHz() {
+    public boolean hasCarrierFrequencyHz() {
         return isFlagSet(HAS_CARRIER_FREQUENCY);
     }
 
@@ -730,26 +578,30 @@
      * Gets the carrier frequency at which codes and messages are modulated, it can be L1 or L2.
      * If the field is not set, the carrier frequency corresponds to L1.
      *
-     * The value is only available if {@link #hasCarrierFrequencyInHz()} is true.
+     * The value is only available if {@link #hasCarrierFrequencyHz()} is true.
      */
-    public float getCarrierFrequencyInHz() {
-        return mCarrierFrequencyInHz;
+    public float getCarrierFrequencyHz() {
+        return mCarrierFrequencyHz;
     }
 
     /**
      * Sets the Carrier frequency (L1 or L2) in Hz.
+     * @hide
      */
-    public void setCarrierFrequencyInHz(float carrierFrequencyInHz) {
+    @TestApi
+    public void setCarrierFrequencyHz(float carrierFrequencyHz) {
         setFlag(HAS_CARRIER_FREQUENCY);
-        mCarrierFrequencyInHz = carrierFrequencyInHz;
+        mCarrierFrequencyHz = carrierFrequencyHz;
     }
 
     /**
      * Resets the Carrier frequency (L1 or L2) in Hz.
+     * @hide
      */
-    public void resetCarrierFrequencyInHz() {
+    @TestApi
+    public void resetCarrierFrequencyHz() {
         resetFlag(HAS_CARRIER_FREQUENCY);
-        mCarrierFrequencyInHz = Float.NaN;
+        mCarrierFrequencyHz = Float.NaN;
     }
 
     /**
@@ -761,7 +613,7 @@
 
     /**
      * The number of full carrier cycles between the satellite and the receiver.
-     * The reference frequency is given by the value of {@link #getCarrierFrequencyInHz()}.
+     * The reference frequency is given by the value of {@link #getCarrierFrequencyHz()}.
      *
      * The value is only available if {@link #hasCarrierCycles()} is true.
      */
@@ -771,7 +623,9 @@
 
     /**
      * Sets the number of full carrier cycles between the satellite and the receiver.
+     * @hide
      */
+    @TestApi
     public void setCarrierCycles(long value) {
         setFlag(HAS_CARRIER_CYCLES);
         mCarrierCycles = value;
@@ -779,7 +633,9 @@
 
     /**
      * Resets the number of full carrier cycles between the satellite and the receiver.
+     * @hide
      */
+    @TestApi
     public void resetCarrierCycles() {
         resetFlag(HAS_CARRIER_CYCLES);
         mCarrierCycles = Long.MIN_VALUE;
@@ -797,7 +653,7 @@
      * Range: [0.0, 1.0].
      * This is usually the fractional part of the complete carrier phase measurement.
      *
-     * The reference frequency is given by the value of {@link #getCarrierFrequencyInHz()}.
+     * The reference frequency is given by the value of {@link #getCarrierFrequencyHz()}.
      * The reported carrier-phase includes {@link #getCarrierPhaseUncertainty()}.
      *
      * The value is only available if {@link #hasCarrierPhase()} is true.
@@ -808,7 +664,9 @@
 
     /**
      * Sets the RF phase detected by the receiver.
+     * @hide
      */
+    @TestApi
     public void setCarrierPhase(double value) {
         setFlag(HAS_CARRIER_PHASE);
         mCarrierPhase = value;
@@ -816,7 +674,9 @@
 
     /**
      * Resets the RF phase detected by the receiver.
+     * @hide
      */
+    @TestApi
     public void resetCarrierPhase() {
         resetFlag(HAS_CARRIER_PHASE);
         mCarrierPhase = Double.NaN;
@@ -841,7 +701,9 @@
 
     /**
      * Sets the Carrier-phase's uncertainty (1-Sigma) in cycles.
+     * @hide
      */
+    @TestApi
     public void setCarrierPhaseUncertainty(double value) {
         setFlag(HAS_CARRIER_PHASE_UNCERTAINTY);
         mCarrierPhaseUncertainty = value;
@@ -849,190 +711,28 @@
 
     /**
      * Resets the Carrier-phase's uncertainty (1-Sigma) in cycles.
+     * @hide
      */
+    @TestApi
     public void resetCarrierPhaseUncertainty() {
         resetFlag(HAS_CARRIER_PHASE_UNCERTAINTY);
         mCarrierPhaseUncertainty = Double.NaN;
     }
 
     /**
-     * Gets a value indicating the 'loss of lock' state of the event.
-     */
-    @LossOfLockStatus
-    public byte getLossOfLock() {
-        return mLossOfLock;
-    }
-
-    /**
-     * Sets the 'loss of lock' status.
-     */
-    public void setLossOfLock(@LossOfLockStatus byte value) {
-        mLossOfLock = value;
-    }
-
-    /**
-     * Gets a string representation of the 'loss of lock'.
-     * For internal and logging use only.
-     */
-    private String getLossOfLockString() {
-        switch (mLossOfLock) {
-            case LOSS_OF_LOCK_UNKNOWN:
-                return "Unknown";
-            case LOSS_OF_LOCK_OK:
-                return "Ok";
-            case LOSS_OF_LOCK_CYCLE_SLIP:
-                return "CycleSlip";
-            default:
-                return "<Invalid:" + mLossOfLock + ">";
-        }
-    }
-
-    /**
-     * Returns true if {@link #getBitNumber()} is available, false otherwise.
-     */
-    public boolean hasBitNumber() {
-        return isFlagSet(HAS_BIT_NUMBER);
-    }
-
-    /**
-     * Gets the number of GPS bits transmitted since Sat-Sun midnight (GPS week).
-     *
-     * The value is only available if {@link #hasBitNumber()} is true.
-     */
-    public int getBitNumber() {
-        return mBitNumber;
-    }
-
-    /**
-     * Sets the bit number within the broadcast frame.
-     */
-    public void setBitNumber(int bitNumber) {
-        setFlag(HAS_BIT_NUMBER);
-        mBitNumber = bitNumber;
-    }
-
-    /**
-     * Resets the bit number within the broadcast frame.
-     */
-    public void resetBitNumber() {
-        resetFlag(HAS_BIT_NUMBER);
-        mBitNumber = Integer.MIN_VALUE;
-    }
-
-    /**
-     * Returns true if {@link #getTimeFromLastBitInMs()} is available, false otherwise.
-     */
-    public boolean hasTimeFromLastBitInMs() {
-        return isFlagSet(HAS_TIME_FROM_LAST_BIT);
-    }
-
-    /**
-     * Gets the elapsed time since the last received bit in milliseconds.
-     * Range: [0, 20].
-     *
-     * The value is only available if {@link #hasTimeFromLastBitInMs()} is true.
-     */
-    public short getTimeFromLastBitInMs() {
-        return mTimeFromLastBitInMs;
-    }
-
-    /**
-     * Sets the elapsed time since the last received bit in milliseconds.
-     */
-    public void setTimeFromLastBitInMs(short value) {
-        setFlag(HAS_TIME_FROM_LAST_BIT);
-        mTimeFromLastBitInMs = value;
-    }
-
-    /**
-     * Resets the elapsed time since the last received bit in milliseconds.
-     */
-    public void resetTimeFromLastBitInMs() {
-        resetFlag(HAS_TIME_FROM_LAST_BIT);
-        mTimeFromLastBitInMs = Short.MIN_VALUE;
-    }
-
-    /**
-     * Returns true if {@link #getDopplerShiftInHz()} is available, false otherwise.
-     */
-    public boolean hasDopplerShiftInHz() {
-        return isFlagSet(HAS_DOPPLER_SHIFT);
-    }
-
-    /**
-     * Gets the Doppler Shift in Hz.
-     * A positive value indicates that the SV is moving toward the receiver.
-     *
-     * The reference frequency is given by the value of {@link #getCarrierFrequencyInHz()}.
-     * The reported doppler shift includes {@link #getDopplerShiftUncertaintyInHz()}.
-     *
-     * The value is only available if {@link #hasDopplerShiftInHz()} is true.
-     */
-    public double getDopplerShiftInHz() {
-        return mDopplerShiftInHz;
-    }
-
-    /**
-     * Sets the Doppler shift in Hz.
-     */
-    public void setDopplerShiftInHz(double value) {
-        setFlag(HAS_DOPPLER_SHIFT);
-        mDopplerShiftInHz = value;
-    }
-
-    /**
-     * Resets the Doppler shift in Hz.
-     */
-    public void resetDopplerShiftInHz() {
-        resetFlag(HAS_DOPPLER_SHIFT);
-        mDopplerShiftInHz = Double.NaN;
-    }
-
-    /**
-     * Returns true if {@link #getDopplerShiftUncertaintyInHz()} is available, false otherwise.
-     */
-    public boolean hasDopplerShiftUncertaintyInHz() {
-        return isFlagSet(HAS_DOPPLER_SHIFT_UNCERTAINTY);
-    }
-
-    /**
-     * Gets the Doppler's Shift uncertainty (1-Sigma) in Hz.
-     * The uncertainty is represented as an absolute (single sided) value.
-     *
-     * The value is only available if {@link #hasDopplerShiftUncertaintyInHz()} is true.
-     */
-    public double getDopplerShiftUncertaintyInHz() {
-        return mDopplerShiftUncertaintyInHz;
-    }
-
-    /**
-     * Sets the Doppler's shift uncertainty (1-Sigma) in Hz.
-     */
-    public void setDopplerShiftUncertaintyInHz(double value) {
-        setFlag(HAS_DOPPLER_SHIFT_UNCERTAINTY);
-        mDopplerShiftUncertaintyInHz = value;
-    }
-
-    /**
-     * Resets the Doppler's shift uncertainty (1-Sigma) in Hz.
-     */
-    public void resetDopplerShiftUncertaintyInHz() {
-        resetFlag(HAS_DOPPLER_SHIFT_UNCERTAINTY);
-        mDopplerShiftUncertaintyInHz = Double.NaN;
-    }
-
-    /**
      * Gets a value indicating the 'multipath' state of the event.
      */
     @MultipathIndicator
-    public byte getMultipathIndicator() {
+    public int getMultipathIndicator() {
         return mMultipathIndicator;
     }
 
     /**
      * Sets the 'multi-path' indicator.
+     * @hide
      */
-    public void setMultipathIndicator(@MultipathIndicator byte value) {
+    @TestApi
+    public void setMultipathIndicator(@MultipathIndicator int value) {
         mMultipathIndicator = value;
     }
 
@@ -1071,7 +771,9 @@
 
     /**
      * Sets the Signal-to-noise ratio (SNR) in dB.
+     * @hide
      */
+    @TestApi
     public void setSnrInDb(double snrInDb) {
         setFlag(HAS_SNR);
         mSnrInDb = snrInDb;
@@ -1079,206 +781,39 @@
 
     /**
      * Resets the Signal-to-noise ratio (SNR) in dB.
+     * @hide
      */
+    @TestApi
     public void resetSnrInDb() {
         resetFlag(HAS_SNR);
         mSnrInDb = Double.NaN;
     }
 
-    /**
-     * Returns true if {@link #getElevationInDeg()} is available, false otherwise.
-     */
-    public boolean hasElevationInDeg() {
-        return isFlagSet(HAS_ELEVATION);
-    }
-
-    /**
-     * Gets the Elevation in degrees.
-     * Range: [-90, 90]
-     * The reported elevation includes {@link #getElevationUncertaintyInDeg()}.
-     *
-     * The value is only available if {@link #hasElevationInDeg()} is true.
-     */
-    public double getElevationInDeg() {
-        return mElevationInDeg;
-    }
-
-    /**
-     * Sets the Elevation in degrees.
-     */
-    public void setElevationInDeg(double elevationInDeg) {
-        setFlag(HAS_ELEVATION);
-        mElevationInDeg = elevationInDeg;
-    }
-
-    /**
-     * Resets the Elevation in degrees.
-     */
-    public void resetElevationInDeg() {
-        resetFlag(HAS_ELEVATION);
-        mElevationInDeg = Double.NaN;
-    }
-
-    /**
-     * Returns true if {@link #getElevationUncertaintyInDeg()} is available, false otherwise.
-     */
-    public boolean hasElevationUncertaintyInDeg() {
-        return isFlagSet(HAS_ELEVATION_UNCERTAINTY);
-    }
-
-    /**
-     * Gets the elevation's uncertainty (1-Sigma) in degrees.
-     * Range: [0, 90]
-     *
-     * The uncertainty is represented as an absolute (single sided) value.
-     *
-     * The value is only available if {@link #hasElevationUncertaintyInDeg()} is true.
-     */
-    public double getElevationUncertaintyInDeg() {
-        return mElevationUncertaintyInDeg;
-    }
-
-    /**
-     * Sets the elevation's uncertainty (1-Sigma) in degrees.
-     */
-    public void setElevationUncertaintyInDeg(double value) {
-        setFlag(HAS_ELEVATION_UNCERTAINTY);
-        mElevationUncertaintyInDeg = value;
-    }
-
-    /**
-     * Resets the elevation's uncertainty (1-Sigma) in degrees.
-     */
-    public void resetElevationUncertaintyInDeg() {
-        resetFlag(HAS_ELEVATION_UNCERTAINTY);
-        mElevationUncertaintyInDeg = Double.NaN;
-    }
-
-    /**
-     * Returns true if {@link #getAzimuthInDeg()} is available, false otherwise.
-     */
-    public boolean hasAzimuthInDeg() {
-        return isFlagSet(HAS_AZIMUTH);
-    }
-
-    /**
-     * Gets the azimuth in degrees.
-     * Range: [0, 360).
-     *
-     * The reported azimuth includes {@link #getAzimuthUncertaintyInDeg()}.
-     *
-     * The value is only available if {@link #hasAzimuthInDeg()} is true.
-     */
-    public double getAzimuthInDeg() {
-        return mAzimuthInDeg;
-    }
-
-    /**
-     * Sets the Azimuth in degrees.
-     */
-    public void setAzimuthInDeg(double value) {
-        setFlag(HAS_AZIMUTH);
-        mAzimuthInDeg = value;
-    }
-
-    /**
-     * Resets the Azimuth in degrees.
-     */
-    public void resetAzimuthInDeg() {
-        resetFlag(HAS_AZIMUTH);
-        mAzimuthInDeg = Double.NaN;
-    }
-
-    /**
-     * Returns true if {@link #getAzimuthUncertaintyInDeg()} is available, false otherwise.
-     */
-    public boolean hasAzimuthUncertaintyInDeg() {
-        return isFlagSet(HAS_AZIMUTH_UNCERTAINTY);
-    }
-
-    /**
-     * Gets the azimuth's uncertainty (1-Sigma) in degrees.
-     * Range: [0, 180].
-     *
-     * The uncertainty is represented as an absolute (single sided) value.
-     *
-     * The value is only available if {@link #hasAzimuthUncertaintyInDeg()} is true.
-     */
-    public double getAzimuthUncertaintyInDeg() {
-        return mAzimuthUncertaintyInDeg;
-    }
-
-    /**
-     * Sets the Azimuth's uncertainty (1-Sigma) in degrees.
-     */
-    public void setAzimuthUncertaintyInDeg(double value) {
-        setFlag(HAS_AZIMUTH_UNCERTAINTY);
-        mAzimuthUncertaintyInDeg = value;
-    }
-
-    /**
-     * Resets the Azimuth's uncertainty (1-Sigma) in degrees.
-     */
-    public void resetAzimuthUncertaintyInDeg() {
-        resetFlag(HAS_AZIMUTH_UNCERTAINTY);
-        mAzimuthUncertaintyInDeg = Double.NaN;
-    }
-
-    /**
-     * Gets a flag indicating whether the GNSS represented by the measurement was used for computing
-     * the most recent fix.
-     *
-     * @return A non-null value if the data is available, null otherwise.
-     */
-    public boolean isUsedInFix() {
-        return mUsedInFix;
-    }
-
-    /**
-     * Sets the Used-in-Fix flag.
-     */
-    public void setUsedInFix(boolean value) {
-        mUsedInFix = value;
-    }
-
     public static final Creator<GnssMeasurement> CREATOR = new Creator<GnssMeasurement>() {
         @Override
         public GnssMeasurement createFromParcel(Parcel parcel) {
             GnssMeasurement gnssMeasurement = new GnssMeasurement();
 
             gnssMeasurement.mFlags = parcel.readInt();
-            gnssMeasurement.mSvid = (short) parcel.readInt();
-            gnssMeasurement.mConstellationType = parcel.readByte();
-            gnssMeasurement.mTimeOffsetInNs = parcel.readDouble();
-            gnssMeasurement.mState = (short) parcel.readInt();
-            gnssMeasurement.mReceivedSvTimeInNs = parcel.readLong();
-            gnssMeasurement.mReceivedSvTimeUncertaintyInNs = parcel.readLong();
-            gnssMeasurement.mCn0InDbHz = parcel.readDouble();
-            gnssMeasurement.mPseudorangeRateInMetersPerSec = parcel.readDouble();
-            gnssMeasurement.mPseudorangeRateUncertaintyInMetersPerSec = parcel.readDouble();
-            gnssMeasurement.mAccumulatedDeltaRangeState = (short) parcel.readInt();
-            gnssMeasurement.mAccumulatedDeltaRangeInMeters = parcel.readDouble();
-            gnssMeasurement.mAccumulatedDeltaRangeUncertaintyInMeters = parcel.readDouble();
-            gnssMeasurement.mPseudorangeInMeters = parcel.readDouble();
-            gnssMeasurement.mPseudorangeUncertaintyInMeters = parcel.readDouble();
-            gnssMeasurement.mCodePhaseInChips = parcel.readDouble();
-            gnssMeasurement.mCodePhaseUncertaintyInChips = parcel.readDouble();
-            gnssMeasurement.mCarrierFrequencyInHz = parcel.readFloat();
+            gnssMeasurement.mSvid = parcel.readInt();
+            gnssMeasurement.mConstellationType = parcel.readInt();
+            gnssMeasurement.mTimeOffsetNanos = parcel.readDouble();
+            gnssMeasurement.mState = parcel.readInt();
+            gnssMeasurement.mReceivedSvTimeNanos = parcel.readLong();
+            gnssMeasurement.mReceivedSvTimeUncertaintyNanos = parcel.readLong();
+            gnssMeasurement.mCn0DbHz = parcel.readDouble();
+            gnssMeasurement.mPseudorangeRateMetersPerSecond = parcel.readDouble();
+            gnssMeasurement.mPseudorangeRateUncertaintyMetersPerSecond = parcel.readDouble();
+            gnssMeasurement.mAccumulatedDeltaRangeState = parcel.readInt();
+            gnssMeasurement.mAccumulatedDeltaRangeMeters = parcel.readDouble();
+            gnssMeasurement.mAccumulatedDeltaRangeUncertaintyMeters = parcel.readDouble();
+            gnssMeasurement.mCarrierFrequencyHz = parcel.readFloat();
             gnssMeasurement.mCarrierCycles = parcel.readLong();
             gnssMeasurement.mCarrierPhase = parcel.readDouble();
             gnssMeasurement.mCarrierPhaseUncertainty = parcel.readDouble();
-            gnssMeasurement.mLossOfLock = parcel.readByte();
-            gnssMeasurement.mBitNumber = parcel.readInt();
-            gnssMeasurement.mTimeFromLastBitInMs = (short) parcel.readInt();
-            gnssMeasurement.mDopplerShiftInHz = parcel.readDouble();
-            gnssMeasurement.mDopplerShiftUncertaintyInHz = parcel.readDouble();
-            gnssMeasurement.mMultipathIndicator = parcel.readByte();
+            gnssMeasurement.mMultipathIndicator = parcel.readInt();
             gnssMeasurement.mSnrInDb = parcel.readDouble();
-            gnssMeasurement.mElevationInDeg = parcel.readDouble();
-            gnssMeasurement.mElevationUncertaintyInDeg = parcel.readDouble();
-            gnssMeasurement.mAzimuthInDeg = parcel.readDouble();
-            gnssMeasurement.mAzimuthUncertaintyInDeg = parcel.readDouble();
-            gnssMeasurement.mUsedInFix = parcel.readInt() != 0;
+            gnssMeasurement.mPseudorangeRateCorrected = (parcel.readByte() != 0);
 
             return gnssMeasurement;
         }
@@ -1293,37 +828,24 @@
     public void writeToParcel(Parcel parcel, int flags) {
         parcel.writeInt(mFlags);
         parcel.writeInt(mSvid);
-        parcel.writeByte(mConstellationType);
-        parcel.writeDouble(mTimeOffsetInNs);
+        parcel.writeInt(mConstellationType);
+        parcel.writeDouble(mTimeOffsetNanos);
         parcel.writeInt(mState);
-        parcel.writeLong(mReceivedSvTimeInNs);
-        parcel.writeLong(mReceivedSvTimeUncertaintyInNs);
-        parcel.writeDouble(mCn0InDbHz);
-        parcel.writeDouble(mPseudorangeRateInMetersPerSec);
-        parcel.writeDouble(mPseudorangeRateUncertaintyInMetersPerSec);
+        parcel.writeLong(mReceivedSvTimeNanos);
+        parcel.writeLong(mReceivedSvTimeUncertaintyNanos);
+        parcel.writeDouble(mCn0DbHz);
+        parcel.writeDouble(mPseudorangeRateMetersPerSecond);
+        parcel.writeDouble(mPseudorangeRateUncertaintyMetersPerSecond);
         parcel.writeInt(mAccumulatedDeltaRangeState);
-        parcel.writeDouble(mAccumulatedDeltaRangeInMeters);
-        parcel.writeDouble(mAccumulatedDeltaRangeUncertaintyInMeters);
-        parcel.writeDouble(mPseudorangeInMeters);
-        parcel.writeDouble(mPseudorangeUncertaintyInMeters);
-        parcel.writeDouble(mCodePhaseInChips);
-        parcel.writeDouble(mCodePhaseUncertaintyInChips);
-        parcel.writeFloat(mCarrierFrequencyInHz);
+        parcel.writeDouble(mAccumulatedDeltaRangeMeters);
+        parcel.writeDouble(mAccumulatedDeltaRangeUncertaintyMeters);
+        parcel.writeFloat(mCarrierFrequencyHz);
         parcel.writeLong(mCarrierCycles);
         parcel.writeDouble(mCarrierPhase);
         parcel.writeDouble(mCarrierPhaseUncertainty);
-        parcel.writeByte(mLossOfLock);
-        parcel.writeInt(mBitNumber);
-        parcel.writeInt(mTimeFromLastBitInMs);
-        parcel.writeDouble(mDopplerShiftInHz);
-        parcel.writeDouble(mDopplerShiftUncertaintyInHz);
-        parcel.writeByte(mMultipathIndicator);
+        parcel.writeInt(mMultipathIndicator);
         parcel.writeDouble(mSnrInDb);
-        parcel.writeDouble(mElevationInDeg);
-        parcel.writeDouble(mElevationUncertaintyInDeg);
-        parcel.writeDouble(mAzimuthInDeg);
-        parcel.writeDouble(mAzimuthUncertaintyInDeg);
-        parcel.writeInt(mUsedInFix ? 1 : 0);
+        parcel.writeByte((byte) (mPseudorangeRateCorrected ? 1 : 0));
     }
 
     @Override
@@ -1339,25 +861,25 @@
 
         builder.append(String.format(format, "Svid", mSvid));
         builder.append(String.format(format, "ConstellationType", mConstellationType));
-        builder.append(String.format(format, "TimeOffsetInNs", mTimeOffsetInNs));
+        builder.append(String.format(format, "TimeOffsetNanos", mTimeOffsetNanos));
 
         builder.append(String.format(format, "State", getStateString()));
 
         builder.append(String.format(
                 formatWithUncertainty,
-                "ReceivedSvTimeInNs",
-                mReceivedSvTimeInNs,
-                "ReceivedSvTimeUncertaintyInNs",
-                mReceivedSvTimeUncertaintyInNs));
+                "ReceivedSvTimeNanos",
+                mReceivedSvTimeNanos,
+                "ReceivedSvTimeUncertaintyNanos",
+                mReceivedSvTimeUncertaintyNanos));
 
-        builder.append(String.format(format, "Cn0InDbHz", mCn0InDbHz));
+        builder.append(String.format(format, "Cn0DbHz", mCn0DbHz));
 
         builder.append(String.format(
                 formatWithUncertainty,
-                "PseudorangeRateInMetersPerSec",
-                mPseudorangeRateInMetersPerSec,
-                "PseudorangeRateUncertaintyInMetersPerSec",
-                mPseudorangeRateUncertaintyInMetersPerSec));
+                "PseudorangeRateMetersPerSecond",
+                mPseudorangeRateMetersPerSecond,
+                "PseudorangeRateUncertaintyMetersPerSecond",
+                mPseudorangeRateUncertaintyMetersPerSecond));
         builder.append(String.format(
                 format,
                 "PseudorangeRateIsCorrected",
@@ -1370,29 +892,15 @@
 
         builder.append(String.format(
                 formatWithUncertainty,
-                "AccumulatedDeltaRangeInMeters",
-                mAccumulatedDeltaRangeInMeters,
-                "AccumulatedDeltaRangeUncertaintyInMeters",
-                mAccumulatedDeltaRangeUncertaintyInMeters));
-
-        builder.append(String.format(
-                formatWithUncertainty,
-                "PseudorangeInMeters",
-                hasPseudorangeInMeters() ? mPseudorangeInMeters : null,
-                "PseudorangeUncertaintyInMeters",
-                hasPseudorangeUncertaintyInMeters() ? mPseudorangeUncertaintyInMeters : null));
-
-        builder.append(String.format(
-                formatWithUncertainty,
-                "CodePhaseInChips",
-                hasCodePhaseInChips() ? mCodePhaseInChips : null,
-                "CodePhaseUncertaintyInChips",
-                hasCodePhaseUncertaintyInChips() ? mCodePhaseUncertaintyInChips : null));
+                "AccumulatedDeltaRangeMeters",
+                mAccumulatedDeltaRangeMeters,
+                "AccumulatedDeltaRangeUncertaintyMeters",
+                mAccumulatedDeltaRangeUncertaintyMeters));
 
         builder.append(String.format(
                 format,
-                "CarrierFrequencyInHz",
-                hasCarrierFrequencyInHz() ? mCarrierFrequencyInHz : null));
+                "CarrierFrequencyHz",
+                hasCarrierFrequencyHz() ? mCarrierFrequencyHz : null));
 
         builder.append(String.format(
                 format,
@@ -1406,25 +914,6 @@
                 "CarrierPhaseUncertainty",
                 hasCarrierPhaseUncertainty() ? mCarrierPhaseUncertainty : null));
 
-        builder.append(String.format(format, "LossOfLock", getLossOfLockString()));
-
-        builder.append(String.format(
-                format,
-                "BitNumber",
-                hasBitNumber() ? mBitNumber : null));
-
-        builder.append(String.format(
-                format,
-                "TimeFromLastBitInMs",
-                hasTimeFromLastBitInMs() ? mTimeFromLastBitInMs : null));
-
-        builder.append(String.format(
-                formatWithUncertainty,
-                "DopplerShiftInHz",
-                hasDopplerShiftInHz() ? mDopplerShiftInHz : null,
-                "DopplerShiftUncertaintyInHz",
-                hasDopplerShiftUncertaintyInHz() ? mDopplerShiftUncertaintyInHz : null));
-
         builder.append(String.format(format, "MultipathIndicator", getMultipathIndicatorString()));
 
         builder.append(String.format(
@@ -1432,58 +921,29 @@
                 "SnrInDb",
                 hasSnrInDb() ? mSnrInDb : null));
 
-        builder.append(String.format(
-                formatWithUncertainty,
-                "ElevationInDeg",
-                hasElevationInDeg() ? mElevationInDeg : null,
-                "ElevationUncertaintyInDeg",
-                hasElevationUncertaintyInDeg() ? mElevationUncertaintyInDeg : null));
-
-        builder.append(String.format(
-                formatWithUncertainty,
-                "AzimuthInDeg",
-                hasAzimuthInDeg() ? mAzimuthInDeg : null,
-                "AzimuthUncertaintyInDeg",
-                hasAzimuthUncertaintyInDeg() ? mAzimuthUncertaintyInDeg : null));
-
-        builder.append(String.format(format, "UsedInFix", mUsedInFix));
-
         return builder.toString();
     }
 
     private void initialize() {
         mFlags = HAS_NO_FLAGS;
-        setSvid((short) 0);
-        setTimeOffsetInNs(Long.MIN_VALUE);
+        setSvid(0);
+        setTimeOffsetNanos(Long.MIN_VALUE);
         setState(STATE_UNKNOWN);
-        setReceivedSvTimeInNs(Long.MIN_VALUE);
-        setReceivedSvTimeUncertaintyInNs(Long.MAX_VALUE);
-        setCn0InDbHz(Double.MIN_VALUE);
-        setPseudorangeRateInMetersPerSec(Double.MIN_VALUE);
-        setPseudorangeRateUncertaintyInMetersPerSec(Double.MIN_VALUE);
+        setReceivedSvTimeNanos(Long.MIN_VALUE);
+        setReceivedSvTimeUncertaintyNanos(Long.MAX_VALUE);
+        setCn0DbHz(Double.MIN_VALUE);
+        setPseudorangeRateMetersPerSecond(Double.MIN_VALUE);
+        setPseudorangeRateUncertaintyMetersPerSecond(Double.MIN_VALUE);
         setAccumulatedDeltaRangeState(ADR_STATE_UNKNOWN);
-        setAccumulatedDeltaRangeInMeters(Double.MIN_VALUE);
-        setAccumulatedDeltaRangeUncertaintyInMeters(Double.MIN_VALUE);
-        resetPseudorangeInMeters();
-        resetPseudorangeUncertaintyInMeters();
-        resetCodePhaseInChips();
-        resetCodePhaseUncertaintyInChips();
-        resetCarrierFrequencyInHz();
+        setAccumulatedDeltaRangeMeters(Double.MIN_VALUE);
+        setAccumulatedDeltaRangeUncertaintyMeters(Double.MIN_VALUE);
+        resetCarrierFrequencyHz();
         resetCarrierCycles();
         resetCarrierPhase();
         resetCarrierPhaseUncertainty();
-        setLossOfLock(LOSS_OF_LOCK_UNKNOWN);
-        resetBitNumber();
-        resetTimeFromLastBitInMs();
-        resetDopplerShiftInHz();
-        resetDopplerShiftUncertaintyInHz();
         setMultipathIndicator(MULTIPATH_INDICATOR_UNKNOWN);
         resetSnrInDb();
-        resetElevationInDeg();
-        resetElevationUncertaintyInDeg();
-        resetAzimuthInDeg();
-        resetAzimuthUncertaintyInDeg();
-        setUsedInFix(false);
+        setPseudorangeRateCorrected(false);
     }
 
     private void setFlag(int flag) {
diff --git a/location/java/android/location/GnssMeasurementsEvent.java b/location/java/android/location/GnssMeasurementsEvent.java
index b744a03..86841ff 100644
--- a/location/java/android/location/GnssMeasurementsEvent.java
+++ b/location/java/android/location/GnssMeasurementsEvent.java
@@ -33,46 +33,46 @@
  * Events are delivered to registered instances of {@link Callback}.
  */
 public final class GnssMeasurementsEvent implements Parcelable {
-    /** The status of GPS measurements event. */
+    /** The status of GNSS measurements event. */
     @Retention(RetentionPolicy.SOURCE)
-    @IntDef({STATUS_NOT_SUPPORTED, STATUS_READY, STATUS_GPS_LOCATION_DISABLED})
+    @IntDef({STATUS_NOT_SUPPORTED, STATUS_READY, STATUS_GNSS_LOCATION_DISABLED})
     public @interface GnssMeasurementsStatus {}
 
     /**
-     * The system does not support tracking of GPS Measurements. This status will not change in the
+     * The system does not support tracking of GNSS Measurements. This status will not change in the
      * future.
      */
     public static final int STATUS_NOT_SUPPORTED = 0;
 
     /**
-     * GPS Measurements are successfully being tracked, it will receive updates once they are
+     * GNSS Measurements are successfully being tracked, it will receive updates once they are
      * available.
      */
     public static final int STATUS_READY = 1;
 
     /**
-     * GPS provider or Location is disabled, updates will not be received until they are enabled.
+     * GNSS provider or Location is disabled, updates will not be received until they are enabled.
      */
-    public static final int STATUS_GPS_LOCATION_DISABLED = 2;
+    public static final int STATUS_GNSS_LOCATION_DISABLED = 2;
 
     private final GnssClock mClock;
     private final Collection<GnssMeasurement> mReadOnlyMeasurements;
 
     /**
-     * Used for receiving GPS satellite measurements from the GPS engine.
+     * Used for receiving GNSS satellite measurements from the GNSS engine.
      * Each measurement contains raw and computed data identifying a satellite.
      * You can implement this interface and call
-     * {@link LocationManager#registerGnssMeasurementCallback}.
+     * {@link LocationManager#registerGnssMeasurementsCallback}.
      */
     public static abstract class Callback {
 
         /**
-         * Returns the latest collected GPS Measurements.
+         * Reports the latest collected GNSS Measurements.
          */
         public void onGnssMeasurementsReceived(GnssMeasurementsEvent eventArgs) {}
 
         /**
-         * Returns the latest status of the GPS Measurements sub-system.
+         * Reports the latest status of the GNSS Measurements sub-system.
          */
         public void onStatusChanged(@GnssMeasurementsStatus int status) {}
     }
diff --git a/location/java/android/location/GnssNavigationMessage.java b/location/java/android/location/GnssNavigationMessage.java
index faefd0bb..ac255c8 100644
--- a/location/java/android/location/GnssNavigationMessage.java
+++ b/location/java/android/location/GnssNavigationMessage.java
@@ -16,6 +16,7 @@
 
 package android.location;
 
+import android.annotation.TestApi;
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.os.Parcel;
@@ -34,66 +35,71 @@
 
     /** The type of the GPS Clock. */
     @Retention(RetentionPolicy.SOURCE)
-    @IntDef({MESSAGE_TYPE_UNKNOWN, MESSAGE_TYPE_GPS_L1CA, MESSAGE_TYPE_GPS_L2CNAV,
-        MESSAGE_TYPE_GPS_L5CNAV, MESSAGE_TYPE_GPS_CNAV2, MESSAGE_TYPE_GLO_L1CA, MESSAGE_TYPE_BDS_D1,
-        MESSAGE_TYPE_BDS_D2, MESSAGE_TYPE_GAL_I, MESSAGE_TYPE_GAL_F})
+    @IntDef({TYPE_UNKNOWN, TYPE_GPS_L1CA, TYPE_GPS_L2CNAV, TYPE_GPS_L5CNAV, TYPE_GPS_CNAV2,
+        TYPE_GLO_L1CA, TYPE_BDS_D1, TYPE_BDS_D2, TYPE_GAL_I, TYPE_GAL_F})
     public @interface GnssNavigationMessageType {}
 
     // The following enumerations must be in sync with the values declared in gps.h
 
     /** Message type unknown */
-    public static final short MESSAGE_TYPE_UNKNOWN = 0;
+    public static final int TYPE_UNKNOWN = 0;
     /** GPS L1 C/A message contained in the structure.  */
-    public static final short MESSAGE_TYPE_GPS_L1CA = 0x0101;
+    public static final int TYPE_GPS_L1CA = 0x0101;
     /** GPS L2-CNAV message contained in the structure. */
-    public static final short MESSAGE_TYPE_GPS_L2CNAV = 0x0102;
+    public static final int TYPE_GPS_L2CNAV = 0x0102;
     /** GPS L5-CNAV message contained in the structure. */
-    public static final short MESSAGE_TYPE_GPS_L5CNAV = 0x0103;
+    public static final int TYPE_GPS_L5CNAV = 0x0103;
     /** GPS CNAV-2 message contained in the structure. */
-    public static final short MESSAGE_TYPE_GPS_CNAV2 = 0x0104;
+    public static final int TYPE_GPS_CNAV2 = 0x0104;
     /** Glonass L1 CA message contained in the structure. */
-    public static final short MESSAGE_TYPE_GLO_L1CA = 0x0301;
+    public static final int TYPE_GLO_L1CA = 0x0301;
     /** Beidou D1 message contained in the structure. */
-    public static final short MESSAGE_TYPE_BDS_D1 = 0x0501;
+    public static final int TYPE_BDS_D1 = 0x0501;
     /** Beidou D2 message contained in the structure. */
-    public static final short MESSAGE_TYPE_BDS_D2 = 0x0502;
+    public static final int TYPE_BDS_D2 = 0x0502;
     /** Galileo I/NAV message contained in the structure. */
-    public static final short MESSAGE_TYPE_GAL_I = 0x0601;
+    public static final int TYPE_GAL_I = 0x0601;
     /** Galileo F/NAV message contained in the structure. */
-    public static final short MESSAGE_TYPE_GAL_F = 0x0602;
+    public static final int TYPE_GAL_F = 0x0602;
 
     /**
      * The Navigation Message Status is 'unknown'.
      */
-    public static final short STATUS_UNKNOWN = 0;
+    public static final int STATUS_UNKNOWN = 0;
 
     /**
      * The Navigation Message was received without any parity error in its navigation words.
      */
-    public static final short STATUS_PARITY_PASSED = (1<<0);
+    public static final int STATUS_PARITY_PASSED = (1<<0);
 
     /**
      * The Navigation Message was received with words that failed parity check, but the receiver was
      * able to correct those words.
      */
-    public static final short STATUS_PARITY_REBUILT = (1<<1);
+    public static final int STATUS_PARITY_REBUILT = (1<<1);
 
     // End enumerations in sync with gps.h
 
-    private short mType;
-    private short mSvid;
-    private short mMessageId;
-    private short mSubmessageId;
+    private int mType;
+    private int mSvid;
+    private int mMessageId;
+    private int mSubmessageId;
     private byte[] mData;
-    private short mStatus;
+    private int mStatus;
 
-    GnssNavigationMessage() {
+    /**
+     * @hide
+     */
+    @TestApi
+    public GnssNavigationMessage() {
         initialize();
     }
 
     /**
      * Sets all contents to the values stored in the provided object.
+     * @hide
      */
+    @TestApi
     public void set(GnssNavigationMessage navigationMessage) {
         mType = navigationMessage.mType;
         mSvid = navigationMessage.mSvid;
@@ -105,7 +111,9 @@
 
     /**
      * Resets all the contents to its original state.
+     * @hide
      */
+    @TestApi
     public void reset() {
         initialize();
     }
@@ -114,14 +122,16 @@
      * Gets the type of the navigation message contained in the object.
      */
     @GnssNavigationMessageType
-    public short getType() {
+    public int getType() {
         return mType;
     }
 
     /**
      * Sets the type of the navigation message.
+     * @hide
      */
-    public void setType(@GnssNavigationMessageType short value) {
+    @TestApi
+    public void setType(@GnssNavigationMessageType int value) {
         mType = value;
     }
 
@@ -131,25 +141,25 @@
      */
     private String getTypeString() {
         switch (mType) {
-            case MESSAGE_TYPE_UNKNOWN:
+            case TYPE_UNKNOWN:
                 return "Unknown";
-            case MESSAGE_TYPE_GPS_L1CA:
+            case TYPE_GPS_L1CA:
                 return "GPS L1 C/A";
-            case MESSAGE_TYPE_GPS_L2CNAV:
+            case TYPE_GPS_L2CNAV:
                 return "GPS L2-CNAV";
-            case MESSAGE_TYPE_GPS_L5CNAV:
+            case TYPE_GPS_L5CNAV:
                 return "GPS L5-CNAV";
-            case MESSAGE_TYPE_GPS_CNAV2:
+            case TYPE_GPS_CNAV2:
                 return "GPS CNAV2";
-            case MESSAGE_TYPE_GLO_L1CA:
+            case TYPE_GLO_L1CA:
                 return "Glonass L1 C/A";
-            case MESSAGE_TYPE_BDS_D1:
+            case TYPE_BDS_D1:
                 return "Beidou D1";
-            case MESSAGE_TYPE_BDS_D2:
+            case TYPE_BDS_D2:
                 return "Beidou D2";
-            case MESSAGE_TYPE_GAL_I:
+            case TYPE_GAL_I:
                 return "Galileo I";
-            case MESSAGE_TYPE_GAL_F:
+            case TYPE_GAL_F:
                 return "Galileo F";
             default:
                 return "<Invalid:" + mType + ">";
@@ -160,14 +170,16 @@
      * Gets the Pseudo-random number.
      * Range: [1, 32].
      */
-    public short getSvid() {
+    public int getSvid() {
         return mSvid;
     }
 
     /**
      * Sets the Pseud-random number.
+     * @hide
      */
-    public void setSvid(short value) {
+    @TestApi
+    public void setSvid(int value) {
         mSvid = value;
     }
 
@@ -177,14 +189,16 @@
      * subframe 4 and 5, this value corresponds to the 'frame id' of the navigation message.
      * Subframe 1, 2, 3 does not contain a 'frame id' and this might be reported as -1.
      */
-    public short getMessageId() {
+    public int getMessageId() {
         return mMessageId;
     }
 
     /**
      * Sets the Message Identifier.
+     * @hide
      */
-    public void setMessageId(short value) {
+    @TestApi
+    public void setMessageId(int value) {
         mMessageId = value;
     }
 
@@ -194,14 +208,16 @@
      * (or frame) that is being transmitted. i.e. for L1 C/A the sub-message identifier corresponds
      * to the sub-frame Id of the navigation message.
      */
-    public short getSubmessageId() {
+    public int getSubmessageId() {
         return mSubmessageId;
     }
 
     /**
      * Sets the Sub-message identifier.
+     * @hide
      */
-    public void setSubmessageId(short value) {
+    @TestApi
+    public void setSubmessageId(int value) {
         mSubmessageId = value;
     }
 
@@ -216,7 +232,9 @@
 
     /**
      * Sets the data associated with the Navigation Message.
+     * @hide
      */
+    @TestApi
     public void setData(byte[] value) {
         if (value == null) {
             throw new InvalidParameterException("Data must be a non-null array");
@@ -228,14 +246,16 @@
     /**
      * Gets the Status of the navigation message contained in the object.
      */
-    public short getStatus() {
+    public int getStatus() {
         return mStatus;
     }
 
     /**
      * Sets the status of the navigation message.
+     * @hide
      */
-    public void setStatus(short value) {
+    @TestApi
+    public void setStatus(int value) {
         mStatus = value;
     }
 
@@ -262,10 +282,10 @@
         public GnssNavigationMessage createFromParcel(Parcel parcel) {
             GnssNavigationMessage navigationMessage = new GnssNavigationMessage();
 
-            navigationMessage.setType((short) parcel.readInt());
-            navigationMessage.setSvid((short) parcel.readInt());
-            navigationMessage.setMessageId((short) parcel.readInt());
-            navigationMessage.setSubmessageId((short) parcel.readInt());
+            navigationMessage.setType(parcel.readInt());
+            navigationMessage.setSvid(parcel.readInt());
+            navigationMessage.setMessageId(parcel.readInt());
+            navigationMessage.setSubmessageId(parcel.readInt());
 
             int dataLength = parcel.readInt();
             byte[] data = new byte[dataLength];
@@ -274,7 +294,7 @@
 
             if (parcel.dataAvail() >= Integer.SIZE) {
                 int status = parcel.readInt();
-                navigationMessage.setStatus((short) status);
+                navigationMessage.setStatus(status);
             } else {
                 navigationMessage.setStatus(STATUS_UNKNOWN);
             }
@@ -328,7 +348,7 @@
     }
 
     private void initialize() {
-        mType = MESSAGE_TYPE_UNKNOWN;
+        mType = TYPE_UNKNOWN;
         mSvid = 0;
         mMessageId = -1;
         mSubmessageId = -1;
diff --git a/location/java/android/location/GnssNavigationMessageEvent.java b/location/java/android/location/GnssNavigationMessageEvent.java
index 19c82e9..0df730d 100644
--- a/location/java/android/location/GnssNavigationMessageEvent.java
+++ b/location/java/android/location/GnssNavigationMessageEvent.java
@@ -32,7 +32,7 @@
 public final class GnssNavigationMessageEvent implements Parcelable {
     /** The status of GPS measurements event. */
     @Retention(RetentionPolicy.SOURCE)
-    @IntDef({STATUS_NOT_SUPPORTED, STATUS_READY, STATUS_GPS_LOCATION_DISABLED})
+    @IntDef({STATUS_NOT_SUPPORTED, STATUS_READY, STATUS_GNSS_LOCATION_DISABLED})
     public @interface GnssNavigationMessageStatus {}
 
     /**
@@ -50,7 +50,7 @@
     /**
      * GPS provider or Location is disabled, updated will not be received until they are enabled.
      */
-    public static final int STATUS_GPS_LOCATION_DISABLED = 2;
+    public static final int STATUS_GNSS_LOCATION_DISABLED = 2;
 
     private final GnssNavigationMessage mNavigationMessage;
 
diff --git a/location/java/android/location/GnssStatus.java b/location/java/android/location/GnssStatus.java
index 06ce30c..2a42fc6 100644
--- a/location/java/android/location/GnssStatus.java
+++ b/location/java/android/location/GnssStatus.java
@@ -27,19 +27,19 @@
  */
 public final class GnssStatus {
     /** Unknown constellation type. */
-    public static final byte CONSTELLATION_UNKNOWN = 0;
+    public static final int CONSTELLATION_UNKNOWN = 0;
     /** Constellation type constant for GPS. */
-    public static final byte CONSTELLATION_GPS = 1;
+    public static final int CONSTELLATION_GPS = 1;
     /** Constellation type constant for SBAS. */
-    public static final byte CONSTELLATION_SBAS = 2;
+    public static final int CONSTELLATION_SBAS = 2;
     /** Constellation type constant for Glonass. */
-    public static final byte CONSTELLATION_GLONASS = 3;
+    public static final int CONSTELLATION_GLONASS = 3;
     /** Constellation type constant for QZSS. */
-    public static final byte CONSTELLATION_QZSS = 4;
+    public static final int CONSTELLATION_QZSS = 4;
     /** Constellation type constant for Beidou. */
-    public static final byte CONSTELLATION_BEIDOU = 5;
+    public static final int CONSTELLATION_BEIDOU = 5;
     /** Constellation type constant for Galileo. */
-    public static final byte CONSTELLATION_GALILEO = 6;
+    public static final int CONSTELLATION_GALILEO = 6;
 
     /** Constellation type. */
     @Retention(RetentionPolicy.SOURCE)
@@ -66,16 +66,16 @@
 
     /* These package private values are modified by the LocationManager class */
     /* package */ int[] mSvidWithFlags;
-    /* package */ float[] mSnrs;
+    /* package */ float[] mCn0DbHz;
     /* package */ float[] mElevations;
     /* package */ float[] mAzimuths;
     /* package */ int mSvCount;
 
-    GnssStatus(int svCount, int[] svidWithFlags, float[] snrs, float[] elevations,
+    GnssStatus(int svCount, int[] svidWithFlags, float[] cn0s, float[] elevations,
             float[] azimuths) {
         mSvCount = svCount;
         mSvidWithFlags = svidWithFlags;
-        mSnrs = snrs;
+        mCn0DbHz = cn0s;
         mElevations = elevations;
         mAzimuths = azimuths;
     }
@@ -92,8 +92,8 @@
      * @param satIndex the index of the satellite in the list.
      */
     @ConstellationType
-    public byte getConstellationType(int satIndex) {
-        return (byte) ((mSvidWithFlags[satIndex] >> CONSTELLATION_TYPE_SHIFT_WIDTH)
+    public int getConstellationType(int satIndex) {
+        return ((mSvidWithFlags[satIndex] >> CONSTELLATION_TYPE_SHIFT_WIDTH)
                 & CONSTELLATION_TYPE_MASK);
     }
 
@@ -109,15 +109,15 @@
      * Retrieves the signal-noise ration of the satellite at the specified position.
      * @param satIndex the index of the satellite in the list.
      */
-    public float getSnr(int satIndex) {
-        return mSnrs[satIndex];
+    public float getCn0DbHz(int satIndex) {
+        return mCn0DbHz[satIndex];
     }
 
     /**
      * Retrieves the elevation of the satellite at the specified position.
      * @param satIndex the index of the satellite in the list.
      */
-    public float getElevation(int satIndex) {
+    public float getElevationDegrees(int satIndex) {
         return 0f;
     }
 
@@ -125,7 +125,7 @@
      * Retrieves the azimuth the satellite at the specified position.
      * @param satIndex the index of the satellite in the list.
      */
-    public float getAzimuth(int satIndex) {
+    public float getAzimuthDegrees(int satIndex) {
         return mAzimuths[satIndex];
     }
 
diff --git a/location/java/android/location/GnssStatusCallback.java b/location/java/android/location/GnssStatusCallback.java
index b86171b..0d2955a 100644
--- a/location/java/android/location/GnssStatusCallback.java
+++ b/location/java/android/location/GnssStatusCallback.java
@@ -32,13 +32,13 @@
 
     /**
      * Called when the GNSS system has received its first fix since starting.
-     * @param ttff the time from start to first fix.
+     * @param ttffMillis the time from start to first fix in milliseconds.
      */
-    public void onFirstFix(int ttff) {}
+    public void onFirstFix(int ttffMillis) {}
 
     /**
      * Called periodically to report GNSS satellite status.
      * @param status the current status of all satellites.
      */
     public void onSatelliteStatusChanged(GnssStatus status) {}
-}
\ No newline at end of file
+}
diff --git a/location/java/android/location/GpsStatus.java b/location/java/android/location/GpsStatus.java
index 7b3dd7d..bc518f9 100644
--- a/location/java/android/location/GpsStatus.java
+++ b/location/java/android/location/GpsStatus.java
@@ -138,7 +138,7 @@
     // For API-compat a public ctor() is not available
     GpsStatus() {}
 
-    private void setStatus(int svCount, int[] svidWithFlags, float[] snrs, float[] elevations,
+    private void setStatus(int svCount, int[] svidWithFlags, float[] cn0s, float[] elevations,
             float[] azimuths) {
         clearSatellites();
         for (int i = 0; i < svCount; i++) {
@@ -158,7 +158,7 @@
                 }
 
                 satellite.mValid = true;
-                satellite.mSnr = snrs[i];
+                satellite.mSnr = cn0s[i];
                 satellite.mElevation = elevations[i];
                 satellite.mAzimuth = azimuths[i];
                 satellite.mHasEphemeris =
@@ -179,7 +179,7 @@
      */
     void setStatus(GnssStatus status, int timeToFirstFix) {
         mTimeToFirstFix = timeToFirstFix;
-        setStatus(status.mSvCount, status.mSvidWithFlags, status.mSnrs, status.mElevations,
+        setStatus(status.mSvCount, status.mSvidWithFlags, status.mCn0DbHz, status.mElevations,
                 status.mAzimuths);
     }
 
diff --git a/location/java/android/location/IGnssStatusListener.aidl b/location/java/android/location/IGnssStatusListener.aidl
index 8c7d06e..d84614f 100644
--- a/location/java/android/location/IGnssStatusListener.aidl
+++ b/location/java/android/location/IGnssStatusListener.aidl
@@ -26,7 +26,7 @@
     void onGnssStarted();
     void onGnssStopped();
     void onFirstFix(int ttff);
-    void onSvStatusChanged(int svCount, in int[] svidWithFlags, in float[] snrs,
+    void onSvStatusChanged(int svCount, in int[] svidWithFlags, in float[] cn0s,
             in float[] elevations, in float[] azimuths);
     void onNmeaReceived(long timestamp, String nmea);
 }
diff --git a/location/java/android/location/LocationManager.java b/location/java/android/location/LocationManager.java
index e14e36d..28db099 100644
--- a/location/java/android/location/LocationManager.java
+++ b/location/java/android/location/LocationManager.java
@@ -307,7 +307,7 @@
             try {
                 mService.locationCallbackFinished(this);
             } catch (RemoteException e) {
-                Log.e(TAG, "locationCallbackFinished: RemoteException", e);
+                throw e.rethrowFromSystemServer();
             }
         }
     }
@@ -341,9 +341,8 @@
         try {
             return mService.getAllProviders();
         } catch (RemoteException e) {
-            Log.e(TAG, "RemoteException", e);
+            throw e.rethrowFromSystemServer();
         }
-        return null;
     }
 
     /**
@@ -357,9 +356,8 @@
         try {
             return mService.getProviders(null, enabledOnly);
         } catch (RemoteException e) {
-            Log.e(TAG, "RemoteException", e);
+            throw e.rethrowFromSystemServer();
         }
-        return null;
     }
 
     /**
@@ -382,9 +380,8 @@
             }
             return createProvider(name, properties);
         } catch (RemoteException e) {
-            Log.e(TAG, "RemoteException", e);
+            throw e.rethrowFromSystemServer();
         }
-        return null;
     }
 
     /**
@@ -402,9 +399,8 @@
         try {
             return mService.getProviders(criteria, enabledOnly);
         } catch (RemoteException e) {
-            Log.e(TAG, "RemoteException", e);
+            throw e.rethrowFromSystemServer();
         }
-        return null;
     }
 
     /**
@@ -434,9 +430,8 @@
         try {
             return mService.getBestProvider(criteria, enabledOnly);
         } catch (RemoteException e) {
-            Log.e(TAG, "RemoteException", e);
+            throw e.rethrowFromSystemServer();
         }
-        return null;
     }
 
     /**
@@ -885,7 +880,7 @@
         try {
             mService.requestLocationUpdates(request, transport, intent, packageName);
        } catch (RemoteException e) {
-           Log.e(TAG, "RemoteException", e);
+           throw e.rethrowFromSystemServer();
        }
     }
 
@@ -911,7 +906,7 @@
         try {
             mService.removeUpdates(transport, null, packageName);
         } catch (RemoteException e) {
-            Log.e(TAG, "RemoteException", e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -930,7 +925,7 @@
         try {
             mService.removeUpdates(null, intent, packageName);
         } catch (RemoteException e) {
-            Log.e(TAG, "RemoteException", e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -992,7 +987,7 @@
         try {
             mService.requestGeofence(request, fence, intent, mContext.getPackageName());
         } catch (RemoteException e) {
-            Log.e(TAG, "RemoteException", e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1040,7 +1035,7 @@
         try {
             mService.requestGeofence(request, fence, intent, mContext.getPackageName());
         } catch (RemoteException e) {
-            Log.e(TAG, "RemoteException", e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1067,7 +1062,7 @@
         try {
             mService.removeGeofence(null, intent, packageName);
         } catch (RemoteException e) {
-            Log.e(TAG, "RemoteException", e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1095,7 +1090,7 @@
         try {
             mService.removeGeofence(fence, intent, packageName);
         } catch (RemoteException e) {
-            Log.e(TAG, "RemoteException", e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1117,7 +1112,7 @@
         try {
             mService.removeGeofence(null, intent, packageName);
         } catch (RemoteException e) {
-            Log.e(TAG, "RemoteException", e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1148,8 +1143,7 @@
         try {
             return mService.isProviderEnabled(provider);
         } catch (RemoteException e) {
-            Log.e(TAG, "RemoteException", e);
-            return false;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1173,8 +1167,7 @@
         try {
             return mService.getLastLocation(null, packageName);
         } catch (RemoteException e) {
-            Log.e(TAG, "RemoteException", e);
-            return null;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1205,8 +1198,7 @@
         try {
             return mService.getLastLocation(request, packageName);
         } catch (RemoteException e) {
-            Log.e(TAG, "RemoteException", e);
-            return null;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1237,7 +1229,7 @@
         try {
             mService.addTestProvider(name, properties, mContext.getOpPackageName());
         } catch (RemoteException e) {
-            Log.e(TAG, "RemoteException", e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1255,7 +1247,7 @@
         try {
             mService.removeTestProvider(provider, mContext.getOpPackageName());
         } catch (RemoteException e) {
-            Log.e(TAG, "RemoteException", e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1292,7 +1284,7 @@
         try {
             mService.setTestProviderLocation(provider, loc, mContext.getOpPackageName());
         } catch (RemoteException e) {
-            Log.e(TAG, "RemoteException", e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1310,7 +1302,7 @@
         try {
             mService.clearTestProviderLocation(provider, mContext.getOpPackageName());
         } catch (RemoteException e) {
-            Log.e(TAG, "RemoteException", e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1330,7 +1322,7 @@
         try {
             mService.setTestProviderEnabled(provider, enabled, mContext.getOpPackageName());
         } catch (RemoteException e) {
-            Log.e(TAG, "RemoteException", e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1348,7 +1340,7 @@
         try {
             mService.clearTestProviderEnabled(provider, mContext.getOpPackageName());
         } catch (RemoteException e) {
-            Log.e(TAG, "RemoteException", e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1371,7 +1363,7 @@
             mService.setTestProviderStatus(provider, status, extras, updateTime,
                     mContext.getOpPackageName());
         } catch (RemoteException e) {
-            Log.e(TAG, "RemoteException", e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1389,7 +1381,7 @@
         try {
             mService.clearTestProviderStatus(provider, mContext.getOpPackageName());
         } catch (RemoteException e) {
-            Log.e(TAG, "RemoteException", e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1562,9 +1554,9 @@
 
         @Override
         public void onSvStatusChanged(int svCount, int[] prnWithFlags,
-                float[] snrs, float[] elevations, float[] azimuths) {
+                float[] cn0s, float[] elevations, float[] azimuths) {
             if (mGnssCallback != null) {
-                mGnssStatus = new GnssStatus(svCount, prnWithFlags, snrs, elevations, azimuths);
+                mGnssStatus = new GnssStatus(svCount, prnWithFlags, cn0s, elevations, azimuths);
 
                 Message msg = Message.obtain();
                 msg.what = GpsStatus.GPS_EVENT_SATELLITE_STATUS;
@@ -1615,8 +1607,7 @@
                 mGpsStatusListeners.put(listener, transport);
             }
         } catch (RemoteException e) {
-            Log.e(TAG, "RemoteException in registerGpsStatusListener: ", e);
-            result = false;
+            throw e.rethrowFromSystemServer();
         }
 
         return result;
@@ -1635,7 +1626,7 @@
                 mService.unregisterGnssStatusCallback(transport);
             }
         } catch (RemoteException e) {
-            Log.e(TAG, "RemoteException in unregisterGpsStatusListener: ", e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1679,8 +1670,7 @@
                 mGnssStatusListeners.put(callback, transport);
             }
         } catch (RemoteException e) {
-            Log.e(TAG, "RemoteException in registerGnssStatusCallback: ", e);
-            result = false;
+            throw e.rethrowFromSystemServer();
         }
 
         return result;
@@ -1698,7 +1688,7 @@
                 mService.unregisterGnssStatusCallback(transport);
             }
         } catch (RemoteException e) {
-            Log.e(TAG, "RemoteException in unregisterGnssStatusCallback: ", e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1728,8 +1718,7 @@
                 mGpsNmeaListeners.put(listener, transport);
             }
         } catch (RemoteException e) {
-            Log.e(TAG, "RemoteException in registerGpsStatusListener: ", e);
-            result = false;
+            throw e.rethrowFromSystemServer();
         }
 
         return result;
@@ -1748,7 +1737,7 @@
                 mService.unregisterGnssStatusCallback(transport);
             }
         } catch (RemoteException e) {
-            Log.e(TAG, "RemoteException in unregisterGpsStatusListener: ", e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1792,8 +1781,7 @@
                 mGnssNmeaListeners.put(listener, transport);
             }
         } catch (RemoteException e) {
-            Log.e(TAG, "RemoteException in registerGnssStatusCallback: ", e);
-            result = false;
+            throw e.rethrowFromSystemServer();
         }
 
         return result;
@@ -1811,13 +1799,13 @@
                 mService.unregisterGnssStatusCallback(transport);
             }
         } catch (RemoteException e) {
-            Log.e(TAG, "RemoteException in unregisterGnssStatusCallback: ", e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
     /**
      * No-op method to keep backward-compatibility.
-     * Don't use it. Use {@link #registerGnssMeasurementCallback} instead.
+     * Don't use it. Use {@link #registerGnssMeasurementsCallback} instead.
      * @hide
      * @deprecated
      */
@@ -1834,8 +1822,8 @@
      * @return {@code true} if the callback was added successfully, {@code false} otherwise.
      */
     @RequiresPermission(ACCESS_FINE_LOCATION)
-    public boolean registerGnssMeasurementCallback(GnssMeasurementsEvent.Callback callback) {
-        return registerGnssMeasurementCallback(callback, null);
+    public boolean registerGnssMeasurementsCallback(GnssMeasurementsEvent.Callback callback) {
+        return registerGnssMeasurementsCallback(callback, null);
     }
 
     /**
@@ -1846,14 +1834,14 @@
      * @return {@code true} if the callback was added successfully, {@code false} otherwise.
      */
     @RequiresPermission(ACCESS_FINE_LOCATION)
-    public boolean registerGnssMeasurementCallback(GnssMeasurementsEvent.Callback callback,
+    public boolean registerGnssMeasurementsCallback(GnssMeasurementsEvent.Callback callback,
             Handler handler) {
         return mGnssMeasurementCallbackTransport.add(callback, handler);
     }
 
     /**
      * No-op method to keep backward-compatibility.
-     * Don't use it. Use {@link #unregisterGnssMeasurementCallback} instead.
+     * Don't use it. Use {@link #unregisterGnssMeasurementsCallback} instead.
      * @hide
      * @deprecated
      */
@@ -1867,7 +1855,7 @@
      *
      * @param callback a {@link GnssMeasurementsEvent.Callback} object to remove.
      */
-    public void unregisterGnssMeasurementCallback(GnssMeasurementsEvent.Callback callback) {
+    public void unregisterGnssMeasurementsCallback(GnssMeasurementsEvent.Callback callback) {
         mGnssMeasurementCallbackTransport.remove(callback);
     }
 
@@ -1963,8 +1951,7 @@
         try {
             return mService.getGnssYearOfHardware();
         } catch (RemoteException e) {
-            Log.e(TAG, "RemoteException in getGnssSystemInfo: ", e);
-            return 0;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1983,8 +1970,7 @@
         try {
             return mService.sendExtraCommand(provider, command, extras);
         } catch (RemoteException e) {
-            Log.e(TAG, "RemoteException in sendExtraCommand: ", e);
-            return false;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1998,8 +1984,7 @@
         try {
             return mService.sendNiResponse(notifId, userResponse);
         } catch (RemoteException e) {
-            Log.e(TAG, "RemoteException in sendNiResponse: ", e);
-            return false;
+            throw e.rethrowFromSystemServer();
         }
     }
 
diff --git a/location/tests/locationtests/src/android/location/GpsStatusTest.java b/location/tests/locationtests/src/android/location/GpsStatusTest.java
index 4808faf..316e88d 100644
--- a/location/tests/locationtests/src/android/location/GpsStatusTest.java
+++ b/location/tests/locationtests/src/android/location/GpsStatusTest.java
@@ -40,7 +40,7 @@
     private GpsStatus mStatus;
     private int mCount;
     private int[] mPrns;
-    private float[] mSnrs;
+    private float[] mCn0s;
     private float[] mElevations;
     private float[] mAzimuth;
     private int mEphemerisMask;
@@ -179,7 +179,7 @@
 
     private void verifySatellites(GpsStatus status) {
         verifySatelliteCount(status, mCount);
-        verifySatellites(status, mCount, mPrns, mSnrs, mElevations, mAzimuth, mEphemerisMask,
+        verifySatellites(status, mCount, mPrns, mCn0s, mElevations, mAzimuth, mEphemerisMask,
                 mAlmanacMask, mUsedInFixMask);
     }
 
@@ -187,7 +187,7 @@
             GpsStatus status,
             int count,
             int[] prns,
-            float[] snrs,
+            float[] cn0s,
             float[] elevations,
             float[] azimuth,
             int ephemerisMask,
@@ -197,7 +197,7 @@
             int prn = prns[i];
             GpsSatellite satellite = getSatellite(status, prn);
             assertNotNull(getSatelliteAssertInfo(i, prn, "non-null"), satellite);
-            assertEquals(getSatelliteAssertInfo(i, prn, "Snr"), snrs[i], satellite.getSnr());
+            assertEquals(getSatelliteAssertInfo(i, prn, "Snr"), cn0s[i], satellite.getSnr());
             assertEquals(
                     getSatelliteAssertInfo(i, prn, "Elevation"),
                     elevations[i],
@@ -247,7 +247,7 @@
     }
 
     private void setSatellites(GpsStatus status) throws Exception {
-        set(status, mCount, mPrns, mSnrs, mElevations, mAzimuth, mEphemerisMask, mAlmanacMask,
+        set(status, mCount, mPrns, mCn0s, mElevations, mAzimuth, mEphemerisMask, mAlmanacMask,
                 mUsedInFixMask);
     }
 
@@ -255,7 +255,7 @@
             GpsStatus status,
             int count,
             int[] prns,
-            float[] snrs,
+            float[] cn0s,
             float[] elevations,
             float[] azimuth,
             int ephemerisMask,
@@ -279,7 +279,7 @@
                 status,
                 count,
                 prns,
-                snrs,
+                cn0s,
                 elevations,
                 azimuth,
                 ephemerisMask,
@@ -333,7 +333,7 @@
         if (!reusePrns) {
             mPrns = generateIntArray(count);
         }
-        mSnrs = generateFloatArray(count);
+        mCn0s = generateFloatArray(count);
         mElevations = generateFloatArray(count);
         mAzimuth = generateFloatArray(count);
         mEphemerisMask = generateMask(mPrns);
diff --git a/media/java/android/media/AudioFormat.java b/media/java/android/media/AudioFormat.java
index a0dfaa0f..abb6f4e 100644
--- a/media/java/android/media/AudioFormat.java
+++ b/media/java/android/media/AudioFormat.java
@@ -212,7 +212,7 @@
  * AudioTrack.getPlaybackHeadPosition()}),
  * depending on the context where audio frame is used.
  */
-public class AudioFormat implements Parcelable {
+public final class AudioFormat implements Parcelable {
 
     //---------------------------------------------------------
     // Constants
@@ -898,6 +898,26 @@
     }
 
     @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+
+        AudioFormat that = (AudioFormat) o;
+
+        if (mPropertySetMask != that.mPropertySetMask) return false;
+
+        // return false if any of the properties is set and the values differ
+        return !((((mPropertySetMask & AUDIO_FORMAT_HAS_PROPERTY_ENCODING) != 0)
+                            && (mEncoding != that.mEncoding))
+                    || (((mPropertySetMask & AUDIO_FORMAT_HAS_PROPERTY_SAMPLE_RATE) != 0)
+                            && (mSampleRate != that.mSampleRate))
+                    || (((mPropertySetMask & AUDIO_FORMAT_HAS_PROPERTY_CHANNEL_MASK) != 0)
+                            && (mChannelMask != that.mChannelMask))
+                    || (((mPropertySetMask & AUDIO_FORMAT_HAS_PROPERTY_CHANNEL_INDEX_MASK) != 0)
+                            && (mChannelIndexMask != that.mChannelIndexMask)));
+    }
+
+    @Override
     public int hashCode() {
         return Objects.hash(mPropertySetMask, mSampleRate, mEncoding, mChannelMask,
                 mChannelIndexMask);
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index 38e3b15..69d4487 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -177,16 +177,6 @@
         "android.media.MASTER_MUTE_CHANGED_ACTION";
 
     /**
-     * @hide Broadcast intent when the master mono state changes.
-     * Includes the new mono state
-     *
-     * @see #EXTRA_MASTER_MONO
-     */
-    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
-    public static final String MASTER_MONO_CHANGED_ACTION =
-        "android.media.MASTER_MONO_CHANGED_ACTION";
-
-    /**
      * The new vibrate setting for a particular type.
      *
      * @see #VIBRATE_SETTING_CHANGED_ACTION
@@ -265,13 +255,6 @@
         "android.media.EXTRA_STREAM_VOLUME_MUTED";
 
     /**
-     * @hide The new master mono state for the master mono changed intent.
-     * Value is boolean
-     */
-    public static final String EXTRA_MASTER_MONO =
-        "android.media.EXTRA_MASTER_MONO";
-
-    /**
      * Broadcast Action: Wired Headset plugged in or unplugged.
      *
      * You <em>cannot</em> receive this through components declared
@@ -826,7 +809,7 @@
             service.adjustStreamVolume(streamType, direction, flags,
                     getContext().getOpPackageName());
         } catch (RemoteException e) {
-            Log.e(TAG, "Dead object in adjustStreamVolume", e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -894,18 +877,7 @@
             service.setMasterMute(mute, flags, getContext().getOpPackageName(),
                     UserHandle.getCallingUserId());
         } catch (RemoteException e) {
-            Log.e(TAG, "Dead object in setMasterMute", e);
-        }
-    }
-
-    /** @hide */
-    public void setMasterMono(boolean mono) {
-        IAudioService service = getService();
-        try {
-            service.setMasterMono(mono, getContext().getOpPackageName(),
-                    UserHandle.getCallingUserId());
-        } catch (RemoteException e) {
-            Log.e(TAG, "Dead object in setMasterMono", e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -921,8 +893,7 @@
         try {
             return service.getRingerModeExternal();
         } catch (RemoteException e) {
-            Log.e(TAG, "Dead object in getRingerMode", e);
-            return RINGER_MODE_NORMAL;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -942,8 +913,7 @@
         try {
             return service.isValidRingerMode(ringerMode);
         } catch (RemoteException e) {
-            Log.e(TAG, "Dead object in isValidRingerMode", e);
-            return false;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -959,8 +929,7 @@
         try {
             return service.getStreamMaxVolume(streamType);
         } catch (RemoteException e) {
-            Log.e(TAG, "Dead object in getStreamMaxVolume", e);
-            return 0;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -977,8 +946,7 @@
         try {
             return service.getStreamMinVolume(streamType);
         } catch (RemoteException e) {
-            Log.e(TAG, "Dead object in getStreamMinVolume", e);
-            return 0;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -995,8 +963,7 @@
         try {
             return service.getStreamVolume(streamType);
         } catch (RemoteException e) {
-            Log.e(TAG, "Dead object in getStreamVolume", e);
-            return 0;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1010,8 +977,7 @@
         try {
             return service.getLastAudibleStreamVolume(streamType);
         } catch (RemoteException e) {
-            Log.e(TAG, "Dead object in getLastAudibleStreamVolume", e);
-            return 0;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1026,8 +992,7 @@
         try {
             return service.getUiSoundsStreamType();
         } catch (RemoteException e) {
-            Log.e(TAG, "Dead object in getUiSoundsStreamType", e);
-            return STREAM_RING;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1052,7 +1017,7 @@
         try {
             service.setRingerModeExternal(ringerMode, getContext().getOpPackageName());
         } catch (RemoteException e) {
-            Log.e(TAG, "Dead object in setRingerMode", e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1073,7 +1038,7 @@
         try {
             service.setStreamVolume(streamType, index, flags, getContext().getOpPackageName());
         } catch (RemoteException e) {
-            Log.e(TAG, "Dead object in setStreamVolume", e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1150,8 +1115,7 @@
         try {
             return service.isStreamMute(streamType);
         } catch (RemoteException e) {
-            Log.e(TAG, "Dead object in isStreamMute", e);
-            return false;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1165,23 +1129,7 @@
         try {
             return service.isMasterMute();
         } catch (RemoteException e) {
-            Log.e(TAG, "Dead object in isMasterMute", e);
-            return false;
-        }
-    }
-
-    /**
-     * get master mono state.
-     *
-     * @hide
-     */
-    public boolean isMasterMono() {
-        IAudioService service = getService();
-        try {
-            return service.isMasterMono();
-        } catch (RemoteException e) {
-            Log.e(TAG, "Dead object in isMasterMono", e);
-            return false;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1197,7 +1145,7 @@
         try {
             service.forceVolumeControlStream(streamType, mICallBack);
         } catch (RemoteException e) {
-            Log.e(TAG, "Dead object in forceVolumeControlStream", e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1225,8 +1173,7 @@
         try {
             return service.shouldVibrate(vibrateType);
         } catch (RemoteException e) {
-            Log.e(TAG, "Dead object in shouldVibrate", e);
-            return false;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1252,8 +1199,7 @@
         try {
             return service.getVibrateSetting(vibrateType);
         } catch (RemoteException e) {
-            Log.e(TAG, "Dead object in getVibrateSetting", e);
-            return VIBRATE_SETTING_OFF;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1280,7 +1226,7 @@
         try {
             service.setVibrateSetting(vibrateType, vibrateSetting);
         } catch (RemoteException e) {
-            Log.e(TAG, "Dead object in setVibrateSetting", e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1298,7 +1244,7 @@
         try {
             service.setSpeakerphoneOn(on);
         } catch (RemoteException e) {
-            Log.e(TAG, "Dead object in setSpeakerphoneOn", e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1312,8 +1258,7 @@
         try {
             return service.isSpeakerphoneOn();
         } catch (RemoteException e) {
-            Log.e(TAG, "Dead object in isSpeakerphoneOn", e);
-            return false;
+            throw e.rethrowFromSystemServer();
         }
      }
 
@@ -1454,7 +1399,7 @@
             service.startBluetoothSco(mICallBack,
                     getContext().getApplicationInfo().targetSdkVersion);
         } catch (RemoteException e) {
-            Log.e(TAG, "Dead object in startBluetoothSco", e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1478,7 +1423,7 @@
         try {
             service.startBluetoothScoVirtualCall(mICallBack);
         } catch (RemoteException e) {
-            Log.e(TAG, "Dead object in startBluetoothScoVirtualCall", e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1497,7 +1442,7 @@
         try {
             service.stopBluetoothSco(mICallBack);
         } catch (RemoteException e) {
-            Log.e(TAG, "Dead object in stopBluetoothSco", e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1515,7 +1460,7 @@
         try {
             service.setBluetoothScoOn(on);
         } catch (RemoteException e) {
-            Log.e(TAG, "Dead object in setBluetoothScoOn", e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1530,8 +1475,7 @@
         try {
             return service.isBluetoothScoOn();
         } catch (RemoteException e) {
-            Log.e(TAG, "Dead object in isBluetoothScoOn", e);
-            return false;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1603,7 +1547,7 @@
             service.setMicrophoneMute(on, getContext().getOpPackageName(),
                     UserHandle.getCallingUserId());
         } catch (RemoteException e) {
-            Log.e(TAG, "Dead object in setMicrophoneMute", e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1636,7 +1580,7 @@
         try {
             service.setMode(mode, mICallBack, mApplicationContext.getOpPackageName());
         } catch (RemoteException e) {
-            Log.e(TAG, "Dead object in setMode", e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1652,8 +1596,7 @@
         try {
             return service.getMode();
         } catch (RemoteException e) {
-            Log.e(TAG, "Dead object in getMode", e);
-            return MODE_INVALID;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1790,8 +1733,7 @@
         try {
             return service.getCurrentAudioFocus() == AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE;
         } catch (RemoteException e) {
-            Log.e(TAG, "Dead object in isAudioFocusExclusive()", e);
-            return false;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1957,7 +1899,7 @@
         try {
             service.playSoundEffect(effectType);
         } catch (RemoteException e) {
-            Log.e(TAG, "Dead object in playSoundEffect"+e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1992,7 +1934,7 @@
         try {
             service.playSoundEffect(effectType);
         } catch (RemoteException e) {
-            Log.e(TAG, "Dead object in playSoundEffect"+e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -2024,7 +1966,7 @@
         try {
             service.playSoundEffectVolume(effectType, volume);
         } catch (RemoteException e) {
-            Log.e(TAG, "Dead object in playSoundEffect"+e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -2046,7 +1988,7 @@
         try {
             service.loadSoundEffects();
         } catch (RemoteException e) {
-            Log.e(TAG, "Dead object in loadSoundEffects"+e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -2060,7 +2002,7 @@
         try {
             service.unloadSoundEffects();
         } catch (RemoteException e) {
-            Log.e(TAG, "Dead object in unloadSoundEffects"+e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -2205,9 +2147,10 @@
                                 }
                                 break;
                             case MSSG_RECORDING_CONFIG_CHANGE:
-                                final AudioRecordingCallback cb = (AudioRecordingCallback) msg.obj;
-                                if (cb != null) {
-                                    cb.onRecordConfigChanged();
+                                final RecordConfigChangeCallbackData cbData =
+                                        (RecordConfigChangeCallbackData) msg.obj;
+                                if (cbData.mCb != null) {
+                                    cbData.mCb.onRecordConfigChanged(cbData.mConfigs);
                                 }
                                 break;
                             default:
@@ -2471,7 +2414,7 @@
                     getContext().getOpPackageName() /* package name */, flags,
                     ap != null ? ap.cb() : null);
         } catch (RemoteException e) {
-            Log.e(TAG, "Can't call requestAudioFocus() on AudioService:", e);
+            throw e.rethrowFromSystemServer();
         }
         return status;
     }
@@ -2497,7 +2440,7 @@
                     AUDIOFOCUS_FLAG_LOCK,
                     null /* policy token */);
         } catch (RemoteException e) {
-            Log.e(TAG, "Can't call requestAudioFocusForCall() on AudioService:", e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -2513,7 +2456,7 @@
             service.abandonAudioFocus(null, AudioSystem.IN_VOICE_COMM_FOCUS_ID,
                     null /*AudioAttributes, legacy behavior*/);
         } catch (RemoteException e) {
-            Log.e(TAG, "Can't call abandonAudioFocusForCall() on AudioService:", e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -2542,7 +2485,7 @@
             status = service.abandonAudioFocus(mAudioFocusDispatcher,
                     getIdForAudioFocusListener(l), aa);
         } catch (RemoteException e) {
-            Log.e(TAG, "Can't call abandonAudioFocus() on AudioService:", e);
+            throw e.rethrowFromSystemServer();
         }
         return status;
     }
@@ -2756,8 +2699,7 @@
             }
             // successful registration
         } catch (RemoteException e) {
-            Log.e(TAG, "Dead object in registerAudioPolicyAsync()", e);
-            return ERROR;
+            throw e.rethrowFromSystemServer();
         }
         return SUCCESS;
     }
@@ -2776,7 +2718,7 @@
             service.unregisterAudioPolicyAsync(policy.cb());
             policy.setRegistration(null);
         } catch (RemoteException e) {
-            Log.e(TAG, "Dead object in unregisterAudioPolicyAsync()", e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -2788,13 +2730,16 @@
      * this abstract class and register it with
      * {@link AudioManager#registerAudioRecordingCallback(AudioRecordingCallback, Handler)}
      * to be notified.
-     * Use {@link AudioManager#getActiveRecordConfigurations()} to query the current configuration.
+     * Use {@link AudioManager#getActiveRecordingConfigurations()} to query the current
+     * configuration.
      */
     public static abstract class AudioRecordingCallback {
         /**
          * Called whenever the device recording configuration has changed.
+         * @param configs array containing the results of
+         *      {@link AudioManager#getActiveRecordingConfigurations()}.
          */
-        public void onRecordConfigChanged() {}
+        public void onRecordConfigChanged(AudioRecordingConfiguration[] configs) {}
     }
 
     private static class AudioRecordingCallbackInfo {
@@ -2806,6 +2751,17 @@
         }
     }
 
+    private final static class RecordConfigChangeCallbackData {
+        final AudioRecordingCallback mCb;
+        final AudioRecordingConfiguration[] mConfigs;
+
+        RecordConfigChangeCallbackData(AudioRecordingCallback cb,
+                AudioRecordingConfiguration[] configs) {
+            mCb = cb;
+            mConfigs = configs;
+        }
+    }
+
     /**
      * Register a callback to be notified of audio recording changes through
      * {@link AudioRecordingCallback}
@@ -2836,7 +2792,7 @@
                     try {
                         service.registerRecordingCallback(mRecCb);
                     } catch (RemoteException e) {
-                        Log.e(TAG, "Dead object in registerRecordingCallback", e);
+                        throw e.rethrowFromSystemServer();
                     }
                 }
             } else {
@@ -2868,7 +2824,7 @@
                     try {
                         service.unregisterRecordingCallback(mRecCb);
                     } catch (RemoteException e) {
-                        Log.e(TAG, "Dead object in unregisterRecordingCallback", e);
+                        throw e.rethrowFromSystemServer();
                     }
                 }
             } else {
@@ -2883,13 +2839,12 @@
      * @return a non-null array of recording configurations. An array of length 0 indicates there is
      *     no recording active when queried.
      */
-    public @NonNull AudioRecordConfiguration[] getActiveRecordConfigurations() {
+    public @NonNull AudioRecordingConfiguration[] getActiveRecordingConfigurations() {
         final IAudioService service = getService();
         try {
-            return service.getActiveRecordConfigurations();
+            return service.getActiveRecordingConfigurations();
         } catch (RemoteException e) {
-            Log.e(TAG, "Unable to retrieve active record configurations", e);
-            return null;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -2942,14 +2897,15 @@
 
     private final IRecordingConfigDispatcher mRecCb = new IRecordingConfigDispatcher.Stub() {
 
-        public void dispatchRecordingConfigChange() {
+        public void dispatchRecordingConfigChange(AudioRecordingConfiguration[] configs) {
             synchronized(mRecordCallbackLock) {
                 if (mRecordCallbackList != null) {
                     for (int i=0 ; i < mRecordCallbackList.size() ; i++) {
                         final AudioRecordingCallbackInfo arci = mRecordCallbackList.get(i);
                         if (arci.mHandler != null) {
                             final Message m = arci.mHandler.obtainMessage(
-                                    MSSG_RECORDING_CONFIG_CHANGE/*what*/, arci.mCb/*obj*/);
+                                    MSSG_RECORDING_CONFIG_CHANGE/*what*/,
+                                    new RecordConfigChangeCallbackData(arci.mCb, configs)/*obj*/);
                             arci.mHandler.sendMessage(m);
                         }
                     }
@@ -2972,7 +2928,7 @@
         try {
             service.reloadAudioSettings();
         } catch (RemoteException e) {
-            Log.e(TAG, "Dead object in reloadAudioSettings"+e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -2987,7 +2943,7 @@
         try {
             service.avrcpSupportsAbsoluteVolume(address, support);
         } catch (RemoteException e) {
-            Log.e(TAG, "Dead object in avrcpSupportsAbsoluteVolume", e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -3281,7 +3237,7 @@
             service.setWiredDeviceConnectionState(type, state, address, name,
                     mApplicationContext.getOpPackageName());
         } catch (RemoteException e) {
-            Log.e(TAG, "Dead object in setWiredDeviceConnectionState "+e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -3303,7 +3259,7 @@
         try {
             delay = service.setBluetoothA2dpDeviceConnectionState(device, state, profile);
         } catch (RemoteException e) {
-            Log.e(TAG, "Dead object in setBluetoothA2dpDeviceConnectionState "+e);
+            throw e.rethrowFromSystemServer();
         }
         return delay;
     }
@@ -3313,7 +3269,7 @@
         try {
             return getService().getRingtonePlayer();
         } catch (RemoteException e) {
-            return null;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -3408,7 +3364,7 @@
         try {
             getService().setVolumeController(controller);
         } catch (RemoteException e) {
-            Log.w(TAG, "Error setting volume controller", e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -3422,7 +3378,7 @@
         try {
             getService().notifyVolumeControllerVisible(controller, visible);
         } catch (RemoteException e) {
-            Log.w(TAG, "Error notifying about volume controller visibility", e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -3434,8 +3390,7 @@
         try {
             return getService().isStreamAffectedByRingerMode(streamType);
         } catch (RemoteException e) {
-            Log.w(TAG, "Error calling isStreamAffectedByRingerMode", e);
-            return false;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -3447,8 +3402,7 @@
         try {
             return getService().isStreamAffectedByMute(streamType);
         } catch (RemoteException e) {
-            Log.w(TAG, "Error calling isStreamAffectedByMute", e);
-            return false;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -3460,7 +3414,7 @@
         try {
             getService().disableSafeMediaVolume(mApplicationContext.getOpPackageName());
         } catch (RemoteException e) {
-            Log.w(TAG, "Error disabling safe media volume", e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -3472,7 +3426,7 @@
         try {
             getService().setRingerModeInternal(ringerMode, getContext().getOpPackageName());
         } catch (RemoteException e) {
-            Log.w(TAG, "Error calling setRingerModeInternal", e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -3484,8 +3438,7 @@
         try {
             return getService().getRingerModeInternal();
         } catch (RemoteException e) {
-            Log.w(TAG, "Error calling getRingerModeInternal", e);
-            return RINGER_MODE_NORMAL;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -3497,7 +3450,7 @@
         try {
             getService().setVolumePolicy(policy);
         } catch (RemoteException e) {
-            Log.w(TAG, "Error calling setVolumePolicy", e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -3512,8 +3465,7 @@
         try {
             return getService().setHdmiSystemAudioSupported(on);
         } catch (RemoteException e) {
-            Log.w(TAG, "Error setting system audio mode", e);
-            return AudioSystem.DEVICE_NONE;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -3527,8 +3479,7 @@
         try {
             return getService().isHdmiSystemAudioSupported();
         } catch (RemoteException e) {
-            Log.w(TAG, "Error querying system audio mode", e);
-            return false;
+            throw e.rethrowFromSystemServer();
         }
     }
 
diff --git a/media/java/android/media/AudioPatch.java b/media/java/android/media/AudioPatch.java
index acadb41..6c70213 100644
--- a/media/java/android/media/AudioPatch.java
+++ b/media/java/android/media/AudioPatch.java
@@ -53,6 +53,13 @@
         return mSinks;
     }
 
+    /**
+     * Get the system unique patch ID.
+     */
+    public int id() {
+        return mHandle.id();
+    }
+
     @Override
     public String toString() {
         StringBuilder s = new StringBuilder();
diff --git a/media/java/android/media/AudioRecord.java b/media/java/android/media/AudioRecord.java
index 8f6b178..3771474 100644
--- a/media/java/android/media/AudioRecord.java
+++ b/media/java/android/media/AudioRecord.java
@@ -374,7 +374,7 @@
         int initResult = native_setup( new WeakReference<AudioRecord>(this),
                 mAudioAttributes, sampleRate, mChannelMask, mChannelIndexMask,
                 mAudioFormat, mNativeBufferSizeInBytes,
-                session, ActivityThread.currentOpPackageName());
+                session, ActivityThread.currentOpPackageName(), 0 /*nativeRecordInJavaObj*/);
         if (initResult != SUCCESS) {
             loge("Error code "+initResult+" when initializing native AudioRecord object.");
             return; // with mState == STATE_UNINITIALIZED
@@ -390,12 +390,32 @@
      * A constructor which explicitly connects a Native (C++) AudioRecord. For use by
      * the AudioRecordRoutingProxy subclass.
      * @param nativeRecordInJavaObj A C/C++ pointer to a native AudioRecord
-     * (associated with an OpenSL ES recorder).
+     * (associated with an OpenSL ES recorder). Note: the caller must ensure a correct
+     * value here as no error checking is or can be done.
      */
     /*package*/ AudioRecord(long nativeRecordInJavaObj) {
-        mNativeRecorderInJavaObj = nativeRecordInJavaObj;
+        int[] session = { 0 };
+        int[] rates = { 0 };
+        //TODO: update native initialization when information about hardware init failure
+        //      due to capture device already open is available.
+        // Note that for this native_setup, we are providing an already created/initialized
+        // *Native* AudioRecord, so the attributes parameters to native_setup() are ignored.
+        int initResult = native_setup(new WeakReference<AudioRecord>(this),
+                null /*mAudioAttributes*/,
+                rates /*mSampleRates*/,
+                0 /*mChannelMask*/,
+                0 /*mChannelIndexMask*/,
+                0 /*mAudioFormat*/,
+                0 /*mNativeBufferSizeInBytes*/,
+                session,
+                ActivityThread.currentOpPackageName(),
+                nativeRecordInJavaObj);
+        if (initResult != SUCCESS) {
+            loge("Error code "+initResult+" when initializing native AudioRecord object.");
+            return; // with mState == STATE_UNINITIALIZED
+        }
 
-        // other initialization here...
+        mSessionId = session[0];
 
         mState = STATE_INITIALIZED;
     }
@@ -1712,12 +1732,16 @@
     private native final int native_setup(Object audiorecord_this,
             Object /*AudioAttributes*/ attributes,
             int[] sampleRate, int channelMask, int channelIndexMask, int audioFormat,
-            int buffSizeInBytes, int[] sessionId, String opPackageName);
+            int buffSizeInBytes, int[] sessionId, String opPackageName,
+            long nativeRecordInJavaObj);
 
     // TODO remove: implementation calls directly into implementation of native_release()
     private native final void native_finalize();
 
-    private native final void native_release();
+    /**
+     * @hide
+     */
+    public native final void native_release();
 
     private native final int native_start(int syncEvent, int sessionId);
 
diff --git a/media/java/android/media/AudioRecordConfiguration.java b/media/java/android/media/AudioRecordConfiguration.java
deleted file mode 100644
index 61d239c..0000000
--- a/media/java/android/media/AudioRecordConfiguration.java
+++ /dev/null
@@ -1,156 +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.media;
-
-import android.os.Parcel;
-import android.os.Parcelable;
-
-import java.util.Objects;
-
-/**
- * The AudioRecordConfiguration class collects the information describing an audio recording
- * session. This information is returned through the
- * {@link AudioManager#getActiveRecordConfigurations()} method.
- *
- */
-public class AudioRecordConfiguration implements Parcelable {
-
-    private final int mSessionId;
-
-    private final int mClientSource;
-
-    private final AudioFormat mDeviceFormat;
-    private final AudioFormat mClientFormat;
-
-    private final AudioDeviceInfo mRecDevice;
-
-    /**
-     * @hide
-     */
-    public AudioRecordConfiguration(int session, int source,
-            AudioFormat clientFormat, AudioFormat deviceFormat) {
-        mSessionId = session;
-        mClientSource = source;
-        mDeviceFormat = deviceFormat;
-        mClientFormat = clientFormat;
-        mRecDevice = null;
-    }
-
-    /**
-     * @hide
-     */
-    public AudioRecordConfiguration(int session, int source, AudioFormat devFormat,
-            AudioFormat clientFormat, AudioDeviceInfo device) {
-        mSessionId = session;
-        mClientSource = source;
-        mDeviceFormat = devFormat;
-        mClientFormat = clientFormat;
-        mRecDevice = device;
-    }
-
-    /**
-     * Returns the audio source being used for the recording.
-     * @return one of {@link MediaRecorder.AudioSource#MIC},
-     *       {@link MediaRecorder.AudioSource#VOICE_UPLINK},
-     *       {@link MediaRecorder.AudioSource#VOICE_DOWNLINK},
-     *       {@link MediaRecorder.AudioSource#VOICE_CALL},
-     *       {@link MediaRecorder.AudioSource#CAMCORDER},
-     *       {@link MediaRecorder.AudioSource#VOICE_RECOGNITION},
-     *       {@link MediaRecorder.AudioSource#VOICE_COMMUNICATION}.
-     */
-    public int getClientAudioSource() { return mClientSource; }
-
-    /**
-     * Returns the session number of the recording, see {@link AudioRecord#getAudioSessionId()}.
-     * @return the session number.
-     */
-    public int getClientAudioSessionId() { return mSessionId; }
-
-    /**
-     * Returns the audio format at which audio is recorded on this Android device.
-     * Note that it may differ from the client application recording format
-     * (see {@link #getClientFormat()}).
-     * @return the device recording format
-     */
-    public AudioFormat getFormat() { return mDeviceFormat; }
-
-    /**
-     * Returns the audio format at which the client application is recording audio.
-     * Note that it may differ from the actual recording format (see {@link #getFormat()}).
-     * @return the recording format
-     */
-    public AudioFormat getClientFormat() { return mClientFormat; }
-
-    /**
-     * Returns the audio input device used for this recording.
-     * @return the audio recording device
-     */
-    public AudioDeviceInfo getAudioDevice() { return mRecDevice; }
-
-    public static final Parcelable.Creator<AudioRecordConfiguration> CREATOR
-            = new Parcelable.Creator<AudioRecordConfiguration>() {
-        /**
-         * Rebuilds an AudioRecordConfiguration previously stored with writeToParcel().
-         * @param p Parcel object to read the AudioRecordConfiguration from
-         * @return a new AudioRecordConfiguration created from the data in the parcel
-         */
-        public AudioRecordConfiguration createFromParcel(Parcel p) {
-            return new AudioRecordConfiguration(p);
-        }
-        public AudioRecordConfiguration[] newArray(int size) {
-            return new AudioRecordConfiguration[size];
-        }
-    };
-
-    @Override
-    public int hashCode() {
-        return Objects.hash(mSessionId, mClientSource);
-    }
-
-    @Override
-    public int describeContents() {
-        return 0;
-    }
-
-    @Override
-    public void writeToParcel(Parcel dest, int flags) {
-        dest.writeInt(mSessionId);
-        dest.writeInt(mClientSource);
-        mClientFormat.writeToParcel(dest, 0);
-        mDeviceFormat.writeToParcel(dest, 0);
-        //TODO marshall device info
-    }
-
-    private AudioRecordConfiguration(Parcel in) {
-        mSessionId = in.readInt();
-        mClientSource = in.readInt();
-        mClientFormat = AudioFormat.CREATOR.createFromParcel(in);
-        mDeviceFormat = AudioFormat.CREATOR.createFromParcel(in);
-        //TODO unmarshall device info
-        mRecDevice = null;
-    }
-
-    @Override
-    public boolean equals(Object o) {
-        if (this == o) return true;
-        if (o == null || !(o instanceof AudioRecordConfiguration)) return false;
-
-        final AudioRecordConfiguration that = (AudioRecordConfiguration) o;
-         return ((mSessionId == that.mSessionId)
-                 && (mClientSource == that.mClientSource));
-    }
-}
\ No newline at end of file
diff --git a/media/java/android/media/AudioRecordConfiguration.aidl b/media/java/android/media/AudioRecordingConfiguration.aidl
similarity index 93%
rename from media/java/android/media/AudioRecordConfiguration.aidl
rename to media/java/android/media/AudioRecordingConfiguration.aidl
index afe912b..c63d30b 100644
--- a/media/java/android/media/AudioRecordConfiguration.aidl
+++ b/media/java/android/media/AudioRecordingConfiguration.aidl
@@ -15,4 +15,4 @@
 
 package android.media;
 
-parcelable AudioRecordConfiguration;
+parcelable AudioRecordingConfiguration;
diff --git a/media/java/android/media/AudioRecordingConfiguration.java b/media/java/android/media/AudioRecordingConfiguration.java
new file mode 100644
index 0000000..cd6f95a
--- /dev/null
+++ b/media/java/android/media/AudioRecordingConfiguration.java
@@ -0,0 +1,194 @@
+/*
+ * 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;
+
+import android.annotation.IntDef;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.util.Log;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.ArrayList;
+import java.util.Objects;
+
+/**
+ * The AudioRecordingConfiguration class collects the information describing an audio recording
+ * session. This information is returned through the
+ * {@link AudioManager#getActiveRecordingConfigurations()} method.
+ *
+ */
+public final class AudioRecordingConfiguration implements Parcelable {
+    private final static String TAG = new String("AudioRecordingConfiguration");
+
+    private final int mSessionId;
+
+    private final int mClientSource;
+
+    private final AudioFormat mDeviceFormat;
+    private final AudioFormat mClientFormat;
+
+    private final int mPatchHandle;
+
+    /**
+     * @hide
+     */
+    public AudioRecordingConfiguration(int session, int source, AudioFormat devFormat,
+            AudioFormat clientFormat, int patchHandle) {
+        mSessionId = session;
+        mClientSource = source;
+        mDeviceFormat = devFormat;
+        mClientFormat = clientFormat;
+        mPatchHandle = patchHandle;
+    }
+
+    /** @hide */
+    @IntDef({
+        MediaRecorder.AudioSource.DEFAULT,
+        MediaRecorder.AudioSource.VOICE_UPLINK,
+        MediaRecorder.AudioSource.VOICE_DOWNLINK,
+        MediaRecorder.AudioSource.VOICE_CALL,
+        MediaRecorder.AudioSource.CAMCORDER,
+        MediaRecorder.AudioSource.VOICE_RECOGNITION,
+        MediaRecorder.AudioSource.VOICE_COMMUNICATION
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface AudioSource {}
+
+    /**
+     * Returns the audio source being used for the recording.
+     * @return one of {@link MediaRecorder.AudioSource#MIC},
+     *       {@link MediaRecorder.AudioSource#VOICE_UPLINK},
+     *       {@link MediaRecorder.AudioSource#VOICE_DOWNLINK},
+     *       {@link MediaRecorder.AudioSource#VOICE_CALL},
+     *       {@link MediaRecorder.AudioSource#CAMCORDER},
+     *       {@link MediaRecorder.AudioSource#VOICE_RECOGNITION},
+     *       {@link MediaRecorder.AudioSource#VOICE_COMMUNICATION}.
+     */
+    public @AudioSource int getClientAudioSource() { return mClientSource; }
+
+    /**
+     * Returns the session number of the recording, see {@link AudioRecord#getAudioSessionId()}.
+     * @return the session number.
+     */
+    public int getClientAudioSessionId() { return mSessionId; }
+
+    /**
+     * Returns the audio format at which audio is recorded on this Android device.
+     * Note that it may differ from the client application recording format
+     * (see {@link #getClientFormat()}).
+     * @return the device recording format
+     */
+    public AudioFormat getFormat() { return mDeviceFormat; }
+
+    /**
+     * Returns the audio format at which the client application is recording audio.
+     * Note that it may differ from the actual recording format (see {@link #getFormat()}).
+     * @return the recording format
+     */
+    public AudioFormat getClientFormat() { return mClientFormat; }
+
+    /**
+     * Returns information about the audio input device used for this recording.
+     * @return the audio recording device or null if this information cannot be retrieved
+     */
+    public AudioDeviceInfo getAudioDevice() {
+        // build the AudioDeviceInfo from the patch handle
+        ArrayList<AudioPatch> patches = new ArrayList<AudioPatch>();
+        if (AudioManager.listAudioPatches(patches) != AudioManager.SUCCESS) {
+            Log.e(TAG, "Error retrieving list of audio patches");
+            return null;
+        }
+        for (int i = 0 ; i < patches.size() ; i++) {
+            final AudioPatch patch = patches.get(i);
+            if (patch.id() == mPatchHandle) {
+                final AudioPortConfig[] sources = patch.sources();
+                if ((sources != null) && (sources.length > 0)) {
+                    // not supporting multiple sources, so just look at the first source
+                    final int devId = sources[0].port().id();
+                    final AudioDeviceInfo[] devices =
+                            AudioManager.getDevicesStatic(AudioManager.GET_DEVICES_INPUTS);
+                    for (int j = 0; j < devices.length; j++) {
+                        if (devices[j].getId() == devId) {
+                            return devices[j];
+                        }
+                    }
+                }
+                // patch handle is unique, there won't be another with the same handle
+                break;
+            }
+        }
+        Log.e(TAG, "Couldn't find device for recording, did recording end already?");
+        return null;
+    }
+
+    public static final Parcelable.Creator<AudioRecordingConfiguration> CREATOR
+            = new Parcelable.Creator<AudioRecordingConfiguration>() {
+        /**
+         * Rebuilds an AudioRecordingConfiguration previously stored with writeToParcel().
+         * @param p Parcel object to read the AudioRecordingConfiguration from
+         * @return a new AudioRecordingConfiguration created from the data in the parcel
+         */
+        public AudioRecordingConfiguration createFromParcel(Parcel p) {
+            return new AudioRecordingConfiguration(p);
+        }
+        public AudioRecordingConfiguration[] newArray(int size) {
+            return new AudioRecordingConfiguration[size];
+        }
+    };
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(mSessionId, mClientSource);
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeInt(mSessionId);
+        dest.writeInt(mClientSource);
+        mClientFormat.writeToParcel(dest, 0);
+        mDeviceFormat.writeToParcel(dest, 0);
+        dest.writeInt(mPatchHandle);
+    }
+
+    private AudioRecordingConfiguration(Parcel in) {
+        mSessionId = in.readInt();
+        mClientSource = in.readInt();
+        mClientFormat = AudioFormat.CREATOR.createFromParcel(in);
+        mDeviceFormat = AudioFormat.CREATOR.createFromParcel(in);
+        mPatchHandle = in.readInt();
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || !(o instanceof AudioRecordingConfiguration)) return false;
+
+        AudioRecordingConfiguration that = (AudioRecordingConfiguration) o;
+
+        return ((mSessionId == that.mSessionId)
+                && (mClientSource == that.mClientSource)
+                && (mPatchHandle == that.mPatchHandle)
+                && (mClientFormat.equals(that.mClientFormat))
+                && (mDeviceFormat.equals(that.mDeviceFormat)));
+    }
+}
\ No newline at end of file
diff --git a/media/java/android/media/AudioRouting.java b/media/java/android/media/AudioRouting.java
index 2161cf3..41f92d4 100644
--- a/media/java/android/media/AudioRouting.java
+++ b/media/java/android/media/AudioRouting.java
@@ -41,6 +41,14 @@
     public AudioDeviceInfo getPreferredDevice();
 
     /**
+     * Returns an {@link AudioDeviceInfo} identifying the current routing of this
+     * AudioTrack/AudioRecord.
+     * Note: The query is only valid if the AudioTrack/AudioRecord is currently playing.
+     * If it is not, <code>getRoutedDevice()</code> will return null.
+     */
+    public AudioDeviceInfo getRoutedDevice();
+
+    /**
      * Adds an {@link AudioRouting.OnRoutingChangedListener} to receive notifications of routing
      * changes on this AudioTrack/AudioRecord.
      * @param listener The {@link AudioRouting.OnRoutingChangedListener} interface to receive
diff --git a/media/java/android/media/AudioSystem.java b/media/java/android/media/AudioSystem.java
index 59782cb..f597440 100644
--- a/media/java/android/media/AudioSystem.java
+++ b/media/java/android/media/AudioSystem.java
@@ -279,8 +279,14 @@
          * @param session
          * @param source
          * @param recordingFormat an array of ints containing respectively the client and device
-         *    recording configuration. Each set of parameters contains the following parameters
-         *    in this order: format, channel mask, sample rate
+         *    recording configurations (2*3 ints), followed by the patch handle:
+         *    index 0: client format
+         *          1: client channel mask
+         *          2: client sample rate
+         *          3: device format
+         *          4: device channel mask
+         *          5: device sample rate
+         *          6: patch handle
          */
         void onRecordingConfigurationChanged(int event, int session, int source,
                 int[] recordingFormat);
@@ -632,7 +638,7 @@
     public static final int PHONE_STATE_RINGING = 1;
     public static final int PHONE_STATE_INCALL = 2;
 
-    // device categories config for setForceUse, must match AudioSystem::forced_config
+    // device categories config for setForceUse, must match audio_policy_forced_cfg_t
     public static final int FORCE_NONE = 0;
     public static final int FORCE_SPEAKER = 1;
     public static final int FORCE_HEADPHONES = 2;
@@ -646,17 +652,20 @@
     public static final int FORCE_NO_BT_A2DP = 10;
     public static final int FORCE_SYSTEM_ENFORCED = 11;
     public static final int FORCE_HDMI_SYSTEM_AUDIO_ENFORCED = 12;
-    private static final int NUM_FORCE_CONFIG = 13;
+    public static final int FORCE_ENCODED_SURROUND_NEVER = 13;
+    public static final int FORCE_ENCODED_SURROUND_ALWAYS = 14;
+    public static final int NUM_FORCE_CONFIG = 15;
     public static final int FORCE_DEFAULT = FORCE_NONE;
 
-    // usage for setForceUse, must match AudioSystem::force_use
+    // usage for setForceUse, must match audio_policy_force_use_t
     public static final int FOR_COMMUNICATION = 0;
     public static final int FOR_MEDIA = 1;
     public static final int FOR_RECORD = 2;
     public static final int FOR_DOCK = 3;
     public static final int FOR_SYSTEM = 4;
     public static final int FOR_HDMI_SYSTEM_AUDIO = 5;
-    private static final int NUM_FORCE_USE = 6;
+    public static final int FOR_ENCODED_SURROUND = 6;
+    private static final int NUM_FORCE_USE = 7;
 
     // usage for AudioRecord.startRecordingSync(), must match AudioSystem::sync_event_t
     public static final int SYNC_EVENT_NONE = 0;
diff --git a/media/java/android/media/AudioTrack.java b/media/java/android/media/AudioTrack.java
index 708768c..2aac2b3 100644
--- a/media/java/android/media/AudioTrack.java
+++ b/media/java/android/media/AudioTrack.java
@@ -505,7 +505,7 @@
         // native initialization
         int initResult = native_setup(new WeakReference<AudioTrack>(this), mAttributes,
                 sampleRate, mChannelMask, mChannelIndexMask, mAudioFormat,
-                mNativeBufferSizeInBytes, mDataLoadMode, session);
+                mNativeBufferSizeInBytes, mDataLoadMode, session, 0 /*nativeTrackInJavaObj*/);
         if (initResult != SUCCESS) {
             loge("Error code "+initResult+" when initializing AudioTrack.");
             return; // with mState == STATE_UNINITIALIZED
@@ -528,8 +528,6 @@
      * (associated with an OpenSL ES player).
      */
     /*package*/ AudioTrack(long nativeTrackInJavaObj) {
-        mNativeTrackInJavaObj = nativeTrackInJavaObj;
-
         // "final"s
         mAttributes = null;
         mAppOps = null;
@@ -542,6 +540,26 @@
         mInitializationLooper = looper;
 
         // other initialization...
+        // Note that for this native_setup, we are providing an already created/initialized
+        // *Native* AudioTrack, so the attributes parameters to native_setup() are ignored.
+        int[] session = { 0 };
+        int[] rates = { 0 };
+        int initResult = native_setup(new WeakReference<AudioTrack>(this),
+                null /*mAttributes - NA*/,
+                rates /*sampleRate - NA*/,
+                0 /*mChannelMask - NA*/,
+                0 /*mChannelIndexMask - NA*/,
+                0 /*mAudioFormat - NA*/,
+                0 /*mNativeBufferSizeInBytes - NA*/,
+                0 /*mDataLoadMode - NA*/,
+                session,
+                nativeTrackInJavaObj);
+        if (initResult != SUCCESS) {
+            loge("Error code "+initResult+" when initializing AudioTrack.");
+            return; // with mState == STATE_UNINITIALIZED
+        }
+
+        mSessionId = session[0];
 
         mState = STATE_INITIALIZED;
     }
@@ -1196,13 +1214,12 @@
      * An underrun occurs if the application does not write audio
      * data quickly enough, causing the buffer to underflow
      * and a potential audio glitch or pop.
+     * <p>
      * Underruns are less likely when buffer sizes are large.
-     * <p> Though the "int" type is signed 32-bits, the value should be reinterpreted
-     * as if it is unsigned 32-bits.
-     * That is, the next position after 0x7FFFFFFF is (int) 0x80000000.
-     * This is a continuously advancing counter. It can wrap around to zero
-     * if there are too many underruns. If there were, for example, 68 underruns per
-     * second then the counter would wrap in 2 years.
+     * It may be possible to eliminate underruns by recreating the AudioTrack with
+     * a larger buffer.
+     * Or by using {@link #setBufferSizeInFrames(int)} to dynamically increase the
+     * effective size of the buffer.
      */
     public int getUnderrunCount() {
         return native_get_underrun_count();
@@ -2773,11 +2790,14 @@
     private native final int native_setup(Object /*WeakReference<AudioTrack>*/ audiotrack_this,
             Object /*AudioAttributes*/ attributes,
             int[] sampleRate, int channelMask, int channelIndexMask, int audioFormat,
-            int buffSizeInBytes, int mode, int[] sessionId);
+            int buffSizeInBytes, int mode, int[] sessionId, long nativeAudioTrack);
 
     private native final void native_finalize();
 
-    private native final void native_release();
+    /**
+     * @hide
+     */
+    public native final void native_release();
 
     private native final void native_start();
 
diff --git a/media/java/android/media/ExifInterface.java b/media/java/android/media/ExifInterface.java
index 1a387be..ce12e76 100644
--- a/media/java/android/media/ExifInterface.java
+++ b/media/java/android/media/ExifInterface.java
@@ -16,14 +16,16 @@
 
 package android.media;
 
+import android.annotation.NonNull;
+import android.content.res.AssetManager;
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
 import android.system.ErrnoException;
 import android.system.Os;
 import android.system.OsConstants;
 import android.util.Log;
-import android.util.Pair;
 
+import java.io.BufferedInputStream;
 import java.io.ByteArrayInputStream;
 import java.io.DataInputStream;
 import java.io.DataOutputStream;
@@ -44,6 +46,7 @@
 import java.util.Date;
 import java.util.HashMap;
 import java.util.Map;
+import java.util.Set;
 import java.util.TimeZone;
 import java.util.regex.Pattern;
 
@@ -62,89 +65,273 @@
     private static final boolean DEBUG = false;
 
     // The Exif tag names
+    /** Type is String. */
+    public static final String TAG_ARTIST = "Artist";
     /** Type is int. */
-    public static final String TAG_ORIENTATION = "Orientation";
+    public static final String TAG_BITS_PER_SAMPLE = "BitsPerSample";
+    /** Type is int. */
+    public static final String TAG_COMPRESSION = "Compression";
+    /** Type is String. */
+    public static final String TAG_COPYRIGHT = "Copyright";
     /** Type is String. */
     public static final String TAG_DATETIME = "DateTime";
     /** Type is String. */
+    public static final String TAG_IMAGE_DESCRIPTION = "ImageDescription";
+    /** Type is int. */
+    public static final String TAG_IMAGE_LENGTH = "ImageLength";
+    /** Type is int. */
+    public static final String TAG_IMAGE_WIDTH = "ImageWidth";
+    /** Type is int. */
+    public static final String TAG_JPEG_INTERCHANGE_FORMAT = "JPEGInterchangeFormat";
+    /** Type is int. */
+    public static final String TAG_JPEG_INTERCHANGE_FORMAT_LENGTH = "JPEGInterchangeFormatLength";
+    /** Type is String. */
     public static final String TAG_MAKE = "Make";
     /** Type is String. */
     public static final String TAG_MODEL = "Model";
     /** Type is int. */
-    public static final String TAG_FLASH = "Flash";
+    public static final String TAG_ORIENTATION = "Orientation";
     /** Type is int. */
-    public static final String TAG_IMAGE_WIDTH = "ImageWidth";
+    public static final String TAG_PHOTOMETRIC_INTERPRETATION = "PhotometricInterpretation";
     /** Type is int. */
-    public static final String TAG_IMAGE_LENGTH = "ImageLength";
-    /** String. Format is "num1/denom1,num2/denom2,num3/denom3". */
-    public static final String TAG_GPS_LATITUDE = "GPSLatitude";
-    /** String. Format is "num1/denom1,num2/denom2,num3/denom3". */
-    public static final String TAG_GPS_LONGITUDE = "GPSLongitude";
+    public static final String TAG_PLANAR_CONFIGURATION = "PlanarConfiguration";
+    /** Type is rational. */
+    public static final String TAG_PRIMARY_CHROMATICITIES = "PrimaryChromaticities";
+    /** Type is rational. */
+    public static final String TAG_REFERENCE_BLACK_WHITE = "ReferenceBlackWhite";
+    /** Type is int. */
+    public static final String TAG_RESOLUTION_UNIT = "ResolutionUnit";
+    /** Type is int. */
+    public static final String TAG_ROWS_PER_STRIP = "RowsPerStrip";
+    /** Type is int. */
+    public static final String TAG_SAMPLES_PER_PIXEL = "SamplesPerPixel";
     /** Type is String. */
-    public static final String TAG_GPS_LATITUDE_REF = "GPSLatitudeRef";
+    public static final String TAG_SOFTWARE = "Software";
+    /** Type is int. */
+    public static final String TAG_STRIP_BYTE_COUNTS = "StripByteCounts";
+    /** Type is int. */
+    public static final String TAG_STRIP_OFFSETS = "StripOffsets";
+    /** Type is int. */
+    public static final String TAG_TRANSFER_FUNCTION = "TransferFunction";
+    /** Type is rational. */
+    public static final String TAG_WHITE_POINT = "WhitePoint";
+    /** Type is rational. */
+    public static final String TAG_X_RESOLUTION = "XResolution";
+    /** Type is rational. */
+    public static final String TAG_Y_CB_CR_COEFFICIENTS = "YCbCrCoefficients";
+    /** Type is int. */
+    public static final String TAG_Y_CB_CR_POSITIONING = "YCbCrPositioning";
+    /** Type is int. */
+    public static final String TAG_Y_CB_CR_SUB_SAMPLING = "YCbCrSubSampling";
+    /** Type is rational. */
+    public static final String TAG_Y_RESOLUTION = "YResolution";
+    /** Type is rational. */
+    public static final String TAG_APERTURE_VALUE = "ApertureValue";
+    /** Type is rational. */
+    public static final String TAG_BRIGHTNESS_VALUE = "BrightnessValue";
     /** Type is String. */
-    public static final String TAG_GPS_LONGITUDE_REF = "GPSLongitudeRef";
+    public static final String TAG_CFA_PATTERN = "CFAPattern";
+    /** Type is int. */
+    public static final String TAG_COLOR_SPACE = "ColorSpace";
     /** Type is String. */
+    public static final String TAG_COMPONENTS_CONFIGURATION = "ComponentsConfiguration";
+    /** Type is rational. */
+    public static final String TAG_COMPRESSED_BITS_PER_PIXEL = "CompressedBitsPerPixel";
+    /** Type is int. */
+    public static final String TAG_CONTRAST = "Contrast";
+    /** Type is int. */
+    public static final String TAG_CUSTOM_RENDERED = "CustomRendered";
+    /** Type is String. */
+    public static final String TAG_DATETIME_DIGITIZED = "DateTimeDigitized";
+    /** Type is String. */
+    public static final String TAG_DATETIME_ORIGINAL = "DateTimeOriginal";
+    /** Type is String. */
+    public static final String TAG_DEVICE_SETTING_DESCRIPTION = "DeviceSettingDescription";
+    /** Type is double. */
+    public static final String TAG_DIGITAL_ZOOM_RATIO = "DigitalZoomRatio";
+    /** Type is String. */
+    public static final String TAG_EXIF_VERSION = "ExifVersion";
+    /** Type is double. */
+    public static final String TAG_EXPOSURE_BIAS_VALUE = "ExposureBiasValue";
+    /** Type is rational. */
+    public static final String TAG_EXPOSURE_INDEX = "ExposureIndex";
+    /** Type is int. */
+    public static final String TAG_EXPOSURE_MODE = "ExposureMode";
+    /** Type is int. */
+    public static final String TAG_EXPOSURE_PROGRAM = "ExposureProgram";
+    /** Type is double. */
     public static final String TAG_EXPOSURE_TIME = "ExposureTime";
     /** Type is String. */
+    public static final String TAG_F_NUMBER = "FNumber";
+    /** Type is String. */
     public static final String TAG_APERTURE = "FNumber";
     /** Type is String. */
+    public static final String TAG_FILE_SOURCE = "FileSource";
+    /** Type is int. */
+    public static final String TAG_FLASH = "Flash";
+    /** Type is rational. */
+    public static final String TAG_FLASH_ENERGY = "FlashEnergy";
+    /** Type is String. */
+    public static final String TAG_FLASHPIX_VERSION = "FlashpixVersion";
+    /** Type is rational. */
+    public static final String TAG_FOCAL_LENGTH = "FocalLength";
+    /** Type is int. */
+    public static final String TAG_FOCAL_LENGTH_IN_35MM_FILM = "FocalLengthIn35mmFilm";
+    /** Type is int. */
+    public static final String TAG_FOCAL_PLANE_RESOLUTION_UNIT = "FocalPlaneResolutionUnit";
+    /** Type is rational. */
+    public static final String TAG_FOCAL_PLANE_X_RESOLUTION = "FocalPlaneXResolution";
+    /** Type is rational. */
+    public static final String TAG_FOCAL_PLANE_Y_RESOLUTION = "FocalPlaneYResolution";
+    /** Type is rational. */
+    public static final String TAG_GAIN_CONTROL = "GainControl";
+    /** Type is String. */
+    public static final String TAG_ISO_SPEED_RATINGS = "ISOSpeedRatings";
+    /** Type is String. */
     public static final String TAG_ISO = "ISOSpeedRatings";
     /** Type is String. */
-    public static final String TAG_DATETIME_DIGITIZED = "DateTimeDigitized";
+    public static final String TAG_IMAGE_UNIQUE_ID = "ImageUniqueID";
+    /** Type is int. */
+    public static final String TAG_LIGHT_SOURCE = "LightSource";
+    /** Type is String. */
+    public static final String TAG_MAKER_NOTE = "MakerNote";
+    /** Type is rational. */
+    public static final String TAG_MAX_APERTURE_VALUE = "MaxApertureValue";
+    /** Type is int. */
+    public static final String TAG_METERING_MODE = "MeteringMode";
+    /** Type is String. */
+    public static final String TAG_OECF = "OECF";
+    /** Type is int. */
+    public static final String TAG_PIXEL_X_DIMENSION = "PixelXDimension";
+    /** Type is int. */
+    public static final String TAG_PIXEL_Y_DIMENSION = "PixelYDimension";
+    /** Type is String. */
+    public static final String TAG_RELATED_SOUND_FILE = "RelatedSoundFile";
+    /** Type is int. */
+    public static final String TAG_SATURATION = "Saturation";
+    /** Type is int. */
+    public static final String TAG_SCENE_CAPTURE_TYPE = "SceneCaptureType";
+    /** Type is String. */
+    public static final String TAG_SCENE_TYPE = "SceneType";
+    /** Type is int. */
+    public static final String TAG_SENSING_METHOD = "SensingMethod";
+    /** Type is int. */
+    public static final String TAG_SHARPNESS = "Sharpness";
+    /** Type is rational. */
+    public static final String TAG_SHUTTER_SPEED_VALUE = "ShutterSpeedValue";
+    /** Type is String. */
+    public static final String TAG_SPATIAL_FREQUENCY_RESPONSE = "SpatialFrequencyResponse";
+    /** Type is String. */
+    public static final String TAG_SPECTRAL_SENSITIVITY = "SpectralSensitivity";
     /** Type is int. */
     public static final String TAG_SUBSEC_TIME = "SubSecTime";
+    /** Type is int. @hide */
+    public static final String TAG_SUBSECTIME = "SubSecTime";
+    /** Type is int. */
+    public static final String TAG_SUBSEC_TIME_DIGITIZED = "SubSecTimeDigitized";
+    /** Type is int. */
+    public static final String TAG_SUBSEC_TIME_DIG = "SubSecTimeDigitized";
     /** Type is int. */
     public static final String TAG_SUBSEC_TIME_ORIG = "SubSecTimeOriginal";
     /** Type is int. */
-    public static final String TAG_SUBSEC_TIME_DIG = "SubSecTimeDigitized";
-
-    /**
-     * @hide
-     */
-    public static final String TAG_SUBSECTIME = "SubSecTime";
-
+    public static final String TAG_SUBSEC_TIME_ORIGINAL = "SubSecTimeOriginal";
+    /** Type is int. */
+    public static final String TAG_SUBJECT_AREA = "SubjectArea";
+    /** Type is double. */
+    public static final String TAG_SUBJECT_DISTANCE = "SubjectDistance";
+    /** Type is int. */
+    public static final String TAG_SUBJECT_DISTANCE_RANGE = "SubjectDistanceRange";
+    /** Type is int. */
+    public static final String TAG_SUBJECT_LOCATION = "SubjectLocation";
+    /** Type is String. */
+    public static final String TAG_USER_COMMENT = "UserComment";
+    /** Type is int. */
+    public static final String TAG_WHITE_BALANCE = "WhiteBalance";
     /**
      * The altitude (in meters) based on the reference in TAG_GPS_ALTITUDE_REF.
      * Type is rational.
      */
     public static final String TAG_GPS_ALTITUDE = "GPSAltitude";
-
     /**
      * 0 if the altitude is above sea level. 1 if the altitude is below sea
      * level. Type is int.
      */
     public static final String TAG_GPS_ALTITUDE_REF = "GPSAltitudeRef";
-
     /** Type is String. */
-    public static final String TAG_GPS_TIMESTAMP = "GPSTimeStamp";
+    public static final String TAG_GPS_AREA_INFORMATION = "GPSAreaInformation";
+    /** Type is rational. */
+    public static final String TAG_GPS_DOP = "GPSDOP";
     /** Type is String. */
     public static final String TAG_GPS_DATESTAMP = "GPSDateStamp";
-    /** Type is int. */
-    public static final String TAG_WHITE_BALANCE = "WhiteBalance";
     /** Type is rational. */
-    public static final String TAG_FOCAL_LENGTH = "FocalLength";
+    public static final String TAG_GPS_DEST_BEARING = "GPSDestBearing";
+    /** Type is String. */
+    public static final String TAG_GPS_DEST_BEARING_REF = "GPSDestBearingRef";
+    /** Type is rational. */
+    public static final String TAG_GPS_DEST_DISTANCE = "GPSDestDistance";
+    /** Type is String. */
+    public static final String TAG_GPS_DEST_DISTANCE_REF = "GPSDestDistanceRef";
+    /** Type is rational. */
+    public static final String TAG_GPS_DEST_LATITUDE = "GPSDestLatitude";
+    /** Type is String. */
+    public static final String TAG_GPS_DEST_LATITUDE_REF = "GPSDestLatitudeRef";
+    /** Type is rational. */
+    public static final String TAG_GPS_DEST_LONGITUDE = "GPSDestLongitude";
+    /** Type is String. */
+    public static final String TAG_GPS_DEST_LONGITUDE_REF = "GPSDestLongitudeRef";
+    /** Type is int. */
+    public static final String TAG_GPS_DIFFERENTIAL = "GPSDifferential";
+    /** Type is rational. */
+    public static final String TAG_GPS_IMG_DIRECTION = "GPSImgDirection";
+    /** Type is String. */
+    public static final String TAG_GPS_IMG_DIRECTION_REF = "GPSImgDirectionRef";
+    /** String. Format is "num1/denom1,num2/denom2,num3/denom3". */
+    public static final String TAG_GPS_LATITUDE = "GPSLatitude";
+    /** Type is String. */
+    public static final String TAG_GPS_LATITUDE_REF = "GPSLatitudeRef";
+    /** String. Format is "num1/denom1,num2/denom2,num3/denom3". */
+    public static final String TAG_GPS_LONGITUDE = "GPSLongitude";
+    /** Type is String. */
+    public static final String TAG_GPS_LONGITUDE_REF = "GPSLongitudeRef";
+    /** Type is String. */
+    public static final String TAG_GPS_MAP_DATUM = "GPSMapDatum";
+    /** Type is String. */
+    public static final String TAG_GPS_MEASURE_MODE = "GPSMeasureMode";
     /** Type is String. Name of GPS processing method used for location finding. */
     public static final String TAG_GPS_PROCESSING_METHOD = "GPSProcessingMethod";
-    /** Type is double. */
-    public static final String TAG_DIGITAL_ZOOM_RATIO = "DigitalZoomRatio";
-    /** Type is double. */
-    public static final String TAG_SUBJECT_DISTANCE = "SubjectDistance";
-    /** Type is double. */
-    public static final String TAG_EXPOSURE_BIAS_VALUE = "ExposureBiasValue";
+    /** Type is String. */
+    public static final String TAG_GPS_SATELLITES = "GPSSatellites";
+    /** Type is rational. */
+    public static final String TAG_GPS_SPEED = "GPSSpeed";
+    /** Type is String. */
+    public static final String TAG_GPS_SPEED_REF = "GPSSpeedRef";
+    /** Type is String. */
+    public static final String TAG_GPS_STATUS = "GPSStatus";
+    /** Type is String. */
+    public static final String TAG_GPS_TIMESTAMP = "GPSTimeStamp";
+    /** Type is rational. */
+    public static final String TAG_GPS_TRACK = "GPSTrack";
+    /** Type is String. */
+    public static final String TAG_GPS_TRACK_REF = "GPSTrackRef";
+    /** Type is String. */
+    public static final String TAG_GPS_VERSION_ID = "GPSVersionID";
+    /** Type is String. */
+    public static final String TAG_INTEROPERABILITY_INDEX = "InteroperabilityIndex";
     /** Type is int. */
-    public static final String TAG_LIGHT_SOURCE = "LightSource";
+    public static final String TAG_THUMBNAIL_IMAGE_LENGTH = "ThumbnailImageLength";
     /** Type is int. */
-    public static final String TAG_METERING_MODE = "MeteringMode";
-    /** Type is int. */
-    public static final String TAG_EXPOSURE_PROGRAM = "ExposureProgram";
-    /** Type is int. */
-    public static final String TAG_EXPOSURE_MODE = "ExposureMode";
+    public static final String TAG_THUMBNAIL_IMAGE_WIDTH = "ThumbnailImageWidth";
+
+    // Private tags used for pointing the other IFD offset. The types of the following tags are int.
+    private static final String TAG_EXIF_IFD_POINTER = "ExifIFDPointer";
+    private static final String TAG_GPS_INFO_IFD_POINTER = "GPSInfoIFDPointer";
+    private static final String TAG_INTEROPERABILITY_IFD_POINTER = "InteroperabilityIFDPointer";
 
     // Private tags used for thumbnail information.
     private static final String TAG_HAS_THUMBNAIL = "hasThumbnail";
     private static final String TAG_THUMBNAIL_OFFSET = "thumbnailOffset";
     private static final String TAG_THUMBNAIL_LENGTH = "thumbnailLength";
+    private static final String TAG_THUMBNAIL_DATA = "thumbnailData";
 
     // Constants used for the Orientation Exif tag.
     public static final int ORIENTATION_UNDEFINED = 0;
@@ -163,6 +350,9 @@
     public static final int WHITEBALANCE_AUTO = 0;
     public static final int WHITEBALANCE_MANUAL = 1;
 
+    private static final byte[] JPEG_SIGNATURE = new byte[] {(byte) 0xff, (byte) 0xd8, (byte) 0xff};
+    private static final int JPEG_SIGNATURE_SIZE = 3;
+
     private static SimpleDateFormat sFormatter;
 
     // See Exchangeable image file format for digital still cameras: Exif version 2.2.
@@ -208,171 +398,171 @@
 
     // Primary image IFD TIFF tags (See JEITA CP-3451 Table 14. page 54).
     private static final ExifTag[] IFD_TIFF_TAGS = new ExifTag[] {
-            new ExifTag("ImageWidth", 256),
-            new ExifTag("ImageLength", 257),
-            new ExifTag("BitsPerSample", 258),
-            new ExifTag("Compression", 259),
-            new ExifTag("PhotometricInterpretation", 262),
-            new ExifTag("ImageDescription", 270),
-            new ExifTag("Make", 271),
-            new ExifTag("Model", 272),
-            new ExifTag("StripOffsets", 273),
-            new ExifTag("Orientation", 274),
-            new ExifTag("SamplesPerPixel", 277),
-            new ExifTag("RowsPerStrip", 278),
-            new ExifTag("StripByteCounts", 279),
-            new ExifTag("XResolution", 282),
-            new ExifTag("YResolution", 283),
-            new ExifTag("PlanarConfiguration", 284),
-            new ExifTag("ResolutionUnit", 296),
-            new ExifTag("TransferFunction", 301),
-            new ExifTag("Software", 305),
-            new ExifTag("DateTime", 306),
-            new ExifTag("Artist", 315),
-            new ExifTag("WhitePoint", 318),
-            new ExifTag("PrimaryChromaticities", 319),
-            new ExifTag("JPEGInterchangeFormat", 513),
-            new ExifTag("JPEGInterchangeFormatLength", 514),
-            new ExifTag("YCbCrCoefficients", 529),
-            new ExifTag("YCbCrSubSampling", 530),
-            new ExifTag("YCbCrPositioning", 531),
-            new ExifTag("ReferenceBlackWhite", 532),
-            new ExifTag("Copyright", 33432),
-            new ExifTag("ExifIFDPointer", 34665),
-            new ExifTag("GPSInfoIFDPointer", 34853),
+            new ExifTag(TAG_IMAGE_WIDTH, 256),
+            new ExifTag(TAG_IMAGE_LENGTH, 257),
+            new ExifTag(TAG_BITS_PER_SAMPLE, 258),
+            new ExifTag(TAG_COMPRESSION, 259),
+            new ExifTag(TAG_PHOTOMETRIC_INTERPRETATION, 262),
+            new ExifTag(TAG_IMAGE_DESCRIPTION, 270),
+            new ExifTag(TAG_MAKE, 271),
+            new ExifTag(TAG_MODEL, 272),
+            new ExifTag(TAG_STRIP_OFFSETS, 273),
+            new ExifTag(TAG_ORIENTATION, 274),
+            new ExifTag(TAG_SAMPLES_PER_PIXEL, 277),
+            new ExifTag(TAG_ROWS_PER_STRIP, 278),
+            new ExifTag(TAG_STRIP_BYTE_COUNTS, 279),
+            new ExifTag(TAG_X_RESOLUTION, 282),
+            new ExifTag(TAG_Y_RESOLUTION, 283),
+            new ExifTag(TAG_PLANAR_CONFIGURATION, 284),
+            new ExifTag(TAG_RESOLUTION_UNIT, 296),
+            new ExifTag(TAG_TRANSFER_FUNCTION, 301),
+            new ExifTag(TAG_SOFTWARE, 305),
+            new ExifTag(TAG_DATETIME, 306),
+            new ExifTag(TAG_ARTIST, 315),
+            new ExifTag(TAG_WHITE_POINT, 318),
+            new ExifTag(TAG_PRIMARY_CHROMATICITIES, 319),
+            new ExifTag(TAG_JPEG_INTERCHANGE_FORMAT, 513),
+            new ExifTag(TAG_JPEG_INTERCHANGE_FORMAT_LENGTH, 514),
+            new ExifTag(TAG_Y_CB_CR_COEFFICIENTS, 529),
+            new ExifTag(TAG_Y_CB_CR_SUB_SAMPLING, 530),
+            new ExifTag(TAG_Y_CB_CR_POSITIONING, 531),
+            new ExifTag(TAG_REFERENCE_BLACK_WHITE, 532),
+            new ExifTag(TAG_COPYRIGHT, 33432),
+            new ExifTag(TAG_EXIF_IFD_POINTER, 34665),
+            new ExifTag(TAG_GPS_INFO_IFD_POINTER, 34853),
     };
     // Primary image IFD Exif Private tags (See JEITA CP-3451 Table 15. page 55).
     private static final ExifTag[] IFD_EXIF_TAGS = new ExifTag[] {
-            new ExifTag("ExposureTime", 33434),
-            new ExifTag("FNumber", 33437),
-            new ExifTag("ExposureProgram", 34850),
-            new ExifTag("SpectralSensitivity", 34852),
-            new ExifTag("ISOSpeedRatings", 34855),
-            new ExifTag("OECF", 34856),
-            new ExifTag("ExifVersion", 36864),
-            new ExifTag("DateTimeOriginal", 36867),
-            new ExifTag("DateTimeDigitized", 36868),
-            new ExifTag("ComponentsConfiguration", 37121),
-            new ExifTag("CompressedBitsPerPixel", 37122),
-            new ExifTag("ShutterSpeedValue", 37377),
-            new ExifTag("ApertureValue", 37378),
-            new ExifTag("BrightnessValue", 37379),
-            new ExifTag("ExposureBiasValue", 37380),
-            new ExifTag("MaxApertureValue", 37381),
-            new ExifTag("SubjectDistance", 37382),
-            new ExifTag("MeteringMode", 37383),
-            new ExifTag("LightSource", 37384),
-            new ExifTag("Flash", 37385),
-            new ExifTag("FocalLength", 37386),
-            new ExifTag("SubjectArea", 37396),
-            new ExifTag("MakerNote", 37500),
-            new ExifTag("UserComment", 37510),
-            new ExifTag("SubSecTime", 37520),
-            new ExifTag("SubSecTimeOriginal", 37521),
-            new ExifTag("SubSecTimeDigitized", 37522),
-            new ExifTag("FlashpixVersion", 40960),
-            new ExifTag("ColorSpace", 40961),
-            new ExifTag("PixelXDimension", 40962),
-            new ExifTag("PixelYDimension", 40963),
-            new ExifTag("RelatedSoundFile", 40964),
-            new ExifTag("InteroperabilityIFDPointer", 40965),
-            new ExifTag("FlashEnergy", 41483),
-            new ExifTag("SpatialFrequencyResponse", 41484),
-            new ExifTag("FocalPlaneXResolution", 41486),
-            new ExifTag("FocalPlaneYResolution", 41487),
-            new ExifTag("FocalPlaneResolutionUnit", 41488),
-            new ExifTag("SubjectLocation", 41492),
-            new ExifTag("ExposureIndex", 41493),
-            new ExifTag("SensingMethod", 41495),
-            new ExifTag("FileSource", 41728),
-            new ExifTag("SceneType", 41729),
-            new ExifTag("CFAPattern", 41730),
-            new ExifTag("CustomRendered", 41985),
-            new ExifTag("ExposureMode", 41986),
-            new ExifTag("WhiteBalance", 41987),
-            new ExifTag("DigitalZoomRatio", 41988),
-            new ExifTag("FocalLengthIn35mmFilm", 41989),
-            new ExifTag("SceneCaptureType", 41990),
-            new ExifTag("GainControl", 41991),
-            new ExifTag("Contrast", 41992),
-            new ExifTag("Saturation", 41993),
-            new ExifTag("Sharpness", 41994),
-            new ExifTag("DeviceSettingDescription", 41995),
-            new ExifTag("SubjectDistanceRange", 41996),
-            new ExifTag("ImageUniqueID", 42016),
+            new ExifTag(TAG_EXPOSURE_TIME, 33434),
+            new ExifTag(TAG_F_NUMBER, 33437),
+            new ExifTag(TAG_EXPOSURE_PROGRAM, 34850),
+            new ExifTag(TAG_SPECTRAL_SENSITIVITY, 34852),
+            new ExifTag(TAG_ISO, 34855),
+            new ExifTag(TAG_OECF, 34856),
+            new ExifTag(TAG_EXIF_VERSION, 36864),
+            new ExifTag(TAG_DATETIME_ORIGINAL, 36867),
+            new ExifTag(TAG_DATETIME_DIGITIZED, 36868),
+            new ExifTag(TAG_COMPONENTS_CONFIGURATION, 37121),
+            new ExifTag(TAG_COMPRESSED_BITS_PER_PIXEL, 37122),
+            new ExifTag(TAG_SHUTTER_SPEED_VALUE, 37377),
+            new ExifTag(TAG_APERTURE_VALUE, 37378),
+            new ExifTag(TAG_BRIGHTNESS_VALUE, 37379),
+            new ExifTag(TAG_EXPOSURE_BIAS_VALUE, 37380),
+            new ExifTag(TAG_MAX_APERTURE_VALUE, 37381),
+            new ExifTag(TAG_SUBJECT_DISTANCE, 37382),
+            new ExifTag(TAG_METERING_MODE, 37383),
+            new ExifTag(TAG_LIGHT_SOURCE, 37384),
+            new ExifTag(TAG_FLASH, 37385),
+            new ExifTag(TAG_FOCAL_LENGTH, 37386),
+            new ExifTag(TAG_SUBJECT_AREA, 37396),
+            new ExifTag(TAG_MAKER_NOTE, 37500),
+            new ExifTag(TAG_USER_COMMENT, 37510),
+            new ExifTag(TAG_SUBSEC_TIME, 37520),
+            new ExifTag(TAG_SUBSEC_TIME_ORIG, 37521),
+            new ExifTag(TAG_SUBSEC_TIME_DIG, 37522),
+            new ExifTag(TAG_FLASHPIX_VERSION, 40960),
+            new ExifTag(TAG_COLOR_SPACE, 40961),
+            new ExifTag(TAG_PIXEL_X_DIMENSION, 40962),
+            new ExifTag(TAG_PIXEL_Y_DIMENSION, 40963),
+            new ExifTag(TAG_RELATED_SOUND_FILE, 40964),
+            new ExifTag(TAG_INTEROPERABILITY_IFD_POINTER, 40965),
+            new ExifTag(TAG_FLASH_ENERGY, 41483),
+            new ExifTag(TAG_SPATIAL_FREQUENCY_RESPONSE, 41484),
+            new ExifTag(TAG_FOCAL_PLANE_X_RESOLUTION, 41486),
+            new ExifTag(TAG_FOCAL_PLANE_Y_RESOLUTION, 41487),
+            new ExifTag(TAG_FOCAL_PLANE_RESOLUTION_UNIT, 41488),
+            new ExifTag(TAG_SUBJECT_LOCATION, 41492),
+            new ExifTag(TAG_EXPOSURE_INDEX, 41493),
+            new ExifTag(TAG_SENSING_METHOD, 41495),
+            new ExifTag(TAG_FILE_SOURCE, 41728),
+            new ExifTag(TAG_SCENE_TYPE, 41729),
+            new ExifTag(TAG_CFA_PATTERN, 41730),
+            new ExifTag(TAG_CUSTOM_RENDERED, 41985),
+            new ExifTag(TAG_EXPOSURE_MODE, 41986),
+            new ExifTag(TAG_WHITE_BALANCE, 41987),
+            new ExifTag(TAG_DIGITAL_ZOOM_RATIO, 41988),
+            new ExifTag(TAG_FOCAL_LENGTH_IN_35MM_FILM, 41989),
+            new ExifTag(TAG_SCENE_CAPTURE_TYPE, 41990),
+            new ExifTag(TAG_GAIN_CONTROL, 41991),
+            new ExifTag(TAG_CONTRAST, 41992),
+            new ExifTag(TAG_SATURATION, 41993),
+            new ExifTag(TAG_SHARPNESS, 41994),
+            new ExifTag(TAG_DEVICE_SETTING_DESCRIPTION, 41995),
+            new ExifTag(TAG_SUBJECT_DISTANCE_RANGE, 41996),
+            new ExifTag(TAG_IMAGE_UNIQUE_ID, 42016),
     };
     // Primary image IFD GPS Info tags (See JEITA CP-3451 Table 16. page 56).
     private static final ExifTag[] IFD_GPS_TAGS = new ExifTag[] {
-            new ExifTag("GPSVersionID", 0),
-            new ExifTag("GPSLatitudeRef", 1),
-            new ExifTag("GPSLatitude", 2),
-            new ExifTag("GPSLongitudeRef", 3),
-            new ExifTag("GPSLongitude", 4),
-            new ExifTag("GPSAltitudeRef", 5),
-            new ExifTag("GPSAltitude", 6),
-            new ExifTag("GPSTimeStamp", 7),
-            new ExifTag("GPSSatellites", 8),
-            new ExifTag("GPSStatus", 9),
-            new ExifTag("GPSMeasureMode", 10),
-            new ExifTag("GPSDOP", 11),
-            new ExifTag("GPSSpeedRef", 12),
-            new ExifTag("GPSSpeed", 13),
-            new ExifTag("GPSTrackRef", 14),
-            new ExifTag("GPSTrack", 15),
-            new ExifTag("GPSImgDirectionRef", 16),
-            new ExifTag("GPSImgDirection", 17),
-            new ExifTag("GPSMapDatum", 18),
-            new ExifTag("GPSDestLatitudeRef", 19),
-            new ExifTag("GPSDestLatitude", 20),
-            new ExifTag("GPSDestLongitudeRef", 21),
-            new ExifTag("GPSDestLongitude", 22),
-            new ExifTag("GPSDestBearingRef", 23),
-            new ExifTag("GPSDestBearing", 24),
-            new ExifTag("GPSDestDistanceRef", 25),
-            new ExifTag("GPSDestDistance", 26),
-            new ExifTag("GPSProcessingMethod", 27),
-            new ExifTag("GPSAreaInformation", 28),
-            new ExifTag("GPSDateStamp", 29),
-            new ExifTag("GPSDifferential", 30),
+            new ExifTag(TAG_GPS_VERSION_ID, 0),
+            new ExifTag(TAG_GPS_LATITUDE_REF, 1),
+            new ExifTag(TAG_GPS_LATITUDE, 2),
+            new ExifTag(TAG_GPS_LONGITUDE_REF, 3),
+            new ExifTag(TAG_GPS_LONGITUDE, 4),
+            new ExifTag(TAG_GPS_ALTITUDE_REF, 5),
+            new ExifTag(TAG_GPS_ALTITUDE, 6),
+            new ExifTag(TAG_GPS_TIMESTAMP, 7),
+            new ExifTag(TAG_GPS_SATELLITES, 8),
+            new ExifTag(TAG_GPS_STATUS, 9),
+            new ExifTag(TAG_GPS_MEASURE_MODE, 10),
+            new ExifTag(TAG_GPS_DOP, 11),
+            new ExifTag(TAG_GPS_SPEED_REF, 12),
+            new ExifTag(TAG_GPS_SPEED, 13),
+            new ExifTag(TAG_GPS_TRACK_REF, 14),
+            new ExifTag(TAG_GPS_TRACK, 15),
+            new ExifTag(TAG_GPS_IMG_DIRECTION_REF, 16),
+            new ExifTag(TAG_GPS_IMG_DIRECTION, 17),
+            new ExifTag(TAG_GPS_MAP_DATUM, 18),
+            new ExifTag(TAG_GPS_DEST_LATITUDE_REF, 19),
+            new ExifTag(TAG_GPS_DEST_LATITUDE, 20),
+            new ExifTag(TAG_GPS_DEST_LONGITUDE_REF, 21),
+            new ExifTag(TAG_GPS_DEST_LONGITUDE, 22),
+            new ExifTag(TAG_GPS_DEST_BEARING_REF, 23),
+            new ExifTag(TAG_GPS_DEST_BEARING, 24),
+            new ExifTag(TAG_GPS_DEST_DISTANCE_REF, 25),
+            new ExifTag(TAG_GPS_DEST_DISTANCE, 26),
+            new ExifTag(TAG_GPS_PROCESSING_METHOD, 27),
+            new ExifTag(TAG_GPS_AREA_INFORMATION, 28),
+            new ExifTag(TAG_GPS_DATESTAMP, 29),
+            new ExifTag(TAG_GPS_DIFFERENTIAL, 30),
     };
     // Primary image IFD Interoperability tag (See JEITA CP-3451 Table 17. page 56).
     private static final ExifTag[] IFD_INTEROPERABILITY_TAGS = new ExifTag[] {
-            new ExifTag("InteroperabilityIndex", 1),
+            new ExifTag(TAG_INTEROPERABILITY_INDEX, 1),
     };
     // IFD Thumbnail tags (See JEITA CP-3451 Table 18. page 57).
     private static final ExifTag[] IFD_THUMBNAIL_TAGS = new ExifTag[] {
-            new ExifTag("ThumbnailImageWidth", 256),
-            new ExifTag("ThumbnailImageLength", 257),
-            new ExifTag("BitsPerSample", 258),
-            new ExifTag("Compression", 259),
-            new ExifTag("PhotometricInterpretation", 262),
-            new ExifTag("ImageDescription", 270),
-            new ExifTag("Make", 271),
-            new ExifTag("Model", 272),
-            new ExifTag("StripOffsets", 273),
-            new ExifTag("Orientation", 274),
-            new ExifTag("SamplesPerPixel", 277),
-            new ExifTag("RowsPerStrip", 278),
-            new ExifTag("StripByteCounts", 279),
-            new ExifTag("XResolution", 282),
-            new ExifTag("YResolution", 283),
-            new ExifTag("PlanarConfiguration", 284),
-            new ExifTag("ResolutionUnit", 296),
-            new ExifTag("TransferFunction", 301),
-            new ExifTag("Software", 305),
-            new ExifTag("DateTime", 306),
-            new ExifTag("Artist", 315),
-            new ExifTag("WhitePoint", 318),
-            new ExifTag("PrimaryChromaticities", 319),
-            new ExifTag("JPEGInterchangeFormat", 513),
-            new ExifTag("JPEGInterchangeFormatLength", 514),
-            new ExifTag("YCbCrCoefficients", 529),
-            new ExifTag("YCbCrSubSampling", 530),
-            new ExifTag("YCbCrPositioning", 531),
-            new ExifTag("ReferenceBlackWhite", 532),
-            new ExifTag("Copyright", 33432),
-            new ExifTag("ExifIFDPointer", 34665),
-            new ExifTag("GPSInfoIFDPointer", 34853),
+            new ExifTag(TAG_THUMBNAIL_IMAGE_WIDTH, 256),
+            new ExifTag(TAG_THUMBNAIL_IMAGE_LENGTH, 257),
+            new ExifTag(TAG_BITS_PER_SAMPLE, 258),
+            new ExifTag(TAG_COMPRESSION, 259),
+            new ExifTag(TAG_PHOTOMETRIC_INTERPRETATION, 262),
+            new ExifTag(TAG_IMAGE_DESCRIPTION, 270),
+            new ExifTag(TAG_MAKE, 271),
+            new ExifTag(TAG_MODEL, 272),
+            new ExifTag(TAG_STRIP_OFFSETS, 273),
+            new ExifTag(TAG_ORIENTATION, 274),
+            new ExifTag(TAG_SAMPLES_PER_PIXEL, 277),
+            new ExifTag(TAG_ROWS_PER_STRIP, 278),
+            new ExifTag(TAG_STRIP_BYTE_COUNTS, 279),
+            new ExifTag(TAG_X_RESOLUTION, 282),
+            new ExifTag(TAG_Y_RESOLUTION, 283),
+            new ExifTag(TAG_PLANAR_CONFIGURATION, 284),
+            new ExifTag(TAG_RESOLUTION_UNIT, 296),
+            new ExifTag(TAG_TRANSFER_FUNCTION, 301),
+            new ExifTag(TAG_SOFTWARE, 305),
+            new ExifTag(TAG_DATETIME, 306),
+            new ExifTag(TAG_ARTIST, 315),
+            new ExifTag(TAG_WHITE_POINT, 318),
+            new ExifTag(TAG_PRIMARY_CHROMATICITIES, 319),
+            new ExifTag(TAG_JPEG_INTERCHANGE_FORMAT, 513),
+            new ExifTag(TAG_JPEG_INTERCHANGE_FORMAT_LENGTH, 514),
+            new ExifTag(TAG_Y_CB_CR_COEFFICIENTS, 529),
+            new ExifTag(TAG_Y_CB_CR_SUB_SAMPLING, 530),
+            new ExifTag(TAG_Y_CB_CR_POSITIONING, 531),
+            new ExifTag(TAG_REFERENCE_BLACK_WHITE, 532),
+            new ExifTag(TAG_COPYRIGHT, 33432),
+            new ExifTag(TAG_EXIF_IFD_POINTER, 34665),
+            new ExifTag(TAG_GPS_INFO_IFD_POINTER, 34853),
     };
 
     // See JEITA CP-3451 Figure 5. page 9.
@@ -391,9 +581,9 @@
     };
     // List of tags for pointing to the other image file directory offset.
     private static final ExifTag[] IFD_POINTER_TAGS = new ExifTag[] {
-            new ExifTag("ExifIFDPointer", 34665),
-            new ExifTag("GPSInfoPointer", 34853),
-            new ExifTag("InteroperabilityIFDPointer", 40965),
+            new ExifTag(TAG_EXIF_IFD_POINTER, 34665),
+            new ExifTag(TAG_GPS_INFO_IFD_POINTER, 34853),
+            new ExifTag(TAG_INTEROPERABILITY_IFD_POINTER, 40965),
     };
     // List of indices of the indicated tag groups according to the IFD_POINTER_TAGS
     private static final int[] IFD_POINTER_TAG_HINTS = new int[] {
@@ -401,15 +591,14 @@
     };
     // Tags for indicating the thumbnail offset and length
     private static final ExifTag JPEG_INTERCHANGE_FORMAT_TAG =
-            new ExifTag("JPEGInterchangeFormat", 513);
+            new ExifTag(TAG_JPEG_INTERCHANGE_FORMAT, 513);
     private static final ExifTag JPEG_INTERCHANGE_FORMAT_LENGTH_TAG =
-            new ExifTag("JPEGInterchangeFormatLength", 514);
+            new ExifTag(TAG_JPEG_INTERCHANGE_FORMAT_LENGTH, 514);
 
     // Mappings from tag number to tag name and each item represents one IFD tag group.
     private static final HashMap[] sExifTagMapsForReading = new HashMap[EXIF_TAGS.length];
-    // Mapping from tag name to tag number and the corresponding tag group.
-    private static final HashMap<String, Pair<Integer, Integer>> sExifTagMapForWriting
-            = new HashMap<>();
+    // Mappings from tag name to tag number and each item represents one IFD tag group.
+    private static final HashMap[] sExifTagMapsForWriting = new HashMap[EXIF_TAGS.length];
 
     // See JPEG File Interchange Format Version 1.02.
     // The following values are defined for handling JPEG streams. In this implementation, we are
@@ -443,35 +632,26 @@
 
     static {
         System.loadLibrary("media_jni");
-        initRawNative();
+        nativeInitRaw();
         sFormatter = new SimpleDateFormat("yyyy:MM:dd HH:mm:ss");
         sFormatter.setTimeZone(TimeZone.getTimeZone("UTC"));
 
         // Build up the hash tables to look up Exif tags for reading Exif tags.
         for (int hint = 0; hint < EXIF_TAGS.length; ++hint) {
             sExifTagMapsForReading[hint] = new HashMap();
+            sExifTagMapsForWriting[hint] = new HashMap();
             for (ExifTag tag : EXIF_TAGS[hint]) {
                 sExifTagMapsForReading[hint].put(tag.number, tag.name);
-            }
-        }
-
-        // Build up the hash tables to look up Exif tags for writing Exif tags.
-        // There are some tags that have the same tag name in the different group. For that tags,
-        // Primary image TIFF IFD and Exif private IFD have a higher priority to map than the other
-        // tag groups. For the same tags, it writes one tag in the only one IFD group, which has the
-        // higher priority group.
-        for (int hint = EXIF_TAGS.length - 1; hint >= 0; --hint) {
-            for (ExifTag tag : EXIF_TAGS[hint]) {
-                sExifTagMapForWriting.put(tag.name, new Pair<>(tag.number, hint));
+                sExifTagMapsForWriting[hint].put(tag.name, tag.number);
             }
         }
     }
 
     private final String mFilename;
-    private final FileDescriptor mFileDescriptor;
-    private final InputStream mInputStream;
+    private final FileDescriptor mSeekableFileDescriptor;
+    private final AssetManager.AssetInputStream mAssetInputStream;
     private boolean mIsRaw;
-    private final HashMap<String, String> mAttributes = new HashMap<>();
+    private final HashMap[] mAttributes = new HashMap[EXIF_TAGS.length];
     private boolean mHasThumbnail;
     // The following values used for indicating a thumbnail position.
     private int mThumbnailOffset;
@@ -488,23 +668,33 @@
         if (filename == null) {
             throw new IllegalArgumentException("filename cannot be null");
         }
+        FileInputStream in = new FileInputStream(filename);
+        mAssetInputStream = null;
         mFilename = filename;
-        mFileDescriptor = null;
-        mInputStream = new FileInputStream(filename);
-        loadAttributes();
+        if (isSeekableFD(in.getFD())) {
+            mSeekableFileDescriptor = in.getFD();
+        } else {
+            mSeekableFileDescriptor = null;
+        }
+        loadAttributes(in);
     }
 
     /**
-     * Reads Exif tags from the specified image file descriptor.
+     * Reads Exif tags from the specified image file descriptor. Attribute mutation is supported
+     * for seekable file descriptors only.
      */
     public ExifInterface(FileDescriptor fileDescriptor) throws IOException {
         if (fileDescriptor == null) {
             throw new IllegalArgumentException("parcelFileDescriptor cannot be null");
         }
+        mAssetInputStream = null;
         mFilename = null;
-        mFileDescriptor = fileDescriptor;
-        mInputStream = new FileInputStream(fileDescriptor);
-        loadAttributes();
+        if (isSeekableFD(fileDescriptor)) {
+            mSeekableFileDescriptor = fileDescriptor;
+        } else {
+            mSeekableFileDescriptor = null;
+        }
+        loadAttributes(new FileInputStream(fileDescriptor));
     }
 
     /**
@@ -516,9 +706,18 @@
             throw new IllegalArgumentException("inputStream cannot be null");
         }
         mFilename = null;
-        mFileDescriptor = null;
-        mInputStream = inputStream;
-        loadAttributes();
+        if (inputStream instanceof AssetManager.AssetInputStream) {
+            mAssetInputStream = (AssetManager.AssetInputStream) inputStream;
+            mSeekableFileDescriptor = null;
+        } else if (inputStream instanceof FileInputStream
+                && isSeekableFD(((FileInputStream) inputStream).getFD())) {
+            mAssetInputStream = null;
+            mSeekableFileDescriptor = ((FileInputStream) inputStream).getFD();
+        } else {
+            mAssetInputStream = null;
+            mSeekableFileDescriptor = null;
+        }
+        loadAttributes(inputStream);
     }
 
     /**
@@ -528,7 +727,15 @@
      * @param tag the name of the tag.
      */
     public String getAttribute(String tag) {
-        return mAttributes.get(tag);
+        // Retrieves all tag groups. The value from primary image tag group has a higher priority
+        // than the value from the thumbnail tag group if there are more than one candidates.
+        for (int i = 0; i < EXIF_TAGS.length; ++i) {
+            Object value = mAttributes[i].get(tag);
+            if (value != null) {
+                return (String) value;
+            }
+        }
+        return null;
     }
 
     /**
@@ -540,11 +747,11 @@
      * @param defaultValue the value to return if the tag is not available.
      */
     public int getAttributeInt(String tag, int defaultValue) {
-        String value = mAttributes.get(tag);
+        String value = getAttribute(tag);
         if (value == null) return defaultValue;
         try {
             return Integer.valueOf(value);
-        } catch (NumberFormatException ex) {
+        } catch (NumberFormatException e) {
             return defaultValue;
         }
     }
@@ -558,7 +765,7 @@
      * @param defaultValue the value to return if the tag is not available.
      */
     public double getAttributeDouble(String tag, double defaultValue) {
-        String value = mAttributes.get(tag);
+        String value = getAttribute(tag);
         if (value == null) return defaultValue;
         try {
             int index = value.indexOf("/");
@@ -567,7 +774,7 @@
             if (denom == 0) return defaultValue;
             double num = Double.parseDouble(value.substring(0, index));
             return num / denom;
-        } catch (NumberFormatException ex) {
+        } catch (NumberFormatException e) {
             return defaultValue;
         }
     }
@@ -579,92 +786,114 @@
      * @param value the value of the tag.
      */
     public void setAttribute(String tag, String value) {
-        if (value == null) {
-            mAttributes.remove(tag);
-            return;
+        for (int i = 0 ; i < EXIF_TAGS.length; ++i) {
+            if (sExifTagMapsForWriting[i].containsKey(tag)) {
+                mAttributes[i].put(tag, value);
+            }
         }
-        mAttributes.put(tag, value);
     }
 
     /**
-     * Initialize mAttributes with the attributes from the file mFilename.
-     *
-     * mAttributes is a HashMap which stores the Exif attributes of the file.
-     * The key is the standard tag name and the value is the tag's value: e.g.
-     * Model -&gt; Nikon. Numeric values are stored as strings.
-     *
-     * This function also initialize mHasThumbnail to indicate whether the
-     * file has a thumbnail inside.
+     * This function decides which parser to read the image data according to the given input stream
+     * type and the content of the input stream. In each case, it reads the first three bytes to
+     * determine whether the image data format is JPEG or not.
      */
-    private void loadAttributes() throws IOException {
-        FileInputStream in = null;
-        try {
-            if (mFilename != null) {
-                in = new FileInputStream(mFilename);
-            }
-            if (mFileDescriptor != null) {
-                in = new FileInputStream(mFileDescriptor);
-            }
-            if (in != null) {
-                // First test whether a given file is a one of RAW format or not.
-                HashMap map = getRawAttributesNative(Os.dup(in.getFD()));
-                mIsRaw = map != null;
-                if (mIsRaw) {
-                    for (Object obj : map.entrySet()) {
-                        Map.Entry entry = (Map.Entry) obj;
-                        String attrName = (String) entry.getKey();
-                        String attrValue = (String) entry.getValue();
-
-                        switch (attrName) {
-                            case TAG_HAS_THUMBNAIL:
-                                mHasThumbnail = attrValue.equalsIgnoreCase("true");
-                                break;
-                            case TAG_THUMBNAIL_OFFSET:
-                                mThumbnailOffset = Integer.parseInt(attrValue);
-                                break;
-                            case TAG_THUMBNAIL_LENGTH:
-                                mThumbnailLength = Integer.parseInt(attrValue);
-                                break;
-                            default:
-                                mAttributes.put(attrName, attrValue);
-                                break;
-                        }
-                    }
-
-                    if (DEBUG) {
-                        printAttributes();
-                    }
-                    return;
-                }
-            }
-        } catch (ErrnoException e) {
-            e.rethrowAsIOException();
-        } finally {
-            IoUtils.closeQuietly(in);
+    private void loadAttributes(@NonNull InputStream in) throws IOException {
+        // Initialize mAttributes.
+        for (int i = 0; i < EXIF_TAGS.length; ++i) {
+            mAttributes[i] = new HashMap();
         }
 
-        try {
-            if (mFileDescriptor != null) {
-                Os.lseek(mFileDescriptor, 0, OsConstants.SEEK_SET);
+        // Process RAW input stream
+        if (mAssetInputStream != null) {
+            long asset = mAssetInputStream.getNativeAsset();
+            if (handleRawResult(nativeGetRawAttributesFromAsset(asset))) {
+                return;
             }
-
-            getJpegAttributes(mInputStream);
-        } catch (ErrnoException e) {
-            e.rethrowAsIOException();
-        } finally {
-            IoUtils.closeQuietly(mInputStream);
+        } else if (mSeekableFileDescriptor != null) {
+            if (handleRawResult(nativeGetRawAttributesFromFileDescriptor(
+                    mSeekableFileDescriptor))) {
+                return;
+            }
+        } else {
+            in = new BufferedInputStream(in, JPEG_SIGNATURE_SIZE);
+            if (!isJpegInputStream((BufferedInputStream) in) && handleRawResult(
+                    nativeGetRawAttributesFromInputStream(in))) {
+                return;
+            }
         }
 
+        // Process JPEG input stream
+        getJpegAttributes(in);
+
         if (DEBUG) {
             printAttributes();
         }
     }
 
+    private static boolean isJpegInputStream(BufferedInputStream in) throws IOException {
+        in.mark(JPEG_SIGNATURE_SIZE);
+        byte[] signatureBytes = new byte[JPEG_SIGNATURE_SIZE];
+        if (in.read(signatureBytes) != JPEG_SIGNATURE_SIZE) {
+            throw new EOFException();
+        }
+        boolean isJpeg = Arrays.equals(JPEG_SIGNATURE, signatureBytes);
+        in.reset();
+        return isJpeg;
+    }
+
+    private boolean handleRawResult(HashMap map) {
+        if (map == null) {
+            return false;
+        }
+
+        // Mark for disabling the save feature.
+        mIsRaw = true;
+
+        for (Map.Entry entry : (Set<Map.Entry>) map.entrySet()) {
+            String attrName = (String) entry.getKey();
+
+            switch (attrName) {
+                case TAG_HAS_THUMBNAIL:
+                    mHasThumbnail = ((String) entry.getValue()).equalsIgnoreCase("true");
+                    break;
+                case TAG_THUMBNAIL_OFFSET:
+                    mThumbnailOffset = Integer.parseInt((String) entry.getValue());
+                    break;
+                case TAG_THUMBNAIL_LENGTH:
+                    mThumbnailLength = Integer.parseInt((String) entry.getValue());
+                    break;
+                case TAG_THUMBNAIL_DATA:
+                    mThumbnailBytes = (byte[]) entry.getValue();
+                    break;
+                default:
+                    setAttribute(attrName, (String) entry.getValue());
+                    break;
+            }
+        }
+
+        if (DEBUG) {
+            printAttributes();
+        }
+        return true;
+    }
+
+    private static boolean isSeekableFD(FileDescriptor fd) throws IOException {
+        try {
+            Os.lseek(fd, 0, OsConstants.SEEK_CUR);
+            return true;
+        } catch (ErrnoException e) {
+            return false;
+        }
+    }
+
     // Prints out attributes for debugging.
     private void printAttributes() {
-        Log.d(TAG, "The size of tags: " + mAttributes.size());
-        for (Map.Entry<String, String> entry : mAttributes.entrySet()) {
-            Log.d(TAG, "tagName: " + entry.getKey() + ", tagValue: " + entry.getValue());
+        for (int i = 0; i < mAttributes.length; ++i) {
+            Log.d(TAG, "The size of tag group[" + i + "]: " + mAttributes[i].size());
+            for (Map.Entry entry : (Set<Map.Entry>) mAttributes[i].entrySet()) {
+                Log.d(TAG, "tagName: " + entry.getKey() + ", tagValue: " + entry.getValue());
+            }
         }
     }
 
@@ -679,9 +908,9 @@
             throw new UnsupportedOperationException(
                     "ExifInterface does not support saving attributes on RAW formats.");
         }
-        if (mFileDescriptor == null && mFilename == null) {
+        if (mSeekableFileDescriptor == null && mFilename == null) {
             throw new UnsupportedOperationException(
-                    "ExifInterface does not support saving attributes for input streams.");
+                    "ExifInterface does not support saving attributes for the current input.");
         }
 
         // Keep the thumbnail in memory
@@ -698,11 +927,10 @@
                 if (!originalFile.renameTo(tempFile)) {
                     throw new IOException("Could'nt rename to " + tempFile.getAbsolutePath());
                 }
-            }
-            if (mFileDescriptor != null) {
+            } else if (mSeekableFileDescriptor != null) {
                 tempFile = File.createTempFile("temp", "jpg");
-                Os.lseek(mFileDescriptor, 0, OsConstants.SEEK_SET);
-                in = new FileInputStream(mFileDescriptor);
+                Os.lseek(mSeekableFileDescriptor, 0, OsConstants.SEEK_SET);
+                in = new FileInputStream(mSeekableFileDescriptor);
                 out = new FileOutputStream(tempFile);
                 Streams.copy(in, out);
             }
@@ -720,10 +948,9 @@
             in = new FileInputStream(tempFile);
             if (mFilename != null) {
                 out = new FileOutputStream(mFilename);
-            }
-            if (mFileDescriptor != null) {
-                Os.lseek(mFileDescriptor, 0, OsConstants.SEEK_SET);
-                out = new FileOutputStream(mFileDescriptor);
+            } else if (mSeekableFileDescriptor != null) {
+                Os.lseek(mSeekableFileDescriptor, 0, OsConstants.SEEK_SET);
+                out = new FileOutputStream(mSeekableFileDescriptor);
             }
             saveJpegAttributes(in, out);
         } catch (ErrnoException e) {
@@ -760,13 +987,15 @@
 
         // Read the thumbnail.
         FileInputStream in = null;
-        try  {
-            if (mFileDescriptor != null) {
-                Os.lseek(mFileDescriptor, 0, OsConstants.SEEK_SET);
-                in = new FileInputStream(mFileDescriptor);
-            }
-            if (mFilename != null) {
+        try {
+            if (mAssetInputStream != null) {
+                return nativeGetThumbnailFromAsset(
+                        mAssetInputStream.getNativeAsset(), mThumbnailOffset, mThumbnailLength);
+            } else if (mFilename != null) {
                 in = new FileInputStream(mFilename);
+            } else if (mSeekableFileDescriptor != null) {
+                Os.lseek(mSeekableFileDescriptor, 0, OsConstants.SEEK_SET);
+                in = new FileInputStream(mSeekableFileDescriptor);
             }
             if (in == null) {
                 // Should not be reached this.
@@ -809,10 +1038,10 @@
      * Exif tags are not available.
      */
     public boolean getLatLong(float output[]) {
-        String latValue = mAttributes.get(TAG_GPS_LATITUDE);
-        String latRef = mAttributes.get(TAG_GPS_LATITUDE_REF);
-        String lngValue = mAttributes.get(TAG_GPS_LONGITUDE);
-        String lngRef = mAttributes.get(TAG_GPS_LONGITUDE_REF);
+        String latValue = getAttribute(TAG_GPS_LATITUDE);
+        String latRef = getAttribute(TAG_GPS_LATITUDE_REF);
+        String lngValue = getAttribute(TAG_GPS_LONGITUDE);
+        String lngRef = getAttribute(TAG_GPS_LONGITUDE_REF);
 
         if (latValue != null && latRef != null && lngValue != null && lngRef != null) {
             try {
@@ -850,7 +1079,7 @@
      * @hide
      */
     public long getDateTime() {
-        String dateTimeString = mAttributes.get(TAG_DATETIME);
+        String dateTimeString = getAttribute(TAG_DATETIME);
         if (dateTimeString == null
                 || !sNonZeroTimePattern.matcher(dateTimeString).matches()) return -1;
 
@@ -862,7 +1091,7 @@
             if (datetime == null) return -1;
             long msecs = datetime.getTime();
 
-            String subSecs = mAttributes.get(TAG_SUBSECTIME);
+            String subSecs = getAttribute(TAG_SUBSECTIME);
             if (subSecs != null) {
                 try {
                     long sub = Long.valueOf(subSecs);
@@ -875,7 +1104,7 @@
                 }
             }
             return msecs;
-        } catch (IllegalArgumentException ex) {
+        } catch (IllegalArgumentException e) {
             return -1;
         }
     }
@@ -886,8 +1115,8 @@
      * @hide
      */
     public long getGpsDateTime() {
-        String date = mAttributes.get(TAG_GPS_DATESTAMP);
-        String time = mAttributes.get(TAG_GPS_TIMESTAMP);
+        String date = getAttribute(TAG_GPS_DATESTAMP);
+        String time = getAttribute(TAG_GPS_TIMESTAMP);
         if (date == null || time == null
                 || (!sNonZeroTimePattern.matcher(date).matches()
                 && !sNonZeroTimePattern.matcher(time).matches())) return -1;
@@ -899,7 +1128,7 @@
             Date datetime = sFormatter.parse(dateTimeString, pos);
             if (datetime == null) return -1;
             return datetime.getTime();
-        } catch (IllegalArgumentException ex) {
+        } catch (IllegalArgumentException e) {
             return -1;
         }
     }
@@ -1007,8 +1236,7 @@
                     if (dataInputStream.read(bytes) != length) {
                         throw new IOException("Invalid exif");
                     }
-                    mAttributes.put("UserComment",
-                            new String(bytes, Charset.forName("US-ASCII")));
+                    setAttribute("UserComment", new String(bytes, Charset.forName("US-ASCII")));
                     break;
                 }
 
@@ -1026,10 +1254,9 @@
                 case MARKER_SOF14:
                 case MARKER_SOF15: {
                     dataInputStream.skipBytes(1);
-                    mAttributes.put("ImageLength",
+                    setAttribute("ImageLength",
                             String.valueOf(dataInputStream.readUnsignedShort()));
-                    mAttributes.put("ImageWidth",
-                            String.valueOf(dataInputStream.readUnsignedShort()));
+                    setAttribute("ImageWidth", String.valueOf(dataInputStream.readUnsignedShort()));
                     length -= 5;
                     break;
                 }
@@ -1166,38 +1393,44 @@
         readImageFileDirectory(dataInputStream, IFD_TIFF_HINT);
 
         // Process thumbnail.
-        try {
-            int jpegInterchangeFormat = Integer.parseInt(
-                    mAttributes.get(JPEG_INTERCHANGE_FORMAT_TAG.name));
-            int jpegInterchangeFormatLength = Integer.parseInt(
-                    mAttributes.get(JPEG_INTERCHANGE_FORMAT_LENGTH_TAG.name));
-            // The following code limits the size of thumbnail size not to overflow EXIF data area.
-            jpegInterchangeFormatLength = Math.min(jpegInterchangeFormat
-                    + jpegInterchangeFormatLength, exifOffsetFromBeginning + exifBytes.length)
-                    - jpegInterchangeFormat;
-            if (jpegInterchangeFormat > 0 && jpegInterchangeFormatLength > 0) {
-                mHasThumbnail = true;
-                mThumbnailOffset = exifOffsetFromBeginning + jpegInterchangeFormat;
-                mThumbnailLength = jpegInterchangeFormatLength;
+        String jpegInterchangeFormatString = getAttribute(JPEG_INTERCHANGE_FORMAT_TAG.name);
+        String jpegInterchangeFormatLengthString =
+                getAttribute(JPEG_INTERCHANGE_FORMAT_LENGTH_TAG.name);
+        if (jpegInterchangeFormatString != null && jpegInterchangeFormatLengthString != null) {
+            try {
+                int jpegInterchangeFormat = Integer.parseInt(jpegInterchangeFormatString);
+                int jpegInterchangeFormatLength = Integer
+                        .parseInt(jpegInterchangeFormatLengthString);
+                // The following code limits the size of thumbnail size not to overflow EXIF data area.
+                jpegInterchangeFormatLength = Math.min(jpegInterchangeFormat
+                        + jpegInterchangeFormatLength, exifOffsetFromBeginning + exifBytes.length)
+                        - jpegInterchangeFormat;
+                if (jpegInterchangeFormat > 0 && jpegInterchangeFormatLength > 0) {
+                    mHasThumbnail = true;
+                    mThumbnailOffset = exifOffsetFromBeginning + jpegInterchangeFormat;
+                    mThumbnailLength = jpegInterchangeFormatLength;
 
-                // Do not store a thumbnail in memory if the given input can be re-read.
-                if (mFileDescriptor == null && mFilename == null) {
-                    byte[] thumbnailBytes = new byte[jpegInterchangeFormatLength];
-                    dataInputStream.seek(jpegInterchangeFormat);
-                    dataInputStream.readFully(thumbnailBytes);
-                    mThumbnailBytes = thumbnailBytes;
+                    if (mFilename == null && mAssetInputStream == null
+                            && mSeekableFileDescriptor == null) {
+                        // Save the thumbnail in memory if the input doesn't support reading again.
+                        byte[] thumbnailBytes = new byte[jpegInterchangeFormatLength];
+                        dataInputStream.seek(jpegInterchangeFormat);
+                        dataInputStream.readFully(thumbnailBytes);
+                        mThumbnailBytes = thumbnailBytes;
 
-                    if (DEBUG) {
-                        Bitmap bitmap = BitmapFactory.decodeByteArray(
-                                thumbnailBytes, 0, thumbnailBytes.length);
-                        Log.d(TAG, "Thumbnail offset: " + mThumbnailOffset + ", length: "
-                                + mThumbnailLength + ", width: " + bitmap.getWidth() + ", height: "
-                                + bitmap.getHeight());
+                        if (DEBUG) {
+                            Bitmap bitmap = BitmapFactory.decodeByteArray(
+                                    thumbnailBytes, 0, thumbnailBytes.length);
+                            Log.d(TAG, "Thumbnail offset: " + mThumbnailOffset + ", length: "
+                                    + mThumbnailLength + ", width: " + bitmap.getWidth()
+                                    + ", height: "
+                                    + bitmap.getHeight());
+                        }
                     }
                 }
+            } catch (NumberFormatException e) {
+                // Ignored the corrupted image.
             }
-        } catch (NumberFormatException e) {
-            // Ignored the corrupted image.
         }
 
         // For compatibility, keep data formats as follows.
@@ -1208,7 +1441,7 @@
         convertToRational(TAG_FOCAL_LENGTH);
         convertToDouble(TAG_DIGITAL_ZOOM_RATIO);
         convertToDouble(TAG_EXPOSURE_TIME);
-        convertToDouble(TAG_APERTURE);
+        convertToDouble(TAG_F_NUMBER);
         convertToDouble(TAG_SUBJECT_DISTANCE);
         convertToInt(TAG_ISO);
         convertToDouble(TAG_EXPOSURE_BIAS_VALUE);
@@ -1224,29 +1457,29 @@
         convertToTimetamp(TAG_GPS_TIMESTAMP);
 
         // The value of DATETIME tag has the same value of DATETIME_ORIGINAL tag.
-        String valueOfDateTimeOriginal = mAttributes.get("DateTimeOriginal");
+        String valueOfDateTimeOriginal = getAttribute("DateTimeOriginal");
         if (valueOfDateTimeOriginal != null) {
-            mAttributes.put(TAG_DATETIME, valueOfDateTimeOriginal);
+            setAttribute(TAG_DATETIME, valueOfDateTimeOriginal);
         }
 
         // Add the default value.
-        if (!mAttributes.containsKey(TAG_IMAGE_WIDTH)) {
-            mAttributes.put(TAG_IMAGE_WIDTH, "0");
+        if (getAttribute(TAG_IMAGE_WIDTH) == null) {
+            setAttribute(TAG_IMAGE_WIDTH, "0");
         }
-        if (!mAttributes.containsKey(TAG_IMAGE_LENGTH)) {
-            mAttributes.put(TAG_IMAGE_LENGTH, "0");
+        if (getAttribute(TAG_IMAGE_LENGTH) == null) {
+            setAttribute(TAG_IMAGE_LENGTH, "0");
         }
-        if (!mAttributes.containsKey(TAG_ORIENTATION)) {
-            mAttributes.put(TAG_ORIENTATION, "0");
+        if (getAttribute(TAG_ORIENTATION) == null) {
+            setAttribute(TAG_ORIENTATION, "0");
         }
-        if (!mAttributes.containsKey(TAG_LIGHT_SOURCE)) {
-            mAttributes.put(TAG_LIGHT_SOURCE, "0");
+        if (getAttribute(TAG_LIGHT_SOURCE) == null) {
+            setAttribute(TAG_LIGHT_SOURCE, "0");
         }
     }
 
     // Converts the tag value to timestamp; Otherwise deletes the given tag.
     private void convertToTimetamp(String tagName) {
-        String entryValue = mAttributes.get(tagName);
+        String entryValue = getAttribute(tagName);
         if (entryValue == null) return;
         int dataFormat = getDataFormatOfExifEntryValue(entryValue);
         String[] components = entryValue.split(",");
@@ -1266,16 +1499,16 @@
                 int value = numerator / denominator;
                 stringBuilder.append(String.format("%02d", value));
             }
-            mAttributes.put(tagName, stringBuilder.toString());
+            setAttribute(tagName, stringBuilder.toString());
         } else if (dataFormat != IFD_FORMAT_STRING) {
-            mAttributes.remove(tagName);
+            setAttribute(tagName, null);
         }
     }
 
     // Checks the tag value of a given tag formatted in double type; Otherwise try to convert it to
     // double type or delete it.
     private void convertToDouble(String tagName) {
-        String entryValue = mAttributes.get(tagName);
+        String entryValue = getAttribute(tagName);
         if (entryValue == null) return;
         int dataFormat = getDataFormatOfExifEntryValue(entryValue);
         switch (dataFormat) {
@@ -1295,21 +1528,21 @@
                     }
                     stringBuilder.append((double) numerator / denominator);
                 }
-                mAttributes.put(tagName, stringBuilder.toString());
+                setAttribute(tagName, stringBuilder.toString());
                 break;
             }
             case IFD_FORMAT_DOUBLE:
                 // Keep it as is.
                 break;
             default:
-                mAttributes.remove(tagName);
+                setAttribute(tagName, null);
                 break;
         }
     }
 
     // Checks the tag value of a given tag formatted in int type; Otherwise deletes the tag value.
     private void convertToRational(String tagName) {
-        String entryValue = mAttributes.get(tagName);
+        String entryValue = getAttribute(tagName);
         if (entryValue == null) return;
         int dataFormat = getDataFormatOfExifEntryValue(entryValue);
         switch (dataFormat) {
@@ -1324,25 +1557,25 @@
                     double doubleValue = Double.parseDouble(component);
                     stringBuilder.append((int) (doubleValue * 10000.0)).append("/").append(10000);
                 }
-                mAttributes.put(tagName, stringBuilder.toString());
+                setAttribute(tagName, stringBuilder.toString());
                 break;
             }
             case IFD_FORMAT_SRATIONAL:
                 // Keep it as is.
                 break;
             default:
-                mAttributes.remove(tagName);
+                setAttribute(tagName, null);
                 break;
         }
     }
 
     // Checks the tag value of a given tag formatted in int type; Otherwise deletes the tag value.
     private void convertToInt(String tagName) {
-        String entryValue = mAttributes.get(tagName);
+        String entryValue = getAttribute(tagName);
         if (entryValue == null) return;
         int dataFormat = getDataFormatOfExifEntryValue(entryValue);
         if (dataFormat != IFD_FORMAT_SLONG) {
-            mAttributes.remove(tagName);
+            setAttribute(tagName, null);
         }
     }
 
@@ -1431,7 +1664,7 @@
                 String entryValue = readExifEntryValue(
                         dataInputStream, dataFormat, numberOfComponents);
                 if (entryValue != null) {
-                    mAttributes.put(tagName, entryValue);
+                    setAttribute(tagName, entryValue);
                 }
             } else {
                 StringBuilder entryValueBuilder = new StringBuilder();
@@ -1442,7 +1675,7 @@
                     entryValueBuilder.append(readExifEntryValue(
                             dataInputStream, dataFormat, numberOfComponents));
                 }
-                mAttributes.put(tagName, entryValueBuilder.toString());
+                setAttribute(tagName, entryValueBuilder.toString());
             }
 
             if (dataInputStream.peek() != nextEntryOffset) {
@@ -1517,8 +1750,6 @@
                 StringBuilder stringBuilder = new StringBuilder();
                 while (true) {
                     int ch = bytes[index];
-                    if (ch < 0)
-                        throw new EOFException();
                     if (ch == 0)
                         break;
                     if (ch >= 32)
@@ -1554,49 +1785,46 @@
         int[] ifdOffsets = new int[EXIF_TAGS.length];
         int[] ifdDataSizes = new int[EXIF_TAGS.length];
 
-        // Maps to store tags per IFD tag group
-        HashMap[] ifdTags = new HashMap[EXIF_TAGS.length];
-        for (int i = 0; i < EXIF_TAGS.length; ++i) {
-            ifdTags[i] = new HashMap();
-        }
-
         // Remove IFD pointer tags (we'll re-add it later.)
         for (ExifTag tag : IFD_POINTER_TAGS) {
-            mAttributes.remove(tag.name);
-        }
-
-        // Assign tags to the corresponding group
-        for (Map.Entry<String, String> entry : mAttributes.entrySet()) {
-            Pair<Integer, Integer> pair = sExifTagMapForWriting.get(entry.getKey());
-            if (pair != null) {
-                int tagNumber = pair.first;
-                int hint = pair.second;
-                ifdTags[hint].put(tagNumber, entry.getValue());
-            }
+            setAttribute(tag.name, null);
         }
 
         // Add IFD pointer tags. The next offset of primary image TIFF IFD will have thumbnail IFD
         // offset when there is one or more tags in the thumbnail IFD.
-        if (!ifdTags[IFD_INTEROPERABILITY_HINT].isEmpty()) {
-            ifdTags[IFD_EXIF_HINT].put(IFD_POINTER_TAGS[2].number, "0");
+        if (!mAttributes[IFD_INTEROPERABILITY_HINT].isEmpty()) {
+            mAttributes[IFD_EXIF_HINT].put(IFD_POINTER_TAGS[2].name, "0");
         }
-        if (!ifdTags[IFD_EXIF_HINT].isEmpty()) {
-            ifdTags[IFD_TIFF_HINT].put(IFD_POINTER_TAGS[0].number, "0");
+        if (!mAttributes[IFD_EXIF_HINT].isEmpty()) {
+            mAttributes[IFD_TIFF_HINT].put(IFD_POINTER_TAGS[0].name, "0");
         }
-        if (!ifdTags[IFD_GPS_HINT].isEmpty()) {
-            ifdTags[IFD_TIFF_HINT].put(IFD_POINTER_TAGS[1].number, "0");
+        if (!mAttributes[IFD_GPS_HINT].isEmpty()) {
+            mAttributes[IFD_TIFF_HINT].put(IFD_POINTER_TAGS[1].name, "0");
         }
+        // Remove old thumbnail data
+        setAttribute(JPEG_INTERCHANGE_FORMAT_TAG.name, null);
+        setAttribute(JPEG_INTERCHANGE_FORMAT_LENGTH_TAG.name, null);
         if (mHasThumbnail) {
-            ifdTags[IFD_TIFF_HINT].put(JPEG_INTERCHANGE_FORMAT_TAG.number, "0");
-            ifdTags[IFD_TIFF_HINT].put(JPEG_INTERCHANGE_FORMAT_LENGTH_TAG.number,
+            mAttributes[IFD_TIFF_HINT].put(JPEG_INTERCHANGE_FORMAT_TAG.name, "0");
+            mAttributes[IFD_TIFF_HINT].put(JPEG_INTERCHANGE_FORMAT_LENGTH_TAG.name,
                     String.valueOf(mThumbnailLength));
         }
 
+        // Remove null value tags.
+        for (int hint = 0; hint < EXIF_TAGS.length; ++hint) {
+            for (Object obj : mAttributes[hint].entrySet().toArray()) {
+                Map.Entry entry = (Map.Entry) obj;
+                if (entry.getValue() == null) {
+                    mAttributes[hint].remove(entry.getKey());
+                }
+            }
+        }
+
         // Calculate IFD group data area sizes. IFD group data area is assigned to save the entry
         // value which has a bigger size than 4 bytes.
         for (int i = 0; i < 5; ++i) {
             int sum = 0;
-            for (Object entry : ifdTags[i].entrySet()) {
+            for (Map.Entry entry : (Set<Map.Entry>) mAttributes[i].entrySet()) {
                 String entryValue = (String) ((Map.Entry) entry).getValue();
                 int dataFormat = getDataFormatOfExifEntryValue(entryValue);
                 int size = getSizeOfExifEntryValue(dataFormat, entryValue);
@@ -1610,16 +1838,16 @@
         // Calculate IFD offsets.
         int position = 8;
         for (int hint = 0; hint < EXIF_TAGS.length; ++hint) {
-            if (!ifdTags[hint].isEmpty()) {
+            if (!mAttributes[hint].isEmpty()) {
                 ifdOffsets[hint] = position;
-                position += 2 + ifdTags[hint].size() * 12 + 4 + ifdDataSizes[hint];
+                position += 2 + mAttributes[hint].size() * 12 + 4 + ifdDataSizes[hint];
             }
         }
         if (mHasThumbnail) {
             int thumbnailOffset = position;
-            ifdTags[IFD_TIFF_HINT].put(JPEG_INTERCHANGE_FORMAT_TAG.number,
+            mAttributes[IFD_TIFF_HINT].put(JPEG_INTERCHANGE_FORMAT_TAG.name,
                     String.valueOf(thumbnailOffset));
-            ifdTags[IFD_TIFF_HINT].put(JPEG_INTERCHANGE_FORMAT_LENGTH_TAG.number,
+            mAttributes[IFD_TIFF_HINT].put(JPEG_INTERCHANGE_FORMAT_LENGTH_TAG.name,
                     String.valueOf(mThumbnailLength));
             mThumbnailOffset = exifOffsetFromBeginning + thumbnailOffset;
             position += mThumbnailLength;
@@ -1631,21 +1859,21 @@
             Log.d(TAG, "totalSize length: " + totalSize);
             for (int i = 0; i < 5; ++i) {
                 Log.d(TAG, String.format("index: %d, offsets: %d, tag count: %d, data sizes: %d",
-                        i, ifdOffsets[i], ifdTags[i].size(), ifdDataSizes[i]));
+                        i, ifdOffsets[i], mAttributes[i].size(), ifdDataSizes[i]));
             }
         }
 
         // Update IFD pointer tags with the calculated offsets.
-        if (!ifdTags[IFD_EXIF_HINT].isEmpty()) {
-            ifdTags[IFD_TIFF_HINT].put(IFD_POINTER_TAGS[0].number,
+        if (!mAttributes[IFD_EXIF_HINT].isEmpty()) {
+            mAttributes[IFD_TIFF_HINT].put(IFD_POINTER_TAGS[0].name,
                     String.valueOf(ifdOffsets[IFD_EXIF_HINT]));
         }
-        if (!ifdTags[IFD_GPS_HINT].isEmpty()) {
-            ifdTags[IFD_TIFF_HINT].put(IFD_POINTER_TAGS[1].number,
+        if (!mAttributes[IFD_GPS_HINT].isEmpty()) {
+            mAttributes[IFD_TIFF_HINT].put(IFD_POINTER_TAGS[1].name,
                     String.valueOf(ifdOffsets[IFD_GPS_HINT]));
         }
-        if (!ifdTags[IFD_INTEROPERABILITY_HINT].isEmpty()) {
-            ifdTags[IFD_EXIF_HINT].put(IFD_POINTER_TAGS[2].number,
+        if (!mAttributes[IFD_INTEROPERABILITY_HINT].isEmpty()) {
+            mAttributes[IFD_EXIF_HINT].put(IFD_POINTER_TAGS[2].name,
                     String.valueOf(ifdOffsets[IFD_INTEROPERABILITY_HINT]));
         }
 
@@ -1658,16 +1886,16 @@
 
         // Write IFD groups. See JEITA CP-3451C Figure 7. page 12.
         for (int hint = 0; hint < EXIF_TAGS.length; ++hint) {
-            if (!ifdTags[hint].isEmpty()) {
+            if (!mAttributes[hint].isEmpty()) {
                 // See JEITA CP-3451C 4.6.2 IFD structure. page 13.
                 // Write entry count
-                dataOutputStream.writeUnsignedShort(ifdTags[hint].size());
+                dataOutputStream.writeUnsignedShort(mAttributes[hint].size());
 
                 // Write entry info
-                int dataOffset = ifdOffsets[hint] + 2 + ifdTags[hint].size() * 12 + 4;
-                for (Object obj : ifdTags[hint].entrySet()) {
-                    Map.Entry entry = (Map.Entry) obj;
-                    int tagNumber = (int) entry.getKey();
+                int dataOffset = ifdOffsets[hint] + 2 + mAttributes[hint].size() * 12 + 4;
+                for (Map.Entry entry : (Set<Map.Entry>) mAttributes[hint].entrySet()) {
+                    // Convert tag name to tag number.
+                    int tagNumber = (int) sExifTagMapsForWriting[hint].get(entry.getKey());
                     String entryValue = (String) entry.getValue();
 
                     int dataFormat = getDataFormatOfExifEntryValue(entryValue);
@@ -1695,15 +1923,14 @@
                 // Write the next offset. It writes the offset of thumbnail IFD if there is one or
                 // more tags in the thumbnail IFD when the current IFD is the primary image TIFF
                 // IFD; Otherwise 0.
-                if (hint == 0 && !ifdTags[IFD_THUMBNAIL_HINT].isEmpty()) {
+                if (hint == 0 && !mAttributes[IFD_THUMBNAIL_HINT].isEmpty()) {
                     dataOutputStream.writeUnsignedInt(ifdOffsets[IFD_THUMBNAIL_HINT]);
                 } else {
                     dataOutputStream.writeUnsignedInt(0);
                 }
 
                 // Write values of data field exceeding 4 bytes after the next offset.
-                for (Object obj : ifdTags[hint].entrySet()) {
-                    Map.Entry entry = (Map.Entry) obj;
+                for (Map.Entry entry : (Set<Map.Entry>) mAttributes[hint].entrySet()) {
                     String entryValue = (String) entry.getValue();
 
                     int dataFormat = getDataFormatOfExifEntryValue(entryValue);
@@ -1988,6 +2215,10 @@
     }
 
     // JNI methods for RAW formats.
-    private static native void initRawNative();
-    private static native HashMap getRawAttributesNative(FileDescriptor fileDescriptor);
+    private static native void nativeInitRaw();
+    private static native byte[] nativeGetThumbnailFromAsset(
+            long asset, int thumbnailOffset, int thumbnailLength);
+    private static native HashMap nativeGetRawAttributesFromAsset(long asset);
+    private static native HashMap nativeGetRawAttributesFromFileDescriptor(FileDescriptor fd);
+    private static native HashMap nativeGetRawAttributesFromInputStream(InputStream in);
 }
diff --git a/media/java/android/media/IAudioService.aidl b/media/java/android/media/IAudioService.aidl
index abe92c7..97f670b 100644
--- a/media/java/android/media/IAudioService.aidl
+++ b/media/java/android/media/IAudioService.aidl
@@ -20,7 +20,7 @@
 import android.bluetooth.BluetoothDevice;
 import android.content.ComponentName;
 import android.media.AudioAttributes;
-import android.media.AudioRecordConfiguration;
+import android.media.AudioRecordingConfiguration;
 import android.media.AudioRoutesInfo;
 import android.media.IAudioFocusDispatcher;
 import android.media.IAudioRoutesObserver;
@@ -54,10 +54,6 @@
 
     void setMasterMute(boolean mute, int flags, String callingPackage, int userId);
 
-    boolean isMasterMono();
-
-    void setMasterMono(boolean mute, String callingPackage, int userId);
-
     int getStreamVolume(int streamType);
 
     int getStreamMinVolume(int streamType);
@@ -168,5 +164,5 @@
 
     oneway void unregisterRecordingCallback(in IRecordingConfigDispatcher rcdb);
 
-    AudioRecordConfiguration[] getActiveRecordConfigurations();
+    AudioRecordingConfiguration[] getActiveRecordingConfigurations();
 }
diff --git a/media/java/android/media/IRecordingConfigDispatcher.aidl b/media/java/android/media/IRecordingConfigDispatcher.aidl
index a5eb8b9f..e803283 100644
--- a/media/java/android/media/IRecordingConfigDispatcher.aidl
+++ b/media/java/android/media/IRecordingConfigDispatcher.aidl
@@ -16,6 +16,8 @@
 
 package android.media;
 
+import android.media.AudioRecordingConfiguration;
+
 /**
  * AIDL for the RecordingActivity monitor in AudioService to signal audio recording updates.
  *
@@ -23,6 +25,6 @@
  */
 oneway interface IRecordingConfigDispatcher {
 
-    void dispatchRecordingConfigChange();
+    void dispatchRecordingConfigChange(in AudioRecordingConfiguration[] configs);
 
 }
diff --git a/media/java/android/media/IRingtonePlayer.aidl b/media/java/android/media/IRingtonePlayer.aidl
index 8091421..4b1e39f 100644
--- a/media/java/android/media/IRingtonePlayer.aidl
+++ b/media/java/android/media/IRingtonePlayer.aidl
@@ -18,6 +18,7 @@
 
 import android.media.AudioAttributes;
 import android.net.Uri;
+import android.os.ParcelFileDescriptor;
 import android.os.UserHandle;
 
 /**
@@ -36,4 +37,6 @@
 
     /** Return the title of the media. */
     String getTitle(in Uri uri);
+
+    ParcelFileDescriptor openRingtone(in Uri uri);
 }
diff --git a/media/java/android/media/ImageReader.java b/media/java/android/media/ImageReader.java
index c08f4bf..81cc035 100644
--- a/media/java/android/media/ImageReader.java
+++ b/media/java/android/media/ImageReader.java
@@ -335,7 +335,6 @@
 
             switch (status) {
                 case ACQUIRE_SUCCESS:
-                    si.createSurfacePlanes();
                     si.mIsImageValid = true;
                 case ACQUIRE_NO_BUFS:
                 case ACQUIRE_MAX_IMAGES:
@@ -693,7 +692,7 @@
                     width = ImageReader.this.getWidth();
                     break;
                 default:
-                    width = nativeGetWidth(mFormat);
+                    width = nativeGetWidth();
             }
             return width;
         }
@@ -709,7 +708,7 @@
                     height = ImageReader.this.getHeight();
                     break;
                 default:
-                    height = nativeGetHeight(mFormat);
+                    height = nativeGetHeight();
             }
             return height;
         }
@@ -729,6 +728,10 @@
         @Override
         public Plane[] getPlanes() {
             throwISEIfImageIsInvalid();
+
+            if (mPlanes == null) {
+                mPlanes = nativeCreatePlanes(ImageReader.this.mNumPlanes, ImageReader.this.mFormat);
+            }
             // Shallow copy is fine.
             return mPlanes.clone();
         }
@@ -766,7 +769,8 @@
         }
 
         private void clearSurfacePlanes() {
-            if (mIsImageValid) {
+            // Image#getPlanes may not be called before the image is closed.
+            if (mIsImageValid && mPlanes != null) {
                 for (int i = 0; i < mPlanes.length; i++) {
                     if (mPlanes[i] != null) {
                         mPlanes[i].clearBuffer();
@@ -776,32 +780,25 @@
             }
         }
 
-        private void createSurfacePlanes() {
-            mPlanes = new SurfacePlane[ImageReader.this.mNumPlanes];
-            for (int i = 0; i < ImageReader.this.mNumPlanes; i++) {
-                mPlanes[i] = nativeCreatePlane(i, ImageReader.this.mFormat);
-            }
-        }
         private class SurfacePlane extends android.media.Image.Plane {
-            // SurfacePlane instance is created by native code when a new SurfaceImage is created
-            private SurfacePlane(int index, int rowStride, int pixelStride) {
-                mIndex = index;
+            // SurfacePlane instance is created by native code when SurfaceImage#getPlanes() is
+            // called
+            private SurfacePlane(int rowStride, int pixelStride, ByteBuffer buffer) {
                 mRowStride = rowStride;
                 mPixelStride = pixelStride;
+                mBuffer = buffer;
+                /**
+                 * Set the byteBuffer order according to host endianness (native
+                 * order), otherwise, the byteBuffer order defaults to
+                 * ByteOrder.BIG_ENDIAN.
+                 */
+                mBuffer.order(ByteOrder.nativeOrder());
             }
 
             @Override
             public ByteBuffer getBuffer() {
-                SurfaceImage.this.throwISEIfImageIsInvalid();
-                if (mBuffer != null) {
-                    return mBuffer;
-                } else {
-                    mBuffer = SurfaceImage.this.nativeImageGetBuffer(mIndex,
-                            ImageReader.this.mFormat);
-                    // Set the byteBuffer order according to host endianness (native order),
-                    // otherwise, the byteBuffer order defaults to ByteOrder.BIG_ENDIAN.
-                    return mBuffer.order(ByteOrder.nativeOrder());
-                }
+                throwISEIfImageIsInvalid();
+                return mBuffer;
             }
 
             @Override
@@ -837,7 +834,6 @@
                 mBuffer = null;
             }
 
-            final private int mIndex;
             final private int mPixelStride;
             final private int mRowStride;
 
@@ -860,10 +856,10 @@
         // If this image is detached from the ImageReader.
         private AtomicBoolean mIsDetached = new AtomicBoolean(false);
 
-        private synchronized native ByteBuffer nativeImageGetBuffer(int idx, int readerFormat);
-        private synchronized native SurfacePlane nativeCreatePlane(int idx, int readerFormat);
-        private synchronized native int nativeGetWidth(int format);
-        private synchronized native int nativeGetHeight(int format);
+        private synchronized native SurfacePlane[] nativeCreatePlanes(int numPlanes,
+                int readerFormat);
+        private synchronized native int nativeGetWidth();
+        private synchronized native int nativeGetHeight();
         private synchronized native int nativeGetFormat(int readerFormat);
     }
 
diff --git a/media/java/android/media/ImageWriter.java b/media/java/android/media/ImageWriter.java
index 851d436..83a4f17 100644
--- a/media/java/android/media/ImageWriter.java
+++ b/media/java/android/media/ImageWriter.java
@@ -748,8 +748,8 @@
             final private int mPixelStride;
             final private int mRowStride;
 
-            // SurfacePlane instance is created by native code when a new
-            // SurfaceImage is created
+            // SurfacePlane instance is created by native code when SurfaceImage#getPlanes() is
+            // called
             private SurfacePlane(int rowStride, int pixelStride, ByteBuffer buffer) {
                 mRowStride = rowStride;
                 mPixelStride = pixelStride;
@@ -795,7 +795,7 @@
 
         }
 
-        // this will create the SurfacePlane object and fill the information
+        // Create the SurfacePlane object and fill the information
         private synchronized native SurfacePlane[] nativeCreatePlanes(int numPlanes, int writerFmt);
 
         private synchronized native int nativeGetWidth();
diff --git a/media/java/android/media/MediaCodec.java b/media/java/android/media/MediaCodec.java
index f1f8437..c73cad4 100644
--- a/media/java/android/media/MediaCodec.java
+++ b/media/java/android/media/MediaCodec.java
@@ -2074,6 +2074,16 @@
          */
         public static final int ERROR_SESSION_NOT_OPENED = 5;
 
+        /**
+         * This indicates that an operation was attempted that could not be
+         * supported by the crypto system of the device in its current
+         * configuration.  It may occur when the license policy requires
+         * device security features that aren't supported by the device,
+         * or due to an internal error in the crypto system that prevents
+         * the specified security policy from being met.
+         */
+        public static final int ERROR_UNSUPPORTED_OPERATION = 6;
+
         /** @hide */
         @IntDef({
             ERROR_NO_KEY,
@@ -2081,6 +2091,7 @@
             ERROR_RESOURCE_BUSY,
             ERROR_INSUFFICIENT_OUTPUT_PROTECTION,
             ERROR_SESSION_NOT_OPENED,
+            ERROR_UNSUPPORTED_OPERATION
         })
         @Retention(RetentionPolicy.SOURCE)
         public @interface CryptoErrorCode {}
@@ -2221,7 +2232,10 @@
         public int mode;
 
         /**
-         * Metadata describing encryption pattern for the protected bytes in a subsample.
+         * Metadata describing an encryption pattern for the protected bytes in
+         * a subsample.  An encryption pattern consists of a repeating sequence
+         * of crypto blocks comprised of a number of encrypted blocks followed
+         * by a number of unencrypted, or skipped, blocks.
          */
         public final static class Pattern {
             /**
@@ -2273,6 +2287,10 @@
          */
         private Pattern pattern;
 
+        /**
+         * Set the subsample count, clear/encrypted sizes, key, IV and mode fields of
+         * a {@link MediaCodec.CryptoInfo} instance.
+         */
         public void set(
                 int newNumSubSamples,
                 @NonNull int[] newNumBytesOfClearData,
@@ -2289,6 +2307,10 @@
             pattern = new Pattern(0, 0);
         }
 
+        /**
+         * Set the encryption pattern on a {@link MediaCodec.CryptoInfo} instance.
+         * See {@link MediaCodec.CryptoInfo.Pattern}.
+         */
         public void setPattern(Pattern newPattern) {
             pattern = newPattern;
         }
@@ -3339,14 +3361,6 @@
         }
 
 
-        private int readInt(@NonNull ByteBuffer buffer, boolean asLong) {
-            if (asLong) {
-                return (int)buffer.getLong();
-            } else {
-                return buffer.getInt();
-            }
-        }
-
         public MediaImage(
                 @NonNull ByteBuffer buffer, @NonNull ByteBuffer info, boolean readOnly,
                 long timestamp, int xOffset, int yOffset, @Nullable Rect cropRect) {
@@ -3361,39 +3375,46 @@
             mYOffset = yOffset;
             mInfo = info;
 
-            // read media-info.  the size of media info can be 80 or 156/160 depending on
-            // whether it was created on a 32- or 64-bit process.  See MediaImage
-            if (info.remaining() == 80 || info.remaining() == 156 || info.remaining() == 160) {
-                boolean sizeIsLong = info.remaining() != 80;
-                int type = readInt(info, info.remaining() == 160);
+            // read media-info.  See MediaImage2
+            if (info.remaining() == 104) {
+                int type = info.getInt();
                 if (type != TYPE_YUV) {
                     throw new UnsupportedOperationException("unsupported type: " + type);
                 }
-                int numPlanes = readInt(info, sizeIsLong);
+                int numPlanes = info.getInt();
                 if (numPlanes != 3) {
                     throw new RuntimeException("unexpected number of planes: " + numPlanes);
                 }
-                mWidth = readInt(info, sizeIsLong);
-                mHeight = readInt(info, sizeIsLong);
+                mWidth = info.getInt();
+                mHeight = info.getInt();
                 if (mWidth < 1 || mHeight < 1) {
                     throw new UnsupportedOperationException(
                             "unsupported size: " + mWidth + "x" + mHeight);
                 }
-                int bitDepth = readInt(info, sizeIsLong);
+                int bitDepth = info.getInt();
                 if (bitDepth != 8) {
                     throw new UnsupportedOperationException("unsupported bit depth: " + bitDepth);
                 }
+                int bitDepthAllocated = info.getInt();
+                if (bitDepthAllocated != 8) {
+                    throw new UnsupportedOperationException(
+                            "unsupported allocated bit depth: " + bitDepthAllocated);
+                }
                 mPlanes = new MediaPlane[numPlanes];
                 for (int ix = 0; ix < numPlanes; ix++) {
-                    int planeOffset = readInt(info, sizeIsLong);
-                    int colInc = readInt(info, sizeIsLong);
-                    int rowInc = readInt(info, sizeIsLong);
-                    int horiz = readInt(info, sizeIsLong);
-                    int vert = readInt(info, sizeIsLong);
+                    int planeOffset = info.getInt();
+                    int colInc = info.getInt();
+                    int rowInc = info.getInt();
+                    int horiz = info.getInt();
+                    int vert = info.getInt();
                     if (horiz != vert || horiz != (ix == 0 ? 1 : 2)) {
                         throw new UnsupportedOperationException("unexpected subsampling: "
                                 + horiz + "x" + vert + " on plane " + ix);
                     }
+                    if (colInc < 1 || rowInc < 1) {
+                        throw new UnsupportedOperationException("unexpected strides: "
+                                + colInc + " pixel, " + rowInc + " row on plane " + ix);
+                    }
 
                     buffer.clear();
                     buffer.position(mBuffer.position() + planeOffset
diff --git a/media/java/android/media/MediaCodecInfo.java b/media/java/android/media/MediaCodecInfo.java
index d9690f0..b1c1b79 100644
--- a/media/java/android/media/MediaCodecInfo.java
+++ b/media/java/android/media/MediaCodecInfo.java
@@ -2231,6 +2231,7 @@
                     switch (profileLevel.profile) {
                         case CodecProfileLevel.HEVCProfileMain:
                         case CodecProfileLevel.HEVCProfileMain10:
+                        case CodecProfileLevel.HEVCProfileMain10HDR10:
                             break;
                         default:
                             Log.w(TAG, "Unrecognized profile "
@@ -2632,8 +2633,9 @@
         public static final int VP9Level62 = 0x1000;
 
         // from OMX_VIDEO_HEVCPROFILETYPE
-        public static final int HEVCProfileMain   = 0x01;
-        public static final int HEVCProfileMain10 = 0x02;
+        public static final int HEVCProfileMain        = 0x01;
+        public static final int HEVCProfileMain10      = 0x02;
+        public static final int HEVCProfileMain10HDR10 = 0x1000;
 
         // from OMX_VIDEO_HEVCLEVELTYPE
         public static final int HEVCMainTierLevel1  = 0x1;
diff --git a/media/java/android/media/MediaExtractor.java b/media/java/android/media/MediaExtractor.java
index b339925..177344a 100644
--- a/media/java/android/media/MediaExtractor.java
+++ b/media/java/android/media/MediaExtractor.java
@@ -28,6 +28,8 @@
 import android.net.Uri;
 import android.os.IBinder;
 
+import com.android.internal.util.Preconditions;
+
 import java.io.FileDescriptor;
 import java.io.IOException;
 import java.lang.annotation.Retention;
@@ -189,6 +191,26 @@
     }
 
     /**
+     * Sets the data source (AssetFileDescriptor) to use. It is the caller's
+     * responsibility to close the file descriptor. It is safe to do so as soon
+     * as this call returns.
+     *
+     * @param afd the AssetFileDescriptor for the file you want to extract from.
+     */
+    public final void setDataSource(@NonNull AssetFileDescriptor afd)
+            throws IOException, IllegalArgumentException, IllegalStateException {
+        Preconditions.checkNotNull(afd);
+        // Note: using getDeclaredLength so that our behavior is the same
+        // as previous versions when the content provider is returning
+        // a full file.
+        if (afd.getDeclaredLength() < 0) {
+            setDataSource(afd.getFileDescriptor());
+        } else {
+            setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getDeclaredLength());
+        }
+    }
+
+    /**
      * Sets the data source (FileDescriptor) to use. It is the caller's responsibility
      * to close the file descriptor. It is safe to do so as soon as this call returns.
      *
diff --git a/media/java/android/media/MediaFormat.java b/media/java/android/media/MediaFormat.java
index 646ab4e..26061e4 100644
--- a/media/java/android/media/MediaFormat.java
+++ b/media/java/android/media/MediaFormat.java
@@ -16,6 +16,10 @@
 
 package android.media;
 
+import android.annotation.IntDef;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 import java.nio.ByteBuffer;
 import java.util.HashMap;
 import java.util.Map;
@@ -606,6 +610,16 @@
     /** BT.2020 color chromacity coordinates with KR = 0.2627, KB = 0.0593. */
     public static final int COLOR_STANDARD_BT2020 = 6;
 
+    /** @hide */
+    @IntDef({
+        COLOR_STANDARD_BT709,
+        COLOR_STANDARD_BT601_PAL,
+        COLOR_STANDARD_BT601_NTSC,
+        COLOR_STANDARD_BT2020,
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface ColorStandard {}
+
     /**
      * An optional key describing the opto-electronic transfer function used
      * for the video content.
@@ -628,6 +642,16 @@
     /** ARIB STD-B67 hybrid-log-gamma transfer function. This is used by some HDR video content. */
     public static final int COLOR_TRANSFER_HLG = 7;
 
+    /** @hide */
+    @IntDef({
+        COLOR_TRANSFER_LINEAR,
+        COLOR_TRANSFER_SDR_VIDEO,
+        COLOR_TRANSFER_ST2084,
+        COLOR_TRANSFER_HLG,
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface ColorTransfer {}
+
     /**
      * An optional key describing the range of the component values of the video content.
      *
@@ -644,6 +668,41 @@
     /** Full range. Y, Cr and Cb component values range from 0 to 255 for 8-bit content. */
     public static final int COLOR_RANGE_FULL = 1;
 
+    /** @hide */
+    @IntDef({
+        COLOR_RANGE_LIMITED,
+        COLOR_RANGE_FULL,
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface ColorRange {}
+
+    /**
+     * An optional key describing the static metadata of HDR (high-dynamic-range) video content.
+     *
+     * The associated value is a ByteBuffer. This buffer contains the raw contents of the
+     * Static Metadata Descriptor (including the descriptor ID) of an HDMI Dynamic Range and
+     * Mastering InfoFrame as defined by CTA-861.3. This key must be provided to video decoders
+     * for HDR video content unless this information is contained in the bitstream and the video
+     * decoder supports an HDR-capable profile. This key must be provided to video encoders for
+     * HDR video content.
+     */
+    public static final String KEY_HDR_STATIC_INFO = "hdr-static-info";
+
+    /**
+     * A key describing a unique ID for the content of a media track.
+     *
+     * <p>This key is used by {@link MediaExtractor}. Some extractors provide multiple encodings
+     * of the same track (e.g. float audio tracks for FLAC and WAV may be expressed as two
+     * tracks via MediaExtractor: a normal PCM track for backward compatibility, and a float PCM
+     * track for added fidelity. Similarly, Dolby Vision extractor may provide a baseline SDR
+     * version of a DV track.) This key can be used to identify which MediaExtractor tracks refer
+     * to the same underlying content.
+     * </p>
+     *
+     * The associated value is an integer.
+     */
+    public static final String KEY_TRACK_ID = "track-id";
+
     /* package private */ MediaFormat(Map<String, Object> map) {
         mMap = map;
     }
diff --git a/media/java/android/media/MediaMetadata.java b/media/java/android/media/MediaMetadata.java
index 39bcef5..722605f 100644
--- a/media/java/android/media/MediaMetadata.java
+++ b/media/java/android/media/MediaMetadata.java
@@ -16,6 +16,7 @@
 package android.media;
 
 import android.annotation.NonNull;
+import android.annotation.StringDef;
 import android.content.ContentResolver;
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
@@ -30,6 +31,8 @@
 import android.util.Log;
 import android.util.SparseArray;
 
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 import java.util.Set;
 
 /**
@@ -39,6 +42,40 @@
     private static final String TAG = "MediaMetadata";
 
     /**
+     * @hide
+     */
+    @StringDef({METADATA_KEY_TITLE, METADATA_KEY_ARTIST, METADATA_KEY_ALBUM, METADATA_KEY_AUTHOR,
+            METADATA_KEY_WRITER, METADATA_KEY_COMPOSER, METADATA_KEY_COMPILATION,
+            METADATA_KEY_DATE, METADATA_KEY_GENRE, METADATA_KEY_ALBUM_ARTIST, METADATA_KEY_ART_URI,
+            METADATA_KEY_ALBUM_ART_URI, METADATA_KEY_DISPLAY_TITLE, METADATA_KEY_DISPLAY_SUBTITLE,
+            METADATA_KEY_DISPLAY_DESCRIPTION, METADATA_KEY_DISPLAY_ICON_URI,
+            METADATA_KEY_MEDIA_ID})
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface TextKey {}
+
+    /**
+     * @hide
+     */
+    @StringDef({METADATA_KEY_DURATION, METADATA_KEY_YEAR, METADATA_KEY_TRACK_NUMBER,
+            METADATA_KEY_NUM_TRACKS, METADATA_KEY_DISC_NUMBER})
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface LongKey {}
+
+    /**
+     * @hide
+     */
+    @StringDef({METADATA_KEY_ART, METADATA_KEY_ALBUM_ART, METADATA_KEY_DISPLAY_ICON})
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface BitmapKey {}
+
+    /**
+     * @hide
+     */
+    @StringDef({METADATA_KEY_USER_RATING, METADATA_KEY_RATING})
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface RatingKey {}
+
+    /**
      * The title of the media.
      */
     public static final String METADATA_KEY_TITLE = "android.media.metadata.TITLE";
@@ -232,7 +269,7 @@
      */
     public static final String METADATA_KEY_MEDIA_ID = "android.media.metadata.MEDIA_ID";
 
-    private static final String[] PREFERRED_DESCRIPTION_ORDER = {
+    private static final @TextKey String[] PREFERRED_DESCRIPTION_ORDER = {
             METADATA_KEY_TITLE,
             METADATA_KEY_ARTIST,
             METADATA_KEY_ALBUM,
@@ -242,13 +279,13 @@
             METADATA_KEY_COMPOSER
     };
 
-    private static final String[] PREFERRED_BITMAP_ORDER = {
+    private static final @BitmapKey String[] PREFERRED_BITMAP_ORDER = {
             METADATA_KEY_DISPLAY_ICON,
             METADATA_KEY_ART,
             METADATA_KEY_ALBUM_ART
     };
 
-    private static final String[] PREFERRED_URI_ORDER = {
+    private static final @TextKey String[] PREFERRED_URI_ORDER = {
             METADATA_KEY_DISPLAY_ICON_URI,
             METADATA_KEY_ART_URI,
             METADATA_KEY_ALBUM_ART_URI
@@ -349,7 +386,7 @@
      * @param key The key the value is stored under
      * @return a CharSequence value, or null
      */
-    public CharSequence getText(String key) {
+    public CharSequence getText(@TextKey String key) {
         return mBundle.getCharSequence(key);
     }
 
@@ -362,7 +399,7 @@
      * @param key The key the value is stored under
      * @return a String value, or null
      */
-    public String getString(String key) {
+    public String getString(@TextKey String key) {
         CharSequence text = getText(key);
         if (text != null) {
             return text.toString();
@@ -377,7 +414,7 @@
      * @param key The key the value is stored under
      * @return a long value
      */
-    public long getLong(String key) {
+    public long getLong(@LongKey String key) {
         return mBundle.getLong(key, 0);
     }
 
@@ -388,7 +425,7 @@
      * @param key The key the value is stored under
      * @return A {@link Rating} or null
      */
-    public Rating getRating(String key) {
+    public Rating getRating(@RatingKey String key) {
         Rating rating = null;
         try {
             rating = mBundle.getParcelable(key);
@@ -406,7 +443,7 @@
      * @param key The key the value is stored under
      * @return A {@link Bitmap} or null
      */
-    public Bitmap getBitmap(String key) {
+    public Bitmap getBitmap(@BitmapKey String key) {
         Bitmap bmp = null;
         try {
             bmp = mBundle.getParcelable(key);
@@ -612,7 +649,7 @@
          * @param value The CharSequence value to store
          * @return The Builder to allow chaining
          */
-        public Builder putText(String key, CharSequence value) {
+        public Builder putText(@TextKey String key, CharSequence value) {
             if (METADATA_KEYS_TYPE.containsKey(key)) {
                 if (METADATA_KEYS_TYPE.get(key) != METADATA_TYPE_TEXT) {
                     throw new IllegalArgumentException("The " + key
@@ -654,7 +691,7 @@
          * @param value The String value to store
          * @return The Builder to allow chaining
          */
-        public Builder putString(String key, String value) {
+        public Builder putString(@TextKey String key, String value) {
             if (METADATA_KEYS_TYPE.containsKey(key)) {
                 if (METADATA_KEYS_TYPE.get(key) != METADATA_TYPE_TEXT) {
                     throw new IllegalArgumentException("The " + key
@@ -681,7 +718,7 @@
          * @param value The long value to store
          * @return The Builder to allow chaining
          */
-        public Builder putLong(String key, long value) {
+        public Builder putLong(@LongKey String key, long value) {
             if (METADATA_KEYS_TYPE.containsKey(key)) {
                 if (METADATA_KEYS_TYPE.get(key) != METADATA_TYPE_LONG) {
                     throw new IllegalArgumentException("The " + key
@@ -705,7 +742,7 @@
          * @param value The Rating value to store
          * @return The Builder to allow chaining
          */
-        public Builder putRating(String key, Rating value) {
+        public Builder putRating(@RatingKey String key, Rating value) {
             if (METADATA_KEYS_TYPE.containsKey(key)) {
                 if (METADATA_KEYS_TYPE.get(key) != METADATA_TYPE_RATING) {
                     throw new IllegalArgumentException("The " + key
@@ -734,7 +771,7 @@
          * @param value The Bitmap to store
          * @return The Builder to allow chaining
          */
-        public Builder putBitmap(String key, Bitmap value) {
+        public Builder putBitmap(@BitmapKey String key, Bitmap value) {
             if (METADATA_KEYS_TYPE.containsKey(key)) {
                 if (METADATA_KEYS_TYPE.get(key) != METADATA_TYPE_BITMAP) {
                     throw new IllegalArgumentException("The " + key
diff --git a/media/java/android/media/MediaMuxer.java b/media/java/android/media/MediaMuxer.java
index 8618ec9..ebe509c 100644
--- a/media/java/android/media/MediaMuxer.java
+++ b/media/java/android/media/MediaMuxer.java
@@ -127,7 +127,8 @@
      * @param path The path of the output media file.
      * @param format The format of the output media file.
      * @see android.media.MediaMuxer.OutputFormat
-     * @throws IOException if failed to open the file for write
+     * @throws IllegalArgumentException if path is invalid or format is not supported.
+     * @throws IOException if failed to open the file for write.
      */
     public MediaMuxer(@NonNull String path, @Format int format) throws IOException {
         if (path == null) {
@@ -165,6 +166,8 @@
      * By default, the rotation degree is 0.</p>
      * @param degrees the angle to be rotated clockwise in degrees.
      * The supported angles are 0, 90, 180, and 270 degrees.
+     * @throws IllegalArgumentException if degree is not supported.
+     * @throws IllegalStateException If this method is called after {@link #start}.
      */
     public void setOrientationHint(int degrees) {
         if (degrees != 0 && degrees != 90  && degrees != 180 && degrees != 270) {
@@ -217,6 +220,8 @@
      * Starts the muxer.
      * <p>Make sure this is called after {@link #addTrack} and before
      * {@link #writeSampleData}.</p>
+     * @throws IllegalStateException If this method is called after {@link #start}
+     * or Muxer is released
      */
     public void start() {
         if (mNativeObject == 0) {
@@ -233,6 +238,7 @@
     /**
      * Stops the muxer.
      * <p>Once the muxer stops, it can not be restarted.</p>
+     * @throws IllegalStateException if muxer is in the wrong state.
      */
     public void stop() {
         if (mState == MUXER_STATE_STARTED) {
@@ -264,6 +270,8 @@
      *               MediaFormat.
      * @return The track index for this newly added track, and it should be used
      * in the {@link #writeSampleData}.
+     * @throws IllegalArgumentException if format is invalid.
+     * @throws IllegalStateException if muxer is in the wrong state.
      */
     public int addTrack(@NonNull MediaFormat format) {
         if (format == null) {
@@ -314,6 +322,8 @@
      * @param byteBuf The encoded sample.
      * @param trackIndex The track index for this sample.
      * @param bufferInfo The buffer information related to this sample.
+     * @throws IllegalArgumentException if trackIndex, byteBuf or bufferInfo is  invalid.
+     * @throws IllegalStateException if muxer is in wrong state.
      * MediaMuxer uses the flags provided in {@link MediaCodec.BufferInfo},
      * to signal sync frames.
      */
diff --git a/media/java/android/media/MediaPlayer.java b/media/java/android/media/MediaPlayer.java
index adf8551..b78869e 100644
--- a/media/java/android/media/MediaPlayer.java
+++ b/media/java/android/media/MediaPlayer.java
@@ -2845,13 +2845,17 @@
                             MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, MEDIA_ERROR_UNSUPPORTED, null);
                     sendMessage(msg2);
                 }
-                if (mOnPreparedListener != null)
-                    mOnPreparedListener.onPrepared(mMediaPlayer);
+                OnPreparedListener onPreparedListener = mOnPreparedListener;
+                if (onPreparedListener != null)
+                    onPreparedListener.onPrepared(mMediaPlayer);
                 return;
 
             case MEDIA_PLAYBACK_COMPLETE:
-                if (mOnCompletionListener != null)
-                    mOnCompletionListener.onCompletion(mMediaPlayer);
+                {
+                    OnCompletionListener onCompletionListener = mOnCompletionListener;
+                    if (onCompletionListener != null)
+                        onCompletionListener.onCompletion(mMediaPlayer);
+                }
                 stayAwake(false);
                 return;
 
@@ -2875,13 +2879,15 @@
                 break;
 
             case MEDIA_BUFFERING_UPDATE:
-                if (mOnBufferingUpdateListener != null)
-                    mOnBufferingUpdateListener.onBufferingUpdate(mMediaPlayer, msg.arg1);
+                OnBufferingUpdateListener onBufferingUpdateListener = mOnBufferingUpdateListener;
+                if (onBufferingUpdateListener != null)
+                    onBufferingUpdateListener.onBufferingUpdate(mMediaPlayer, msg.arg1);
                 return;
 
             case MEDIA_SEEK_COMPLETE:
-                if (mOnSeekCompleteListener != null) {
-                    mOnSeekCompleteListener.onSeekComplete(mMediaPlayer);
+                OnSeekCompleteListener onSeekCompleteListener = mOnSeekCompleteListener;
+                if (onSeekCompleteListener != null) {
+                    onSeekCompleteListener.onSeekComplete(mMediaPlayer);
                 }
                 // fall through
 
@@ -2895,8 +2901,9 @@
                 return;
 
             case MEDIA_SET_VIDEO_SIZE:
-                if (mOnVideoSizeChangedListener != null) {
-                    mOnVideoSizeChangedListener.onVideoSizeChanged(
+                OnVideoSizeChangedListener onVideoSizeChangedListener = mOnVideoSizeChangedListener;
+                if (onVideoSizeChangedListener != null) {
+                    onVideoSizeChangedListener.onVideoSizeChanged(
                         mMediaPlayer, msg.arg1, msg.arg2);
                 }
                 return;
@@ -2904,11 +2911,15 @@
             case MEDIA_ERROR:
                 Log.e(TAG, "Error (" + msg.arg1 + "," + msg.arg2 + ")");
                 boolean error_was_handled = false;
-                if (mOnErrorListener != null) {
-                    error_was_handled = mOnErrorListener.onError(mMediaPlayer, msg.arg1, msg.arg2);
+                OnErrorListener onErrorListener = mOnErrorListener;
+                if (onErrorListener != null) {
+                    error_was_handled = onErrorListener.onError(mMediaPlayer, msg.arg1, msg.arg2);
                 }
-                if (mOnCompletionListener != null && ! error_was_handled) {
-                    mOnCompletionListener.onCompletion(mMediaPlayer);
+                {
+                    OnCompletionListener onCompletionListener = mOnCompletionListener;
+                    if (onCompletionListener != null && ! error_was_handled) {
+                        onCompletionListener.onCompletion(mMediaPlayer);
+                    }
                 }
                 stayAwake(false);
                 return;
@@ -2944,47 +2955,52 @@
                     break;
                 }
 
-                if (mOnInfoListener != null) {
-                    mOnInfoListener.onInfo(mMediaPlayer, msg.arg1, msg.arg2);
+                OnInfoListener onInfoListener = mOnInfoListener;
+                if (onInfoListener != null) {
+                    onInfoListener.onInfo(mMediaPlayer, msg.arg1, msg.arg2);
                 }
                 // No real default action so far.
                 return;
             case MEDIA_TIMED_TEXT:
-                if (mOnTimedTextListener == null)
+                OnTimedTextListener onTimedTextListener = mOnTimedTextListener;
+                if (onTimedTextListener == null)
                     return;
                 if (msg.obj == null) {
-                    mOnTimedTextListener.onTimedText(mMediaPlayer, null);
+                    onTimedTextListener.onTimedText(mMediaPlayer, null);
                 } else {
                     if (msg.obj instanceof Parcel) {
                         Parcel parcel = (Parcel)msg.obj;
                         TimedText text = new TimedText(parcel);
                         parcel.recycle();
-                        mOnTimedTextListener.onTimedText(mMediaPlayer, text);
+                        onTimedTextListener.onTimedText(mMediaPlayer, text);
                     }
                 }
                 return;
 
             case MEDIA_SUBTITLE_DATA:
-                if (mOnSubtitleDataListener == null) {
+                OnSubtitleDataListener onSubtitleDataListener = mOnSubtitleDataListener;
+                if (onSubtitleDataListener == null) {
                     return;
                 }
                 if (msg.obj instanceof Parcel) {
                     Parcel parcel = (Parcel) msg.obj;
                     SubtitleData data = new SubtitleData(parcel);
                     parcel.recycle();
-                    mOnSubtitleDataListener.onSubtitleData(mMediaPlayer, data);
+                    onSubtitleDataListener.onSubtitleData(mMediaPlayer, data);
                 }
                 return;
 
             case MEDIA_META_DATA:
-                if (mOnTimedMetaDataAvailableListener == null) {
+                OnTimedMetaDataAvailableListener onTimedMetaDataAvailableListener =
+                    mOnTimedMetaDataAvailableListener;
+                if (onTimedMetaDataAvailableListener == null) {
                     return;
                 }
                 if (msg.obj instanceof Parcel) {
                     Parcel parcel = (Parcel) msg.obj;
                     TimedMetaData data = TimedMetaData.createTimedMetaDataFromParcel(parcel);
                     parcel.recycle();
-                    mOnTimedMetaDataAvailableListener.onTimedMetaDataAvailable(mMediaPlayer, data);
+                    onTimedMetaDataAvailableListener.onTimedMetaDataAvailable(mMediaPlayer, data);
                 }
                 return;
 
diff --git a/media/java/android/media/MediaRouter.java b/media/java/android/media/MediaRouter.java
index bcc2b406..d8e0d6d 100644
--- a/media/java/android/media/MediaRouter.java
+++ b/media/java/android/media/MediaRouter.java
@@ -1547,18 +1547,30 @@
 
         private Object mTag;
 
+        /** @hide */
+        @IntDef({PLAYBACK_TYPE_LOCAL, PLAYBACK_TYPE_REMOTE})
+        @Retention(RetentionPolicy.SOURCE)
+        public @interface PlaybackType {}
+
         /**
          * The default playback type, "local", indicating the presentation of the media is happening
          * on the same device (e&#46;g&#46; a phone, a tablet) as where it is controlled from.
          * @see #getPlaybackType()
          */
         public final static int PLAYBACK_TYPE_LOCAL = 0;
+
         /**
          * A playback type indicating the presentation of the media is happening on
          * a different device (i&#46;e&#46; the remote device) than where it is controlled from.
          * @see #getPlaybackType()
          */
         public final static int PLAYBACK_TYPE_REMOTE = 1;
+
+        /** @hide */
+         @IntDef({PLAYBACK_VOLUME_FIXED,PLAYBACK_VOLUME_VARIABLE})
+         @Retention(RetentionPolicy.SOURCE)
+         private @interface PlaybackVolume {}
+
         /**
          * Playback information indicating the playback volume is fixed, i&#46;e&#46; it cannot be
          * controlled from this object. An example of fixed playback volume is a remote player,
@@ -1783,6 +1795,7 @@
          * @return the type of playback associated with this route
          * @see UserRouteInfo#setPlaybackType(int)
          */
+        @PlaybackType
         public int getPlaybackType() {
             return mPlaybackType;
         }
@@ -1874,6 +1887,7 @@
          * @return how volume is handling on the route
          * @see UserRouteInfo#setVolumeHandling(int)
          */
+        @PlaybackVolume
         public int getVolumeHandling() {
             return mVolumeHandling;
         }
@@ -2164,7 +2178,7 @@
          *    ({@link RouteInfo#PLAYBACK_TYPE_REMOTE}).
          * @param type
          */
-        public void setPlaybackType(int type) {
+        public void setPlaybackType(@RouteInfo.PlaybackType int type) {
             if (mPlaybackType != type) {
                 mPlaybackType = type;
                 configureSessionVolume();
@@ -2177,7 +2191,7 @@
          * ({@link RouteInfo#PLAYBACK_VOLUME_VARIABLE}).
          * @param volumeHandling
          */
-        public void setVolumeHandling(int volumeHandling) {
+        public void setVolumeHandling(@RouteInfo.PlaybackVolume int volumeHandling) {
             if (mVolumeHandling != volumeHandling) {
                 mVolumeHandling = volumeHandling;
                 configureSessionVolume();
@@ -2268,7 +2282,8 @@
                 return;
             }
             if (mPlaybackType == RemoteControlClient.PLAYBACK_TYPE_REMOTE) {
-                int volumeControl = VolumeProvider.VOLUME_CONTROL_FIXED;
+                @VolumeProvider.ControlType int volumeControl =
+                        VolumeProvider.VOLUME_CONTROL_FIXED;
                 switch (mVolumeHandling) {
                     case RemoteControlClient.PLAYBACK_VOLUME_VARIABLE:
                         volumeControl = VolumeProvider.VOLUME_CONTROL_ABSOLUTE;
@@ -2294,7 +2309,8 @@
 
         class SessionVolumeProvider extends VolumeProvider {
 
-            public SessionVolumeProvider(int volumeControl, int maxVolume, int currentVolume) {
+            public SessionVolumeProvider(@VolumeProvider.ControlType int volumeControl,
+                    int maxVolume, int currentVolume) {
                 super(volumeControl, maxVolume, currentVolume);
             }
 
diff --git a/media/java/android/media/MediaScanner.java b/media/java/android/media/MediaScanner.java
index 78f357f..5fd85d1 100644
--- a/media/java/android/media/MediaScanner.java
+++ b/media/java/android/media/MediaScanner.java
@@ -1042,13 +1042,13 @@
 
             if(needToSetSettings) {
                 if (notifications) {
-                    setSettingIfNotSet(Settings.System.NOTIFICATION_SOUND, tableUri, rowId);
+                    setRingtoneIfNotSet(Settings.System.NOTIFICATION_SOUND, tableUri, rowId);
                     mDefaultNotificationSet = true;
                 } else if (ringtones) {
-                    setSettingIfNotSet(Settings.System.RINGTONE, tableUri, rowId);
+                    setRingtoneIfNotSet(Settings.System.RINGTONE, tableUri, rowId);
                     mDefaultRingtoneSet = true;
                 } else if (alarms) {
-                    setSettingIfNotSet(Settings.System.ALARM_ALERT, tableUri, rowId);
+                    setRingtoneIfNotSet(Settings.System.ALARM_ALERT, tableUri, rowId);
                     mDefaultAlarmSet = true;
                 }
             }
@@ -1063,18 +1063,18 @@
                     pathFilenameStart + filenameLength == path.length();
         }
 
-        private void setSettingIfNotSet(String settingName, Uri uri, long rowId) {
-
-            if(wasSettingAlreadySet(settingName)) {
+        private void setRingtoneIfNotSet(String settingName, Uri uri, long rowId) {
+            if (wasRingtoneAlreadySet(settingName)) {
                 return;
             }
 
             ContentResolver cr = mContext.getContentResolver();
             String existingSettingValue = Settings.System.getString(cr, settingName);
             if (TextUtils.isEmpty(existingSettingValue)) {
-                // Set the setting to the given URI
-                Settings.System.putString(cr, settingName,
-                        ContentUris.withAppendedId(uri, rowId).toString());
+                final Uri settingUri = Settings.System.getUriFor(settingName);
+                final Uri ringtoneUri = ContentUris.withAppendedId(uri, rowId);
+                RingtoneManager.setActualDefaultRingtoneUri(mContext,
+                        RingtoneManager.getDefaultType(settingUri), ringtoneUri);
             }
             Settings.System.putInt(cr, settingSetIndicatorName(settingName), 1);
         }
@@ -1107,7 +1107,7 @@
         return base + "_set";
     }
 
-    private boolean wasSettingAlreadySet(String name) {
+    private boolean wasRingtoneAlreadySet(String name) {
         ContentResolver cr = mContext.getContentResolver();
         String indicatorName = settingSetIndicatorName(name);
         try {
@@ -1134,9 +1134,9 @@
             selectionArgs = new String[] { "" };
         }
 
-        mDefaultRingtoneSet = wasSettingAlreadySet(Settings.System.RINGTONE);
-        mDefaultNotificationSet = wasSettingAlreadySet(Settings.System.NOTIFICATION_SOUND);
-        mDefaultAlarmSet = wasSettingAlreadySet(Settings.System.ALARM_ALERT);
+        mDefaultRingtoneSet = wasRingtoneAlreadySet(Settings.System.RINGTONE);
+        mDefaultNotificationSet = wasRingtoneAlreadySet(Settings.System.NOTIFICATION_SOUND);
+        mDefaultAlarmSet = wasRingtoneAlreadySet(Settings.System.ALARM_ALERT);
 
         // Tell the provider to not delete the file.
         // If the file is truly gone the delete is unnecessary, and we want to avoid
diff --git a/media/java/android/media/Rating.java b/media/java/android/media/Rating.java
index a518bb4..04d5364f 100644
--- a/media/java/android/media/Rating.java
+++ b/media/java/android/media/Rating.java
@@ -16,10 +16,14 @@
 
 package android.media;
 
+import android.annotation.IntDef;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.util.Log;
 
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
 /**
  * A class to encapsulate rating information used as content metadata.
  * A rating is defined by its rating style (see {@link #RATING_HEART},
@@ -32,6 +36,21 @@
     private final static String TAG = "Rating";
 
     /**
+     * @hide
+     */
+    @IntDef({RATING_NONE, RATING_HEART, RATING_THUMB_UP_DOWN, RATING_3_STARS, RATING_4_STARS,
+            RATING_5_STARS, RATING_PERCENTAGE})
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface Style {}
+
+    /**
+     * @hide
+     */
+    @IntDef({RATING_3_STARS, RATING_4_STARS, RATING_5_STARS})
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface StarStyle {}
+
+    /**
      * Indicates a rating style is not supported. A Rating will never have this
      * type, but can be used by other classes to indicate they do not support
      * Rating.
@@ -75,7 +94,7 @@
 
     private final float mRatingValue;
 
-    private Rating(int ratingStyle, float rating) {
+    private Rating(@Style int ratingStyle, float rating) {
         mRatingStyle = ratingStyle;
         mRatingValue = rating;
     }
@@ -124,7 +143,7 @@
      *    or {@link #RATING_PERCENTAGE}.
      * @return null if an invalid rating style is passed, a new Rating instance otherwise.
      */
-    public static Rating newUnratedRating(int ratingStyle) {
+    public static Rating newUnratedRating(@Style int ratingStyle) {
         switch(ratingStyle) {
             case RATING_HEART:
             case RATING_THUMB_UP_DOWN:
@@ -172,7 +191,7 @@
      * @return null if the rating style is invalid, or the rating is out of range,
      *     a new Rating instance otherwise.
      */
-    public static Rating newStarRating(int starRatingStyle, float starRating) {
+    public static Rating newStarRating(@StarStyle int starRatingStyle, float starRating) {
         float maxRating = -1.0f;
         switch(starRatingStyle) {
             case RATING_3_STARS:
@@ -225,6 +244,7 @@
      *    {@link #RATING_3_STARS}, {@link #RATING_4_STARS}, {@link #RATING_5_STARS},
      *    or {@link #RATING_PERCENTAGE}.
      */
+    @Style
     public int getRatingStyle() {
         return mRatingStyle;
     }
@@ -285,4 +305,4 @@
             return mRatingValue;
         }
     }
-}
\ No newline at end of file
+}
diff --git a/media/java/android/media/RingtoneManager.java b/media/java/android/media/RingtoneManager.java
index feb490d..86ebae1 100644
--- a/media/java/android/media/RingtoneManager.java
+++ b/media/java/android/media/RingtoneManager.java
@@ -16,10 +16,6 @@
 
 package android.media;
 
-import com.android.internal.database.SortCursor;
-
-import libcore.io.Streams;
-
 import android.annotation.SdkConstant;
 import android.annotation.SdkConstant.SdkConstantType;
 import android.app.Activity;
@@ -30,12 +26,17 @@
 import android.database.Cursor;
 import android.net.Uri;
 import android.os.Environment;
+import android.os.ParcelFileDescriptor;
 import android.os.Process;
 import android.provider.MediaStore;
 import android.provider.Settings;
 import android.provider.Settings.System;
 import android.util.Log;
 
+import com.android.internal.database.SortCursor;
+
+import libcore.io.Streams;
+
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
@@ -223,9 +224,9 @@
      */
     public static final int URI_COLUMN_INDEX = 2;
 
-    private Activity mActivity;
-    private Context mContext;
-    
+    private final Activity mActivity;
+    private final Context mContext;
+
     private Cursor mCursor;
 
     private int mType = TYPE_RINGTONE;
@@ -246,7 +247,8 @@
      * @param activity The activity used to get a managed cursor.
      */
     public RingtoneManager(Activity activity) {
-        mContext = mActivity = activity;
+        mActivity = activity;
+        mContext = activity;
         setType(mType);
     }
 
@@ -258,6 +260,7 @@
      * @param context The context to used to get a cursor.
      */
     public RingtoneManager(Context context) {
+        mActivity = null;
         mContext = context;
         setType(mType);
     }
@@ -271,7 +274,6 @@
      * @see #EXTRA_RINGTONE_TYPE           
      */
     public void setType(int type) {
-
         if (mCursor != null) {
             throw new IllegalStateException(
                     "Setting filter columns should be done before querying for ringtones.");
@@ -641,7 +643,8 @@
     public static Uri getActualDefaultRingtoneUri(Context context, int type) {
         String setting = getSettingForType(type);
         if (setting == null) return null;
-        final String uriString = Settings.System.getString(context.getContentResolver(), setting);
+        final String uriString = Settings.System.getStringForUser(context.getContentResolver(),
+                setting, context.getUserId());
         return uriString != null ? Uri.parse(uriString) : null;
     }
     
@@ -656,18 +659,19 @@
      * @see #getActualDefaultRingtoneUri(Context, int)
      */
     public static void setActualDefaultRingtoneUri(Context context, int type, Uri ringtoneUri) {
+        final ContentResolver resolver = context.getContentResolver();
+
         String setting = getSettingForType(type);
         if (setting == null) return;
-        Settings.System.putString(context.getContentResolver(), setting,
-                ringtoneUri != null ? ringtoneUri.toString() : null);
+        Settings.System.putStringForUser(resolver, setting,
+                ringtoneUri != null ? ringtoneUri.toString() : null, context.getUserId());
 
         // Stream selected ringtone into cache so it's available for playback
         // when CE storage is still locked
         if (ringtoneUri != null) {
-            final ContentResolver cr = context.getContentResolver();
             final Uri cacheUri = getCacheForType(type);
-            try (InputStream in = cr.openInputStream(ringtoneUri);
-                    OutputStream out = cr.openOutputStream(cacheUri)) {
+            try (InputStream in = openRingtone(context, ringtoneUri);
+                    OutputStream out = resolver.openOutputStream(cacheUri)) {
                 Streams.copy(in, out);
             } catch (IOException e) {
                 Log.w(TAG, "Failed to cache ringtone: " + e);
@@ -675,6 +679,28 @@
         }
     }
 
+    /**
+     * Try opening the given ringtone locally first, but failover to
+     * {@link IRingtonePlayer} if we can't access it directly. Typically happens
+     * when process doesn't hold
+     * {@link android.Manifest.permission#READ_EXTERNAL_STORAGE}.
+     */
+    private static InputStream openRingtone(Context context, Uri uri) throws IOException {
+        final ContentResolver resolver = context.getContentResolver();
+        try {
+            return resolver.openInputStream(uri);
+        } catch (SecurityException | IOException e) {
+            Log.w(TAG, "Failed to open directly; attempting failover: " + e);
+            final IRingtonePlayer player = context.getSystemService(AudioManager.class)
+                    .getRingtonePlayer();
+            try {
+                return new ParcelFileDescriptor.AutoCloseInputStream(player.openRingtone(uri));
+            } catch (Exception e2) {
+                throw new IOException(e2);
+            }
+        }
+    }
+
     private static String getSettingForType(int type) {
         if ((type & TYPE_RINGTONE) != 0) {
             return Settings.System.RINGTONE;
diff --git a/media/java/android/media/VolumeProvider.java b/media/java/android/media/VolumeProvider.java
index 5d1e004..1c017c5 100644
--- a/media/java/android/media/VolumeProvider.java
+++ b/media/java/android/media/VolumeProvider.java
@@ -15,8 +15,12 @@
  */
 package android.media;
 
+import android.annotation.IntDef;
 import android.media.session.MediaSession;
 
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
 /**
  * Handles requests to adjust or set the volume on a session. This is also used
  * to push volume updates back to the session. The provider must call
@@ -26,6 +30,14 @@
  * {@link MediaSession#setPlaybackToRemote}.
  */
 public abstract class VolumeProvider {
+
+    /**
+     * @hide
+     */
+    @IntDef({VOLUME_CONTROL_FIXED, VOLUME_CONTROL_RELATIVE, VOLUME_CONTROL_ABSOLUTE})
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface ControlType {}
+
     /**
      * The volume is fixed and can not be modified. Requests to change volume
      * should be ignored.
@@ -61,7 +73,7 @@
      * @param maxVolume The maximum allowed volume.
      * @param currentVolume The current volume on the output.
      */
-    public VolumeProvider(int volumeControl, int maxVolume, int currentVolume) {
+    public VolumeProvider(@ControlType int volumeControl, int maxVolume, int currentVolume) {
         mControlType = volumeControl;
         mMaxVolume = maxVolume;
         mCurrentVolume = currentVolume;
@@ -72,6 +84,7 @@
      *
      * @return The volume control type for this volume provider
      */
+    @ControlType
     public final int getVolumeControl() {
         return mControlType;
     }
@@ -145,4 +158,4 @@
     public static abstract class Callback {
         public abstract void onVolumeChanged(VolumeProvider volumeProvider);
     }
-}
\ No newline at end of file
+}
diff --git a/media/java/android/media/browse/MediaBrowser.java b/media/java/android/media/browse/MediaBrowser.java
index 2f72df6..fe2796c 100644
--- a/media/java/android/media/browse/MediaBrowser.java
+++ b/media/java/android/media/browse/MediaBrowser.java
@@ -73,7 +73,6 @@
      * Used as an int extra field to denote the page number to subscribe.
      * The value of {@code EXTRA_PAGE} should be greater than or equal to 1.
      *
-     * @see android.service.media.MediaBrowserService.BrowserRoot
      * @see #EXTRA_PAGE_SIZE
      */
     public static final String EXTRA_PAGE = "android.media.browse.extra.PAGE";
@@ -82,7 +81,6 @@
      * Used as an int extra field to denote the number of media items in a page.
      * The value of {@code EXTRA_PAGE_SIZE} should be greater than or equal to 1.
      *
-     * @see android.service.media.MediaBrowserService.BrowserRoot
      * @see #EXTRA_PAGE
      */
     public static final String EXTRA_PAGE_SIZE = "android.media.browse.extra.PAGE_SIZE";
@@ -367,7 +365,7 @@
         if (options == null) {
             throw new IllegalArgumentException("options are null");
         }
-        subscribeInternal(parentId, options, callback);
+        subscribeInternal(parentId, new Bundle(options), callback);
     }
 
     /**
@@ -635,7 +633,6 @@
                     return;
                 }
 
-                List<MediaItem> data = list == null ? null : list.getList();
                 if (DBG) {
                     Log.d(TAG, "onLoadChildren for " + mServiceComponent + " id=" + parentId);
                 }
@@ -646,10 +643,19 @@
                     // Tell the app.
                     SubscriptionCallback subscriptionCallback = subscription.getCallback(options);
                     if (subscriptionCallback != null) {
+                        List<MediaItem> data = list == null ? null : list.getList();
                         if (options == null) {
-                            subscriptionCallback.onChildrenLoaded(parentId, data);
+                            if (data == null) {
+                                subscriptionCallback.onError(parentId);
+                            } else {
+                                subscriptionCallback.onChildrenLoaded(parentId, data);
+                            }
                         } else {
-                            subscriptionCallback.onChildrenLoaded(parentId, data, options);
+                            if (data == null) {
+                                subscriptionCallback.onError(parentId, options);
+                            } else {
+                                subscriptionCallback.onChildrenLoaded(parentId, data, options);
+                            }
                         }
                         return;
                     }
@@ -850,21 +856,21 @@
          * Called when the list of children is loaded or updated.
          *
          * @param parentId The media id of the parent media item.
-         * @param children The children which were loaded, or null if the id is invalid.
+         * @param children The children which were loaded.
          */
-        public void onChildrenLoaded(@NonNull String parentId, List<MediaItem> children) {
+        public void onChildrenLoaded(@NonNull String parentId, @NonNull List<MediaItem> children) {
         }
 
         /**
          * Called when the list of children is loaded or updated.
          *
          * @param parentId The media id of the parent media item.
-         * @param children The children which were loaded, or null if the id is invalid.
-         * @param options A bundle of service-specific arguments to send to the media
+         * @param children The children which were loaded.
+         * @param options A bundle of service-specific arguments sent to the media
          *            browse service. The contents of this bundle may affect the
          *            information returned when browsing.
          */
-        public void onChildrenLoaded(@NonNull String parentId, List<MediaItem> children,
+        public void onChildrenLoaded(@NonNull String parentId, @NonNull List<MediaItem> children,
                 @NonNull Bundle options) {
         }
 
diff --git a/media/java/android/media/midi/MidiManager.java b/media/java/android/media/midi/MidiManager.java
index 266b0d9..07c8ae8 100644
--- a/media/java/android/media/midi/MidiManager.java
+++ b/media/java/android/media/midi/MidiManager.java
@@ -186,8 +186,7 @@
         try {
             mService.registerListener(mToken, deviceListener);
         } catch (RemoteException e) {
-            Log.e(TAG, "RemoteException in registerDeviceListener");
-            return;
+            throw e.rethrowFromSystemServer();
         }
         mDeviceListeners.put(callback, deviceListener);
     }
@@ -203,7 +202,7 @@
             try {
                 mService.unregisterListener(mToken, deviceListener);
             } catch (RemoteException e) {
-                Log.e(TAG, "RemoteException in unregisterDeviceListener");
+                throw e.rethrowFromSystemServer();
             }
         }
     }
@@ -217,8 +216,7 @@
         try {
            return mService.getDevices();
         } catch (RemoteException e) {
-            Log.e(TAG, "RemoteException in getDevices");
-            return new MidiDeviceInfo[0];
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -267,7 +265,7 @@
         try {
             mService.openDevice(mToken, deviceInfo, callback);
         } catch (RemoteException e) {
-            Log.e(TAG, "RemoteException in openDevice");
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -306,7 +304,7 @@
         try {
             mService.openBluetoothDevice(mToken, bluetoothDevice, callback);
         } catch (RemoteException e) {
-            Log.e(TAG, "RemoteException in openDevice");
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -326,8 +324,7 @@
             }
             return server;
         } catch (RemoteException e) {
-            Log.e(TAG, "RemoteException in createVirtualDevice");
-            return null;
+            throw e.rethrowFromSystemServer();
         }
     }
 }
diff --git a/media/java/android/media/session/MediaController.java b/media/java/android/media/session/MediaController.java
index 13db00e..622900f 100644
--- a/media/java/android/media/session/MediaController.java
+++ b/media/java/android/media/session/MediaController.java
@@ -592,10 +592,11 @@
         }
 
         /**
-         * Request that the player prepare its playback. Once the preparation is done, the session
-         * will change its playback state to {@link PlaybackState#STATE_PAUSED}. Afterwards,
-         * {@link #play} can be called to start playback. If the preparation is not needed,
-         * {@link #play} can be directly called without this method.
+         * Request that the player prepare its playback. In other words, other sessions can continue
+         * to play during the preparation of this session. This method can be used to speed up the
+         * start of the playback. Once the preparation is done, the session will change its playback
+         * state to {@link PlaybackState#STATE_PAUSED}. Afterwards, {@link #play} can be called to
+         * start playback.
          */
         public void prepare() {
             try {
@@ -606,10 +607,12 @@
         }
 
         /**
-         * Request that the player prepare playback for a specific media id. Once the preparation is
-         * done, the session will change its playback state to {@link PlaybackState#STATE_PAUSED}.
-         * Afterwards, {@link #play} can be called to start playback. If the preparation is not
-         * needed, {@link #playFromMediaId} can be directly called without this method.
+         * Request that the player prepare playback for a specific media id. In other words, other
+         * sessions can continue to play during the preparation of this session. This method can be
+         * used to speed up the start of the playback. Once the preparation is done, the session
+         * will change its playback state to {@link PlaybackState#STATE_PAUSED}. Afterwards,
+         * {@link #play} can be called to start playback. If the preparation is not needed,
+         * {@link #playFromMediaId} can be directly called without this method.
          *
          * @param mediaId The id of the requested media.
          * @param extras Optional extras that can include extra information about the media item
@@ -628,12 +631,13 @@
         }
 
         /**
-         * Request that the player prepare playback for a specific search query.
-         * An empty or null query should be treated as a request to prepare any
-         * music. Once the preparation is done, the session will change its playback state to
-         * {@link PlaybackState#STATE_PAUSED}. Afterwards, {@link #play} can be called to start
-         * playback. If the preparation is not needed, {@link #playFromSearch} can be directly
-         * called without this method.
+         * Request that the player prepare playback for a specific search query. An empty or null
+         * query should be treated as a request to prepare any music. In other words, other sessions
+         * can continue to play during the preparation of this session. This method can be used to
+         * speed up the start of the playback. Once the preparation is done, the session will
+         * change its playback state to {@link PlaybackState#STATE_PAUSED}. Afterwards,
+         * {@link #play} can be called to start playback. If the preparation is not needed,
+         * {@link #playFromSearch} can be directly called without this method.
          *
          * @param query The search query.
          * @param extras Optional extras that can include extra information
@@ -653,11 +657,12 @@
         }
 
         /**
-         * Request that the player prepare playback for a specific {@link Uri}.
-         * Once the preparation is done, the session will change its playback state to
-         * {@link PlaybackState#STATE_PAUSED}. Afterwards, {@link #play} can be called to start
-         * playback. If the preparation is not needed, {@link #playFromUri} can be directly
-         * called without this method.
+         * Request that the player prepare playback for a specific {@link Uri}. In other words,
+         * other sessions can continue to play during the preparation of this session. This method
+         * can be used to speed up the start of the playback. Once the preparation is done, the
+         * session will change its playback state to {@link PlaybackState#STATE_PAUSED}. Afterwards,
+         * {@link #play} can be called to start playback. If the preparation is not needed,
+         * {@link #playFromUri} can be directly called without this method.
          *
          * @param uri The URI of the requested media.
          * @param extras Optional extras that can include extra information about the media item
diff --git a/media/java/android/media/session/MediaSession.java b/media/java/android/media/session/MediaSession.java
index 9073077..7f9653d 100644
--- a/media/java/android/media/session/MediaSession.java
+++ b/media/java/android/media/session/MediaSession.java
@@ -469,7 +469,7 @@
      * <li>{@link Rating#RATING_THUMB_UP_DOWN}</li>
      * </ul>
      */
-    public void setRatingType(int type) {
+    public void setRatingType(@Rating.Style int type) {
         try {
             mBinder.setRatingType(type);
         } catch (RemoteException e) {
@@ -830,40 +830,45 @@
         }
 
         /**
-         * Override to handle requests to prepare playback. The state of playback should be updated
-         * to {@link PlaybackState#STATE_PAUSED} after the preparation is done. Override
-         * {@link #onPlay} to handle requests for starting playback of prepared content.
+         * Override to handle requests to prepare playback. During the preparation, a session should
+         * not hold audio focus in order to allow other sessions play seamlessly. The state of
+         * playback should be updated to {@link PlaybackState#STATE_PAUSED} after the preparation is
+         * done.
          */
         public void onPrepare() {
         }
 
         /**
          * Override to handle requests to prepare for playing a specific mediaId that was provided
-         * by your app's {@link MediaBrowserService}. The state of playback should be updated
-         * to {@link PlaybackState#STATE_PAUSED} after the preparation is done. The playback of
-         * the prepared content should start in the implementation of {@link #onPlay}. Override
-         * {@link #onPlayFromMediaId} to handle requests for starting playback without preparation.
+         * by your app's {@link MediaBrowserService}. During the preparation, a session should not
+         * hold audio focus in order to allow other sessions play seamlessly. The state of playback
+         * should be updated to {@link PlaybackState#STATE_PAUSED} after the preparation is done.
+         * The playback of the prepared content should start in the implementation of
+         * {@link #onPlay}. Override {@link #onPlayFromMediaId} to handle requests for starting
+         * playback without preparation.
          */
         public void onPrepareFromMediaId(String mediaId, Bundle extras) {
         }
 
         /**
-         * Override to handle requests to prepare playback from a search query. An
-         * empty query indicates that the app may prepare any music. The
-         * implementation should attempt to make a smart choice about what to
-         * play. The state of playback should be updated to {@link PlaybackState#STATE_PAUSED}
-         * after the preparation is done. The playback of the prepared content should start
-         * in the implementation of {@link #onPlay}. Override {@link #onPlayFromSearch}
-         * to handle requests for starting playback without preparation.
+         * Override to handle requests to prepare playback from a search query. An empty query
+         * indicates that the app may prepare any music. The implementation should attempt to make a
+         * smart choice about what to play. During the preparation, a session should not hold audio
+         * focus in order to allow other sessions play seamlessly. The state of playback should be
+         * updated to {@link PlaybackState#STATE_PAUSED} after the preparation is done. The playback
+         * of the prepared content should start in the implementation of {@link #onPlay}. Override
+         * {@link #onPlayFromSearch} to handle requests for starting playback without preparation.
          */
         public void onPrepareFromSearch(String query, Bundle extras) {
         }
 
         /**
          * Override to handle requests to prepare a specific media item represented by a URI.
-         * The state of playback should be updated to {@link PlaybackState#STATE_PAUSED}
-         * after the preparation is done. The playback of the prepared content should start in
-         * the implementation of {@link #onPlay}. Override {@link #onPlayFromUri} to handle requests
+         * During the preparation, a session should not hold audio focus in order to allow
+         * other sessions play seamlessly. The state of playback should be updated to
+         * {@link PlaybackState#STATE_PAUSED} after the preparation is done.
+         * The playback of the prepared content should start in the implementation of
+         * {@link #onPlay}. Override {@link #onPlayFromUri} to handle requests
          * for starting playback without preparation.
          */
         public void onPrepareFromUri(Uri uri, Bundle extras) {
diff --git a/media/java/android/media/session/MediaSessionLegacyHelper.java b/media/java/android/media/session/MediaSessionLegacyHelper.java
index c61d7ad..95cb8ae 100644
--- a/media/java/android/media/session/MediaSessionLegacyHelper.java
+++ b/media/java/android/media/session/MediaSessionLegacyHelper.java
@@ -154,8 +154,8 @@
                     metadata.getString(MediaMetadata.METADATA_KEY_WRITER));
         }
         if (metadata.containsKey(MediaMetadata.METADATA_KEY_YEAR)) {
-            oldMetadata.putString(String.valueOf(MediaMetadataRetriever.METADATA_KEY_YEAR),
-                    metadata.getString(MediaMetadata.METADATA_KEY_YEAR));
+            oldMetadata.putLong(String.valueOf(MediaMetadataRetriever.METADATA_KEY_YEAR),
+                    metadata.getLong(MediaMetadata.METADATA_KEY_YEAR));
         }
         return oldMetadata;
     }
diff --git a/media/java/android/media/session/PlaybackState.java b/media/java/android/media/session/PlaybackState.java
index 1485cd7..8283c8b 100644
--- a/media/java/android/media/session/PlaybackState.java
+++ b/media/java/android/media/session/PlaybackState.java
@@ -16,6 +16,7 @@
 package android.media.session;
 
 import android.annotation.DrawableRes;
+import android.annotation.IntDef;
 import android.annotation.Nullable;
 import android.media.RemoteControlClient;
 import android.os.Bundle;
@@ -26,6 +27,9 @@
 import java.util.ArrayList;
 import java.util.List;
 
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
 /**
  * Playback state for a {@link MediaSession}. This includes a state like
  * {@link PlaybackState#STATE_PLAYING}, the current playback position,
@@ -35,6 +39,17 @@
     private static final String TAG = "PlaybackState";
 
     /**
+     * @hide
+     */
+    @IntDef(flag=true, value={ACTION_STOP, ACTION_PAUSE, ACTION_PLAY, ACTION_REWIND,
+            ACTION_SKIP_TO_PREVIOUS, ACTION_SKIP_TO_NEXT, ACTION_FAST_FORWARD, ACTION_SET_RATING,
+            ACTION_SEEK_TO, ACTION_PLAY_PAUSE, ACTION_PLAY_FROM_MEDIA_ID, ACTION_PLAY_FROM_SEARCH,
+            ACTION_SKIP_TO_QUEUE_ITEM, ACTION_PLAY_FROM_URI, ACTION_PREPARE,
+            ACTION_PREPARE_FROM_MEDIA_ID, ACTION_PREPARE_FROM_SEARCH, ACTION_PREPARE_FROM_URI})
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface Actions {}
+
+    /**
      * Indicates this session supports the stop command.
      *
      * @see Builder#setActions(long)
@@ -161,6 +176,15 @@
     public static final long ACTION_PREPARE_FROM_URI = 1 << 17;
 
     /**
+     * @hide
+     */
+    @IntDef({STATE_NONE, STATE_STOPPED, STATE_PAUSED, STATE_PLAYING, STATE_FAST_FORWARDING,
+            STATE_REWINDING, STATE_BUFFERING, STATE_ERROR, STATE_CONNECTING,
+            STATE_SKIPPING_TO_PREVIOUS, STATE_SKIPPING_TO_NEXT, STATE_SKIPPING_TO_QUEUE_ITEM})
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface State {}
+
+    /**
      * This is the default playback state and indicates that no media has been
      * added yet, or the performer has been reset and has no content to play.
      *
@@ -349,9 +373,11 @@
      * <li> {@link PlaybackState#STATE_SKIPPING_TO_QUEUE_ITEM}</li>
      * </ul>
      */
+    @State
     public int getState() {
         return mState;
     }
+
     /**
      * Get the current playback position in ms.
      */
@@ -403,6 +429,7 @@
      * <li> {@link PlaybackState#ACTION_PREPARE_FROM_URI}</li>
      * </ul>
      */
+    @Actions
     public long getActions() {
         return mActions;
     }
@@ -866,7 +893,8 @@
          *            timebase that the position was updated at.
          * @return this
          */
-        public Builder setState(int state, long position, float playbackSpeed, long updateTime) {
+        public Builder setState(@State int state, long position, float playbackSpeed,
+                long updateTime) {
             mState = state;
             mPosition = position;
             mUpdateTime = updateTime;
@@ -907,7 +935,7 @@
          *            normal playback.
          * @return this
          */
-        public Builder setState(int state, long position, float playbackSpeed) {
+        public Builder setState(@State int state, long position, float playbackSpeed) {
             return setState(state, position, playbackSpeed, SystemClock.elapsedRealtime());
         }
 
@@ -938,7 +966,7 @@
          * @param actions The set of actions allowed.
          * @return this
          */
-        public Builder setActions(long actions) {
+        public Builder setActions(@Actions long actions) {
             mActions = actions;
             return this;
         }
diff --git a/media/java/android/media/soundtrigger/SoundTriggerManager.java b/media/java/android/media/soundtrigger/SoundTriggerManager.java
index 4fd3310..fdd7fc2 100644
--- a/media/java/android/media/soundtrigger/SoundTriggerManager.java
+++ b/media/java/android/media/soundtrigger/SoundTriggerManager.java
@@ -69,6 +69,7 @@
         try {
             mSoundTriggerService.updateSoundModel(model.getGenericSoundModel());
         } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -81,7 +82,7 @@
             return new Model(mSoundTriggerService.getSoundModel(
                     new ParcelUuid(soundModelId)));
         } catch (RemoteException e) {
-            return null;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -92,6 +93,7 @@
         try {
             mSoundTriggerService.deleteSoundModel(new ParcelUuid(soundModelId));
         } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
         }
     }
 
diff --git a/media/java/android/media/tv/ITvInputClient.aidl b/media/java/android/media/tv/ITvInputClient.aidl
index 5dd4e85..72f8b57 100644
--- a/media/java/android/media/tv/ITvInputClient.aidl
+++ b/media/java/android/media/tv/ITvInputClient.aidl
@@ -45,7 +45,7 @@
     void onTimeShiftCurrentPositionChanged(long timeMs, int seq);
 
     // For the recording session
-    void onTuned(int seq);
+    void onTuned(int seq, in Uri channelUri);
     void onRecordingStopped(in Uri recordedProgramUri, int seq);
     void onError(int error, int seq);
 }
diff --git a/media/java/android/media/tv/ITvInputSessionCallback.aidl b/media/java/android/media/tv/ITvInputSessionCallback.aidl
index 60d6f0d..af76f90 100644
--- a/media/java/android/media/tv/ITvInputSessionCallback.aidl
+++ b/media/java/android/media/tv/ITvInputSessionCallback.aidl
@@ -42,7 +42,7 @@
     void onTimeShiftCurrentPositionChanged(long timeMs);
 
     // For the recording session
-    void onTuned();
+    void onTuned(in Uri channelUri);
     void onRecordingStopped(in Uri recordedProgramUri);
     void onError(int error);
 }
diff --git a/media/java/android/media/tv/TvContract.java b/media/java/android/media/tv/TvContract.java
index a332195..e8c50e3 100644
--- a/media/java/android/media/tv/TvContract.java
+++ b/media/java/android/media/tv/TvContract.java
@@ -575,16 +575,11 @@
         /**
          * The original network ID of this TV channel.
          *
-         * <p>This is used to identify the originating delivery system, if applicable. Use the same
-         * coding for {@code original_network_id} in the underlying broadcast standard if it is
-         * defined there (e.g. ETSI EN 300 468/TR 101 211 and ARIB STD-B10). If channels cannot be
-         * globally identified by 2-tuple {{@link #COLUMN_TRANSPORT_STREAM_ID},
-         * {@link #COLUMN_SERVICE_ID}}, one must carefully assign a value to this field to form a
-         * unique 3-tuple identification {{@code COLUMN_ORIGINAL_NETWORK_ID},
-         * {@link #COLUMN_TRANSPORT_STREAM_ID}, {@link #COLUMN_SERVICE_ID}} for its channels.
+         * <p>It is used to identify the originating delivery system, if applicable. Use the same
+         * coding for {@code original_network_id} for ETSI EN 300 468/TR 101 211 and ARIB STD-B10.
          *
-         * <p>This is a required field if the channel cannot be uniquely identified by a 2-tuple
-         * {{@link #COLUMN_TRANSPORT_STREAM_ID}, {@link #COLUMN_SERVICE_ID}}.
+         * <p>This is a required field only if the underlying broadcast standard defines the same
+         * name field. Otherwise, leave empty.
          *
          * <p>Type: INTEGER
          */
@@ -593,13 +588,13 @@
         /**
          * The transport stream ID of this channel.
          *
-         * <p>This is used to identify the Transport Stream that contains the current channel from
-         * any other multiplex within a network, if applicable. Use the same coding for
+         * <p>It is used to identify the Transport Stream that contains the current channel from any
+         * other multiplex within a network, if applicable. Use the same coding for
          * {@code transport_stream_id} defined in ISO/IEC 13818-1 if the channel is transmitted via
-         * the MPEG Transport Stream as is the case for many digital broadcast standards.
+         * the MPEG Transport Stream.
          *
-         * <p>This is a required field if the current channel is transmitted via the MPEG Transport
-         * Stream.
+         * <p>This is a required field only if the current channel is transmitted via the MPEG
+         * Transport Stream. Leave empty otherwise.
          *
          * <p>Type: INTEGER
          */
@@ -608,15 +603,13 @@
         /**
          * The service ID of this channel.
          *
-         * <p>This is used to identify the current service (roughly equivalent to channel) from any
-         * other service within the Transport Stream, if applicable. Use the same coding for
-         * {@code service_id} in the underlying broadcast standard if it is defined there (e.g. ETSI
-         * EN 300 468 and ARIB STD-B10) or {@code program_number} (which usually has the same value
-         * as {@code service_id}) in ISO/IEC 13818-1 if the channel is transmitted via the MPEG
-         * Transport Stream.
+         * <p>It is used to identify the current service, or channel from any other services within
+         * a given Transport Stream, if applicable. Use the same coding for {@code service_id} in
+         * ETSI EN 300 468 and ARIB STD-B10 or {@code program_number} in ISO/IEC 13818-1.
          *
-         * <p>This is a required field if the current channel is transmitted via the MPEG Transport
-         * Stream.
+         * <p>This is a required field only if the underlying broadcast standard defines the same
+         * name field, or the current channel is transmitted via the MPEG Transport Stream. Leave
+         * empty otherwise.
          *
          * <p>Type: INTEGER
          */
diff --git a/media/java/android/media/tv/TvInputInfo.java b/media/java/android/media/tv/TvInputInfo.java
index ec65ffe..7c9591d 100644
--- a/media/java/android/media/tv/TvInputInfo.java
+++ b/media/java/android/media/tv/TvInputInfo.java
@@ -111,26 +111,32 @@
     public static final String EXTRA_INPUT_ID = "android.media.tv.extra.INPUT_ID";
 
     private final ResolveInfo mService;
+
     private final String mId;
-    private final String mParentId;
     private final int mType;
     private final boolean mIsHardwareInput;
-    private final Bundle mExtras;
+
+    // TODO: Remove mLabel and mIconUri when createTvInputInfo() is removed.
+    private String mLabel;
+    private Uri mIconUri;
+
+    private final int mLabelResId;
+    private final Icon mIcon;
+    private final Icon mIconStandby;
+    private final Icon mIconDisconnected;
 
     // Attributes from XML meta data.
-    private String mSetupActivity;
-    private String mSettingsActivity;
-    private boolean mCanRecord;
-    private int mTunerCount;
+    private final String mSetupActivity;
+    private final String mSettingsActivity;
+    private final boolean mCanRecord;
+    private final int mTunerCount;
 
-    private HdmiDeviceInfo mHdmiDeviceInfo;
-    private int mLabelResId;
-    // TODO: Remove when createTvInputInfo() is removed.
-    private String mLabel;
-    private Icon mIcon;
-    // TODO: Remove when createTvInputInfo() is removed.
-    private Uri mIconUri;
-    private boolean mIsConnectedToHdmiSwitch;
+    // Attributes specific to HDMI
+    private final HdmiDeviceInfo mHdmiDeviceInfo;
+    private final boolean mIsConnectedToHdmiSwitch;
+    private final String mParentId;
+
+    private final Bundle mExtras;
 
     /**
      * Create a new instance of the TvInputInfo class, instantiating it from the given Context,
@@ -240,28 +246,27 @@
                 .build();
     }
 
-    /**
-     * Constructor.
-     *
-     * @param service The ResolveInfo returned from the package manager about this TV input service.
-     * @param id ID of this TV input. Should be generated via generateInputId*().
-     * @param parentId ID of this TV input's parent input. {@code null} if none exists.
-     * @param type The type of this TV input service.
-     * @param isHardwareInput {@code true} if this TV input represents a hardware device.
-     *            {@code false} otherwise.
-     * @param isConnectedToHdmiSwitch Whether a CEC device for this TV input is connected to an HDMI
-     *            switch, i.e., the device isn't directly connected to a HDMI port.
-     */
-    private TvInputInfo(ResolveInfo service, String id, String parentId, int type,
-            boolean isHardwareInput, boolean isConnectedToHdmiSwitch, Bundle extras) {
+    private TvInputInfo(ResolveInfo service, String id, int type, boolean isHardwareInput,
+            int labelResId, Icon icon, Icon iconStandby, Icon iconDisconnected,
+            String setupActivity, String settingsActivity, boolean canRecord, int tunerCount,
+            HdmiDeviceInfo hdmiDeviceInfo, boolean isConnectedToHdmiSwitch, String parentId,
+            Bundle extras) {
         mService = service;
         mId = id;
-        mParentId = parentId;
         mType = type;
         mIsHardwareInput = isHardwareInput;
+        mLabelResId = labelResId;
+        mIcon = icon;
+        mIconStandby = iconStandby;
+        mIconDisconnected = iconDisconnected;
+        mSetupActivity = setupActivity;
+        mSettingsActivity = settingsActivity;
+        mCanRecord = canRecord;
+        mTunerCount = tunerCount;
+        mHdmiDeviceInfo = hdmiDeviceInfo;
         mIsConnectedToHdmiSwitch = isConnectedToHdmiSwitch;
+        mParentId = parentId;
         mExtras = extras;
-        mTunerCount = type == TYPE_TUNER ? 1 : 0;
     }
 
     /**
@@ -344,12 +349,12 @@
     /**
      * Returns the number of tuners this TV input has.
      *
-     * <p>This method is valid only for the input of type {@link #TYPE_TUNER}.
+     * <p>This method is valid only for inputs of type {@link #TYPE_TUNER}. For inputs of other
+     * types, it returns 0.
      *
      * <p>Tuners correspond to physical/logical resources that allow reception of TV signal. Having
      * <i>N</i> tuners means that the TV input is capable of receiving <i>N</i> different channels
      * concurrently.
-     *
      */
     public int getTunerCount() {
         return mTunerCount;
@@ -475,6 +480,36 @@
         return loadServiceIcon(context);
     }
 
+    /**
+     * Loads the user-displayed icon for this TV input per input state.
+     *
+     * @param context Supplies a {@link Context} used to load the icon.
+     * @param state The input state. Should be one of the followings.
+     *              {@link TvInputManager#INPUT_STATE_CONNECTED},
+     *              {@link TvInputManager#INPUT_STATE_CONNECTED_STANDBY} and
+     *              {@link TvInputManager#INPUT_STATE_DISCONNECTED}.
+     * @return a Drawable containing the TV input's icon for the given state or {@code null} if such
+     *         an icon is not defined.
+     * @hide
+     */
+    @SystemApi
+    public Drawable loadIcon(@NonNull Context context, int state) {
+        if (state == TvInputManager.INPUT_STATE_CONNECTED) {
+            return loadIcon(context);
+        } else if (state == TvInputManager.INPUT_STATE_CONNECTED_STANDBY) {
+            if (mIconStandby != null) {
+                return mIconStandby.loadDrawable(context);
+            }
+        } else if (state == TvInputManager.INPUT_STATE_DISCONNECTED) {
+            if (mIconDisconnected != null) {
+                return mIconDisconnected.loadDrawable(context);
+            }
+        } else {
+            throw new IllegalArgumentException("Unknown state: " + state);
+        }
+        return null;
+    }
+
     @Override
     public int describeContents() {
         return 0;
@@ -496,21 +531,23 @@
         }
 
         TvInputInfo obj = (TvInputInfo) o;
-        return TextUtils.equals(mId, obj.mId)
-                && TextUtils.equals(mParentId, obj.mParentId)
-                && Objects.equals(mService, obj.mService)
-                && TextUtils.equals(mSetupActivity, obj.mSetupActivity)
-                && TextUtils.equals(mSettingsActivity, obj.mSettingsActivity)
+        return Objects.equals(mService, obj.mService)
+                && TextUtils.equals(mId, obj.mId)
                 && mType == obj.mType
-                && mTunerCount == obj.mTunerCount
-                && mCanRecord == obj.mCanRecord
                 && mIsHardwareInput == obj.mIsHardwareInput
-                && Objects.equals(mHdmiDeviceInfo, obj.mHdmiDeviceInfo)
-                && Objects.equals(mIcon, obj.mIcon)
+                && TextUtils.equals(mLabel, obj.mLabel)
                 && Objects.equals(mIconUri, obj.mIconUri)
                 && mLabelResId == obj.mLabelResId
-                && TextUtils.equals(mLabel, obj.mLabel)
+                && Objects.equals(mIcon, obj.mIcon)
+                && Objects.equals(mIconStandby, obj.mIconStandby)
+                && Objects.equals(mIconDisconnected, obj.mIconDisconnected)
+                && TextUtils.equals(mSetupActivity, obj.mSetupActivity)
+                && TextUtils.equals(mSettingsActivity, obj.mSettingsActivity)
+                && mCanRecord == obj.mCanRecord
+                && mTunerCount == obj.mTunerCount
+                && Objects.equals(mHdmiDeviceInfo, obj.mHdmiDeviceInfo)
                 && mIsConnectedToHdmiSwitch == obj.mIsConnectedToHdmiSwitch
+                && TextUtils.equals(mParentId, obj.mParentId)
                 && Objects.equals(mExtras, obj.mExtras);
     }
 
@@ -529,21 +566,23 @@
      */
     @Override
     public void writeToParcel(@NonNull Parcel dest, int flags) {
-        dest.writeString(mId);
-        dest.writeString(mParentId);
         mService.writeToParcel(dest, flags);
-        dest.writeString(mSetupActivity);
-        dest.writeString(mSettingsActivity);
+        dest.writeString(mId);
         dest.writeInt(mType);
-        dest.writeInt(mTunerCount);
-        dest.writeByte(mCanRecord ? (byte) 1 : 0);
         dest.writeByte(mIsHardwareInput ? (byte) 1 : 0);
-        dest.writeParcelable(mHdmiDeviceInfo, flags);
-        dest.writeParcelable(mIcon, flags);
+        dest.writeString(mLabel);
         dest.writeParcelable(mIconUri, flags);
         dest.writeInt(mLabelResId);
-        dest.writeString(mLabel);
+        dest.writeParcelable(mIcon, flags);
+        dest.writeParcelable(mIconStandby, flags);
+        dest.writeParcelable(mIconDisconnected, flags);
+        dest.writeString(mSetupActivity);
+        dest.writeString(mSettingsActivity);
+        dest.writeByte(mCanRecord ? (byte) 1 : 0);
+        dest.writeInt(mTunerCount);
+        dest.writeParcelable(mHdmiDeviceInfo, flags);
         dest.writeByte(mIsConnectedToHdmiSwitch ? (byte) 1 : 0);
+        dest.writeString(mParentId);
         dest.writeBundle(mExtras);
     }
 
@@ -569,21 +608,23 @@
     };
 
     private TvInputInfo(Parcel in) {
-        mId = in.readString();
-        mParentId = in.readString();
         mService = ResolveInfo.CREATOR.createFromParcel(in);
-        mSetupActivity = in.readString();
-        mSettingsActivity = in.readString();
+        mId = in.readString();
         mType = in.readInt();
-        mTunerCount = in.readInt();
-        mCanRecord = in.readByte() == 1;
         mIsHardwareInput = in.readByte() == 1;
-        mHdmiDeviceInfo = in.readParcelable(null);
-        mIcon = in.readParcelable(null);
+        mLabel = in.readString();
         mIconUri = in.readParcelable(null);
         mLabelResId = in.readInt();
-        mLabel = in.readString();
+        mIcon = in.readParcelable(null);
+        mIconStandby = in.readParcelable(null);
+        mIconDisconnected = in.readParcelable(null);
+        mSetupActivity = in.readString();
+        mSettingsActivity = in.readString();
+        mCanRecord = in.readByte() == 1;
+        mTunerCount = in.readInt();
+        mHdmiDeviceInfo = in.readParcelable(null);
         mIsConnectedToHdmiSwitch = in.readByte() == 1;
+        mParentId = in.readString();
         mExtras = in.readBundle();
     }
 
@@ -619,24 +660,29 @@
 
         private final Context mContext;
         private final ResolveInfo mResolveInfo;
-        private Icon mIcon;
         private int mLabelResId;
-        private int mTunerCount = 1;
-        private boolean mCanRecord;
+        private Icon mIcon;
+        private Icon mIconStandby;
+        private Icon mIconDisconnected;
+        private String mSetupActivity;
+        private String mSettingsActivity;
+        private Boolean mCanRecord;
+        private Integer mTunerCount;
+        private TvInputHardwareInfo mTvInputHardwareInfo;
         private HdmiDeviceInfo mHdmiDeviceInfo;
         private String mParentId;
-        private TvInputHardwareInfo mTvInputHardwareInfo;
         private Bundle mExtras;
 
         /**
          * Constructs a new builder for {@link TvInputInfo}.
          *
          * @param context A Context of the application package implementing this class.
-         * @param cls The component class that is to be used for the {@link TvInputService}.
+         * @param component The name of the application component to be used for the
+         *            {@link TvInputService}.
          */
-        public Builder(Context context, Class<?> cls) {
+        public Builder(Context context, ComponentName component) {
             mContext = context;
-            Intent intent = new Intent(TvInputService.SERVICE_INTERFACE).setClass(context, cls);
+            Intent intent = new Intent(TvInputService.SERVICE_INTERFACE).setComponent(component);
             mResolveInfo = context.getPackageManager().resolveService(intent,
                     PackageManager.GET_SERVICES | PackageManager.GET_META_DATA);
         }
@@ -673,6 +719,31 @@
         }
 
         /**
+         * Sets the icon for a given input state.
+         *
+         * @param icon The icon that represents this TV input for the given state.
+         * @param state The input state. Should be one of the followings.
+         *              {@link TvInputManager#INPUT_STATE_CONNECTED},
+         *              {@link TvInputManager#INPUT_STATE_CONNECTED_STANDBY} and
+         *              {@link TvInputManager#INPUT_STATE_DISCONNECTED}.
+         * @return This Builder object to allow for chaining of calls to builder methods.
+         * @hide
+         */
+        @SystemApi
+        public Builder setIcon(Icon icon, int state) {
+            if (state == TvInputManager.INPUT_STATE_CONNECTED) {
+                this.mIcon = icon;
+            } else if (state == TvInputManager.INPUT_STATE_CONNECTED_STANDBY) {
+                this.mIconStandby = icon;
+            } else if (state == TvInputManager.INPUT_STATE_DISCONNECTED) {
+                this.mIconDisconnected = icon;
+            } else {
+                throw new IllegalArgumentException("Unknown state: " + state);
+            }
+            return this;
+        }
+
+        /**
          * Sets the label.
          *
          * @param resId The resource ID of the text to use.
@@ -796,10 +867,11 @@
                 id = generateInputId(componentName);
                 type = TYPE_TUNER;
             }
-
-            TvInputInfo info = new TvInputInfo(mResolveInfo, id, mParentId, type, isHardwareInput,
-                    isConnectedToHdmiSwitch, mExtras);
-            return parseServiceMetadata(type, info);
+            parseServiceMetadata(type);
+            return new TvInputInfo(mResolveInfo, id, type, isHardwareInput, mLabelResId, mIcon,
+                    mIconStandby, mIconDisconnected, mSetupActivity, mSettingsActivity,
+                    mCanRecord == null ? false : mCanRecord, mTunerCount == null ? 0 : mTunerCount,
+                    mHdmiDeviceInfo, isConnectedToHdmiSwitch, mParentId, mExtras);
         }
 
         private static String generateInputId(ComponentName name) {
@@ -821,7 +893,7 @@
                     + tvInputHardwareInfo.getDeviceId();
         }
 
-        private TvInputInfo parseServiceMetadata(int inputType, TvInputInfo info)
+        private void parseServiceMetadata(int inputType)
                 throws XmlPullParserException, IOException {
             ServiceInfo si = mResolveInfo.serviceInfo;
             PackageManager pm = mContext.getPackageManager();
@@ -848,32 +920,32 @@
 
                 TypedArray sa = res.obtainAttributes(attrs,
                         com.android.internal.R.styleable.TvInputService);
-                info.mSetupActivity = sa.getString(
+                mSetupActivity = sa.getString(
                         com.android.internal.R.styleable.TvInputService_setupActivity);
                 if (DEBUG) {
-                    Log.d(TAG, "Setup activity loaded. [" + info.mSetupActivity + "] for "
-                            + si.name);
+                    Log.d(TAG, "Setup activity loaded. [" + mSetupActivity + "] for " + si.name);
                 }
-                if (inputType == TYPE_TUNER && TextUtils.isEmpty(info.mSetupActivity)) {
+                if (inputType == TYPE_TUNER && TextUtils.isEmpty(mSetupActivity)) {
                     throw new XmlPullParserException("Setup activity not found in " + si.name);
                 }
-                info.mSettingsActivity = sa.getString(
+                mSettingsActivity = sa.getString(
                         com.android.internal.R.styleable.TvInputService_settingsActivity);
                 if (DEBUG) {
-                    Log.d(TAG, "Settings activity loaded. [" + info.mSettingsActivity + "] for "
+                    Log.d(TAG, "Settings activity loaded. [" + mSettingsActivity + "] for "
                             + si.name);
                 }
-                info.mCanRecord = sa.getBoolean(
-                        com.android.internal.R.styleable.TvInputService_canRecord, false);
-                info.mTunerCount = sa.getInt(
-                        com.android.internal.R.styleable.TvInputService_tunerCount,
-                        info.mTunerCount);
-
+                if (mCanRecord == null) {
+                    mCanRecord = sa.getBoolean(
+                            com.android.internal.R.styleable.TvInputService_canRecord, false);
+                }
+                if (mTunerCount == null && inputType == TYPE_TUNER) {
+                    mTunerCount = sa.getInt(
+                            com.android.internal.R.styleable.TvInputService_tunerCount, 1);
+                }
                 sa.recycle();
             } catch (NameNotFoundException e) {
                 throw new XmlPullParserException("Unable to create context for: " + si.packageName);
             }
-            return info;
         }
     }
 
diff --git a/media/java/android/media/tv/TvInputManager.java b/media/java/android/media/tv/TvInputManager.java
index 2703b1a..0b0306c 100644
--- a/media/java/android/media/tv/TvInputManager.java
+++ b/media/java/android/media/tv/TvInputManager.java
@@ -478,8 +478,10 @@
         /**
          * This is called when the recording session has been tuned to the given channel and is
          * ready to start recording.
+         *
+         * @param channelUri The URI of a channel.
          */
-        void onTuned(Session session) {
+        void onTuned(Session session, Uri channelUri) {
         }
 
         // For the recording session only
@@ -653,11 +655,11 @@
         }
 
         // For the recording session only
-        void postTuned() {
+        void postTuned(final Uri channelUri) {
             mHandler.post(new Runnable() {
                 @Override
                 public void run() {
-                    mSessionCallback.onTuned(mSession);
+                    mSessionCallback.onTuned(mSession, channelUri);
                 }
             });
         }
@@ -1013,14 +1015,14 @@
             }
 
             @Override
-            public void onTuned(int seq) {
+            public void onTuned(int seq, Uri channelUri) {
                 synchronized (mSessionCallbackRecordMap) {
                     SessionCallbackRecord record = mSessionCallbackRecordMap.get(seq);
                     if (record == null) {
                         Log.e(TAG, "Callback not found for seq " + seq);
                         return;
                     }
-                    record.postTuned();
+                    record.postTuned(channelUri);
                 }
             }
 
@@ -1109,7 +1111,7 @@
                 }
             }
         } catch (RemoteException e) {
-            Log.e(TAG, "TvInputManager initialization failed", e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1122,7 +1124,7 @@
         try {
             return mService.getTvInputList(mUserId);
         } catch (RemoteException e) {
-            throw new RuntimeException(e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1138,7 +1140,7 @@
         try {
             return mService.getTvInputInfo(inputId, mUserId);
         } catch (RemoteException e) {
-            throw new RuntimeException(e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1155,7 +1157,7 @@
         try {
             mService.updateTvInputInfo(inputInfo, mUserId);
         } catch (RemoteException e) {
-            throw new RuntimeException("Error trying to update " + inputInfo, e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1226,7 +1228,7 @@
         try {
             return mService.isParentalControlsEnabled(mUserId);
         } catch (RemoteException e) {
-            throw new RuntimeException(e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1243,7 +1245,7 @@
         try {
             mService.setParentalControlsEnabled(enabled, mUserId);
         } catch (RemoteException e) {
-            throw new RuntimeException(e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1258,7 +1260,7 @@
         try {
             return mService.isRatingBlocked(rating.flattenToString(), mUserId);
         } catch (RemoteException e) {
-            throw new RuntimeException(e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1277,7 +1279,7 @@
             }
             return ratings;
         } catch (RemoteException e) {
-            throw new RuntimeException(e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1295,7 +1297,7 @@
         try {
             mService.addBlockedRating(rating.flattenToString(), mUserId);
         } catch (RemoteException e) {
-            throw new RuntimeException(e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1313,7 +1315,7 @@
         try {
             mService.removeBlockedRating(rating.flattenToString(), mUserId);
         } catch (RemoteException e) {
-            throw new RuntimeException(e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1326,7 +1328,7 @@
         try {
             return mService.getTvContentRatingSystemList(mUserId);
         } catch (RemoteException e) {
-            throw new RuntimeException(e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1376,7 +1378,7 @@
             try {
                 mService.createSession(mClient, inputId, isRecordingSession, seq, mUserId);
             } catch (RemoteException e) {
-                throw new RuntimeException(e);
+                throw e.rethrowFromSystemServer();
             }
         }
     }
@@ -1400,7 +1402,7 @@
         try {
             return mService.getAvailableTvStreamConfigList(inputId, mUserId);
         } catch (RemoteException e) {
-            throw new RuntimeException(e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1418,7 +1420,7 @@
         try {
             return mService.captureFrame(inputId, surface, config, mUserId);
         } catch (RemoteException e) {
-            throw new RuntimeException(e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1432,7 +1434,7 @@
         try {
             return mService.isSingleSessionActive(mUserId);
         } catch (RemoteException e) {
-            throw new RuntimeException(e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1446,7 +1448,7 @@
         try {
             return mService.getHardwareList();
         } catch (RemoteException e) {
-            throw new RuntimeException(e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1476,7 +1478,7 @@
                 }
             }, info, mUserId));
         } catch (RemoteException e) {
-            throw new RuntimeException(e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1490,7 +1492,7 @@
         try {
             mService.releaseTvInputHardware(deviceId, hardware.getInterface(), mUserId);
         } catch (RemoteException e) {
-            throw new RuntimeException(e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1504,7 +1506,7 @@
         try {
             return mService.getDvbDeviceList();
         } catch (RemoteException e) {
-            throw new RuntimeException(e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1527,7 +1529,7 @@
             }
             return mService.openDvbDevice(info, device);
         } catch (RemoteException e) {
-            throw new RuntimeException(e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1598,7 +1600,7 @@
             try {
                 mService.releaseSession(mToken, mUserId);
             } catch (RemoteException e) {
-                throw new RuntimeException(e);
+                throw e.rethrowFromSystemServer();
             }
 
             releaseInternal();
@@ -1618,7 +1620,7 @@
             try {
                 mService.setMainSession(mToken, mUserId);
             } catch (RemoteException e) {
-                throw new RuntimeException(e);
+                throw e.rethrowFromSystemServer();
             }
         }
 
@@ -1636,7 +1638,7 @@
             try {
                 mService.setSurface(mToken, surface, mUserId);
             } catch (RemoteException e) {
-                throw new RuntimeException(e);
+                throw e.rethrowFromSystemServer();
             }
         }
 
@@ -1658,7 +1660,7 @@
             try {
                 mService.dispatchSurfaceChanged(mToken, format, width, height, mUserId);
             } catch (RemoteException e) {
-                throw new RuntimeException(e);
+                throw e.rethrowFromSystemServer();
             }
         }
 
@@ -1679,7 +1681,7 @@
                 }
                 mService.setVolume(mToken, volume, mUserId);
             } catch (RemoteException e) {
-                throw new RuntimeException(e);
+                throw e.rethrowFromSystemServer();
             }
         }
 
@@ -1719,7 +1721,7 @@
             try {
                 mService.tune(mToken, channelUri, params, mUserId);
             } catch (RemoteException e) {
-                throw new RuntimeException(e);
+                throw e.rethrowFromSystemServer();
             }
         }
 
@@ -1736,7 +1738,7 @@
             try {
                 mService.setCaptionEnabled(mToken, enabled, mUserId);
             } catch (RemoteException e) {
-                throw new RuntimeException(e);
+                throw e.rethrowFromSystemServer();
             }
         }
 
@@ -1778,7 +1780,7 @@
             try {
                 mService.selectTrack(mToken, type, trackId, mUserId);
             } catch (RemoteException e) {
-                throw new RuntimeException(e);
+                throw e.rethrowFromSystemServer();
             }
         }
 
@@ -1926,7 +1928,7 @@
             try {
                 mService.timeShiftPlay(mToken, recordedProgramUri, mUserId);
             } catch (RemoteException e) {
-                throw new RuntimeException(e);
+                throw e.rethrowFromSystemServer();
             }
         }
 
@@ -1941,7 +1943,7 @@
             try {
                 mService.timeShiftPause(mToken, mUserId);
             } catch (RemoteException e) {
-                throw new RuntimeException(e);
+                throw e.rethrowFromSystemServer();
             }
         }
 
@@ -1956,7 +1958,7 @@
             try {
                 mService.timeShiftResume(mToken, mUserId);
             } catch (RemoteException e) {
-                throw new RuntimeException(e);
+                throw e.rethrowFromSystemServer();
             }
         }
 
@@ -1977,7 +1979,7 @@
             try {
                 mService.timeShiftSeekTo(mToken, timeMs, mUserId);
             } catch (RemoteException e) {
-                throw new RuntimeException(e);
+                throw e.rethrowFromSystemServer();
             }
         }
 
@@ -1994,7 +1996,7 @@
             try {
                 mService.timeShiftSetPlaybackParams(mToken, params, mUserId);
             } catch (RemoteException e) {
-                throw new RuntimeException(e);
+                throw e.rethrowFromSystemServer();
             }
         }
 
@@ -2011,7 +2013,7 @@
             try {
                 mService.timeShiftEnablePositionTracking(mToken, enable, mUserId);
             } catch (RemoteException e) {
-                throw new RuntimeException(e);
+                throw e.rethrowFromSystemServer();
             }
         }
 
@@ -2029,7 +2031,7 @@
             try {
                 mService.startRecording(mToken, programHint, mUserId);
             } catch (RemoteException e) {
-                throw new RuntimeException(e);
+                throw e.rethrowFromSystemServer();
             }
         }
 
@@ -2044,7 +2046,7 @@
             try {
                 mService.stopRecording(mToken, mUserId);
             } catch (RemoteException e) {
-                throw new RuntimeException(e);
+                throw e.rethrowFromSystemServer();
             }
         }
 
@@ -2067,7 +2069,7 @@
             try {
                 mService.sendAppPrivateCommand(mToken, action, data, mUserId);
             } catch (RemoteException e) {
-                throw new RuntimeException(e);
+                throw e.rethrowFromSystemServer();
             }
         }
 
@@ -2095,7 +2097,7 @@
             try {
                 mService.createOverlayView(mToken, view.getWindowToken(), frame, mUserId);
             } catch (RemoteException e) {
-                throw new RuntimeException(e);
+                throw e.rethrowFromSystemServer();
             }
         }
 
@@ -2113,7 +2115,7 @@
             try {
                 mService.relayoutOverlayView(mToken, frame, mUserId);
             } catch (RemoteException e) {
-                throw new RuntimeException(e);
+                throw e.rethrowFromSystemServer();
             }
         }
 
@@ -2128,7 +2130,7 @@
             try {
                 mService.removeOverlayView(mToken, mUserId);
             } catch (RemoteException e) {
-                throw new RuntimeException(e);
+                throw e.rethrowFromSystemServer();
             }
         }
 
@@ -2144,7 +2146,7 @@
             try {
                 mService.unblockContent(mToken, unblockedRating.flattenToString(), mUserId);
             } catch (RemoteException e) {
-                throw new RuntimeException(e);
+                throw e.rethrowFromSystemServer();
             }
         }
 
diff --git a/media/java/android/media/tv/TvInputService.java b/media/java/android/media/tv/TvInputService.java
index db851a3..bc20c17 100644
--- a/media/java/android/media/tv/TvInputService.java
+++ b/media/java/android/media/tv/TvInputService.java
@@ -491,7 +491,7 @@
          * until this method is called.
          *
          * <p>The TV input service must call this method as soon as the content rendered onto its
-         * surface is ready for viewing. This method must be called each time {@link #onTune(Uri)}
+         * surface is ready for viewing. This method must be called each time {@link #onTune}
          * is called.
          *
          * @see #notifyVideoUnavailable
@@ -837,14 +837,15 @@
         public abstract boolean onTune(Uri channelUri);
 
         /**
-         * Calls {@link #onTune(Uri)}. Override this method in order to handle {@code params}.
+         * Calls {@link #onTune(Uri)}. Override this method in order to handle domain-specific
+         * features that are only known between certain TV inputs and their clients.
          *
          * @param channelUri The URI of the channel.
-         * @param params The extra parameters from other applications.
+         * @param params Domain-specific data for this tune request. Keys <em>must</em> be a scoped
+         *            name, i.e. prefixed with a package name you own, so that different developers
+         *            will not create conflicting keys.
          * @return {@code true} if the tuning was successful, {@code false} otherwise.
-         * @hide
          */
-        @SystemApi
         public boolean onTune(Uri channelUri, Bundle params) {
             return onTune(channelUri);
         }
@@ -1209,7 +1210,7 @@
         }
 
         /**
-         * Calls {@link #onTune}.
+         * Calls {@link #onTune(Uri, Bundle)}.
          */
         void tune(Uri channelUri, Bundle params) {
             mCurrentPositionMs = TvInputManager.TIME_SHIFT_INVALID_TIME;
@@ -1567,8 +1568,10 @@
          * passed channel and call this method to indicate that it is now available for immediate
          * recording. When {@link #onStartRecording(Uri)} is called, recording must start with
          * minimal delay.
+         *
+         * @param channelUri The URI of a channel.
          */
-        public void notifyTuned() {
+        public void notifyTuned(Uri channelUri) {
             executeOrPostRunnableOnMainThread(new Runnable() {
                 @MainThread
                 @Override
@@ -1576,7 +1579,7 @@
                     try {
                         if (DEBUG) Log.d(TAG, "notifyTuned");
                         if (mSessionCallback != null) {
-                            mSessionCallback.onTuned();
+                            mSessionCallback.onTuned(channelUri);
                         }
                     } catch (RemoteException e) {
                         Log.w(TAG, "error in notifyTuned", e);
@@ -1679,7 +1682,7 @@
          * <p>The application may call this method before starting or after stopping recording, but
          * not during recording.
          *
-         * <p>The session must call {@link #notifyTuned()} if the tune request was fulfilled, or
+         * <p>The session must call {@link #notifyTuned(Uri)} if the tune request was fulfilled, or
          * {@link #notifyError(int)} otherwise.
          *
          * @param channelUri The URI of a channel.
@@ -1708,8 +1711,8 @@
          * Called when the application requests to start TV program recording. Recording must start
          * immediately when this method is called.
          *
-         * <p>The application may supply the URI for a TV program as a hint for filling in program
-         * specific data fields in the {@link android.media.tv.TvContract.RecordedPrograms} table.
+         * <p>The application may supply the URI for a TV program for filling in program specific
+         * data fields in the {@link android.media.tv.TvContract.RecordedPrograms} table.
          * A non-null {@code programHint} implies the started recording should be of that specific
          * program, whereas null {@code programHint} does not impose such a requirement and the
          * recording can span across multiple TV programs. In either case, the application must call
@@ -1718,10 +1721,10 @@
          * <p>The session must call {@link #notifyError(int)} if the start request cannot be
          * fulfilled.
          *
-         * @param programHint The URI for the TV program to record as a hint, built by
+         * @param programUri The URI for the TV program to record, built by
          *            {@link TvContract#buildProgramUri(long)}. Can be {@code null}.
          */
-        public abstract void onStartRecording(@Nullable Uri programHint);
+        public abstract void onStartRecording(@Nullable Uri programUri);
 
         /**
          * Called when the application requests to stop TV program recording. Recording must stop
@@ -1834,7 +1837,7 @@
      * a hardware TV Input (e.g. HDMI 1) and forward the application's surface to the session so
      * that the user can see the screen of the hardware TV Input when she tunes to a channel from
      * this TV input. The implementation of this class is expected to change the channel of the
-     * external set-top box via a proprietary protocol when {@link HardwareSession#onTune(Uri)} is
+     * external set-top box via a proprietary protocol when {@link HardwareSession#onTune} is
      * requested by the application.
      *
      * <p>Note that this class is not for inputs for internal hardware like built-in tuner and HDMI
diff --git a/media/java/android/media/tv/TvRecordingClient.java b/media/java/android/media/tv/TvRecordingClient.java
index 1c920f5..d48ea21e 100644
--- a/media/java/android/media/tv/TvRecordingClient.java
+++ b/media/java/android/media/tv/TvRecordingClient.java
@@ -76,11 +76,12 @@
      * during recording.
      *
      * <p>The recording session will respond by calling
-     * {@link RecordingCallback#onTuned()} if the tune request was fulfilled, or
+     * {@link RecordingCallback#onTuned(Uri)} if the tune request was fulfilled, or
      * {@link RecordingCallback#onError(int)} otherwise.
      *
      * @param inputId The ID of the TV input for the given channel.
      * @param channelUri The URI of a channel.
+     * @throws IllegalStateException If recording is already started.
      */
     public void tune(String inputId, Uri channelUri) {
         tune(inputId, channelUri, null);
@@ -102,6 +103,7 @@
      * @param inputId The ID of the TV input for the given channel.
      * @param channelUri The URI of a channel.
      * @param params Extra parameters.
+     * @throws IllegalStateException If recording is already started.
      * @hide
      */
     @SystemApi
@@ -152,8 +154,8 @@
      * immediately when this method is called. If the current recording session has not yet tuned to
      * any channel, this method throws an exception.
      *
-     * <p>The application may supply the URI for a TV program as a hint for filling in program
-     * specific data fields in the {@link android.media.tv.TvContract.RecordedPrograms} table.
+     * <p>The application may supply the URI for a TV program for filling in program specific data
+     * fields in the {@link android.media.tv.TvContract.RecordedPrograms} table.
      * A non-null {@code programHint} implies the started recording should be of that specific
      * program, whereas null {@code programHint} does not impose such a requirement and the
      * recording can span across multiple TV programs. In either case, the application must call
@@ -162,15 +164,16 @@
      * <p>The recording session will respond by calling {@link RecordingCallback#onError(int)} if
      * the start request cannot be fulfilled.
      *
-     * @param programHint The URI for the TV program to record as a hint, built by
+     * @param programUri The URI for the TV program to record, built by
      *            {@link TvContract#buildProgramUri(long)}. Can be {@code null}.
+     * @throws IllegalStateException If {@link #tune} request hasn't been handled yet.
      */
-    public void startRecording(@Nullable Uri programHint) {
+    public void startRecording(@Nullable Uri programUri) {
         if (!mIsTuned) {
             throw new IllegalStateException("startRecording failed - not yet tuned");
         }
         if (mSession != null) {
-            mSession.startRecording(programHint);
+            mSession.startRecording(programUri);
             mIsRecordingStarted = true;
         }
     }
@@ -245,8 +248,10 @@
         /**
          * This is called when the recording session has been tuned to the given channel and is
          * ready to start recording.
+         *
+         * @param channelUri The URI of a channel.
          */
-        public void onTuned() {
+        public void onTuned(Uri channelUri) {
         }
 
         /**
@@ -327,7 +332,7 @@
         }
 
         @Override
-        void onTuned(TvInputManager.Session session) {
+        void onTuned(TvInputManager.Session session, Uri channelUri) {
             if (DEBUG) {
                 Log.d(TAG, "onTuned()");
             }
@@ -336,7 +341,7 @@
                 return;
             }
             mIsTuned = true;
-            mCallback.onTuned();
+            mCallback.onTuned(channelUri);
         }
 
         @Override
diff --git a/media/java/android/media/tv/TvTrackInfo.java b/media/java/android/media/tv/TvTrackInfo.java
index 6a44b1e..e623353 100644
--- a/media/java/android/media/tv/TvTrackInfo.java
+++ b/media/java/android/media/tv/TvTrackInfo.java
@@ -121,6 +121,8 @@
 
     /**
      * Returns the audio channel count. Valid only for {@link #TYPE_AUDIO} tracks.
+     *
+     * @throws IllegalStateException if not called on an audio track
      */
     public final int getAudioChannelCount() {
         if (mType != TYPE_AUDIO) {
@@ -131,6 +133,8 @@
 
     /**
      * Returns the audio sample rate, in the unit of Hz. Valid only for {@link #TYPE_AUDIO} tracks.
+     *
+     * @throws IllegalStateException if not called on an audio track
      */
     public final int getAudioSampleRate() {
         if (mType != TYPE_AUDIO) {
@@ -142,6 +146,8 @@
     /**
      * Returns the width of the video, in the unit of pixels. Valid only for {@link #TYPE_VIDEO}
      * tracks.
+     *
+     * @throws IllegalStateException if not called on a video track
      */
     public final int getVideoWidth() {
         if (mType != TYPE_VIDEO) {
@@ -153,6 +159,8 @@
     /**
      * Returns the height of the video, in the unit of pixels. Valid only for {@link #TYPE_VIDEO}
      * tracks.
+     *
+     * @throws IllegalStateException if not called on a video track
      */
     public final int getVideoHeight() {
         if (mType != TYPE_VIDEO) {
@@ -164,6 +172,8 @@
     /**
      * Returns the frame rate of the video, in the unit of fps (frames per second). Valid only for
      * {@link #TYPE_VIDEO} tracks.
+     *
+     * @throws IllegalStateException if not called on a video track
      */
     public final float getVideoFrameRate() {
         if (mType != TYPE_VIDEO) {
@@ -175,6 +185,8 @@
     /**
      * Returns the pixel aspect ratio (the ratio of a pixel's width to its height) of the video.
      * Valid only for {@link #TYPE_VIDEO} tracks.
+     *
+     * @throws IllegalStateException if not called on a video track
      */
     public final float getVideoPixelAspectRatio() {
         if (mType != TYPE_VIDEO) {
@@ -189,6 +201,8 @@
      *
      * <p>The complete list of values are defined in ETSI TS 101 154 V1.7.1 Annex B, ATSC A/53 Part
      * 4 and SMPTE 2016-1-2007.
+     *
+     * @throws IllegalStateException if not called on a video track
      */
     public final byte getVideoActiveFormatDescription() {
         if (mType != TYPE_VIDEO) {
@@ -268,6 +282,8 @@
          * @param type The type of the track.
          * @param id The ID of the track that uniquely identifies the current track among all the
          *            other tracks in the same TV program.
+         * @throws IllegalArgumentException if the type is not any of {@link #TYPE_AUDIO},
+         *                                  {@link #TYPE_VIDEO} and {@link #TYPE_SUBTITLE}
          */
         public Builder(int type, @NonNull String id) {
             if (type != TYPE_AUDIO
@@ -304,6 +320,7 @@
          * Sets the audio channel count. Valid only for {@link #TYPE_AUDIO} tracks.
          *
          * @param audioChannelCount The audio channel count.
+         * @throws IllegalStateException if not called on an audio track
          */
         public final Builder setAudioChannelCount(int audioChannelCount) {
             if (mType != TYPE_AUDIO) {
@@ -318,6 +335,7 @@
          * tracks.
          *
          * @param audioSampleRate The audio sample rate.
+         * @throws IllegalStateException if not called on an audio track
          */
         public final Builder setAudioSampleRate(int audioSampleRate) {
             if (mType != TYPE_AUDIO) {
@@ -332,6 +350,7 @@
          * tracks.
          *
          * @param videoWidth The width of the video.
+         * @throws IllegalStateException if not called on a video track
          */
         public final Builder setVideoWidth(int videoWidth) {
             if (mType != TYPE_VIDEO) {
@@ -346,6 +365,7 @@
          * tracks.
          *
          * @param videoHeight The height of the video.
+         * @throws IllegalStateException if not called on a video track
          */
         public final Builder setVideoHeight(int videoHeight) {
             if (mType != TYPE_VIDEO) {
@@ -360,6 +380,7 @@
          * {@link #TYPE_VIDEO} tracks.
          *
          * @param videoFrameRate The frame rate of the video.
+         * @throws IllegalStateException if not called on a video track
          */
         public final Builder setVideoFrameRate(float videoFrameRate) {
             if (mType != TYPE_VIDEO) {
@@ -379,6 +400,7 @@
          * pixel aspect ratio for most video formats.
          *
          * @param videoPixelAspectRatio The pixel aspect ratio of the video.
+         * @throws IllegalStateException if not called on a video track
          */
         public final Builder setVideoPixelAspectRatio(float videoPixelAspectRatio) {
             if (mType != TYPE_VIDEO) {
@@ -398,6 +420,7 @@
          * 4 and SMPTE 2016-1-2007.
          *
          * @param videoActiveFormatDescription The AFD code of the video.
+         * @throws IllegalStateException if not called on a video track
          */
         public final Builder setVideoActiveFormatDescription(byte videoActiveFormatDescription) {
             if (mType != TYPE_VIDEO) {
diff --git a/media/java/android/media/tv/TvView.java b/media/java/android/media/tv/TvView.java
index 5c4b528..9623076 100644
--- a/media/java/android/media/tv/TvView.java
+++ b/media/java/android/media/tv/TvView.java
@@ -18,6 +18,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.RequiresPermission;
 import android.annotation.SystemApi;
 import android.content.Context;
 import android.graphics.Canvas;
@@ -56,7 +57,7 @@
  * TV inputs available on the system can be obtained by calling
  * {@link TvInputManager#getTvInputList() TvInputManager.getTvInputList()}.)
  *
- * <p>Once the application supplies the URI for a specific TV channel to {@link #tune(String, Uri)}
+ * <p>Once the application supplies the URI for a specific TV channel to {@link #tune}
  * method, it takes care of underlying service binding (and unbinding if the current TvView is
  * already bound to a service) and automatically allocates/deallocates resources needed. In addition
  * to a few essential methods to control how the contents are presented, it also provides a way to
@@ -206,13 +207,18 @@
     }
 
     /**
-     * Sets the Z order of a window owning the surface of this TvView above the normal TvView
-     * but below an application.
+     * Controls whether the TvView's surface is placed on top of another regular surface view in the
+     * window (but still behind the window itself).
+     * This is typically used to place overlays on top of an underlying TvView.
      *
-     * @see SurfaceView#setZOrderMediaOverlay
-     * @hide
+     * <p>Note that this must be set before the TvView's containing window is attached to the
+     * window manager.
+     *
+     * <p>Calling this overrides any previous call to {@link #setZOrderOnTop}.
+     *
+     * @param isMediaOverlay {@code true} to be on top of another regular surface, {@code false}
+     *            otherwise.
      */
-    @SystemApi
     public void setZOrderMediaOverlay(boolean isMediaOverlay) {
         if (isMediaOverlay) {
             mWindowZOrder = ZORDER_MEDIA_OVERLAY;
@@ -230,12 +236,18 @@
     }
 
     /**
-     * Sets the Z order of a window owning the surface of this TvView on top of an application.
+     * Controls whether the TvView's surface is placed on top of its window. Normally it is placed
+     * behind the window, to allow it to (for the most part) appear to composite with the views in
+     * the hierarchy.  By setting this, you cause it to be placed above the window. This means that
+     * none of the contents of the window this TvView is in will be visible on top of its surface.
      *
-     * @see SurfaceView#setZOrderOnTop
-     * @hide
+     * <p>Note that this must be set before the TvView's containing window is attached to the window
+     * manager.
+     *
+     * <p>Calling this overrides any previous call to {@link #setZOrderMediaOverlay}.
+     *
+     * @param onTop {@code true} to be on top of its window, {@code false} otherwise.
      */
-    @SystemApi
     public void setZOrderOnTop(boolean onTop) {
         if (onTop) {
             mWindowZOrder = ZORDER_ON_TOP;
@@ -280,14 +292,15 @@
     }
 
     /**
-     * Tunes to a given channel.
+     * Tunes to a given channel. This can be used to provide domain-specific features that are only
+     * known between certain TvView applications and their TV inputs.
      *
      * @param inputId The ID of TV input for the given channel.
      * @param channelUri The URI of a channel.
-     * @param params Extra parameters.
-     * @hide
+     * @param params Domain-specific data for this tune request. Keys <em>must</em> be a scoped
+     *            name, i.e. prefixed with a package name you own, so that different developers will
+     *            not create conflicting keys.
      */
-    @SystemApi
     public void tune(String inputId, Uri channelUri, Bundle params) {
         if (DEBUG) Log.d(TAG, "tune(" + channelUri + ")");
         if (TextUtils.isEmpty(inputId)) {
@@ -360,11 +373,8 @@
      *
      * @param unblockedRating A TvContentRating to unblock.
      * @see TvInputService.Session#notifyContentBlocked(TvContentRating)
-     * @hide
-     * @deprecated Use {@link #unblockContent} instead.
+     * @removed
      */
-    @Deprecated
-    @SystemApi
     public void requestUnblockContent(TvContentRating unblockedRating) {
         unblockContent(unblockedRating);
     }
@@ -379,6 +389,7 @@
      * @hide
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.MODIFY_PARENTAL_CONTROLS)
     public void unblockContent(TvContentRating unblockedRating) {
         if (mSession != null) {
             mSession.unblockContent(unblockedRating);
@@ -539,7 +550,7 @@
     }
 
     /**
-     * Calls {@link TvInputService.Session#appPrivateCommand(String, Bundle)} for the current
+     * Calls {@link TvInputService.Session#onAppPrivateCommand(String, Bundle)} for the current
      * session.
      *
      * @param action The name of the private command to send. This <em>must</em> be a scoped name,
@@ -893,7 +904,7 @@
 
         /**
          * This is invoked when the channel of this TvView is changed by the underlying TV input
-         * without any {@link TvView#tune(String, Uri)} request.
+         * without any {@link TvView#tune} request.
          *
          * @param inputId The ID of the TV input bound to this view.
          * @param channelUri The URI of a channel.
diff --git a/media/java/android/mtp/MtpDatabase.java b/media/java/android/mtp/MtpDatabase.java
index 29bcc19..760a2d1 100755
--- a/media/java/android/mtp/MtpDatabase.java
+++ b/media/java/android/mtp/MtpDatabase.java
@@ -713,8 +713,7 @@
         };
     }
 
-
-    private MtpPropertyList getObjectPropertyList(long handle, int format, long property,
+    private MtpPropertyList getObjectPropertyList(int handle, int format, int property,
                         int groupCode, int depth) {
         // FIXME - implement group support
         if (groupCode != 0) {
@@ -722,29 +721,29 @@
         }
 
         MtpPropertyGroup propertyGroup;
-        if (property == 0xFFFFFFFFL) {
-            if (format == 0 && handle > 0) {
+        if (property == 0xffffffff) {
+            if (format == 0 && handle != 0 && handle != 0xffffffff) {
                 // return properties based on the object's format
-                format = getObjectFormat((int)handle);
+                format = getObjectFormat(handle);
             }
-             propertyGroup = mPropertyGroupsByFormat.get(format);
-             if (propertyGroup == null) {
+            propertyGroup = mPropertyGroupsByFormat.get(format);
+            if (propertyGroup == null) {
                 int[] propertyList = getSupportedObjectProperties(format);
                 propertyGroup = new MtpPropertyGroup(this, mMediaProvider,
                         mVolumeName, propertyList);
-                mPropertyGroupsByFormat.put(new Integer(format), propertyGroup);
+                mPropertyGroupsByFormat.put(format, propertyGroup);
             }
         } else {
-              propertyGroup = mPropertyGroupsByProperty.get(property);
-             if (propertyGroup == null) {
-                int[] propertyList = new int[] { (int)property };
-                propertyGroup = new MtpPropertyGroup(this, mMediaProvider,
-                        mVolumeName, propertyList);
-                mPropertyGroupsByProperty.put(new Integer((int)property), propertyGroup);
+            propertyGroup = mPropertyGroupsByProperty.get(property);
+            if (propertyGroup == null) {
+                final int[] propertyList = new int[] { property };
+                propertyGroup = new MtpPropertyGroup(
+                        this, mMediaProvider, mVolumeName, propertyList);
+                mPropertyGroupsByProperty.put(property, propertyGroup);
             }
         }
 
-        return propertyGroup.getPropertyList((int)handle, format, depth);
+        return propertyGroup.getPropertyList(handle, format, depth);
     }
 
     private int renameFile(int handle, String newName) {
@@ -970,7 +969,7 @@
         Cursor c = null;
         try {
             c = mMediaProvider.query(mObjectsUri, FORMAT_PROJECTION,
-                            ID_WHERE, new String[] {  Integer.toString(handle) }, null, null);
+                            ID_WHERE, new String[] { Integer.toString(handle) }, null, null);
             if (c != null && c.moveToNext()) {
                 return c.getInt(1);
             } else {
diff --git a/media/java/android/service/media/MediaBrowserService.java b/media/java/android/service/media/MediaBrowserService.java
index 480acd9..f593685 100644
--- a/media/java/android/service/media/MediaBrowserService.java
+++ b/media/java/android/service/media/MediaBrowserService.java
@@ -45,6 +45,7 @@
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
 
@@ -120,8 +121,8 @@
      * they are done. If more than one of those methods is called, an exception will
      * be thrown.
      *
-     * @see MediaBrowserService#onLoadChildren
-     * @see MediaBrowserService#onLoadItem
+     * @see #onLoadChildren
+     * @see #onLoadItem
      */
     public class Result<T> {
         private Object mDebug;
@@ -367,11 +368,16 @@
      * {@link Result#detach result.detach} may be called before returning from
      * this function, and then {@link Result#sendResult result.sendResult}
      * called when the loading is complete.
+     * </p><p>
+     * In case the media item does not have any children, call {@link Result#sendResult}
+     * with an empty list. When the given {@code parentId} is invalid, implementations must
+     * call {@link Result#sendResult result.sendResult} with {@code null}, which will invoke
+     * {@link MediaBrowser.SubscriptionCallback#onError}.
+     * </p>
      *
      * @param parentId The id of the parent media item whose children are to be
      *            queried.
-     * @param result The Result to send the list of children to, or null if the
-     *            id is invalid.
+     * @param result The Result to send the list of children to.
      */
     public abstract void onLoadChildren(@NonNull String parentId,
             @NonNull Result<List<MediaBrowser.MediaItem>> result);
@@ -385,11 +391,16 @@
      * {@link Result#detach result.detach} may be called before returning from
      * this function, and then {@link Result#sendResult result.sendResult}
      * called when the loading is complete.
+     * </p><p>
+     * In case the media item does not have any children, call {@link Result#sendResult}
+     * with an empty list. When the given {@code parentId} is invalid, implementations must
+     * call {@link Result#sendResult result.sendResult} with {@code null}, which will invoke
+     * {@link MediaBrowser.SubscriptionCallback#onError}.
+     * </p>
      *
      * @param parentId The id of the parent media item whose children are to be
      *            queried.
-     * @param result The Result to send the list of children to, or null if the
-     *            id is invalid.
+     * @param result The Result to send the list of children to.
      * @param options A bundle of service-specific arguments sent from the media
      *            browse. The information returned through the result should be
      *            affected by the contents of this bundle.
@@ -411,13 +422,18 @@
      * result.detach} may be called before returning from this function, and
      * then {@link Result#sendResult result.sendResult} called when the item has
      * been loaded.
-     * <p>
-     * The default implementation sends a null result.
+     * </p><p>
+     * When the given {@code itemId} is invalid, implementations must call
+     * {@link Result#sendResult result.sendResult} with {@code null}, which will
+     * invoke {@link MediaBrowser.ItemCallback#onError}.
+     * </p><p>
+     * The default implementation calls {@link Result#sendResult result.sendResult}
+     * with {@code null}.
+     * </p>
      *
      * @param itemId The id for the specific
      *            {@link android.media.browse.MediaBrowser.MediaItem}.
-     * @param result The Result to send the item to, or null if the id is
-     *            invalid.
+     * @param result The Result to send the item to.
      */
     public void onLoadItem(String itemId, Result<MediaBrowser.MediaItem> result) {
         result.sendResult(null);
@@ -630,6 +646,9 @@
 
     private List<MediaBrowser.MediaItem> applyOptions(List<MediaBrowser.MediaItem> list,
             final Bundle options) {
+        if (list == null) {
+            return null;
+        }
         int page = options.getInt(MediaBrowser.EXTRA_PAGE, -1);
         int pageSize = options.getInt(MediaBrowser.EXTRA_PAGE_SIZE, -1);
         if (page == -1 && pageSize == -1) {
@@ -638,7 +657,7 @@
         int fromIndex = pageSize * (page - 1);
         int toIndex = fromIndex + pageSize;
         if (page < 1 || pageSize < 1 || fromIndex >= list.size()) {
-            return null;
+            return Collections.EMPTY_LIST;
         }
         if (toIndex > list.size()) {
             toIndex = list.size();
diff --git a/media/jni/Android.mk b/media/jni/Android.mk
index fa9c48c..29739ca 100644
--- a/media/jni/Android.mk
+++ b/media/jni/Android.mk
@@ -64,7 +64,6 @@
     frameworks/av/media/mtp \
     frameworks/native/include/media/openmax \
     $(call include-path-for, libhardware)/hardware \
-    system/media/camera/include \
     $(PV_INCLUDES) \
     $(JNI_H_INCLUDE)
 
diff --git a/media/jni/android_media_ExifInterface.cpp b/media/jni/android_media_ExifInterface.cpp
index a1fcb07..418a3f2 100644
--- a/media/jni/android_media_ExifInterface.cpp
+++ b/media/jni/android_media_ExifInterface.cpp
@@ -19,12 +19,15 @@
 
 #include "android_media_Utils.h"
 
+#include "android/graphics/CreateJavaOutputStreamAdaptor.h"
 #include "src/piex_types.h"
 #include "src/piex.h"
 
 #include <jni.h>
 #include <JNIHelp.h>
+#include <androidfw/Asset.h>
 #include <android_runtime/AndroidRuntime.h>
+#include <android/graphics/Utils.h>
 #include <nativehelper/ScopedLocalRef.h>
 
 #include <utils/Log.h>
@@ -35,6 +38,9 @@
 
 using namespace android;
 
+static const char kJpegSignatureChars[] = {(char)0xff, (char)0xd8, (char)0xff};
+static const int kJpegSignatureSize = 3;
+
 #define FIND_CLASS(var, className) \
     var = env->FindClass(className); \
     LOG_FATAL_IF(! var, "Unable to find class " className);
@@ -82,28 +88,58 @@
                   "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;");
 }
 
-static jobject ExifInterface_getRawMetadata(
-        JNIEnv* env, jclass /* clazz */, jobject jfileDescriptor) {
-    int fd = jniGetFDFromFileDescriptor(env, jfileDescriptor);
-    if (fd < 0) {
-        ALOGI("Invalid file descriptor");
+static bool is_asset_stream(const SkStream& stream) {
+    return stream.hasLength() && stream.hasPosition();
+}
+
+static jobject ExifInterface_getThumbnailFromAsset(
+        JNIEnv* env, jclass /* clazz */, jlong jasset, jint jthumbnailOffset,
+        jint jthumbnailLength) {
+    Asset* asset = reinterpret_cast<Asset*>(jasset);
+    std::unique_ptr<AssetStreamAdaptor> stream(new AssetStreamAdaptor(asset));
+
+    std::unique_ptr<jbyte[]> thumbnailData(new jbyte[(int)jthumbnailLength]);
+    if (thumbnailData.get() == NULL) {
+        ALOGI("No memory to get thumbnail");
         return NULL;
     }
 
-    piex::PreviewImageData image_data;
-    std::unique_ptr<FileStream> stream(new FileStream(fd));
+    // Do not know the current offset. So rewind it.
+    stream->rewind();
 
-    if (!GetExifFromRawImage(stream.get(), String8("[file descriptor]"), image_data)) {
+    // Read thumbnail.
+    stream->skip((int)jthumbnailOffset);
+    stream->read((void*)thumbnailData.get(), (int)jthumbnailLength);
+
+    // Copy to the byte array.
+    jbyteArray byteArray = env->NewByteArray(jthumbnailLength);
+    env->SetByteArrayRegion(byteArray, 0, jthumbnailLength, thumbnailData.get());
+    return byteArray;
+}
+
+static jobject getRawAttributes(JNIEnv* env, SkStream* stream, bool returnThumbnail) {
+    std::unique_ptr<SkStream> streamDeleter(stream);
+
+    std::unique_ptr<::piex::StreamInterface> piexStream;
+    if (is_asset_stream(*stream)) {
+        piexStream.reset(new AssetStream(streamDeleter.release()));
+    } else {
+        piexStream.reset(new BufferedStream(streamDeleter.release()));
+    }
+
+    piex::PreviewImageData image_data;
+
+    if (!GetExifFromRawImage(piexStream.get(), String8("[piex stream]"), image_data)) {
         ALOGI("Raw image not detected");
         return NULL;
     }
 
     KeyedVector<String8, String8> map;
 
-    if (image_data.thumbnail_length > 0) {
+    if (image_data.thumbnail.length > 0) {
         map.add(String8("hasThumbnail"), String8("true"));
-        map.add(String8("thumbnailOffset"), String8::format("%d", image_data.thumbnail_offset));
-        map.add(String8("thumbnailLength"), String8::format("%d", image_data.thumbnail_length));
+        map.add(String8("thumbnailOffset"), String8::format("%d", image_data.thumbnail.offset));
+        map.add(String8("thumbnailLength"), String8::format("%d", image_data.thumbnail.length));
     } else {
         map.add(String8("hasThumbnail"), String8("false"));
     }
@@ -253,7 +289,117 @@
         }
     }
 
-    return KeyedVectorToHashMap(env, map);
+    jobject hashMap = KeyedVectorToHashMap(env, map);
+
+    if (returnThumbnail) {
+        std::unique_ptr<jbyte[]> thumbnailData(new jbyte[image_data.thumbnail.length]);
+        if (thumbnailData.get() == NULL) {
+            ALOGE("No memory to parse a thumbnail");
+            return NULL;
+        }
+        jbyteArray jthumbnailByteArray = env->NewByteArray(image_data.thumbnail.length);
+        if (jthumbnailByteArray == NULL) {
+            ALOGE("No memory to parse a thumbnail");
+            return NULL;
+        }
+        piexStream.get()->GetData(image_data.thumbnail.offset, image_data.thumbnail.length,
+                (uint8_t*)thumbnailData.get());
+        env->SetByteArrayRegion(
+                jthumbnailByteArray, 0, image_data.thumbnail.length, thumbnailData.get());
+        jstring jkey = env->NewStringUTF(String8("thumbnailData"));
+        env->CallObjectMethod(hashMap, gFields.hashMap.put, jkey, jthumbnailByteArray);
+        env->DeleteLocalRef(jkey);
+        env->DeleteLocalRef(jthumbnailByteArray);
+    }
+    return hashMap;
+}
+
+static jobject ExifInterface_getRawAttributesFromAsset(
+        JNIEnv* env, jclass /* clazz */, jlong jasset) {
+    std::unique_ptr<char[]> jpegSignature(new char[kJpegSignatureSize]);
+    if (jpegSignature.get() == NULL) {
+        ALOGE("No enough memory to parse");
+        return NULL;
+    }
+
+    Asset* asset = reinterpret_cast<Asset*>(jasset);
+    std::unique_ptr<AssetStreamAdaptor> stream(new AssetStreamAdaptor(asset));
+
+    if (stream.get()->read(jpegSignature.get(), kJpegSignatureSize) != kJpegSignatureSize) {
+        // Rewind the stream.
+        stream.get()->rewind();
+
+        ALOGI("Corrupted image.");
+        return NULL;
+    }
+
+    // Rewind the stream.
+    stream.get()->rewind();
+
+    if (memcmp(jpegSignature.get(), kJpegSignatureChars, kJpegSignatureSize) == 0) {
+        ALOGI("Should be a JPEG stream.");
+        return NULL;
+    }
+
+    // Try to parse from the given stream.
+    jobject result = getRawAttributes(env, stream.get(), false);
+
+    // Rewind the stream for the chance to read JPEG.
+    if (result == NULL) {
+        stream.get()->rewind();
+    }
+    return result;
+}
+
+static jobject ExifInterface_getRawAttributesFromFileDescriptor(
+        JNIEnv* env, jclass /* clazz */, jobject jfileDescriptor) {
+    std::unique_ptr<char[]> jpegSignature(new char[kJpegSignatureSize]);
+    if (jpegSignature.get() == NULL) {
+        ALOGE("No enough memory to parse");
+        return NULL;
+    }
+
+    int fd = jniGetFDFromFileDescriptor(env, jfileDescriptor);
+    if (fd < 0) {
+        ALOGI("Invalid file descriptor");
+        return NULL;
+    }
+
+    // Restore the file descriptor's offset on exiting this function.
+    AutoFDSeek autoRestore(fd);
+
+    int dupFd = dup(fd);
+
+    FILE* file = fdopen(dupFd, "r");
+    if (file == NULL) {
+        ALOGI("Failed to open the file descriptor");
+        return NULL;
+    }
+
+    if (fgets(jpegSignature.get(), kJpegSignatureSize, file) == NULL) {
+        ALOGI("Corrupted image.");
+        return NULL;
+    }
+
+    if (memcmp(jpegSignature.get(), kJpegSignatureChars, kJpegSignatureSize) == 0) {
+        ALOGI("Should be a JPEG stream.");
+        return NULL;
+    }
+
+    // Rewind the file descriptor.
+    fseek(file, 0L, SEEK_SET);
+
+    std::unique_ptr<SkFILEStream> fileStream(new SkFILEStream(file,
+                SkFILEStream::kCallerPasses_Ownership));
+    return getRawAttributes(env, fileStream.get(), false);
+}
+
+static jobject ExifInterface_getRawAttributesFromInputStream(
+        JNIEnv* env, jclass /* clazz */, jobject jinputStream) {
+    jbyteArray byteArray = env->NewByteArray(8*1024);
+    ScopedLocalRef<jbyteArray> scoper(env, byteArray);
+    std::unique_ptr<SkStream> stream(CreateJavaInputStreamAdaptor(env, jinputStream, scoper.get()));
+    return getRawAttributes(env, stream.get(), true);
 }
 
 } // extern "C"
@@ -261,9 +407,14 @@
 // ----------------------------------------------------------------------------
 
 static JNINativeMethod gMethods[] = {
-    { "initRawNative", "()V", (void *)ExifInterface_initRaw },
-    { "getRawAttributesNative", "(Ljava/io/FileDescriptor;)Ljava/util/HashMap;",
-      (void*)ExifInterface_getRawMetadata },
+    { "nativeInitRaw", "()V", (void *)ExifInterface_initRaw },
+    { "nativeGetThumbnailFromAsset", "(JII)[B", (void *)ExifInterface_getThumbnailFromAsset },
+    { "nativeGetRawAttributesFromAsset", "(J)Ljava/util/HashMap;",
+      (void*)ExifInterface_getRawAttributesFromAsset },
+    { "nativeGetRawAttributesFromFileDescriptor", "(Ljava/io/FileDescriptor;)Ljava/util/HashMap;",
+      (void*)ExifInterface_getRawAttributesFromFileDescriptor },
+    { "nativeGetRawAttributesFromInputStream", "(Ljava/io/InputStream;)Ljava/util/HashMap;",
+      (void*)ExifInterface_getRawAttributesFromInputStream },
 };
 
 int register_android_media_ExifInterface(JNIEnv *env) {
diff --git a/media/jni/android_media_ImageReader.cpp b/media/jni/android_media_ImageReader.cpp
index 9e90a19..c3993ae 100644
--- a/media/jni/android_media_ImageReader.cpp
+++ b/media/jni/android_media_ImageReader.cpp
@@ -16,6 +16,7 @@
 
 //#define LOG_NDEBUG 0
 #define LOG_TAG "ImageReader_JNI"
+#include "android_media_Utils.h"
 #include <utils/Log.h>
 #include <utils/misc.h>
 #include <utils/List.h>
@@ -23,7 +24,6 @@
 
 #include <cstdio>
 
-#include <gui/CpuConsumer.h>
 #include <gui/BufferItemConsumer.h>
 #include <gui/Surface.h>
 #include <camera3.h>
@@ -37,8 +37,6 @@
 #include <stdint.h>
 #include <inttypes.h>
 
-#define ALIGN(x, mask) ( ((x) + (mask) - 1) & ~((mask) - 1) )
-
 #define ANDROID_MEDIA_IMAGEREADER_CTX_JNI_ID       "mNativeContext"
 #define ANDROID_MEDIA_SURFACEIMAGE_BUFFER_JNI_ID   "mNativeBuffer"
 #define ANDROID_MEDIA_SURFACEIMAGE_TS_JNI_ID       "mTimestamp"
@@ -47,9 +45,6 @@
 
 using namespace android;
 
-enum {
-    IMAGE_READER_MAX_NUM_PLANES = 3,
-};
 
 enum {
     ACQUIRE_SUCCESS = 0,
@@ -65,6 +60,7 @@
 static struct {
     jfieldID mNativeBuffer;
     jfieldID mTimestamp;
+    jfieldID mPlanes;
 } gSurfaceImageClassInfo;
 
 static struct {
@@ -89,21 +85,12 @@
 
     virtual void onFrameAvailable(const BufferItem& item);
 
-    CpuConsumer::LockedBuffer* getLockedBuffer();
-    void returnLockedBuffer(CpuConsumer::LockedBuffer* buffer);
+    BufferItem* getBufferItem();
+    void returnBufferItem(BufferItem* buffer);
 
-    BufferItem* getOpaqueBuffer();
-    void returnOpaqueBuffer(BufferItem* buffer);
 
-    void setCpuConsumer(const sp<CpuConsumer>& consumer) { mConsumer = consumer; }
-    CpuConsumer* getCpuConsumer() { return mConsumer.get(); }
-
-    void setOpaqueConsumer(const sp<BufferItemConsumer>& consumer) { mOpaqueConsumer = consumer; }
-    BufferItemConsumer* getOpaqueConsumer() { return mOpaqueConsumer.get(); }
-    // This is the only opaque format exposed in the ImageFormat public API.
-    // Note that we do support CPU access for HAL_PIXEL_FORMAT_RAW_OPAQUE
-    // (ImageFormat#RAW_PRIVATE) so it doesn't count as opaque here.
-    bool isOpaque() { return mFormat == HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED; }
+    void setBufferConsumer(const sp<BufferItemConsumer>& consumer) { mConsumer = consumer; }
+    BufferItemConsumer* getBufferConsumer() { return mConsumer.get(); }
 
     void setProducer(const sp<IGraphicBufferProducer>& producer) { mProducer = producer; }
     IGraphicBufferProducer* getProducer() { return mProducer.get(); }
@@ -124,10 +111,8 @@
     static JNIEnv* getJNIEnv(bool* needsDetach);
     static void detachJNI();
 
-    List<CpuConsumer::LockedBuffer*> mBuffers;
-    List<BufferItem*> mOpaqueBuffers;
-    sp<CpuConsumer> mConsumer;
-    sp<BufferItemConsumer> mOpaqueConsumer;
+    List<BufferItem*> mBuffers;
+    sp<BufferItemConsumer> mConsumer;
     sp<IGraphicBufferProducer> mProducer;
     jobject mWeakThiz;
     jclass mClazz;
@@ -140,12 +125,14 @@
 JNIImageReaderContext::JNIImageReaderContext(JNIEnv* env,
         jobject weakThiz, jclass clazz, int maxImages) :
     mWeakThiz(env->NewGlobalRef(weakThiz)),
-    mClazz((jclass)env->NewGlobalRef(clazz)) {
+    mClazz((jclass)env->NewGlobalRef(clazz)),
+    mFormat(0),
+    mDataSpace(HAL_DATASPACE_UNKNOWN),
+    mWidth(-1),
+    mHeight(-1) {
     for (int i = 0; i < maxImages; i++) {
-        CpuConsumer::LockedBuffer *buffer = new CpuConsumer::LockedBuffer;
-        BufferItem* opaqueBuffer = new BufferItem;
+        BufferItem* buffer = new BufferItem;
         mBuffers.push_back(buffer);
-        mOpaqueBuffers.push_back(opaqueBuffer);
     }
 }
 
@@ -174,36 +161,21 @@
     }
 }
 
-CpuConsumer::LockedBuffer* JNIImageReaderContext::getLockedBuffer() {
+BufferItem* JNIImageReaderContext::getBufferItem() {
     if (mBuffers.empty()) {
         return NULL;
     }
-    // Return a LockedBuffer pointer and remove it from the list
-    List<CpuConsumer::LockedBuffer*>::iterator it = mBuffers.begin();
-    CpuConsumer::LockedBuffer* buffer = *it;
+    // Return a BufferItem pointer and remove it from the list
+    List<BufferItem*>::iterator it = mBuffers.begin();
+    BufferItem* buffer = *it;
     mBuffers.erase(it);
     return buffer;
 }
 
-void JNIImageReaderContext::returnLockedBuffer(CpuConsumer::LockedBuffer* buffer) {
+void JNIImageReaderContext::returnBufferItem(BufferItem* buffer) {
     mBuffers.push_back(buffer);
 }
 
-BufferItem* JNIImageReaderContext::getOpaqueBuffer() {
-    if (mOpaqueBuffers.empty()) {
-        return NULL;
-    }
-    // Return an opaque buffer pointer and remove it from the list
-    List<BufferItem*>::iterator it = mOpaqueBuffers.begin();
-    BufferItem* buffer = *it;
-    mOpaqueBuffers.erase(it);
-    return buffer;
-}
-
-void JNIImageReaderContext::returnOpaqueBuffer(BufferItem* buffer) {
-    mOpaqueBuffers.push_back(buffer);
-}
-
 JNIImageReaderContext::~JNIImageReaderContext() {
     bool needsDetach = false;
     JNIEnv* env = getJNIEnv(&needsDetach);
@@ -217,25 +189,15 @@
         detachJNI();
     }
 
-    // Delete LockedBuffers
-    for (List<CpuConsumer::LockedBuffer *>::iterator it = mBuffers.begin();
+    // Delete buffer items.
+    for (List<BufferItem *>::iterator it = mBuffers.begin();
             it != mBuffers.end(); it++) {
         delete *it;
     }
 
-    // Delete opaque buffers
-    for (List<BufferItem *>::iterator it = mOpaqueBuffers.begin();
-            it != mOpaqueBuffers.end(); it++) {
-        delete *it;
-    }
-
-    mBuffers.clear();
     if (mConsumer != 0) {
         mConsumer.clear();
     }
-    if (mOpaqueConsumer != 0) {
-        mOpaqueConsumer.clear();
-    }
 }
 
 void JNIImageReaderContext::onFrameAvailable(const BufferItem& /*item*/)
@@ -257,11 +219,6 @@
 
 extern "C" {
 
-static bool isFormatOpaque(int format) {
-    // Only treat IMPLEMENTATION_DEFINED as an opaque format for now.
-    return format == HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED;
-}
-
 static JNIImageReaderContext* ImageReader_getContext(JNIEnv* env, jobject thiz)
 {
     JNIImageReaderContext *ctx;
@@ -270,24 +227,6 @@
     return ctx;
 }
 
-static CpuConsumer* ImageReader_getCpuConsumer(JNIEnv* env, jobject thiz)
-{
-    ALOGV("%s:", __FUNCTION__);
-    JNIImageReaderContext* const ctx = ImageReader_getContext(env, thiz);
-    if (ctx == NULL) {
-        jniThrowRuntimeException(env, "ImageReaderContext is not initialized");
-        return NULL;
-    }
-
-    if (ctx->isOpaque()) {
-        jniThrowException(env, "java/lang/IllegalStateException",
-                "Opaque ImageReader doesn't support this method");
-        return NULL;
-    }
-
-    return ctx->getCpuConsumer();
-}
-
 static IGraphicBufferProducer* ImageReader_getProducer(JNIEnv* env, jobject thiz)
 {
     ALOGV("%s:", __FUNCTION__);
@@ -315,411 +254,7 @@
             reinterpret_cast<jlong>(ctx.get()));
 }
 
-static CpuConsumer::LockedBuffer* Image_getLockedBuffer(JNIEnv* env, jobject image)
-{
-    return reinterpret_cast<CpuConsumer::LockedBuffer*>(
-            env->GetLongField(image, gSurfaceImageClassInfo.mNativeBuffer));
-}
-
-static void Image_setBuffer(JNIEnv* env, jobject thiz,
-        const CpuConsumer::LockedBuffer* buffer)
-{
-    env->SetLongField(thiz, gSurfaceImageClassInfo.mNativeBuffer, reinterpret_cast<jlong>(buffer));
-}
-
-static void Image_setOpaqueBuffer(JNIEnv* env, jobject thiz,
-        const BufferItem* buffer)
-{
-    env->SetLongField(thiz, gSurfaceImageClassInfo.mNativeBuffer, reinterpret_cast<jlong>(buffer));
-}
-
-static uint32_t Image_getJpegSize(CpuConsumer::LockedBuffer* buffer, bool usingRGBAOverride)
-{
-    ALOG_ASSERT(buffer != NULL, "Input buffer is NULL!!!");
-    uint32_t size = 0;
-    uint32_t width = buffer->width;
-    uint8_t* jpegBuffer = buffer->data;
-
-    if (usingRGBAOverride) {
-        width = (buffer->width + buffer->stride * (buffer->height - 1)) * 4;
-    }
-
-    // First check for JPEG transport header at the end of the buffer
-    uint8_t* header = jpegBuffer + (width - sizeof(struct camera3_jpeg_blob));
-    struct camera3_jpeg_blob *blob = (struct camera3_jpeg_blob*)(header);
-    if (blob->jpeg_blob_id == CAMERA3_JPEG_BLOB_ID) {
-        size = blob->jpeg_size;
-        ALOGV("%s: Jpeg size = %d", __FUNCTION__, size);
-    }
-
-    // failed to find size, default to whole buffer
-    if (size == 0) {
-        /*
-         * This is a problem because not including the JPEG header
-         * means that in certain rare situations a regular JPEG blob
-         * will be misidentified as having a header, in which case
-         * we will get a garbage size value.
-         */
-        ALOGW("%s: No JPEG header detected, defaulting to size=width=%d",
-                __FUNCTION__, width);
-        size = width;
-    }
-
-    return size;
-}
-
-static bool usingRGBAToJpegOverride(int32_t bufferFormat, int32_t readerCtxFormat) {
-    return readerCtxFormat == HAL_PIXEL_FORMAT_BLOB && bufferFormat == HAL_PIXEL_FORMAT_RGBA_8888;
-}
-
-static int32_t applyFormatOverrides(int32_t bufferFormat, int32_t readerCtxFormat)
-{
-    // Using HAL_PIXEL_FORMAT_RGBA_8888 gralloc buffers containing JPEGs to get around SW
-    // write limitations for some platforms (b/17379185).
-    if (usingRGBAToJpegOverride(bufferFormat, readerCtxFormat)) {
-        return HAL_PIXEL_FORMAT_BLOB;
-    }
-    return bufferFormat;
-}
-
-static void Image_getLockedBufferInfo(JNIEnv* env, CpuConsumer::LockedBuffer* buffer, int idx,
-                                uint8_t **base, uint32_t *size, int32_t readerFormat)
-{
-    ALOG_ASSERT(buffer != NULL, "Input buffer is NULL!!!");
-    ALOG_ASSERT(base != NULL, "base is NULL!!!");
-    ALOG_ASSERT(size != NULL, "size is NULL!!!");
-    ALOG_ASSERT((idx < IMAGE_READER_MAX_NUM_PLANES) && (idx >= 0));
-
-    ALOGV("%s: buffer: %p", __FUNCTION__, buffer);
-
-    uint32_t dataSize, ySize, cSize, cStride;
-    uint8_t *cb, *cr;
-    uint8_t *pData = NULL;
-    int bytesPerPixel = 0;
-
-    dataSize = ySize = cSize = cStride = 0;
-    int32_t fmt = buffer->flexFormat;
-
-    bool usingRGBAOverride = usingRGBAToJpegOverride(fmt, readerFormat);
-    fmt = applyFormatOverrides(fmt, readerFormat);
-    switch (fmt) {
-        case HAL_PIXEL_FORMAT_YCbCr_420_888:
-            pData =
-                (idx == 0) ?
-                    buffer->data :
-                (idx == 1) ?
-                    buffer->dataCb :
-                buffer->dataCr;
-            // only map until last pixel
-            if (idx == 0) {
-                dataSize = buffer->stride * (buffer->height - 1) + buffer->width;
-            } else {
-                dataSize = buffer->chromaStride * (buffer->height / 2 - 1) +
-                        buffer->chromaStep * (buffer->width / 2 - 1) + 1;
-            }
-            break;
-        // NV21
-        case HAL_PIXEL_FORMAT_YCrCb_420_SP:
-            cr = buffer->data + (buffer->stride * buffer->height);
-            cb = cr + 1;
-            // only map until last pixel
-            ySize = buffer->width * (buffer->height - 1) + buffer->width;
-            cSize = buffer->width * (buffer->height / 2 - 1) + buffer->width - 1;
-
-            pData =
-                (idx == 0) ?
-                    buffer->data :
-                (idx == 1) ?
-                    cb:
-                cr;
-
-            dataSize = (idx == 0) ? ySize : cSize;
-            break;
-        case HAL_PIXEL_FORMAT_YV12:
-            // Y and C stride need to be 16 pixel aligned.
-            LOG_ALWAYS_FATAL_IF(buffer->stride % 16,
-                                "Stride is not 16 pixel aligned %d", buffer->stride);
-
-            ySize = buffer->stride * buffer->height;
-            cStride = ALIGN(buffer->stride / 2, 16);
-            cr = buffer->data + ySize;
-            cSize = cStride * buffer->height / 2;
-            cb = cr + cSize;
-
-            pData =
-                (idx == 0) ?
-                    buffer->data :
-                (idx == 1) ?
-                    cb :
-                cr;
-            dataSize = (idx == 0) ? ySize : cSize;
-            break;
-        case HAL_PIXEL_FORMAT_Y8:
-            // Single plane, 8bpp.
-            ALOG_ASSERT(idx == 0, "Wrong index: %d", idx);
-
-            pData = buffer->data;
-            dataSize = buffer->stride * buffer->height;
-            break;
-        case HAL_PIXEL_FORMAT_Y16:
-            bytesPerPixel = 2;
-            // Single plane, 16bpp, strides are specified in pixels, not in bytes
-            ALOG_ASSERT(idx == 0, "Wrong index: %d", idx);
-
-            pData = buffer->data;
-            dataSize = buffer->stride * buffer->height * bytesPerPixel;
-            break;
-        case HAL_PIXEL_FORMAT_BLOB:
-            // Used for JPEG data, height must be 1, width == size, single plane.
-            ALOG_ASSERT(idx == 0, "Wrong index: %d", idx);
-            ALOG_ASSERT(buffer->height == 1,
-                    "JPEG should has height value one but got %d", buffer->height);
-
-            pData = buffer->data;
-            dataSize = Image_getJpegSize(buffer, usingRGBAOverride);
-            break;
-        case HAL_PIXEL_FORMAT_RAW16:
-            // Single plane 16bpp bayer data.
-            bytesPerPixel = 2;
-            ALOG_ASSERT(idx == 0, "Wrong index: %d", idx);
-            pData = buffer->data;
-            dataSize = buffer->stride * buffer->height * bytesPerPixel;
-            break;
-        case HAL_PIXEL_FORMAT_RAW_OPAQUE:
-            // Used for RAW_OPAQUE data, height must be 1, width == size, single plane.
-            ALOG_ASSERT(idx == 0, "Wrong index: %d", idx);
-            ALOG_ASSERT(buffer->height == 1,
-                    "RAW_PRIVATE should has height value one but got %d", buffer->height);
-            pData = buffer->data;
-            dataSize = buffer->width;
-            break;
-        case HAL_PIXEL_FORMAT_RAW10:
-            // Single plane 10bpp bayer data.
-            ALOG_ASSERT(idx == 0, "Wrong index: %d", idx);
-            LOG_ALWAYS_FATAL_IF(buffer->width % 4,
-                                "Width is not multiple of 4 %d", buffer->width);
-            LOG_ALWAYS_FATAL_IF(buffer->height % 2,
-                                "Height is not even %d", buffer->height);
-            LOG_ALWAYS_FATAL_IF(buffer->stride < (buffer->width * 10 / 8),
-                                "stride (%d) should be at least %d",
-                                buffer->stride, buffer->width * 10 / 8);
-            pData = buffer->data;
-            dataSize = buffer->stride * buffer->height;
-            break;
-        case HAL_PIXEL_FORMAT_RAW12:
-            // Single plane 10bpp bayer data.
-            ALOG_ASSERT(idx == 0, "Wrong index: %d", idx);
-            LOG_ALWAYS_FATAL_IF(buffer->width % 4,
-                                "Width is not multiple of 4 %d", buffer->width);
-            LOG_ALWAYS_FATAL_IF(buffer->height % 2,
-                                "Height is not even %d", buffer->height);
-            LOG_ALWAYS_FATAL_IF(buffer->stride < (buffer->width * 12 / 8),
-                                "stride (%d) should be at least %d",
-                                buffer->stride, buffer->width * 12 / 8);
-            pData = buffer->data;
-            dataSize = buffer->stride * buffer->height;
-            break;
-        case HAL_PIXEL_FORMAT_RGBA_8888:
-        case HAL_PIXEL_FORMAT_RGBX_8888:
-            // Single plane, 32bpp.
-            bytesPerPixel = 4;
-            ALOG_ASSERT(idx == 0, "Wrong index: %d", idx);
-            pData = buffer->data;
-            dataSize = buffer->stride * buffer->height * bytesPerPixel;
-            break;
-        case HAL_PIXEL_FORMAT_RGB_565:
-            // Single plane, 16bpp.
-            bytesPerPixel = 2;
-            ALOG_ASSERT(idx == 0, "Wrong index: %d", idx);
-            pData = buffer->data;
-            dataSize = buffer->stride * buffer->height * bytesPerPixel;
-            break;
-        case HAL_PIXEL_FORMAT_RGB_888:
-            // Single plane, 24bpp.
-            bytesPerPixel = 3;
-            ALOG_ASSERT(idx == 0, "Wrong index: %d", idx);
-            pData = buffer->data;
-            dataSize = buffer->stride * buffer->height * bytesPerPixel;
-            break;
-        default:
-            jniThrowExceptionFmt(env, "java/lang/UnsupportedOperationException",
-                                 "Pixel format: 0x%x is unsupported", fmt);
-            break;
-    }
-
-    *base = pData;
-    *size = dataSize;
-}
-
-static jint Image_imageGetPixelStride(JNIEnv* env, CpuConsumer::LockedBuffer* buffer, int idx,
-        int32_t halReaderFormat)
-{
-    ALOGV("%s: buffer index: %d", __FUNCTION__, idx);
-    ALOG_ASSERT((idx < IMAGE_READER_MAX_NUM_PLANES) && (idx >= 0), "Index is out of range:%d", idx);
-
-    int pixelStride = 0;
-    ALOG_ASSERT(buffer != NULL, "buffer is NULL");
-
-    int32_t fmt = buffer->flexFormat;
-
-    fmt = applyFormatOverrides(fmt, halReaderFormat);
-
-    switch (fmt) {
-        case HAL_PIXEL_FORMAT_YCbCr_420_888:
-            pixelStride = (idx == 0) ? 1 : buffer->chromaStep;
-            break;
-        case HAL_PIXEL_FORMAT_YCrCb_420_SP:
-            pixelStride = (idx == 0) ? 1 : 2;
-            break;
-        case HAL_PIXEL_FORMAT_Y8:
-            // Single plane 8bpp data.
-            ALOG_ASSERT(idx == 0, "Wrong index: %d", idx);
-            pixelStride = 1;
-            break;
-        case HAL_PIXEL_FORMAT_YV12:
-            pixelStride = 1;
-            break;
-        case HAL_PIXEL_FORMAT_BLOB:
-        case HAL_PIXEL_FORMAT_RAW10:
-        case HAL_PIXEL_FORMAT_RAW12:
-            // Blob is used for JPEG data, RAW10 and RAW12 is used for 10-bit and 12-bit raw data,
-            // those are single plane data with pixel stride 0 since they don't really have a
-            // well defined pixel stride
-            ALOG_ASSERT(idx == 0, "Wrong index: %d", idx);
-            pixelStride = 0;
-            break;
-        case HAL_PIXEL_FORMAT_Y16:
-        case HAL_PIXEL_FORMAT_RAW16:
-        case HAL_PIXEL_FORMAT_RGB_565:
-            // Single plane 16bpp data.
-            ALOG_ASSERT(idx == 0, "Wrong index: %d", idx);
-            pixelStride = 2;
-            break;
-        case HAL_PIXEL_FORMAT_RGBA_8888:
-        case HAL_PIXEL_FORMAT_RGBX_8888:
-            ALOG_ASSERT(idx == 0, "Wrong index: %d", idx);
-            pixelStride = 4;
-            break;
-        case HAL_PIXEL_FORMAT_RGB_888:
-            // Single plane, 24bpp.
-            ALOG_ASSERT(idx == 0, "Wrong index: %d", idx);
-            pixelStride = 3;
-            break;
-        case HAL_PIXEL_FORMAT_RAW_OPAQUE:
-            ALOG_ASSERT(idx == 0, "Wrong index: %d", idx);
-            pixelStride = 0; // RAW OPAQUE doesn't have pixel stride
-            break;
-        default:
-            jniThrowExceptionFmt(env, "java/lang/UnsupportedOperationException",
-                                 "Pixel format: 0x%x is unsupported", fmt);
-            break;
-    }
-
-    return pixelStride;
-}
-
-static jint Image_imageGetRowStride(JNIEnv* env, CpuConsumer::LockedBuffer* buffer, int idx,
-        int32_t halReaderFormat)
-{
-    ALOGV("%s: buffer index: %d", __FUNCTION__, idx);
-    ALOG_ASSERT((idx < IMAGE_READER_MAX_NUM_PLANES) && (idx >= 0));
-
-    int rowStride = 0;
-    ALOG_ASSERT(buffer != NULL, "buffer is NULL");
-
-    int32_t fmt = buffer->flexFormat;
-
-    fmt = applyFormatOverrides(fmt, halReaderFormat);
-
-    switch (fmt) {
-        case HAL_PIXEL_FORMAT_YCbCr_420_888:
-            rowStride = (idx == 0) ? buffer->stride : buffer->chromaStride;
-            break;
-        case HAL_PIXEL_FORMAT_YCrCb_420_SP:
-            rowStride = buffer->width;
-            break;
-        case HAL_PIXEL_FORMAT_YV12:
-            LOG_ALWAYS_FATAL_IF(buffer->stride % 16,
-                                "Stride is not 16 pixel aligned %d", buffer->stride);
-            rowStride = (idx == 0) ? buffer->stride : ALIGN(buffer->stride / 2, 16);
-            break;
-        case HAL_PIXEL_FORMAT_BLOB:
-            // Blob is used for JPEG data. It is single plane and has 0 row stride and
-            // 0 pixel stride
-            ALOG_ASSERT(idx == 0, "Wrong index: %d", idx);
-            rowStride = 0;
-            break;
-        case HAL_PIXEL_FORMAT_RAW10:
-        case HAL_PIXEL_FORMAT_RAW12:
-            // RAW10 and RAW12 are used for 10-bit and 12-bit raw data, they are single plane
-            ALOG_ASSERT(idx == 0, "Wrong index: %d", idx);
-            rowStride = buffer->stride;
-            break;
-        case HAL_PIXEL_FORMAT_Y8:
-            ALOG_ASSERT(idx == 0, "Wrong index: %d", idx);
-            LOG_ALWAYS_FATAL_IF(buffer->stride % 16,
-                                "Stride is not 16 pixel aligned %d", buffer->stride);
-            rowStride = buffer->stride;
-            break;
-        case HAL_PIXEL_FORMAT_Y16:
-        case HAL_PIXEL_FORMAT_RAW16:
-            // In native side, strides are specified in pixels, not in bytes.
-            // Single plane 16bpp bayer data. even width/height,
-            // row stride multiple of 16 pixels (32 bytes)
-            ALOG_ASSERT(idx == 0, "Wrong index: %d", idx);
-            LOG_ALWAYS_FATAL_IF(buffer->stride % 16,
-                                "Stride is not 16 pixel aligned %d", buffer->stride);
-            rowStride = buffer->stride * 2;
-            break;
-        case HAL_PIXEL_FORMAT_RGB_565:
-            ALOG_ASSERT(idx == 0, "Wrong index: %d", idx);
-            rowStride = buffer->stride * 2;
-            break;
-        case HAL_PIXEL_FORMAT_RGBA_8888:
-        case HAL_PIXEL_FORMAT_RGBX_8888:
-            ALOG_ASSERT(idx == 0, "Wrong index: %d", idx);
-            rowStride = buffer->stride * 4;
-            break;
-        case HAL_PIXEL_FORMAT_RGB_888:
-            // Single plane, 24bpp.
-            ALOG_ASSERT(idx == 0, "Wrong index: %d", idx);
-            rowStride = buffer->stride * 3;
-            break;
-        case HAL_PIXEL_FORMAT_RAW_OPAQUE:
-            ALOG_ASSERT(idx == 0, "Wrong index: %d", idx);
-            rowStride = 0; // RAW OPAQUE doesn't have row stride
-            break;
-        default:
-            ALOGE("%s Pixel format: 0x%x is unsupported", __FUNCTION__, fmt);
-            jniThrowException(env, "java/lang/UnsupportedOperationException",
-                              "unsupported buffer format");
-          break;
-    }
-
-    return rowStride;
-}
-
-static int Image_getBufferWidth(CpuConsumer::LockedBuffer* buffer) {
-    if (buffer == NULL) return -1;
-
-    if (!buffer->crop.isEmpty()) {
-        return buffer->crop.getWidth();
-    }
-    return buffer->width;
-}
-
-static int Image_getBufferHeight(CpuConsumer::LockedBuffer* buffer) {
-    if (buffer == NULL) return -1;
-
-    if (!buffer->crop.isEmpty()) {
-        return buffer->crop.getHeight();
-    }
-    return buffer->height;
-}
-
-// --------------------------Methods for opaque Image and ImageReader----------
-
-static BufferItemConsumer* ImageReader_getOpaqueConsumer(JNIEnv* env, jobject thiz)
+static BufferItemConsumer* ImageReader_getBufferConsumer(JNIEnv* env, jobject thiz)
 {
     ALOGV("%s:", __FUNCTION__);
     JNIImageReaderContext* const ctx = ImageReader_getContext(env, thiz);
@@ -728,40 +263,21 @@
         return NULL;
     }
 
-    if (!ctx->isOpaque()) {
-        jniThrowException(env, "java/lang/IllegalStateException",
-                "Non-opaque ImageReader doesn't support this method");
-    }
-
-    return ctx->getOpaqueConsumer();
+    return ctx->getBufferConsumer();
 }
 
-static BufferItem* Image_getOpaqueBuffer(JNIEnv* env, jobject image)
+static void Image_setBufferItem(JNIEnv* env, jobject thiz,
+        const BufferItem* buffer)
+{
+    env->SetLongField(thiz, gSurfaceImageClassInfo.mNativeBuffer, reinterpret_cast<jlong>(buffer));
+}
+
+static BufferItem* Image_getBufferItem(JNIEnv* env, jobject image)
 {
     return reinterpret_cast<BufferItem*>(
             env->GetLongField(image, gSurfaceImageClassInfo.mNativeBuffer));
 }
 
-static int Image_getOpaqueBufferWidth(BufferItem* buffer) {
-    if (buffer == NULL) return -1;
-
-    if (!buffer->mCrop.isEmpty()) {
-        return buffer->mCrop.getWidth();
-    }
-    return buffer->mGraphicBuffer->getWidth();
-}
-
-static int Image_getOpaqueBufferHeight(BufferItem* buffer) {
-    if (buffer == NULL) return -1;
-
-    if (!buffer->mCrop.isEmpty()) {
-        return buffer->mCrop.getHeight();
-    }
-
-    return buffer->mGraphicBuffer->getHeight();
-}
-
-
 
 // ----------------------------------------------------------------------------
 
@@ -784,6 +300,11 @@
                         "can't find android/graphics/ImageReader.%s",
                         ANDROID_MEDIA_SURFACEIMAGE_TS_JNI_ID);
 
+    gSurfaceImageClassInfo.mPlanes = env->GetFieldID(
+            imageClazz, "mPlanes", "[Landroid/media/ImageReader$SurfaceImage$SurfacePlane;");
+    LOG_ALWAYS_FATAL_IF(gSurfaceImageClassInfo.mPlanes == NULL,
+            "can't find android/media/ImageReader$ReaderSurfaceImage.mPlanes");
+
     gImageReaderClassInfo.mNativeContext = env->GetFieldID(
             clazz, ANDROID_MEDIA_IMAGEREADER_CTX_JNI_ID, "J");
     LOG_ALWAYS_FATAL_IF(gImageReaderClassInfo.mNativeContext == NULL,
@@ -800,7 +321,7 @@
     // FindClass only gives a local reference of jclass object.
     gSurfacePlaneClassInfo.clazz = (jclass) env->NewGlobalRef(planeClazz);
     gSurfacePlaneClassInfo.ctor = env->GetMethodID(gSurfacePlaneClassInfo.clazz, "<init>",
-            "(Landroid/media/ImageReader$SurfaceImage;III)V");
+            "(Landroid/media/ImageReader$SurfaceImage;IILjava/nio/ByteBuffer;)V");
     LOG_ALWAYS_FATAL_IF(gSurfacePlaneClassInfo.ctor == NULL,
             "Can not find SurfacePlane constructor");
 }
@@ -831,81 +352,52 @@
     sp<IGraphicBufferProducer> gbProducer;
     sp<IGraphicBufferConsumer> gbConsumer;
     BufferQueue::createBufferQueue(&gbProducer, &gbConsumer);
-    sp<ConsumerBase> consumer;
-    sp<CpuConsumer> cpuConsumer;
-    sp<BufferItemConsumer> opaqueConsumer;
+    sp<BufferItemConsumer> bufferConsumer;
     String8 consumerName = String8::format("ImageReader-%dx%df%xm%d-%d-%d",
             width, height, format, maxImages, getpid(),
             createProcessUniqueId());
+    uint32_t consumerUsage = GRALLOC_USAGE_SW_READ_OFTEN;
+
     if (isFormatOpaque(nativeFormat)) {
         // Use the SW_READ_NEVER usage to tell producer that this format is not for preview or video
         // encoding. The only possibility will be ZSL output.
-        opaqueConsumer =
-                new BufferItemConsumer(gbConsumer, GRALLOC_USAGE_SW_READ_NEVER, maxImages,
-                        /*controlledByApp*/true);
-        if (opaqueConsumer == NULL) {
-            jniThrowRuntimeException(env, "Failed to allocate native opaque consumer");
-            return;
-        }
-        ctx->setOpaqueConsumer(opaqueConsumer);
-        opaqueConsumer->setName(consumerName);
-        consumer = opaqueConsumer;
-    } else {
-        cpuConsumer = new CpuConsumer(gbConsumer, maxImages, /*controlledByApp*/true);
-        // TODO: throw dvm exOutOfMemoryError?
-        if (cpuConsumer == NULL) {
-            jniThrowRuntimeException(env, "Failed to allocate native CpuConsumer");
-            return;
-        }
-        ctx->setCpuConsumer(cpuConsumer);
-        cpuConsumer->setName(consumerName);
-        consumer = cpuConsumer;
+        consumerUsage = GRALLOC_USAGE_SW_READ_NEVER;
     }
+    bufferConsumer = new BufferItemConsumer(gbConsumer, consumerUsage, maxImages,
+            /*controlledByApp*/true);
+    if (bufferConsumer == nullptr) {
+        jniThrowExceptionFmt(env, "java/lang/RuntimeException",
+                "Failed to allocate native buffer consumer for format 0x%x", nativeFormat);
+        return;
+    }
+    ctx->setBufferConsumer(bufferConsumer);
+    bufferConsumer->setName(consumerName);
 
     ctx->setProducer(gbProducer);
-    consumer->setFrameAvailableListener(ctx);
+    bufferConsumer->setFrameAvailableListener(ctx);
     ImageReader_setNativeContext(env, thiz, ctx);
     ctx->setBufferFormat(nativeFormat);
     ctx->setBufferDataspace(nativeDataspace);
     ctx->setBufferWidth(width);
     ctx->setBufferHeight(height);
 
-    // Set the width/height/format/dataspace to the CpuConsumer
-    // TODO: below code can be simplified once b/19977701 is fixed.
-    if (isFormatOpaque(nativeFormat)) {
-        res = opaqueConsumer->setDefaultBufferSize(width, height);
-        if (res != OK) {
-            jniThrowException(env, "java/lang/IllegalStateException",
-                              "Failed to set opaque consumer buffer size");
-            return;
-        }
-        res = opaqueConsumer->setDefaultBufferFormat(nativeFormat);
-        if (res != OK) {
-            jniThrowException(env, "java/lang/IllegalStateException",
-                              "Failed to set opaque consumer buffer format");
-        }
-        res = opaqueConsumer->setDefaultBufferDataSpace(nativeDataspace);
-        if (res != OK) {
-            jniThrowException(env, "java/lang/IllegalStateException",
-                              "Failed to set opaque consumer buffer dataSpace");
-        }
-    } else {
-        res = cpuConsumer->setDefaultBufferSize(width, height);
-        if (res != OK) {
-            jniThrowException(env, "java/lang/IllegalStateException",
-                              "Failed to set CpuConsumer buffer size");
-            return;
-        }
-        res = cpuConsumer->setDefaultBufferFormat(nativeFormat);
-        if (res != OK) {
-            jniThrowException(env, "java/lang/IllegalStateException",
-                              "Failed to set CpuConsumer buffer format");
-        }
-        res = cpuConsumer->setDefaultBufferDataSpace(nativeDataspace);
-        if (res != OK) {
-            jniThrowException(env, "java/lang/IllegalStateException",
-                              "Failed to set CpuConsumer buffer dataSpace");
-        }
+    // Set the width/height/format/dataspace to the bufferConsumer.
+    res = bufferConsumer->setDefaultBufferSize(width, height);
+    if (res != OK) {
+        jniThrowExceptionFmt(env, "java/lang/IllegalStateException",
+                          "Failed to set buffer consumer default size (%dx%d) for format 0x%x",
+                          width, height, nativeFormat);
+        return;
+    }
+    res = bufferConsumer->setDefaultBufferFormat(nativeFormat);
+    if (res != OK) {
+        jniThrowExceptionFmt(env, "java/lang/IllegalStateException",
+                          "Failed to set buffer consumer default format 0x%x", nativeFormat);
+    }
+    res = bufferConsumer->setDefaultBufferDataSpace(nativeDataspace);
+    if (res != OK) {
+        jniThrowExceptionFmt(env, "java/lang/IllegalStateException",
+                          "Failed to set buffer consumer default dataSpace 0x%x", nativeDataspace);
     }
 }
 
@@ -919,12 +411,8 @@
         return;
     }
 
-    ConsumerBase* consumer = NULL;
-    if (ctx->isOpaque()) {
-        consumer = ImageReader_getOpaqueConsumer(env, thiz);
-    } else {
-        consumer = ImageReader_getCpuConsumer(env, thiz);
-    }
+    BufferItemConsumer* consumer = NULL;
+    consumer = ImageReader_getBufferConsumer(env, thiz);
 
     if (consumer != NULL) {
         consumer->abandon();
@@ -933,6 +421,39 @@
     ImageReader_setNativeContext(env, thiz, NULL);
 }
 
+static sp<Fence> Image_unlockIfLocked(JNIEnv* env, jobject image) {
+    ALOGV("%s", __FUNCTION__);
+    BufferItem* buffer = Image_getBufferItem(env, image);
+    if (buffer == NULL) {
+        jniThrowException(env, "java/lang/IllegalStateException",
+                "Image is not initialized");
+        return Fence::NO_FENCE;
+    }
+
+    // Is locked?
+    bool wasBufferLocked = false;
+    jobject planes = NULL;
+    if (!isFormatOpaque(buffer->mGraphicBuffer->getPixelFormat())) {
+        planes = env->GetObjectField(image, gSurfaceImageClassInfo.mPlanes);
+    }
+    wasBufferLocked = (planes != NULL);
+    if (wasBufferLocked) {
+        status_t res = OK;
+        int fenceFd = -1;
+        if (wasBufferLocked) {
+            res = buffer->mGraphicBuffer->unlockAsync(&fenceFd);
+            if (res != OK) {
+                jniThrowRuntimeException(env, "unlock buffer failed");
+                return Fence::NO_FENCE;
+            }
+        }
+        sp<Fence> releaseFence = new Fence(fenceFd);
+        return releaseFence;
+        ALOGV("Successfully unlocked the image");
+    }
+    return Fence::NO_FENCE;
+}
+
 static void ImageReader_imageRelease(JNIEnv* env, jobject thiz, jobject image)
 {
     ALOGV("%s:", __FUNCTION__);
@@ -942,156 +463,18 @@
         return;
     }
 
-    if (ctx->isOpaque()) {
-        BufferItemConsumer* opaqueConsumer = ctx->getOpaqueConsumer();
-        BufferItem* opaqueBuffer = Image_getOpaqueBuffer(env, image);
-        opaqueConsumer->releaseBuffer(*opaqueBuffer); // Not using fence for now.
-        Image_setOpaqueBuffer(env, image, NULL);
-        ctx->returnOpaqueBuffer(opaqueBuffer);
-        ALOGV("%s: Opaque Image has been released", __FUNCTION__);
-    } else {
-        CpuConsumer* consumer = ctx->getCpuConsumer();
-        CpuConsumer::LockedBuffer* buffer = Image_getLockedBuffer(env, image);
-        if (!buffer) {
-            // Release an already closed image is harmless.
-            return;
-        }
-        consumer->unlockBuffer(*buffer);
-        Image_setBuffer(env, image, NULL);
-        ctx->returnLockedBuffer(buffer);
-        ALOGV("%s: Image (format: 0x%x) has been released", __FUNCTION__, ctx->getBufferFormat());
-    }
-}
-
-static jint ImageReader_opaqueImageSetup(JNIEnv* env, JNIImageReaderContext* ctx, jobject image) {
-    ALOGV("%s:", __FUNCTION__);
-    if (ctx == NULL || !ctx->isOpaque()) {
-        jniThrowRuntimeException(env, "ImageReaderContext is not initialized");
-        return -1;
+    BufferItemConsumer* bufferConsumer = ctx->getBufferConsumer();
+    BufferItem* buffer = Image_getBufferItem(env, image);
+    if (buffer == nullptr) {
+        // Release an already closed image is harmless.
+        return;
     }
 
-    BufferItemConsumer* opaqueConsumer = ctx->getOpaqueConsumer();
-    BufferItem* buffer = ctx->getOpaqueBuffer();
-    if (buffer == NULL) {
-        ALOGW("Unable to acquire a buffer item, very likely client tried to acquire more than"
-            " maxImages buffers");
-        return ACQUIRE_MAX_IMAGES;
-    }
-
-    status_t res = opaqueConsumer->acquireBuffer(buffer, 0);
-    if (res != OK) {
-        ctx->returnOpaqueBuffer(buffer);
-        if (res == INVALID_OPERATION) {
-            // Max number of images were already acquired.
-            ALOGE("%s: Max number of buffers allowed are already acquired : %s (%d)",
-                    __FUNCTION__, strerror(-res), res);
-            return ACQUIRE_MAX_IMAGES;
-        } else {
-            ALOGE("%s: Acquire image failed with error: %s (%d)",
-                    __FUNCTION__, strerror(-res), res);
-            return ACQUIRE_NO_BUFFERS;
-        }
-    }
-
-    // Set SurfaceImage instance member variables
-    Image_setOpaqueBuffer(env, image, buffer);
-    env->SetLongField(image, gSurfaceImageClassInfo.mTimestamp,
-            static_cast<jlong>(buffer->mTimestamp));
-
-    return ACQUIRE_SUCCESS;
-}
-
-static jint ImageReader_lockedImageSetup(JNIEnv* env, JNIImageReaderContext* ctx, jobject image) {
-    CpuConsumer* consumer = ctx->getCpuConsumer();
-    CpuConsumer::LockedBuffer* buffer = ctx->getLockedBuffer();
-    if (buffer == NULL) {
-        ALOGW("Unable to acquire a lockedBuffer, very likely client tries to lock more than"
-            " maxImages buffers");
-        return ACQUIRE_MAX_IMAGES;
-    }
-    status_t res = consumer->lockNextBuffer(buffer);
-    if (res != NO_ERROR) {
-        ctx->returnLockedBuffer(buffer);
-        if (res != BAD_VALUE /*no buffers*/) {
-            if (res == NOT_ENOUGH_DATA) {
-                return ACQUIRE_MAX_IMAGES;
-            } else {
-                ALOGE("%s Fail to lockNextBuffer with error: %d ",
-                      __FUNCTION__, res);
-                jniThrowExceptionFmt(env, "java/lang/AssertionError",
-                          "Unknown error (%d) when we tried to lock buffer.",
-                          res);
-            }
-        }
-        return ACQUIRE_NO_BUFFERS;
-    }
-
-    if (buffer->flexFormat == HAL_PIXEL_FORMAT_YCrCb_420_SP) {
-        jniThrowException(env, "java/lang/UnsupportedOperationException",
-                "NV21 format is not supported by ImageReader");
-        return -1;
-    }
-
-    // Check if the left-top corner of the crop rect is origin, we currently assume this point is
-    // zero, will revist this once this assumption turns out problematic.
-    Point lt = buffer->crop.leftTop();
-    if (lt.x != 0 || lt.y != 0) {
-        jniThrowExceptionFmt(env, "java/lang/UnsupportedOperationException",
-                "crop left top corner [%d, %d] need to be at origin", lt.x, lt.y);
-        return -1;
-    }
-
-    // Check if the producer buffer configurations match what ImageReader configured.
-    int outputWidth = Image_getBufferWidth(buffer);
-    int outputHeight = Image_getBufferHeight(buffer);
-
-    int imgReaderFmt = ctx->getBufferFormat();
-    int imageReaderWidth = ctx->getBufferWidth();
-    int imageReaderHeight = ctx->getBufferHeight();
-    if ((buffer->format != HAL_PIXEL_FORMAT_BLOB) && (imgReaderFmt != HAL_PIXEL_FORMAT_BLOB) &&
-            (imageReaderWidth != outputWidth || imageReaderHeight != outputHeight)) {
-        ALOGV("%s: Producer buffer size: %dx%d, doesn't match ImageReader configured size: %dx%d",
-                __FUNCTION__, outputWidth, outputHeight, imageReaderWidth, imageReaderHeight);
-    }
-
-    int bufFmt = buffer->format;
-    if (imgReaderFmt == HAL_PIXEL_FORMAT_YCbCr_420_888) {
-        bufFmt = buffer->flexFormat;
-    }
-    if (imgReaderFmt != bufFmt) {
-        if (imgReaderFmt == HAL_PIXEL_FORMAT_YCbCr_420_888 && (bufFmt ==
-                HAL_PIXEL_FORMAT_YCrCb_420_SP || bufFmt == HAL_PIXEL_FORMAT_YV12)) {
-            // Special casing for when producer switches to a format compatible with flexible YUV
-            // (HAL_PIXEL_FORMAT_YCbCr_420_888).
-            ctx->setBufferFormat(bufFmt);
-            ALOGD("%s: Overriding buffer format YUV_420_888 to %x.", __FUNCTION__, bufFmt);
-        } else if (imgReaderFmt == HAL_PIXEL_FORMAT_BLOB && bufFmt == HAL_PIXEL_FORMAT_RGBA_8888) {
-            // Using HAL_PIXEL_FORMAT_RGBA_8888 gralloc buffers containing JPEGs to get around SW
-            // write limitations for (b/17379185).
-            ALOGD("%s: Receiving JPEG in HAL_PIXEL_FORMAT_RGBA_8888 buffer.", __FUNCTION__);
-        } else {
-            // Return the buffer to the queue.
-            consumer->unlockBuffer(*buffer);
-            ctx->returnLockedBuffer(buffer);
-
-            // Throw exception
-            ALOGE("Producer output buffer format: 0x%x, ImageReader configured format: 0x%x",
-                    buffer->format, ctx->getBufferFormat());
-            String8 msg;
-            msg.appendFormat("The producer output buffer format 0x%x doesn't "
-                    "match the ImageReader's configured buffer format 0x%x.",
-                    bufFmt, ctx->getBufferFormat());
-            jniThrowException(env, "java/lang/UnsupportedOperationException",
-                    msg.string());
-            return -1;
-        }
-    }
-    // Set SurfaceImage instance member variables
-    Image_setBuffer(env, image, buffer);
-    env->SetLongField(image, gSurfaceImageClassInfo.mTimestamp,
-            static_cast<jlong>(buffer->timestamp));
-
-    return ACQUIRE_SUCCESS;
+    sp<Fence> releaseFence = Image_unlockIfLocked(env, image);
+    bufferConsumer->releaseBuffer(*buffer, releaseFence);
+    Image_setBufferItem(env, image, NULL);
+    ctx->returnBufferItem(buffer);
+    ALOGV("%s: Image (format: 0x%x) has been released", __FUNCTION__, ctx->getBufferFormat());
 }
 
 static jint ImageReader_imageSetup(JNIEnv* env, jobject thiz, jobject image) {
@@ -1103,11 +486,99 @@
         return -1;
     }
 
-    if (ctx->isOpaque()) {
-        return ImageReader_opaqueImageSetup(env, ctx, image);
-    } else {
-        return ImageReader_lockedImageSetup(env, ctx, image);
+    BufferItemConsumer* bufferConsumer = ctx->getBufferConsumer();
+    BufferItem* buffer = ctx->getBufferItem();
+    if (buffer == NULL) {
+        ALOGW("Unable to acquire a buffer item, very likely client tried to acquire more than"
+            " maxImages buffers");
+        return ACQUIRE_MAX_IMAGES;
     }
+
+    status_t res = bufferConsumer->acquireBuffer(buffer, 0);
+    if (res != OK) {
+        ctx->returnBufferItem(buffer);
+        if (res != BufferQueue::NO_BUFFER_AVAILABLE) {
+            if (res == INVALID_OPERATION) {
+                // Max number of images were already acquired.
+                ALOGE("%s: Max number of buffers allowed are already acquired : %s (%d)",
+                        __FUNCTION__, strerror(-res), res);
+                return ACQUIRE_MAX_IMAGES;
+            } else {
+                ALOGE("%s: Acquire image failed with some unknown error: %s (%d)",
+                        __FUNCTION__, strerror(-res), res);
+                jniThrowExceptionFmt(env, "java/lang/IllegalStateException",
+                        "Unknown error (%d) when we tried to acquire an image.",
+                                          res);
+                return ACQUIRE_NO_BUFFERS;
+            }
+        }
+        // This isn't really an error case, as the application may acquire buffer at any time.
+        return ACQUIRE_NO_BUFFERS;
+    }
+
+    // Add some extra checks for non-opaque formats.
+    if (!isFormatOpaque(ctx->getBufferFormat())) {
+        // Check if the left-top corner of the crop rect is origin, we currently assume this point is
+        // zero, will revisit this once this assumption turns out problematic.
+        Point lt = buffer->mCrop.leftTop();
+        if (lt.x != 0 || lt.y != 0) {
+            jniThrowExceptionFmt(env, "java/lang/UnsupportedOperationException",
+                    "crop left top corner [%d, %d] need to be at origin", lt.x, lt.y);
+            return -1;
+        }
+
+        // Check if the producer buffer configurations match what ImageReader configured.
+        int outputWidth = getBufferWidth(buffer);
+        int outputHeight = getBufferHeight(buffer);
+
+        int imgReaderFmt = ctx->getBufferFormat();
+        int imageReaderWidth = ctx->getBufferWidth();
+        int imageReaderHeight = ctx->getBufferHeight();
+        int bufferFormat = buffer->mGraphicBuffer->getPixelFormat();
+        if ((bufferFormat != HAL_PIXEL_FORMAT_BLOB) && (imgReaderFmt != HAL_PIXEL_FORMAT_BLOB) &&
+                (imageReaderWidth != outputWidth || imageReaderHeight != outputHeight)) {
+            ALOGV("%s: Producer buffer size: %dx%d, doesn't match ImageReader configured size: %dx%d",
+                    __FUNCTION__, outputWidth, outputHeight, imageReaderWidth, imageReaderHeight);
+        }
+        if (imgReaderFmt != bufferFormat) {
+            if (imgReaderFmt == HAL_PIXEL_FORMAT_YCbCr_420_888 &&
+                    isPossiblyYUV(bufferFormat)) {
+                // Treat formats that are compatible with flexible YUV
+                // (HAL_PIXEL_FORMAT_YCbCr_420_888) as HAL_PIXEL_FORMAT_YCbCr_420_888.
+                ALOGV("%s: Treat buffer format to 0x%x as HAL_PIXEL_FORMAT_YCbCr_420_888",
+                        __FUNCTION__, bufferFormat);
+            } else if (imgReaderFmt == HAL_PIXEL_FORMAT_BLOB &&
+                    bufferFormat == HAL_PIXEL_FORMAT_RGBA_8888) {
+                // Using HAL_PIXEL_FORMAT_RGBA_8888 Gralloc buffers containing JPEGs to get around
+                // SW write limitations for (b/17379185).
+                ALOGV("%s: Receiving JPEG in HAL_PIXEL_FORMAT_RGBA_8888 buffer.", __FUNCTION__);
+            } else {
+                // Return the buffer to the queue. No need to provide fence, as this buffer wasn't
+                // used anywhere yet.
+                bufferConsumer->releaseBuffer(*buffer);
+                ctx->returnBufferItem(buffer);
+
+                // Throw exception
+                ALOGE("Producer output buffer format: 0x%x, ImageReader configured format: 0x%x",
+                        bufferFormat, ctx->getBufferFormat());
+                String8 msg;
+                msg.appendFormat("The producer output buffer format 0x%x doesn't "
+                        "match the ImageReader's configured buffer format 0x%x.",
+                        bufferFormat, ctx->getBufferFormat());
+                jniThrowException(env, "java/lang/UnsupportedOperationException",
+                        msg.string());
+                return -1;
+            }
+        }
+
+    }
+
+    // Set SurfaceImage instance member variables
+    Image_setBufferItem(env, image, buffer);
+    env->SetLongField(image, gSurfaceImageClassInfo.mTimestamp,
+            static_cast<jlong>(buffer->mTimestamp));
+
+    return ACQUIRE_SUCCESS;
 }
 
 static jint ImageReader_detachImage(JNIEnv* env, jobject thiz, jobject image) {
@@ -1118,29 +589,23 @@
         return -1;
     }
 
-    status_t res = OK;
-    if (!ctx->isOpaque()) {
-        // TODO: Non-Opaque format detach is not implemented yet.
-        jniThrowRuntimeException(env,
-                "nativeDetachImage is not implemented yet for non-opaque format !!!");
-        return -1;
-    }
-
-    BufferItemConsumer* opaqueConsumer = ctx->getOpaqueConsumer();
-    BufferItem* opaqueBuffer = Image_getOpaqueBuffer(env, image);
-    if (!opaqueBuffer) {
+    BufferItemConsumer* bufferConsumer = ctx->getBufferConsumer();
+    BufferItem* buffer = Image_getBufferItem(env, image);
+    if (!buffer) {
         ALOGE(
-                "Opaque Image already released and can not be detached from ImageReader!!!");
+                "Image already released and can not be detached from ImageReader!!!");
         jniThrowException(env, "java/lang/IllegalStateException",
-                "Opaque Image detach from ImageReader failed: buffer was already released");
+                "Image detach from ImageReader failed: buffer was already released");
         return -1;
     }
 
-    res = opaqueConsumer->detachBuffer(opaqueBuffer->mSlot);
+    status_t res = OK;
+    Image_unlockIfLocked(env, image);
+    res = bufferConsumer->detachBuffer(buffer->mSlot);
     if (res != OK) {
-        ALOGE("Opaque Image detach failed: %s (%d)!!!", strerror(-res), res);
+        ALOGE("Image detach failed: %s (%d)!!!", strerror(-res), res);
         jniThrowRuntimeException(env,
-                "nativeDetachImage failed for opaque image!!!");
+                "nativeDetachImage failed for image!!!");
         return res;
     }
     return OK;
@@ -1152,7 +617,7 @@
 
     IGraphicBufferProducer* gbp = ImageReader_getProducer(env, thiz);
     if (gbp == NULL) {
-        jniThrowRuntimeException(env, "CpuConsumer is uninitialized");
+        jniThrowRuntimeException(env, "Buffer consumer is uninitialized");
         return NULL;
     }
 
@@ -1160,98 +625,115 @@
     return android_view_Surface_createFromIGraphicBufferProducer(env, gbp);
 }
 
-static jobject Image_createSurfacePlane(JNIEnv* env, jobject thiz, int idx, int readerFormat)
+static void Image_getLockedImage(JNIEnv* env, jobject thiz, LockedImage *image) {
+    ALOGV("%s", __FUNCTION__);
+    BufferItem* buffer = Image_getBufferItem(env, thiz);
+    if (buffer == NULL) {
+        jniThrowException(env, "java/lang/IllegalStateException",
+                "Image is not initialized");
+        return;
+    }
+
+    status_t res = lockImageFromBuffer(buffer,
+            GRALLOC_USAGE_SW_READ_OFTEN, buffer->mFence->dup(), image);
+    if (res != OK) {
+        jniThrowExceptionFmt(env, "java/lang/RuntimeException",
+                "lock buffer failed for format 0x%x",
+                buffer->mGraphicBuffer->getPixelFormat());
+        return;
+    }
+
+    // Carry over some fields from BufferItem.
+    image->crop        = buffer->mCrop;
+    image->transform   = buffer->mTransform;
+    image->scalingMode = buffer->mScalingMode;
+    image->timestamp   = buffer->mTimestamp;
+    image->dataSpace   = buffer->mDataSpace;
+    image->frameNumber = buffer->mFrameNumber;
+
+    ALOGV("%s: Successfully locked the image", __FUNCTION__);
+    // crop, transform, scalingMode, timestamp, and frameNumber should be set by producer,
+    // and we don't set them here.
+}
+
+static void Image_getLockedImageInfo(JNIEnv* env, LockedImage* buffer, int idx,
+        int32_t writerFormat, uint8_t **base, uint32_t *size, int *pixelStride, int *rowStride) {
+    ALOGV("%s", __FUNCTION__);
+
+    status_t res = getLockedImageInfo(buffer, idx, writerFormat, base, size,
+            pixelStride, rowStride);
+    if (res != OK) {
+        jniThrowExceptionFmt(env, "java/lang/UnsupportedOperationException",
+                             "Pixel format: 0x%x is unsupported", buffer->flexFormat);
+    }
+}
+
+static jobjectArray Image_createSurfacePlanes(JNIEnv* env, jobject thiz,
+        int numPlanes, int readerFormat)
 {
-    int rowStride, pixelStride;
+    ALOGV("%s: create SurfacePlane array with size %d", __FUNCTION__, numPlanes);
+    int rowStride = 0;
+    int pixelStride = 0;
+    uint8_t *pData = NULL;
+    uint32_t dataSize = 0;
+    jobject byteBuffer = NULL;
+
     PublicFormat publicReaderFormat = static_cast<PublicFormat>(readerFormat);
     int halReaderFormat = android_view_Surface_mapPublicFormatToHalFormat(
         publicReaderFormat);
 
-    ALOGV("%s: buffer index: %d", __FUNCTION__, idx);
+    if (isFormatOpaque(halReaderFormat) && numPlanes > 0) {
+        String8 msg;
+        msg.appendFormat("Format 0x%x is opaque, thus not writable, the number of planes (%d)"
+                " must be 0", halReaderFormat, numPlanes);
+        jniThrowException(env, "java/lang/IllegalArgumentException", msg.string());
+        return NULL;
+    }
+
+    jobjectArray surfacePlanes = env->NewObjectArray(numPlanes, gSurfacePlaneClassInfo.clazz,
+            /*initial_element*/NULL);
+    if (surfacePlanes == NULL) {
+        jniThrowRuntimeException(env, "Failed to create SurfacePlane arrays,"
+                " probably out of memory");
+        return NULL;
+    }
     if (isFormatOpaque(halReaderFormat)) {
-        jniThrowException(env, "java/lang/IllegalStateException",
-                "Opaque images from Opaque ImageReader do not have any planes");
-        return NULL;
+        // Return 0 element surface array.
+        return surfacePlanes;
     }
 
-    CpuConsumer::LockedBuffer* buffer = Image_getLockedBuffer(env, thiz);
+    LockedImage lockedImg = LockedImage();
+    Image_getLockedImage(env, thiz, &lockedImg);
+    // Create all SurfacePlanes
+    for (int i = 0; i < numPlanes; i++) {
+        Image_getLockedImageInfo(env, &lockedImg, i, halReaderFormat,
+                &pData, &dataSize, &pixelStride, &rowStride);
+        byteBuffer = env->NewDirectByteBuffer(pData, dataSize);
+        if ((byteBuffer == NULL) && (env->ExceptionCheck() == false)) {
+            jniThrowException(env, "java/lang/IllegalStateException",
+                    "Failed to allocate ByteBuffer");
+            return NULL;
+        }
 
-    ALOG_ASSERT(buffer != NULL);
-    if (buffer == NULL) {
-        jniThrowException(env, "java/lang/IllegalStateException", "Image was released");
+        // Finally, create this SurfacePlane.
+        jobject surfacePlane = env->NewObject(gSurfacePlaneClassInfo.clazz,
+                    gSurfacePlaneClassInfo.ctor, thiz, rowStride, pixelStride, byteBuffer);
+        env->SetObjectArrayElement(surfacePlanes, i, surfacePlane);
     }
 
-    rowStride = Image_imageGetRowStride(env, buffer, idx, halReaderFormat);
-    pixelStride = Image_imageGetPixelStride(env, buffer, idx, halReaderFormat);
-
-    jobject surfPlaneObj = env->NewObject(gSurfacePlaneClassInfo.clazz,
-            gSurfacePlaneClassInfo.ctor, thiz, idx, rowStride, pixelStride);
-
-    return surfPlaneObj;
+    return surfacePlanes;
 }
 
-static jobject Image_getByteBuffer(JNIEnv* env, jobject thiz, int idx, int readerFormat)
+static jint Image_getWidth(JNIEnv* env, jobject thiz)
 {
-    uint8_t *base = NULL;
-    uint32_t size = 0;
-    jobject byteBuffer;
-    PublicFormat readerPublicFormat = static_cast<PublicFormat>(readerFormat);
-    int readerHalFormat = android_view_Surface_mapPublicFormatToHalFormat(
-            readerPublicFormat);
-
-    ALOGV("%s: buffer index: %d", __FUNCTION__, idx);
-
-    if (isFormatOpaque(readerHalFormat)) {
-        jniThrowException(env, "java/lang/IllegalStateException",
-                "Opaque images from Opaque ImageReader do not have any plane");
-        return NULL;
-    }
-
-    CpuConsumer::LockedBuffer* buffer = Image_getLockedBuffer(env, thiz);
-
-    if (buffer == NULL) {
-        jniThrowException(env, "java/lang/IllegalStateException", "Image was released");
-    }
-
-    // Create byteBuffer from native buffer
-    Image_getLockedBufferInfo(env, buffer, idx, &base, &size, readerHalFormat);
-
-    if (size > static_cast<uint32_t>(INT32_MAX)) {
-        // Byte buffer have 'int capacity', so check the range
-        jniThrowExceptionFmt(env, "java/lang/IllegalStateException",
-                "Size too large for bytebuffer capacity %" PRIu32, size);
-        return NULL;
-    }
-
-    byteBuffer = env->NewDirectByteBuffer(base, size);
-    // TODO: throw dvm exOutOfMemoryError?
-    if ((byteBuffer == NULL) && (env->ExceptionCheck() == false)) {
-        jniThrowException(env, "java/lang/IllegalStateException", "Failed to allocate ByteBuffer");
-    }
-
-    return byteBuffer;
+    BufferItem* buffer = Image_getBufferItem(env, thiz);
+    return getBufferWidth(buffer);
 }
 
-static jint Image_getWidth(JNIEnv* env, jobject thiz, jint format)
+static jint Image_getHeight(JNIEnv* env, jobject thiz)
 {
-    if (isFormatOpaque(format)) {
-        BufferItem* opaqueBuffer = Image_getOpaqueBuffer(env, thiz);
-        return Image_getOpaqueBufferWidth(opaqueBuffer);
-    } else {
-        CpuConsumer::LockedBuffer* buffer = Image_getLockedBuffer(env, thiz);
-        return Image_getBufferWidth(buffer);
-    }
-}
-
-static jint Image_getHeight(JNIEnv* env, jobject thiz, jint format)
-{
-    if (isFormatOpaque(format)) {
-        BufferItem* opaqueBuffer = Image_getOpaqueBuffer(env, thiz);
-        return Image_getOpaqueBufferHeight(opaqueBuffer);
-    } else {
-        CpuConsumer::LockedBuffer* buffer = Image_getLockedBuffer(env, thiz);
-        return Image_getBufferHeight(buffer);
-    }
+    BufferItem* buffer = Image_getBufferItem(env, thiz);
+    return getBufferHeight(buffer);
 }
 
 static jint Image_getFormat(JNIEnv* env, jobject thiz, jint readerFormat)
@@ -1260,20 +742,21 @@
         // Assuming opaque reader produce opaque images.
         return static_cast<jint>(PublicFormat::PRIVATE);
     } else {
-        CpuConsumer::LockedBuffer* buffer = Image_getLockedBuffer(env, thiz);
+        BufferItem* buffer = Image_getBufferItem(env, thiz);
         int readerHalFormat = android_view_Surface_mapPublicFormatToHalFormat(
                 static_cast<PublicFormat>(readerFormat));
-        int32_t fmt = applyFormatOverrides(buffer->flexFormat, readerHalFormat);
+        int32_t fmt = applyFormatOverrides(
+                buffer->mGraphicBuffer->getPixelFormat(), readerHalFormat);
         // Override the image format to HAL_PIXEL_FORMAT_YCbCr_420_888 if the actual format is
         // NV21 or YV12. This could only happen when the Gralloc HAL version is v0.1 thus doesn't
         // support lockycbcr(), the CpuConsumer need to use the lock() method in the
         // lockNextBuffer() call. For Gralloc HAL v0.2 or newer, this format should already be
         // overridden to HAL_PIXEL_FORMAT_YCbCr_420_888 for the flexible YUV compatible formats.
-        if (fmt == HAL_PIXEL_FORMAT_YCrCb_420_SP || fmt == HAL_PIXEL_FORMAT_YV12) {
+        if (isPossiblyYUV(fmt)) {
             fmt = HAL_PIXEL_FORMAT_YCbCr_420_888;
         }
         PublicFormat publicFmt = android_view_Surface_mapHalFormatDataspaceToPublicFormat(
-                fmt, buffer->dataSpace);
+                fmt, buffer->mDataSpace);
         return static_cast<jint>(publicFmt);
     }
 }
@@ -1293,11 +776,10 @@
 };
 
 static const JNINativeMethod gImageMethods[] = {
-    {"nativeImageGetBuffer",   "(II)Ljava/nio/ByteBuffer;",   (void*)Image_getByteBuffer },
-    {"nativeCreatePlane",      "(II)Landroid/media/ImageReader$SurfaceImage$SurfacePlane;",
-                                                              (void*)Image_createSurfacePlane },
-    {"nativeGetWidth",         "(I)I",                        (void*)Image_getWidth },
-    {"nativeGetHeight",        "(I)I",                        (void*)Image_getHeight },
+    {"nativeCreatePlanes",      "(II)[Landroid/media/ImageReader$SurfaceImage$SurfacePlane;",
+                                                              (void*)Image_createSurfacePlanes },
+    {"nativeGetWidth",         "()I",                        (void*)Image_getWidth },
+    {"nativeGetHeight",        "()I",                        (void*)Image_getHeight },
     {"nativeGetFormat",        "(I)I",                        (void*)Image_getFormat },
 };
 
diff --git a/media/jni/android_media_ImageWriter.cpp b/media/jni/android_media_ImageWriter.cpp
index f50da85..d5d9fc9 100644
--- a/media/jni/android_media_ImageWriter.cpp
+++ b/media/jni/android_media_ImageWriter.cpp
@@ -16,34 +16,28 @@
 
 //#define LOG_NDEBUG 0
 #define LOG_TAG "ImageWriter_JNI"
+#include "android_media_Utils.h"
+
 #include <utils/Log.h>
 #include <utils/String8.h>
 
 #include <gui/IProducerListener.h>
 #include <gui/Surface.h>
-#include <gui/CpuConsumer.h>
 #include <android_runtime/AndroidRuntime.h>
 #include <android_runtime/android_view_Surface.h>
 #include <camera3.h>
-
 #include <jni.h>
 #include <JNIHelp.h>
 
 #include <stdint.h>
 #include <inttypes.h>
 
-#define ALIGN(x, mask) ( ((x) + (mask) - 1) & ~((mask) - 1) )
-
 #define IMAGE_BUFFER_JNI_ID           "mNativeBuffer"
 
 // ----------------------------------------------------------------------------
 
 using namespace android;
 
-enum {
-    IMAGE_WRITER_MAX_NUM_PLANES = 3,
-};
-
 static struct {
     jmethodID postEventFromNative;
     jfieldID mWriterFormat;
@@ -60,8 +54,6 @@
     jmethodID ctor;
 } gSurfacePlaneClassInfo;
 
-typedef CpuConsumer::LockedBuffer LockedImage;
-
 // ----------------------------------------------------------------------------
 
 class JNIImageWriterContext : public BnProducerListener {
@@ -181,13 +173,11 @@
 
 // -------------------------------Private method declarations--------------
 
-static bool isPossiblyYUV(PixelFormat format);
 static void Image_setNativeContext(JNIEnv* env, jobject thiz,
         sp<GraphicBuffer> buffer, int fenceFd);
 static void Image_getNativeContext(JNIEnv* env, jobject thiz,
         GraphicBuffer** buffer, int* fenceFd);
 static void Image_unlockIfLocked(JNIEnv* env, jobject thiz);
-static bool isFormatOpaque(int format);
 
 // --------------------------ImageWriter methods---------------------------------------
 
@@ -672,28 +662,6 @@
     return buffer->getHeight();
 }
 
-// Some formats like JPEG defined with different values between android.graphics.ImageFormat and
-// graphics.h, need convert to the one defined in graphics.h here.
-static int Image_getPixelFormat(JNIEnv* env, int format) {
-    int jpegFormat;
-    jfieldID fid;
-
-    ALOGV("%s: format = 0x%x", __FUNCTION__, format);
-
-    jclass imageFormatClazz = env->FindClass("android/graphics/ImageFormat");
-    ALOG_ASSERT(imageFormatClazz != NULL);
-
-    fid = env->GetStaticFieldID(imageFormatClazz, "JPEG", "I");
-    jpegFormat = env->GetStaticIntField(imageFormatClazz, fid);
-
-    // Translate the JPEG to BLOB for camera purpose.
-    if (format == jpegFormat) {
-        format = HAL_PIXEL_FORMAT_BLOB;
-    }
-
-    return format;
-}
-
 static jint Image_getFormat(JNIEnv* env, jobject thiz) {
     ALOGV("%s", __FUNCTION__);
     GraphicBuffer* buffer;
@@ -704,7 +672,10 @@
         return 0;
     }
 
-    return Image_getPixelFormat(env, buffer->getPixelFormat());
+    // ImageWriter doesn't support data space yet, assuming it is unknown.
+    PublicFormat publicFmt = android_view_Surface_mapHalFormatDataspaceToPublicFormat(
+            buffer->getPixelFormat(), HAL_DATASPACE_UNKNOWN);
+    return static_cast<jint>(publicFmt);
 }
 
 static void Image_setFenceFd(JNIEnv* env, jobject thiz, int fenceFd) {
@@ -723,272 +694,34 @@
         return;
     }
 
-    void* pData = NULL;
-    android_ycbcr ycbcr = android_ycbcr();
-    status_t res;
-    int format = Image_getFormat(env, thiz);
-    int flexFormat = format;
-    if (isPossiblyYUV(format)) {
-        // ImageWriter doesn't use crop by itself, app sets it, use the no crop version.
-        res = buffer->lockAsyncYCbCr(GRALLOC_USAGE_SW_WRITE_OFTEN, &ycbcr, fenceFd);
-        // Clear the fenceFd as it is already consumed by lock call.
-        Image_setFenceFd(env, thiz, /*fenceFd*/-1);
-        if (res != OK) {
-            jniThrowRuntimeException(env, "lockAsyncYCbCr failed for YUV buffer");
-            return;
-        }
-        pData = ycbcr.y;
-        flexFormat = HAL_PIXEL_FORMAT_YCbCr_420_888;
+    // ImageWriter doesn't use crop by itself, app sets it, use the no crop version.
+    const Rect noCrop(buffer->width, buffer->height);
+    status_t res = lockImageFromBuffer(
+            buffer, GRALLOC_USAGE_SW_WRITE_OFTEN, noCrop, fenceFd, image);
+    // Clear the fenceFd as it is already consumed by lock call.
+    Image_setFenceFd(env, thiz, /*fenceFd*/-1);
+    if (res != OK) {
+        jniThrowExceptionFmt(env, "java/lang/RuntimeException",
+                "lock buffer failed for format 0x%x",
+                buffer->getPixelFormat());
+        return;
     }
 
-    // lockAsyncYCbCr for YUV is unsuccessful.
-    if (pData == NULL) {
-        res = buffer->lockAsync(GRALLOC_USAGE_SW_WRITE_OFTEN, &pData, fenceFd);
-        if (res != OK) {
-            jniThrowRuntimeException(env, "lockAsync failed");
-            return;
-        }
-    }
-
-    image->data = reinterpret_cast<uint8_t*>(pData);
-    image->width = buffer->getWidth();
-    image->height = buffer->getHeight();
-    image->format = format;
-    image->flexFormat = flexFormat;
-    image->stride = (ycbcr.y != NULL) ? static_cast<uint32_t>(ycbcr.ystride) : buffer->getStride();
-
-    image->dataCb = reinterpret_cast<uint8_t*>(ycbcr.cb);
-    image->dataCr = reinterpret_cast<uint8_t*>(ycbcr.cr);
-    image->chromaStride = static_cast<uint32_t>(ycbcr.cstride);
-    image->chromaStep = static_cast<uint32_t>(ycbcr.chroma_step);
-    ALOGV("Successfully locked the image");
+    ALOGV("%s: Successfully locked the image", __FUNCTION__);
     // crop, transform, scalingMode, timestamp, and frameNumber should be set by producer,
     // and we don't set them here.
 }
 
-static bool usingRGBAToJpegOverride(int32_t bufferFormat, int32_t writerCtxFormat) {
-    return writerCtxFormat == HAL_PIXEL_FORMAT_BLOB && bufferFormat == HAL_PIXEL_FORMAT_RGBA_8888;
-}
-
-static int32_t applyFormatOverrides(int32_t bufferFormat, int32_t writerCtxFormat)
-{
-    // Using HAL_PIXEL_FORMAT_RGBA_8888 gralloc buffers containing JPEGs to get around SW
-    // write limitations for some platforms (b/17379185).
-    if (usingRGBAToJpegOverride(bufferFormat, writerCtxFormat)) {
-        return HAL_PIXEL_FORMAT_BLOB;
-    }
-    return bufferFormat;
-}
-
-static uint32_t Image_getJpegSize(LockedImage* buffer, bool usingRGBAOverride) {
-    ALOGV("%s", __FUNCTION__);
-    ALOG_ASSERT(buffer != NULL, "Input buffer is NULL!!!");
-    uint32_t size = 0;
-    uint32_t width = buffer->width;
-    uint8_t* jpegBuffer = buffer->data;
-
-    if (usingRGBAOverride) {
-        width = (buffer->width + buffer->stride * (buffer->height - 1)) * 4;
-    }
-
-    // First check for JPEG transport header at the end of the buffer
-    uint8_t* header = jpegBuffer + (width - sizeof(struct camera3_jpeg_blob));
-    struct camera3_jpeg_blob *blob = (struct camera3_jpeg_blob*)(header);
-    if (blob->jpeg_blob_id == CAMERA3_JPEG_BLOB_ID) {
-        size = blob->jpeg_size;
-        ALOGV("%s: Jpeg size = %d", __FUNCTION__, size);
-    }
-
-    // failed to find size, default to whole buffer
-    if (size == 0) {
-        /*
-         * This is a problem because not including the JPEG header
-         * means that in certain rare situations a regular JPEG blob
-         * will be misidentified as having a header, in which case
-         * we will get a garbage size value.
-         */
-        ALOGW("%s: No JPEG header detected, defaulting to size=width=%d",
-                __FUNCTION__, width);
-        size = width;
-    }
-
-    return size;
-}
-
 static void Image_getLockedImageInfo(JNIEnv* env, LockedImage* buffer, int idx,
         int32_t writerFormat, uint8_t **base, uint32_t *size, int *pixelStride, int *rowStride) {
     ALOGV("%s", __FUNCTION__);
-    ALOG_ASSERT(buffer != NULL, "Input buffer is NULL!!!");
-    ALOG_ASSERT(base != NULL, "base is NULL!!!");
-    ALOG_ASSERT(size != NULL, "size is NULL!!!");
-    ALOG_ASSERT(pixelStride != NULL, "pixelStride is NULL!!!");
-    ALOG_ASSERT(rowStride != NULL, "rowStride is NULL!!!");
-    ALOG_ASSERT((idx < IMAGE_WRITER_MAX_NUM_PLANES) && (idx >= 0));
 
-    ALOGV("%s: buffer: %p", __FUNCTION__, buffer);
-
-    uint32_t dataSize, ySize, cSize, cStride;
-    uint32_t pStride = 0, rStride = 0;
-    uint8_t *cb, *cr;
-    uint8_t *pData = NULL;
-    int bytesPerPixel = 0;
-
-    dataSize = ySize = cSize = cStride = 0;
-    int32_t fmt = buffer->flexFormat;
-
-    bool usingRGBAOverride = usingRGBAToJpegOverride(fmt, writerFormat);
-    fmt = applyFormatOverrides(fmt, writerFormat);
-    switch (fmt) {
-        case HAL_PIXEL_FORMAT_YCbCr_420_888:
-            pData =
-                (idx == 0) ?
-                    buffer->data :
-                (idx == 1) ?
-                    buffer->dataCb :
-                buffer->dataCr;
-            // only map until last pixel
-            if (idx == 0) {
-                pStride = 1;
-                rStride = buffer->stride;
-                dataSize = buffer->stride * (buffer->height - 1) + buffer->width;
-            } else {
-                pStride = buffer->chromaStep;
-                rStride = buffer->chromaStride;
-                dataSize = buffer->chromaStride * (buffer->height / 2 - 1) +
-                        buffer->chromaStep * (buffer->width / 2 - 1) + 1;
-            }
-            break;
-        // NV21
-        case HAL_PIXEL_FORMAT_YCrCb_420_SP:
-            cr = buffer->data + (buffer->stride * buffer->height);
-            cb = cr + 1;
-            // only map until last pixel
-            ySize = buffer->width * (buffer->height - 1) + buffer->width;
-            cSize = buffer->width * (buffer->height / 2 - 1) + buffer->width - 1;
-
-            pData =
-                (idx == 0) ?
-                    buffer->data :
-                (idx == 1) ?
-                    cb:
-                cr;
-
-            dataSize = (idx == 0) ? ySize : cSize;
-            pStride = (idx == 0) ? 1 : 2;
-            rStride = buffer->width;
-            break;
-        case HAL_PIXEL_FORMAT_YV12:
-            // Y and C stride need to be 16 pixel aligned.
-            LOG_ALWAYS_FATAL_IF(buffer->stride % 16,
-                                "Stride is not 16 pixel aligned %d", buffer->stride);
-
-            ySize = buffer->stride * buffer->height;
-            cStride = ALIGN(buffer->stride / 2, 16);
-            cr = buffer->data + ySize;
-            cSize = cStride * buffer->height / 2;
-            cb = cr + cSize;
-
-            pData =
-                (idx == 0) ?
-                    buffer->data :
-                (idx == 1) ?
-                    cb :
-                cr;
-            dataSize = (idx == 0) ? ySize : cSize;
-            pStride = 1;
-            rStride = (idx == 0) ? buffer->stride : ALIGN(buffer->stride / 2, 16);
-            break;
-        case HAL_PIXEL_FORMAT_Y8:
-            // Single plane, 8bpp.
-            ALOG_ASSERT(idx == 0, "Wrong index: %d", idx);
-
-            pData = buffer->data;
-            dataSize = buffer->stride * buffer->height;
-            pStride = 1;
-            rStride = buffer->stride;
-            break;
-        case HAL_PIXEL_FORMAT_Y16:
-            bytesPerPixel = 2;
-            // Single plane, 16bpp, strides are specified in pixels, not in bytes
-            ALOG_ASSERT(idx == 0, "Wrong index: %d", idx);
-
-            pData = buffer->data;
-            dataSize = buffer->stride * buffer->height * bytesPerPixel;
-            pStride = bytesPerPixel;
-            rStride = buffer->stride * 2;
-            break;
-        case HAL_PIXEL_FORMAT_BLOB:
-            // Used for JPEG data, height must be 1, width == size, single plane.
-            ALOG_ASSERT(idx == 0, "Wrong index: %d", idx);
-            ALOG_ASSERT(buffer->height == 1, "JPEG should has height value %d", buffer->height);
-
-            pData = buffer->data;
-            dataSize = Image_getJpegSize(buffer, usingRGBAOverride);
-            pStride = bytesPerPixel;
-            rowStride = 0;
-            break;
-        case HAL_PIXEL_FORMAT_RAW16:
-            // Single plane 16bpp bayer data.
-            bytesPerPixel = 2;
-            ALOG_ASSERT(idx == 0, "Wrong index: %d", idx);
-            pData = buffer->data;
-            dataSize = buffer->stride * buffer->height * bytesPerPixel;
-            pStride = bytesPerPixel;
-            rStride = buffer->stride * 2;
-            break;
-        case HAL_PIXEL_FORMAT_RAW10:
-            // Single plane 10bpp bayer data.
-            ALOG_ASSERT(idx == 0, "Wrong index: %d", idx);
-            LOG_ALWAYS_FATAL_IF(buffer->width % 4,
-                                "Width is not multiple of 4 %d", buffer->width);
-            LOG_ALWAYS_FATAL_IF(buffer->height % 2,
-                                "Height is not even %d", buffer->height);
-            LOG_ALWAYS_FATAL_IF(buffer->stride < (buffer->width * 10 / 8),
-                                "stride (%d) should be at least %d",
-                                buffer->stride, buffer->width * 10 / 8);
-            pData = buffer->data;
-            dataSize = buffer->stride * buffer->height;
-            pStride = 0;
-            rStride = buffer->stride;
-            break;
-        case HAL_PIXEL_FORMAT_RGBA_8888:
-        case HAL_PIXEL_FORMAT_RGBX_8888:
-            // Single plane, 32bpp.
-            bytesPerPixel = 4;
-            ALOG_ASSERT(idx == 0, "Wrong index: %d", idx);
-            pData = buffer->data;
-            dataSize = buffer->stride * buffer->height * bytesPerPixel;
-            pStride = bytesPerPixel;
-            rStride = buffer->stride * 4;
-            break;
-        case HAL_PIXEL_FORMAT_RGB_565:
-            // Single plane, 16bpp.
-            bytesPerPixel = 2;
-            ALOG_ASSERT(idx == 0, "Wrong index: %d", idx);
-            pData = buffer->data;
-            dataSize = buffer->stride * buffer->height * bytesPerPixel;
-            pStride = bytesPerPixel;
-            rStride = buffer->stride * 2;
-            break;
-        case HAL_PIXEL_FORMAT_RGB_888:
-            // Single plane, 24bpp.
-            bytesPerPixel = 3;
-            ALOG_ASSERT(idx == 0, "Wrong index: %d", idx);
-            pData = buffer->data;
-            dataSize = buffer->stride * buffer->height * bytesPerPixel;
-            pStride = bytesPerPixel;
-            rStride = buffer->stride * 3;
-            break;
-        default:
-            jniThrowExceptionFmt(env, "java/lang/UnsupportedOperationException",
-                                 "Pixel format: 0x%x is unsupported", fmt);
-            break;
+    status_t res = getLockedImageInfo(buffer, idx, writerFormat, base, size,
+            pixelStride, rowStride);
+    if (res != OK) {
+        jniThrowExceptionFmt(env, "java/lang/UnsupportedOperationException",
+                             "Pixel format: 0x%x is unsupported", buffer->flexFormat);
     }
-
-    *base = pData;
-    *size = dataSize;
-    *pixelStride = pStride;
-    *rowStride = rStride;
 }
 
 static jobjectArray Image_createSurfacePlanes(JNIEnv* env, jobject thiz,
@@ -1024,7 +757,8 @@
     Image_getLockedImage(env, thiz, &lockedImg);
 
     // Create all SurfacePlanes
-    writerFormat = Image_getPixelFormat(env, writerFormat);
+    PublicFormat publicWriterFormat = static_cast<PublicFormat>(writerFormat);
+    writerFormat = android_view_Surface_mapPublicFormatToHalFormat(publicWriterFormat);
     for (int i = 0; i < numPlanes; i++) {
         Image_getLockedImageInfo(env, &lockedImg, i, writerFormat,
                 &pData, &dataSize, &pixelStride, &rowStride);
@@ -1044,39 +778,6 @@
     return surfacePlanes;
 }
 
-// -------------------------------Private convenience methods--------------------
-
-static bool isFormatOpaque(int format) {
-    // Only treat IMPLEMENTATION_DEFINED as an opaque format for now.
-    return format == HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED;
-}
-
-static bool isPossiblyYUV(PixelFormat format) {
-    switch (static_cast<int>(format)) {
-        case HAL_PIXEL_FORMAT_RGBA_8888:
-        case HAL_PIXEL_FORMAT_RGBX_8888:
-        case HAL_PIXEL_FORMAT_RGB_888:
-        case HAL_PIXEL_FORMAT_RGB_565:
-        case HAL_PIXEL_FORMAT_BGRA_8888:
-        case HAL_PIXEL_FORMAT_Y8:
-        case HAL_PIXEL_FORMAT_Y16:
-        case HAL_PIXEL_FORMAT_RAW16:
-        case HAL_PIXEL_FORMAT_RAW10:
-        case HAL_PIXEL_FORMAT_RAW_OPAQUE:
-        case HAL_PIXEL_FORMAT_BLOB:
-        case HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED:
-            return false;
-
-        case HAL_PIXEL_FORMAT_YV12:
-        case HAL_PIXEL_FORMAT_YCbCr_420_888:
-        case HAL_PIXEL_FORMAT_YCbCr_422_SP:
-        case HAL_PIXEL_FORMAT_YCrCb_420_SP:
-        case HAL_PIXEL_FORMAT_YCbCr_422_I:
-        default:
-            return true;
-    }
-}
-
 } // extern "C"
 
 // ----------------------------------------------------------------------------
diff --git a/media/jni/android_media_MediaCodec.cpp b/media/jni/android_media_MediaCodec.cpp
index 2004a3a..810996e 100644
--- a/media/jni/android_media_MediaCodec.cpp
+++ b/media/jni/android_media_MediaCodec.cpp
@@ -65,6 +65,7 @@
     jint cryptoErrorResourceBusy;
     jint cryptoErrorInsufficientOutputProtection;
     jint cryptoErrorSessionNotOpened;
+    jint cryptoErrorUnsupportedOperation;
 } gCryptoErrorCodes;
 
 static struct CodecActionCodes {
@@ -869,6 +870,10 @@
             err = gCryptoErrorCodes.cryptoErrorSessionNotOpened;
             defaultMsg = "Attempted to use a closed session";
             break;
+        case ERROR_DRM_CANNOT_HANDLE:
+            err = gCryptoErrorCodes.cryptoErrorUnsupportedOperation;
+            defaultMsg = "Operation not supported in this configuration";
+            break;
         default:  /* Other negative DRM error codes go out as is. */
             break;
     }
@@ -1302,7 +1307,10 @@
     jobject patternObj = env->GetObjectField(cryptoInfoObj, gFields.cryptoInfoPatternID);
 
     CryptoPlugin::Pattern pattern;
-    if (patternObj != NULL) {
+    if (patternObj == NULL) {
+        pattern.mEncryptBlocks = 0;
+        pattern.mSkipBlocks = 0;
+    } else {
         pattern.mEncryptBlocks = env->GetIntField(patternObj, gFields.patternEncryptBlocksID);
         pattern.mSkipBlocks = env->GetIntField(patternObj, gFields.patternSkipBlocksID);
     }
@@ -1770,6 +1778,11 @@
     gCryptoErrorCodes.cryptoErrorSessionNotOpened =
         env->GetStaticIntField(clazz.get(), field);
 
+    field = env->GetStaticFieldID(clazz.get(), "ERROR_UNSUPPORTED_OPERATION", "I");
+    CHECK(field != NULL);
+    gCryptoErrorCodes.cryptoErrorUnsupportedOperation =
+        env->GetStaticIntField(clazz.get(), field);
+
     clazz.reset(env->FindClass("android/media/MediaCodec$CodecException"));
     CHECK(clazz.get() != NULL);
     field = env->GetStaticFieldID(clazz.get(), "ACTION_TRANSIENT", "I");
diff --git a/media/jni/android_media_MediaDataSource.cpp b/media/jni/android_media_MediaDataSource.cpp
index 3b892cb..537b56d 100644
--- a/media/jni/android_media_MediaDataSource.cpp
+++ b/media/jni/android_media_MediaDataSource.cpp
@@ -116,7 +116,8 @@
         return UNKNOWN_ERROR;
     }
     if (mSizeIsCached) {
-        return mCachedSize;
+        *size = mCachedSize;
+        return OK;
     }
 
     JNIEnv* env = AndroidRuntime::getJNIEnv();
diff --git a/media/jni/android_media_MediaRecorder.cpp b/media/jni/android_media_MediaRecorder.cpp
index 701f7ac..922ad79 100644
--- a/media/jni/android_media_MediaRecorder.cpp
+++ b/media/jni/android_media_MediaRecorder.cpp
@@ -26,7 +26,6 @@
 #include <utils/Log.h>
 
 #include <gui/Surface.h>
-#include <camera/ICameraService.h>
 #include <camera/Camera.h>
 #include <media/mediarecorder.h>
 #include <media/stagefright/PersistentSurface.h>
diff --git a/media/jni/android_media_Utils.cpp b/media/jni/android_media_Utils.cpp
index 9c4f7c4..527e6c2 100644
--- a/media/jni/android_media_Utils.cpp
+++ b/media/jni/android_media_Utils.cpp
@@ -26,32 +26,82 @@
 
 #include <nativehelper/ScopedLocalRef.h>
 
+#define ALIGN(x, mask) ( ((x) + (mask) - 1) & ~((mask) - 1) )
+
 namespace android {
 
+AssetStream::AssetStream(SkStream* stream)
+    : mStream(stream) {
+}
+
+AssetStream::~AssetStream() {
+}
+
+piex::Error AssetStream::GetData(
+        const size_t offset, const size_t length, std::uint8_t* data) {
+    // Seek first.
+    if (mPosition != offset) {
+        if (!mStream->seek(offset)) {
+            return piex::Error::kFail;
+        }
+    }
+
+    // Read bytes.
+    size_t size = mStream->read((void*)data, length);
+    mPosition += size;
+
+    return size == length ? piex::Error::kOk : piex::Error::kFail;
+}
+
+BufferedStream::BufferedStream(SkStream* stream)
+    : mStream(stream) {
+}
+
+BufferedStream::~BufferedStream() {
+}
+
+piex::Error BufferedStream::GetData(
+        const size_t offset, const size_t length, std::uint8_t* data) {
+    // Seek first.
+    if (offset + length > mStreamBuffer.bytesWritten()) {
+        size_t sizeToRead = offset + length - mStreamBuffer.bytesWritten();
+        if (sizeToRead <= kMinSizeToRead) {
+            sizeToRead = kMinSizeToRead;
+        }
+        void* tempBuffer = malloc(sizeToRead);
+        if (tempBuffer != NULL) {
+            size_t bytesRead = mStream->read(tempBuffer, sizeToRead);
+            if (bytesRead != sizeToRead) {
+                free(tempBuffer);
+                return piex::Error::kFail;
+            }
+            mStreamBuffer.write(tempBuffer, bytesRead);
+            free(tempBuffer);
+        }
+    }
+
+    // Read bytes.
+    if (mStreamBuffer.read((void*)data, offset, length)) {
+        return piex::Error::kOk;
+    } else {
+        return piex::Error::kFail;
+    }
+}
+
 FileStream::FileStream(const int fd)
-    : mPosition(0),
-      mSize(0) {
+    : mPosition(0) {
     mFile = fdopen(fd, "r");
     if (mFile == NULL) {
         return;
     }
-    // Get the size.
-    fseek(mFile, 0l, SEEK_END);
-    mSize = ftell(mFile);
-    fseek(mFile, 0l, SEEK_SET);
 }
 
 FileStream::FileStream(const String8 filename)
-    : mPosition(0),
-      mSize(0) {
+    : mPosition(0) {
     mFile = fopen(filename.string(), "r");
     if (mFile == NULL) {
         return;
     }
-    // Get the size.
-    fseek(mFile, 0l, SEEK_END);
-    mSize = ftell(mFile);
-    fseek(mFile, 0l, SEEK_SET);
 }
 
 FileStream::~FileStream() {
@@ -77,7 +127,7 @@
     mPosition += size;
 
     // Handle errors.
-    if (ferror(mFile) || (size == 0 && feof(mFile))) {
+    if (ferror(mFile)) {
         ALOGV("GetData read failed: (offset: %zu, length: %zu)", offset, length);
         return piex::Error::kFail;
     }
@@ -88,21 +138,12 @@
     return mFile != NULL;
 }
 
-size_t FileStream::size() const {
-    return mSize;
-}
-
 bool GetExifFromRawImage(
-        FileStream* stream, const String8& filename, piex::PreviewImageData& image_data) {
+        piex::StreamInterface* stream, const String8& filename,
+        piex::PreviewImageData& image_data) {
     // Reset the PreviewImageData to its default.
     image_data = piex::PreviewImageData();
 
-    if (!stream->exists()) {
-        // File is not exists.
-        ALOGV("File is not exists: %s", filename.string());
-        return false;
-    }
-
     if (!piex::IsRaw(stream)) {
         // Format not supported.
         ALOGV("Format not supported: %s", filename.string());
@@ -117,12 +158,6 @@
         return false;
     }
 
-    if (image_data.thumbnail_offset + image_data.thumbnail_length > stream->size()) {
-        // Corrupted image.
-        ALOGV("Corrupted file: %s", filename.string());
-        return false;
-    }
-
     return true;
 }
 
@@ -509,5 +544,391 @@
     return OK;
 }
 
+// -----------Utility functions used by ImageReader/Writer JNI-----------------
+
+enum {
+    IMAGE_MAX_NUM_PLANES = 3,
+};
+
+bool usingRGBAToJpegOverride(int32_t imageFormat,
+        int32_t containerFormat) {
+    return containerFormat == HAL_PIXEL_FORMAT_BLOB && imageFormat == HAL_PIXEL_FORMAT_RGBA_8888;
+}
+
+int32_t applyFormatOverrides(int32_t imageFormat, int32_t containerFormat) {
+    // Using HAL_PIXEL_FORMAT_RGBA_8888 gralloc buffers containing JPEGs to get around SW
+    // write limitations for some platforms (b/17379185).
+    if (usingRGBAToJpegOverride(imageFormat, containerFormat)) {
+        return HAL_PIXEL_FORMAT_BLOB;
+    }
+    return containerFormat;
+}
+
+bool isFormatOpaque(int format) {
+    // This is the only opaque format exposed in the ImageFormat public API.
+    // Note that we do support CPU access for HAL_PIXEL_FORMAT_RAW_OPAQUE
+    // (ImageFormat#RAW_PRIVATE) so it doesn't count as opaque here.
+    return format == HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED;
+}
+
+bool isPossiblyYUV(PixelFormat format) {
+    switch (static_cast<int>(format)) {
+        case HAL_PIXEL_FORMAT_RGBA_8888:
+        case HAL_PIXEL_FORMAT_RGBX_8888:
+        case HAL_PIXEL_FORMAT_RGB_888:
+        case HAL_PIXEL_FORMAT_RGB_565:
+        case HAL_PIXEL_FORMAT_BGRA_8888:
+        case HAL_PIXEL_FORMAT_Y8:
+        case HAL_PIXEL_FORMAT_Y16:
+        case HAL_PIXEL_FORMAT_RAW16:
+        case HAL_PIXEL_FORMAT_RAW10:
+        case HAL_PIXEL_FORMAT_RAW_OPAQUE:
+        case HAL_PIXEL_FORMAT_BLOB:
+        case HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED:
+            return false;
+
+        case HAL_PIXEL_FORMAT_YV12:
+        case HAL_PIXEL_FORMAT_YCbCr_420_888:
+        case HAL_PIXEL_FORMAT_YCrCb_420_SP:
+        default:
+            return true;
+    }
+}
+
+uint32_t Image_getJpegSize(LockedImage* buffer, bool usingRGBAOverride) {
+    ALOGV("%s", __FUNCTION__);
+    LOG_ALWAYS_FATAL_IF(buffer == NULL, "Input buffer is NULL!!!");
+    uint32_t size = 0;
+    uint32_t width = buffer->width;
+    uint8_t* jpegBuffer = buffer->data;
+
+    if (usingRGBAOverride) {
+        width = (buffer->width + buffer->stride * (buffer->height - 1)) * 4;
+    }
+
+    // First check for JPEG transport header at the end of the buffer
+    uint8_t* header = jpegBuffer + (width - sizeof(struct camera3_jpeg_blob));
+    struct camera3_jpeg_blob *blob = (struct camera3_jpeg_blob*)(header);
+    if (blob->jpeg_blob_id == CAMERA3_JPEG_BLOB_ID) {
+        size = blob->jpeg_size;
+        ALOGV("%s: Jpeg size = %d", __FUNCTION__, size);
+    }
+
+    // failed to find size, default to whole buffer
+    if (size == 0) {
+        /*
+         * This is a problem because not including the JPEG header
+         * means that in certain rare situations a regular JPEG blob
+         * will be mis-identified as having a header, in which case
+         * we will get a garbage size value.
+         */
+        ALOGW("%s: No JPEG header detected, defaulting to size=width=%d",
+                __FUNCTION__, width);
+        size = width;
+    }
+
+    return size;
+}
+
+status_t getLockedImageInfo(LockedImage* buffer, int idx,
+        int32_t containerFormat, uint8_t **base, uint32_t *size, int *pixelStride, int *rowStride) {
+    ALOGV("%s", __FUNCTION__);
+    LOG_ALWAYS_FATAL_IF(buffer == NULL, "Input buffer is NULL!!!");
+    LOG_ALWAYS_FATAL_IF(base == NULL, "base is NULL!!!");
+    LOG_ALWAYS_FATAL_IF(size == NULL, "size is NULL!!!");
+    LOG_ALWAYS_FATAL_IF(pixelStride == NULL, "pixelStride is NULL!!!");
+    LOG_ALWAYS_FATAL_IF(rowStride == NULL, "rowStride is NULL!!!");
+    LOG_ALWAYS_FATAL_IF((idx >= IMAGE_MAX_NUM_PLANES) || (idx < 0), "idx (%d) is illegal", idx);
+
+    ALOGV("%s: buffer: %p", __FUNCTION__, buffer);
+
+    uint32_t dataSize, ySize, cSize, cStride;
+    uint32_t pStride = 0, rStride = 0;
+    uint8_t *cb, *cr;
+    uint8_t *pData = NULL;
+    int bytesPerPixel = 0;
+
+    dataSize = ySize = cSize = cStride = 0;
+    int32_t fmt = buffer->flexFormat;
+
+    bool usingRGBAOverride = usingRGBAToJpegOverride(fmt, containerFormat);
+    fmt = applyFormatOverrides(fmt, containerFormat);
+    switch (fmt) {
+        case HAL_PIXEL_FORMAT_YCbCr_420_888:
+            pData =
+                (idx == 0) ?
+                    buffer->data :
+                (idx == 1) ?
+                    buffer->dataCb :
+                buffer->dataCr;
+            // only map until last pixel
+            if (idx == 0) {
+                pStride = 1;
+                rStride = buffer->stride;
+                dataSize = buffer->stride * (buffer->height - 1) + buffer->width;
+            } else {
+                pStride = buffer->chromaStep;
+                rStride = buffer->chromaStride;
+                dataSize = buffer->chromaStride * (buffer->height / 2 - 1) +
+                        buffer->chromaStep * (buffer->width / 2 - 1) + 1;
+            }
+            break;
+        // NV21
+        case HAL_PIXEL_FORMAT_YCrCb_420_SP:
+            cr = buffer->data + (buffer->stride * buffer->height);
+            cb = cr + 1;
+            // only map until last pixel
+            ySize = buffer->width * (buffer->height - 1) + buffer->width;
+            cSize = buffer->width * (buffer->height / 2 - 1) + buffer->width - 1;
+
+            pData =
+                (idx == 0) ?
+                    buffer->data :
+                (idx == 1) ?
+                    cb:
+                cr;
+
+            dataSize = (idx == 0) ? ySize : cSize;
+            pStride = (idx == 0) ? 1 : 2;
+            rStride = buffer->width;
+            break;
+        case HAL_PIXEL_FORMAT_YV12:
+            // Y and C stride need to be 16 pixel aligned.
+            LOG_ALWAYS_FATAL_IF(buffer->stride % 16,
+                                "Stride is not 16 pixel aligned %d", buffer->stride);
+
+            ySize = buffer->stride * buffer->height;
+            cStride = ALIGN(buffer->stride / 2, 16);
+            cr = buffer->data + ySize;
+            cSize = cStride * buffer->height / 2;
+            cb = cr + cSize;
+
+            pData =
+                (idx == 0) ?
+                    buffer->data :
+                (idx == 1) ?
+                    cb :
+                cr;
+            dataSize = (idx == 0) ? ySize : cSize;
+            pStride = 1;
+            rStride = (idx == 0) ? buffer->stride : ALIGN(buffer->stride / 2, 16);
+            break;
+        case HAL_PIXEL_FORMAT_Y8:
+            // Single plane, 8bpp.
+            LOG_ALWAYS_FATAL_IF(idx != 0, "Wrong index: %d", idx);
+
+            pData = buffer->data;
+            dataSize = buffer->stride * buffer->height;
+            pStride = 1;
+            rStride = buffer->stride;
+            break;
+        case HAL_PIXEL_FORMAT_Y16:
+            bytesPerPixel = 2;
+            // Single plane, 16bpp, strides are specified in pixels, not in bytes
+            LOG_ALWAYS_FATAL_IF(idx != 0, "Wrong index: %d", idx);
+
+            pData = buffer->data;
+            dataSize = buffer->stride * buffer->height * bytesPerPixel;
+            pStride = bytesPerPixel;
+            rStride = buffer->stride * 2;
+            break;
+        case HAL_PIXEL_FORMAT_BLOB:
+            // Used for JPEG data, height must be 1, width == size, single plane.
+            LOG_ALWAYS_FATAL_IF(idx != 0, "Wrong index: %d", idx);
+            LOG_ALWAYS_FATAL_IF(buffer->height != 1,
+                    "BLOB format buffer should has height value %d", buffer->height);
+
+            pData = buffer->data;
+            dataSize = Image_getJpegSize(buffer, usingRGBAOverride);
+            pStride = 0;
+            rStride = 0;
+            break;
+        case HAL_PIXEL_FORMAT_RAW16:
+            // Single plane 16bpp bayer data.
+            bytesPerPixel = 2;
+            LOG_ALWAYS_FATAL_IF(idx != 0, "Wrong index: %d", idx);
+            pData = buffer->data;
+            dataSize = buffer->stride * buffer->height * bytesPerPixel;
+            pStride = bytesPerPixel;
+            rStride = buffer->stride * 2;
+            break;
+        case HAL_PIXEL_FORMAT_RAW_OPAQUE:
+            // Used for RAW_OPAQUE data, height must be 1, width == size, single plane.
+            LOG_ALWAYS_FATAL_IF(idx != 0, "Wrong index: %d", idx);
+            LOG_ALWAYS_FATAL_IF(buffer->height != 1,
+                    "RAW_PRIVATE should has height value one but got %d", buffer->height);
+            pData = buffer->data;
+            dataSize = buffer->width;
+            pStride = 0; // RAW OPAQUE doesn't have pixel stride
+            rStride = 0; // RAW OPAQUE doesn't have row stride
+            break;
+        case HAL_PIXEL_FORMAT_RAW10:
+            // Single plane 10bpp bayer data.
+            LOG_ALWAYS_FATAL_IF(idx != 0, "Wrong index: %d", idx);
+            LOG_ALWAYS_FATAL_IF(buffer->width % 4,
+                                "Width is not multiple of 4 %d", buffer->width);
+            LOG_ALWAYS_FATAL_IF(buffer->height % 2,
+                                "Height is not even %d", buffer->height);
+            LOG_ALWAYS_FATAL_IF(buffer->stride < (buffer->width * 10 / 8),
+                                "stride (%d) should be at least %d",
+                                buffer->stride, buffer->width * 10 / 8);
+            pData = buffer->data;
+            dataSize = buffer->stride * buffer->height;
+            pStride = 0;
+            rStride = buffer->stride;
+            break;
+        case HAL_PIXEL_FORMAT_RAW12:
+            // Single plane 10bpp bayer data.
+            LOG_ALWAYS_FATAL_IF(idx != 0, "Wrong index: %d", idx);
+            LOG_ALWAYS_FATAL_IF(buffer->width % 4,
+                                "Width is not multiple of 4 %d", buffer->width);
+            LOG_ALWAYS_FATAL_IF(buffer->height % 2,
+                                "Height is not even %d", buffer->height);
+            LOG_ALWAYS_FATAL_IF(buffer->stride < (buffer->width * 12 / 8),
+                                "stride (%d) should be at least %d",
+                                buffer->stride, buffer->width * 12 / 8);
+            pData = buffer->data;
+            dataSize = buffer->stride * buffer->height;
+            pStride = 0;
+            rStride = buffer->stride;
+            break;
+        case HAL_PIXEL_FORMAT_RGBA_8888:
+        case HAL_PIXEL_FORMAT_RGBX_8888:
+            // Single plane, 32bpp.
+            bytesPerPixel = 4;
+            LOG_ALWAYS_FATAL_IF(idx != 0, "Wrong index: %d", idx);
+            pData = buffer->data;
+            dataSize = buffer->stride * buffer->height * bytesPerPixel;
+            pStride = bytesPerPixel;
+            rStride = buffer->stride * 4;
+            break;
+        case HAL_PIXEL_FORMAT_RGB_565:
+            // Single plane, 16bpp.
+            bytesPerPixel = 2;
+            LOG_ALWAYS_FATAL_IF(idx != 0, "Wrong index: %d", idx);
+            pData = buffer->data;
+            dataSize = buffer->stride * buffer->height * bytesPerPixel;
+            pStride = bytesPerPixel;
+            rStride = buffer->stride * 2;
+            break;
+        case HAL_PIXEL_FORMAT_RGB_888:
+            // Single plane, 24bpp.
+            bytesPerPixel = 3;
+            LOG_ALWAYS_FATAL_IF(idx != 0, "Wrong index: %d", idx);
+            pData = buffer->data;
+            dataSize = buffer->stride * buffer->height * bytesPerPixel;
+            pStride = bytesPerPixel;
+            rStride = buffer->stride * 3;
+            break;
+        default:
+            return BAD_VALUE;
+    }
+
+    *base = pData;
+    *size = dataSize;
+    *pixelStride = pStride;
+    *rowStride = rStride;
+
+    return OK;
+}
+
+status_t lockImageFromBuffer(sp<GraphicBuffer> buffer, uint32_t inUsage,
+        const Rect& rect, int fenceFd, LockedImage* outputImage) {
+    ALOGV("%s: Try to lock the GraphicBuffer", __FUNCTION__);
+
+    if (buffer == nullptr || outputImage == nullptr) {
+        ALOGE("Input BufferItem or output LockedImage is NULL!");
+        return BAD_VALUE;
+    }
+    if (isFormatOpaque(buffer->getPixelFormat())) {
+        ALOGE("Opaque format buffer is not lockable!");
+        return BAD_VALUE;
+    }
+
+    void* pData = NULL;
+    android_ycbcr ycbcr = android_ycbcr();
+    status_t res;
+    int format = buffer->getPixelFormat();
+    int flexFormat = format;
+    if (isPossiblyYUV(format)) {
+        res = buffer->lockAsyncYCbCr(inUsage, rect, &ycbcr, fenceFd);
+        pData = ycbcr.y;
+        flexFormat = HAL_PIXEL_FORMAT_YCbCr_420_888;
+    }
+
+    // lockAsyncYCbCr for YUV is unsuccessful.
+    if (pData == NULL) {
+        res = buffer->lockAsync(inUsage, rect, &pData, fenceFd);
+        if (res != OK) {
+            ALOGE("Lock buffer failed!");
+            return res;
+        }
+    }
+
+    outputImage->data = reinterpret_cast<uint8_t*>(pData);
+    outputImage->width = buffer->getWidth();
+    outputImage->height = buffer->getHeight();
+    outputImage->format = format;
+    outputImage->flexFormat = flexFormat;
+    outputImage->stride =
+            (ycbcr.y != NULL) ? static_cast<uint32_t>(ycbcr.ystride) : buffer->getStride();
+
+    outputImage->dataCb = reinterpret_cast<uint8_t*>(ycbcr.cb);
+    outputImage->dataCr = reinterpret_cast<uint8_t*>(ycbcr.cr);
+    outputImage->chromaStride = static_cast<uint32_t>(ycbcr.cstride);
+    outputImage->chromaStep = static_cast<uint32_t>(ycbcr.chroma_step);
+    ALOGV("%s: Successfully locked the image from the GraphicBuffer", __FUNCTION__);
+    // Crop, transform, scalingMode, timestamp, and frameNumber should be set by caller,
+    // and cann't be set them here.
+    return OK;
+}
+
+status_t lockImageFromBuffer(BufferItem* bufferItem, uint32_t inUsage,
+        int fenceFd, LockedImage* outputImage) {
+    ALOGV("%s: Try to lock the BufferItem", __FUNCTION__);
+    if (bufferItem == nullptr || outputImage == nullptr) {
+        ALOGE("Input BufferItem or output LockedImage is NULL!");
+        return BAD_VALUE;
+    }
+
+    status_t res = lockImageFromBuffer(bufferItem->mGraphicBuffer, inUsage, bufferItem->mCrop,
+            fenceFd, outputImage);
+    if (res != OK) {
+        ALOGE("%s: lock graphic buffer failed", __FUNCTION__);
+        return res;
+    }
+
+    outputImage->crop        = bufferItem->mCrop;
+    outputImage->transform   = bufferItem->mTransform;
+    outputImage->scalingMode = bufferItem->mScalingMode;
+    outputImage->timestamp   = bufferItem->mTimestamp;
+    outputImage->dataSpace   = bufferItem->mDataSpace;
+    outputImage->frameNumber = bufferItem->mFrameNumber;
+    ALOGV("%s: Successfully locked the image from the BufferItem", __FUNCTION__);
+    return OK;
+}
+
+int getBufferWidth(BufferItem* buffer) {
+    if (buffer == NULL) return -1;
+
+    if (!buffer->mCrop.isEmpty()) {
+        return buffer->mCrop.getWidth();
+    }
+
+    ALOGV("%s: buffer->mGraphicBuffer: %p", __FUNCTION__, buffer->mGraphicBuffer.get());
+    return buffer->mGraphicBuffer->getWidth();
+}
+
+int getBufferHeight(BufferItem* buffer) {
+    if (buffer == NULL) return -1;
+
+    if (!buffer->mCrop.isEmpty()) {
+        return buffer->mCrop.getHeight();
+    }
+
+    ALOGV("%s: buffer->mGraphicBuffer: %p", __FUNCTION__, buffer->mGraphicBuffer.get());
+    return buffer->mGraphicBuffer->getHeight();
+}
+
 }  // namespace android
 
diff --git a/media/jni/android_media_Utils.h b/media/jni/android_media_Utils.h
index a30e1be..8184f94 100644
--- a/media/jni/android_media_Utils.h
+++ b/media/jni/android_media_Utils.h
@@ -21,18 +21,62 @@
 #include "src/piex.h"
 
 #include <android_runtime/AndroidRuntime.h>
+#include <camera3.h>
+#include <gui/CpuConsumer.h>
 #include <jni.h>
 #include <JNIHelp.h>
 #include <utils/KeyedVector.h>
 #include <utils/String8.h>
+#include <SkStream.h>
 
 namespace android {
 
+class AssetStream : public piex::StreamInterface {
+private:
+    SkStream *mStream;
+    size_t mPosition;
+
+public:
+    AssetStream(SkStream* stream);
+    ~AssetStream();
+
+    // Reads 'length' amount of bytes from 'offset' to 'data'. The 'data' buffer
+    // provided by the caller, guaranteed to be at least "length" bytes long.
+    // On 'kOk' the 'data' pointer contains 'length' valid bytes beginning at
+    // 'offset' bytes from the start of the stream.
+    // Returns 'kFail' if 'offset' + 'length' exceeds the stream and does not
+    // change the contents of 'data'.
+    piex::Error GetData(
+            const size_t offset, const size_t length, std::uint8_t* data) override;
+};
+
+class BufferedStream : public piex::StreamInterface {
+private:
+    SkStream *mStream;
+    // Growable memory stream
+    SkDynamicMemoryWStream mStreamBuffer;
+
+    // Minimum size to read on filling the buffer.
+    const size_t kMinSizeToRead = 8192;
+
+public:
+    BufferedStream(SkStream* stream);
+    ~BufferedStream();
+
+    // Reads 'length' amount of bytes from 'offset' to 'data'. The 'data' buffer
+    // provided by the caller, guaranteed to be at least "length" bytes long.
+    // On 'kOk' the 'data' pointer contains 'length' valid bytes beginning at
+    // 'offset' bytes from the start of the stream.
+    // Returns 'kFail' if 'offset' + 'length' exceeds the stream and does not
+    // change the contents of 'data'.
+    piex::Error GetData(
+            const size_t offset, const size_t length, std::uint8_t* data) override;
+};
+
 class FileStream : public piex::StreamInterface {
 private:
     FILE *mFile;
     size_t mPosition;
-    size_t mSize;
 
 public:
     FileStream(const int fd);
@@ -48,13 +92,12 @@
     piex::Error GetData(
             const size_t offset, const size_t length, std::uint8_t* data) override;
     bool exists() const;
-    size_t size() const;
 };
 
 // Reads EXIF metadata from a given raw image via piex.
 // And returns true if the operation is successful; otherwise, false.
 bool GetExifFromRawImage(
-        FileStream* stream, const String8& filename, piex::PreviewImageData& image_data);
+        piex::StreamInterface* stream, const String8& filename, piex::PreviewImageData& image_data);
 
 // Returns true if the conversion is successful; otherwise, false.
 bool ConvertKeyValueArraysToKeyedVector(
@@ -69,6 +112,33 @@
         JNIEnv *env, jobjectArray keys, jobjectArray values,
         sp<AMessage> *msg);
 
+// -----------Utility functions used by ImageReader/Writer JNI-----------------
+
+typedef CpuConsumer::LockedBuffer LockedImage;
+
+bool usingRGBAToJpegOverride(int32_t imageFormat, int32_t containerFormat);
+
+int32_t applyFormatOverrides(int32_t imageFormat, int32_t containerFormat);
+
+uint32_t Image_getJpegSize(LockedImage* buffer, bool usingRGBAOverride);
+
+bool isFormatOpaque(int format);
+
+bool isPossiblyYUV(PixelFormat format);
+
+status_t getLockedImageInfo(LockedImage* buffer, int idx, int32_t containerFormat,
+        uint8_t **base, uint32_t *size, int *pixelStride, int *rowStride);
+
+status_t lockImageFromBuffer(sp<GraphicBuffer> buffer, uint32_t inUsage,
+        const Rect& rect, int fenceFd, LockedImage* outputImage);
+
+status_t lockImageFromBuffer(BufferItem* bufferItem, uint32_t inUsage,
+        int fenceFd, LockedImage* outputImage);
+
+int getBufferWidth(BufferItem *buffer);
+
+int getBufferHeight(BufferItem *buffer);
+
 };  // namespace android
 
 #endif //  _ANDROID_MEDIA_UTILS_H_
diff --git a/media/jni/android_mtp_MtpDatabase.cpp b/media/jni/android_mtp_MtpDatabase.cpp
index 556f2c7..5722cb0 100644
--- a/media/jni/android_mtp_MtpDatabase.cpp
+++ b/media/jni/android_mtp_MtpDatabase.cpp
@@ -231,11 +231,11 @@
 }
 
 MtpObjectHandle MyMtpDatabase::beginSendObject(const char* path,
-                                            MtpObjectFormat format,
-                                            MtpObjectHandle parent,
-                                            MtpStorageID storage,
-                                            uint64_t size,
-                                            time_t modified) {
+                                               MtpObjectFormat format,
+                                               MtpObjectHandle parent,
+                                               MtpStorageID storage,
+                                               uint64_t size,
+                                               time_t modified) {
     JNIEnv* env = AndroidRuntime::getJNIEnv();
     jstring pathStr = env->NewStringUTF(path);
     MtpObjectHandle result = env->CallIntMethod(mDatabase, method_beginSendObject,
@@ -249,7 +249,7 @@
 }
 
 void MyMtpDatabase::endSendObject(const char* path, MtpObjectHandle handle,
-                                MtpObjectFormat format, bool succeeded) {
+                                  MtpObjectFormat format, bool succeeded) {
     JNIEnv* env = AndroidRuntime::getJNIEnv();
     jstring pathStr = env->NewStringUTF(path);
     env->CallVoidMethod(mDatabase, method_endSendObject, pathStr,
@@ -261,8 +261,8 @@
 }
 
 MtpObjectHandleList* MyMtpDatabase::getObjectList(MtpStorageID storageID,
-                                    MtpObjectFormat format,
-                                    MtpObjectHandle parent) {
+                                                  MtpObjectFormat format,
+                                                  MtpObjectHandle parent) {
     JNIEnv* env = AndroidRuntime::getJNIEnv();
     jintArray array = (jintArray)env->CallObjectMethod(mDatabase, method_getObjectList,
                 (jint)storageID, (jint)format, (jint)parent);
@@ -281,8 +281,8 @@
 }
 
 int MyMtpDatabase::getNumObjects(MtpStorageID storageID,
-                                MtpObjectFormat format,
-                                MtpObjectHandle parent) {
+                                 MtpObjectFormat format,
+                                 MtpObjectHandle parent) {
     JNIEnv* env = AndroidRuntime::getJNIEnv();
     int result = env->CallIntMethod(mDatabase, method_getNumObjects,
                 (jint)storageID, (jint)format, (jint)parent);
@@ -364,11 +364,21 @@
 }
 
 MtpResponseCode MyMtpDatabase::getObjectPropertyValue(MtpObjectHandle handle,
-                                            MtpObjectProperty property,
-                                            MtpDataPacket& packet) {
+                                                      MtpObjectProperty property,
+                                                      MtpDataPacket& packet) {
+    static_assert(sizeof(jint) >= sizeof(MtpObjectHandle),
+                  "Casting MtpObjectHandle to jint loses a value");
+    static_assert(sizeof(jint) >= sizeof(MtpObjectProperty),
+                  "Casting MtpObjectProperty to jint loses a value");
     JNIEnv* env = AndroidRuntime::getJNIEnv();
-    jobject list = env->CallObjectMethod(mDatabase, method_getObjectPropertyList,
-                (jlong)handle, 0, (jlong)property, 0, 0);
+    jobject list = env->CallObjectMethod(
+            mDatabase,
+            method_getObjectPropertyList,
+            static_cast<jint>(handle),
+            0,
+            static_cast<jint>(property),
+            0,
+            0);
     MtpResponseCode result = env->GetIntField(list, field_mResult);
     int count = env->GetIntField(list, field_mCount);
     if (result == MTP_RESPONSE_OK && count != 1)
@@ -532,8 +542,8 @@
 }
 
 MtpResponseCode MyMtpDatabase::setObjectPropertyValue(MtpObjectHandle handle,
-                                            MtpObjectProperty property,
-                                            MtpDataPacket& packet) {
+                                                      MtpObjectProperty property,
+                                                      MtpDataPacket& packet) {
     int         type;
 
     if (!getObjectPropertyInfo(property, type))
@@ -563,7 +573,7 @@
 }
 
 MtpResponseCode MyMtpDatabase::getDevicePropertyValue(MtpDeviceProperty property,
-                                            MtpDataPacket& packet) {
+                                                      MtpDataPacket& packet) {
     JNIEnv* env = AndroidRuntime::getJNIEnv();
 
     if (property == MTP_DEVICE_PROPERTY_BATTERY_LEVEL) {
@@ -636,7 +646,7 @@
 }
 
 MtpResponseCode MyMtpDatabase::setDevicePropertyValue(MtpDeviceProperty property,
-                                            MtpDataPacket& packet) {
+                                                      MtpDataPacket& packet) {
     int         type;
 
     if (!getDevicePropertyInfo(property, type))
@@ -670,12 +680,20 @@
 }
 
 MtpResponseCode MyMtpDatabase::getObjectPropertyList(MtpObjectHandle handle,
-                                            uint32_t format, uint32_t property,
-                                            int groupCode, int depth,
-                                            MtpDataPacket& packet) {
+                                                     uint32_t format, uint32_t property,
+                                                     int groupCode, int depth,
+                                                     MtpDataPacket& packet) {
+    static_assert(sizeof(jint) >= sizeof(MtpObjectHandle),
+                  "Casting MtpObjectHandle to jint loses a value");
     JNIEnv* env = AndroidRuntime::getJNIEnv();
-    jobject list = env->CallObjectMethod(mDatabase, method_getObjectPropertyList,
-                (jlong)handle, (jint)format, (jlong)property, (jint)groupCode, (jint)depth);
+    jobject list = env->CallObjectMethod(
+            mDatabase,
+            method_getObjectPropertyList,
+            static_cast<jint>(handle),
+            static_cast<jint>(format),
+            static_cast<jint>(property),
+            static_cast<jint>(groupCode),
+            static_cast<jint>(depth));
     checkAndClearExceptionFromCallback(env, __FUNCTION__);
     if (!list)
         return MTP_RESPONSE_GENERAL_ERROR;
@@ -787,7 +805,7 @@
 }
 
 MtpResponseCode MyMtpDatabase::getObjectInfo(MtpObjectHandle handle,
-                                            MtpObjectInfo& info) {
+                                             MtpObjectInfo& info) {
     MtpString       path;
     int64_t         length;
     MtpObjectFormat format;
@@ -940,9 +958,9 @@
 }
 
 MtpResponseCode MyMtpDatabase::getObjectFilePath(MtpObjectHandle handle,
-                                            MtpString& outFilePath,
-                                            int64_t& outFileLength,
-                                            MtpObjectFormat& outFormat) {
+                                                 MtpString& outFilePath,
+                                                 int64_t& outFileLength,
+                                                 MtpObjectFormat& outFormat) {
     JNIEnv* env = AndroidRuntime::getJNIEnv();
     jint result = env->CallIntMethod(mDatabase, method_getObjectFilePath,
                 (jint)handle, mStringBuffer, mLongBuffer);
@@ -1056,7 +1074,7 @@
 }
 
 MtpResponseCode MyMtpDatabase::setObjectReferences(MtpObjectHandle handle,
-                                                    MtpObjectHandleList* references) {
+                                                   MtpObjectHandleList* references) {
     JNIEnv* env = AndroidRuntime::getJNIEnv();
     int count = references->size();
     jintArray array = env->NewIntArray(count);
@@ -1077,7 +1095,7 @@
 }
 
 MtpProperty* MyMtpDatabase::getObjectPropertyDesc(MtpObjectProperty property,
-                                            MtpObjectFormat format) {
+                                                  MtpObjectFormat format) {
     static const int channelEnum[] = {
                                         1,  // mono
                                         2,  // stereo
@@ -1313,7 +1331,7 @@
         return -1;
     }
     method_getObjectPropertyList = env->GetMethodID(clazz, "getObjectPropertyList",
-            "(JIJII)Landroid/mtp/MtpPropertyList;");
+            "(IIIII)Landroid/mtp/MtpPropertyList;");
     if (method_getObjectPropertyList == NULL) {
         ALOGE("Can't find getObjectPropertyList");
         return -1;
diff --git a/media/tests/MediaFrameworkTest/Android.mk b/media/tests/MediaFrameworkTest/Android.mk
index 7c1142b..7e438a1 100644
--- a/media/tests/MediaFrameworkTest/Android.mk
+++ b/media/tests/MediaFrameworkTest/Android.mk
@@ -11,7 +11,6 @@
 
 LOCAL_STATIC_JAVA_LIBRARIES := easymocklib \
     mockito-target \
-    core-tests \
     android-support-test \
     android-ex-camera2
 
diff --git a/media/tests/MediaFrameworkTest/assets/image_exif_byte_order_ii.jpg b/media/tests/MediaFrameworkTest/assets/image_exif_byte_order_ii.jpg
new file mode 100644
index 0000000..477cd3a
--- /dev/null
+++ b/media/tests/MediaFrameworkTest/assets/image_exif_byte_order_ii.jpg
Binary files differ
diff --git a/media/tests/MediaFrameworkTest/assets/image_exif_byte_order_mm.jpg b/media/tests/MediaFrameworkTest/assets/image_exif_byte_order_mm.jpg
new file mode 100644
index 0000000..78ac703
--- /dev/null
+++ b/media/tests/MediaFrameworkTest/assets/image_exif_byte_order_mm.jpg
Binary files differ
diff --git a/media/tests/MediaFrameworkTest/assets/lg_g4_iso_800.dng b/media/tests/MediaFrameworkTest/assets/lg_g4_iso_800.dng
new file mode 100644
index 0000000..5fcc720
--- /dev/null
+++ b/media/tests/MediaFrameworkTest/assets/lg_g4_iso_800.dng
Binary files differ
diff --git a/media/tests/MediaFrameworkTest/assets/volantis.jpg b/media/tests/MediaFrameworkTest/assets/volantis.jpg
new file mode 100644
index 0000000..cfe300f
--- /dev/null
+++ b/media/tests/MediaFrameworkTest/assets/volantis.jpg
Binary files differ
diff --git a/media/tests/MediaFrameworkTest/res/raw/volantis.jpg b/media/tests/MediaFrameworkTest/res/raw/volantis.jpg
new file mode 100644
index 0000000..cfe300f
--- /dev/null
+++ b/media/tests/MediaFrameworkTest/res/raw/volantis.jpg
Binary files differ
diff --git a/media/tests/MediaFrameworkTest/res/values/exifinterface.xml b/media/tests/MediaFrameworkTest/res/values/exifinterface.xml
index 8fc6adc..d556ad3 100644
--- a/media/tests/MediaFrameworkTest/res/values/exifinterface.xml
+++ b/media/tests/MediaFrameworkTest/res/values/exifinterface.xml
@@ -76,9 +76,9 @@
         <item>0</item>
     </array>
     <array name="lg_g4_iso_800_dng">
-        <item>false</item>
-        <item>0</item>
-        <item>0</item>
+        <item>true</item>
+        <item>256</item>
+        <item>144</item>
         <item>true</item>
         <item>53.834507</item>
         <item>10.69585</item>
@@ -105,4 +105,34 @@
         <item>1</item>
         <item />
     </array>
+    <array name="volantis_jpg">
+        <item>false</item>
+        <item>0</item>
+        <item>0</item>
+        <item>true</item>
+        <item>37.423</item>
+        <item>-122.162</item>
+        <item>0.0</item>
+        <item>htc</item>
+        <item>Nexus 9</item>
+        <item>1.2904</item>
+        <item>2016:03:09 17:36:42</item>
+        <item>0.0083</item>
+        <item>64</item>
+        <item>3097/1000</item>
+        <item />
+        <item />
+        <item>2016:03:09</item>
+        <item>37/1,25/1,2291/100</item>
+        <item>N</item>
+        <item>122/1,9/1,4330/100</item>
+        <item>W</item>
+        <item />
+        <item>08:35:34</item>
+        <item>720</item>
+        <item>1280</item>
+        <item>175</item>
+        <item>1</item>
+        <item>0</item>
+    </array>
 </resources>
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaFrameworkUnitTestRunner.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaFrameworkUnitTestRunner.java
index 61dede3..9be7004 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaFrameworkUnitTestRunner.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaFrameworkUnitTestRunner.java
@@ -60,10 +60,7 @@
     }
 
     private void addCameraUnitTests(TestSuite suite) {
-        suite.addTestSuite(CameraUtilsDecoratorTest.class);
-        suite.addTestSuite(CameraUtilsRuntimeExceptionTest.class);
         suite.addTestSuite(CameraUtilsUncheckedThrowTest.class);
-        suite.addTestSuite(CameraUtilsBinderDecoratorTest.class);
         suite.addTestSuite(CameraUtilsTypeReferenceTest.class);
         suite.addTestSuite(CameraMetadataTest.class);
     }
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraBinderTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraBinderTest.java
index 6f74203..9a0946e 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraBinderTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraBinderTest.java
@@ -19,16 +19,16 @@
 import android.hardware.CameraInfo;
 import android.hardware.ICamera;
 import android.hardware.ICameraClient;
+import android.hardware.ICameraService;
 import android.hardware.ICameraServiceListener;
 import android.hardware.camera2.ICameraDeviceCallbacks;
 import android.hardware.camera2.ICameraDeviceUser;
 import android.hardware.camera2.impl.CameraMetadataNative;
 import android.hardware.camera2.impl.CaptureResultExtras;
-import android.hardware.camera2.utils.BinderHolder;
-import android.hardware.camera2.utils.CameraBinderDecorator;
 import android.os.Binder;
 import android.os.IBinder;
 import android.os.RemoteException;
+import android.os.ServiceSpecificException;
 import android.test.AndroidTestCase;
 import android.test.suitebuilder.annotation.SmallTest;
 import android.util.Log;
@@ -84,14 +84,7 @@
     public void testCameraInfo() throws Exception {
         for (int cameraId = 0; cameraId < mUtils.getGuessedNumCameras(); ++cameraId) {
 
-            CameraInfo info = new CameraInfo();
-            info.info.facing = -1;
-            info.info.orientation = -1;
-
-            assertTrue(
-                    "Camera service returned info for camera " + cameraId,
-                    mUtils.getCameraService().getCameraInfo(cameraId, info) ==
-                    CameraBinderTestUtils.NO_ERROR);
+            CameraInfo info = mUtils.getCameraService().getCameraInfo(cameraId);
             assertTrue("Facing was not set for camera " + cameraId, info.info.facing != -1);
             assertTrue("Orientation was not set for camera " + cameraId,
                     info.info.orientation != -1);
@@ -105,20 +98,17 @@
     public void testGetLegacyParameters() throws Exception {
         for (int cameraId = 0; cameraId < mUtils.getGuessedNumCameras(); ++cameraId) {
 
-            String[] parameters = new String[1];
-            assertEquals("Camera service returned parameters for camera " + cameraId,
-                    CameraBinderTestUtils.NO_ERROR,
-                    mUtils.getCameraService().getLegacyParameters(cameraId, /*out*/parameters));
-            assertNotNull(parameters[0]);
+            String parameters = mUtils.getCameraService().getLegacyParameters(cameraId);
+            assertNotNull(parameters);
             assertTrue("Parameters should have at least one character in it",
-                    parameters[0].length() > 0);
+                    parameters.length() > 0);
 
-            int end = parameters[0].length();
+            int end = parameters.length();
             if (end > MAX_PARAMETERS_LENGTH) {
                 end = MAX_PARAMETERS_LENGTH;
             }
 
-            Log.v(TAG, "Camera " + cameraId + " parameters: " + parameters[0].substring(0, end));
+            Log.v(TAG, "Camera " + cameraId + " parameters: " + parameters.substring(0, end));
         }
     }
 
@@ -127,14 +117,8 @@
     public void testSupportsCamera2Api() throws Exception {
         for (int cameraId = 0; cameraId < mUtils.getGuessedNumCameras(); ++cameraId) {
 
-            int res = mUtils.getCameraService().supportsCameraApi(cameraId, API_VERSION_2);
+            boolean supports = mUtils.getCameraService().supportsCameraApi(cameraId, API_VERSION_2);
 
-            if (res != CameraBinderTestUtils.NO_ERROR && res != -android.system.OsConstants.EOPNOTSUPP) {
-                fail("Camera service returned bad value when queried if it supports camera2 api: "
-                        + res + " for camera ID " + cameraId);
-            }
-
-            boolean supports = res == CameraBinderTestUtils.NO_ERROR;
             Log.v(TAG, "Camera " + cameraId + " supports api2: " + supports);
         }
     }
@@ -144,10 +128,10 @@
     public void testSupportsCamera1Api() throws Exception {
         for (int cameraId = 0; cameraId < mUtils.getGuessedNumCameras(); ++cameraId) {
 
-            int res = mUtils.getCameraService().supportsCameraApi(cameraId, API_VERSION_1);
-            assertEquals(
-                    "Camera service returned bad value when queried if it supports camera1 api: "
-                    + res + " for camera ID " + cameraId, CameraBinderTestUtils.NO_ERROR, res);
+            boolean supports = mUtils.getCameraService().supportsCameraApi(cameraId, API_VERSION_1);
+            assertTrue(
+                    "Camera service returned false when queried if it supports camera1 api " +
+                    " for camera ID " + cameraId, supports);
         }
     }
 
@@ -169,11 +153,10 @@
 
             String clientPackageName = getContext().getPackageName();
 
-            BinderHolder holder = new BinderHolder();
-            CameraBinderDecorator.newInstance(mUtils.getCameraService())
+            ICamera cameraUser = mUtils.getCameraService()
                     .connect(dummyCallbacks, cameraId, clientPackageName,
-                    CameraBinderTestUtils.USE_CALLING_UID, holder);
-            ICamera cameraUser = ICamera.Stub.asInterface(holder.getBinder());
+                            ICameraService.USE_CALLING_UID,
+                            ICameraService.USE_CALLING_PID);
             assertNotNull(String.format("Camera %s was null", cameraId), cameraUser);
 
             Log.v(TAG, String.format("Camera %s connected", cameraId));
@@ -191,14 +174,11 @@
 
             String clientPackageName = getContext().getPackageName();
 
-            BinderHolder holder = new BinderHolder();
-
             try {
-                CameraBinderDecorator.newInstance(mUtils.getCameraService())
+                cameraUser = mUtils.getCameraService()
                         .connectLegacy(dummyCallbacks, cameraId, CAMERA_HAL_API_VERSION_1_0,
-                        clientPackageName,
-                        CameraBinderTestUtils.USE_CALLING_UID, holder);
-                cameraUser = ICamera.Stub.asInterface(holder.getBinder());
+                                clientPackageName,
+                                ICameraService.USE_CALLING_UID);
                 assertNotNull(String.format("Camera %s was null", cameraId), cameraUser);
 
                 Log.v(TAG, String.format("Camera %s connected as HAL1 legacy device", cameraId));
@@ -284,11 +264,11 @@
 
             String clientPackageName = getContext().getPackageName();
 
-            BinderHolder holder = new BinderHolder();
-            CameraBinderDecorator.newInstance(mUtils.getCameraService())
-                    .connectDevice(dummyCallbacks, cameraId,
-                    clientPackageName, CameraBinderTestUtils.USE_CALLING_UID, holder);
-            ICameraDeviceUser cameraUser = ICameraDeviceUser.Stub.asInterface(holder.getBinder());
+            ICameraDeviceUser cameraUser =
+                    mUtils.getCameraService().connectDevice(
+                        dummyCallbacks, cameraId,
+                        clientPackageName,
+                        ICameraService.USE_CALLING_UID);
             assertNotNull(String.format("Camera %s was null", cameraId), cameraUser);
 
             Log.v(TAG, String.format("Camera %s connected", cameraId));
@@ -323,27 +303,33 @@
 
             ICameraServiceListener listener = new DummyCameraServiceListener();
 
-            assertTrue(
-                    "Listener was removed before added",
-                    mUtils.getCameraService().removeListener(listener) ==
-                    CameraBinderTestUtils.BAD_VALUE);
+            try {
+                mUtils.getCameraService().removeListener(listener);
+                fail("Listener was removed before added");
+            } catch (ServiceSpecificException e) {
+                assertEquals("Listener was removed before added",
+                        e.errorCode, ICameraService.ERROR_ILLEGAL_ARGUMENT);
+            }
 
-            assertTrue("Listener was not added",
-                    mUtils.getCameraService().addListener(listener) ==
-                    CameraBinderTestUtils.NO_ERROR);
-            assertTrue(
-                    "Listener was wrongly added again",
-                    mUtils.getCameraService().addListener(listener) ==
-                    CameraBinderTestUtils.ALREADY_EXISTS);
+            mUtils.getCameraService().addListener(listener);
 
-            assertTrue(
-                    "Listener was not removed",
-                    mUtils.getCameraService().removeListener(listener) ==
-                    CameraBinderTestUtils.NO_ERROR);
-            assertTrue(
-                    "Listener was wrongly removed again",
-                    mUtils.getCameraService().removeListener(listener) ==
-                    CameraBinderTestUtils.BAD_VALUE);
+            try {
+                mUtils.getCameraService().addListener(listener);
+                fail("Listener was wrongly added again");
+            } catch (ServiceSpecificException e) {
+                assertEquals("Listener was wrongly added again",
+                        e.errorCode, ICameraService.ERROR_ALREADY_EXISTS);
+            }
+
+            mUtils.getCameraService().removeListener(listener);
+
+            try {
+                mUtils.getCameraService().removeListener(listener);
+                fail("Listener was wrongly removed twice");
+            } catch (ServiceSpecificException e) {
+                assertEquals("Listener was wrongly removed twice",
+                        e.errorCode, ICameraService.ERROR_ILLEGAL_ARGUMENT);
+            }
         }
     }
 }
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraBinderTestUtils.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraBinderTestUtils.java
index 5c4b23b..38fc49f 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraBinderTestUtils.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraBinderTestUtils.java
@@ -18,10 +18,6 @@
 
     static final String CAMERA_SERVICE_BINDER_NAME = "media.camera";
 
-    protected static final int USE_CALLING_UID = -1;
-    protected static final int BAD_VALUE = -EINVAL;
-    protected static final int INVALID_OPERATION = -ENOSYS;
-    protected static final int ALREADY_EXISTS = -EEXIST;
     public static final int NO_ERROR = 0;
     private final Context mContext;
 
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraDeviceBinderTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraDeviceBinderTest.java
index d71b44b..5c1d8a7 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraDeviceBinderTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraDeviceBinderTest.java
@@ -18,6 +18,7 @@
 
 import android.graphics.ImageFormat;
 import android.graphics.SurfaceTexture;
+import android.hardware.ICameraService;
 import android.hardware.camera2.CameraMetadata;
 import android.hardware.camera2.CameraCaptureSession;
 import android.hardware.camera2.CameraCharacteristics;
@@ -27,12 +28,13 @@
 import android.hardware.camera2.impl.CameraMetadataNative;
 import android.hardware.camera2.impl.CaptureResultExtras;
 import android.hardware.camera2.params.OutputConfiguration;
-import android.hardware.camera2.utils.BinderHolder;
+import android.hardware.camera2.utils.SubmitInfo;
 import android.media.Image;
 import android.media.ImageReader;
 import android.os.Handler;
 import android.os.HandlerThread;
 import android.os.RemoteException;
+import android.os.ServiceSpecificException;
 import android.os.SystemClock;
 import android.test.AndroidTestCase;
 import android.test.suitebuilder.annotation.SmallTest;
@@ -164,11 +166,10 @@
     }
 
     private CaptureRequest.Builder createDefaultBuilder(boolean needStream) throws Exception {
-        CameraMetadataNative metadata = new CameraMetadataNative();
+        CameraMetadataNative metadata = null;
         assertTrue(metadata.isEmpty());
 
-        int status = mCameraUser.createDefaultRequest(TEMPLATE_PREVIEW, /* out */metadata);
-        assertEquals(CameraBinderTestUtils.NO_ERROR, status);
+        metadata = mCameraUser.createDefaultRequest(TEMPLATE_PREVIEW);
         assertFalse(metadata.isEmpty());
 
         CaptureRequest.Builder request = new CaptureRequest.Builder(metadata, /*reprocess*/false,
@@ -183,12 +184,13 @@
         return request;
     }
 
-    private int submitCameraRequest(CaptureRequest request, boolean streaming) throws Exception {
-        int requestId = mCameraUser.submitRequest(request, streaming, null);
+    private SubmitInfo submitCameraRequest(CaptureRequest request, boolean streaming) throws Exception {
+        SubmitInfo requestInfo = mCameraUser.submitRequest(request, streaming);
         assertTrue(
-                "Request IDs should be non-negative (expected: >= 0, actual: " + requestId + ")",
-                requestId >= 0);
-        return requestId;
+                "Request IDs should be non-negative (expected: >= 0, actual: " +
+                requestInfo.getRequestId() + ")",
+                requestInfo.getRequestId() >= 0);
+        return requestInfo;
     }
 
     @Override
@@ -214,10 +216,8 @@
 
         mMockCb = spy(dummyCallbacks);
 
-        BinderHolder holder = new BinderHolder();
-        mUtils.getCameraService().connectDevice(mMockCb, mCameraId,
-                clientPackageName, CameraBinderTestUtils.USE_CALLING_UID, holder);
-        mCameraUser = ICameraDeviceUser.Stub.asInterface(holder.getBinder());
+        mCameraUser = mUtils.getCameraService().connectDevice(mMockCb, mCameraId,
+                clientPackageName, ICameraService.USE_CALLING_UID);
         assertNotNull(String.format("Camera %s was null", mCameraId), mCameraUser);
         mHandlerThread = new HandlerThread(TAG);
         mHandlerThread.start();
@@ -238,11 +238,10 @@
 
     @SmallTest
     public void testCreateDefaultRequest() throws Exception {
-        CameraMetadataNative metadata = new CameraMetadataNative();
+        CameraMetadataNative metadata = null;
         assertTrue(metadata.isEmpty());
 
-        int status = mCameraUser.createDefaultRequest(TEMPLATE_PREVIEW, /* out */metadata);
-        assertEquals(CameraBinderTestUtils.NO_ERROR, status);
+        metadata = mCameraUser.createDefaultRequest(TEMPLATE_PREVIEW);
         assertFalse(metadata.isEmpty());
 
     }
@@ -252,18 +251,28 @@
         int streamId = mCameraUser.createStream(mOutputConfiguration);
         assertEquals(0, streamId);
 
-        assertEquals(CameraBinderTestUtils.ALREADY_EXISTS,
-                mCameraUser.createStream(mOutputConfiguration));
+        try {
+            mCameraUser.createStream(mOutputConfiguration);
+            fail("Creating same stream twice");
+        } catch (ServiceSpecificException e) {
+            assertEquals("Creating same stream twice",
+                    e.errorCode, ICameraService.ERROR_ALREADY_EXISTS);
+        }
 
-        assertEquals(CameraBinderTestUtils.NO_ERROR, mCameraUser.deleteStream(streamId));
+        mCameraUser.deleteStream(streamId);
     }
 
     @SmallTest
     public void testDeleteInvalidStream() throws Exception {
-        assertEquals(CameraBinderTestUtils.BAD_VALUE, mCameraUser.deleteStream(-1));
-        assertEquals(CameraBinderTestUtils.BAD_VALUE, mCameraUser.deleteStream(0));
-        assertEquals(CameraBinderTestUtils.BAD_VALUE, mCameraUser.deleteStream(1));
-        assertEquals(CameraBinderTestUtils.BAD_VALUE, mCameraUser.deleteStream(0xC0FFEE));
+        int[] badStreams = { -1, 0, 1, 0xC0FFEE };
+        for (int badStream : badStreams) {
+            try {
+                mCameraUser.deleteStream(badStream);
+                fail("Allowed bad stream delete");
+            } catch (ServiceSpecificException e) {
+                assertEquals(e.errorCode, ICameraService.ERROR_ILLEGAL_ARGUMENT);
+            }
+        }
     }
 
     @SmallTest
@@ -273,8 +282,13 @@
         int streamId = mCameraUser.createStream(mOutputConfiguration);
         assertEquals(0, streamId);
 
-        assertEquals(CameraBinderTestUtils.ALREADY_EXISTS,
-                mCameraUser.createStream(mOutputConfiguration));
+        try {
+            mCameraUser.createStream(mOutputConfiguration);
+            fail("Created same stream twice");
+        } catch (ServiceSpecificException e) {
+            assertEquals("Created same stream twice",
+                    ICameraService.ERROR_ALREADY_EXISTS, e.errorCode);
+        }
 
         // Create second stream with a different surface.
         SurfaceTexture surfaceTexture = new SurfaceTexture(/* ignored */0);
@@ -286,8 +300,8 @@
         assertEquals(1, streamId2);
 
         // Clean up streams
-        assertEquals(CameraBinderTestUtils.NO_ERROR, mCameraUser.deleteStream(streamId));
-        assertEquals(CameraBinderTestUtils.NO_ERROR, mCameraUser.deleteStream(streamId2));
+        mCameraUser.deleteStream(streamId);
+        mCameraUser.deleteStream(streamId2);
     }
 
     @SmallTest
@@ -295,16 +309,25 @@
 
         CaptureRequest.Builder builder = createDefaultBuilder(/* needStream */false);
         CaptureRequest request1 = builder.build();
-        int status = mCameraUser.submitRequest(request1, /* streaming */false, null);
-        assertEquals("Expected submitRequest to return BAD_VALUE " +
-                "since we had 0 surface targets set.", CameraBinderTestUtils.BAD_VALUE, status);
+        try {
+            SubmitInfo requestInfo = mCameraUser.submitRequest(request1, /* streaming */false);
+            fail("Exception expected");
+        } catch(ServiceSpecificException e) {
+            assertEquals("Expected submitRequest to throw ServiceSpecificException with BAD_VALUE " +
+                    "since we had 0 surface targets set.", ICameraService.ERROR_ILLEGAL_ARGUMENT,
+                    e.errorCode);
+        }
 
         builder.addTarget(mSurface);
         CaptureRequest request2 = builder.build();
-        status = mCameraUser.submitRequest(request2, /* streaming */false, null);
-        assertEquals("Expected submitRequest to return BAD_VALUE since " +
-                "the target surface wasn't registered with createStream.",
-                CameraBinderTestUtils.BAD_VALUE, status);
+        try {
+            SubmitInfo requestInfo = mCameraUser.submitRequest(request2, /* streaming */false);
+            fail("Exception expected");
+        } catch(ServiceSpecificException e) {
+            assertEquals("Expected submitRequest to throw ILLEGAL_ARGUMENT " +
+                    "ServiceSpecificException since the target wasn't registered with createStream.",
+                    ICameraService.ERROR_ILLEGAL_ARGUMENT, e.errorCode);
+        }
     }
 
     @SmallTest
@@ -314,9 +337,10 @@
         CaptureRequest request = builder.build();
 
         // Submit valid request twice.
-        int requestId1 = submitCameraRequest(request, /* streaming */false);
-        int requestId2 = submitCameraRequest(request, /* streaming */false);
-        assertNotSame("Request IDs should be unique for multiple requests", requestId1, requestId2);
+        SubmitInfo requestInfo1 = submitCameraRequest(request, /* streaming */false);
+        SubmitInfo requestInfo2 = submitCameraRequest(request, /* streaming */false);
+        assertNotSame("Request IDs should be unique for multiple requests",
+                requestInfo1.getRequestId(), requestInfo2.getRequestId());
 
     }
 
@@ -329,32 +353,35 @@
 
         // Submit valid request once (non-streaming), and another time
         // (streaming)
-        int requestId1 = submitCameraRequest(request, /* streaming */false);
+        SubmitInfo requestInfo1 = submitCameraRequest(request, /* streaming */false);
 
-        int requestIdStreaming = submitCameraRequest(request, /* streaming */true);
-        assertNotSame("Request IDs should be unique for multiple requests", requestId1,
-                requestIdStreaming);
+        SubmitInfo requestInfoStreaming = submitCameraRequest(request, /* streaming */true);
+        assertNotSame("Request IDs should be unique for multiple requests",
+                requestInfo1.getRequestId(),
+                requestInfoStreaming.getRequestId());
 
-        int status = mCameraUser.cancelRequest(-1, null);
-        assertEquals("Invalid request IDs should not be cancellable",
-                CameraBinderTestUtils.BAD_VALUE, status);
+        try {
+            long lastFrameNumber = mCameraUser.cancelRequest(-1);
+            fail("Expected exception");
+        } catch (ServiceSpecificException e) {
+            assertEquals("Invalid request IDs should not be cancellable",
+                    ICameraService.ERROR_ILLEGAL_ARGUMENT, e.errorCode);
+        }
 
-        status = mCameraUser.cancelRequest(requestId1, null);
-        assertEquals("Non-streaming request IDs should not be cancellable",
-                CameraBinderTestUtils.BAD_VALUE, status);
+        try {
+            long lastFrameNumber = mCameraUser.cancelRequest(requestInfo1.getRequestId());
+            fail("Expected exception");
+        } catch (ServiceSpecificException e) {
+            assertEquals("Non-streaming request IDs should not be cancellable",
+                    ICameraService.ERROR_ILLEGAL_ARGUMENT, e.errorCode);
+        }
 
-        status = mCameraUser.cancelRequest(requestIdStreaming, null);
-        assertEquals("Streaming request IDs should be cancellable", CameraBinderTestUtils.NO_ERROR,
-                status);
-
+        long lastFrameNumber = mCameraUser.cancelRequest(requestInfoStreaming.getRequestId());
     }
 
     @SmallTest
     public void testCameraInfo() throws RemoteException {
-        CameraMetadataNative info = new CameraMetadataNative();
-
-        int status = mCameraUser.getCameraInfo(/*out*/info);
-        assertEquals(CameraBinderTestUtils.NO_ERROR, status);
+        CameraMetadataNative info = mCameraUser.getCameraInfo();
 
         assertFalse(info.isEmpty());
         assertNotNull(info.get(CameraCharacteristics.SCALER_AVAILABLE_FORMATS));
@@ -362,10 +389,7 @@
 
     @SmallTest
     public void testCameraCharacteristics() throws RemoteException {
-        CameraMetadataNative info = new CameraMetadataNative();
-
-        int status = mUtils.getCameraService().getCameraCharacteristics(mCameraId, /*out*/info);
-        assertEquals(CameraBinderTestUtils.NO_ERROR, status);
+        CameraMetadataNative info = mUtils.getCameraService().getCameraCharacteristics(mCameraId);
 
         assertFalse(info.isEmpty());
         assertNotNull(info.get(CameraCharacteristics.SCALER_AVAILABLE_FORMATS));
@@ -374,18 +398,19 @@
     @SmallTest
     public void testWaitUntilIdle() throws Exception {
         CaptureRequest.Builder builder = createDefaultBuilder(/* needStream */true);
-        int requestIdStreaming = submitCameraRequest(builder.build(), /* streaming */true);
+        SubmitInfo requestInfoStreaming = submitCameraRequest(builder.build(), /* streaming */true);
 
         // Test Bad case first: waitUntilIdle when there is active repeating request
-        int status = mCameraUser.waitUntilIdle();
-        assertEquals("waitUntilIdle is invalid operation when there is active repeating request",
-            CameraBinderTestUtils.INVALID_OPERATION, status);
+        try {
+            mCameraUser.waitUntilIdle();
+        } catch (ServiceSpecificException e) {
+            assertEquals("waitUntilIdle is invalid operation when there is active repeating request",
+                    ICameraService.ERROR_INVALID_OPERATION, e.errorCode);
+        }
 
         // Test good case, waitUntilIdle when there is no active repeating request
-        status = mCameraUser.cancelRequest(requestIdStreaming, null);
-        assertEquals(CameraBinderTestUtils.NO_ERROR, status);
-        status = mCameraUser.waitUntilIdle();
-        assertEquals(CameraBinderTestUtils.NO_ERROR, status);
+        long lastFrameNumber = mCameraUser.cancelRequest(requestInfoStreaming.getRequestId());
+        mCameraUser.waitUntilIdle();
     }
 
     @SmallTest
@@ -411,12 +436,12 @@
         ArgumentCaptor<Long> timestamps = ArgumentCaptor.forClass(Long.class);
 
         // Test both single request and streaming request.
-        int requestId1 = submitCameraRequest(request, /* streaming */false);
+        SubmitInfo requestInfo1 = submitCameraRequest(request, /* streaming */false);
         verify(mMockCb, timeout(WAIT_FOR_COMPLETE_TIMEOUT_MS).times(1)).onCaptureStarted(
                 any(CaptureResultExtras.class),
                 anyLong());
 
-        int streamingId = submitCameraRequest(request, /* streaming */true);
+        SubmitInfo streamingInfo = submitCameraRequest(request, /* streaming */true);
         verify(mMockCb, timeout(WAIT_FOR_COMPLETE_TIMEOUT_MS).atLeast(NUM_CALLBACKS_CHECKED))
                 .onCaptureStarted(
                         any(CaptureResultExtras.class),
@@ -436,22 +461,22 @@
         CaptureRequest request = createDefaultBuilder(/* needStream */true).build();
 
         // Try streaming
-        int streamingId = submitCameraRequest(request, /* streaming */true);
+        SubmitInfo streamingInfo = submitCameraRequest(request, /* streaming */true);
 
         // Wait a bit to fill up the queue
         SystemClock.sleep(WAIT_FOR_WORK_MS);
 
         // Cancel and make sure we eventually quiesce
-        status = mCameraUser.cancelRequest(streamingId, null);
+        long lastFrameNumber = mCameraUser.cancelRequest(streamingInfo.getRequestId());
 
         verify(mMockCb, timeout(WAIT_FOR_IDLE_TIMEOUT_MS).times(1)).onDeviceIdle();
 
         // Submit a few capture requests
-        int requestId1 = submitCameraRequest(request, /* streaming */false);
-        int requestId2 = submitCameraRequest(request, /* streaming */false);
-        int requestId3 = submitCameraRequest(request, /* streaming */false);
-        int requestId4 = submitCameraRequest(request, /* streaming */false);
-        int requestId5 = submitCameraRequest(request, /* streaming */false);
+        SubmitInfo requestInfo1 = submitCameraRequest(request, /* streaming */false);
+        SubmitInfo requestInfo2 = submitCameraRequest(request, /* streaming */false);
+        SubmitInfo requestInfo3 = submitCameraRequest(request, /* streaming */false);
+        SubmitInfo requestInfo4 = submitCameraRequest(request, /* streaming */false);
+        SubmitInfo requestInfo5 = submitCameraRequest(request, /* streaming */false);
 
         // And wait for more idle
         verify(mMockCb, timeout(WAIT_FOR_IDLE_TIMEOUT_MS).times(2)).onDeviceIdle();
@@ -463,38 +488,34 @@
         int status;
 
         // Initial flush should work
-        status = mCameraUser.flush(null);
-        assertEquals(CameraBinderTestUtils.NO_ERROR, status);
+        long lastFrameNumber = mCameraUser.flush();
 
         // Then set up a stream
         CaptureRequest request = createDefaultBuilder(/* needStream */true).build();
 
         // Flush should still be a no-op, really
-        status = mCameraUser.flush(null);
-        assertEquals(CameraBinderTestUtils.NO_ERROR, status);
+        lastFrameNumber = mCameraUser.flush();
 
         // Submit a few capture requests
-        int requestId1 = submitCameraRequest(request, /* streaming */false);
-        int requestId2 = submitCameraRequest(request, /* streaming */false);
-        int requestId3 = submitCameraRequest(request, /* streaming */false);
-        int requestId4 = submitCameraRequest(request, /* streaming */false);
-        int requestId5 = submitCameraRequest(request, /* streaming */false);
+        SubmitInfo requestInfo1 = submitCameraRequest(request, /* streaming */false);
+        SubmitInfo requestInfo2 = submitCameraRequest(request, /* streaming */false);
+        SubmitInfo requestInfo3 = submitCameraRequest(request, /* streaming */false);
+        SubmitInfo requestInfo4 = submitCameraRequest(request, /* streaming */false);
+        SubmitInfo requestInfo5 = submitCameraRequest(request, /* streaming */false);
 
         // Then flush and wait for idle
-        status = mCameraUser.flush(null);
-        assertEquals(CameraBinderTestUtils.NO_ERROR, status);
+        lastFrameNumber = mCameraUser.flush();
 
         verify(mMockCb, timeout(WAIT_FOR_FLUSH_TIMEOUT_MS).times(1)).onDeviceIdle();
 
         // Now a streaming request
-        int streamingId = submitCameraRequest(request, /* streaming */true);
+        SubmitInfo streamingInfo = submitCameraRequest(request, /* streaming */true);
 
         // Wait a bit to fill up the queue
         SystemClock.sleep(WAIT_FOR_WORK_MS);
 
         // Then flush and wait for the idle callback
-        status = mCameraUser.flush(null);
-        assertEquals(CameraBinderTestUtils.NO_ERROR, status);
+        lastFrameNumber = mCameraUser.flush();
 
         verify(mMockCb, timeout(WAIT_FOR_FLUSH_TIMEOUT_MS).times(2)).onDeviceIdle();
 
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/CameraUtilsBinderDecoratorTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/CameraUtilsBinderDecoratorTest.java
deleted file mode 100644
index 33c6388..0000000
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/CameraUtilsBinderDecoratorTest.java
+++ /dev/null
@@ -1,173 +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.mediaframeworktest.unit;
-
-import android.hardware.camera2.CameraAccessException;
-import android.hardware.camera2.utils.CameraBinderDecorator;
-import android.hardware.camera2.utils.CameraRuntimeException;
-import android.os.DeadObjectException;
-import android.os.RemoteException;
-import android.os.TransactionTooLargeException;
-import android.test.suitebuilder.annotation.SmallTest;
-
-import static org.mockito.Mockito.*;
-import static android.hardware.camera2.utils.CameraBinderDecorator.*;
-import static android.hardware.camera2.CameraAccessException.*;
-import static android.system.OsConstants.*;
-
-import junit.framework.Assert;
-
-public class CameraUtilsBinderDecoratorTest extends junit.framework.TestCase {
-
-    private interface ICameraBinderStereotype {
-
-        double doNothing();
-
-        // int is a 'status_t'
-        int doSomethingPositive();
-
-        int doSomethingNoError();
-
-        int doSomethingPermissionDenied();
-
-        int doSomethingAlreadyExists();
-
-        int doSomethingBadValue();
-
-        int doSomethingDeadObject() throws CameraRuntimeException;
-
-        int doSomethingBadPolicy() throws CameraRuntimeException;
-
-        int doSomethingDeviceBusy() throws CameraRuntimeException;
-
-        int doSomethingNoSuchDevice() throws CameraRuntimeException;
-
-        int doSomethingUnknownErrorCode();
-
-        int doSomethingThrowDeadObjectException() throws RemoteException;
-
-        int doSomethingThrowTransactionTooLargeException() throws RemoteException;
-    }
-
-    private static final double SOME_ARBITRARY_DOUBLE = 1.0;
-    private static final int SOME_ARBITRARY_POSITIVE_INT = 5;
-    private static final int SOME_ARBITRARY_NEGATIVE_INT = -0xC0FFEE;
-
-    @SmallTest
-    public void testStereotypes() {
-
-        ICameraBinderStereotype mock = mock(ICameraBinderStereotype.class);
-        try {
-            when(mock.doNothing()).thenReturn(SOME_ARBITRARY_DOUBLE);
-            when(mock.doSomethingPositive()).thenReturn(SOME_ARBITRARY_POSITIVE_INT);
-            when(mock.doSomethingNoError()).thenReturn(NO_ERROR);
-            when(mock.doSomethingPermissionDenied()).thenReturn(PERMISSION_DENIED);
-            when(mock.doSomethingAlreadyExists()).thenReturn(ALREADY_EXISTS);
-            when(mock.doSomethingBadValue()).thenReturn(BAD_VALUE);
-            when(mock.doSomethingDeadObject()).thenReturn(DEAD_OBJECT);
-            when(mock.doSomethingBadPolicy()).thenReturn(-EACCES);
-            when(mock.doSomethingDeviceBusy()).thenReturn(-EBUSY);
-            when(mock.doSomethingNoSuchDevice()).thenReturn(-ENODEV);
-            when(mock.doSomethingUnknownErrorCode()).thenReturn(SOME_ARBITRARY_NEGATIVE_INT);
-            when(mock.doSomethingThrowDeadObjectException()).thenThrow(new DeadObjectException());
-            when(mock.doSomethingThrowTransactionTooLargeException()).thenThrow(
-                    new TransactionTooLargeException());
-        } catch (RemoteException e) {
-            Assert.fail("Unreachable");
-        }
-
-        ICameraBinderStereotype decoratedMock = CameraBinderDecorator.newInstance(mock);
-
-        // ignored by decorator because return type is double, not int
-        assertEquals(SOME_ARBITRARY_DOUBLE, decoratedMock.doNothing());
-
-        // pass through for positive values
-        assertEquals(SOME_ARBITRARY_POSITIVE_INT, decoratedMock.doSomethingPositive());
-
-        // pass through NO_ERROR
-        assertEquals(NO_ERROR, decoratedMock.doSomethingNoError());
-
-        try {
-            decoratedMock.doSomethingPermissionDenied();
-            Assert.fail("Should've thrown SecurityException");
-        } catch (SecurityException e) {
-        }
-
-        assertEquals(ALREADY_EXISTS, decoratedMock.doSomethingAlreadyExists());
-
-        try {
-            decoratedMock.doSomethingBadValue();
-            Assert.fail("Should've thrown IllegalArgumentException");
-        } catch (IllegalArgumentException e) {
-        }
-
-        try {
-            decoratedMock.doSomethingDeadObject();
-            Assert.fail("Should've thrown CameraRuntimeException");
-        } catch (CameraRuntimeException e) {
-            assertEquals(CAMERA_DISCONNECTED, e.getReason());
-        }
-
-        try {
-            decoratedMock.doSomethingBadPolicy();
-            Assert.fail("Should've thrown CameraRuntimeException");
-        } catch (CameraRuntimeException e) {
-            assertEquals(CAMERA_DISABLED, e.getReason());
-        }
-
-        try {
-            decoratedMock.doSomethingDeviceBusy();
-            Assert.fail("Should've thrown CameraRuntimeException");
-        } catch (CameraRuntimeException e) {
-            assertEquals(CAMERA_IN_USE, e.getReason());
-        }
-
-        try {
-            decoratedMock.doSomethingNoSuchDevice();
-            Assert.fail("Should've thrown CameraRuntimeException");
-        } catch (CameraRuntimeException e) {
-            assertEquals(CAMERA_DISCONNECTED, e.getReason());
-        }
-
-        try {
-            decoratedMock.doSomethingUnknownErrorCode();
-            Assert.fail("Should've thrown UnsupportedOperationException");
-        } catch (UnsupportedOperationException e) {
-            assertEquals(String.format("Unknown error %d",
-                    SOME_ARBITRARY_NEGATIVE_INT), e.getMessage());
-        }
-
-        try {
-            decoratedMock.doSomethingThrowDeadObjectException();
-            Assert.fail("Should've thrown CameraRuntimeException");
-        } catch (CameraRuntimeException e) {
-            assertEquals(CAMERA_DISCONNECTED, e.getReason());
-        } catch (RemoteException e) {
-            Assert.fail("Should not throw a DeadObjectException directly, but rethrow");
-        }
-
-        try {
-            decoratedMock.doSomethingThrowTransactionTooLargeException();
-            Assert.fail("Should've thrown UnsupportedOperationException");
-        } catch (UnsupportedOperationException e) {
-            assertTrue(e.getCause() instanceof TransactionTooLargeException);
-        } catch (RemoteException e) {
-            Assert.fail("Should not throw a TransactionTooLargeException directly, but rethrow");
-        }
-    }
-
-}
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/CameraUtilsDecoratorTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/CameraUtilsDecoratorTest.java
deleted file mode 100644
index c3b6006..0000000
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/CameraUtilsDecoratorTest.java
+++ /dev/null
@@ -1,171 +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.mediaframeworktest.unit;
-
-import android.test.suitebuilder.annotation.SmallTest;
-import android.hardware.camera2.utils.*;
-import android.hardware.camera2.utils.Decorator.DecoratorListener;
-
-import junit.framework.Assert;
-
-import java.lang.reflect.Method;
-
-/**
- * adb shell am instrument -e class 'com.android.mediaframeworktest.unit.CameraUtilsDecoratorTest' \
- *      -w com.android.mediaframeworktest/.MediaFrameworkUnitTestRunner
- */
-public class CameraUtilsDecoratorTest extends junit.framework.TestCase {
-    private DummyListener mDummyListener;
-    private DummyInterface mIface;
-
-    @Override
-    public void setUp() {
-        mDummyListener = new DummyListener();
-        mIface = Decorator.newInstance(new DummyImpl(), mDummyListener);
-    }
-
-    interface DummyInterface {
-        int addValues(int x, int y, int z);
-
-        void raiseException() throws Exception;
-
-        void raiseUnsupportedOperationException() throws UnsupportedOperationException;
-    }
-
-    class DummyImpl implements DummyInterface {
-        @Override
-        public int addValues(int x, int y, int z) {
-            return x + y + z;
-        }
-
-        @Override
-        public void raiseException() throws Exception {
-            throw new Exception("Test exception");
-        }
-
-        @Override
-        public void raiseUnsupportedOperationException() throws UnsupportedOperationException {
-            throw new UnsupportedOperationException("Test exception");
-        }
-    }
-
-    class DummyListener implements DecoratorListener {
-
-        public boolean beforeCalled = false;
-        public boolean afterCalled = false;
-        public boolean catchCalled = false;
-        public boolean finallyCalled = false;
-        public Object resultValue = null;
-
-        public boolean raiseException = false;
-
-        @Override
-        public void onBeforeInvocation(Method m, Object[] args) {
-            beforeCalled = true;
-        }
-
-        @Override
-        public void onAfterInvocation(Method m, Object[] args, Object result) {
-            afterCalled = true;
-            resultValue = result;
-
-            if (raiseException) {
-                throw new UnsupportedOperationException("Test exception");
-            }
-        }
-
-        @Override
-        public boolean onCatchException(Method m, Object[] args, Throwable t) {
-            catchCalled = true;
-            return false;
-        }
-
-        @Override
-        public void onFinally(Method m, Object[] args) {
-            finallyCalled = true;
-        }
-
-    };
-
-    @SmallTest
-    public void testDecorator() {
-
-        // TODO rewrite this using mocks
-
-        assertTrue(mIface.addValues(1, 2, 3) == 6);
-        assertTrue(mDummyListener.beforeCalled);
-        assertTrue(mDummyListener.afterCalled);
-
-        int resultValue = (Integer)mDummyListener.resultValue;
-        assertTrue(resultValue == 6);
-        assertTrue(mDummyListener.finallyCalled);
-        assertFalse(mDummyListener.catchCalled);
-    }
-
-    @SmallTest
-    public void testDecoratorExceptions() {
-
-        boolean gotExceptions = false;
-        try {
-            mIface.raiseException();
-        } catch (Exception e) {
-            gotExceptions = true;
-            assertTrue(e.getMessage() == "Test exception");
-        }
-        assertTrue(gotExceptions);
-        assertTrue(mDummyListener.beforeCalled);
-        assertFalse(mDummyListener.afterCalled);
-        assertTrue(mDummyListener.catchCalled);
-        assertTrue(mDummyListener.finallyCalled);
-    }
-
-    @SmallTest
-    public void testDecoratorUnsupportedOperationException() {
-
-        boolean gotExceptions = false;
-        try {
-            mIface.raiseUnsupportedOperationException();
-        } catch (UnsupportedOperationException e) {
-            gotExceptions = true;
-            assertTrue(e.getMessage() == "Test exception");
-        }
-        assertTrue(gotExceptions);
-        assertTrue(mDummyListener.beforeCalled);
-        assertFalse(mDummyListener.afterCalled);
-        assertTrue(mDummyListener.catchCalled);
-        assertTrue(mDummyListener.finallyCalled);
-    }
-
-    @SmallTest
-    public void testDecoratorRaisesException() {
-
-        boolean gotExceptions = false;
-        try {
-            mDummyListener.raiseException = true;
-            mIface.addValues(1, 2, 3);
-            Assert.fail("unreachable");
-        } catch (UnsupportedOperationException e) {
-            gotExceptions = true;
-            assertTrue(e.getMessage() == "Test exception");
-        }
-        assertTrue(gotExceptions);
-        assertTrue(mDummyListener.beforeCalled);
-        assertTrue(mDummyListener.afterCalled);
-        assertFalse(mDummyListener.catchCalled);
-        assertTrue(mDummyListener.finallyCalled);
-    }
-}
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/CameraUtilsRuntimeExceptionTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/CameraUtilsRuntimeExceptionTest.java
deleted file mode 100644
index 02c9f2a..0000000
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/CameraUtilsRuntimeExceptionTest.java
+++ /dev/null
@@ -1,77 +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.mediaframeworktest.unit;
-
-import android.hardware.camera2.CameraAccessException;
-import android.hardware.camera2.utils.CameraRuntimeException;
-import android.hardware.camera2.utils.UncheckedThrow;
-import android.test.suitebuilder.annotation.SmallTest;
-
-import junit.framework.Assert;
-
-public class CameraUtilsRuntimeExceptionTest extends junit.framework.TestCase {
-
-    @SmallTest
-    public void testCameraRuntimeException1() {
-        try {
-            CameraRuntimeException runtimeExc = new CameraRuntimeException(12345);
-            throw runtimeExc.asChecked();
-        } catch (CameraAccessException e) {
-            assertEquals(12345, e.getReason());
-            assertNull(e.getMessage());
-            assertNull(e.getCause());
-        }
-    }
-
-    @SmallTest
-    public void testCameraRuntimeException2() {
-        try {
-            CameraRuntimeException runtimeExc = new CameraRuntimeException(12345, "Hello");
-            throw runtimeExc.asChecked();
-        } catch (CameraAccessException e) {
-            assertEquals(12345, e.getReason());
-            assertEquals("Hello", e.getMessage());
-            assertNull(e.getCause());
-        }
-    }
-
-    @SmallTest
-    public void testCameraRuntimeException3() {
-        Throwable cause = new IllegalStateException("For great justice");
-        try {
-            CameraRuntimeException runtimeExc = new CameraRuntimeException(12345, cause);
-            throw runtimeExc.asChecked();
-        } catch (CameraAccessException e) {
-            assertEquals(12345, e.getReason());
-            assertNull(e.getMessage());
-            assertEquals(cause, e.getCause());
-        }
-    }
-
-    @SmallTest
-    public void testCameraRuntimeException4() {
-        Throwable cause = new IllegalStateException("For great justice");
-        try {
-            CameraRuntimeException runtimeExc = new CameraRuntimeException(12345, "Hello", cause);
-            throw runtimeExc.asChecked();
-        } catch (CameraAccessException e) {
-            assertEquals(12345, e.getReason());
-            assertEquals("Hello", e.getMessage());
-            assertEquals(cause, e.getCause());
-        }
-    }
-}
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/ExifInterfaceTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/ExifInterfaceTest.java
index 1c80746..5bd6079 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/ExifInterfaceTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/ExifInterfaceTest.java
@@ -23,20 +23,20 @@
 import android.graphics.BitmapFactory;
 import android.media.ExifInterface;
 import android.os.Environment;
-import android.os.ParcelFileDescriptor;
 import android.test.AndroidTestCase;
 import android.util.Log;
 import android.system.ErrnoException;
 import android.system.Os;
 import android.system.OsConstants;
 
+import java.io.BufferedInputStream;
+import java.io.ByteArrayInputStream;
 import java.io.File;
 import java.io.FileDescriptor;
 import java.io.FileInputStream;
 import java.io.FileOutputStream;
 import java.io.InputStream;
 import java.io.IOException;
-import java.lang.reflect.Type;
 
 import libcore.io.IoUtils;
 import libcore.io.Streams;
@@ -46,16 +46,17 @@
     private static final boolean VERBOSE = false;  // lots of logging
 
     private static final double DIFFERENCE_TOLERANCE = .005;
-    private static final int BUFFER_SIZE = 32768;
 
     // List of files.
-    private static final String EXIF_BYTE_ORDER_II_JPEG = "ExifByteOrderII.jpg";
-    private static final String EXIF_BYTE_ORDER_MM_JPEG = "ExifByteOrderMM.jpg";
+    private static final String EXIF_BYTE_ORDER_II_JPEG = "image_exif_byte_order_ii.jpg";
+    private static final String EXIF_BYTE_ORDER_MM_JPEG = "image_exif_byte_order_mm.jpg";
     private static final String LG_G4_ISO_800_DNG = "lg_g4_iso_800.dng";
+    private static final String VOLANTIS_JPEG = "volantis.jpg";
     private static final int[] IMAGE_RESOURCES = new int[] {
-            R.raw.image_exif_byte_order_ii,  R.raw.image_exif_byte_order_mm, R.raw.lg_g4_iso_800 };
+            R.raw.image_exif_byte_order_ii,  R.raw.image_exif_byte_order_mm, R.raw.lg_g4_iso_800,
+            R.raw.volantis };
     private static final String[] IMAGE_FILENAMES = new String[] {
-            EXIF_BYTE_ORDER_II_JPEG, EXIF_BYTE_ORDER_MM_JPEG, LG_G4_ISO_800_DNG };
+            EXIF_BYTE_ORDER_II_JPEG, EXIF_BYTE_ORDER_MM_JPEG, LG_G4_ISO_800_DNG, VOLANTIS_JPEG };
 
     private static final String[] EXIF_TAGS = {
             ExifInterface.TAG_MAKE,
@@ -165,8 +166,6 @@
 
     @Override
     protected void setUp() throws Exception {
-        byte[] buffer = new byte[BUFFER_SIZE];
-
         for (int i = 0; i < IMAGE_RESOURCES.length; ++i) {
             String outputPath = new File(Environment.getExternalStorageDirectory(),
                     IMAGE_FILENAMES[i]).getAbsolutePath();
@@ -314,26 +313,30 @@
                 expectedValue.whiteBalance);
     }
 
-    private void testExifInterfaceForJpeg(String fileName, int typedArrayResourceId)
+    private void testExifInterfaceCommon(File imageFile, ExpectedValue expectedValue)
             throws IOException {
-        ExpectedValue expectedValue = new ExpectedValue(
-                getContext().getResources().obtainTypedArray(typedArrayResourceId));
-        File imageFile = new File(Environment.getExternalStorageDirectory(), fileName);
-
         // Created via path.
         ExifInterface exifInterface = new ExifInterface(imageFile.getAbsolutePath());
         if (VERBOSE) {
-            printExifTagsAndValues(fileName, exifInterface);
+            printExifTagsAndValues(imageFile.getName(), exifInterface);
+        }
+        compareWithExpectedValue(exifInterface, expectedValue);
+
+        // Created from an asset file.
+        InputStream in = mContext.getAssets().open(imageFile.getName());
+        exifInterface = new ExifInterface(in);
+        if (VERBOSE) {
+            printExifTagsAndValues(imageFile.getName(), exifInterface);
         }
         compareWithExpectedValue(exifInterface, expectedValue);
 
         // Created via InputStream.
-        FileInputStream in = null;
+        in = null;
         try {
-            in = new FileInputStream(imageFile.getAbsolutePath());
+            in = new BufferedInputStream(new FileInputStream(imageFile.getAbsolutePath()));
             exifInterface = new ExifInterface(in);
             if (VERBOSE) {
-                printExifTagsAndValues(fileName, exifInterface);
+                printExifTagsAndValues(imageFile.getName(), exifInterface);
             }
             compareWithExpectedValue(exifInterface, expectedValue);
         } finally {
@@ -345,18 +348,30 @@
             FileDescriptor fd = Os.open(imageFile.getAbsolutePath(), OsConstants.O_RDONLY, 0600);
             exifInterface = new ExifInterface(fd);
             if (VERBOSE) {
-                printExifTagsAndValues(fileName, exifInterface);
+                printExifTagsAndValues(imageFile.getName(), exifInterface);
             }
             compareWithExpectedValue(exifInterface, expectedValue);
         } catch (ErrnoException e) {
             e.rethrowAsIOException();
         }
+    }
+
+    private void testExifInterfaceForJpeg(String fileName, int typedArrayResourceId)
+            throws IOException {
+        ExpectedValue expectedValue = new ExpectedValue(
+                getContext().getResources().obtainTypedArray(typedArrayResourceId));
+        File imageFile = new File(Environment.getExternalStorageDirectory(), fileName);
+
+        // Test for reading from various inputs.
+        testExifInterfaceCommon(imageFile, expectedValue);
 
         // Test for saving attributes.
+        ExifInterface exifInterface;
         try {
             FileDescriptor fd = Os.open(imageFile.getAbsolutePath(), OsConstants.O_RDWR, 0600);
             exifInterface = new ExifInterface(fd);
             exifInterface.saveAttributes();
+            fd = Os.open(imageFile.getAbsolutePath(), OsConstants.O_RDWR, 0600);
             exifInterface = new ExifInterface(fd);
             if (VERBOSE) {
                 printExifTagsAndValues(fileName, exifInterface);
@@ -383,25 +398,11 @@
                 getContext().getResources().obtainTypedArray(typedArrayResourceId));
         File imageFile = new File(Environment.getExternalStorageDirectory(), fileName);
 
-        // Created via path.
-        ExifInterface exifInterface = new ExifInterface(imageFile.getAbsolutePath());
-        if (VERBOSE) {
-            printExifTagsAndValues(fileName, exifInterface);
-        }
-        compareWithExpectedValue(exifInterface, expectedValue);
+        // Test for reading from various inputs.
+        testExifInterfaceCommon(imageFile, expectedValue);
 
-        // Created via FileDescriptor.
-        FileInputStream in = null;
-        try {
-            in = new FileInputStream(imageFile);
-            exifInterface = new ExifInterface(in.getFD());
-            if (VERBOSE) {
-                printExifTagsAndValues(fileName, exifInterface);
-            }
-            compareWithExpectedValue(exifInterface, expectedValue);
-        } finally {
-            IoUtils.closeQuietly(in);
-        }
+        // Since ExifInterface does not support for saving attributes for RAW files, do not test
+        // about writing back in here.
     }
 
     public void testReadExifDataFromExifByteOrderIIJpeg() throws Throwable {
@@ -415,4 +416,19 @@
     public void testReadExifDataFromLgG4Iso800Dng() throws Throwable {
         testExifInterfaceForRaw(LG_G4_ISO_800_DNG, R.array.lg_g4_iso_800_dng);
     }
+
+    public void testCorruptedImage() throws Throwable {
+        byte[] bytes = new byte[1024];
+        try {
+            new ExifInterface(new ByteArrayInputStream(bytes));
+            fail("Should not reach here!");
+        } catch (IOException e) {
+            // Success
+        }
+    }
+
+    public void testReadExifDataFromVolantisJpg() throws Throwable {
+        // Test if it is possible to parse the volantis generated JPEG smoothly.
+        testExifInterfaceForJpeg(VOLANTIS_JPEG, R.array.volantis_jpg);
+    }
 }
diff --git a/opengl/java/android/opengl/GLES30.java b/opengl/java/android/opengl/GLES30.java
index 9c3b505..74181c5 100644
--- a/opengl/java/android/opengl/GLES30.java
+++ b/opengl/java/android/opengl/GLES30.java
@@ -889,7 +889,10 @@
     );
 
     // C function void glGetTransformFeedbackVarying ( GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name )
-
+    /**
+     * @deprecated
+     * Use the version that takes a ByteBuffer as the last argument, or the versions that return a String.
+     * */
     public static native void glGetTransformFeedbackVarying(
         int program,
         int index,
@@ -902,6 +905,18 @@
 
     // C function void glGetTransformFeedbackVarying ( GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name )
 
+    public static native void glGetTransformFeedbackVarying(
+        int program,
+        int index,
+        int bufsize,
+        java.nio.IntBuffer length,
+        java.nio.IntBuffer size,
+        java.nio.IntBuffer type,
+        java.nio.ByteBuffer name
+    );
+
+    // C function void glGetTransformFeedbackVarying ( GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name )
+
     public static native String glGetTransformFeedbackVarying(
         int program,
         int index,
diff --git a/packages/DocumentsUI/Android.mk b/packages/DocumentsUI/Android.mk
index e1650e1..d5e48b5 100644
--- a/packages/DocumentsUI/Android.mk
+++ b/packages/DocumentsUI/Android.mk
@@ -30,9 +30,12 @@
   --extra-packages android.support.design \
   --extra-packages android.support.v7.recyclerview
 
+LOCAL_JACK_FLAGS := \
+  -D jack.assert.policy=enable \
+  -D jack.optimization.inner-class.accessors=true
+
 LOCAL_PACKAGE_NAME := DocumentsUI
 LOCAL_CERTIFICATE := platform
 
 include $(BUILD_PACKAGE)
-
-include $(LOCAL_PATH)/tests/Android.mk
+include $(call all-makefiles-under, $(LOCAL_PATH))
diff --git a/packages/DocumentsUI/AndroidManifest.xml b/packages/DocumentsUI/AndroidManifest.xml
index 637e06e..6f38e25 100644
--- a/packages/DocumentsUI/AndroidManifest.xml
+++ b/packages/DocumentsUI/AndroidManifest.xml
@@ -40,18 +40,6 @@
         </activity>
 
         <activity
-            android:name=".DownloadsActivity"
-            android:theme="@style/DocumentsTheme"
-            android:label="@string/downloads_label"
-            android:icon="@drawable/ic_doc_text">
-            <intent-filter>
-                <action android:name="android.provider.action.MANAGE_ROOT" />
-                <category android:name="android.intent.category.DEFAULT" />
-                <data android:mimeType="vnd.android.document/root" />
-            </intent-filter>
-        </activity>
-
-        <activity
             android:name=".LauncherActivity"
             android:theme="@android:style/Theme.NoDisplay"
             android:icon="@drawable/ic_files_app"
@@ -72,6 +60,10 @@
                 <action android:name="android.intent.action.MAIN" />
             </intent-filter>
             <intent-filter>
+                <action android:name="android.intent.action.VIEW_DOWNLOADS" />
+                <category android:name="android.intent.category.DEFAULT" />
+            </intent-filter>
+            <intent-filter>
                 <action android:name="android.provider.action.BROWSE" />
                 <category android:name="android.intent.category.DEFAULT" />
                 <data android:mimeType="vnd.android.document/root" />
diff --git a/packages/DocumentsUI/perf-tests/Android.mk b/packages/DocumentsUI/perf-tests/Android.mk
new file mode 100644
index 0000000..11c163b
--- /dev/null
+++ b/packages/DocumentsUI/perf-tests/Android.mk
@@ -0,0 +1,22 @@
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+#LOCAL_SDK_VERSION := current
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src) \
+    $(call all-java-files-under, ../tests/src/com/android/documentsui/bots) \
+    ../tests/src/com/android/documentsui/ActivityTest.java \
+    ../tests/src/com/android/documentsui/DocumentsProviderHelper.java \
+    ../tests/src/com/android/documentsui/StubProvider.java
+
+LOCAL_JAVA_LIBRARIES := android-support-v4 android.test.runner
+LOCAL_STATIC_JAVA_LIBRARIES := mockito-target ub-uiautomator
+
+LOCAL_PACKAGE_NAME := DocumentsUIPerfTests
+LOCAL_INSTRUMENTATION_FOR := DocumentsUI
+
+LOCAL_CERTIFICATE := platform
+
+include $(BUILD_PACKAGE)
+
diff --git a/packages/DocumentsUI/perf-tests/AndroidManifest.xml b/packages/DocumentsUI/perf-tests/AndroidManifest.xml
new file mode 100644
index 0000000..97353e7
--- /dev/null
+++ b/packages/DocumentsUI/perf-tests/AndroidManifest.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.android.documentsui.perftests">
+
+    <application>
+        <uses-library android:name="android.test.runner" />
+        <provider
+            android:name="com.android.documentsui.StressProvider"
+            android:authorities="com.android.documentsui.stressprovider"
+            android:exported="true"
+            android:grantUriPermissions="true"
+            android:permission="android.permission.MANAGE_DOCUMENTS"
+            android:enabled="true">
+            <intent-filter>
+                <action android:name="android.content.action.DOCUMENTS_PROVIDER" />
+            </intent-filter>
+        </provider>
+    </application>
+
+    <instrumentation android:name="android.test.InstrumentationTestRunner"
+        android:targetPackage="com.android.documentsui"
+        android:label="Performance tests for DocumentsUI" />
+
+</manifest>
diff --git a/packages/DocumentsUI/perf-tests/src/com/android/documentsui/FilesActivityPerfTest.java b/packages/DocumentsUI/perf-tests/src/com/android/documentsui/FilesActivityPerfTest.java
new file mode 100644
index 0000000..bf056f1
--- /dev/null
+++ b/packages/DocumentsUI/perf-tests/src/com/android/documentsui/FilesActivityPerfTest.java
@@ -0,0 +1,143 @@
+/*
+ * 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.documentsui;
+
+import static com.android.documentsui.StressProvider.DEFAULT_AUTHORITY;
+import static com.android.documentsui.StressProvider.STRESS_ROOT_0_ID;
+import static com.android.documentsui.StressProvider.STRESS_ROOT_1_ID;
+
+import android.app.Activity;
+import android.net.Uri;
+import android.os.Bundle;
+import android.os.RemoteException;
+import android.test.suitebuilder.annotation.LargeTest;
+import android.util.Log;
+import android.view.KeyEvent;
+
+import com.android.documentsui.model.RootInfo;
+import com.android.documentsui.EventListener;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Random;
+import java.util.concurrent.CountDownLatch;
+
+@LargeTest
+public class FilesActivityPerfTest extends ActivityTest<FilesActivity> {
+
+    // Constants starting with KEY_ are used to report metrics to APCT.
+    private static final String KEY_FILES_LISTED_PERFORMANCE_FIRST =
+            "files-listed-performance-first";
+
+    private static final String KEY_FILES_LISTED_PERFORMANCE_MEDIAN =
+            "files-listed-performance-median";
+
+    private static final String TESTED_URI =
+            "content://com.android.documentsui.stressprovider/document/STRESS_ROOT_1_DOC";
+
+    private static final int NUM_MEASUREMENTS = 10;
+
+    public FilesActivityPerfTest() {
+        super(FilesActivity.class);
+    }
+
+    @Override
+    protected RootInfo getInitialRoot() {
+        return rootDir0;
+    }
+
+    @Override
+    protected String getTestingProviderAuthority() {
+        return DEFAULT_AUTHORITY;
+    }
+
+    @Override
+    protected void setupTestingRoots() throws RemoteException {
+        rootDir0 = mDocsHelper.getRoot(STRESS_ROOT_0_ID);
+        rootDir1 = mDocsHelper.getRoot(STRESS_ROOT_1_ID);
+    }
+
+    @Override
+    public void initTestFiles() throws RemoteException {
+        // Nothing to create, already done by StressProvider.
+    }
+
+    public void testFilesListedPerformance() throws Exception {
+        final BaseActivity activity = getActivity();
+
+        final List<Long> measurements = new ArrayList<Long>();
+        EventListener listener;
+        for (int i = 0; i < 10; i++) {
+            final CountDownLatch signal = new CountDownLatch(1);
+            listener = new EventListener() {
+                @Override
+                public void onDirectoryNavigated(Uri uri) {
+                    if (uri != null && TESTED_URI.equals(uri.toString())) {
+                        mStartTime = System.currentTimeMillis();
+                    } else {
+                        mStartTime = -1;
+                    }
+                }
+
+                @Override
+                public void onDirectoryLoaded(Uri uri) {
+                    if (uri == null || !TESTED_URI.equals(uri.toString())) {
+                        return;
+                    }
+                    assertTrue(mStartTime != -1);
+                    getInstrumentation().waitForIdle(new Runnable() {
+                        @Override
+                        public void run() {
+                            assertTrue(mStartTime != -1);
+                            measurements.add(System.currentTimeMillis() - mStartTime);
+                            signal.countDown();
+                        }
+                    });
+                }
+
+                private long mStartTime = -1;
+            };
+
+            try {
+                activity.addEventListener(listener);
+                bots.roots.openRoot(STRESS_ROOT_1_ID);
+                signal.await();
+            } finally {
+                activity.removeEventListener(listener);
+            }
+
+            assertEquals(i + 1, measurements.size());
+
+            // Go back to the empty root.
+            bots.roots.openRoot(STRESS_ROOT_0_ID);
+        }
+
+        assertEquals(NUM_MEASUREMENTS, measurements.size());
+
+        final Bundle status = new Bundle();
+        status.putDouble(KEY_FILES_LISTED_PERFORMANCE_FIRST, measurements.get(0));
+
+        final Long[] rawMeasurements = measurements.toArray(new Long[NUM_MEASUREMENTS]);
+        Arrays.sort(rawMeasurements);
+
+        final long median = rawMeasurements[NUM_MEASUREMENTS / 2 - 1];
+        status.putDouble(KEY_FILES_LISTED_PERFORMANCE_MEDIAN, median);
+
+        getInstrumentation().sendStatus(Activity.RESULT_OK, status);
+    }
+}
diff --git a/packages/DocumentsUI/perf-tests/src/com/android/documentsui/StressProvider.java b/packages/DocumentsUI/perf-tests/src/com/android/documentsui/StressProvider.java
new file mode 100644
index 0000000..1bc802a
--- /dev/null
+++ b/packages/DocumentsUI/perf-tests/src/com/android/documentsui/StressProvider.java
@@ -0,0 +1,149 @@
+/*
+ * 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.documentsui;
+
+import android.content.Context;
+import android.content.pm.ProviderInfo;
+import android.database.Cursor;
+import android.database.MatrixCursor.RowBuilder;
+import android.database.MatrixCursor;
+import android.os.CancellationSignal;
+import android.os.FileUtils;
+import android.os.ParcelFileDescriptor;
+import android.provider.DocumentsContract.Document;
+import android.provider.DocumentsContract.Root;
+import android.provider.DocumentsContract;
+import android.provider.DocumentsProvider;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Random;
+
+/**
+ * Provider with thousands of files for testing loading time of directories in DocumentsUI.
+ * It doesn't support any file operations.
+ */
+public class StressProvider extends DocumentsProvider {
+
+    public static final String DEFAULT_AUTHORITY = "com.android.documentsui.stressprovider";
+
+    // Empty root.
+    public static final String STRESS_ROOT_0_ID = "STRESS_ROOT_0";
+
+    // Root with thousands of items.
+    public static final String STRESS_ROOT_1_ID = "STRESS_ROOT_1";
+
+    private static final String STRESS_ROOT_0_DOC_ID = "STRESS_ROOT_0_DOC";
+    private static final String STRESS_ROOT_1_DOC_ID = "STRESS_ROOT_1_DOC";
+
+    private static final String[] DEFAULT_ROOT_PROJECTION = new String[] {
+            Root.COLUMN_ROOT_ID, Root.COLUMN_FLAGS, Root.COLUMN_TITLE, Root.COLUMN_DOCUMENT_ID,
+            Root.COLUMN_AVAILABLE_BYTES
+    };
+    private static final String[] DEFAULT_DOCUMENT_PROJECTION = new String[] {
+            Document.COLUMN_DOCUMENT_ID, Document.COLUMN_MIME_TYPE, Document.COLUMN_DISPLAY_NAME,
+            Document.COLUMN_LAST_MODIFIED, Document.COLUMN_FLAGS, Document.COLUMN_SIZE,
+    };
+
+    private String mAuthority = DEFAULT_AUTHORITY;
+    private ArrayList<String> mIds = new ArrayList<>();
+
+    @Override
+    public void attachInfo(Context context, ProviderInfo info) {
+        mAuthority = info.authority;
+        super.attachInfo(context, info);
+    }
+
+    @Override
+    public boolean onCreate() {
+        mIds = new ArrayList();
+        for (int i = 0; i < 10000; i++) {
+            mIds.add(createRandomId(i));
+        }
+        mIds.add(STRESS_ROOT_0_DOC_ID);
+        mIds.add(STRESS_ROOT_1_DOC_ID);
+        return true;
+    }
+
+    @Override
+    public Cursor queryRoots(String[] projection) throws FileNotFoundException {
+        final MatrixCursor result = new MatrixCursor(DEFAULT_ROOT_PROJECTION);
+        includeRoot(result, STRESS_ROOT_0_ID, STRESS_ROOT_0_DOC_ID);
+        includeRoot(result, STRESS_ROOT_1_ID, STRESS_ROOT_1_DOC_ID);
+        return result;
+    }
+
+    @Override
+    public Cursor queryDocument(String documentId, String[] projection)
+            throws FileNotFoundException {
+        final MatrixCursor result = new MatrixCursor(DEFAULT_DOCUMENT_PROJECTION);
+        includeDocument(result, documentId);
+        return result;
+    }
+
+    @Override
+    public Cursor queryChildDocuments(String parentDocumentId, String[] projection, String sortOrder)
+            throws FileNotFoundException {
+        final MatrixCursor result = new MatrixCursor(DEFAULT_DOCUMENT_PROJECTION);
+        if (STRESS_ROOT_1_DOC_ID.equals(parentDocumentId)) {
+            for (String id : mIds) {
+                includeDocument(result, id);
+            }
+        }
+        return result;
+    }
+
+    @Override
+    public ParcelFileDescriptor openDocument(String docId, String mode, CancellationSignal signal)
+            throws FileNotFoundException {
+        throw new UnsupportedOperationException();
+    }
+
+    private void includeRoot(MatrixCursor result, String rootId, String docId) {
+        final RowBuilder row = result.newRow();
+        row.add(Root.COLUMN_ROOT_ID, rootId);
+        row.add(Root.COLUMN_FLAGS, 0);
+        row.add(Root.COLUMN_TITLE, rootId);
+        row.add(Root.COLUMN_DOCUMENT_ID, docId);
+    }
+
+    private void includeDocument(MatrixCursor result, String id) {
+        final RowBuilder row = result.newRow();
+        row.add(Document.COLUMN_DOCUMENT_ID, id);
+        row.add(Document.COLUMN_DISPLAY_NAME, id);
+        row.add(Document.COLUMN_SIZE, 0);
+        row.add(Document.COLUMN_MIME_TYPE, DocumentsContract.Document.MIME_TYPE_DIR);
+        row.add(Document.COLUMN_FLAGS, 0);
+        row.add(Document.COLUMN_LAST_MODIFIED, null);
+    }
+
+    private static String getDocumentIdForFile(File file) {
+        return file.getAbsolutePath();
+    }
+
+    private String createRandomId(int index) {
+        final Random random = new Random(index);
+        final StringBuilder builder = new StringBuilder();
+        for (int i = 0; i < 20; i++) {
+            builder.append((char) (random.nextInt(96) + 32));
+        }
+        builder.append(index);  // Append a number to guarantee uniqueness.
+        return builder.toString();
+    }
+}
diff --git a/packages/DocumentsUI/res/animator/dir_enter.xml b/packages/DocumentsUI/res/animator/dir_enter.xml
index 7f547f1..7daf1c0 100644
--- a/packages/DocumentsUI/res/animator/dir_enter.xml
+++ b/packages/DocumentsUI/res/animator/dir_enter.xml
@@ -13,10 +13,23 @@
      limitations under the License.
 -->
 
-<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
-    android:valueFrom="1"
-    android:valueTo="0"
-    android:propertyName="position"
-    android:valueType="floatType"
-    android:duration="@android:integer/config_mediumAnimTime"
-    android:interpolator="@android:interpolator/decelerate_quad" />
+<set xmlns:android="http://schemas.android.com/apk/res/android"
+    android:ordering="together">
+
+    <objectAnimator
+        android:valueFrom="0f"
+        android:valueTo="1f"
+        android:propertyName="alpha"
+        android:valueType="floatType"
+        android:duration="@android:integer/config_mediumAnimTime"
+        android:interpolator="@android:interpolator/decelerate_quad" />
+
+    <objectAnimator
+        android:propertyName="position"
+        android:valueFrom="1"
+        android:valueTo="0"
+        android:valueType="floatType"
+        android:duration="@android:integer/config_mediumAnimTime"
+        android:interpolator="@android:interpolator/decelerate_quad" />
+
+</set>
diff --git a/packages/DocumentsUI/res/animator/dir_leave.xml b/packages/DocumentsUI/res/animator/dir_leave.xml
index fda0faf..de09638 100644
--- a/packages/DocumentsUI/res/animator/dir_leave.xml
+++ b/packages/DocumentsUI/res/animator/dir_leave.xml
@@ -13,10 +13,23 @@
      limitations under the License.
 -->
 
-<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
-    android:valueFrom="0"
-    android:valueTo="1"
-    android:propertyName="position"
-    android:valueType="floatType"
-    android:duration="@android:integer/config_mediumAnimTime"
-    android:interpolator="@android:interpolator/accelerate_quad" />
+<set xmlns:android="http://schemas.android.com/apk/res/android"
+    android:ordering="together">
+
+    <objectAnimator
+        android:valueFrom="1f"
+        android:valueTo="0f"
+        android:propertyName="alpha"
+        android:valueType="floatType"
+        android:duration="@android:integer/config_mediumAnimTime"
+        android:interpolator="@android:interpolator/decelerate_quad" />
+
+    <objectAnimator
+        android:valueFrom="0"
+        android:valueTo="1"
+        android:propertyName="position"
+        android:valueType="floatType"
+        android:duration="@android:integer/config_mediumAnimTime"
+        android:interpolator="@android:interpolator/accelerate_quad" />
+
+</set>
\ No newline at end of file
diff --git a/packages/DocumentsUI/res/animator/fade_in.xml b/packages/DocumentsUI/res/animator/fade_in.xml
new file mode 100644
index 0000000..3ce012b
--- /dev/null
+++ b/packages/DocumentsUI/res/animator/fade_in.xml
@@ -0,0 +1,22 @@
+<!-- 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.
+-->
+
+<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
+    android:valueFrom="0f"
+    android:valueTo="1f"
+    android:propertyName="alpha"
+    android:valueType="floatType"
+    android:duration="@android:integer/config_mediumAnimTime"
+    android:interpolator="@android:interpolator/decelerate_quad" />
diff --git a/packages/DocumentsUI/res/animator/fade_out.xml b/packages/DocumentsUI/res/animator/fade_out.xml
new file mode 100644
index 0000000..8d02c77
--- /dev/null
+++ b/packages/DocumentsUI/res/animator/fade_out.xml
@@ -0,0 +1,22 @@
+<!-- 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.
+-->
+
+<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
+    android:valueFrom="1f"
+    android:valueTo="0f"
+    android:propertyName="alpha"
+    android:valueType="floatType"
+    android:duration="@android:integer/config_mediumAnimTime"
+    android:interpolator="@android:interpolator/decelerate_quad" />
diff --git a/packages/DocumentsUI/res/color/item_details.xml b/packages/DocumentsUI/res/color/item_details.xml
new file mode 100644
index 0000000..769b944
--- /dev/null
+++ b/packages/DocumentsUI/res/color/item_details.xml
@@ -0,0 +1,26 @@
+<?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.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item
+        android:state_enabled="true"
+        android:color="?android:attr/textColorPrimary"
+        android:alpha="0.63" />
+    <item
+        android:state_enabled="false"
+        android:color="?android:attr/textColorPrimary"
+        android:alpha="0.3" />
+</selector>
diff --git a/packages/SystemUI/res/drawable/qs_background_secondary.xml b/packages/DocumentsUI/res/color/item_title.xml
similarity index 61%
copy from packages/SystemUI/res/drawable/qs_background_secondary.xml
copy to packages/DocumentsUI/res/color/item_title.xml
index 31c0162..ef6aea3 100644
--- a/packages/SystemUI/res/drawable/qs_background_secondary.xml
+++ b/packages/DocumentsUI/res/color/item_title.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2014 The Android Open Source Project
+<!-- Copyright (C) 2016 The Android Open Source Project
 
      Licensed under the Apache License, Version 2.0 (the "License");
      you may not use this file except in compliance with the License.
@@ -13,9 +13,13 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-<shape xmlns:android="http://schemas.android.com/apk/res/android">
-    <solid android:color="@color/system_secondary_color" />
-    <corners
-        android:topLeftRadius="0dp"
-        android:topRightRadius="0dp" />
-</shape>
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item
+        android:state_enabled="true"
+        android:color="?android:attr/textColorPrimary" />
+    <item
+        android:state_enabled="false"
+        android:color="?android:attr/textColorPrimary"
+        android:alpha="0.3" />
+</selector>
diff --git a/packages/DocumentsUI/res/drawable/ic_breadcrumb_arrow_down.xml b/packages/DocumentsUI/res/drawable/ic_breadcrumb_arrow_down.xml
new file mode 100644
index 0000000..199a308
--- /dev/null
+++ b/packages/DocumentsUI/res/drawable/ic_breadcrumb_arrow_down.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<rotate xmlns:android="http://schemas.android.com/apk/res/android"
+        android:fromDegrees="90"
+        android:toDegrees="90"
+        android:pivotX="50%"
+        android:pivotY="50%"
+        android:drawable="@drawable/ic_breadcrumb_arrow">
+</rotate>
\ No newline at end of file
diff --git a/packages/DocumentsUI/res/drawable/ic_sd_storage.xml b/packages/DocumentsUI/res/drawable/ic_sd_storage.xml
index b0f3cc3..5aeebbb 100644
--- a/packages/DocumentsUI/res/drawable/ic_sd_storage.xml
+++ b/packages/DocumentsUI/res/drawable/ic_sd_storage.xml
@@ -14,8 +14,8 @@
     limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="48dp"
-        android:height="48dp"
+        android:width="24dp"
+        android:height="24dp"
         android:viewportWidth="24.0"
         android:viewportHeight="24.0">
     <path
diff --git a/packages/DocumentsUI/res/drawable/ic_usb_storage.xml b/packages/DocumentsUI/res/drawable/ic_usb_storage.xml
new file mode 100644
index 0000000..2a8d024
--- /dev/null
+++ b/packages/DocumentsUI/res/drawable/ic_usb_storage.xml
@@ -0,0 +1,24 @@
+<!--
+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.
+-->
+<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="M15 7v4h1v2h-3V5h2l-3,-4,-3 4h2v8H8v-2.07c.7,-.37 1.2,-1.08 1.2,-1.93 0,-1.21,-.99,-2.2,-2.2,-2.2,-1.21 0,-2.2.99,-2.2 2.2 0 .85.5 1.56 1.2 1.93V13c0 1.11.89 2 2 2h3v3.05c-.71.37,-1.2 1.1,-1.2 1.95 0 1.22.99 2.2 2.2 2.2 1.21 0 2.2,-.98 2.2,-2.2 0,-.85,-.49,-1.58,-1.2,-1.95V15h3c1.11 0 2,-.89 2,-2v-2h1V7h-4z"/>
+</vector>
diff --git a/packages/DocumentsUI/res/layout/dialog_delete_confirmation.xml b/packages/DocumentsUI/res/layout/dialog_delete_confirmation.xml
new file mode 100644
index 0000000..a1c2910
--- /dev/null
+++ b/packages/DocumentsUI/res/layout/dialog_delete_confirmation.xml
@@ -0,0 +1,26 @@
+<?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.
+-->
+
+<TextView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:paddingTop="24dp"
+    android:paddingStart="24dp"
+    android:paddingEnd="24dp"
+    android:textAppearance="@android:style/TextAppearance.Material.Subhead"
+    android:textColor="@*android:color/primary_text_default_material_light">
+</TextView>
diff --git a/packages/DocumentsUI/res/layout/drawer_layout.xml b/packages/DocumentsUI/res/layout/drawer_layout.xml
index 065102b..b65c5a0 100644
--- a/packages/DocumentsUI/res/layout/drawer_layout.xml
+++ b/packages/DocumentsUI/res/layout/drawer_layout.xml
@@ -46,6 +46,8 @@
                     android:layout_width="wrap_content"
                     android:layout_height="wrap_content"
                     android:layout_marginStart="4dp"
+                    android:popupTheme="?actionBarPopupTheme"
+                    android:background="@android:color/transparent"
                     android:overlapAnchor="true" />
 
             </com.android.documentsui.DocumentsToolbar>
diff --git a/packages/DocumentsUI/res/layout/fixed_layout.xml b/packages/DocumentsUI/res/layout/fixed_layout.xml
index 84a928d..deb0894 100644
--- a/packages/DocumentsUI/res/layout/fixed_layout.xml
+++ b/packages/DocumentsUI/res/layout/fixed_layout.xml
@@ -44,6 +44,8 @@
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
                 android:layout_marginStart="4dp"
+                android:popupTheme="?actionBarPopupTheme"
+                android:background="@android:color/transparent"
                 android:overlapAnchor="true" />
 
         </com.android.documentsui.DocumentsToolbar>
diff --git a/packages/DocumentsUI/res/layout/item_dir_grid.xml b/packages/DocumentsUI/res/layout/item_dir_grid.xml
index a4f06d1..429a972 100644
--- a/packages/DocumentsUI/res/layout/item_dir_grid.xml
+++ b/packages/DocumentsUI/res/layout/item_dir_grid.xml
@@ -66,7 +66,7 @@
             android:singleLine="true"
             android:textAlignment="viewStart"
             android:textAppearance="@android:style/TextAppearance.Material.Subhead"
-            android:textColor="@*android:color/primary_text_default_material_light" />
+            android:textColor="@color/item_title" />
 
     </LinearLayout>
 
diff --git a/packages/DocumentsUI/res/layout/item_doc_grid.xml b/packages/DocumentsUI/res/layout/item_doc_grid.xml
index af1703f..56a061f 100644
--- a/packages/DocumentsUI/res/layout/item_doc_grid.xml
+++ b/packages/DocumentsUI/res/layout/item_doc_grid.xml
@@ -93,7 +93,7 @@
             android:ellipsize="end"
             android:textAlignment="viewStart"
             android:textAppearance="@android:style/TextAppearance.Material.Subhead"
-            android:textColor="@*android:color/primary_text_default_material_light" />
+            android:textColor="@color/item_title" />
 
         <TextView
             android:id="@+id/size"
@@ -106,7 +106,7 @@
             android:ellipsize="end"
             android:textAlignment="viewStart"
             android:textAppearance="@android:style/TextAppearance.Material.Caption"
-            android:textColor="@*android:color/primary_text_default_material_light" />
+            android:textColor="@color/item_details" />
 
         <TextView
             android:id="@+id/date"
@@ -118,7 +118,7 @@
             android:ellipsize="end"
             android:textAlignment="viewStart"
             android:textAppearance="@android:style/TextAppearance.Material.Caption"
-            android:textColor="@*android:color/primary_text_default_material_light" />
+            android:textColor="@color/item_details" />
 
     </RelativeLayout>
 
diff --git a/packages/DocumentsUI/res/layout/item_doc_list.xml b/packages/DocumentsUI/res/layout/item_doc_list.xml
index b169ec8..a939fcd 100644
--- a/packages/DocumentsUI/res/layout/item_doc_list.xml
+++ b/packages/DocumentsUI/res/layout/item_doc_list.xml
@@ -73,7 +73,8 @@
             android:layout_width="0dp"
             android:layout_height="wrap_content"
             android:layout_weight="1"
-            android:orientation="vertical" >
+            android:orientation="vertical"
+            android:layout_gravity="center_vertical" >
 
             <TextView
                 android:id="@android:id/title"
@@ -84,7 +85,7 @@
                 android:singleLine="true"
                 android:textAlignment="viewStart"
                 android:textAppearance="@android:style/TextAppearance.Material.Subhead"
-                android:textColor="?android:attr/textColorPrimary" />
+                android:textColor="@color/item_title" />
 
             <LinearLayout
                 android:id="@+id/line2"
@@ -101,8 +102,8 @@
                     android:ellipsize="end"
                     android:singleLine="true"
                     android:textAlignment="viewStart"
-                    android:textAppearance="@android:style/TextAppearance.Material.Body1"
-                    android:textColor="?android:attr/textColorSecondary" />
+                    android:textAppearance="@android:style/TextAppearance.Material.Caption"
+                    android:textColor="@color/item_details" />
 
                 <TextView
                     android:id="@+id/size"
@@ -112,8 +113,8 @@
                     android:ellipsize="end"
                     android:singleLine="true"
                     android:textAlignment="viewStart"
-                    android:textAppearance="@android:style/TextAppearance.Material.Body1"
-                    android:textColor="?android:attr/textColorSecondary" />
+                    android:textAppearance="@android:style/TextAppearance.Material.Caption"
+                    android:textColor="@color/item_details" />
 
                 <TextView
                     android:id="@android:id/summary"
@@ -124,8 +125,8 @@
                     android:ellipsize="end"
                     android:singleLine="true"
                     android:textAlignment="viewStart"
-                    android:textAppearance="@android:style/TextAppearance.Material.Body1"
-                    android:textColor="?android:attr/textColorSecondary" />
+                    android:textAppearance="@android:style/TextAppearance.Material.Caption"
+                    android:textColor="@color/item_details" />
             </LinearLayout>
         </LinearLayout>
     </LinearLayout>
diff --git a/packages/DocumentsUI/res/layout/item_root.xml b/packages/DocumentsUI/res/layout/item_root.xml
index ff80d07..816cb8a 100644
--- a/packages/DocumentsUI/res/layout/item_root.xml
+++ b/packages/DocumentsUI/res/layout/item_root.xml
@@ -27,8 +27,6 @@
     <FrameLayout
         android:layout_width="@dimen/icon_size"
         android:layout_height="@dimen/icon_size"
-        android:layout_marginStart="@dimen/root_icon_margin"
-        android:layout_marginEnd="@dimen/root_icon_margin"
         android:duplicateParentState="true">
 
         <ImageView
@@ -55,7 +53,7 @@
             android:singleLine="true"
             android:ellipsize="end"
             android:textAlignment="viewStart"
-            android:textAppearance="@android:style/TextAppearance.Material.Body1"
+            android:textAppearance="@android:style/TextAppearance.Material.Menu"
             android:textColor="@color/item_root_primary_text" />
 
         <TextView
@@ -65,7 +63,7 @@
             android:singleLine="true"
             android:ellipsize="end"
             android:textAlignment="viewStart"
-            android:textAppearance="@android:style/TextAppearance.Material.Body1"
+            android:textAppearance="@android:style/TextAppearance.Material.Caption"
             android:textColor="@color/item_root_primary_text" />
 
     </LinearLayout>
diff --git a/packages/DocumentsUI/res/layout/item_subdir.xml b/packages/DocumentsUI/res/layout/item_subdir.xml
index b8251d1..ffe4afe 100644
--- a/packages/DocumentsUI/res/layout/item_subdir.xml
+++ b/packages/DocumentsUI/res/layout/item_subdir.xml
@@ -24,16 +24,6 @@
     android:orientation="horizontal"
     android:baselineAligned="false">
 
-    <ImageView
-        android:id="@+id/subdir"
-        android:layout_width="24dp"
-        android:layout_height="24dp"
-        android:paddingEnd="8dp"
-        android:scaleType="centerInside"
-        android:visibility="gone"
-        android:src="@drawable/ic_subdirectory_arrow"
-        android:contentDescription="@null" />
-
     <TextView
         android:id="@android:id/title"
         android:layout_width="0dp"
diff --git a/packages/DocumentsUI/res/layout/item_subdir_title.xml b/packages/DocumentsUI/res/layout/item_subdir_title.xml
index de6c523..8d0d807 100644
--- a/packages/DocumentsUI/res/layout/item_subdir_title.xml
+++ b/packages/DocumentsUI/res/layout/item_subdir_title.xml
@@ -28,6 +28,7 @@
         android:singleLine="true"
         android:ellipsize="end"
         android:textAlignment="viewStart"
+        android:drawablePadding="12dp"
+        android:drawableRight="@drawable/ic_breadcrumb_arrow_down"
         android:textAppearance="@android:style/TextAppearance.DeviceDefault.Widget.ActionBar.Title" />
-
 </LinearLayout>
diff --git a/packages/DocumentsUI/res/layout/single_pane_layout.xml b/packages/DocumentsUI/res/layout/single_pane_layout.xml
index 235d22d..7b7e229 100644
--- a/packages/DocumentsUI/res/layout/single_pane_layout.xml
+++ b/packages/DocumentsUI/res/layout/single_pane_layout.xml
@@ -43,6 +43,8 @@
                 android:id="@+id/stack"
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
+                android:popupTheme="?actionBarPopupTheme"
+                android:background="@android:color/transparent"
                 android:layout_marginStart="4dp"
                 android:overlapAnchor="true" />
 
diff --git a/packages/DocumentsUI/res/menu/activity.xml b/packages/DocumentsUI/res/menu/activity.xml
index 73571af..2aee569 100644
--- a/packages/DocumentsUI/res/menu/activity.xml
+++ b/packages/DocumentsUI/res/menu/activity.xml
@@ -66,7 +66,7 @@
         android:id="@+id/menu_sort"
         android:title="@string/menu_sort"
         android:icon="@drawable/ic_menu_sortby"
-        android:showAsAction="never">
+        android:showAsAction="ifRoom">
         <menu>
             <item
                 android:id="@+id/menu_sort_name"
@@ -84,10 +84,6 @@
         android:showAsAction="never"
         android:visible="false" />
     <item
-        android:id="@+id/menu_advanced"
-        android:showAsAction="never"
-        android:visible="false" />
-    <item
         android:id="@+id/menu_settings"
         android:title="@string/menu_settings"
         android:showAsAction="never"
diff --git a/packages/DocumentsUI/res/values-af/config.xml b/packages/DocumentsUI/res/values-af/config.xml
deleted file mode 100644
index 843a8aa..0000000
--- a/packages/DocumentsUI/res/values-af/config.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--  Copyright (C) 2015 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="trusted_quick_viewer_package" msgid="3354383993907861267"></string>
-</resources>
diff --git a/packages/DocumentsUI/res/values-af/strings.xml b/packages/DocumentsUI/res/values-af/strings.xml
index b8bc289..6fff804 100644
--- a/packages/DocumentsUI/res/values-af/strings.xml
+++ b/packages/DocumentsUI/res/values-af/strings.xml
@@ -67,6 +67,7 @@
     <string name="share_via" msgid="8966594246261344259">"Deel via"</string>
     <string name="copy_notification_title" msgid="6374299806748219777">"Kopieer tans lêers"</string>
     <string name="move_notification_title" msgid="6193835179777284805">"Skuif tans lêers"</string>
+    <string name="delete_notification_title" msgid="3329403967712437496">"Vee tans lêers uit"</string>
     <string name="copy_remaining" msgid="6283790937387975095">"<xliff:g id="DURATION">%s</xliff:g> oor"</string>
     <plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
       <item quantity="other">Kopieer tans <xliff:g id="COUNT_1">%1$d</xliff:g> lêers.</item>
@@ -111,4 +112,12 @@
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Sommige lêers is omgeskakel"</string>
     <string name="allow" msgid="7225948811296386551">"Laat toe"</string>
     <string name="deny" msgid="2081879885755434506">"Weier"</string>
+    <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772">
+      <item quantity="other">Vee <xliff:g id="COUNT_1">%1$d</xliff:g> lêers uit?</item>
+      <item quantity="one">Vee <xliff:g id="COUNT_0">%1$d</xliff:g> lêer uit?</item>
+    </plurals>
+    <plurals name="elements_selected" formatted="false" msgid="1376955402452875047">
+      <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> gekies</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> gekies</item>
+    </plurals>
 </resources>
diff --git a/packages/DocumentsUI/res/values-am/config.xml b/packages/DocumentsUI/res/values-am/config.xml
deleted file mode 100644
index 843a8aa..0000000
--- a/packages/DocumentsUI/res/values-am/config.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--  Copyright (C) 2015 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="trusted_quick_viewer_package" msgid="3354383993907861267"></string>
-</resources>
diff --git a/packages/DocumentsUI/res/values-am/strings.xml b/packages/DocumentsUI/res/values-am/strings.xml
index f28c433..c61db57 100644
--- a/packages/DocumentsUI/res/values-am/strings.xml
+++ b/packages/DocumentsUI/res/values-am/strings.xml
@@ -67,6 +67,7 @@
     <string name="share_via" msgid="8966594246261344259">"በሚከተለው በኩል ያጋሩ"</string>
     <string name="copy_notification_title" msgid="6374299806748219777">"ፋይሎች በመገልበጥ ላይ"</string>
     <string name="move_notification_title" msgid="6193835179777284805">"ፋይሎችን በመውሰድ ላይ"</string>
+    <string name="delete_notification_title" msgid="3329403967712437496">"ፋይሎችን በመሰረዝ ላይ"</string>
     <string name="copy_remaining" msgid="6283790937387975095">"<xliff:g id="DURATION">%s</xliff:g> ቀርቷል"</string>
     <plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
       <item quantity="one"><xliff:g id="COUNT_1">%1$d</xliff:g> ፋይሎች በመቅዳት ላይ።</item>
@@ -111,4 +112,12 @@
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"አንዳንድ ፋይሎች ተለውጠዋል"</string>
     <string name="allow" msgid="7225948811296386551">"ይፍቀዱ"</string>
     <string name="deny" msgid="2081879885755434506">"ያስተባብሉ"</string>
+    <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772">
+      <item quantity="one"><xliff:g id="COUNT_1">%1$d</xliff:g> ፋይሎች ይሰረዙ?</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> ፋይሎች ይሰረዙ?</item>
+    </plurals>
+    <plurals name="elements_selected" formatted="false" msgid="1376955402452875047">
+      <item quantity="one"><xliff:g id="COUNT_1">%1$d</xliff:g> ተመርጠዋል</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> ተመርጠዋል</item>
+    </plurals>
 </resources>
diff --git a/packages/DocumentsUI/res/values-ar/config.xml b/packages/DocumentsUI/res/values-ar/config.xml
deleted file mode 100644
index 843a8aa..0000000
--- a/packages/DocumentsUI/res/values-ar/config.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--  Copyright (C) 2015 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="trusted_quick_viewer_package" msgid="3354383993907861267"></string>
-</resources>
diff --git a/packages/DocumentsUI/res/values-ar/strings.xml b/packages/DocumentsUI/res/values-ar/strings.xml
index c19e406..dcfef2a 100644
--- a/packages/DocumentsUI/res/values-ar/strings.xml
+++ b/packages/DocumentsUI/res/values-ar/strings.xml
@@ -67,6 +67,7 @@
     <string name="share_via" msgid="8966594246261344259">"مشاركة عبر"</string>
     <string name="copy_notification_title" msgid="6374299806748219777">"جارٍ نسخ الملفات"</string>
     <string name="move_notification_title" msgid="6193835179777284805">"نقل الملفات"</string>
+    <string name="delete_notification_title" msgid="3329403967712437496">"جارٍ حذف الملفات"</string>
     <string name="copy_remaining" msgid="6283790937387975095">"المدة المتبقية: <xliff:g id="DURATION">%s</xliff:g>"</string>
     <plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
       <item quantity="zero">جارٍ نسخ <xliff:g id="COUNT_1">%1$d</xliff:g> ملفات.</item>
@@ -139,4 +140,20 @@
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"تم تحويل بعض الملفات"</string>
     <string name="allow" msgid="7225948811296386551">"السماح"</string>
     <string name="deny" msgid="2081879885755434506">"رفض"</string>
+    <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772">
+      <item quantity="zero">هل تريد حذف <xliff:g id="COUNT_1">%1$d</xliff:g> ملف؟</item>
+      <item quantity="two">هل تريد حذف ملفين (<xliff:g id="COUNT_1">%1$d</xliff:g>)؟</item>
+      <item quantity="few">هل تريد حذف <xliff:g id="COUNT_1">%1$d</xliff:g> ملفات؟</item>
+      <item quantity="many">هل تريد حذف <xliff:g id="COUNT_1">%1$d</xliff:g> ملفًا؟</item>
+      <item quantity="other">هل تريد حذف <xliff:g id="COUNT_1">%1$d</xliff:g> ملف؟</item>
+      <item quantity="one">هل تريد حذف <xliff:g id="COUNT_0">%1$d</xliff:g> ملف؟</item>
+    </plurals>
+    <plurals name="elements_selected" formatted="false" msgid="1376955402452875047">
+      <item quantity="zero">تم تحديد <xliff:g id="COUNT_1">%1$d</xliff:g></item>
+      <item quantity="two">تم تحديد <xliff:g id="COUNT_1">%1$d</xliff:g></item>
+      <item quantity="few">تم تحديد <xliff:g id="COUNT_1">%1$d</xliff:g></item>
+      <item quantity="many">تم تحديد <xliff:g id="COUNT_1">%1$d</xliff:g></item>
+      <item quantity="other">تم تحديد <xliff:g id="COUNT_1">%1$d</xliff:g></item>
+      <item quantity="one">تم تحديد <xliff:g id="COUNT_0">%1$d</xliff:g></item>
+    </plurals>
 </resources>
diff --git a/packages/DocumentsUI/res/values-az-rAZ/config.xml b/packages/DocumentsUI/res/values-az-rAZ/config.xml
deleted file mode 100644
index 843a8aa..0000000
--- a/packages/DocumentsUI/res/values-az-rAZ/config.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--  Copyright (C) 2015 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="trusted_quick_viewer_package" msgid="3354383993907861267"></string>
-</resources>
diff --git a/packages/DocumentsUI/res/values-az-rAZ/strings.xml b/packages/DocumentsUI/res/values-az-rAZ/strings.xml
index dc9a390..e1505f8 100644
--- a/packages/DocumentsUI/res/values-az-rAZ/strings.xml
+++ b/packages/DocumentsUI/res/values-az-rAZ/strings.xml
@@ -67,6 +67,7 @@
     <string name="share_via" msgid="8966594246261344259">"Bunun vasitəsilə paylaş:"</string>
     <string name="copy_notification_title" msgid="6374299806748219777">"Fayllar kopyalanır"</string>
     <string name="move_notification_title" msgid="6193835179777284805">"Fayllar köçürülür"</string>
+    <string name="delete_notification_title" msgid="3329403967712437496">"Fayllar silinir"</string>
     <string name="copy_remaining" msgid="6283790937387975095">"<xliff:g id="DURATION">%s</xliff:g> qalıb"</string>
     <plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
       <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> fayl kopyalanır.</item>
@@ -111,4 +112,12 @@
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Bəzi fayllar konvertasiya edilib"</string>
     <string name="allow" msgid="7225948811296386551">"İcazə verin"</string>
     <string name="deny" msgid="2081879885755434506">"Rədd et"</string>
+    <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772">
+      <item quantity="other"> <xliff:g id="COUNT_1">%1$d</xliff:g> fayl silinsin?</item>
+      <item quantity="one"> <xliff:g id="COUNT_0">%1$d</xliff:g> fayl silinsin?</item>
+    </plurals>
+    <plurals name="elements_selected" formatted="false" msgid="1376955402452875047">
+      <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> seçilib</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> seçilib</item>
+    </plurals>
 </resources>
diff --git a/packages/DocumentsUI/res/values-b+sr+Latn/config.xml b/packages/DocumentsUI/res/values-b+sr+Latn/config.xml
deleted file mode 100644
index 843a8aa..0000000
--- a/packages/DocumentsUI/res/values-b+sr+Latn/config.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--  Copyright (C) 2015 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="trusted_quick_viewer_package" msgid="3354383993907861267"></string>
-</resources>
diff --git a/packages/DocumentsUI/res/values-b+sr+Latn/strings.xml b/packages/DocumentsUI/res/values-b+sr+Latn/strings.xml
index 1e1a2f7..b884a19 100644
--- a/packages/DocumentsUI/res/values-b+sr+Latn/strings.xml
+++ b/packages/DocumentsUI/res/values-b+sr+Latn/strings.xml
@@ -67,6 +67,7 @@
     <string name="share_via" msgid="8966594246261344259">"Delite preko"</string>
     <string name="copy_notification_title" msgid="6374299806748219777">"Kopiranje datoteka"</string>
     <string name="move_notification_title" msgid="6193835179777284805">"Datoteke se premeštaju"</string>
+    <string name="delete_notification_title" msgid="3329403967712437496">"Datoteke se brišu"</string>
     <string name="copy_remaining" msgid="6283790937387975095">"Još <xliff:g id="DURATION">%s</xliff:g>"</string>
     <plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
       <item quantity="one">Kopiranje <xliff:g id="COUNT_1">%1$d</xliff:g> datoteke.</item>
@@ -118,4 +119,14 @@
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Neke datoteke su konvertovane"</string>
     <string name="allow" msgid="7225948811296386551">"Dozvoli"</string>
     <string name="deny" msgid="2081879885755434506">"Odbij"</string>
+    <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772">
+      <item quantity="one">Želite li da izbrišete <xliff:g id="COUNT_1">%1$d</xliff:g> datoteku?</item>
+      <item quantity="few">Želite li da izbrišete <xliff:g id="COUNT_1">%1$d</xliff:g> datoteke?</item>
+      <item quantity="other">Želite li da izbrišete <xliff:g id="COUNT_1">%1$d</xliff:g> datoteka?</item>
+    </plurals>
+    <plurals name="elements_selected" formatted="false" msgid="1376955402452875047">
+      <item quantity="one">Izabrana je <xliff:g id="COUNT_1">%1$d</xliff:g> stavka</item>
+      <item quantity="few">Izabrane su <xliff:g id="COUNT_1">%1$d</xliff:g> stavke</item>
+      <item quantity="other">Izabrano je <xliff:g id="COUNT_1">%1$d</xliff:g> stavki</item>
+    </plurals>
 </resources>
diff --git a/packages/DocumentsUI/res/values-bg/config.xml b/packages/DocumentsUI/res/values-bg/config.xml
deleted file mode 100644
index 843a8aa..0000000
--- a/packages/DocumentsUI/res/values-bg/config.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--  Copyright (C) 2015 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="trusted_quick_viewer_package" msgid="3354383993907861267"></string>
-</resources>
diff --git a/packages/DocumentsUI/res/values-bg/strings.xml b/packages/DocumentsUI/res/values-bg/strings.xml
index 4a6d499..94c34bd 100644
--- a/packages/DocumentsUI/res/values-bg/strings.xml
+++ b/packages/DocumentsUI/res/values-bg/strings.xml
@@ -67,6 +67,7 @@
     <string name="share_via" msgid="8966594246261344259">"Споделяне чрез"</string>
     <string name="copy_notification_title" msgid="6374299806748219777">"Файловете се копират"</string>
     <string name="move_notification_title" msgid="6193835179777284805">"Файловете се преместват"</string>
+    <string name="delete_notification_title" msgid="3329403967712437496">"Изтриване на файлове"</string>
     <string name="copy_remaining" msgid="6283790937387975095">"Оставащо време: <xliff:g id="DURATION">%s</xliff:g>"</string>
     <plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
       <item quantity="other">Копират се <xliff:g id="COUNT_1">%1$d</xliff:g> файла.</item>
@@ -111,4 +112,12 @@
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Някои файлове бяха преобразувани"</string>
     <string name="allow" msgid="7225948811296386551">"Разрешаване"</string>
     <string name="deny" msgid="2081879885755434506">"Отказване"</string>
+    <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772">
+      <item quantity="other">Искате ли да изтриете <xliff:g id="COUNT_1">%1$d</xliff:g> файла?</item>
+      <item quantity="one">Искате ли да изтриете <xliff:g id="COUNT_0">%1$d</xliff:g> файл?</item>
+    </plurals>
+    <plurals name="elements_selected" formatted="false" msgid="1376955402452875047">
+      <item quantity="other">Избрахте <xliff:g id="COUNT_1">%1$d</xliff:g></item>
+      <item quantity="one">Избрахте <xliff:g id="COUNT_0">%1$d</xliff:g></item>
+    </plurals>
 </resources>
diff --git a/packages/DocumentsUI/res/values-bn-rBD/config.xml b/packages/DocumentsUI/res/values-bn-rBD/config.xml
deleted file mode 100644
index 843a8aa..0000000
--- a/packages/DocumentsUI/res/values-bn-rBD/config.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--  Copyright (C) 2015 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="trusted_quick_viewer_package" msgid="3354383993907861267"></string>
-</resources>
diff --git a/packages/DocumentsUI/res/values-bn-rBD/strings.xml b/packages/DocumentsUI/res/values-bn-rBD/strings.xml
index f53cfa8..2159044 100644
--- a/packages/DocumentsUI/res/values-bn-rBD/strings.xml
+++ b/packages/DocumentsUI/res/values-bn-rBD/strings.xml
@@ -67,6 +67,7 @@
     <string name="share_via" msgid="8966594246261344259">"এর মাধ্যমে শেয়ার করুন"</string>
     <string name="copy_notification_title" msgid="6374299806748219777">"ফাইলগুলি অনুলিপি করা হচ্ছে"</string>
     <string name="move_notification_title" msgid="6193835179777284805">"ফাইলগুলি সরানো হচ্ছে"</string>
+    <string name="delete_notification_title" msgid="3329403967712437496">"ফাইলগুলি মোছা হচ্ছে"</string>
     <string name="copy_remaining" msgid="6283790937387975095">"<xliff:g id="DURATION">%s</xliff:g> বাকি"</string>
     <plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
       <item quantity="one"><xliff:g id="COUNT_1">%1$d</xliff:g>টি ফাইল অনুলিপি করা হচ্ছে৷</item>
@@ -111,4 +112,12 @@
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"কিছু ফাইল রূপান্তরিত হয়েছে"</string>
     <string name="allow" msgid="7225948811296386551">"অনুমতি দিন"</string>
     <string name="deny" msgid="2081879885755434506">"আস্বীকার করুন"</string>
+    <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772">
+      <item quantity="one"><xliff:g id="COUNT_1">%1$d</xliff:g>টি ফাইল মুছবেন?</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g>টি ফাইল মুছবেন?</item>
+    </plurals>
+    <plurals name="elements_selected" formatted="false" msgid="1376955402452875047">
+      <item quantity="one"><xliff:g id="COUNT_1">%1$d</xliff:g>টি নির্বাচন করা হয়েছে</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g>টি নির্বাচন করা হয়েছে</item>
+    </plurals>
 </resources>
diff --git a/packages/DocumentsUI/res/values-bs-rBA/config.xml b/packages/DocumentsUI/res/values-bs-rBA/config.xml
deleted file mode 100644
index 843a8aa..0000000
--- a/packages/DocumentsUI/res/values-bs-rBA/config.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--  Copyright (C) 2015 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="trusted_quick_viewer_package" msgid="3354383993907861267"></string>
-</resources>
diff --git a/packages/DocumentsUI/res/values-bs-rBA/strings.xml b/packages/DocumentsUI/res/values-bs-rBA/strings.xml
index d315166..f366ce8 100644
--- a/packages/DocumentsUI/res/values-bs-rBA/strings.xml
+++ b/packages/DocumentsUI/res/values-bs-rBA/strings.xml
@@ -67,6 +67,7 @@
     <string name="share_via" msgid="8966594246261344259">"Podijeli preko"</string>
     <string name="copy_notification_title" msgid="6374299806748219777">"Kopiraju se fajlovi"</string>
     <string name="move_notification_title" msgid="6193835179777284805">"Premještanje fajlova"</string>
+    <string name="delete_notification_title" msgid="3329403967712437496">"Brisanje fajlova"</string>
     <string name="copy_remaining" msgid="6283790937387975095">"Još <xliff:g id="DURATION">%s</xliff:g>"</string>
     <plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
       <item quantity="one">Kopira se <xliff:g id="COUNT_1">%1$d</xliff:g> fajl.</item>
@@ -118,4 +119,14 @@
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Neke od datoteka su pretvorene"</string>
     <string name="allow" msgid="7225948811296386551">"Dozvoli"</string>
     <string name="deny" msgid="2081879885755434506">"Odbijte"</string>
+    <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772">
+      <item quantity="one">Želite li izbrisati <xliff:g id="COUNT_1">%1$d</xliff:g> fajl.</item>
+      <item quantity="few">Želite li izbrisati <xliff:g id="COUNT_1">%1$d</xliff:g> fajla.</item>
+      <item quantity="other">Želite li izbrisati <xliff:g id="COUNT_1">%1$d</xliff:g> fajlova.</item>
+    </plurals>
+    <plurals name="elements_selected" formatted="false" msgid="1376955402452875047">
+      <item quantity="one"><xliff:g id="COUNT_1">%1$d</xliff:g> stavka je odabrana</item>
+      <item quantity="few"><xliff:g id="COUNT_1">%1$d</xliff:g> stavke su odabrane</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> stavki je odabrano</item>
+    </plurals>
 </resources>
diff --git a/packages/DocumentsUI/res/values-ca/config.xml b/packages/DocumentsUI/res/values-ca/config.xml
deleted file mode 100644
index 843a8aa..0000000
--- a/packages/DocumentsUI/res/values-ca/config.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--  Copyright (C) 2015 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="trusted_quick_viewer_package" msgid="3354383993907861267"></string>
-</resources>
diff --git a/packages/DocumentsUI/res/values-ca/strings.xml b/packages/DocumentsUI/res/values-ca/strings.xml
index 96bfbb7..5af86b1 100644
--- a/packages/DocumentsUI/res/values-ca/strings.xml
+++ b/packages/DocumentsUI/res/values-ca/strings.xml
@@ -67,6 +67,7 @@
     <string name="share_via" msgid="8966594246261344259">"Comparteix mitjançant"</string>
     <string name="copy_notification_title" msgid="6374299806748219777">"S\'estan copiant fitxers"</string>
     <string name="move_notification_title" msgid="6193835179777284805">"S\'estan movent fitxers"</string>
+    <string name="delete_notification_title" msgid="3329403967712437496">"Suprimint els fitxers"</string>
     <string name="copy_remaining" msgid="6283790937387975095">"Temps restant: <xliff:g id="DURATION">%s</xliff:g>"</string>
     <plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
       <item quantity="other">S\'estan copiant <xliff:g id="COUNT_1">%1$d</xliff:g> fitxers.</item>
@@ -111,4 +112,12 @@
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"S\'han convertit alguns fitxers"</string>
     <string name="allow" msgid="7225948811296386551">"Permet"</string>
     <string name="deny" msgid="2081879885755434506">"Denega"</string>
+    <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772">
+      <item quantity="other">Vols suprimir <xliff:g id="COUNT_1">%1$d</xliff:g> fitxers?</item>
+      <item quantity="one">Vols suprimir <xliff:g id="COUNT_0">%1$d</xliff:g> fitxer?</item>
+    </plurals>
+    <plurals name="elements_selected" formatted="false" msgid="1376955402452875047">
+      <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> elements seleccionats</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> element seleccionat</item>
+    </plurals>
 </resources>
diff --git a/packages/DocumentsUI/res/values-cs/config.xml b/packages/DocumentsUI/res/values-cs/config.xml
deleted file mode 100644
index 843a8aa..0000000
--- a/packages/DocumentsUI/res/values-cs/config.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--  Copyright (C) 2015 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="trusted_quick_viewer_package" msgid="3354383993907861267"></string>
-</resources>
diff --git a/packages/DocumentsUI/res/values-cs/strings.xml b/packages/DocumentsUI/res/values-cs/strings.xml
index a6e79b6..4e8b440 100644
--- a/packages/DocumentsUI/res/values-cs/strings.xml
+++ b/packages/DocumentsUI/res/values-cs/strings.xml
@@ -67,6 +67,7 @@
     <string name="share_via" msgid="8966594246261344259">"Sdílet pomocí"</string>
     <string name="copy_notification_title" msgid="6374299806748219777">"Kopírování souborů"</string>
     <string name="move_notification_title" msgid="6193835179777284805">"Přesouvání souborů"</string>
+    <string name="delete_notification_title" msgid="3329403967712437496">"Mazání souborů"</string>
     <string name="copy_remaining" msgid="6283790937387975095">"Zbývající čas: <xliff:g id="DURATION">%s</xliff:g>"</string>
     <plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
       <item quantity="few">Kopírování <xliff:g id="COUNT_1">%1$d</xliff:g> souborů</item>
@@ -125,4 +126,16 @@
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Některé soubory byly převedeny"</string>
     <string name="allow" msgid="7225948811296386551">"Povolit"</string>
     <string name="deny" msgid="2081879885755434506">"Odepřít"</string>
+    <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772">
+      <item quantity="few">Smazat <xliff:g id="COUNT_1">%1$d</xliff:g> soubory?</item>
+      <item quantity="many">Smazat <xliff:g id="COUNT_1">%1$d</xliff:g> souboru?</item>
+      <item quantity="other">Smazat <xliff:g id="COUNT_1">%1$d</xliff:g> souborů?</item>
+      <item quantity="one">Smazat <xliff:g id="COUNT_0">%1$d</xliff:g> soubor?</item>
+    </plurals>
+    <plurals name="elements_selected" formatted="false" msgid="1376955402452875047">
+      <item quantity="few">Vybrány <xliff:g id="COUNT_1">%1$d</xliff:g> položky</item>
+      <item quantity="many">Vybráno <xliff:g id="COUNT_1">%1$d</xliff:g> položky</item>
+      <item quantity="other">Vybráno <xliff:g id="COUNT_1">%1$d</xliff:g> položek</item>
+      <item quantity="one">Vybrána <xliff:g id="COUNT_0">%1$d</xliff:g> položka</item>
+    </plurals>
 </resources>
diff --git a/packages/DocumentsUI/res/values-da/config.xml b/packages/DocumentsUI/res/values-da/config.xml
deleted file mode 100644
index 843a8aa..0000000
--- a/packages/DocumentsUI/res/values-da/config.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--  Copyright (C) 2015 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="trusted_quick_viewer_package" msgid="3354383993907861267"></string>
-</resources>
diff --git a/packages/DocumentsUI/res/values-da/strings.xml b/packages/DocumentsUI/res/values-da/strings.xml
index a0b7c1f..ee5ba49 100644
--- a/packages/DocumentsUI/res/values-da/strings.xml
+++ b/packages/DocumentsUI/res/values-da/strings.xml
@@ -67,6 +67,7 @@
     <string name="share_via" msgid="8966594246261344259">"Del via"</string>
     <string name="copy_notification_title" msgid="6374299806748219777">"Kopierer filer"</string>
     <string name="move_notification_title" msgid="6193835179777284805">"Flytter filer"</string>
+    <string name="delete_notification_title" msgid="3329403967712437496">"Filerne slettes"</string>
     <string name="copy_remaining" msgid="6283790937387975095">"<xliff:g id="DURATION">%s</xliff:g> tilbage"</string>
     <plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
       <item quantity="one">Kopierer <xliff:g id="COUNT_1">%1$d</xliff:g> filer.</item>
@@ -111,4 +112,12 @@
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Nogle filer er konverteret"</string>
     <string name="allow" msgid="7225948811296386551">"Tillad"</string>
     <string name="deny" msgid="2081879885755434506">"Afvis"</string>
+    <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772">
+      <item quantity="one">Vil du slette <xliff:g id="COUNT_1">%1$d</xliff:g> filer?</item>
+      <item quantity="other">Vil du slette <xliff:g id="COUNT_1">%1$d</xliff:g> filer?</item>
+    </plurals>
+    <plurals name="elements_selected" formatted="false" msgid="1376955402452875047">
+      <item quantity="one">Der er valgt <xliff:g id="COUNT_1">%1$d</xliff:g></item>
+      <item quantity="other">Der er valgt <xliff:g id="COUNT_1">%1$d</xliff:g></item>
+    </plurals>
 </resources>
diff --git a/packages/DocumentsUI/res/values-de/config.xml b/packages/DocumentsUI/res/values-de/config.xml
deleted file mode 100644
index 843a8aa..0000000
--- a/packages/DocumentsUI/res/values-de/config.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--  Copyright (C) 2015 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="trusted_quick_viewer_package" msgid="3354383993907861267"></string>
-</resources>
diff --git a/packages/DocumentsUI/res/values-de/strings.xml b/packages/DocumentsUI/res/values-de/strings.xml
index 2d968fe..a42e955 100644
--- a/packages/DocumentsUI/res/values-de/strings.xml
+++ b/packages/DocumentsUI/res/values-de/strings.xml
@@ -67,6 +67,7 @@
     <string name="share_via" msgid="8966594246261344259">"Teilen über"</string>
     <string name="copy_notification_title" msgid="6374299806748219777">"Dateien werden kopiert"</string>
     <string name="move_notification_title" msgid="6193835179777284805">"Dateien werden verschoben"</string>
+    <string name="delete_notification_title" msgid="3329403967712437496">"Dateien werden gelöscht"</string>
     <string name="copy_remaining" msgid="6283790937387975095">"Noch <xliff:g id="DURATION">%s</xliff:g>"</string>
     <plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
       <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> Dateien werden kopiert.</item>
@@ -111,4 +112,12 @@
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Einige Dateien wurden konvertiert"</string>
     <string name="allow" msgid="7225948811296386551">"Zulassen"</string>
     <string name="deny" msgid="2081879885755434506">"Ablehnen"</string>
+    <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772">
+      <item quantity="other">Möchtest du <xliff:g id="COUNT_1">%1$d</xliff:g> Dateien löschen?</item>
+      <item quantity="one">Möchtest du <xliff:g id="COUNT_0">%1$d</xliff:g> Datei löschen?</item>
+    </plurals>
+    <plurals name="elements_selected" formatted="false" msgid="1376955402452875047">
+      <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> ausgewählt</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> ausgewählt</item>
+    </plurals>
 </resources>
diff --git a/packages/DocumentsUI/res/values-el/config.xml b/packages/DocumentsUI/res/values-el/config.xml
deleted file mode 100644
index 843a8aa..0000000
--- a/packages/DocumentsUI/res/values-el/config.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--  Copyright (C) 2015 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="trusted_quick_viewer_package" msgid="3354383993907861267"></string>
-</resources>
diff --git a/packages/DocumentsUI/res/values-el/strings.xml b/packages/DocumentsUI/res/values-el/strings.xml
index 6c9896d..e6839de 100644
--- a/packages/DocumentsUI/res/values-el/strings.xml
+++ b/packages/DocumentsUI/res/values-el/strings.xml
@@ -67,6 +67,7 @@
     <string name="share_via" msgid="8966594246261344259">"Κοινή χρήση μέσω"</string>
     <string name="copy_notification_title" msgid="6374299806748219777">"Αντιγραφή αρχείων"</string>
     <string name="move_notification_title" msgid="6193835179777284805">"Μετακίνηση αρχείων"</string>
+    <string name="delete_notification_title" msgid="3329403967712437496">"Διαγραφή αρχείων"</string>
     <string name="copy_remaining" msgid="6283790937387975095">"Απομένουν <xliff:g id="DURATION">%s</xliff:g>"</string>
     <plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
       <item quantity="other">Αντιγραφή <xliff:g id="COUNT_1">%1$d</xliff:g> αρχείων.</item>
@@ -111,4 +112,12 @@
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Ορισμένα αρχεία μετατράπηκαν"</string>
     <string name="allow" msgid="7225948811296386551">"Να επιτρέπεται"</string>
     <string name="deny" msgid="2081879885755434506">"Άρνηση"</string>
+    <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772">
+      <item quantity="other">Να διαγραφούν <xliff:g id="COUNT_1">%1$d</xliff:g> αρχεία;</item>
+      <item quantity="one">Να διαγραφεί <xliff:g id="COUNT_0">%1$d</xliff:g> αρχείο;</item>
+    </plurals>
+    <plurals name="elements_selected" formatted="false" msgid="1376955402452875047">
+      <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> επιλεγμένα</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> επιλεγμένο</item>
+    </plurals>
 </resources>
diff --git a/packages/DocumentsUI/res/values-en-rAU/config.xml b/packages/DocumentsUI/res/values-en-rAU/config.xml
deleted file mode 100644
index 843a8aa..0000000
--- a/packages/DocumentsUI/res/values-en-rAU/config.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--  Copyright (C) 2015 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="trusted_quick_viewer_package" msgid="3354383993907861267"></string>
-</resources>
diff --git a/packages/DocumentsUI/res/values-en-rAU/strings.xml b/packages/DocumentsUI/res/values-en-rAU/strings.xml
index 5bc4f59..8b46660 100644
--- a/packages/DocumentsUI/res/values-en-rAU/strings.xml
+++ b/packages/DocumentsUI/res/values-en-rAU/strings.xml
@@ -67,6 +67,7 @@
     <string name="share_via" msgid="8966594246261344259">"Share via"</string>
     <string name="copy_notification_title" msgid="6374299806748219777">"Copying files"</string>
     <string name="move_notification_title" msgid="6193835179777284805">"Moving files"</string>
+    <string name="delete_notification_title" msgid="3329403967712437496">"Deleting files"</string>
     <string name="copy_remaining" msgid="6283790937387975095">"<xliff:g id="DURATION">%s</xliff:g> left"</string>
     <plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
       <item quantity="other">Copying <xliff:g id="COUNT_1">%1$d</xliff:g> files.</item>
@@ -111,4 +112,12 @@
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Some files were converted"</string>
     <string name="allow" msgid="7225948811296386551">"Allow"</string>
     <string name="deny" msgid="2081879885755434506">"Deny"</string>
+    <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772">
+      <item quantity="other">Delete <xliff:g id="COUNT_1">%1$d</xliff:g> files?</item>
+      <item quantity="one">Delete <xliff:g id="COUNT_0">%1$d</xliff:g> file?</item>
+    </plurals>
+    <plurals name="elements_selected" formatted="false" msgid="1376955402452875047">
+      <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> selected</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> selected</item>
+    </plurals>
 </resources>
diff --git a/packages/DocumentsUI/res/values-en-rGB/config.xml b/packages/DocumentsUI/res/values-en-rGB/config.xml
deleted file mode 100644
index 843a8aa..0000000
--- a/packages/DocumentsUI/res/values-en-rGB/config.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--  Copyright (C) 2015 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="trusted_quick_viewer_package" msgid="3354383993907861267"></string>
-</resources>
diff --git a/packages/DocumentsUI/res/values-en-rGB/strings.xml b/packages/DocumentsUI/res/values-en-rGB/strings.xml
index 5bc4f59..8b46660 100644
--- a/packages/DocumentsUI/res/values-en-rGB/strings.xml
+++ b/packages/DocumentsUI/res/values-en-rGB/strings.xml
@@ -67,6 +67,7 @@
     <string name="share_via" msgid="8966594246261344259">"Share via"</string>
     <string name="copy_notification_title" msgid="6374299806748219777">"Copying files"</string>
     <string name="move_notification_title" msgid="6193835179777284805">"Moving files"</string>
+    <string name="delete_notification_title" msgid="3329403967712437496">"Deleting files"</string>
     <string name="copy_remaining" msgid="6283790937387975095">"<xliff:g id="DURATION">%s</xliff:g> left"</string>
     <plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
       <item quantity="other">Copying <xliff:g id="COUNT_1">%1$d</xliff:g> files.</item>
@@ -111,4 +112,12 @@
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Some files were converted"</string>
     <string name="allow" msgid="7225948811296386551">"Allow"</string>
     <string name="deny" msgid="2081879885755434506">"Deny"</string>
+    <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772">
+      <item quantity="other">Delete <xliff:g id="COUNT_1">%1$d</xliff:g> files?</item>
+      <item quantity="one">Delete <xliff:g id="COUNT_0">%1$d</xliff:g> file?</item>
+    </plurals>
+    <plurals name="elements_selected" formatted="false" msgid="1376955402452875047">
+      <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> selected</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> selected</item>
+    </plurals>
 </resources>
diff --git a/packages/DocumentsUI/res/values-en-rIN/config.xml b/packages/DocumentsUI/res/values-en-rIN/config.xml
deleted file mode 100644
index 843a8aa..0000000
--- a/packages/DocumentsUI/res/values-en-rIN/config.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--  Copyright (C) 2015 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="trusted_quick_viewer_package" msgid="3354383993907861267"></string>
-</resources>
diff --git a/packages/DocumentsUI/res/values-en-rIN/strings.xml b/packages/DocumentsUI/res/values-en-rIN/strings.xml
index 5bc4f59..8b46660 100644
--- a/packages/DocumentsUI/res/values-en-rIN/strings.xml
+++ b/packages/DocumentsUI/res/values-en-rIN/strings.xml
@@ -67,6 +67,7 @@
     <string name="share_via" msgid="8966594246261344259">"Share via"</string>
     <string name="copy_notification_title" msgid="6374299806748219777">"Copying files"</string>
     <string name="move_notification_title" msgid="6193835179777284805">"Moving files"</string>
+    <string name="delete_notification_title" msgid="3329403967712437496">"Deleting files"</string>
     <string name="copy_remaining" msgid="6283790937387975095">"<xliff:g id="DURATION">%s</xliff:g> left"</string>
     <plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
       <item quantity="other">Copying <xliff:g id="COUNT_1">%1$d</xliff:g> files.</item>
@@ -111,4 +112,12 @@
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Some files were converted"</string>
     <string name="allow" msgid="7225948811296386551">"Allow"</string>
     <string name="deny" msgid="2081879885755434506">"Deny"</string>
+    <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772">
+      <item quantity="other">Delete <xliff:g id="COUNT_1">%1$d</xliff:g> files?</item>
+      <item quantity="one">Delete <xliff:g id="COUNT_0">%1$d</xliff:g> file?</item>
+    </plurals>
+    <plurals name="elements_selected" formatted="false" msgid="1376955402452875047">
+      <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> selected</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> selected</item>
+    </plurals>
 </resources>
diff --git a/packages/DocumentsUI/res/values-es-rUS/config.xml b/packages/DocumentsUI/res/values-es-rUS/config.xml
deleted file mode 100644
index 843a8aa..0000000
--- a/packages/DocumentsUI/res/values-es-rUS/config.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--  Copyright (C) 2015 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="trusted_quick_viewer_package" msgid="3354383993907861267"></string>
-</resources>
diff --git a/packages/DocumentsUI/res/values-es-rUS/strings.xml b/packages/DocumentsUI/res/values-es-rUS/strings.xml
index e212053..8fd8381 100644
--- a/packages/DocumentsUI/res/values-es-rUS/strings.xml
+++ b/packages/DocumentsUI/res/values-es-rUS/strings.xml
@@ -67,6 +67,7 @@
     <string name="share_via" msgid="8966594246261344259">"Compartir mediante"</string>
     <string name="copy_notification_title" msgid="6374299806748219777">"Copiando archivos"</string>
     <string name="move_notification_title" msgid="6193835179777284805">"Moviendo archivos"</string>
+    <string name="delete_notification_title" msgid="3329403967712437496">"Borrando los archivos"</string>
     <string name="copy_remaining" msgid="6283790937387975095">"Faltan <xliff:g id="DURATION">%s</xliff:g>."</string>
     <plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
       <item quantity="other">Copiando <xliff:g id="COUNT_1">%1$d</xliff:g> archivos</item>
@@ -111,4 +112,12 @@
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Se convirtieron algunos archivos"</string>
     <string name="allow" msgid="7225948811296386551">"Permitir"</string>
     <string name="deny" msgid="2081879885755434506">"Denegar"</string>
+    <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772">
+      <item quantity="other">¿Deseas borrar <xliff:g id="COUNT_1">%1$d</xliff:g> archivos?</item>
+      <item quantity="one">¿Deseas borrar <xliff:g id="COUNT_0">%1$d</xliff:g> archivo?</item>
+    </plurals>
+    <plurals name="elements_selected" formatted="false" msgid="1376955402452875047">
+      <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> elementos seleccionados</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> elemento seleccionado</item>
+    </plurals>
 </resources>
diff --git a/packages/DocumentsUI/res/values-es/config.xml b/packages/DocumentsUI/res/values-es/config.xml
deleted file mode 100644
index 843a8aa..0000000
--- a/packages/DocumentsUI/res/values-es/config.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--  Copyright (C) 2015 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="trusted_quick_viewer_package" msgid="3354383993907861267"></string>
-</resources>
diff --git a/packages/DocumentsUI/res/values-es/strings.xml b/packages/DocumentsUI/res/values-es/strings.xml
index 28f3fd0..81fc59abb 100644
--- a/packages/DocumentsUI/res/values-es/strings.xml
+++ b/packages/DocumentsUI/res/values-es/strings.xml
@@ -67,6 +67,7 @@
     <string name="share_via" msgid="8966594246261344259">"Compartir a través de"</string>
     <string name="copy_notification_title" msgid="6374299806748219777">"Copiando archivos"</string>
     <string name="move_notification_title" msgid="6193835179777284805">"Moviendo archivos"</string>
+    <string name="delete_notification_title" msgid="3329403967712437496">"Eliminando archivos"</string>
     <string name="copy_remaining" msgid="6283790937387975095">"Tiempo restante: <xliff:g id="DURATION">%s</xliff:g>"</string>
     <plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
       <item quantity="other">Copiando <xliff:g id="COUNT_1">%1$d</xliff:g> archivos.</item>
@@ -111,4 +112,12 @@
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Se han convertido algunos archivos"</string>
     <string name="allow" msgid="7225948811296386551">"Permitir"</string>
     <string name="deny" msgid="2081879885755434506">"Denegar"</string>
+    <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772">
+      <item quantity="other">¿Eliminar <xliff:g id="COUNT_1">%1$d</xliff:g> archivos?</item>
+      <item quantity="one">¿Eliminar <xliff:g id="COUNT_0">%1$d</xliff:g> archivo?</item>
+    </plurals>
+    <plurals name="elements_selected" formatted="false" msgid="1376955402452875047">
+      <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> seleccionados</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> seleccionado</item>
+    </plurals>
 </resources>
diff --git a/packages/DocumentsUI/res/values-et-rEE/config.xml b/packages/DocumentsUI/res/values-et-rEE/config.xml
deleted file mode 100644
index 843a8aa..0000000
--- a/packages/DocumentsUI/res/values-et-rEE/config.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--  Copyright (C) 2015 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="trusted_quick_viewer_package" msgid="3354383993907861267"></string>
-</resources>
diff --git a/packages/DocumentsUI/res/values-et-rEE/strings.xml b/packages/DocumentsUI/res/values-et-rEE/strings.xml
index d8d6bea..7cf134e 100644
--- a/packages/DocumentsUI/res/values-et-rEE/strings.xml
+++ b/packages/DocumentsUI/res/values-et-rEE/strings.xml
@@ -67,6 +67,7 @@
     <string name="share_via" msgid="8966594246261344259">"Jagage teenusega"</string>
     <string name="copy_notification_title" msgid="6374299806748219777">"Failide kopeerimine"</string>
     <string name="move_notification_title" msgid="6193835179777284805">"Failide teisaldamine"</string>
+    <string name="delete_notification_title" msgid="3329403967712437496">"Failide kustutamine"</string>
     <string name="copy_remaining" msgid="6283790937387975095">"Jäänud on <xliff:g id="DURATION">%s</xliff:g>"</string>
     <plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
       <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> faili kopeerimine.</item>
@@ -111,4 +112,12 @@
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Mõned failid teisendati"</string>
     <string name="allow" msgid="7225948811296386551">"Luba"</string>
     <string name="deny" msgid="2081879885755434506">"Keela"</string>
+    <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772">
+      <item quantity="other">Kas kustutada <xliff:g id="COUNT_1">%1$d</xliff:g> faili?</item>
+      <item quantity="one">Kas kustutada <xliff:g id="COUNT_0">%1$d</xliff:g> fail?</item>
+    </plurals>
+    <plurals name="elements_selected" formatted="false" msgid="1376955402452875047">
+      <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> on valitud</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> on valitud</item>
+    </plurals>
 </resources>
diff --git a/packages/DocumentsUI/res/values-eu-rES/config.xml b/packages/DocumentsUI/res/values-eu-rES/config.xml
deleted file mode 100644
index 843a8aa..0000000
--- a/packages/DocumentsUI/res/values-eu-rES/config.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--  Copyright (C) 2015 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="trusted_quick_viewer_package" msgid="3354383993907861267"></string>
-</resources>
diff --git a/packages/DocumentsUI/res/values-eu-rES/strings.xml b/packages/DocumentsUI/res/values-eu-rES/strings.xml
index a8f3517..23e4079 100644
--- a/packages/DocumentsUI/res/values-eu-rES/strings.xml
+++ b/packages/DocumentsUI/res/values-eu-rES/strings.xml
@@ -67,6 +67,7 @@
     <string name="share_via" msgid="8966594246261344259">"Partekatu honen bidez:"</string>
     <string name="copy_notification_title" msgid="6374299806748219777">"Fitxategiak kopiatzen"</string>
     <string name="move_notification_title" msgid="6193835179777284805">"Fitxategiak mugitzea"</string>
+    <string name="delete_notification_title" msgid="3329403967712437496">"Fitxategiak ezabatzea"</string>
     <string name="copy_remaining" msgid="6283790937387975095">"Falta den denbora: <xliff:g id="DURATION">%s</xliff:g>"</string>
     <plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
       <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> fitxategi kopiatzen.</item>
@@ -111,4 +112,12 @@
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Artxibo batzuk bihurtu dira"</string>
     <string name="allow" msgid="7225948811296386551">"Onartu"</string>
     <string name="deny" msgid="2081879885755434506">"Ukatu"</string>
+    <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772">
+      <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> fitxategi ezabatu nahi dituzu?</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> fitxategi ezabatu nahi duzu?</item>
+    </plurals>
+    <plurals name="elements_selected" formatted="false" msgid="1376955402452875047">
+      <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> hautatuta</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> hautatuta</item>
+    </plurals>
 </resources>
diff --git a/packages/DocumentsUI/res/values-fa/config.xml b/packages/DocumentsUI/res/values-fa/config.xml
deleted file mode 100644
index 843a8aa..0000000
--- a/packages/DocumentsUI/res/values-fa/config.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--  Copyright (C) 2015 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="trusted_quick_viewer_package" msgid="3354383993907861267"></string>
-</resources>
diff --git a/packages/DocumentsUI/res/values-fa/strings.xml b/packages/DocumentsUI/res/values-fa/strings.xml
index 3b3d559..6aa5626 100644
--- a/packages/DocumentsUI/res/values-fa/strings.xml
+++ b/packages/DocumentsUI/res/values-fa/strings.xml
@@ -67,6 +67,7 @@
     <string name="share_via" msgid="8966594246261344259">"اشتراک‌گذاری از طریق"</string>
     <string name="copy_notification_title" msgid="6374299806748219777">"در حال کپی کردن فایل‌ها"</string>
     <string name="move_notification_title" msgid="6193835179777284805">"درحال انتقال فایل‌ها"</string>
+    <string name="delete_notification_title" msgid="3329403967712437496">"در حال حذف فایل‌ها"</string>
     <string name="copy_remaining" msgid="6283790937387975095">"<xliff:g id="DURATION">%s</xliff:g> باقی‌مانده"</string>
     <plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
       <item quantity="one">در حال کپی کردن <xliff:g id="COUNT_1">%1$d</xliff:g> فایل.</item>
@@ -111,4 +112,12 @@
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"بعضی از فایل‌ها تبدیل شدند"</string>
     <string name="allow" msgid="7225948811296386551">"ارزیابی‌شده"</string>
     <string name="deny" msgid="2081879885755434506">"اجازه ندارد"</string>
+    <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772">
+      <item quantity="one"><xliff:g id="COUNT_1">%1$d</xliff:g> فایل حذف شود؟</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> فایل حذف شود؟</item>
+    </plurals>
+    <plurals name="elements_selected" formatted="false" msgid="1376955402452875047">
+      <item quantity="one">‏<xliff:g id="COUNT_1">%1$d</xliff:g> مورد انتخاب شد</item>
+      <item quantity="other">‏<xliff:g id="COUNT_1">%1$d</xliff:g> مورد انتخاب شد</item>
+    </plurals>
 </resources>
diff --git a/packages/DocumentsUI/res/values-fi/config.xml b/packages/DocumentsUI/res/values-fi/config.xml
deleted file mode 100644
index 843a8aa..0000000
--- a/packages/DocumentsUI/res/values-fi/config.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--  Copyright (C) 2015 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="trusted_quick_viewer_package" msgid="3354383993907861267"></string>
-</resources>
diff --git a/packages/DocumentsUI/res/values-fi/strings.xml b/packages/DocumentsUI/res/values-fi/strings.xml
index 14513bd..8be6d61 100644
--- a/packages/DocumentsUI/res/values-fi/strings.xml
+++ b/packages/DocumentsUI/res/values-fi/strings.xml
@@ -67,6 +67,7 @@
     <string name="share_via" msgid="8966594246261344259">"Jaa sovelluksessa"</string>
     <string name="copy_notification_title" msgid="6374299806748219777">"Kopioidaan tiedostoja"</string>
     <string name="move_notification_title" msgid="6193835179777284805">"Siirretään tiedostoja"</string>
+    <string name="delete_notification_title" msgid="3329403967712437496">"Poistetaan tiedostoja"</string>
     <string name="copy_remaining" msgid="6283790937387975095">"<xliff:g id="DURATION">%s</xliff:g> jäljellä"</string>
     <plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
       <item quantity="other">Kopioidaan <xliff:g id="COUNT_1">%1$d</xliff:g> tiedostoa.</item>
@@ -111,4 +112,12 @@
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Joitakin tiedostoja muunnettiin."</string>
     <string name="allow" msgid="7225948811296386551">"Salli"</string>
     <string name="deny" msgid="2081879885755434506">"Kiellä"</string>
+    <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772">
+      <item quantity="other">Poistetaanko <xliff:g id="COUNT_1">%1$d</xliff:g> tiedostoa?</item>
+      <item quantity="one">Poistetaanko <xliff:g id="COUNT_0">%1$d</xliff:g> tiedosto?</item>
+    </plurals>
+    <plurals name="elements_selected" formatted="false" msgid="1376955402452875047">
+      <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> valittu</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> valittu</item>
+    </plurals>
 </resources>
diff --git a/packages/DocumentsUI/res/values-fr-rCA/config.xml b/packages/DocumentsUI/res/values-fr-rCA/config.xml
deleted file mode 100644
index 843a8aa..0000000
--- a/packages/DocumentsUI/res/values-fr-rCA/config.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--  Copyright (C) 2015 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="trusted_quick_viewer_package" msgid="3354383993907861267"></string>
-</resources>
diff --git a/packages/DocumentsUI/res/values-fr-rCA/strings.xml b/packages/DocumentsUI/res/values-fr-rCA/strings.xml
index 0d35f4a..0a33570 100644
--- a/packages/DocumentsUI/res/values-fr-rCA/strings.xml
+++ b/packages/DocumentsUI/res/values-fr-rCA/strings.xml
@@ -67,6 +67,7 @@
     <string name="share_via" msgid="8966594246261344259">"Partager par"</string>
     <string name="copy_notification_title" msgid="6374299806748219777">"Copie de fichiers..."</string>
     <string name="move_notification_title" msgid="6193835179777284805">"Déplacement des fichiers"</string>
+    <string name="delete_notification_title" msgid="3329403967712437496">"Suppression des fichiers"</string>
     <string name="copy_remaining" msgid="6283790937387975095">"Durée restante : <xliff:g id="DURATION">%s</xliff:g>"</string>
     <plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
       <item quantity="one">Copier de <xliff:g id="COUNT_1">%1$d</xliff:g> fichier en cours.</item>
@@ -111,4 +112,12 @@
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Certains fichiers ont été convertis"</string>
     <string name="allow" msgid="7225948811296386551">"Autoriser"</string>
     <string name="deny" msgid="2081879885755434506">"Refuser"</string>
+    <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772">
+      <item quantity="one">Supprimer <xliff:g id="COUNT_1">%1$d</xliff:g> fichier?</item>
+      <item quantity="other">Supprimer <xliff:g id="COUNT_1">%1$d</xliff:g> fichiers?</item>
+    </plurals>
+    <plurals name="elements_selected" formatted="false" msgid="1376955402452875047">
+      <item quantity="one"><xliff:g id="COUNT_1">%1$d</xliff:g> élément sélectionné</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> éléments sélectionnés</item>
+    </plurals>
 </resources>
diff --git a/packages/DocumentsUI/res/values-fr/config.xml b/packages/DocumentsUI/res/values-fr/config.xml
deleted file mode 100644
index 843a8aa..0000000
--- a/packages/DocumentsUI/res/values-fr/config.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--  Copyright (C) 2015 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="trusted_quick_viewer_package" msgid="3354383993907861267"></string>
-</resources>
diff --git a/packages/DocumentsUI/res/values-fr/strings.xml b/packages/DocumentsUI/res/values-fr/strings.xml
index 7ed98bb..478ea46 100644
--- a/packages/DocumentsUI/res/values-fr/strings.xml
+++ b/packages/DocumentsUI/res/values-fr/strings.xml
@@ -67,6 +67,7 @@
     <string name="share_via" msgid="8966594246261344259">"Partager via"</string>
     <string name="copy_notification_title" msgid="6374299806748219777">"Copie de fichiers en cours"</string>
     <string name="move_notification_title" msgid="6193835179777284805">"Déplacement de fichiers"</string>
+    <string name="delete_notification_title" msgid="3329403967712437496">"Suppression des fichiers…"</string>
     <string name="copy_remaining" msgid="6283790937387975095">"Temps restant : <xliff:g id="DURATION">%s</xliff:g>"</string>
     <plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
       <item quantity="one">Copie de <xliff:g id="COUNT_1">%1$d</xliff:g> fichier en cours…</item>
@@ -111,4 +112,12 @@
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Certains fichiers ont été convertis"</string>
     <string name="allow" msgid="7225948811296386551">"Autoriser"</string>
     <string name="deny" msgid="2081879885755434506">"Refuser"</string>
+    <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772">
+      <item quantity="one">Supprimer <xliff:g id="COUNT_1">%1$d</xliff:g> fichier ?</item>
+      <item quantity="other">Supprimer <xliff:g id="COUNT_1">%1$d</xliff:g> fichiers ?</item>
+    </plurals>
+    <plurals name="elements_selected" formatted="false" msgid="1376955402452875047">
+      <item quantity="one"><xliff:g id="COUNT_1">%1$d</xliff:g> élément sélectionné</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> éléments sélectionnés</item>
+    </plurals>
 </resources>
diff --git a/packages/DocumentsUI/res/values-gl-rES/config.xml b/packages/DocumentsUI/res/values-gl-rES/config.xml
deleted file mode 100644
index 843a8aa..0000000
--- a/packages/DocumentsUI/res/values-gl-rES/config.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--  Copyright (C) 2015 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="trusted_quick_viewer_package" msgid="3354383993907861267"></string>
-</resources>
diff --git a/packages/DocumentsUI/res/values-gl-rES/strings.xml b/packages/DocumentsUI/res/values-gl-rES/strings.xml
index 645eb04..c933faa 100644
--- a/packages/DocumentsUI/res/values-gl-rES/strings.xml
+++ b/packages/DocumentsUI/res/values-gl-rES/strings.xml
@@ -67,6 +67,7 @@
     <string name="share_via" msgid="8966594246261344259">"Compartir a través de"</string>
     <string name="copy_notification_title" msgid="6374299806748219777">"Copiando ficheiros"</string>
     <string name="move_notification_title" msgid="6193835179777284805">"Mover ficheiros"</string>
+    <string name="delete_notification_title" msgid="3329403967712437496">"Eliminando ficheiros"</string>
     <string name="copy_remaining" msgid="6283790937387975095">"Tempo restante: <xliff:g id="DURATION">%s</xliff:g>"</string>
     <plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
       <item quantity="other">Copiando <xliff:g id="COUNT_1">%1$d</xliff:g> ficheiros.</item>
@@ -111,4 +112,12 @@
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Convertéronse algúns ficheiros"</string>
     <string name="allow" msgid="7225948811296386551">"Permitir"</string>
     <string name="deny" msgid="2081879885755434506">"Rexeitar"</string>
+    <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772">
+      <item quantity="other">Queres eliminar <xliff:g id="COUNT_1">%1$d</xliff:g> ficheiros?</item>
+      <item quantity="one">Queres eliminar <xliff:g id="COUNT_0">%1$d</xliff:g> ficheiro?</item>
+    </plurals>
+    <plurals name="elements_selected" formatted="false" msgid="1376955402452875047">
+      <item quantity="other">Seleccionáronse <xliff:g id="COUNT_1">%1$d</xliff:g></item>
+      <item quantity="one">Seleccionouse <xliff:g id="COUNT_0">%1$d</xliff:g></item>
+    </plurals>
 </resources>
diff --git a/packages/DocumentsUI/res/values-gu-rIN/config.xml b/packages/DocumentsUI/res/values-gu-rIN/config.xml
deleted file mode 100644
index 843a8aa..0000000
--- a/packages/DocumentsUI/res/values-gu-rIN/config.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--  Copyright (C) 2015 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="trusted_quick_viewer_package" msgid="3354383993907861267"></string>
-</resources>
diff --git a/packages/DocumentsUI/res/values-gu-rIN/strings.xml b/packages/DocumentsUI/res/values-gu-rIN/strings.xml
index 927906a..e9fda19 100644
--- a/packages/DocumentsUI/res/values-gu-rIN/strings.xml
+++ b/packages/DocumentsUI/res/values-gu-rIN/strings.xml
@@ -67,6 +67,7 @@
     <string name="share_via" msgid="8966594246261344259">"આના દ્વારા શેર કરો"</string>
     <string name="copy_notification_title" msgid="6374299806748219777">"ફાઇલો કૉપિ કરી રહ્યાં છે"</string>
     <string name="move_notification_title" msgid="6193835179777284805">"ફાઇલો ખસેડી રહ્યાં છે"</string>
+    <string name="delete_notification_title" msgid="3329403967712437496">"ફાઇલને નીકાળી રહ્યાં છે"</string>
     <string name="copy_remaining" msgid="6283790937387975095">"<xliff:g id="DURATION">%s</xliff:g> બાકી"</string>
     <plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
       <item quantity="one"><xliff:g id="COUNT_1">%1$d</xliff:g> ફાઇલો કૉપિ કરી રહ્યાં છે.</item>
@@ -111,4 +112,12 @@
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"કેટલીક ફાઇલો રૂપાંતરિત કરી હતી"</string>
     <string name="allow" msgid="7225948811296386551">"મંજૂરી આપો"</string>
     <string name="deny" msgid="2081879885755434506">"નકારો"</string>
+    <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772">
+      <item quantity="one"><xliff:g id="COUNT_1">%1$d</xliff:g> ફાઇલ કાઢી નાખીએ?</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> ફાઇલ કાઢી નાખીએ?</item>
+    </plurals>
+    <plurals name="elements_selected" formatted="false" msgid="1376955402452875047">
+      <item quantity="one"><xliff:g id="COUNT_1">%1$d</xliff:g> પસંદ કરી</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> પસંદ કરી</item>
+    </plurals>
 </resources>
diff --git a/packages/DocumentsUI/res/values-hi/config.xml b/packages/DocumentsUI/res/values-hi/config.xml
deleted file mode 100644
index 843a8aa..0000000
--- a/packages/DocumentsUI/res/values-hi/config.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--  Copyright (C) 2015 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="trusted_quick_viewer_package" msgid="3354383993907861267"></string>
-</resources>
diff --git a/packages/DocumentsUI/res/values-hi/strings.xml b/packages/DocumentsUI/res/values-hi/strings.xml
index f947d3d..489bb98 100644
--- a/packages/DocumentsUI/res/values-hi/strings.xml
+++ b/packages/DocumentsUI/res/values-hi/strings.xml
@@ -67,6 +67,7 @@
     <string name="share_via" msgid="8966594246261344259">"इसके द्वारा साझा करें"</string>
     <string name="copy_notification_title" msgid="6374299806748219777">"फ़ाइलें कॉपी हो रही हैं"</string>
     <string name="move_notification_title" msgid="6193835179777284805">"फाइलें ले जाई जा रही हैं"</string>
+    <string name="delete_notification_title" msgid="3329403967712437496">"फ़ाइलें हटाई जा रही हैं"</string>
     <string name="copy_remaining" msgid="6283790937387975095">"<xliff:g id="DURATION">%s</xliff:g> शेष"</string>
     <plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
       <item quantity="one"><xliff:g id="COUNT_1">%1$d</xliff:g> फ़ाइलें कॉपी की जा रही हैं.</item>
@@ -111,4 +112,12 @@
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"कुछ फ़ाइलें रूपांतरित हो गई थीं"</string>
     <string name="allow" msgid="7225948811296386551">"अनुमति दें"</string>
     <string name="deny" msgid="2081879885755434506">"अस्वीकारें"</string>
+    <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772">
+      <item quantity="one"><xliff:g id="COUNT_1">%1$d</xliff:g> फ़ाइलें हटाएं?</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> फ़ाइलें हटाएं?</item>
+    </plurals>
+    <plurals name="elements_selected" formatted="false" msgid="1376955402452875047">
+      <item quantity="one"><xliff:g id="COUNT_1">%1$d</xliff:g> चयनित</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> चयनित</item>
+    </plurals>
 </resources>
diff --git a/packages/DocumentsUI/res/values-hr/config.xml b/packages/DocumentsUI/res/values-hr/config.xml
deleted file mode 100644
index 843a8aa..0000000
--- a/packages/DocumentsUI/res/values-hr/config.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--  Copyright (C) 2015 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="trusted_quick_viewer_package" msgid="3354383993907861267"></string>
-</resources>
diff --git a/packages/DocumentsUI/res/values-hr/strings.xml b/packages/DocumentsUI/res/values-hr/strings.xml
index bfac527..51b8673 100644
--- a/packages/DocumentsUI/res/values-hr/strings.xml
+++ b/packages/DocumentsUI/res/values-hr/strings.xml
@@ -67,6 +67,7 @@
     <string name="share_via" msgid="8966594246261344259">"Dijeli putem"</string>
     <string name="copy_notification_title" msgid="6374299806748219777">"Kopiranje datoteka"</string>
     <string name="move_notification_title" msgid="6193835179777284805">"Premještanje datoteka"</string>
+    <string name="delete_notification_title" msgid="3329403967712437496">"Brisanje datoteka"</string>
     <string name="copy_remaining" msgid="6283790937387975095">"Još <xliff:g id="DURATION">%s</xliff:g>"</string>
     <plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
       <item quantity="one">Kopiranje <xliff:g id="COUNT_1">%1$d</xliff:g> datoteke.</item>
@@ -118,4 +119,14 @@
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Neke su datoteke konvertirane"</string>
     <string name="allow" msgid="7225948811296386551">"Dopusti"</string>
     <string name="deny" msgid="2081879885755434506">"Odbij"</string>
+    <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772">
+      <item quantity="one">Želite li izbrisati <xliff:g id="COUNT_1">%1$d</xliff:g> datoteku?</item>
+      <item quantity="few">Želite li izbrisati <xliff:g id="COUNT_1">%1$d</xliff:g> datoteke?</item>
+      <item quantity="other">Želite li izbrisati <xliff:g id="COUNT_1">%1$d</xliff:g> datoteka?</item>
+    </plurals>
+    <plurals name="elements_selected" formatted="false" msgid="1376955402452875047">
+      <item quantity="one">Odabrano: <xliff:g id="COUNT_1">%1$d</xliff:g></item>
+      <item quantity="few">Odabrano: <xliff:g id="COUNT_1">%1$d</xliff:g></item>
+      <item quantity="other">Odabrano: <xliff:g id="COUNT_1">%1$d</xliff:g></item>
+    </plurals>
 </resources>
diff --git a/packages/DocumentsUI/res/values-hu/config.xml b/packages/DocumentsUI/res/values-hu/config.xml
deleted file mode 100644
index 843a8aa..0000000
--- a/packages/DocumentsUI/res/values-hu/config.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--  Copyright (C) 2015 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="trusted_quick_viewer_package" msgid="3354383993907861267"></string>
-</resources>
diff --git a/packages/DocumentsUI/res/values-hu/strings.xml b/packages/DocumentsUI/res/values-hu/strings.xml
index 220d99c..b7e74e0 100644
--- a/packages/DocumentsUI/res/values-hu/strings.xml
+++ b/packages/DocumentsUI/res/values-hu/strings.xml
@@ -67,6 +67,7 @@
     <string name="share_via" msgid="8966594246261344259">"Megosztás itt:"</string>
     <string name="copy_notification_title" msgid="6374299806748219777">"Fájlok másolása"</string>
     <string name="move_notification_title" msgid="6193835179777284805">"Fájlok áthelyezése"</string>
+    <string name="delete_notification_title" msgid="3329403967712437496">"Fájlok törlése"</string>
     <string name="copy_remaining" msgid="6283790937387975095">"<xliff:g id="DURATION">%s</xliff:g> van hátra"</string>
     <plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
       <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> fájl másolása.</item>
@@ -111,4 +112,12 @@
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Egyes fájlokat konvertált a rendszer"</string>
     <string name="allow" msgid="7225948811296386551">"Engedélyezés"</string>
     <string name="deny" msgid="2081879885755434506">"Elutasítás"</string>
+    <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772">
+      <item quantity="other">Töröl <xliff:g id="COUNT_1">%1$d</xliff:g> fájlt?</item>
+      <item quantity="one">Töröl <xliff:g id="COUNT_0">%1$d</xliff:g> fájlt?</item>
+    </plurals>
+    <plurals name="elements_selected" formatted="false" msgid="1376955402452875047">
+      <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> kiválasztva</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> kiválasztva</item>
+    </plurals>
 </resources>
diff --git a/packages/DocumentsUI/res/values-hy-rAM/config.xml b/packages/DocumentsUI/res/values-hy-rAM/config.xml
deleted file mode 100644
index 843a8aa..0000000
--- a/packages/DocumentsUI/res/values-hy-rAM/config.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--  Copyright (C) 2015 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="trusted_quick_viewer_package" msgid="3354383993907861267"></string>
-</resources>
diff --git a/packages/DocumentsUI/res/values-hy-rAM/strings.xml b/packages/DocumentsUI/res/values-hy-rAM/strings.xml
index 4448fe4..4dbae9d 100644
--- a/packages/DocumentsUI/res/values-hy-rAM/strings.xml
+++ b/packages/DocumentsUI/res/values-hy-rAM/strings.xml
@@ -67,6 +67,7 @@
     <string name="share_via" msgid="8966594246261344259">"Տարածել"</string>
     <string name="copy_notification_title" msgid="6374299806748219777">"Ֆայլերի պատճենում"</string>
     <string name="move_notification_title" msgid="6193835179777284805">"Ֆայլերի տեղափոխում"</string>
+    <string name="delete_notification_title" msgid="3329403967712437496">"Ֆայլերը ջնջվում են"</string>
     <string name="copy_remaining" msgid="6283790937387975095">"Մնացել է <xliff:g id="DURATION">%s</xliff:g>"</string>
     <plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
       <item quantity="one"><xliff:g id="COUNT_1">%1$d</xliff:g> ֆայլի պատճենում:</item>
@@ -111,4 +112,12 @@
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Որոշ ֆայլեր փոխարկվել են"</string>
     <string name="allow" msgid="7225948811296386551">"Թույլատրել"</string>
     <string name="deny" msgid="2081879885755434506">"Մերժել"</string>
+    <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772">
+      <item quantity="one">Ջնջե՞լ <xliff:g id="COUNT_1">%1$d</xliff:g> ֆայլ:</item>
+      <item quantity="other">Ջնջե՞լ <xliff:g id="COUNT_1">%1$d</xliff:g> ֆայլ:</item>
+    </plurals>
+    <plurals name="elements_selected" formatted="false" msgid="1376955402452875047">
+      <item quantity="one">Ընտրված է՝ <xliff:g id="COUNT_1">%1$d</xliff:g></item>
+      <item quantity="other">Ընտրված է՝ <xliff:g id="COUNT_1">%1$d</xliff:g></item>
+    </plurals>
 </resources>
diff --git a/packages/DocumentsUI/res/values-in/config.xml b/packages/DocumentsUI/res/values-in/config.xml
deleted file mode 100644
index 843a8aa..0000000
--- a/packages/DocumentsUI/res/values-in/config.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--  Copyright (C) 2015 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="trusted_quick_viewer_package" msgid="3354383993907861267"></string>
-</resources>
diff --git a/packages/DocumentsUI/res/values-in/strings.xml b/packages/DocumentsUI/res/values-in/strings.xml
index 4d4e810..73ed8bc 100644
--- a/packages/DocumentsUI/res/values-in/strings.xml
+++ b/packages/DocumentsUI/res/values-in/strings.xml
@@ -67,6 +67,7 @@
     <string name="share_via" msgid="8966594246261344259">"Bagikan melalui"</string>
     <string name="copy_notification_title" msgid="6374299806748219777">"Menyalin file"</string>
     <string name="move_notification_title" msgid="6193835179777284805">"Memindahkan file"</string>
+    <string name="delete_notification_title" msgid="3329403967712437496">"Menghapus file"</string>
     <string name="copy_remaining" msgid="6283790937387975095">"<xliff:g id="DURATION">%s</xliff:g> lagi"</string>
     <plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
       <item quantity="other">Menyalin <xliff:g id="COUNT_1">%1$d</xliff:g> file.</item>
@@ -111,4 +112,12 @@
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Beberapa file dikonversi"</string>
     <string name="allow" msgid="7225948811296386551">"Izinkan"</string>
     <string name="deny" msgid="2081879885755434506">"Tolak"</string>
+    <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772">
+      <item quantity="other">Hapus <xliff:g id="COUNT_1">%1$d</xliff:g> file?</item>
+      <item quantity="one">Hapus <xliff:g id="COUNT_0">%1$d</xliff:g> file?</item>
+    </plurals>
+    <plurals name="elements_selected" formatted="false" msgid="1376955402452875047">
+      <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> dipilih</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> dipilih</item>
+    </plurals>
 </resources>
diff --git a/packages/DocumentsUI/res/values-is-rIS/config.xml b/packages/DocumentsUI/res/values-is-rIS/config.xml
deleted file mode 100644
index 843a8aa..0000000
--- a/packages/DocumentsUI/res/values-is-rIS/config.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--  Copyright (C) 2015 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="trusted_quick_viewer_package" msgid="3354383993907861267"></string>
-</resources>
diff --git a/packages/DocumentsUI/res/values-is-rIS/strings.xml b/packages/DocumentsUI/res/values-is-rIS/strings.xml
index d7e4284..75831ed 100644
--- a/packages/DocumentsUI/res/values-is-rIS/strings.xml
+++ b/packages/DocumentsUI/res/values-is-rIS/strings.xml
@@ -67,6 +67,7 @@
     <string name="share_via" msgid="8966594246261344259">"Deila í gegnum"</string>
     <string name="copy_notification_title" msgid="6374299806748219777">"Afritar skrár"</string>
     <string name="move_notification_title" msgid="6193835179777284805">"Skrár færðar"</string>
+    <string name="delete_notification_title" msgid="3329403967712437496">"Eyðir skrám"</string>
     <string name="copy_remaining" msgid="6283790937387975095">"<xliff:g id="DURATION">%s</xliff:g> eftir"</string>
     <plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
       <item quantity="one">Afritar <xliff:g id="COUNT_1">%1$d</xliff:g> skrá.</item>
@@ -111,4 +112,12 @@
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Sumum skrám var umbreytt"</string>
     <string name="allow" msgid="7225948811296386551">"Leyfa"</string>
     <string name="deny" msgid="2081879885755434506">"Hafna"</string>
+    <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772">
+      <item quantity="one">Eyða <xliff:g id="COUNT_1">%1$d</xliff:g> skrá?</item>
+      <item quantity="other">Eyða <xliff:g id="COUNT_1">%1$d</xliff:g> skrám?</item>
+    </plurals>
+    <plurals name="elements_selected" formatted="false" msgid="1376955402452875047">
+      <item quantity="one"><xliff:g id="COUNT_1">%1$d</xliff:g> valið</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> valin</item>
+    </plurals>
 </resources>
diff --git a/packages/DocumentsUI/res/values-it/config.xml b/packages/DocumentsUI/res/values-it/config.xml
deleted file mode 100644
index 843a8aa..0000000
--- a/packages/DocumentsUI/res/values-it/config.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--  Copyright (C) 2015 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="trusted_quick_viewer_package" msgid="3354383993907861267"></string>
-</resources>
diff --git a/packages/DocumentsUI/res/values-it/strings.xml b/packages/DocumentsUI/res/values-it/strings.xml
index 373f480..cfd5611 100644
--- a/packages/DocumentsUI/res/values-it/strings.xml
+++ b/packages/DocumentsUI/res/values-it/strings.xml
@@ -67,6 +67,7 @@
     <string name="share_via" msgid="8966594246261344259">"Condividi via"</string>
     <string name="copy_notification_title" msgid="6374299806748219777">"Copia di file in corso"</string>
     <string name="move_notification_title" msgid="6193835179777284805">"Spostamento di file"</string>
+    <string name="delete_notification_title" msgid="3329403967712437496">"Eliminazione dei file"</string>
     <string name="copy_remaining" msgid="6283790937387975095">"<xliff:g id="DURATION">%s</xliff:g> rimanenti"</string>
     <plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
       <item quantity="other">Copia di <xliff:g id="COUNT_1">%1$d</xliff:g> file in corso.</item>
@@ -111,4 +112,12 @@
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Alcuni file sono stati convertiti"</string>
     <string name="allow" msgid="7225948811296386551">"Consenti"</string>
     <string name="deny" msgid="2081879885755434506">"Nega"</string>
+    <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772">
+      <item quantity="other">Eliminare <xliff:g id="COUNT_1">%1$d</xliff:g> file?</item>
+      <item quantity="one">Eliminare <xliff:g id="COUNT_0">%1$d</xliff:g> file?</item>
+    </plurals>
+    <plurals name="elements_selected" formatted="false" msgid="1376955402452875047">
+      <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> elementi selezionati</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> elemento selezionato</item>
+    </plurals>
 </resources>
diff --git a/packages/DocumentsUI/res/values-iw/config.xml b/packages/DocumentsUI/res/values-iw/config.xml
deleted file mode 100644
index 843a8aa..0000000
--- a/packages/DocumentsUI/res/values-iw/config.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--  Copyright (C) 2015 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="trusted_quick_viewer_package" msgid="3354383993907861267"></string>
-</resources>
diff --git a/packages/DocumentsUI/res/values-iw/strings.xml b/packages/DocumentsUI/res/values-iw/strings.xml
index 8806079..7d4cb9e 100644
--- a/packages/DocumentsUI/res/values-iw/strings.xml
+++ b/packages/DocumentsUI/res/values-iw/strings.xml
@@ -67,6 +67,7 @@
     <string name="share_via" msgid="8966594246261344259">"שתף באמצעות"</string>
     <string name="copy_notification_title" msgid="6374299806748219777">"מעתיק קבצים"</string>
     <string name="move_notification_title" msgid="6193835179777284805">"מעביר קבצים"</string>
+    <string name="delete_notification_title" msgid="3329403967712437496">"מחיקת קבצים מתבצעת"</string>
     <string name="copy_remaining" msgid="6283790937387975095">"זמן נותר: <xliff:g id="DURATION">%s</xliff:g>"</string>
     <plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
       <item quantity="two">מעתיק <xliff:g id="COUNT_1">%1$d</xliff:g> קבצים.</item>
@@ -125,4 +126,16 @@
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"קבצים מסוימים הומרו"</string>
     <string name="allow" msgid="7225948811296386551">"אפשר"</string>
     <string name="deny" msgid="2081879885755434506">"דחה"</string>
+    <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772">
+      <item quantity="two">האם למחוק <xliff:g id="COUNT_1">%1$d</xliff:g> קבצים?</item>
+      <item quantity="many">האם למחוק <xliff:g id="COUNT_1">%1$d</xliff:g> קבצים?</item>
+      <item quantity="other">האם למחוק <xliff:g id="COUNT_1">%1$d</xliff:g> קבצים?</item>
+      <item quantity="one">האם למחוק קובץ <xliff:g id="COUNT_0">%1$d</xliff:g>?</item>
+    </plurals>
+    <plurals name="elements_selected" formatted="false" msgid="1376955402452875047">
+      <item quantity="two"><xliff:g id="COUNT_1">%1$d</xliff:g> נבחרו</item>
+      <item quantity="many"><xliff:g id="COUNT_1">%1$d</xliff:g> נבחרו</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> נבחרו</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> נבחר</item>
+    </plurals>
 </resources>
diff --git a/packages/DocumentsUI/res/values-ja/config.xml b/packages/DocumentsUI/res/values-ja/config.xml
deleted file mode 100644
index 843a8aa..0000000
--- a/packages/DocumentsUI/res/values-ja/config.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--  Copyright (C) 2015 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="trusted_quick_viewer_package" msgid="3354383993907861267"></string>
-</resources>
diff --git a/packages/DocumentsUI/res/values-ja/strings.xml b/packages/DocumentsUI/res/values-ja/strings.xml
index e0b82e5..9618d36 100644
--- a/packages/DocumentsUI/res/values-ja/strings.xml
+++ b/packages/DocumentsUI/res/values-ja/strings.xml
@@ -67,6 +67,7 @@
     <string name="share_via" msgid="8966594246261344259">"共有ツール"</string>
     <string name="copy_notification_title" msgid="6374299806748219777">"ファイルのコピー中"</string>
     <string name="move_notification_title" msgid="6193835179777284805">"ファイルを移動中"</string>
+    <string name="delete_notification_title" msgid="3329403967712437496">"ファイルを削除しています"</string>
     <string name="copy_remaining" msgid="6283790937387975095">"残り<xliff:g id="DURATION">%s</xliff:g>"</string>
     <plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
       <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g>個のファイルをコピーしています。</item>
@@ -111,4 +112,12 @@
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"一部のファイルが変換されました"</string>
     <string name="allow" msgid="7225948811296386551">"許可"</string>
     <string name="deny" msgid="2081879885755434506">"拒否"</string>
+    <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772">
+      <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> 個のファイルを削除しますか?</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> 個のファイルを削除しますか?</item>
+    </plurals>
+    <plurals name="elements_selected" formatted="false" msgid="1376955402452875047">
+      <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> 個を選択中</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> 個を選択中</item>
+    </plurals>
 </resources>
diff --git a/packages/DocumentsUI/res/values-ka-rGE/config.xml b/packages/DocumentsUI/res/values-ka-rGE/config.xml
deleted file mode 100644
index 843a8aa..0000000
--- a/packages/DocumentsUI/res/values-ka-rGE/config.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--  Copyright (C) 2015 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="trusted_quick_viewer_package" msgid="3354383993907861267"></string>
-</resources>
diff --git a/packages/DocumentsUI/res/values-ka-rGE/strings.xml b/packages/DocumentsUI/res/values-ka-rGE/strings.xml
index 5e1ddd3..ac8d267 100644
--- a/packages/DocumentsUI/res/values-ka-rGE/strings.xml
+++ b/packages/DocumentsUI/res/values-ka-rGE/strings.xml
@@ -67,6 +67,7 @@
     <string name="share_via" msgid="8966594246261344259">"გაზიარება:"</string>
     <string name="copy_notification_title" msgid="6374299806748219777">"მიმდ. ფაილების კოპირება"</string>
     <string name="move_notification_title" msgid="6193835179777284805">"ფაილების გადაადგილება"</string>
+    <string name="delete_notification_title" msgid="3329403967712437496">"ფაილების წაშლა…"</string>
     <string name="copy_remaining" msgid="6283790937387975095">"დარჩა <xliff:g id="DURATION">%s</xliff:g>"</string>
     <plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
       <item quantity="other">მიმდინარეობს <xliff:g id="COUNT_1">%1$d</xliff:g> ფაილის კოპირება.</item>
@@ -111,4 +112,12 @@
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"ზოგიერთი ფაილი გარდაქმნილია"</string>
     <string name="allow" msgid="7225948811296386551">"უფლების მიცემა"</string>
     <string name="deny" msgid="2081879885755434506">"აკრძალვა"</string>
+    <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772">
+      <item quantity="other">გსურთ <xliff:g id="COUNT_1">%1$d</xliff:g> ფაილის წაშლა?</item>
+      <item quantity="one">გსურთ <xliff:g id="COUNT_0">%1$d</xliff:g> ფაილის წაშლა?</item>
+    </plurals>
+    <plurals name="elements_selected" formatted="false" msgid="1376955402452875047">
+      <item quantity="other">არჩეულია <xliff:g id="COUNT_1">%1$d</xliff:g></item>
+      <item quantity="one">არჩეულია <xliff:g id="COUNT_0">%1$d</xliff:g></item>
+    </plurals>
 </resources>
diff --git a/packages/DocumentsUI/res/values-kk-rKZ/config.xml b/packages/DocumentsUI/res/values-kk-rKZ/config.xml
deleted file mode 100644
index 843a8aa..0000000
--- a/packages/DocumentsUI/res/values-kk-rKZ/config.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--  Copyright (C) 2015 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="trusted_quick_viewer_package" msgid="3354383993907861267"></string>
-</resources>
diff --git a/packages/DocumentsUI/res/values-kk-rKZ/strings.xml b/packages/DocumentsUI/res/values-kk-rKZ/strings.xml
index 5b6b94d..759506b 100644
--- a/packages/DocumentsUI/res/values-kk-rKZ/strings.xml
+++ b/packages/DocumentsUI/res/values-kk-rKZ/strings.xml
@@ -67,6 +67,7 @@
     <string name="share_via" msgid="8966594246261344259">"Бөлісу"</string>
     <string name="copy_notification_title" msgid="6374299806748219777">"Файлдарды көшіру"</string>
     <string name="move_notification_title" msgid="6193835179777284805">"Файлдар тасымалдануда"</string>
+    <string name="delete_notification_title" msgid="3329403967712437496">"Файлдар жойылуда"</string>
     <string name="copy_remaining" msgid="6283790937387975095">"<xliff:g id="DURATION">%s</xliff:g> қалды"</string>
     <plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
       <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> файлды көшіру.</item>
@@ -111,4 +112,12 @@
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Кейбір файлдар түрлендірілді"</string>
     <string name="allow" msgid="7225948811296386551">"Рұқсат беру"</string>
     <string name="deny" msgid="2081879885755434506">"Бас тарту"</string>
+    <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772">
+      <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> файлды жою керек пе?</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> файлды жою керек пе?</item>
+    </plurals>
+    <plurals name="elements_selected" formatted="false" msgid="1376955402452875047">
+      <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> таңдалды</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> таңдалды</item>
+    </plurals>
 </resources>
diff --git a/packages/DocumentsUI/res/values-km-rKH/config.xml b/packages/DocumentsUI/res/values-km-rKH/config.xml
deleted file mode 100644
index 843a8aa..0000000
--- a/packages/DocumentsUI/res/values-km-rKH/config.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--  Copyright (C) 2015 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="trusted_quick_viewer_package" msgid="3354383993907861267"></string>
-</resources>
diff --git a/packages/DocumentsUI/res/values-km-rKH/strings.xml b/packages/DocumentsUI/res/values-km-rKH/strings.xml
index 4664bd4..d83c1d3 100644
--- a/packages/DocumentsUI/res/values-km-rKH/strings.xml
+++ b/packages/DocumentsUI/res/values-km-rKH/strings.xml
@@ -67,6 +67,7 @@
     <string name="share_via" msgid="8966594246261344259">"ចែករំលែក​តាម"</string>
     <string name="copy_notification_title" msgid="6374299806748219777">"កំពុងថតចម្លងឯកសារ"</string>
     <string name="move_notification_title" msgid="6193835179777284805">"ផ្លាស់ទីឯកសារ"</string>
+    <string name="delete_notification_title" msgid="3329403967712437496">"កំពុងលុបឯកសារ"</string>
     <string name="copy_remaining" msgid="6283790937387975095">"នៅសល់ <xliff:g id="DURATION">%s</xliff:g>"</string>
     <plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
       <item quantity="other">កំពុងថតចម្លងឯកសារចំនួន <xliff:g id="COUNT_1">%1$d</xliff:g> ។</item>
@@ -111,4 +112,12 @@
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"ឯកសារមួយចំនួនត្រូវបានបម្លែង"</string>
     <string name="allow" msgid="7225948811296386551">"អនុញ្ញាត​"</string>
     <string name="deny" msgid="2081879885755434506">"បដិសេធ"</string>
+    <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772">
+      <item quantity="other">លុបឯកសារ <xliff:g id="COUNT_1">%1$d</xliff:g> ច្បាប់ឬ?</item>
+      <item quantity="one">លុបឯកសារ <xliff:g id="COUNT_0">%1$d</xliff:g> ច្បាប់ឬ?</item>
+    </plurals>
+    <plurals name="elements_selected" formatted="false" msgid="1376955402452875047">
+      <item quantity="other">បានជ្រើស <xliff:g id="COUNT_1">%1$d</xliff:g></item>
+      <item quantity="one">បានជ្រើស <xliff:g id="COUNT_0">%1$d</xliff:g></item>
+    </plurals>
 </resources>
diff --git a/packages/DocumentsUI/res/values-kn-rIN/config.xml b/packages/DocumentsUI/res/values-kn-rIN/config.xml
deleted file mode 100644
index 843a8aa..0000000
--- a/packages/DocumentsUI/res/values-kn-rIN/config.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--  Copyright (C) 2015 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="trusted_quick_viewer_package" msgid="3354383993907861267"></string>
-</resources>
diff --git a/packages/DocumentsUI/res/values-kn-rIN/strings.xml b/packages/DocumentsUI/res/values-kn-rIN/strings.xml
index 487a7b3..57ddd0b 100644
--- a/packages/DocumentsUI/res/values-kn-rIN/strings.xml
+++ b/packages/DocumentsUI/res/values-kn-rIN/strings.xml
@@ -67,6 +67,7 @@
     <string name="share_via" msgid="8966594246261344259">"ಈ ಮೂಲಕ ಹಂಚಿಕೊಳ್ಳಿ"</string>
     <string name="copy_notification_title" msgid="6374299806748219777">"ಫೈಲ್‌ಗಳನ್ನು ನಕಲಿಸಲಾಗುತ್ತಿದೆ"</string>
     <string name="move_notification_title" msgid="6193835179777284805">"ಫೈಲ್‌ಗಳನ್ನು ಸರಿಸಲಾಗುತ್ತಿದೆ"</string>
+    <string name="delete_notification_title" msgid="3329403967712437496">"ಫೈಲ್ ಅಳಿಸಲಾಗುತ್ತಿದೆ"</string>
     <string name="copy_remaining" msgid="6283790937387975095">"<xliff:g id="DURATION">%s</xliff:g> ಉಳಿದಿದೆ"</string>
     <plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
       <item quantity="one"> <xliff:g id="COUNT_1">%1$d</xliff:g> ಫೈಲ್‌ಗಳನ್ನು ನಕಲಿಸಲಾಗುತ್ತಿದೆ.</item>
@@ -111,4 +112,12 @@
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"ಕೆಲವು ಫೈಲ್‌ಗಳನ್ನು ಪರಿವರ್ತಿಸಲಾಗಿದೆ"</string>
     <string name="allow" msgid="7225948811296386551">"ಅನುಮತಿಸು"</string>
     <string name="deny" msgid="2081879885755434506">"ನಿರಾಕರಿಸು"</string>
+    <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772">
+      <item quantity="one"> <xliff:g id="COUNT_1">%1$d</xliff:g> ಫೈಲ್‌ಗಳನ್ನು ಅಳಿಸುವುದೇ?</item>
+      <item quantity="other"> <xliff:g id="COUNT_1">%1$d</xliff:g> ಫೈಲ್‌ಗಳನ್ನು ಅಳಿಸುವುದೇ?</item>
+    </plurals>
+    <plurals name="elements_selected" formatted="false" msgid="1376955402452875047">
+      <item quantity="one"><xliff:g id="COUNT_1">%1$d</xliff:g> ಆಯ್ಕೆಮಾಡಲಾಗಿದೆ</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> ಆಯ್ಕೆಮಾಡಲಾಗಿದೆ</item>
+    </plurals>
 </resources>
diff --git a/packages/DocumentsUI/res/values-ko/config.xml b/packages/DocumentsUI/res/values-ko/config.xml
deleted file mode 100644
index 843a8aa..0000000
--- a/packages/DocumentsUI/res/values-ko/config.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--  Copyright (C) 2015 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="trusted_quick_viewer_package" msgid="3354383993907861267"></string>
-</resources>
diff --git a/packages/DocumentsUI/res/values-ko/strings.xml b/packages/DocumentsUI/res/values-ko/strings.xml
index 62336c7..907802d 100644
--- a/packages/DocumentsUI/res/values-ko/strings.xml
+++ b/packages/DocumentsUI/res/values-ko/strings.xml
@@ -67,6 +67,7 @@
     <string name="share_via" msgid="8966594246261344259">"공유 방법"</string>
     <string name="copy_notification_title" msgid="6374299806748219777">"파일 복사 중"</string>
     <string name="move_notification_title" msgid="6193835179777284805">"파일 이동"</string>
+    <string name="delete_notification_title" msgid="3329403967712437496">"파일 삭제"</string>
     <string name="copy_remaining" msgid="6283790937387975095">"<xliff:g id="DURATION">%s</xliff:g> 남음"</string>
     <plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
       <item quantity="other">파일 <xliff:g id="COUNT_1">%1$d</xliff:g>개를 복사합니다.</item>
@@ -111,4 +112,12 @@
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"일부 파일이 변환되었습니다."</string>
     <string name="allow" msgid="7225948811296386551">"허용"</string>
     <string name="deny" msgid="2081879885755434506">"거부"</string>
+    <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772">
+      <item quantity="other">파일 <xliff:g id="COUNT_1">%1$d</xliff:g>개를 삭제하시겠습니까?</item>
+      <item quantity="one">파일 <xliff:g id="COUNT_0">%1$d</xliff:g>개를 삭제하시겠습니까?</item>
+    </plurals>
+    <plurals name="elements_selected" formatted="false" msgid="1376955402452875047">
+      <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g>개 선택됨</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g>개 선택됨</item>
+    </plurals>
 </resources>
diff --git a/packages/DocumentsUI/res/values-ky-rKG/config.xml b/packages/DocumentsUI/res/values-ky-rKG/config.xml
deleted file mode 100644
index 843a8aa..0000000
--- a/packages/DocumentsUI/res/values-ky-rKG/config.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--  Copyright (C) 2015 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="trusted_quick_viewer_package" msgid="3354383993907861267"></string>
-</resources>
diff --git a/packages/DocumentsUI/res/values-ky-rKG/strings.xml b/packages/DocumentsUI/res/values-ky-rKG/strings.xml
index f93f709..699e76a 100644
--- a/packages/DocumentsUI/res/values-ky-rKG/strings.xml
+++ b/packages/DocumentsUI/res/values-ky-rKG/strings.xml
@@ -67,6 +67,7 @@
     <string name="share_via" msgid="8966594246261344259">"Кийинки аркылуу бөлүшүү:"</string>
     <string name="copy_notification_title" msgid="6374299806748219777">"Файлдар көчүрүлүүдө"</string>
     <string name="move_notification_title" msgid="6193835179777284805">"Файлдар жылдырылууда…"</string>
+    <string name="delete_notification_title" msgid="3329403967712437496">"Файлдар жок кылынууда"</string>
     <string name="copy_remaining" msgid="6283790937387975095">"<xliff:g id="DURATION">%s</xliff:g> калды"</string>
     <plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
       <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> файл көчүрүлүүдө.</item>
@@ -111,4 +112,12 @@
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Айрым файлдардын форматы өзгөртүлдү"</string>
     <string name="allow" msgid="7225948811296386551">"Уруксат берүү"</string>
     <string name="deny" msgid="2081879885755434506">"Жок"</string>
+    <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772">
+      <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> файл жок кылынсынбы?</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> файл жок кылынсынбы?</item>
+    </plurals>
+    <plurals name="elements_selected" formatted="false" msgid="1376955402452875047">
+      <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> тандалды</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> тандалды</item>
+    </plurals>
 </resources>
diff --git a/packages/DocumentsUI/res/values-lo-rLA/config.xml b/packages/DocumentsUI/res/values-lo-rLA/config.xml
deleted file mode 100644
index 843a8aa..0000000
--- a/packages/DocumentsUI/res/values-lo-rLA/config.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--  Copyright (C) 2015 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="trusted_quick_viewer_package" msgid="3354383993907861267"></string>
-</resources>
diff --git a/packages/DocumentsUI/res/values-lo-rLA/strings.xml b/packages/DocumentsUI/res/values-lo-rLA/strings.xml
index 4b36057..468853b 100644
--- a/packages/DocumentsUI/res/values-lo-rLA/strings.xml
+++ b/packages/DocumentsUI/res/values-lo-rLA/strings.xml
@@ -67,6 +67,7 @@
     <string name="share_via" msgid="8966594246261344259">"ແບ່ງປັນຜ່ານ"</string>
     <string name="copy_notification_title" msgid="6374299806748219777">"ກຳ​ລັງ​ອັດ​ສຳ​ເນົາ​ໄຟ​ລ໌"</string>
     <string name="move_notification_title" msgid="6193835179777284805">"ກຳ​ລັງ​ຍ້າຍ​ໄຟ​ລ໌"</string>
+    <string name="delete_notification_title" msgid="3329403967712437496">"ກຳລັງລຶບໄຟລ໌"</string>
     <string name="copy_remaining" msgid="6283790937387975095">"<xliff:g id="DURATION">%s</xliff:g> ຍັງ​ເຫຼືອ​ຢູ່"</string>
     <plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
       <item quantity="other">ກຳ​ລັງ​ອັດ​ສຳ​ເນົາ <xliff:g id="COUNT_1">%1$d</xliff:g> ໄຟ​ລ໌.</item>
@@ -111,4 +112,12 @@
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"ປ່ຽນແປງບາງໄຟລ໌ແລ້ວ"</string>
     <string name="allow" msgid="7225948811296386551">"ອະນຸຍາດ"</string>
     <string name="deny" msgid="2081879885755434506">"ປະ​ຕິ​ເສດ"</string>
+    <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772">
+      <item quantity="other">ລຶບ <xliff:g id="COUNT_1">%1$d</xliff:g> ໄຟລ໌ອອກບໍ?</item>
+      <item quantity="one">ລຶບ <xliff:g id="COUNT_0">%1$d</xliff:g> ໄຟລ໌ອອກບໍ?</item>
+    </plurals>
+    <plurals name="elements_selected" formatted="false" msgid="1376955402452875047">
+      <item quantity="other">ເລືອກ <xliff:g id="COUNT_1">%1$d</xliff:g> ແລ້ວ</item>
+      <item quantity="one">ເລືອກ <xliff:g id="COUNT_0">%1$d</xliff:g> ແລ້ວ</item>
+    </plurals>
 </resources>
diff --git a/packages/DocumentsUI/res/values-lt/config.xml b/packages/DocumentsUI/res/values-lt/config.xml
deleted file mode 100644
index 843a8aa..0000000
--- a/packages/DocumentsUI/res/values-lt/config.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--  Copyright (C) 2015 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="trusted_quick_viewer_package" msgid="3354383993907861267"></string>
-</resources>
diff --git a/packages/DocumentsUI/res/values-lt/strings.xml b/packages/DocumentsUI/res/values-lt/strings.xml
index 8de09ce..a6297be 100644
--- a/packages/DocumentsUI/res/values-lt/strings.xml
+++ b/packages/DocumentsUI/res/values-lt/strings.xml
@@ -67,6 +67,7 @@
     <string name="share_via" msgid="8966594246261344259">"Bendrinti naudojant"</string>
     <string name="copy_notification_title" msgid="6374299806748219777">"Kopijuojami failai"</string>
     <string name="move_notification_title" msgid="6193835179777284805">"Perkeliami failai"</string>
+    <string name="delete_notification_title" msgid="3329403967712437496">"Failų ištrynimas"</string>
     <string name="copy_remaining" msgid="6283790937387975095">"Liko: <xliff:g id="DURATION">%s</xliff:g>"</string>
     <plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
       <item quantity="one">Kopijuojamas <xliff:g id="COUNT_1">%1$d</xliff:g> failas.</item>
@@ -125,4 +126,16 @@
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Kai kurie failai buvo konvertuoti"</string>
     <string name="allow" msgid="7225948811296386551">"Leisti"</string>
     <string name="deny" msgid="2081879885755434506">"Atmesti"</string>
+    <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772">
+      <item quantity="one">Ištrinti <xliff:g id="COUNT_1">%1$d</xliff:g> failą?</item>
+      <item quantity="few">Ištrinti <xliff:g id="COUNT_1">%1$d</xliff:g> failus?</item>
+      <item quantity="many">Ištrinti <xliff:g id="COUNT_1">%1$d</xliff:g> failo?</item>
+      <item quantity="other">Ištrinti <xliff:g id="COUNT_1">%1$d</xliff:g> failų?</item>
+    </plurals>
+    <plurals name="elements_selected" formatted="false" msgid="1376955402452875047">
+      <item quantity="one">Pasirinktas <xliff:g id="COUNT_1">%1$d</xliff:g> elementas</item>
+      <item quantity="few">Pasirinkti <xliff:g id="COUNT_1">%1$d</xliff:g> elementai</item>
+      <item quantity="many">Pasirinkta <xliff:g id="COUNT_1">%1$d</xliff:g> elemento</item>
+      <item quantity="other">Pasirinkta <xliff:g id="COUNT_1">%1$d</xliff:g> elementų</item>
+    </plurals>
 </resources>
diff --git a/packages/DocumentsUI/res/values-lv/config.xml b/packages/DocumentsUI/res/values-lv/config.xml
deleted file mode 100644
index 843a8aa..0000000
--- a/packages/DocumentsUI/res/values-lv/config.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--  Copyright (C) 2015 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="trusted_quick_viewer_package" msgid="3354383993907861267"></string>
-</resources>
diff --git a/packages/DocumentsUI/res/values-lv/strings.xml b/packages/DocumentsUI/res/values-lv/strings.xml
index 7711941..1a9b77c0 100644
--- a/packages/DocumentsUI/res/values-lv/strings.xml
+++ b/packages/DocumentsUI/res/values-lv/strings.xml
@@ -67,6 +67,7 @@
     <string name="share_via" msgid="8966594246261344259">"Kopīgot, izmantojot"</string>
     <string name="copy_notification_title" msgid="6374299806748219777">"Notiek failu kopēšana"</string>
     <string name="move_notification_title" msgid="6193835179777284805">"Failu pārvietošana"</string>
+    <string name="delete_notification_title" msgid="3329403967712437496">"Notiek failu dzēšana"</string>
     <string name="copy_remaining" msgid="6283790937387975095">"Atlikušais laiks: <xliff:g id="DURATION">%s</xliff:g>"</string>
     <plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
       <item quantity="zero">Notiek <xliff:g id="COUNT_1">%1$d</xliff:g> failu kopēšana.</item>
@@ -118,4 +119,14 @@
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Daži faili tika pārveidoti."</string>
     <string name="allow" msgid="7225948811296386551">"Atļaut"</string>
     <string name="deny" msgid="2081879885755434506">"Noraidīt"</string>
+    <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772">
+      <item quantity="zero">Vai izdzēst <xliff:g id="COUNT_1">%1$d</xliff:g> failus?</item>
+      <item quantity="one">Vai izdzēst <xliff:g id="COUNT_1">%1$d</xliff:g> failu?</item>
+      <item quantity="other">Vai izdzēst <xliff:g id="COUNT_1">%1$d</xliff:g> failus?</item>
+    </plurals>
+    <plurals name="elements_selected" formatted="false" msgid="1376955402452875047">
+      <item quantity="zero"><xliff:g id="COUNT_1">%1$d</xliff:g> atlasīti</item>
+      <item quantity="one"><xliff:g id="COUNT_1">%1$d</xliff:g> atlasīts</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> atlasīti</item>
+    </plurals>
 </resources>
diff --git a/packages/DocumentsUI/res/values-mk-rMK/config.xml b/packages/DocumentsUI/res/values-mk-rMK/config.xml
deleted file mode 100644
index 843a8aa..0000000
--- a/packages/DocumentsUI/res/values-mk-rMK/config.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--  Copyright (C) 2015 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="trusted_quick_viewer_package" msgid="3354383993907861267"></string>
-</resources>
diff --git a/packages/DocumentsUI/res/values-mk-rMK/strings.xml b/packages/DocumentsUI/res/values-mk-rMK/strings.xml
index 7798ea6..5bbf8c5 100644
--- a/packages/DocumentsUI/res/values-mk-rMK/strings.xml
+++ b/packages/DocumentsUI/res/values-mk-rMK/strings.xml
@@ -67,6 +67,7 @@
     <string name="share_via" msgid="8966594246261344259">"Сподели преку"</string>
     <string name="copy_notification_title" msgid="6374299806748219777">"Се копираат датотеки"</string>
     <string name="move_notification_title" msgid="6193835179777284805">"Датотеките се преместуваат"</string>
+    <string name="delete_notification_title" msgid="3329403967712437496">"Се бришат датотеките"</string>
     <string name="copy_remaining" msgid="6283790937387975095">"Уште <xliff:g id="DURATION">%s</xliff:g>"</string>
     <plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
       <item quantity="one">Се копира <xliff:g id="COUNT_1">%1$d</xliff:g> датотека.</item>
@@ -111,4 +112,12 @@
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Некои датотеки беа конвертирани"</string>
     <string name="allow" msgid="7225948811296386551">"Дозволи"</string>
     <string name="deny" msgid="2081879885755434506">"Одбиј"</string>
+    <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772">
+      <item quantity="one">Да се избрише <xliff:g id="COUNT_1">%1$d</xliff:g> датотека?</item>
+      <item quantity="other">Да се избришат <xliff:g id="COUNT_1">%1$d</xliff:g> датотеки?</item>
+    </plurals>
+    <plurals name="elements_selected" formatted="false" msgid="1376955402452875047">
+      <item quantity="one"><xliff:g id="COUNT_1">%1$d</xliff:g> е избрана</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> се избрани</item>
+    </plurals>
 </resources>
diff --git a/packages/DocumentsUI/res/values-ml-rIN/config.xml b/packages/DocumentsUI/res/values-ml-rIN/config.xml
deleted file mode 100644
index 843a8aa..0000000
--- a/packages/DocumentsUI/res/values-ml-rIN/config.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--  Copyright (C) 2015 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="trusted_quick_viewer_package" msgid="3354383993907861267"></string>
-</resources>
diff --git a/packages/DocumentsUI/res/values-ml-rIN/strings.xml b/packages/DocumentsUI/res/values-ml-rIN/strings.xml
index a9f9a46..264d196 100644
--- a/packages/DocumentsUI/res/values-ml-rIN/strings.xml
+++ b/packages/DocumentsUI/res/values-ml-rIN/strings.xml
@@ -67,6 +67,7 @@
     <string name="share_via" msgid="8966594246261344259">"ഇതുവഴി പങ്കിടുക"</string>
     <string name="copy_notification_title" msgid="6374299806748219777">"ഫയലുകൾ പകർത്തുന്നു"</string>
     <string name="move_notification_title" msgid="6193835179777284805">"ഫയലുകൾ നീക്കുന്നു"</string>
+    <string name="delete_notification_title" msgid="3329403967712437496">"ഫയലുകൾ ഇല്ലാതാക്കുന്നു"</string>
     <string name="copy_remaining" msgid="6283790937387975095">"<xliff:g id="DURATION">%s</xliff:g> ശേഷിക്കുന്നു"</string>
     <plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
       <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> ഫയലുകൾ പകർത്തുന്നു.</item>
@@ -111,4 +112,12 @@
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"ചില ഫയലുകൾ പരിവർത്തനം ചെയ്യപ്പെട്ടു"</string>
     <string name="allow" msgid="7225948811296386551">"അനുവദിക്കുക"</string>
     <string name="deny" msgid="2081879885755434506">"നിരസിക്കുക"</string>
+    <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772">
+      <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> ഫയലുകൾ ഇല്ലാതാക്കണോ?</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> ഫയൽ ഇല്ലാതാക്കണോ?</item>
+    </plurals>
+    <plurals name="elements_selected" formatted="false" msgid="1376955402452875047">
+      <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> തിരഞ്ഞെടുത്തു</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> തിരഞ്ഞെടുത്തു</item>
+    </plurals>
 </resources>
diff --git a/packages/DocumentsUI/res/values-mn-rMN/config.xml b/packages/DocumentsUI/res/values-mn-rMN/config.xml
deleted file mode 100644
index 843a8aa..0000000
--- a/packages/DocumentsUI/res/values-mn-rMN/config.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--  Copyright (C) 2015 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="trusted_quick_viewer_package" msgid="3354383993907861267"></string>
-</resources>
diff --git a/packages/DocumentsUI/res/values-mn-rMN/strings.xml b/packages/DocumentsUI/res/values-mn-rMN/strings.xml
index 0663588..02c818b 100644
--- a/packages/DocumentsUI/res/values-mn-rMN/strings.xml
+++ b/packages/DocumentsUI/res/values-mn-rMN/strings.xml
@@ -67,6 +67,7 @@
     <string name="share_via" msgid="8966594246261344259">"Дараахаар дамжуулан хуваалцах"</string>
     <string name="copy_notification_title" msgid="6374299806748219777">"Файлуудыг хуулж байна"</string>
     <string name="move_notification_title" msgid="6193835179777284805">"Файлыг зөөвөрлөж байна"</string>
+    <string name="delete_notification_title" msgid="3329403967712437496">"Эдгээр файлыг устгаж байна"</string>
     <string name="copy_remaining" msgid="6283790937387975095">"<xliff:g id="DURATION">%s</xliff:g> үлдсэн"</string>
     <plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
       <item quantity="other"> <xliff:g id="COUNT_1">%1$d</xliff:g> файлуудыг хуулж байна.</item>
@@ -111,4 +112,12 @@
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Зарим файлыг хөрвүүлсэн"</string>
     <string name="allow" msgid="7225948811296386551">"Зөвшөөрөх"</string>
     <string name="deny" msgid="2081879885755434506">"Татгалзах"</string>
+    <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772">
+      <item quantity="other"> <xliff:g id="COUNT_1">%1$d</xliff:g> файлыг устгах уу?</item>
+      <item quantity="one"> <xliff:g id="COUNT_0">%1$d</xliff:g> файлыг устгах уу?</item>
+    </plurals>
+    <plurals name="elements_selected" formatted="false" msgid="1376955402452875047">
+      <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> сонгосон</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> сонгосон</item>
+    </plurals>
 </resources>
diff --git a/packages/DocumentsUI/res/values-mr-rIN/config.xml b/packages/DocumentsUI/res/values-mr-rIN/config.xml
deleted file mode 100644
index 843a8aa..0000000
--- a/packages/DocumentsUI/res/values-mr-rIN/config.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--  Copyright (C) 2015 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="trusted_quick_viewer_package" msgid="3354383993907861267"></string>
-</resources>
diff --git a/packages/DocumentsUI/res/values-mr-rIN/strings.xml b/packages/DocumentsUI/res/values-mr-rIN/strings.xml
index 82bb882..6fae578 100644
--- a/packages/DocumentsUI/res/values-mr-rIN/strings.xml
+++ b/packages/DocumentsUI/res/values-mr-rIN/strings.xml
@@ -67,6 +67,7 @@
     <string name="share_via" msgid="8966594246261344259">"द्वारे सामायिक करा"</string>
     <string name="copy_notification_title" msgid="6374299806748219777">"फायली कॉपी करीत आहे"</string>
     <string name="move_notification_title" msgid="6193835179777284805">"फायली हलविणे"</string>
+    <string name="delete_notification_title" msgid="3329403967712437496">"फायली हटवित आहे"</string>
     <string name="copy_remaining" msgid="6283790937387975095">"<xliff:g id="DURATION">%s</xliff:g> शिल्लक"</string>
     <plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
       <item quantity="one"><xliff:g id="COUNT_1">%1$d</xliff:g> फाईल कॉपी करीत आहे.</item>
@@ -111,4 +112,12 @@
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"काही फायली रूपांतरित केल्या होत्या"</string>
     <string name="allow" msgid="7225948811296386551">"अनुमती द्या"</string>
     <string name="deny" msgid="2081879885755434506">"नकार द्या"</string>
+    <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772">
+      <item quantity="one"> <xliff:g id="COUNT_1">%1$d</xliff:g> फाईल हटवायची?</item>
+      <item quantity="other"> <xliff:g id="COUNT_1">%1$d</xliff:g> फायली हटवायच्या?</item>
+    </plurals>
+    <plurals name="elements_selected" formatted="false" msgid="1376955402452875047">
+      <item quantity="one"><xliff:g id="COUNT_1">%1$d</xliff:g> निवडला</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> निवडले</item>
+    </plurals>
 </resources>
diff --git a/packages/DocumentsUI/res/values-ms-rMY/config.xml b/packages/DocumentsUI/res/values-ms-rMY/config.xml
deleted file mode 100644
index 843a8aa..0000000
--- a/packages/DocumentsUI/res/values-ms-rMY/config.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--  Copyright (C) 2015 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="trusted_quick_viewer_package" msgid="3354383993907861267"></string>
-</resources>
diff --git a/packages/DocumentsUI/res/values-ms-rMY/strings.xml b/packages/DocumentsUI/res/values-ms-rMY/strings.xml
index 64f6163..6f7c525 100644
--- a/packages/DocumentsUI/res/values-ms-rMY/strings.xml
+++ b/packages/DocumentsUI/res/values-ms-rMY/strings.xml
@@ -67,6 +67,7 @@
     <string name="share_via" msgid="8966594246261344259">"Kongsi melalui"</string>
     <string name="copy_notification_title" msgid="6374299806748219777">"Menyalin fail"</string>
     <string name="move_notification_title" msgid="6193835179777284805">"Mengalihkan fail"</string>
+    <string name="delete_notification_title" msgid="3329403967712437496">"Memadamkan fail"</string>
     <string name="copy_remaining" msgid="6283790937387975095">"<xliff:g id="DURATION">%s</xliff:g> lagi"</string>
     <plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
       <item quantity="other">Menyalin <xliff:g id="COUNT_1">%1$d</xliff:g> fail.</item>
@@ -111,4 +112,12 @@
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Sesetengah fail telah ditukarkan"</string>
     <string name="allow" msgid="7225948811296386551">"Benarkan"</string>
     <string name="deny" msgid="2081879885755434506">"Nafi"</string>
+    <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772">
+      <item quantity="other">Padamkan <xliff:g id="COUNT_1">%1$d</xliff:g> fail?</item>
+      <item quantity="one">Padamkan <xliff:g id="COUNT_0">%1$d</xliff:g> fail?</item>
+    </plurals>
+    <plurals name="elements_selected" formatted="false" msgid="1376955402452875047">
+      <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> dipilih</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> dipilih</item>
+    </plurals>
 </resources>
diff --git a/packages/DocumentsUI/res/values-my-rMM/config.xml b/packages/DocumentsUI/res/values-my-rMM/config.xml
deleted file mode 100644
index 843a8aa..0000000
--- a/packages/DocumentsUI/res/values-my-rMM/config.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--  Copyright (C) 2015 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="trusted_quick_viewer_package" msgid="3354383993907861267"></string>
-</resources>
diff --git a/packages/DocumentsUI/res/values-my-rMM/strings.xml b/packages/DocumentsUI/res/values-my-rMM/strings.xml
index 2813f2d..9fb7f84 100644
--- a/packages/DocumentsUI/res/values-my-rMM/strings.xml
+++ b/packages/DocumentsUI/res/values-my-rMM/strings.xml
@@ -67,6 +67,7 @@
     <string name="share_via" msgid="8966594246261344259">"မှ ဝေမျှပါ"</string>
     <string name="copy_notification_title" msgid="6374299806748219777">"ဖိုင်များကူယူနေသည်"</string>
     <string name="move_notification_title" msgid="6193835179777284805">"ဖိုင်များ ရွှေ့နေသည်"</string>
+    <string name="delete_notification_title" msgid="3329403967712437496">"ဖိုင်များကို ဖျက်နေသည်"</string>
     <string name="copy_remaining" msgid="6283790937387975095">"<xliff:g id="DURATION">%s</xliff:g> ကျန်ရှိသည်"</string>
     <plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
       <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> ဖိုင်များကို ကူးယူနေသည်။</item>
@@ -111,4 +112,12 @@
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"အချို့ဖိုင်များကို ပြောင်းလဲထားသည်"</string>
     <string name="allow" msgid="7225948811296386551">"ခွင့်ပြုသည်"</string>
     <string name="deny" msgid="2081879885755434506">"ငြင်းပယ်သည်"</string>
+    <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772">
+      <item quantity="other">ဖိုင် <xliff:g id="COUNT_1">%1$d</xliff:g> ခုကိုဖျက်မလား။</item>
+      <item quantity="one">ဖိုင် <xliff:g id="COUNT_0">%1$d</xliff:g> ခုကိုဖျက်မလား။</item>
+    </plurals>
+    <plurals name="elements_selected" formatted="false" msgid="1376955402452875047">
+      <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> ခုရွေးချယ်ထားသည်</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> ခုရွေးချယ်ထားသည်</item>
+    </plurals>
 </resources>
diff --git a/packages/DocumentsUI/res/values-nb/config.xml b/packages/DocumentsUI/res/values-nb/config.xml
deleted file mode 100644
index 843a8aa..0000000
--- a/packages/DocumentsUI/res/values-nb/config.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--  Copyright (C) 2015 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="trusted_quick_viewer_package" msgid="3354383993907861267"></string>
-</resources>
diff --git a/packages/DocumentsUI/res/values-nb/strings.xml b/packages/DocumentsUI/res/values-nb/strings.xml
index d79b279..0e48f0f 100644
--- a/packages/DocumentsUI/res/values-nb/strings.xml
+++ b/packages/DocumentsUI/res/values-nb/strings.xml
@@ -67,6 +67,7 @@
     <string name="share_via" msgid="8966594246261344259">"Del via"</string>
     <string name="copy_notification_title" msgid="6374299806748219777">"Kopierer filer"</string>
     <string name="move_notification_title" msgid="6193835179777284805">"Flytter filer"</string>
+    <string name="delete_notification_title" msgid="3329403967712437496">"Sletter filene"</string>
     <string name="copy_remaining" msgid="6283790937387975095">"<xliff:g id="DURATION">%s</xliff:g> gjenstår"</string>
     <plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
       <item quantity="other">Kopierer <xliff:g id="COUNT_1">%1$d</xliff:g> filer.</item>
@@ -111,4 +112,12 @@
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Noen filer er konvertert"</string>
     <string name="allow" msgid="7225948811296386551">"Tillat"</string>
     <string name="deny" msgid="2081879885755434506">"Avslå"</string>
+    <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772">
+      <item quantity="other">Vil du slette <xliff:g id="COUNT_1">%1$d</xliff:g> filer?</item>
+      <item quantity="one">Vil du slette <xliff:g id="COUNT_0">%1$d</xliff:g> fil?</item>
+    </plurals>
+    <plurals name="elements_selected" formatted="false" msgid="1376955402452875047">
+      <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> er valgt</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> er valgt</item>
+    </plurals>
 </resources>
diff --git a/packages/DocumentsUI/res/values-ne-rNP/config.xml b/packages/DocumentsUI/res/values-ne-rNP/config.xml
deleted file mode 100644
index 843a8aa..0000000
--- a/packages/DocumentsUI/res/values-ne-rNP/config.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--  Copyright (C) 2015 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="trusted_quick_viewer_package" msgid="3354383993907861267"></string>
-</resources>
diff --git a/packages/DocumentsUI/res/values-ne-rNP/strings.xml b/packages/DocumentsUI/res/values-ne-rNP/strings.xml
index 057e03f..cc70c91 100644
--- a/packages/DocumentsUI/res/values-ne-rNP/strings.xml
+++ b/packages/DocumentsUI/res/values-ne-rNP/strings.xml
@@ -67,6 +67,7 @@
     <string name="share_via" msgid="8966594246261344259">"माध्यमबाट साझेदारी गर्नुहोस्"</string>
     <string name="copy_notification_title" msgid="6374299806748219777">"फाइलहरू प्रतिलिपि गर्दै:"</string>
     <string name="move_notification_title" msgid="6193835179777284805">"फाइलहरू सार्दै"</string>
+    <string name="delete_notification_title" msgid="3329403967712437496">"फाइलहरूलाई मेट्दै"</string>
     <string name="copy_remaining" msgid="6283790937387975095">"<xliff:g id="DURATION">%s</xliff:g>बाँकी"</string>
     <plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
       <item quantity="other"> <xliff:g id="COUNT_1">%1$d</xliff:g>फाइलहरू प्रतिलिप गर्दै।</item>
@@ -111,4 +112,12 @@
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"केही फाइलहरू परिवर्तन गरिएका थिए"</string>
     <string name="allow" msgid="7225948811296386551">"अनुमति दिनुहोस्"</string>
     <string name="deny" msgid="2081879885755434506">"अस्वीकार गर्नुहोस्"</string>
+    <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772">
+      <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> फाइलहरूलाई मेट्ने हो?</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> फाइललाई मेट्ने हो?</item>
+    </plurals>
+    <plurals name="elements_selected" formatted="false" msgid="1376955402452875047">
+      <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> लाई चयन गरियो</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> लाई चयन गरियो</item>
+    </plurals>
 </resources>
diff --git a/packages/DocumentsUI/res/values-nl/config.xml b/packages/DocumentsUI/res/values-nl/config.xml
deleted file mode 100644
index 843a8aa..0000000
--- a/packages/DocumentsUI/res/values-nl/config.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--  Copyright (C) 2015 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="trusted_quick_viewer_package" msgid="3354383993907861267"></string>
-</resources>
diff --git a/packages/DocumentsUI/res/values-nl/strings.xml b/packages/DocumentsUI/res/values-nl/strings.xml
index 99a9f91..ebddf54 100644
--- a/packages/DocumentsUI/res/values-nl/strings.xml
+++ b/packages/DocumentsUI/res/values-nl/strings.xml
@@ -67,6 +67,7 @@
     <string name="share_via" msgid="8966594246261344259">"Delen via"</string>
     <string name="copy_notification_title" msgid="6374299806748219777">"Bestanden kopiëren"</string>
     <string name="move_notification_title" msgid="6193835179777284805">"Bestanden verplaatsen"</string>
+    <string name="delete_notification_title" msgid="3329403967712437496">"Bestanden verwijderen"</string>
     <string name="copy_remaining" msgid="6283790937387975095">"<xliff:g id="DURATION">%s</xliff:g> resterend"</string>
     <plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
       <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> bestanden kopiëren.</item>
@@ -111,4 +112,12 @@
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Sommige bestanden zijn geconverteerd"</string>
     <string name="allow" msgid="7225948811296386551">"Toestaan"</string>
     <string name="deny" msgid="2081879885755434506">"Weigeren"</string>
+    <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772">
+      <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> bestanden verwijderen?</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> bestand verwijderen?</item>
+    </plurals>
+    <plurals name="elements_selected" formatted="false" msgid="1376955402452875047">
+      <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> geselecteerd</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> geselecteerd</item>
+    </plurals>
 </resources>
diff --git a/packages/DocumentsUI/res/values-pa-rIN/config.xml b/packages/DocumentsUI/res/values-pa-rIN/config.xml
deleted file mode 100644
index 843a8aa..0000000
--- a/packages/DocumentsUI/res/values-pa-rIN/config.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--  Copyright (C) 2015 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="trusted_quick_viewer_package" msgid="3354383993907861267"></string>
-</resources>
diff --git a/packages/DocumentsUI/res/values-pa-rIN/strings.xml b/packages/DocumentsUI/res/values-pa-rIN/strings.xml
index 758a4d8..a8c65e7 100644
--- a/packages/DocumentsUI/res/values-pa-rIN/strings.xml
+++ b/packages/DocumentsUI/res/values-pa-rIN/strings.xml
@@ -67,6 +67,7 @@
     <string name="share_via" msgid="8966594246261344259">"ਇਸ ਰਾਹੀਂ ਸ਼ੇਅਰ ਕਰੋ"</string>
     <string name="copy_notification_title" msgid="6374299806748219777">"ਫਾਈਲਾਂ ਕਾਪੀ ਕਰ ਰਿਹਾ ਹੈ"</string>
     <string name="move_notification_title" msgid="6193835179777284805">"ਫ਼ਾਈਲਾਂ ਨੂੰ ਮੂਵ ਕਰ ਰਿਹਾ ਹੈ"</string>
+    <string name="delete_notification_title" msgid="3329403967712437496">"ਫ਼ਾਈਲਾਂ ਨੂੰ ਮਿਟਾਇਆ ਜਾ ਰਿਹਾ ਹੈ"</string>
     <string name="copy_remaining" msgid="6283790937387975095">"<xliff:g id="DURATION">%s</xliff:g> ਬਾਕੀ"</string>
     <plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
       <item quantity="one"> <xliff:g id="COUNT_1">%1$d</xliff:g> ਫਾਈਲਾਂ ਕਾਪੀ ਕਰ ਰਿਹਾ ਹੈ।</item>
@@ -111,4 +112,12 @@
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"ਕੁਝ ਫ਼ਾਈਲਾਂ ਤਬਦੀਲ ਕੀਤੀਆਂ ਗਈਆਂ ਸਨ"</string>
     <string name="allow" msgid="7225948811296386551">"ਆਗਿਆ ਦਿਓ"</string>
     <string name="deny" msgid="2081879885755434506">"ਅਸਵੀਕਾਰ ਕਰੋ"</string>
+    <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772">
+      <item quantity="one">ਕੀ <xliff:g id="COUNT_1">%1$d</xliff:g> ਫ਼ਾਈਲਾਂ ਨੂੰ ਮਿਟਾਉਣਾ ਹੈ?</item>
+      <item quantity="other">ਕੀ <xliff:g id="COUNT_1">%1$d</xliff:g> ਫ਼ਾਈਲਾਂ ਨੂੰ ਮਿਟਾਉਣਾ ਹੈ?</item>
+    </plurals>
+    <plurals name="elements_selected" formatted="false" msgid="1376955402452875047">
+      <item quantity="one"><xliff:g id="COUNT_1">%1$d</xliff:g> ਚੁਣੀ ਗਈ</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> ਚੁਣੀਆਂ ਗਈਆਂ</item>
+    </plurals>
 </resources>
diff --git a/packages/DocumentsUI/res/values-pl/config.xml b/packages/DocumentsUI/res/values-pl/config.xml
deleted file mode 100644
index 843a8aa..0000000
--- a/packages/DocumentsUI/res/values-pl/config.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--  Copyright (C) 2015 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="trusted_quick_viewer_package" msgid="3354383993907861267"></string>
-</resources>
diff --git a/packages/DocumentsUI/res/values-pl/strings.xml b/packages/DocumentsUI/res/values-pl/strings.xml
index 8a4d17c..e888fd7 100644
--- a/packages/DocumentsUI/res/values-pl/strings.xml
+++ b/packages/DocumentsUI/res/values-pl/strings.xml
@@ -67,6 +67,7 @@
     <string name="share_via" msgid="8966594246261344259">"Udostępnij przez:"</string>
     <string name="copy_notification_title" msgid="6374299806748219777">"Kopiowanie plików"</string>
     <string name="move_notification_title" msgid="6193835179777284805">"Przenoszenie plików"</string>
+    <string name="delete_notification_title" msgid="3329403967712437496">"Usuwam pliki"</string>
     <string name="copy_remaining" msgid="6283790937387975095">"Pozostało: <xliff:g id="DURATION">%s</xliff:g>"</string>
     <plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
       <item quantity="few">Kopiowanie <xliff:g id="COUNT_1">%1$d</xliff:g> plików.</item>
@@ -125,4 +126,16 @@
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Niektóre pliki zostały przekonwertowane"</string>
     <string name="allow" msgid="7225948811296386551">"Zezwól"</string>
     <string name="deny" msgid="2081879885755434506">"Odmów"</string>
+    <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772">
+      <item quantity="few">Usunąć <xliff:g id="COUNT_1">%1$d</xliff:g> pliki?</item>
+      <item quantity="many">Usunąć <xliff:g id="COUNT_1">%1$d</xliff:g> plików?</item>
+      <item quantity="other">Usunąć <xliff:g id="COUNT_1">%1$d</xliff:g> pliku?</item>
+      <item quantity="one">Usunąć <xliff:g id="COUNT_0">%1$d</xliff:g> plik?</item>
+    </plurals>
+    <plurals name="elements_selected" formatted="false" msgid="1376955402452875047">
+      <item quantity="few">Wybrano <xliff:g id="COUNT_1">%1$d</xliff:g></item>
+      <item quantity="many">Wybrano <xliff:g id="COUNT_1">%1$d</xliff:g></item>
+      <item quantity="other">Wybrano <xliff:g id="COUNT_1">%1$d</xliff:g></item>
+      <item quantity="one">Wybrano <xliff:g id="COUNT_0">%1$d</xliff:g></item>
+    </plurals>
 </resources>
diff --git a/packages/DocumentsUI/res/values-pt-rBR/config.xml b/packages/DocumentsUI/res/values-pt-rBR/config.xml
deleted file mode 100644
index 843a8aa..0000000
--- a/packages/DocumentsUI/res/values-pt-rBR/config.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--  Copyright (C) 2015 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="trusted_quick_viewer_package" msgid="3354383993907861267"></string>
-</resources>
diff --git a/packages/DocumentsUI/res/values-pt-rBR/strings.xml b/packages/DocumentsUI/res/values-pt-rBR/strings.xml
index 391a053..213e76a 100644
--- a/packages/DocumentsUI/res/values-pt-rBR/strings.xml
+++ b/packages/DocumentsUI/res/values-pt-rBR/strings.xml
@@ -67,6 +67,7 @@
     <string name="share_via" msgid="8966594246261344259">"Compartilhar via"</string>
     <string name="copy_notification_title" msgid="6374299806748219777">"Copiando arquivos"</string>
     <string name="move_notification_title" msgid="6193835179777284805">"Movendo arquivos"</string>
+    <string name="delete_notification_title" msgid="3329403967712437496">"Excluindo arquivos"</string>
     <string name="copy_remaining" msgid="6283790937387975095">"<xliff:g id="DURATION">%s</xliff:g> restantes"</string>
     <plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
       <item quantity="one">Copiando <xliff:g id="COUNT_1">%1$d</xliff:g> arquivos.</item>
@@ -111,4 +112,12 @@
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Alguns arquivos foram convertidos"</string>
     <string name="allow" msgid="7225948811296386551">"Permitir"</string>
     <string name="deny" msgid="2081879885755434506">"Negar"</string>
+    <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772">
+      <item quantity="one">Excluir <xliff:g id="COUNT_1">%1$d</xliff:g> arquivos?</item>
+      <item quantity="other">Excluir <xliff:g id="COUNT_1">%1$d</xliff:g> arquivos?</item>
+    </plurals>
+    <plurals name="elements_selected" formatted="false" msgid="1376955402452875047">
+      <item quantity="one"><xliff:g id="COUNT_1">%1$d</xliff:g> selecionados</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> selecionados</item>
+    </plurals>
 </resources>
diff --git a/packages/DocumentsUI/res/values-pt-rPT/config.xml b/packages/DocumentsUI/res/values-pt-rPT/config.xml
deleted file mode 100644
index 843a8aa..0000000
--- a/packages/DocumentsUI/res/values-pt-rPT/config.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--  Copyright (C) 2015 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="trusted_quick_viewer_package" msgid="3354383993907861267"></string>
-</resources>
diff --git a/packages/DocumentsUI/res/values-pt-rPT/strings.xml b/packages/DocumentsUI/res/values-pt-rPT/strings.xml
index 448ddfe..2c74e67 100644
--- a/packages/DocumentsUI/res/values-pt-rPT/strings.xml
+++ b/packages/DocumentsUI/res/values-pt-rPT/strings.xml
@@ -67,6 +67,7 @@
     <string name="share_via" msgid="8966594246261344259">"Partilhar através de"</string>
     <string name="copy_notification_title" msgid="6374299806748219777">"A copiar ficheiros"</string>
     <string name="move_notification_title" msgid="6193835179777284805">"A mover ficheiros"</string>
+    <string name="delete_notification_title" msgid="3329403967712437496">"Eliminar ficheiros"</string>
     <string name="copy_remaining" msgid="6283790937387975095">"Faltam <xliff:g id="DURATION">%s</xliff:g>"</string>
     <plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
       <item quantity="other">A copiar <xliff:g id="COUNT_1">%1$d</xliff:g> ficheiros.</item>
@@ -111,4 +112,12 @@
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Alguns ficheiros foram convertidos"</string>
     <string name="allow" msgid="7225948811296386551">"Permitir"</string>
     <string name="deny" msgid="2081879885755434506">"Recusar"</string>
+    <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772">
+      <item quantity="other">Pretende eliminar <xliff:g id="COUNT_1">%1$d</xliff:g> ficheiros?</item>
+      <item quantity="one">Pretende eliminar <xliff:g id="COUNT_0">%1$d</xliff:g> ficheiro?</item>
+    </plurals>
+    <plurals name="elements_selected" formatted="false" msgid="1376955402452875047">
+      <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> selecionados</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> selecionado</item>
+    </plurals>
 </resources>
diff --git a/packages/DocumentsUI/res/values-pt/config.xml b/packages/DocumentsUI/res/values-pt/config.xml
deleted file mode 100644
index 843a8aa..0000000
--- a/packages/DocumentsUI/res/values-pt/config.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--  Copyright (C) 2015 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="trusted_quick_viewer_package" msgid="3354383993907861267"></string>
-</resources>
diff --git a/packages/DocumentsUI/res/values-pt/strings.xml b/packages/DocumentsUI/res/values-pt/strings.xml
index 391a053..213e76a 100644
--- a/packages/DocumentsUI/res/values-pt/strings.xml
+++ b/packages/DocumentsUI/res/values-pt/strings.xml
@@ -67,6 +67,7 @@
     <string name="share_via" msgid="8966594246261344259">"Compartilhar via"</string>
     <string name="copy_notification_title" msgid="6374299806748219777">"Copiando arquivos"</string>
     <string name="move_notification_title" msgid="6193835179777284805">"Movendo arquivos"</string>
+    <string name="delete_notification_title" msgid="3329403967712437496">"Excluindo arquivos"</string>
     <string name="copy_remaining" msgid="6283790937387975095">"<xliff:g id="DURATION">%s</xliff:g> restantes"</string>
     <plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
       <item quantity="one">Copiando <xliff:g id="COUNT_1">%1$d</xliff:g> arquivos.</item>
@@ -111,4 +112,12 @@
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Alguns arquivos foram convertidos"</string>
     <string name="allow" msgid="7225948811296386551">"Permitir"</string>
     <string name="deny" msgid="2081879885755434506">"Negar"</string>
+    <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772">
+      <item quantity="one">Excluir <xliff:g id="COUNT_1">%1$d</xliff:g> arquivos?</item>
+      <item quantity="other">Excluir <xliff:g id="COUNT_1">%1$d</xliff:g> arquivos?</item>
+    </plurals>
+    <plurals name="elements_selected" formatted="false" msgid="1376955402452875047">
+      <item quantity="one"><xliff:g id="COUNT_1">%1$d</xliff:g> selecionados</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> selecionados</item>
+    </plurals>
 </resources>
diff --git a/packages/DocumentsUI/res/values-ro/config.xml b/packages/DocumentsUI/res/values-ro/config.xml
deleted file mode 100644
index 843a8aa..0000000
--- a/packages/DocumentsUI/res/values-ro/config.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--  Copyright (C) 2015 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="trusted_quick_viewer_package" msgid="3354383993907861267"></string>
-</resources>
diff --git a/packages/DocumentsUI/res/values-ro/strings.xml b/packages/DocumentsUI/res/values-ro/strings.xml
index ee0e883..e57d1ab 100644
--- a/packages/DocumentsUI/res/values-ro/strings.xml
+++ b/packages/DocumentsUI/res/values-ro/strings.xml
@@ -67,6 +67,7 @@
     <string name="share_via" msgid="8966594246261344259">"Trimiteți prin"</string>
     <string name="copy_notification_title" msgid="6374299806748219777">"Se copiază fișierele"</string>
     <string name="move_notification_title" msgid="6193835179777284805">"Se mută fișierele"</string>
+    <string name="delete_notification_title" msgid="3329403967712437496">"Se șterg fișierele"</string>
     <string name="copy_remaining" msgid="6283790937387975095">"Timp rămas: <xliff:g id="DURATION">%s</xliff:g>"</string>
     <plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
       <item quantity="few">Se copiază <xliff:g id="COUNT_1">%1$d</xliff:g> fișiere.</item>
@@ -118,4 +119,14 @@
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Unele fișiere au fost convertite"</string>
     <string name="allow" msgid="7225948811296386551">"Permiteți"</string>
     <string name="deny" msgid="2081879885755434506">"Refuzați"</string>
+    <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772">
+      <item quantity="few">Ștergeți <xliff:g id="COUNT_1">%1$d</xliff:g> fișiere?</item>
+      <item quantity="other">Ștergeți <xliff:g id="COUNT_1">%1$d</xliff:g> de fișiere?</item>
+      <item quantity="one">Ștergeți <xliff:g id="COUNT_0">%1$d</xliff:g> fișier?</item>
+    </plurals>
+    <plurals name="elements_selected" formatted="false" msgid="1376955402452875047">
+      <item quantity="few"><xliff:g id="COUNT_1">%1$d</xliff:g> selectate</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> selectate</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> selectat</item>
+    </plurals>
 </resources>
diff --git a/packages/DocumentsUI/res/values-ru/config.xml b/packages/DocumentsUI/res/values-ru/config.xml
deleted file mode 100644
index 843a8aa..0000000
--- a/packages/DocumentsUI/res/values-ru/config.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--  Copyright (C) 2015 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="trusted_quick_viewer_package" msgid="3354383993907861267"></string>
-</resources>
diff --git a/packages/DocumentsUI/res/values-ru/strings.xml b/packages/DocumentsUI/res/values-ru/strings.xml
index ec97840..9c0f031 100644
--- a/packages/DocumentsUI/res/values-ru/strings.xml
+++ b/packages/DocumentsUI/res/values-ru/strings.xml
@@ -67,6 +67,7 @@
     <string name="share_via" msgid="8966594246261344259">"Поделиться"</string>
     <string name="copy_notification_title" msgid="6374299806748219777">"Копирование файлов"</string>
     <string name="move_notification_title" msgid="6193835179777284805">"Перемещение файлов"</string>
+    <string name="delete_notification_title" msgid="3329403967712437496">"Удаление файлов…"</string>
     <string name="copy_remaining" msgid="6283790937387975095">"Осталось <xliff:g id="DURATION">%s</xliff:g>"</string>
     <plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
       <item quantity="one">Копируется <xliff:g id="COUNT_1">%1$d</xliff:g> файл...</item>
@@ -125,4 +126,16 @@
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Формат некоторых файлов изменен"</string>
     <string name="allow" msgid="7225948811296386551">"Разрешить"</string>
     <string name="deny" msgid="2081879885755434506">"Отклонить"</string>
+    <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772">
+      <item quantity="one">Удалить <xliff:g id="COUNT_1">%1$d</xliff:g> файл?</item>
+      <item quantity="few">Удалить <xliff:g id="COUNT_1">%1$d</xliff:g> файла?</item>
+      <item quantity="many">Удалить <xliff:g id="COUNT_1">%1$d</xliff:g> файлов?</item>
+      <item quantity="other">Удалить <xliff:g id="COUNT_1">%1$d</xliff:g> файла?</item>
+    </plurals>
+    <plurals name="elements_selected" formatted="false" msgid="1376955402452875047">
+      <item quantity="one">Выбрано: <xliff:g id="COUNT_1">%1$d</xliff:g></item>
+      <item quantity="few">Выбрано: <xliff:g id="COUNT_1">%1$d</xliff:g></item>
+      <item quantity="many">Выбрано: <xliff:g id="COUNT_1">%1$d</xliff:g></item>
+      <item quantity="other">Выбрано: <xliff:g id="COUNT_1">%1$d</xliff:g></item>
+    </plurals>
 </resources>
diff --git a/packages/DocumentsUI/res/values-si-rLK/config.xml b/packages/DocumentsUI/res/values-si-rLK/config.xml
deleted file mode 100644
index 843a8aa..0000000
--- a/packages/DocumentsUI/res/values-si-rLK/config.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--  Copyright (C) 2015 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="trusted_quick_viewer_package" msgid="3354383993907861267"></string>
-</resources>
diff --git a/packages/DocumentsUI/res/values-si-rLK/strings.xml b/packages/DocumentsUI/res/values-si-rLK/strings.xml
index fdfabe2..a34aa88 100644
--- a/packages/DocumentsUI/res/values-si-rLK/strings.xml
+++ b/packages/DocumentsUI/res/values-si-rLK/strings.xml
@@ -67,6 +67,7 @@
     <string name="share_via" msgid="8966594246261344259">"හරහා බෙදාගන්න"</string>
     <string name="copy_notification_title" msgid="6374299806748219777">"ගොනු පිටපත් කරමින්"</string>
     <string name="move_notification_title" msgid="6193835179777284805">"ගොනු ගෙන යාම"</string>
+    <string name="delete_notification_title" msgid="3329403967712437496">"ගොනු මකමින්"</string>
     <string name="copy_remaining" msgid="6283790937387975095">"<xliff:g id="DURATION">%s</xliff:g> ඉතිරියි"</string>
     <plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
       <item quantity="one">ගොනු <xliff:g id="COUNT_1">%1$d</xliff:g> ක් පිටපත් කරමින්.</item>
@@ -111,4 +112,12 @@
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"සමහර ගොනු පරිවර්තනය කරන ලදී"</string>
     <string name="allow" msgid="7225948811296386551">"අවසර දෙන්න"</string>
     <string name="deny" msgid="2081879885755434506">"ප්‍රතික්ෂේප කරන්න"</string>
+    <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772">
+      <item quantity="one">ගොනු <xliff:g id="COUNT_1">%1$d</xliff:g>ක් මකන්නද?</item>
+      <item quantity="other">ගොනු <xliff:g id="COUNT_1">%1$d</xliff:g>ක් මකන්නද?</item>
+    </plurals>
+    <plurals name="elements_selected" formatted="false" msgid="1376955402452875047">
+      <item quantity="one"><xliff:g id="COUNT_1">%1$d</xliff:g>ක් තෝරන ලදී</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g>ක් තෝරන ලදී</item>
+    </plurals>
 </resources>
diff --git a/packages/DocumentsUI/res/values-sk/config.xml b/packages/DocumentsUI/res/values-sk/config.xml
deleted file mode 100644
index 843a8aa..0000000
--- a/packages/DocumentsUI/res/values-sk/config.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--  Copyright (C) 2015 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="trusted_quick_viewer_package" msgid="3354383993907861267"></string>
-</resources>
diff --git a/packages/DocumentsUI/res/values-sk/strings.xml b/packages/DocumentsUI/res/values-sk/strings.xml
index 4d29021..1133815 100644
--- a/packages/DocumentsUI/res/values-sk/strings.xml
+++ b/packages/DocumentsUI/res/values-sk/strings.xml
@@ -67,6 +67,7 @@
     <string name="share_via" msgid="8966594246261344259">"Zdieľať"</string>
     <string name="copy_notification_title" msgid="6374299806748219777">"Kopírovanie súborov"</string>
     <string name="move_notification_title" msgid="6193835179777284805">"Presúvajú sa súbory"</string>
+    <string name="delete_notification_title" msgid="3329403967712437496">"Odstraňujú sa súbory"</string>
     <string name="copy_remaining" msgid="6283790937387975095">"Zostáva: <xliff:g id="DURATION">%s</xliff:g>"</string>
     <plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
       <item quantity="few">Kopírujú sa <xliff:g id="COUNT_1">%1$d</xliff:g> súbory.</item>
@@ -125,4 +126,16 @@
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Niektoré súbory boli konvertované"</string>
     <string name="allow" msgid="7225948811296386551">"Povoliť"</string>
     <string name="deny" msgid="2081879885755434506">"Zamietnuť"</string>
+    <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772">
+      <item quantity="few">Odstrániť <xliff:g id="COUNT_1">%1$d</xliff:g> súbory?</item>
+      <item quantity="many">Odstrániť <xliff:g id="COUNT_1">%1$d</xliff:g> súboru?</item>
+      <item quantity="other">Odstrániť <xliff:g id="COUNT_1">%1$d</xliff:g> súborov?</item>
+      <item quantity="one">Odstrániť <xliff:g id="COUNT_0">%1$d</xliff:g> súbor?</item>
+    </plurals>
+    <plurals name="elements_selected" formatted="false" msgid="1376955402452875047">
+      <item quantity="few">Vybraté: <xliff:g id="COUNT_1">%1$d</xliff:g></item>
+      <item quantity="many">Vybraté: <xliff:g id="COUNT_1">%1$d</xliff:g></item>
+      <item quantity="other">Vybraté: <xliff:g id="COUNT_1">%1$d</xliff:g></item>
+      <item quantity="one">Vybraté: <xliff:g id="COUNT_0">%1$d</xliff:g></item>
+    </plurals>
 </resources>
diff --git a/packages/DocumentsUI/res/values-sl/config.xml b/packages/DocumentsUI/res/values-sl/config.xml
deleted file mode 100644
index 843a8aa..0000000
--- a/packages/DocumentsUI/res/values-sl/config.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--  Copyright (C) 2015 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="trusted_quick_viewer_package" msgid="3354383993907861267"></string>
-</resources>
diff --git a/packages/DocumentsUI/res/values-sl/strings.xml b/packages/DocumentsUI/res/values-sl/strings.xml
index dc17a08..f2c691d 100644
--- a/packages/DocumentsUI/res/values-sl/strings.xml
+++ b/packages/DocumentsUI/res/values-sl/strings.xml
@@ -67,6 +67,7 @@
     <string name="share_via" msgid="8966594246261344259">"Deli z drugimi prek"</string>
     <string name="copy_notification_title" msgid="6374299806748219777">"Kopiranje datotek"</string>
     <string name="move_notification_title" msgid="6193835179777284805">"Premikanje datotek"</string>
+    <string name="delete_notification_title" msgid="3329403967712437496">"Brisanje datotek"</string>
     <string name="copy_remaining" msgid="6283790937387975095">"Še <xliff:g id="DURATION">%s</xliff:g>"</string>
     <plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
       <item quantity="one">Kopiranje <xliff:g id="COUNT_1">%1$d</xliff:g> datoteke.</item>
@@ -125,4 +126,16 @@
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Nekatere datoteke so bile pretvorjene"</string>
     <string name="allow" msgid="7225948811296386551">"Dovoli"</string>
     <string name="deny" msgid="2081879885755434506">"Zavrni"</string>
+    <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772">
+      <item quantity="one">Želite izbrisati <xliff:g id="COUNT_1">%1$d</xliff:g> datoteko?</item>
+      <item quantity="two">Želite izbrisati <xliff:g id="COUNT_1">%1$d</xliff:g> datoteki?</item>
+      <item quantity="few">Želite izbrisati <xliff:g id="COUNT_1">%1$d</xliff:g> datoteke?</item>
+      <item quantity="other">Želite izbrisati <xliff:g id="COUNT_1">%1$d</xliff:g> datotek?</item>
+    </plurals>
+    <plurals name="elements_selected" formatted="false" msgid="1376955402452875047">
+      <item quantity="one"><xliff:g id="COUNT_1">%1$d</xliff:g> izbran</item>
+      <item quantity="two"><xliff:g id="COUNT_1">%1$d</xliff:g> izbrana</item>
+      <item quantity="few"><xliff:g id="COUNT_1">%1$d</xliff:g> izbrani</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> izbranih</item>
+    </plurals>
 </resources>
diff --git a/packages/DocumentsUI/res/values-sq-rAL/config.xml b/packages/DocumentsUI/res/values-sq-rAL/config.xml
deleted file mode 100644
index 843a8aa..0000000
--- a/packages/DocumentsUI/res/values-sq-rAL/config.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--  Copyright (C) 2015 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="trusted_quick_viewer_package" msgid="3354383993907861267"></string>
-</resources>
diff --git a/packages/DocumentsUI/res/values-sq-rAL/strings.xml b/packages/DocumentsUI/res/values-sq-rAL/strings.xml
index 5ae1f2a..80ae000 100644
--- a/packages/DocumentsUI/res/values-sq-rAL/strings.xml
+++ b/packages/DocumentsUI/res/values-sq-rAL/strings.xml
@@ -67,6 +67,7 @@
     <string name="share_via" msgid="8966594246261344259">"Shpërnda publikisht përmes"</string>
     <string name="copy_notification_title" msgid="6374299806748219777">"Po kopjon skedarët"</string>
     <string name="move_notification_title" msgid="6193835179777284805">"Po zhvendos skedarët"</string>
+    <string name="delete_notification_title" msgid="3329403967712437496">"Po fshin skedarët"</string>
     <string name="copy_remaining" msgid="6283790937387975095">"<xliff:g id="DURATION">%s</xliff:g> të mbetura"</string>
     <plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
       <item quantity="other">Po kopjon <xliff:g id="COUNT_1">%1$d</xliff:g> skedarë.</item>
@@ -111,4 +112,12 @@
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Disa skedarë u konvertuan"</string>
     <string name="allow" msgid="7225948811296386551">"Lejo"</string>
     <string name="deny" msgid="2081879885755434506">"Moho"</string>
+    <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772">
+      <item quantity="other">Të fshihen <xliff:g id="COUNT_1">%1$d</xliff:g> skedarë?</item>
+      <item quantity="one">Të fshihet <xliff:g id="COUNT_0">%1$d</xliff:g> skedar?</item>
+    </plurals>
+    <plurals name="elements_selected" formatted="false" msgid="1376955402452875047">
+      <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> të zgjedhur</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> i zgjedhur</item>
+    </plurals>
 </resources>
diff --git a/packages/DocumentsUI/res/values-sr/config.xml b/packages/DocumentsUI/res/values-sr/config.xml
deleted file mode 100644
index 843a8aa..0000000
--- a/packages/DocumentsUI/res/values-sr/config.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--  Copyright (C) 2015 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="trusted_quick_viewer_package" msgid="3354383993907861267"></string>
-</resources>
diff --git a/packages/DocumentsUI/res/values-sr/strings.xml b/packages/DocumentsUI/res/values-sr/strings.xml
index e207c2e..be96db6 100644
--- a/packages/DocumentsUI/res/values-sr/strings.xml
+++ b/packages/DocumentsUI/res/values-sr/strings.xml
@@ -67,6 +67,7 @@
     <string name="share_via" msgid="8966594246261344259">"Делите преко"</string>
     <string name="copy_notification_title" msgid="6374299806748219777">"Копирање датотека"</string>
     <string name="move_notification_title" msgid="6193835179777284805">"Датотеке се премештају"</string>
+    <string name="delete_notification_title" msgid="3329403967712437496">"Датотеке се бришу"</string>
     <string name="copy_remaining" msgid="6283790937387975095">"Још <xliff:g id="DURATION">%s</xliff:g>"</string>
     <plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
       <item quantity="one">Копирање <xliff:g id="COUNT_1">%1$d</xliff:g> датотеке.</item>
@@ -118,4 +119,14 @@
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Неке датотеке су конвертоване"</string>
     <string name="allow" msgid="7225948811296386551">"Дозволи"</string>
     <string name="deny" msgid="2081879885755434506">"Одбиј"</string>
+    <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772">
+      <item quantity="one">Желите ли да избришете <xliff:g id="COUNT_1">%1$d</xliff:g> датотеку?</item>
+      <item quantity="few">Желите ли да избришете <xliff:g id="COUNT_1">%1$d</xliff:g> датотеке?</item>
+      <item quantity="other">Желите ли да избришете <xliff:g id="COUNT_1">%1$d</xliff:g> датотека?</item>
+    </plurals>
+    <plurals name="elements_selected" formatted="false" msgid="1376955402452875047">
+      <item quantity="one">Изабрана је <xliff:g id="COUNT_1">%1$d</xliff:g> ставка</item>
+      <item quantity="few">Изабране су <xliff:g id="COUNT_1">%1$d</xliff:g> ставке</item>
+      <item quantity="other">Изабрано је <xliff:g id="COUNT_1">%1$d</xliff:g> ставки</item>
+    </plurals>
 </resources>
diff --git a/packages/DocumentsUI/res/values-sv/config.xml b/packages/DocumentsUI/res/values-sv/config.xml
deleted file mode 100644
index 843a8aa..0000000
--- a/packages/DocumentsUI/res/values-sv/config.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--  Copyright (C) 2015 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="trusted_quick_viewer_package" msgid="3354383993907861267"></string>
-</resources>
diff --git a/packages/DocumentsUI/res/values-sv/strings.xml b/packages/DocumentsUI/res/values-sv/strings.xml
index dfc42a3..7fd4be0 100644
--- a/packages/DocumentsUI/res/values-sv/strings.xml
+++ b/packages/DocumentsUI/res/values-sv/strings.xml
@@ -67,6 +67,7 @@
     <string name="share_via" msgid="8966594246261344259">"Dela via"</string>
     <string name="copy_notification_title" msgid="6374299806748219777">"Kopierar filer"</string>
     <string name="move_notification_title" msgid="6193835179777284805">"Filer flyttas"</string>
+    <string name="delete_notification_title" msgid="3329403967712437496">"Filerna tas bort"</string>
     <string name="copy_remaining" msgid="6283790937387975095">"<xliff:g id="DURATION">%s</xliff:g> återstår"</string>
     <plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
       <item quantity="other">Kopierar <xliff:g id="COUNT_1">%1$d</xliff:g> filer.</item>
@@ -111,4 +112,12 @@
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Vissa filer konverterades"</string>
     <string name="allow" msgid="7225948811296386551">"Tillåt"</string>
     <string name="deny" msgid="2081879885755434506">"Neka"</string>
+    <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772">
+      <item quantity="other">Radera <xliff:g id="COUNT_1">%1$d</xliff:g> filer?</item>
+      <item quantity="one">Radera <xliff:g id="COUNT_0">%1$d</xliff:g> fil?</item>
+    </plurals>
+    <plurals name="elements_selected" formatted="false" msgid="1376955402452875047">
+      <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> har valts</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> har valts</item>
+    </plurals>
 </resources>
diff --git a/packages/DocumentsUI/res/values-sw/config.xml b/packages/DocumentsUI/res/values-sw/config.xml
deleted file mode 100644
index 843a8aa..0000000
--- a/packages/DocumentsUI/res/values-sw/config.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--  Copyright (C) 2015 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="trusted_quick_viewer_package" msgid="3354383993907861267"></string>
-</resources>
diff --git a/packages/DocumentsUI/res/values-sw/strings.xml b/packages/DocumentsUI/res/values-sw/strings.xml
index cbdb44c..2730ce9 100644
--- a/packages/DocumentsUI/res/values-sw/strings.xml
+++ b/packages/DocumentsUI/res/values-sw/strings.xml
@@ -67,6 +67,7 @@
     <string name="share_via" msgid="8966594246261344259">"Shiriki kupitia"</string>
     <string name="copy_notification_title" msgid="6374299806748219777">"Inanakili faili"</string>
     <string name="move_notification_title" msgid="6193835179777284805">"Inahamisha faili"</string>
+    <string name="delete_notification_title" msgid="3329403967712437496">"Inafuta faili"</string>
     <string name="copy_remaining" msgid="6283790937387975095">"Zimesalia <xliff:g id="DURATION">%s</xliff:g>"</string>
     <plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
       <item quantity="other">Inanakili faili <xliff:g id="COUNT_1">%1$d</xliff:g>.</item>
@@ -111,4 +112,12 @@
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Baadhi ya faili zimebadilishwa muundo"</string>
     <string name="allow" msgid="7225948811296386551">"Ruhusu"</string>
     <string name="deny" msgid="2081879885755434506">"Kataza"</string>
+    <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772">
+      <item quantity="other">Ungependa kufuta faili <xliff:g id="COUNT_1">%1$d</xliff:g>?</item>
+      <item quantity="one">Ungependa kufuta faili <xliff:g id="COUNT_0">%1$d</xliff:g>?</item>
+    </plurals>
+    <plurals name="elements_selected" formatted="false" msgid="1376955402452875047">
+      <item quantity="other">Imechagua <xliff:g id="COUNT_1">%1$d</xliff:g></item>
+      <item quantity="one">Imechagua <xliff:g id="COUNT_0">%1$d</xliff:g></item>
+    </plurals>
 </resources>
diff --git a/packages/DocumentsUI/res/values-sw720dp-land/config.xml b/packages/DocumentsUI/res/values-sw720dp-land/config.xml
index 8d9526d..6893d7a 100644
--- a/packages/DocumentsUI/res/values-sw720dp-land/config.xml
+++ b/packages/DocumentsUI/res/values-sw720dp-land/config.xml
@@ -15,5 +15,4 @@
 -->
 
 <resources>
-    <bool name="always_show_summary">true</bool>
 </resources>
diff --git a/packages/DocumentsUI/res/values-sw720dp-land/dimens.xml b/packages/DocumentsUI/res/values-sw720dp-land/dimens.xml
index fa11244..1b67ee5 100644
--- a/packages/DocumentsUI/res/values-sw720dp-land/dimens.xml
+++ b/packages/DocumentsUI/res/values-sw720dp-land/dimens.xml
@@ -20,4 +20,5 @@
 
     <dimen name="list_divider_inset">80dp</dimen>
 
+    <dimen name="max_drawer_width">320dp</dimen>
 </resources>
diff --git a/packages/DocumentsUI/res/values-sw720dp/dimens.xml b/packages/DocumentsUI/res/values-sw720dp/dimens.xml
index 2488fa2..982b204 100644
--- a/packages/DocumentsUI/res/values-sw720dp/dimens.xml
+++ b/packages/DocumentsUI/res/values-sw720dp/dimens.xml
@@ -18,4 +18,7 @@
     <dimen name="grid_padding_horiz">16dp</dimen>
     <dimen name="grid_padding_vert">16dp</dimen>
 
+    <dimen name="list_item_padding">24dp</dimen>
+
+    <dimen name="max_drawer_width">320dp</dimen>
 </resources>
diff --git a/packages/DocumentsUI/res/values-ta-rIN/config.xml b/packages/DocumentsUI/res/values-ta-rIN/config.xml
deleted file mode 100644
index 843a8aa..0000000
--- a/packages/DocumentsUI/res/values-ta-rIN/config.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--  Copyright (C) 2015 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="trusted_quick_viewer_package" msgid="3354383993907861267"></string>
-</resources>
diff --git a/packages/DocumentsUI/res/values-ta-rIN/strings.xml b/packages/DocumentsUI/res/values-ta-rIN/strings.xml
index 3f85a17..881e05a 100644
--- a/packages/DocumentsUI/res/values-ta-rIN/strings.xml
+++ b/packages/DocumentsUI/res/values-ta-rIN/strings.xml
@@ -67,6 +67,7 @@
     <string name="share_via" msgid="8966594246261344259">"இதன் வழியாகப் பகிர்"</string>
     <string name="copy_notification_title" msgid="6374299806748219777">"கோப்புகளை நகலெடுத்தல்"</string>
     <string name="move_notification_title" msgid="6193835179777284805">"கோப்புகளை நகர்த்துதல்"</string>
+    <string name="delete_notification_title" msgid="3329403967712437496">"கோப்புகளை நீக்குகிறது"</string>
     <string name="copy_remaining" msgid="6283790937387975095">"<xliff:g id="DURATION">%s</xliff:g> மீதமுள்ளது"</string>
     <plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
       <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> கோப்புகளை நகலெடுக்கிறது.</item>
@@ -111,4 +112,12 @@
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"சில கோப்புகள் மாற்றப்பட்டன"</string>
     <string name="allow" msgid="7225948811296386551">"அனுமதி"</string>
     <string name="deny" msgid="2081879885755434506">"நிராகரி"</string>
+    <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772">
+      <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> கோப்புகளை நீக்கவா?</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> கோப்பை நீக்கவா?</item>
+    </plurals>
+    <plurals name="elements_selected" formatted="false" msgid="1376955402452875047">
+      <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> தேர்ந்தெடுக்கப்பட்டன</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> தேர்ந்தெடுக்கப்பட்டது</item>
+    </plurals>
 </resources>
diff --git a/packages/DocumentsUI/res/values-te-rIN/config.xml b/packages/DocumentsUI/res/values-te-rIN/config.xml
deleted file mode 100644
index 843a8aa..0000000
--- a/packages/DocumentsUI/res/values-te-rIN/config.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--  Copyright (C) 2015 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="trusted_quick_viewer_package" msgid="3354383993907861267"></string>
-</resources>
diff --git a/packages/DocumentsUI/res/values-te-rIN/strings.xml b/packages/DocumentsUI/res/values-te-rIN/strings.xml
index 07a7e6d..0043ddc 100644
--- a/packages/DocumentsUI/res/values-te-rIN/strings.xml
+++ b/packages/DocumentsUI/res/values-te-rIN/strings.xml
@@ -67,6 +67,7 @@
     <string name="share_via" msgid="8966594246261344259">"దీని ద్వారా భాగస్వామ్యం చేయండి"</string>
     <string name="copy_notification_title" msgid="6374299806748219777">"ఫైల్‌లు కాపీ అవుతున్నాయి"</string>
     <string name="move_notification_title" msgid="6193835179777284805">"ఫైల్‌లను తరలిస్తోంది"</string>
+    <string name="delete_notification_title" msgid="3329403967712437496">"ఫైల్‌లను తొలగిస్తోంది"</string>
     <string name="copy_remaining" msgid="6283790937387975095">"<xliff:g id="DURATION">%s</xliff:g> మిగిలి ఉంది"</string>
     <plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
       <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> ఫైల్‌లను కాపీ చేస్తోంది.</item>
@@ -111,4 +112,12 @@
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"కొన్ని పైల్‌లు మార్చబడ్డాయి"</string>
     <string name="allow" msgid="7225948811296386551">"అనుమతించండి"</string>
     <string name="deny" msgid="2081879885755434506">"తిరస్కరించండి"</string>
+    <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772">
+      <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> ఫైల్‌లను తొలగించాలా?</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> ఫైల్‌ను తొలగించాలా?</item>
+    </plurals>
+    <plurals name="elements_selected" formatted="false" msgid="1376955402452875047">
+      <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> ఎంచుకోబడ్డాయి</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> ఎంచుకోబడింది</item>
+    </plurals>
 </resources>
diff --git a/packages/DocumentsUI/res/values-th/config.xml b/packages/DocumentsUI/res/values-th/config.xml
deleted file mode 100644
index 843a8aa..0000000
--- a/packages/DocumentsUI/res/values-th/config.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--  Copyright (C) 2015 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="trusted_quick_viewer_package" msgid="3354383993907861267"></string>
-</resources>
diff --git a/packages/DocumentsUI/res/values-th/strings.xml b/packages/DocumentsUI/res/values-th/strings.xml
index 8562ef65..8b24210 100644
--- a/packages/DocumentsUI/res/values-th/strings.xml
+++ b/packages/DocumentsUI/res/values-th/strings.xml
@@ -67,6 +67,7 @@
     <string name="share_via" msgid="8966594246261344259">"แชร์ผ่าน"</string>
     <string name="copy_notification_title" msgid="6374299806748219777">"กำลังคัดลอกไฟล์"</string>
     <string name="move_notification_title" msgid="6193835179777284805">"กำลังย้ายไฟล์"</string>
+    <string name="delete_notification_title" msgid="3329403967712437496">"กำลังลบไฟล์"</string>
     <string name="copy_remaining" msgid="6283790937387975095">"เหลือ <xliff:g id="DURATION">%s</xliff:g>"</string>
     <plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
       <item quantity="other">กำลังคัดลอก <xliff:g id="COUNT_1">%1$d</xliff:g> ไฟล์</item>
@@ -111,4 +112,12 @@
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"แปลงบางไฟล์แล้ว"</string>
     <string name="allow" msgid="7225948811296386551">"อนุญาต"</string>
     <string name="deny" msgid="2081879885755434506">"ปฏิเสธ"</string>
+    <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772">
+      <item quantity="other">ลบ <xliff:g id="COUNT_1">%1$d</xliff:g> ไฟล์ใช่ไหม</item>
+      <item quantity="one">ลบ <xliff:g id="COUNT_0">%1$d</xliff:g> ไฟล์ใช่ไหม</item>
+    </plurals>
+    <plurals name="elements_selected" formatted="false" msgid="1376955402452875047">
+      <item quantity="other">เลือกไว้ <xliff:g id="COUNT_1">%1$d</xliff:g> รายการ</item>
+      <item quantity="one">เลือกไว้ <xliff:g id="COUNT_0">%1$d</xliff:g> รายการ</item>
+    </plurals>
 </resources>
diff --git a/packages/DocumentsUI/res/values-tl/config.xml b/packages/DocumentsUI/res/values-tl/config.xml
deleted file mode 100644
index 843a8aa..0000000
--- a/packages/DocumentsUI/res/values-tl/config.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--  Copyright (C) 2015 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="trusted_quick_viewer_package" msgid="3354383993907861267"></string>
-</resources>
diff --git a/packages/DocumentsUI/res/values-tl/strings.xml b/packages/DocumentsUI/res/values-tl/strings.xml
index de0c9bd..9849b85 100644
--- a/packages/DocumentsUI/res/values-tl/strings.xml
+++ b/packages/DocumentsUI/res/values-tl/strings.xml
@@ -67,6 +67,7 @@
     <string name="share_via" msgid="8966594246261344259">"Ibahagi sa pamamagitan ng"</string>
     <string name="copy_notification_title" msgid="6374299806748219777">"Kinokopya ang mga file"</string>
     <string name="move_notification_title" msgid="6193835179777284805">"Inililipat ang mga file"</string>
+    <string name="delete_notification_title" msgid="3329403967712437496">"Pagde-delete ng mga file"</string>
     <string name="copy_remaining" msgid="6283790937387975095">"<xliff:g id="DURATION">%s</xliff:g> na lang ang natitira"</string>
     <plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
       <item quantity="one">Kumokopya ng <xliff:g id="COUNT_1">%1$d</xliff:g> file.</item>
@@ -111,4 +112,12 @@
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Na-convert ang ilang file"</string>
     <string name="allow" msgid="7225948811296386551">"Payagan"</string>
     <string name="deny" msgid="2081879885755434506">"Tanggihan"</string>
+    <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772">
+      <item quantity="one">Gusto mo bang i-delete ang <xliff:g id="COUNT_1">%1$d</xliff:g> file?</item>
+      <item quantity="other">Gusto mo bang i-delete ang <xliff:g id="COUNT_1">%1$d</xliff:g> na file?</item>
+    </plurals>
+    <plurals name="elements_selected" formatted="false" msgid="1376955402452875047">
+      <item quantity="one"><xliff:g id="COUNT_1">%1$d</xliff:g> ang napili</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> ang napili</item>
+    </plurals>
 </resources>
diff --git a/packages/DocumentsUI/res/values-tr/config.xml b/packages/DocumentsUI/res/values-tr/config.xml
deleted file mode 100644
index 843a8aa..0000000
--- a/packages/DocumentsUI/res/values-tr/config.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--  Copyright (C) 2015 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="trusted_quick_viewer_package" msgid="3354383993907861267"></string>
-</resources>
diff --git a/packages/DocumentsUI/res/values-tr/strings.xml b/packages/DocumentsUI/res/values-tr/strings.xml
index c9245c6..8df52d2 100644
--- a/packages/DocumentsUI/res/values-tr/strings.xml
+++ b/packages/DocumentsUI/res/values-tr/strings.xml
@@ -67,6 +67,7 @@
     <string name="share_via" msgid="8966594246261344259">"Şunu kullanarak paylaş:"</string>
     <string name="copy_notification_title" msgid="6374299806748219777">"Dosyalar kopyalanıyor"</string>
     <string name="move_notification_title" msgid="6193835179777284805">"Dosyalar taşınıyor"</string>
+    <string name="delete_notification_title" msgid="3329403967712437496">"Dosyalar siliniyor"</string>
     <string name="copy_remaining" msgid="6283790937387975095">"<xliff:g id="DURATION">%s</xliff:g> kaldı"</string>
     <plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
       <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> dosya kopyalanıyor.</item>
@@ -111,4 +112,12 @@
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Bazı dosyalar dönüştürüldü"</string>
     <string name="allow" msgid="7225948811296386551">"İzin Ver"</string>
     <string name="deny" msgid="2081879885755434506">"Reddet"</string>
+    <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772">
+      <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> dosya silinsin mi?</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> dosya silinsin mi?</item>
+    </plurals>
+    <plurals name="elements_selected" formatted="false" msgid="1376955402452875047">
+      <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> öğe seçildi</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> öğe seçildi</item>
+    </plurals>
 </resources>
diff --git a/packages/DocumentsUI/res/values-uk/config.xml b/packages/DocumentsUI/res/values-uk/config.xml
deleted file mode 100644
index 843a8aa..0000000
--- a/packages/DocumentsUI/res/values-uk/config.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--  Copyright (C) 2015 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="trusted_quick_viewer_package" msgid="3354383993907861267"></string>
-</resources>
diff --git a/packages/DocumentsUI/res/values-uk/strings.xml b/packages/DocumentsUI/res/values-uk/strings.xml
index 5f2b99c..d5a1fcd 100644
--- a/packages/DocumentsUI/res/values-uk/strings.xml
+++ b/packages/DocumentsUI/res/values-uk/strings.xml
@@ -67,6 +67,7 @@
     <string name="share_via" msgid="8966594246261344259">"Надіслати через"</string>
     <string name="copy_notification_title" msgid="6374299806748219777">"Копіювання файлів"</string>
     <string name="move_notification_title" msgid="6193835179777284805">"Переміщення файлів"</string>
+    <string name="delete_notification_title" msgid="3329403967712437496">"Видалення файлів"</string>
     <string name="copy_remaining" msgid="6283790937387975095">"Залишилося <xliff:g id="DURATION">%s</xliff:g>"</string>
     <plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
       <item quantity="one">Копіювання <xliff:g id="COUNT_1">%1$d</xliff:g> файлу.</item>
@@ -125,4 +126,16 @@
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Деякі файли конвертовано"</string>
     <string name="allow" msgid="7225948811296386551">"Дозвол."</string>
     <string name="deny" msgid="2081879885755434506">"Забор."</string>
+    <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772">
+      <item quantity="one">Видалити <xliff:g id="COUNT_1">%1$d</xliff:g> файл?</item>
+      <item quantity="few">Видалити <xliff:g id="COUNT_1">%1$d</xliff:g> файли?</item>
+      <item quantity="many">Видалити <xliff:g id="COUNT_1">%1$d</xliff:g> файлів?</item>
+      <item quantity="other">Видалити <xliff:g id="COUNT_1">%1$d</xliff:g> файлу?</item>
+    </plurals>
+    <plurals name="elements_selected" formatted="false" msgid="1376955402452875047">
+      <item quantity="one">Вибрано <xliff:g id="COUNT_1">%1$d</xliff:g></item>
+      <item quantity="few">Вибрано <xliff:g id="COUNT_1">%1$d</xliff:g></item>
+      <item quantity="many">Вибрано <xliff:g id="COUNT_1">%1$d</xliff:g></item>
+      <item quantity="other">Вибрано <xliff:g id="COUNT_1">%1$d</xliff:g></item>
+    </plurals>
 </resources>
diff --git a/packages/DocumentsUI/res/values-ur-rPK/config.xml b/packages/DocumentsUI/res/values-ur-rPK/config.xml
deleted file mode 100644
index 843a8aa..0000000
--- a/packages/DocumentsUI/res/values-ur-rPK/config.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--  Copyright (C) 2015 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="trusted_quick_viewer_package" msgid="3354383993907861267"></string>
-</resources>
diff --git a/packages/DocumentsUI/res/values-ur-rPK/strings.xml b/packages/DocumentsUI/res/values-ur-rPK/strings.xml
index 40831eb..846555a 100644
--- a/packages/DocumentsUI/res/values-ur-rPK/strings.xml
+++ b/packages/DocumentsUI/res/values-ur-rPK/strings.xml
@@ -67,6 +67,7 @@
     <string name="share_via" msgid="8966594246261344259">"اشتراک کریں بذریعہ"</string>
     <string name="copy_notification_title" msgid="6374299806748219777">"فائلیں کاپی ہو رہی ہیں"</string>
     <string name="move_notification_title" msgid="6193835179777284805">"فائلیں منتقل ہو رہی ہیں"</string>
+    <string name="delete_notification_title" msgid="3329403967712437496">"فائلیں حذف کی جا رہی ہیں"</string>
     <string name="copy_remaining" msgid="6283790937387975095">"<xliff:g id="DURATION">%s</xliff:g> باقی ہے"</string>
     <plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
       <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> فائلیں کاپی کی جا رہی ہیں۔</item>
@@ -111,4 +112,12 @@
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"کچھ فائلوں کو تبدیل کیا گیا تھا"</string>
     <string name="allow" msgid="7225948811296386551">"اجازت دیں"</string>
     <string name="deny" msgid="2081879885755434506">"مسترد کریں"</string>
+    <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772">
+      <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> فائلیں حذف کریں؟</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> فائل حذف کریں؟</item>
+    </plurals>
+    <plurals name="elements_selected" formatted="false" msgid="1376955402452875047">
+      <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> منتخب کردہ</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> منتخب کردہ</item>
+    </plurals>
 </resources>
diff --git a/packages/DocumentsUI/res/values-uz-rUZ/config.xml b/packages/DocumentsUI/res/values-uz-rUZ/config.xml
deleted file mode 100644
index 843a8aa..0000000
--- a/packages/DocumentsUI/res/values-uz-rUZ/config.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--  Copyright (C) 2015 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="trusted_quick_viewer_package" msgid="3354383993907861267"></string>
-</resources>
diff --git a/packages/DocumentsUI/res/values-uz-rUZ/strings.xml b/packages/DocumentsUI/res/values-uz-rUZ/strings.xml
index 48fa9a6..0e1ac5a 100644
--- a/packages/DocumentsUI/res/values-uz-rUZ/strings.xml
+++ b/packages/DocumentsUI/res/values-uz-rUZ/strings.xml
@@ -67,6 +67,7 @@
     <string name="share_via" msgid="8966594246261344259">"Quyidagi orqali ulashish"</string>
     <string name="copy_notification_title" msgid="6374299806748219777">"Fayllar nusxalanmoqda"</string>
     <string name="move_notification_title" msgid="6193835179777284805">"Ko‘chirib o‘tkazilmoqda"</string>
+    <string name="delete_notification_title" msgid="3329403967712437496">"Fayllar o‘chirilmoqda"</string>
     <string name="copy_remaining" msgid="6283790937387975095">"<xliff:g id="DURATION">%s</xliff:g> qoldi"</string>
     <plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
       <item quantity="other"> <xliff:g id="COUNT_1">%1$d</xliff:g> ta fayl nusxalanmoqda</item>
@@ -111,4 +112,12 @@
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Bir nechta fayllar o‘girildi"</string>
     <string name="allow" msgid="7225948811296386551">"Ruxsat berish"</string>
     <string name="deny" msgid="2081879885755434506">"Rad qilish"</string>
+    <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772">
+      <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> ta fayl o‘chirilsinmi?</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> ta fayl o‘chirilsinmi?</item>
+    </plurals>
+    <plurals name="elements_selected" formatted="false" msgid="1376955402452875047">
+      <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> ta tanlandi</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> ta tanlandi</item>
+    </plurals>
 </resources>
diff --git a/packages/DocumentsUI/res/values-vi/config.xml b/packages/DocumentsUI/res/values-vi/config.xml
deleted file mode 100644
index 843a8aa..0000000
--- a/packages/DocumentsUI/res/values-vi/config.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--  Copyright (C) 2015 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="trusted_quick_viewer_package" msgid="3354383993907861267"></string>
-</resources>
diff --git a/packages/DocumentsUI/res/values-vi/strings.xml b/packages/DocumentsUI/res/values-vi/strings.xml
index 66a5b73..c3c16f4 100644
--- a/packages/DocumentsUI/res/values-vi/strings.xml
+++ b/packages/DocumentsUI/res/values-vi/strings.xml
@@ -67,6 +67,7 @@
     <string name="share_via" msgid="8966594246261344259">"Chia sẻ qua"</string>
     <string name="copy_notification_title" msgid="6374299806748219777">"Đang sao chép tệp"</string>
     <string name="move_notification_title" msgid="6193835179777284805">"Đang di chuyển tệp"</string>
+    <string name="delete_notification_title" msgid="3329403967712437496">"Đang xóa tệp"</string>
     <string name="copy_remaining" msgid="6283790937387975095">"Còn <xliff:g id="DURATION">%s</xliff:g>"</string>
     <plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
       <item quantity="other">Đang sao chép <xliff:g id="COUNT_1">%1$d</xliff:g> tệp.</item>
@@ -111,4 +112,12 @@
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Đã chuyển đổi một số tệp"</string>
     <string name="allow" msgid="7225948811296386551">"Cho phép"</string>
     <string name="deny" msgid="2081879885755434506">"Từ chối"</string>
+    <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772">
+      <item quantity="other">Xóa <xliff:g id="COUNT_1">%1$d</xliff:g> tệp?</item>
+      <item quantity="one">Xóa <xliff:g id="COUNT_0">%1$d</xliff:g> tệp?</item>
+    </plurals>
+    <plurals name="elements_selected" formatted="false" msgid="1376955402452875047">
+      <item quantity="other">Đã chọn <xliff:g id="COUNT_1">%1$d</xliff:g></item>
+      <item quantity="one">Đã chọn <xliff:g id="COUNT_0">%1$d</xliff:g></item>
+    </plurals>
 </resources>
diff --git a/packages/DocumentsUI/res/values-zh-rCN/config.xml b/packages/DocumentsUI/res/values-zh-rCN/config.xml
deleted file mode 100644
index 843a8aa..0000000
--- a/packages/DocumentsUI/res/values-zh-rCN/config.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--  Copyright (C) 2015 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="trusted_quick_viewer_package" msgid="3354383993907861267"></string>
-</resources>
diff --git a/packages/DocumentsUI/res/values-zh-rCN/strings.xml b/packages/DocumentsUI/res/values-zh-rCN/strings.xml
index bb48b0c..7f479ff 100644
--- a/packages/DocumentsUI/res/values-zh-rCN/strings.xml
+++ b/packages/DocumentsUI/res/values-zh-rCN/strings.xml
@@ -67,6 +67,7 @@
     <string name="share_via" msgid="8966594246261344259">"分享方式"</string>
     <string name="copy_notification_title" msgid="6374299806748219777">"正在复制文件"</string>
     <string name="move_notification_title" msgid="6193835179777284805">"正在移动文件"</string>
+    <string name="delete_notification_title" msgid="3329403967712437496">"正在删除文件"</string>
     <string name="copy_remaining" msgid="6283790937387975095">"剩余时间:<xliff:g id="DURATION">%s</xliff:g>"</string>
     <plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
       <item quantity="other">正在复制 <xliff:g id="COUNT_1">%1$d</xliff:g> 个文件。</item>
@@ -111,4 +112,12 @@
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"部分文件已转换成其他格式"</string>
     <string name="allow" msgid="7225948811296386551">"允许"</string>
     <string name="deny" msgid="2081879885755434506">"拒绝"</string>
+    <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772">
+      <item quantity="other">删除 <xliff:g id="COUNT_1">%1$d</xliff:g> 个文件?</item>
+      <item quantity="one">删除 <xliff:g id="COUNT_0">%1$d</xliff:g> 个文件?</item>
+    </plurals>
+    <plurals name="elements_selected" formatted="false" msgid="1376955402452875047">
+      <item quantity="other">已选择 <xliff:g id="COUNT_1">%1$d</xliff:g> 项</item>
+      <item quantity="one">已选择 <xliff:g id="COUNT_0">%1$d</xliff:g> 项</item>
+    </plurals>
 </resources>
diff --git a/packages/DocumentsUI/res/values-zh-rHK/config.xml b/packages/DocumentsUI/res/values-zh-rHK/config.xml
deleted file mode 100644
index 843a8aa..0000000
--- a/packages/DocumentsUI/res/values-zh-rHK/config.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--  Copyright (C) 2015 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="trusted_quick_viewer_package" msgid="3354383993907861267"></string>
-</resources>
diff --git a/packages/DocumentsUI/res/values-zh-rHK/strings.xml b/packages/DocumentsUI/res/values-zh-rHK/strings.xml
index f8d46d5..f22e27e 100644
--- a/packages/DocumentsUI/res/values-zh-rHK/strings.xml
+++ b/packages/DocumentsUI/res/values-zh-rHK/strings.xml
@@ -67,6 +67,7 @@
     <string name="share_via" msgid="8966594246261344259">"分享方式:"</string>
     <string name="copy_notification_title" msgid="6374299806748219777">"正在複製檔案"</string>
     <string name="move_notification_title" msgid="6193835179777284805">"正在移動檔案"</string>
+    <string name="delete_notification_title" msgid="3329403967712437496">"正在刪除檔案"</string>
     <string name="copy_remaining" msgid="6283790937387975095">"剩餘 <xliff:g id="DURATION">%s</xliff:g>"</string>
     <plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
       <item quantity="other">正在複製 <xliff:g id="COUNT_1">%1$d</xliff:g> 個檔案。</item>
@@ -111,4 +112,12 @@
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"部分檔案已轉換成其他格式"</string>
     <string name="allow" msgid="7225948811296386551">"允許"</string>
     <string name="deny" msgid="2081879885755434506">"拒絕"</string>
+    <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772">
+      <item quantity="other">要刪除 <xliff:g id="COUNT_1">%1$d</xliff:g> 個檔案嗎?</item>
+      <item quantity="one">要刪除 <xliff:g id="COUNT_0">%1$d</xliff:g> 個檔案嗎?</item>
+    </plurals>
+    <plurals name="elements_selected" formatted="false" msgid="1376955402452875047">
+      <item quantity="other">已選取 <xliff:g id="COUNT_1">%1$d</xliff:g> 個項目</item>
+      <item quantity="one">已選取 <xliff:g id="COUNT_0">%1$d</xliff:g> 個項目</item>
+    </plurals>
 </resources>
diff --git a/packages/DocumentsUI/res/values-zh-rTW/config.xml b/packages/DocumentsUI/res/values-zh-rTW/config.xml
deleted file mode 100644
index 843a8aa..0000000
--- a/packages/DocumentsUI/res/values-zh-rTW/config.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--  Copyright (C) 2015 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="trusted_quick_viewer_package" msgid="3354383993907861267"></string>
-</resources>
diff --git a/packages/DocumentsUI/res/values-zh-rTW/strings.xml b/packages/DocumentsUI/res/values-zh-rTW/strings.xml
index ad77ad4..a5ede47 100644
--- a/packages/DocumentsUI/res/values-zh-rTW/strings.xml
+++ b/packages/DocumentsUI/res/values-zh-rTW/strings.xml
@@ -67,6 +67,7 @@
     <string name="share_via" msgid="8966594246261344259">"分享方式:"</string>
     <string name="copy_notification_title" msgid="6374299806748219777">"複製檔案"</string>
     <string name="move_notification_title" msgid="6193835179777284805">"正在移動檔案"</string>
+    <string name="delete_notification_title" msgid="3329403967712437496">"正在刪除檔案"</string>
     <string name="copy_remaining" msgid="6283790937387975095">"剩餘 <xliff:g id="DURATION">%s</xliff:g>"</string>
     <plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
       <item quantity="other">正在複製 <xliff:g id="COUNT_1">%1$d</xliff:g> 個檔案。</item>
@@ -111,4 +112,12 @@
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"部分檔案已轉換成其他格式"</string>
     <string name="allow" msgid="7225948811296386551">"允許"</string>
     <string name="deny" msgid="2081879885755434506">"拒絕"</string>
+    <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772">
+      <item quantity="other">要刪除 <xliff:g id="COUNT_1">%1$d</xliff:g> 個檔案嗎?</item>
+      <item quantity="one">要刪除 <xliff:g id="COUNT_0">%1$d</xliff:g> 個檔案嗎?</item>
+    </plurals>
+    <plurals name="elements_selected" formatted="false" msgid="1376955402452875047">
+      <item quantity="other">已選取 <xliff:g id="COUNT_1">%1$d</xliff:g> 個項目</item>
+      <item quantity="one">已選取 <xliff:g id="COUNT_0">%1$d</xliff:g> 個項目</item>
+    </plurals>
 </resources>
diff --git a/packages/DocumentsUI/res/values-zu/config.xml b/packages/DocumentsUI/res/values-zu/config.xml
deleted file mode 100644
index 843a8aa..0000000
--- a/packages/DocumentsUI/res/values-zu/config.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--  Copyright (C) 2015 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="trusted_quick_viewer_package" msgid="3354383993907861267"></string>
-</resources>
diff --git a/packages/DocumentsUI/res/values-zu/strings.xml b/packages/DocumentsUI/res/values-zu/strings.xml
index c49500c..b99ab8c 100644
--- a/packages/DocumentsUI/res/values-zu/strings.xml
+++ b/packages/DocumentsUI/res/values-zu/strings.xml
@@ -67,6 +67,7 @@
     <string name="share_via" msgid="8966594246261344259">"Yabelana nge-"</string>
     <string name="copy_notification_title" msgid="6374299806748219777">"Ikopisha amafayela"</string>
     <string name="move_notification_title" msgid="6193835179777284805">"Ihambisa amafayela"</string>
+    <string name="delete_notification_title" msgid="3329403967712437496">"Ukususa amafayela"</string>
     <string name="copy_remaining" msgid="6283790937387975095">"<xliff:g id="DURATION">%s</xliff:g> okusele"</string>
     <plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
       <item quantity="one">Ikopisha amafayela angu-<xliff:g id="COUNT_1">%1$d</xliff:g>.</item>
@@ -111,4 +112,12 @@
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Amanye amafayela aguqulelwe"</string>
     <string name="allow" msgid="7225948811296386551">"Vumela"</string>
     <string name="deny" msgid="2081879885755434506">"Yala"</string>
+    <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772">
+      <item quantity="one">Sula amafayela angu-<xliff:g id="COUNT_1">%1$d</xliff:g>?</item>
+      <item quantity="other">Sula amafayela angu-<xliff:g id="COUNT_1">%1$d</xliff:g>?</item>
+    </plurals>
+    <plurals name="elements_selected" formatted="false" msgid="1376955402452875047">
+      <item quantity="one"><xliff:g id="COUNT_1">%1$d</xliff:g> okukhethiwe</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> okukhethiwe</item>
+    </plurals>
 </resources>
diff --git a/packages/DocumentsUI/res/values/colors.xml b/packages/DocumentsUI/res/values/colors.xml
index 3785adf..04b7fee 100644
--- a/packages/DocumentsUI/res/values/colors.xml
+++ b/packages/DocumentsUI/res/values/colors.xml
@@ -23,8 +23,6 @@
     <color name="window_background">#fff1f1f1</color>
     <color name="drawer_background">#fff1f1f1</color>
     <color name="directory_background">#fff7f7f7</color>
-    <color name="item_doc_background">#fffafafa</color>
-    <color name="item_doc_background_selected">#ffe0f2f1</color>
     <color name="menu_search_background">#ff676f74</color>
 
     <color name="primary_dark">@*android:color/primary_dark_material_dark</color>
@@ -35,4 +33,11 @@
 
     <color name="band_select_background">#88ffffff</color>
     <color name="band_select_border">#44000000</color>
+
+    <color name="item_doc_background_disabled">#fff4f4f4</color>
+
+    <!-- TODO: Would be nice to move this to a color-set, but not sure how to support animation -->
+    <color name="item_doc_background">#fffafafa</color>
+    <color name="item_doc_background_selected">#ffe0f2f1</color>
+
 </resources>
diff --git a/packages/DocumentsUI/res/values/config.xml b/packages/DocumentsUI/res/values/config.xml
index 07498a0..86087c3 100644
--- a/packages/DocumentsUI/res/values/config.xml
+++ b/packages/DocumentsUI/res/values/config.xml
@@ -19,7 +19,6 @@
     <bool name="config_defaultAdvancedDevices">false</bool>
 
     <!-- Intentionally unset. Vendors should set this in an overlay. -->
-    <string name="trusted_quick_viewer_package"></string>
+    <string name="trusted_quick_viewer_package" translatable="false"></string>
     <bool name="list_divider_inset_left">true</bool>
-    <bool name="always_show_summary">false</bool>
 </resources>
diff --git a/packages/DocumentsUI/res/values/dimens.xml b/packages/DocumentsUI/res/values/dimens.xml
index 9fc8a73..5af7da3 100644
--- a/packages/DocumentsUI/res/values/dimens.xml
+++ b/packages/DocumentsUI/res/values/dimens.xml
@@ -37,4 +37,5 @@
     <dimen name="dir_elevation">8dp</dimen>
     <dimen name="drag_shadow_size">120dp</dimen>
     <dimen name="grid_item_elevation">2dp</dimen>
+    <dimen name="max_drawer_width">280dp</dimen>
 </resources>
diff --git a/packages/DocumentsUI/res/values/strings.xml b/packages/DocumentsUI/res/values/strings.xml
index b97918e..e2d1870 100644
--- a/packages/DocumentsUI/res/values/strings.xml
+++ b/packages/DocumentsUI/res/values/strings.xml
@@ -134,6 +134,8 @@
     <string name="copy_notification_title">Copying files</string>
     <!-- Title of the move notification [CHAR LIMIT=24] -->
     <string name="move_notification_title">Moving files</string>
+    <!-- Title of the move notification [CHAR LIMIT=24] -->
+    <string name="delete_notification_title">Deleting files</string>
     <!-- Text shown on the copy notification to indicate remaining time, in minutes [CHAR LIMIT=24] -->
     <string name="copy_remaining"><xliff:g id="duration" example="3 minutes">%s</xliff:g> left</string>
     <!-- Toast shown when a file copy is kicked off -->
@@ -206,4 +208,14 @@
     <string name="allow">Allow</string>
     <!-- Text in the button asking user to deny access to a given directory. -->
     <string name="deny">Deny</string>
+    <!-- Dialog text shown to users when asking if they want to delete files (a confirmation). -->
+    <plurals name="delete_confirmation_message">
+        <item quantity="one">Delete <xliff:g id="count" example="1">%1$d</xliff:g> file?</item>
+        <item quantity="other">Delete <xliff:g id="count" example="3">%1$d</xliff:g> files?</item>
+    </plurals>
+    <!-- Label text showing user how many items are selected. Can be one or more elements. -->
+    <plurals name="elements_selected">
+        <item quantity="one"><xliff:g id="count" example="1">%1$d</xliff:g> selected</item>
+        <item quantity="other"><xliff:g id="count" example="3">%1$d</xliff:g> selected</item>
+    </plurals>
 </resources>
diff --git a/packages/DocumentsUI/res/values/styles.xml b/packages/DocumentsUI/res/values/styles.xml
index f4dfd73..21bdfd9 100644
--- a/packages/DocumentsUI/res/values/styles.xml
+++ b/packages/DocumentsUI/res/values/styles.xml
@@ -29,6 +29,7 @@
         <item name="android:colorPrimary">@color/primary</item>
         <item name="android:colorAccent">@color/accent</item>
         <item name="colorActionMode">@color/action_mode</item>
+        <item name="android:queryBackground">@color/menu_search_background</item>
 
         <item name="android:listDivider">@*android:drawable/list_divider_material</item>
 
diff --git a/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java b/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java
index 95c49ff..c9d18b3 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java
@@ -22,8 +22,6 @@
 import static com.android.documentsui.dirlist.DirectoryFragment.ANIM_LEAVE;
 import static com.android.documentsui.dirlist.DirectoryFragment.ANIM_NONE;
 import static com.android.documentsui.dirlist.DirectoryFragment.ANIM_SIDE;
-import static com.android.internal.util.Preconditions.checkArgument;
-import static com.google.common.base.Preconditions.checkState;
 
 import android.app.Activity;
 import android.app.Fragment;
@@ -41,6 +39,7 @@
 import android.support.annotation.CallSuper;
 import android.support.annotation.LayoutRes;
 import android.support.annotation.Nullable;
+import android.support.annotation.VisibleForTesting;
 import android.util.Log;
 import android.view.KeyEvent;
 import android.view.Menu;
@@ -54,7 +53,6 @@
 import com.android.documentsui.model.DocumentInfo;
 import com.android.documentsui.model.DocumentStack;
 import com.android.documentsui.model.RootInfo;
-import com.android.internal.util.Preconditions;
 
 import java.io.FileNotFoundException;
 import java.util.ArrayList;
@@ -70,6 +68,7 @@
     SearchViewManager mSearchManager;
     DrawerController mDrawer;
     NavigationView mNavigator;
+    List<EventListener> mEventListeners = new ArrayList<>();
 
     private final String mTag;
 
@@ -152,11 +151,10 @@
         final MenuItem sortSize = menu.findItem(R.id.menu_sort_size);
         final MenuItem grid = menu.findItem(R.id.menu_grid);
         final MenuItem list = menu.findItem(R.id.menu_list);
-        final MenuItem advanced = menu.findItem(R.id.menu_advanced);
         final MenuItem fileSize = menu.findItem(R.id.menu_file_size);
 
         // Search uses backend ranking; no sorting, recents doesn't support sort.
-        sort.setVisible(!inRecents && !mSearchManager.isSearching());
+        sort.setEnabled(!inRecents && !mSearchManager.isSearching());
         sortSize.setVisible(mState.showSize); // Only sort by size when file sizes are visible
         fileSize.setVisible(!mState.forceSize);
 
@@ -164,9 +162,6 @@
         grid.setVisible(mState.derivedMode != State.MODE_GRID);
         list.setVisible(mState.derivedMode != State.MODE_LIST);
 
-        advanced.setVisible(!mState.forceAdvanced);
-        advanced.setTitle(LocalPreferences.getDisplayAdvancedDevices(this)
-                ? R.string.menu_advanced_hide : R.string.menu_advanced_show);
         fileSize.setTitle(LocalPreferences.getDisplayFileSize(this)
                 ? R.string.menu_file_size_hide : R.string.menu_file_size_show);
 
@@ -202,10 +197,6 @@
         state.forceSize = intent.getBooleanExtra(DocumentsContract.EXTRA_SHOW_FILESIZE, false);
         state.showSize = state.forceSize || LocalPreferences.getDisplayFileSize(this);
 
-        state.forceAdvanced = intent.getBooleanExtra(DocumentsContract.EXTRA_SHOW_ADVANCED, false);
-        state.showAdvanced = state.forceAdvanced
-                || LocalPreferences.getDisplayAdvancedDevices(this);
-
         state.initAcceptMimes(intent);
         state.excludedAuthorities = getExcludedAuthorities();
 
@@ -253,6 +244,7 @@
                 return true;
 
             case R.id.menu_search:
+                // SearchViewManager listens for this directly.
                 return false;
 
             case R.id.menu_sort_name:
@@ -281,10 +273,6 @@
                 }
                 return true;
 
-            case R.id.menu_advanced:
-                setDisplayAdvancedDevices(!LocalPreferences.getDisplayAdvancedDevices(this));
-                return true;
-
             case R.id.menu_file_size:
                 setDisplayFileSize(!LocalPreferences.getDisplayFileSize(this));
                 return true;
@@ -330,7 +318,10 @@
     }
 
     void openContainerDocument(DocumentInfo doc) {
-        checkArgument(doc.isContainer());
+        assert(doc.isContainer());
+
+        notifyDirectoryNavigated(doc.derivedUri);
+
         mState.pushDocument(doc);
         // Show an opening animation only if pressing "back" would get us back to the
         // previous directory. Especially after opening a root document, pressing
@@ -373,8 +364,10 @@
     @Override
     public void onSearchChanged(@Nullable String query) {
         // We should not get here if root is not searchable
-        checkState(canSearchRoot());
+        assert(canSearchRoot());
+
         reloadSearch(query);
+        invalidateOptionsMenu();
     }
 
     private void reloadSearch(String query) {
@@ -432,13 +425,6 @@
         return mState;
     }
 
-    void setDisplayAdvancedDevices(boolean display) {
-        LocalPreferences.setDisplayAdvancedDevices(this, display);
-        mState.showAdvanced = mState.forceAdvanced | display;
-        RootsFragment.get(getFragmentManager()).onDisplayStateChanged();
-        invalidateOptionsMenu();
-    }
-
     void setDisplayFileSize(boolean display) {
         LocalPreferences.setDisplayFileSize(this, display);
         mState.showSize = display;
@@ -595,6 +581,28 @@
         return super.onKeyDown(keyCode, event);
     }
 
+    @VisibleForTesting
+    public void addEventListener(EventListener listener) {
+        mEventListeners.add(listener);
+    }
+
+    @VisibleForTesting
+    public void removeEventListener(EventListener listener) {
+        mEventListeners.remove(listener);
+    }
+
+    public void notifyDirectoryLoaded(Uri uri) {
+        for (EventListener listener : mEventListeners) {
+            listener.onDirectoryLoaded(uri);
+        }
+    }
+
+    void notifyDirectoryNavigated(Uri uri) {
+        for (EventListener listener : mEventListeners) {
+            listener.onDirectoryNavigated(uri);
+        }
+    }
+
     /**
      * Toggles focus between the navigation drawer and the directory listing. If the drawer isn't
      * locked, open/close it as appropriate.
@@ -673,7 +681,8 @@
 
         @Override
         protected RootInfo run(RootInfo... roots) {
-            checkArgument(roots.length == 1);
+            assert(roots.length == 1);
+
             final RootInfo currentRoot = roots[0];
             final Collection<RootInfo> cachedRoots = mOwner.mRoots.getRootsBlocking();
             RootInfo homeRoot = null;
@@ -686,7 +695,7 @@
                     return null;
                 }
             }
-            Preconditions.checkNotNull(homeRoot);
+            assert(homeRoot != null);
             mHome = mOwner.getRootDocumentBlocking(homeRoot);
             return homeRoot;
         }
diff --git a/packages/DocumentsUI/src/com/android/documentsui/CreateDirectoryFragment.java b/packages/DocumentsUI/src/com/android/documentsui/CreateDirectoryFragment.java
index 40bd754..ebc9082 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/CreateDirectoryFragment.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/CreateDirectoryFragment.java
@@ -82,6 +82,9 @@
         builder.setNegativeButton(android.R.string.cancel, null);
         final AlertDialog dialog = builder.create();
 
+        // Workaround for the problem - virtual keyboard doesn't show on the phone.
+        Shared.ensureKeyboardPresent(context, dialog);
+
         editText.setOnEditorActionListener(
                 new OnEditorActionListener() {
                     @Override
diff --git a/packages/DocumentsUI/src/com/android/documentsui/DirectoryLoader.java b/packages/DocumentsUI/src/com/android/documentsui/DirectoryLoader.java
index 13b7b14..d2e918c 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/DirectoryLoader.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/DirectoryLoader.java
@@ -59,7 +59,6 @@
     private CancellationSignal mSignal;
     private DirectoryResult mResult;
 
-
     public DirectoryLoader(Context context, int type, RootInfo root, DocumentInfo doc, Uri uri,
             int userSortOrder, boolean inSearchMode) {
         super(context, ProviderExecutor.forAuthority(root.authority));
@@ -84,6 +83,7 @@
         final String authority = mUri.getAuthority();
 
         final DirectoryResult result = new DirectoryResult();
+        result.doc = mDoc;
 
         // Use default document when searching
         if (mSearchMode) {
diff --git a/packages/DocumentsUI/src/com/android/documentsui/DirectoryResult.java b/packages/DocumentsUI/src/com/android/documentsui/DirectoryResult.java
index 22e438a..6268643 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/DirectoryResult.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/DirectoryResult.java
@@ -22,12 +22,15 @@
 import android.content.ContentProviderClient;
 import android.database.Cursor;
 
+import com.android.documentsui.model.DocumentInfo;
+
 import libcore.io.IoUtils;
 
 public class DirectoryResult implements AutoCloseable {
     ContentProviderClient client;
     public Cursor cursor;
     public Exception exception;
+    public DocumentInfo doc;
 
     public int sortOrder = SORT_ORDER_UNKNOWN;
 
diff --git a/packages/DocumentsUI/src/com/android/documentsui/DirectoryView.java b/packages/DocumentsUI/src/com/android/documentsui/DirectoryView.java
index 000b92a..a26fb47 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/DirectoryView.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/DirectoryView.java
@@ -46,7 +46,7 @@
 
     public void setPosition(float position) {
         mPosition = position;
-        setX((mWidth > 0) ? (mPosition * mWidth) : 0);
+        setY((mWidth > 0) ? (mPosition * mWidth) : 0);
 
         if (mPosition != 0) {
             setTranslationZ(getResources().getDimensionPixelSize(R.dimen.dir_elevation));
diff --git a/packages/DocumentsUI/src/com/android/documentsui/Display.java b/packages/DocumentsUI/src/com/android/documentsui/Display.java
new file mode 100644
index 0000000..bae2d58
--- /dev/null
+++ b/packages/DocumentsUI/src/com/android/documentsui/Display.java
@@ -0,0 +1,56 @@
+/*
+ * 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.documentsui;
+
+import android.app.Activity;
+import android.content.Context;
+import android.graphics.Point;
+import android.util.TypedValue;
+
+/*
+ * Convenience class for getting display related attributes
+ */
+public final class Display {
+    /*
+     * Returns the screen width in pixels.
+     */
+    public static float screenWidth(Activity activity) {
+        Point size = new Point();
+        activity.getWindowManager().getDefaultDisplay().getSize(size);
+        return size.x;
+    }
+
+    /*
+     * Returns logical density of the display.
+     */
+    public static float density(Context context) {
+        return context.getResources().getDisplayMetrics().density;
+    }
+
+    /*
+     * Returns action bar height in pixels.
+     */
+    public static float actionBarHeight(Context context) {
+        int actionBarHeight = 0;
+        TypedValue tv = new TypedValue();
+        if (context.getTheme().resolveAttribute(android.R.attr.actionBarSize, tv, true)) {
+            actionBarHeight = TypedValue.complexToDimensionPixelSize(tv.data,
+                    context.getResources().getDisplayMetrics());
+        }
+        return actionBarHeight;
+    }
+}
diff --git a/packages/DocumentsUI/src/com/android/documentsui/DocumentClipper.java b/packages/DocumentsUI/src/com/android/documentsui/DocumentClipper.java
index b3c2846..15bfc3b 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/DocumentClipper.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/DocumentClipper.java
@@ -28,7 +28,6 @@
 import android.util.Log;
 
 import com.android.documentsui.model.DocumentInfo;
-import com.android.internal.util.Preconditions;
 
 import libcore.io.IoUtils;
 
@@ -85,7 +84,7 @@
      * This should be run from inside an AsyncTask.
      */
     public List<DocumentInfo> getDocumentsFromClipData(ClipData clipData) {
-        Preconditions.checkNotNull(clipData);
+        assert(clipData != null);
         final List<DocumentInfo> srcDocs = new ArrayList<>();
 
         int count = clipData.getItemCount();
diff --git a/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java b/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java
index ed531a8..f8b32a0 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java
@@ -23,7 +23,6 @@
 import static com.android.documentsui.State.ACTION_OPEN_TREE;
 import static com.android.documentsui.State.ACTION_PICK_COPY_DESTINATION;
 import static com.android.documentsui.dirlist.DirectoryFragment.ANIM_NONE;
-import static com.android.internal.util.Preconditions.checkArgument;
 
 import android.app.Activity;
 import android.app.Fragment;
@@ -96,7 +95,7 @@
         }
 
         if (mState.restored) {
-            refreshCurrentRootAndDirectory(ANIM_NONE);
+            if (DEBUG) Log.d(TAG, "Stack already resolved");
         } else {
             // We set the activity title in AsyncTask.onPostExecute().
             // To prevent talkback from reading aloud the default title, we clear it here.
@@ -109,9 +108,7 @@
             // we restore the stack as last used from that app.
             if (mState.action == ACTION_PICK_COPY_DESTINATION) {
                 if (DEBUG) Log.d(TAG, "Launching directly into Home directory.");
-                Uri homeUri = DocumentsContract.buildHomeUri();
-                new LoadRootTask(this, homeUri).executeOnExecutor(
-                        ProviderExecutor.forAuthority(homeUri.getAuthority()));
+                loadRoot(DocumentsContract.buildHomeUri());
             } else {
                 if (DEBUG) Log.d(TAG, "Attempting to load last used stack for calling package.");
                 new LoadLastUsedStackTask(this).execute();
@@ -157,30 +154,6 @@
         }
     }
 
-    private void onStackRestored(boolean restored, boolean external) {
-        // Show drawer when no stack restored, but only when requesting
-        // non-visual content. However, if we last used an external app,
-        // drawer is always shown.
-
-        boolean showDrawer = false;
-        if (!restored) {
-            showDrawer = true;
-        }
-        if (MimePredicate.mimeMatches(MimePredicate.VISUAL_MIMES, mState.acceptMimes)) {
-            showDrawer = false;
-        }
-        if (external && mState.action == ACTION_GET_CONTENT) {
-            showDrawer = true;
-        }
-        if (mState.action == ACTION_PICK_COPY_DESTINATION) {
-            showDrawer = true;
-        }
-
-        if (showDrawer) {
-            mNavigator.revealRootsDrawer(true);
-        }
-    }
-
     public void onAppPicked(ResolveInfo info) {
         final Intent intent = new Intent(getIntent());
         intent.setFlags(intent.getFlags() & ~Intent.FLAG_ACTIVITY_FORWARD_RESULT);
@@ -333,7 +306,7 @@
 
     @Override
     void onDirectoryCreated(DocumentInfo doc) {
-        checkArgument(doc.isDirectory());
+        assert(doc.isDirectory());
         openContainerDocument(doc);
     }
 
@@ -518,8 +491,8 @@
         @Override
         protected void finish(Void result) {
             mState.restored = true;
+            mState.external = mExternal;
             mOwner.refreshCurrentRootAndDirectory(ANIM_NONE);
-            mOwner.onStackRestored(mRestoredStack, mExternal);
         }
     }
 
diff --git a/packages/DocumentsUI/src/com/android/documentsui/DownloadsActivity.java b/packages/DocumentsUI/src/com/android/documentsui/DownloadsActivity.java
deleted file mode 100644
index 536feeb..0000000
--- a/packages/DocumentsUI/src/com/android/documentsui/DownloadsActivity.java
+++ /dev/null
@@ -1,189 +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.documentsui;
-
-import static com.android.documentsui.Shared.DEBUG;
-import static com.android.documentsui.State.ACTION_MANAGE;
-import static com.android.documentsui.dirlist.DirectoryFragment.ANIM_NONE;
-import static com.android.internal.util.Preconditions.checkState;
-
-import android.app.Activity;
-import android.app.Fragment;
-import android.app.FragmentManager;
-import android.content.ActivityNotFoundException;
-import android.content.ClipData;
-import android.content.Context;
-import android.content.Intent;
-import android.net.Uri;
-import android.os.Bundle;
-import android.provider.DocumentsContract;
-import android.support.design.widget.Snackbar;
-import android.util.Log;
-import android.view.Menu;
-import android.view.MenuItem;
-import android.widget.Toolbar;
-
-import com.android.documentsui.dirlist.DirectoryFragment;
-import com.android.documentsui.dirlist.Model;
-import com.android.documentsui.model.DocumentInfo;
-import com.android.documentsui.model.RootInfo;
-import com.android.internal.util.Preconditions;
-
-import java.util.Arrays;
-import java.util.List;
-
-// Let's face it. MANAGE_ROOT is used almost exclusively
-// for downloads, and is specialized for this purpose.
-// So it is now thusly christened.
-public class DownloadsActivity extends BaseActivity {
-    private static final String TAG = "DownloadsActivity";
-
-    public DownloadsActivity() {
-        super(R.layout.downloads_activity, TAG);
-    }
-
-    @Override
-    public void onCreate(Bundle icicle) {
-        super.onCreate(icicle);
-
-        final Context context = this;
-
-        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
-        toolbar.setTitleTextAppearance(context,
-                android.R.style.TextAppearance_DeviceDefault_Widget_ActionBar_Title);
-
-        if (!mState.restored) {
-            // In this case, we set the activity title in AsyncTask.onPostExecute(). To prevent
-            // talkback from reading aloud the default title, we clear it here.
-            setTitle("");
-            final Uri rootUri = getIntent().getData();
-            new LoadRootTask(this, rootUri).executeOnExecutor(getExecutorForCurrentDirectory());
-        } else {
-            refreshCurrentRootAndDirectory(ANIM_NONE);
-        }
-    }
-
-    @Override
-    void includeState(State state) {
-        state.action = ACTION_MANAGE;
-        state.acceptMimes = new String[] { "*/*" };
-        state.allowMultiple = true;
-        state.showSize = true;
-        state.excludedAuthorities = getExcludedAuthorities();
-    }
-
-    @Override
-    protected void onPostCreate(Bundle savedInstanceState) {
-        super.onPostCreate(savedInstanceState);
-        mNavigator.update();
-    }
-
-    @Override
-    public String getDrawerTitle() {
-        return null;  // being and nothingness
-    }
-
-    @Override
-    public boolean onPrepareOptionsMenu(Menu menu) {
-        super.onPrepareOptionsMenu(menu);
-
-        final MenuItem advanced = menu.findItem(R.id.menu_advanced);
-        final MenuItem createDir = menu.findItem(R.id.menu_create_dir);
-        final MenuItem pasteFromCb = menu.findItem(R.id.menu_paste_from_clipboard);
-        final MenuItem fileSize = menu.findItem(R.id.menu_file_size);
-
-        advanced.setVisible(false);
-        createDir.setVisible(false);
-        pasteFromCb.setEnabled(false);
-        fileSize.setVisible(false);
-
-        Menus.disableHiddenItems(menu);
-        return true;
-    }
-
-    @Override
-    void refreshDirectory(int anim) {
-        final FragmentManager fm = getFragmentManager();
-        final RootInfo root = getCurrentRoot();
-        final DocumentInfo cwd = getCurrentDirectory();
-
-        if (DEBUG) checkState(!mSearchManager.isSearching());
-
-        // If started in manage roots mode, there has to be a cwd (i.e. the root dir of the managed
-        // root).
-        Preconditions.checkNotNull(cwd);
-
-        // Normal boring directory
-        DirectoryFragment.showDirectory(fm, root, cwd, anim);
-    }
-
-    @Override
-    public void onDocumentPicked(DocumentInfo doc, Model model) {
-        Preconditions.checkArgument(!doc.isDirectory());
-        // First try managing the document; we expect manager to filter
-        // based on authority, so we don't grant.
-        final Intent manage = new Intent(DocumentsContract.ACTION_MANAGE_DOCUMENT);
-        manage.setData(doc.derivedUri);
-
-        try {
-            startActivity(manage);
-        } catch (ActivityNotFoundException ex) {
-            // Fall back to viewing.
-            final Intent view = new Intent(Intent.ACTION_VIEW);
-            view.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
-            view.setData(doc.derivedUri);
-
-            try {
-                startActivity(view);
-            } catch (ActivityNotFoundException ex2) {
-                Snackbars.makeSnackbar(this, R.string.toast_no_application, Snackbar.LENGTH_SHORT)
-                        .show();
-            }
-        }
-    }
-
-    @Override
-    public void onDocumentsPicked(List<DocumentInfo> docs) {}
-
-    @Override
-    void onTaskFinished(Uri... uris) {
-        Log.d(TAG, "onFinished() " + Arrays.toString(uris));
-
-        final Intent intent = new Intent();
-        if (uris.length == 1) {
-            intent.setData(uris[0]);
-        } else if (uris.length > 1) {
-            final ClipData clipData = new ClipData(
-                    null, mState.acceptMimes, new ClipData.Item(uris[0]));
-            for (int i = 1; i < uris.length; i++) {
-                clipData.addItem(new ClipData.Item(uris[i]));
-            }
-            intent.setClipData(clipData);
-        }
-
-        intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION
-                | Intent.FLAG_GRANT_WRITE_URI_PERMISSION
-                | Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION);
-
-        setResult(Activity.RESULT_OK, intent);
-        finish();
-    }
-
-    public static DownloadsActivity get(Fragment fragment) {
-        return (DownloadsActivity) fragment.getActivity();
-    }
-}
diff --git a/packages/DocumentsUI/src/com/android/documentsui/DrawerController.java b/packages/DocumentsUI/src/com/android/documentsui/DrawerController.java
index bcf69c4..020f2c0 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/DrawerController.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/DrawerController.java
@@ -16,12 +16,14 @@
 
 package com.android.documentsui;
 
-import static com.android.internal.util.Preconditions.checkArgument;
+import static com.android.documentsui.Shared.DEBUG;
 
 import android.app.Activity;
+import android.content.Context;
 import android.support.v4.app.ActionBarDrawerToggle;
 import android.support.v4.widget.DrawerLayout;
 import android.support.v4.widget.DrawerLayout.DrawerListener;
+import android.util.Log;
 import android.view.View;
 import android.widget.Toolbar;
 
@@ -32,6 +34,8 @@
  */
 abstract class DrawerController implements DrawerListener {
 
+    public static final String TAG = "DrawerController";
+
     abstract void setOpen(boolean open);
     abstract boolean isPresent();
     abstract boolean isOpen();
@@ -52,6 +56,8 @@
         View drawer = activity.findViewById(R.id.drawer_roots);
         Toolbar toolbar = (Toolbar) activity.findViewById(R.id.roots_toolbar);
 
+        drawer.getLayoutParams().width = calculateDrawerWidth(activity);
+
         ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
                 activity,
                 layout,
@@ -69,6 +75,19 @@
         return new DummyDrawerController();
     }
 
+    private static int calculateDrawerWidth(Activity activity) {
+        // Material design specification for navigation drawer:
+        // https://www.google.com/design/spec/patterns/navigation-drawer.html
+        float width = Display.screenWidth(activity) - Display.actionBarHeight(activity);
+        float maxWidth = activity.getResources().getDimension(R.dimen.max_drawer_width);
+        int finalWidth = (int) ((width > maxWidth ? maxWidth : width));
+
+        if (DEBUG)
+            Log.d(TAG, "Calculated drawer width:" + (finalWidth / Display.density(activity)));
+
+        return finalWidth;
+    }
+
     /**
      * Runtime controller that manages a real drawer.
      */
@@ -83,7 +102,7 @@
                 DrawerLayout layout, View drawer, ActionBarDrawerToggle toggle,
                 Toolbar drawerToolbar) {
             mToolbar = drawerToolbar;
-            checkArgument(layout != null);
+            assert(layout != null);
 
             mLayout = layout;
             mDrawer = drawer;
diff --git a/packages/DocumentsUI/src/com/android/documentsui/EventListener.java b/packages/DocumentsUI/src/com/android/documentsui/EventListener.java
new file mode 100644
index 0000000..c15e9a6
--- /dev/null
+++ b/packages/DocumentsUI/src/com/android/documentsui/EventListener.java
@@ -0,0 +1,32 @@
+/*
+ * 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.documentsui;
+
+import android.net.Uri;
+import android.support.annotation.Nullable;
+
+public interface EventListener {
+    /**
+     * @param uri Uri navigated to. If recents, then null.
+     */
+    void onDirectoryNavigated(@Nullable Uri uri);
+
+    /**
+     * @param uri Uri of the loaded directory. If recents, then null.
+     */
+    void onDirectoryLoaded(@Nullable Uri uri);
+}
diff --git a/packages/DocumentsUI/src/com/android/documentsui/FilesActivity.java b/packages/DocumentsUI/src/com/android/documentsui/FilesActivity.java
index a3378ad..573e4f3 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/FilesActivity.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/FilesActivity.java
@@ -19,8 +19,6 @@
 import static com.android.documentsui.OperationDialogFragment.DIALOG_TYPE_UNKNOWN;
 import static com.android.documentsui.Shared.DEBUG;
 import static com.android.documentsui.dirlist.DirectoryFragment.ANIM_NONE;
-import static com.android.internal.util.Preconditions.checkArgument;
-import static com.android.internal.util.Preconditions.checkState;
 
 import android.app.Activity;
 import android.app.FragmentManager;
@@ -97,11 +95,11 @@
             // Launch URIs support sensible activity management, but don't specify a real
             // content target.
             if (DEBUG) Log.d(TAG, "Launching with non-empty stack.");
-            checkState(uri == null || uri.getAuthority() == null ||
+            assert(uri == null || uri.getAuthority() == null ||
                     LauncherActivity.isLaunchUri(uri));
             refreshCurrentRootAndDirectory(ANIM_NONE);
         } else if (intent.getAction() == Intent.ACTION_VIEW) {
-            checkArgument(uri != null);
+            assert(uri != null);
             new OpenUriForViewTask(this).executeOnExecutor(
                     ProviderExecutor.forAuthority(uri.getAuthority()), uri);
         } else if (DocumentsContract.isRootUri(this, uri)) {
@@ -110,10 +108,10 @@
             // authority. That way a misbehaving provider won't result in an ANR.
             loadRoot(uri);
         } else {
-            if (DEBUG) Log.d(TAG, "Launching into Home directory.");
-            // If all else fails, try to load "Home" directory.
-            final Uri homeUri = DocumentsContract.buildHomeUri();
-            loadRoot(homeUri);
+            if (DEBUG) Log.d(TAG, "All other means skipped. Launching into default directory.");
+            Uri defaultUri = DocumentsContract.buildRootUri(
+                    "com.android.providers.downloads.documents", "downloads");
+            loadRoot(defaultUri);
         }
 
         final @DialogType int dialogType = intent.getIntExtra(
@@ -143,7 +141,7 @@
         state.allowMultiple = true;
 
         // Options specific to the DocumentsActivity.
-        checkArgument(!intent.hasExtra(Intent.EXTRA_LOCAL_ONLY));
+        assert(!intent.hasExtra(Intent.EXTRA_LOCAL_ONLY));
 
         final DocumentStack stack = intent.getParcelableExtra(Shared.EXTRA_STACK);
         if (stack != null) {
@@ -212,7 +210,7 @@
     public boolean onOptionsItemSelected(MenuItem item) {
         switch (item.getItemId()) {
             case R.id.menu_create_dir:
-                checkState(canCreateDirectory());
+                assert(canCreateDirectory());
                 showCreateDirectoryDialog();
                 return true;
             case R.id.menu_new_window:
@@ -250,7 +248,7 @@
         final RootInfo root = getCurrentRoot();
         final DocumentInfo cwd = getCurrentDirectory();
 
-        if (DEBUG) checkState(!mSearchManager.isSearching());
+        assert(!mSearchManager.isSearching());
 
         if (cwd == null) {
             DirectoryFragment.showRecentsOpen(fm, anim);
@@ -284,6 +282,24 @@
      * Launches an intent to view the specified document.
      */
     private void openDocument(DocumentInfo doc, Model model) {
+
+        // Provide specialized handling of downloaded APKs This sends the APK
+        // details off to get extra security information added, and finally
+        // to be handled by the package manager.
+        if (MimePredicate.isApkType(doc.mimeType)) {
+            // First try managing the document; we expect manager to filter
+            // based on authority, so we don't grant.
+            final Intent manage = new Intent(DocumentsContract.ACTION_MANAGE_DOCUMENT);
+            manage.setData(doc.derivedUri);
+
+            try {
+                startActivity(manage);
+                return;
+            } catch (ActivityNotFoundException ex) {
+                // fall back to regular handling below.
+            }
+        }
+
         Intent intent = new QuickViewIntentBuilder(
                 getPackageManager(), getResources(), doc, model).build();
 
@@ -298,7 +314,7 @@
             }
         }
 
-        // Fallback to traditional VIEW action...
+        // Fall back to traditional VIEW action...
         intent = new Intent(Intent.ACTION_VIEW);
         intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
         intent.setData(doc.derivedUri);
diff --git a/packages/DocumentsUI/src/com/android/documentsui/LocalPreferences.java b/packages/DocumentsUI/src/com/android/documentsui/LocalPreferences.java
index 4bffc49..c7c61c3 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/LocalPreferences.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/LocalPreferences.java
@@ -17,7 +17,6 @@
 package com.android.documentsui;
 
 import static com.android.documentsui.State.MODE_UNKNOWN;
-import static com.android.internal.util.Preconditions.checkArgument;
 
 import android.content.Context;
 import android.preference.PreferenceManager;
@@ -26,17 +25,9 @@
 import com.android.documentsui.model.RootInfo;
 
 public class LocalPreferences {
-    private static final String KEY_ADVANCED_DEVICES = "advancedDevices";
     private static final String KEY_FILE_SIZE = "fileSize";
     private static final String ROOT_VIEW_MODE_PREFIX = "rootViewMode-";
 
-    public static boolean getDisplayAdvancedDevices(Context context) {
-        boolean defaultAdvanced = context.getResources()
-                .getBoolean(R.bool.config_defaultAdvancedDevices);
-        return PreferenceManager.getDefaultSharedPreferences(context)
-                .getBoolean(KEY_ADVANCED_DEVICES, defaultAdvanced);
-    }
-
     public static boolean getDisplayFileSize(Context context) {
         return PreferenceManager.getDefaultSharedPreferences(context)
                 .getBoolean(KEY_FILE_SIZE, false);
@@ -48,18 +39,14 @@
                 .getInt(createKey(root), fallback);
     }
 
-    public static void setDisplayAdvancedDevices(Context context, boolean display) {
-        PreferenceManager.getDefaultSharedPreferences(context).edit()
-                .putBoolean(KEY_ADVANCED_DEVICES, display).apply();
-    }
-
     public static void setDisplayFileSize(Context context, boolean display) {
         PreferenceManager.getDefaultSharedPreferences(context).edit()
                 .putBoolean(KEY_FILE_SIZE, display).apply();
     }
 
     public static void setViewMode(Context context, RootInfo root, @ViewMode int viewMode) {
-        checkArgument(viewMode != MODE_UNKNOWN);
+        assert(viewMode != MODE_UNKNOWN);
+
         PreferenceManager.getDefaultSharedPreferences(context).edit()
                 .putInt(createKey(root), viewMode).apply();
     }
diff --git a/packages/DocumentsUI/src/com/android/documentsui/Metrics.java b/packages/DocumentsUI/src/com/android/documentsui/Metrics.java
index 699605f..afd308c 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/Metrics.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/Metrics.java
@@ -16,11 +16,13 @@
 
 package com.android.documentsui;
 
+import static android.os.Environment.STANDARD_DIRECTORIES;
 import static com.android.documentsui.Shared.DEBUG;
-import static com.android.internal.util.Preconditions.checkArgument;
 
 import android.annotation.IntDef;
 import android.annotation.Nullable;
+import android.annotation.StringDef;
+import android.app.Activity;
 import android.content.Context;
 import android.content.Intent;
 import android.content.pm.ResolveInfo;
@@ -33,6 +35,7 @@
 import com.android.documentsui.services.FileOperationService;
 import com.android.documentsui.services.FileOperationService.OpType;
 import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.MetricsProto.MetricsEvent;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
@@ -56,7 +59,7 @@
     private static final String COUNT_CREATE_MIME = "docsui_create_mime";
     private static final String COUNT_GET_CONTENT_MIME = "docsui_get_content_mime";
     private static final String COUNT_BROWSE_ROOT = "docsui_browse_root";
-    private static final String COUNT_MANAGE_ROOT = "docsui_manage_root";
+    @Deprecated private static final String COUNT_MANAGE_ROOT = "docsui_manage_root";
     private static final String COUNT_MULTI_WINDOW = "docsui_multi_window";
     private static final String COUNT_FILEOP_SYSTEM = "docsui_fileop_system";
     private static final String COUNT_FILEOP_EXTERNAL = "docsui_fileop_external";
@@ -192,7 +195,7 @@
     private static final int ACTION_CREATE = 3;
     private static final int ACTION_GET_CONTENT = 4;
     private static final int ACTION_OPEN_TREE = 5;
-    private static final int ACTION_MANAGE = 6;
+    @Deprecated private static final int ACTION_MANAGE = 6;
     private static final int ACTION_BROWSE = 7;
     private static final int ACTION_PICK_COPY_DESTINATION = 8;
 
@@ -244,9 +247,6 @@
             case State.ACTION_GET_CONTENT:
                 logHistogram(context, COUNT_GET_CONTENT_MIME, sanitizeMime(intent.getType()));
                 break;
-            case State.ACTION_MANAGE:
-                logHistogram(context, COUNT_MANAGE_ROOT, sanitizeRoot(uri));
-                break;
             case State.ACTION_BROWSE:
                 logHistogram(context, COUNT_BROWSE_ROOT, sanitizeRoot(uri));
                 break;
@@ -363,7 +363,7 @@
         if (operationType == FileOperationService.OPERATION_DELETE) {
             logHistogram(context, histogram, FILEOP_DELETE);
         } else {
-            checkArgument(dst != null);
+            assert(dst != null);
             @Provider int providerType =
                     isSystemProvider(dst.authority) ? PROVIDER_SYSTEM : PROVIDER_EXTERNAL;
             logHistogram(context, histogram, getOpCode(operationType, providerType));
@@ -377,6 +377,84 @@
         logHistogram(context, histogram, getOpCode(operationType, PROVIDER_INTRA));
     }
 
+    // Types for logInvalidScopedAccessRequest
+    public static final String SCOPED_DIRECTORY_ACCESS_INVALID_ARGUMENTS =
+            "scoped_directory_access_invalid_args";
+    public static final String SCOPED_DIRECTORY_ACCESS_INVALID_DIRECTORY =
+            "scoped_directory_access_invalid_dir";
+    public static final String SCOPED_DIRECTORY_ACCESS_ERROR =
+            "scoped_directory_access_error";
+
+    @StringDef(value = {
+            SCOPED_DIRECTORY_ACCESS_INVALID_ARGUMENTS,
+            SCOPED_DIRECTORY_ACCESS_INVALID_DIRECTORY,
+            SCOPED_DIRECTORY_ACCESS_ERROR
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface InvalidScopedAccess{}
+
+    public static void logInvalidScopedAccessRequest(Context context,
+            @InvalidScopedAccess String type) {
+        MetricsLogger.count(context, type, 1);
+        switch (type) {
+            case SCOPED_DIRECTORY_ACCESS_INVALID_ARGUMENTS:
+            case SCOPED_DIRECTORY_ACCESS_INVALID_DIRECTORY:
+            case SCOPED_DIRECTORY_ACCESS_ERROR:
+                MetricsLogger.count(context, type, 1);
+                break;
+            default:
+                Log.wtf(TAG, "invalid InvalidScopedAccess: " + type);
+        }
+    }
+
+    // Types for logValidScopedAccessRequest
+    public static final int SCOPED_DIRECTORY_ACCESS_ALREADY_GRANTED = 0;
+    public static final int SCOPED_DIRECTORY_ACCESS_GRANTED = 1;
+    public static final int SCOPED_DIRECTORY_ACCESS_DENIED = 2;
+
+    @IntDef(flag = true, value = {
+            SCOPED_DIRECTORY_ACCESS_ALREADY_GRANTED,
+            SCOPED_DIRECTORY_ACCESS_GRANTED,
+            SCOPED_DIRECTORY_ACCESS_DENIED
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface ScopedAccessGrant {}
+
+    public static void logValidScopedAccessRequest(Activity activity, String directory,
+            @ScopedAccessGrant int type) {
+        int index = -1;
+        for (int i = 0; i < STANDARD_DIRECTORIES.length; i++) {
+            if (STANDARD_DIRECTORIES[i].equals(directory)) {
+                index = i;
+                break;
+            }
+        }
+        final String packageName = activity.getCallingPackage();
+        switch (type) {
+            case SCOPED_DIRECTORY_ACCESS_ALREADY_GRANTED:
+                MetricsLogger.action(activity,
+                        MetricsEvent.ACTION_SCOPED_DIRECTORY_ACCESS_ALREADY_GRANTED_BY_PACKAGE,
+                        packageName);
+                MetricsLogger.action(activity,
+                        MetricsEvent.ACTION_SCOPED_DIRECTORY_ACCESS_ALREADY_GRANTED_BY_FOLDER, index);
+                break;
+            case SCOPED_DIRECTORY_ACCESS_GRANTED:
+                MetricsLogger.action(activity,
+                        MetricsEvent.ACTION_SCOPED_DIRECTORY_ACCESS_GRANTED_BY_PACKAGE, packageName);
+                MetricsLogger.action(activity,
+                        MetricsEvent.ACTION_SCOPED_DIRECTORY_ACCESS_GRANTED_BY_FOLDER, index);
+                break;
+            case SCOPED_DIRECTORY_ACCESS_DENIED:
+                MetricsLogger.action(activity,
+                        MetricsEvent.ACTION_SCOPED_DIRECTORY_ACCESS_DENIED_BY_PACKAGE, packageName);
+                MetricsLogger.action(activity,
+                        MetricsEvent.ACTION_SCOPED_DIRECTORY_ACCESS_DENIED_BY_FOLDER, index);
+                break;
+            default:
+                Log.wtf(TAG, "invalid ScopedAccessGrant: " + type);
+        }
+    }
+
     /**
      * Internal method for making a MetricsLogger.count call. Increments the given counter by 1.
      *
@@ -561,8 +639,6 @@
                 return ACTION_GET_CONTENT;
             case State.ACTION_OPEN_TREE:
                 return ACTION_OPEN_TREE;
-            case State.ACTION_MANAGE:
-                return ACTION_MANAGE;
             case State.ACTION_BROWSE:
                 return ACTION_BROWSE;
             case State.ACTION_PICK_COPY_DESTINATION:
diff --git a/packages/DocumentsUI/src/com/android/documentsui/MimePredicate.java b/packages/DocumentsUI/src/com/android/documentsui/MimePredicate.java
index 9df55a0..2f202e7 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/MimePredicate.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/MimePredicate.java
@@ -16,12 +16,15 @@
 
 package com.android.documentsui;
 
+import android.annotation.Nullable;
+
 import com.android.documentsui.model.DocumentInfo;
 import com.android.internal.util.Predicate;
 
 public class MimePredicate implements Predicate<DocumentInfo> {
     private final String[] mFilters;
 
+    private static final String APK_TYPE = "application/vnd.android.package-archive";
     /**
      * MIME types that are visual in nature. For example, they should always be
      * shown as thumbnails in list mode.
@@ -92,4 +95,8 @@
             return false;
         }
     }
+
+    public static boolean isApkType(@Nullable String mimeType) {
+        return APK_TYPE.equals(mimeType);
+    }
 }
diff --git a/packages/DocumentsUI/src/com/android/documentsui/NavigationView.java b/packages/DocumentsUI/src/com/android/documentsui/NavigationView.java
index 4cba135..c520204 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/NavigationView.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/NavigationView.java
@@ -220,17 +220,14 @@
                         .inflate(R.layout.item_subdir, parent, false);
             }
 
-            final ImageView subdir = (ImageView) convertView.findViewById(R.id.subdir);
             final TextView title = (TextView) convertView.findViewById(android.R.id.title);
             final DocumentInfo doc = getItem(position);
 
             if (position == 0) {
                 final RootInfo root = mEnv.getCurrentRoot();
                 title.setText(root.title);
-                subdir.setVisibility(View.GONE);
             } else {
                 title.setText(doc.displayName);
-                subdir.setVisibility(View.VISIBLE);
             }
 
             return convertView;
diff --git a/packages/DocumentsUI/src/com/android/documentsui/OpenExternalDirectoryActivity.java b/packages/DocumentsUI/src/com/android/documentsui/OpenExternalDirectoryActivity.java
index 27d6797..dc529ce 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/OpenExternalDirectoryActivity.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/OpenExternalDirectoryActivity.java
@@ -17,9 +17,18 @@
 package com.android.documentsui;
 
 import static android.os.Environment.isStandardDirectory;
+import static android.os.Environment.STANDARD_DIRECTORIES;
 import static android.os.storage.StorageVolume.EXTRA_DIRECTORY_NAME;
 import static android.os.storage.StorageVolume.EXTRA_STORAGE_VOLUME;
 import static com.android.documentsui.Shared.DEBUG;
+import static com.android.documentsui.Metrics.logInvalidScopedAccessRequest;
+import static com.android.documentsui.Metrics.logValidScopedAccessRequest;
+import static com.android.documentsui.Metrics.SCOPED_DIRECTORY_ACCESS_ALREADY_GRANTED;
+import static com.android.documentsui.Metrics.SCOPED_DIRECTORY_ACCESS_DENIED;
+import static com.android.documentsui.Metrics.SCOPED_DIRECTORY_ACCESS_ERROR;
+import static com.android.documentsui.Metrics.SCOPED_DIRECTORY_ACCESS_GRANTED;
+import static com.android.documentsui.Metrics.SCOPED_DIRECTORY_ACCESS_INVALID_ARGUMENTS;
+import static com.android.documentsui.Metrics.SCOPED_DIRECTORY_ACCESS_INVALID_DIRECTORY;
 
 import android.app.Activity;
 import android.app.ActivityManager;
@@ -73,6 +82,7 @@
         final Intent intent = getIntent();
         if (intent == null) {
             if (DEBUG) Log.d(TAG, "missing intent");
+            logInvalidScopedAccessRequest(this, SCOPED_DIRECTORY_ACCESS_INVALID_ARGUMENTS);
             setResult(RESULT_CANCELED);
             finish();
             return;
@@ -82,12 +92,14 @@
             if (DEBUG)
                 Log.d(TAG, "extra " + EXTRA_STORAGE_VOLUME + " is not a StorageVolume: "
                         + storageVolume);
+            logInvalidScopedAccessRequest(this, SCOPED_DIRECTORY_ACCESS_INVALID_ARGUMENTS);
             setResult(RESULT_CANCELED);
             finish();
             return;
         }
         final String directoryName = intent.getStringExtra(EXTRA_DIRECTORY_NAME);
         if (directoryName == null) {
+            logInvalidScopedAccessRequest(this, SCOPED_DIRECTORY_ACCESS_INVALID_ARGUMENTS);
             if (DEBUG) Log.d(TAG, "missing extra " + EXTRA_DIRECTORY_NAME + " on " + intent);
             setResult(RESULT_CANCELED);
             finish();
@@ -125,6 +137,7 @@
         } catch (IOException e) {
             Log.e(TAG, "Could not get canonical file for volume " + storageVolume.dump()
                     + " and directory " + directoryName);
+            logInvalidScopedAccessRequest(activity, SCOPED_DIRECTORY_ACCESS_ERROR);
             return false;
         }
         final StorageManager sm =
@@ -138,6 +151,7 @@
             if (DEBUG)
                 Log.d(TAG, "Directory '" + directory + "' is not standard (full path: '"
                         + file.getAbsolutePath() + "')");
+            logInvalidScopedAccessRequest(activity, SCOPED_DIRECTORY_ACCESS_INVALID_DIRECTORY);
             return false;
         }
 
@@ -159,6 +173,8 @@
         // Checks if the user has granted the permission already.
         final Intent intent = getIntentForExistingPermission(activity, file);
         if (intent != null) {
+            logValidScopedAccessRequest(activity, directory,
+                    SCOPED_DIRECTORY_ACCESS_ALREADY_GRANTED);
             activity.setResult(RESULT_OK, intent);
             activity.finish();
             return true;
@@ -166,12 +182,14 @@
 
         if (volumeLabel == null) {
             Log.e(TAG, "Could not get volume for " + file);
+            logInvalidScopedAccessRequest(activity, SCOPED_DIRECTORY_ACCESS_ERROR);
             return false;
         }
 
         // Gets the package label.
         final String appLabel = getAppLabel(activity);
         if (appLabel == null) {
+            // Error already logged.
             return false;
         }
 
@@ -198,6 +216,7 @@
         try {
             return pm.getApplicationLabel(pm.getApplicationInfo(packageName, 0)).toString();
         } catch (NameNotFoundException e) {
+            logInvalidScopedAccessRequest(activity, SCOPED_DIRECTORY_ACCESS_ERROR);
             Log.w(TAG, "Could not get label for package " + packageName);
             return null;
         }
@@ -217,18 +236,21 @@
         return volume.isVisibleForWrite(userId) && root.equals(path);
     }
 
-    private static Uri getGrantedUriPermission(ContentProviderClient provider, File file) {
+    private static Uri getGrantedUriPermission(Context context, ContentProviderClient provider,
+            File file) {
         // Calls ExternalStorageProvider to get the doc id for the file
         final Bundle bundle;
         try {
             bundle = provider.call("getDocIdForFileCreateNewDir", file.getPath(), null);
         } catch (RemoteException e) {
             Log.e(TAG, "Did not get doc id from External Storage provider for " + file, e);
+            logInvalidScopedAccessRequest(context, SCOPED_DIRECTORY_ACCESS_ERROR);
             return null;
         }
         final String docId = bundle == null ? null : bundle.getString("DOC_ID");
         if (docId == null) {
             Log.e(TAG, "Did not get doc id from External Storage provider for " + file);
+            logInvalidScopedAccessRequest(context, SCOPED_DIRECTORY_ACCESS_ERROR);
             return null;
         }
         Log.d(TAG, "doc id for " + file + ": " + docId);
@@ -242,9 +264,9 @@
         return uri;
     }
 
-    private static Intent createGrantedUriPermissionsIntent(ContentProviderClient provider,
-            File file) {
-        final Uri uri = getGrantedUriPermission(provider, file);
+    private static Intent createGrantedUriPermissionsIntent(Context context,
+            ContentProviderClient provider, File file) {
+        final Uri uri = getGrantedUriPermission(context, provider, file);
         return createGrantedUriPermissionsIntent(uri);
     }
 
@@ -261,7 +283,8 @@
     private static Intent getIntentForExistingPermission(OpenExternalDirectoryActivity activity,
             File file) {
         final String packageName = activity.getCallingPackage();
-        final Uri grantedUri = getGrantedUriPermission(activity.getExternalStorageClient(), file);
+        final Uri grantedUri =
+                getGrantedUriPermission(activity, activity.getExternalStorageClient(), file);
         if (DEBUG)
             Log.d(TAG, "checking if " + packageName + " already has permission for " + grantedUri);
         final ActivityManager am =
@@ -298,7 +321,7 @@
 
         @Override
         public Dialog onCreateDialog(Bundle savedInstanceState) {
-            final String folder = mFile.getName();
+            final String directory = mFile.getName();
             final Activity activity = getActivity();
             final OnClickListener listener = new OnClickListener() {
 
@@ -306,12 +329,16 @@
                 public void onClick(DialogInterface dialog, int which) {
                     Intent intent = null;
                     if (which == DialogInterface.BUTTON_POSITIVE) {
-                        intent = createGrantedUriPermissionsIntent(
+                        intent = createGrantedUriPermissionsIntent(mActivity,
                                 mActivity.getExternalStorageClient(), mFile);
                     }
                     if (which == DialogInterface.BUTTON_NEGATIVE || intent == null) {
+                        logValidScopedAccessRequest(activity, directory,
+                                SCOPED_DIRECTORY_ACCESS_DENIED);
                         activity.setResult(RESULT_CANCELED);
                     } else {
+                        logValidScopedAccessRequest(activity, directory,
+                                SCOPED_DIRECTORY_ACCESS_GRANTED);
                         activity.setResult(RESULT_OK, intent);
                     }
                     activity.finish();
@@ -320,7 +347,7 @@
 
             final CharSequence message = TextUtils
                     .expandTemplate(
-                            getText(R.string.open_external_dialog_request), mAppLabel, folder,
+                            getText(R.string.open_external_dialog_request), mAppLabel, directory,
                             mVolumeLabel);
             return new AlertDialog.Builder(activity, R.style.AlertDialogTheme)
                     .setMessage(message)
@@ -333,6 +360,7 @@
         public void onCancel(DialogInterface dialog) {
             super.onCancel(dialog);
             final Activity activity = getActivity();
+            logValidScopedAccessRequest(activity, mFile.getName(), SCOPED_DIRECTORY_ACCESS_DENIED);
             activity.setResult(RESULT_CANCELED);
             activity.finish();
         }
diff --git a/packages/DocumentsUI/src/com/android/documentsui/PickFragment.java b/packages/DocumentsUI/src/com/android/documentsui/PickFragment.java
index 32543c8..933506c 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/PickFragment.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/PickFragment.java
@@ -19,7 +19,6 @@
 import static com.android.documentsui.services.FileOperationService.OPERATION_DELETE;
 import static com.android.documentsui.services.FileOperationService.OPERATION_MOVE;
 import static com.android.documentsui.services.FileOperationService.OPERATION_UNKNOWN;
-import static com.android.internal.util.Preconditions.checkArgument;
 
 import android.app.Activity;
 import android.app.Fragment;
@@ -101,7 +100,8 @@
      */
     public void setPickTarget(
             int action, @OpType int copyOperationSubType, DocumentInfo pickTarget) {
-        checkArgument(copyOperationSubType != OPERATION_DELETE);
+        assert(copyOperationSubType != OPERATION_DELETE);
+
         mAction = action;
         mCopyOperationSubType = copyOperationSubType;
         mPickTarget = pickTarget;
diff --git a/packages/DocumentsUI/src/com/android/documentsui/ProviderExecutor.java b/packages/DocumentsUI/src/com/android/documentsui/ProviderExecutor.java
index b0e332f..8145edc 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/ProviderExecutor.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/ProviderExecutor.java
@@ -19,7 +19,6 @@
 import android.os.AsyncTask;
 
 import com.android.internal.annotations.GuardedBy;
-import com.android.internal.util.Preconditions;
 
 import java.lang.ref.WeakReference;
 import java.util.ArrayList;
@@ -85,7 +84,7 @@
     private Executor mNonPreemptingExecutor = new Executor() {
         @Override
         public void execute(Runnable command) {
-            Preconditions.checkNotNull(command);
+            assert(command != null);
             mQueue.add(command);
         }
     };
@@ -93,7 +92,7 @@
     @Override
     public void execute(Runnable command) {
         preempt();
-        Preconditions.checkNotNull(command);
+        assert(command != null);
         mQueue.add(command);
     }
 
diff --git a/packages/DocumentsUI/src/com/android/documentsui/QuickViewIntentBuilder.java b/packages/DocumentsUI/src/com/android/documentsui/QuickViewIntentBuilder.java
index a77a9b3..8fcd9d1 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/QuickViewIntentBuilder.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/QuickViewIntentBuilder.java
@@ -113,8 +113,8 @@
     }
 
     private int collectViewableUris(ArrayList<Uri> uris) {
-        final List<String> siblingIds = mModel.getModelIds();
-        uris.ensureCapacity(siblingIds.size());
+        final String[] siblingIds = mModel.getModelIds();
+        uris.ensureCapacity(siblingIds.length);
 
         int documentLocation = 0;
         Cursor cursor;
@@ -124,8 +124,8 @@
         Uri uri;
 
         // Cursor's are not guaranteed to be immutable. Hence, traverse it only once.
-        for (int i = 0; i < siblingIds.size(); i++) {
-            cursor = mModel.getItem(siblingIds.get(i));
+        for (int i = 0; i < siblingIds.length; i++) {
+            cursor = mModel.getItem(siblingIds[i]);
 
             mimeType = getCursorString(cursor, Document.COLUMN_MIME_TYPE);
             if (Document.MIME_TYPE_DIR.equals(mimeType)) {
diff --git a/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java b/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java
index 216509d..2b7294a 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java
@@ -17,8 +17,6 @@
 package com.android.documentsui;
 
 import static com.android.documentsui.Shared.DEBUG;
-import static com.android.documentsui.Shared.TAG;
-import static com.android.internal.util.Preconditions.checkState;
 
 import android.content.ContentProviderClient;
 import android.content.ContentResolver;
@@ -41,7 +39,6 @@
 
 import com.android.documentsui.model.RootInfo;
 import com.android.internal.annotations.GuardedBy;
-import com.android.internal.util.Preconditions;
 
 import com.google.common.collect.ArrayListMultimap;
 import com.google.common.collect.Multimap;
@@ -64,6 +61,8 @@
     public static final Uri sNotificationUri = Uri.parse(
             "content://com.android.documentsui.roots/");
 
+    private static final String TAG = "RootsCache";
+
     private final Context mContext;
     private final ContentObserver mObserver;
     private OnCacheUpdateListener mCacheUpdateListener;
@@ -90,7 +89,8 @@
                 // Special root for recents
                 derivedIcon = R.drawable.ic_root_recent;
                 derivedType = RootInfo.TYPE_RECENTS;
-                flags = Root.FLAG_LOCAL_ONLY | Root.FLAG_SUPPORTS_IS_CHILD;
+                flags = Root.FLAG_LOCAL_ONLY | Root.FLAG_SUPPORTS_IS_CHILD
+                        | Root.FLAG_SUPPORTS_CREATE;
                 title = mContext.getString(R.string.root_recent);
                 availableBytes = -1;
             }};
@@ -116,16 +116,22 @@
      * Gather roots from all known storage providers.
      */
     public void updateAsync() {
-        // Verifying an assumption about the recents root being immutable.
-        if (DEBUG) {
-            checkState(mRecentsRoot.authority == null);
-            checkState(mRecentsRoot.rootId == null);
-            checkState(mRecentsRoot.derivedIcon == R.drawable.ic_root_recent);
-            checkState(mRecentsRoot.derivedType == RootInfo.TYPE_RECENTS);
-            checkState(mRecentsRoot.flags == (Root.FLAG_LOCAL_ONLY | Root.FLAG_SUPPORTS_IS_CHILD));
-            checkState(mRecentsRoot.title == mContext.getString(R.string.root_recent));
-            checkState(mRecentsRoot.availableBytes == -1);
-        }
+
+        // NOTE: This method is called when the UI language changes.
+        // For that reason we upadte our RecentsRoot to reflect
+        // the current language.
+        mRecentsRoot.title = mContext.getString(R.string.root_recent);
+
+        // Nothing else about the root should ever change.
+        assert(mRecentsRoot.authority == null);
+        assert(mRecentsRoot.rootId == null);
+        assert(mRecentsRoot.derivedIcon == R.drawable.ic_root_recent);
+        assert(mRecentsRoot.derivedType == RootInfo.TYPE_RECENTS);
+        assert(mRecentsRoot.flags == (Root.FLAG_LOCAL_ONLY
+                | Root.FLAG_SUPPORTS_IS_CHILD
+                | Root.FLAG_SUPPORTS_CREATE));
+        assert(mRecentsRoot.availableBytes == -1);
+
         new UpdateTask().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
     }
 
@@ -412,45 +418,64 @@
     static List<RootInfo> getMatchingRoots(Collection<RootInfo> roots, State state) {
         final List<RootInfo> matching = new ArrayList<>();
         for (RootInfo root : roots) {
-            // Exclude read-only devices when creating
-            if (state.action == State.ACTION_CREATE && !root.supportsCreate()) continue;
-            if (state.action == State.ACTION_PICK_COPY_DESTINATION
-                    && !root.supportsCreate()) continue;
-            // Exclude roots that don't support directory picking
-            if (state.action == State.ACTION_OPEN_TREE && !root.supportsChildren()) continue;
-            // Exclude advanced devices when not requested
-            if (!state.showAdvanced && root.isAdvanced()) continue;
-            // Exclude non-local devices when local only
-            if (state.localOnly && !root.isLocalOnly()) continue;
-            // Exclude downloads roots as it doesn't support directory creation (actually
-            // we just don't show them).
-            // TODO: Add flag to check the root supports directory creation.
-            if (state.directoryCopy && !root.isDownloads()) continue;
 
-            // Only show empty roots when creating, or in browse mode.
-            if (root.isEmpty() && (state.action == State.ACTION_OPEN
-                    || state.action == State.ACTION_GET_CONTENT)) {
-                if (DEBUG) Log.i(TAG, "Skipping empty root: " + root);
+            if (DEBUG) Log.d(TAG, "Evaluating " + root);
+
+            if (state.action == State.ACTION_CREATE && !root.supportsCreate()) {
+                if (DEBUG) Log.d(TAG, "Excluding read-only root because: ACTION_CREATE.");
                 continue;
             }
 
-            // Only include roots that serve requested content
+            if (state.action == State.ACTION_PICK_COPY_DESTINATION
+                    && !root.supportsCreate()) {
+                if (DEBUG) Log.d(
+                        TAG, "Excluding read-only root because: ACTION_PICK_COPY_DESTINATION.");
+                continue;
+            }
+
+            if (state.action == State.ACTION_OPEN_TREE && !root.supportsChildren()) {
+                if (DEBUG) Log.d(
+                        TAG, "Excluding root !supportsChildren because: ACTION_OPEN_TREE.");
+                continue;
+            }
+
+            if (state.localOnly && !root.isLocalOnly()) {
+                if (DEBUG) Log.d(TAG, "Excluding root because: unwanted non-local device.");
+                continue;
+            }
+
+            if (state.directoryCopy && root.isDownloads()) {
+                if (DEBUG) Log.d(
+                        TAG, "Excluding downloads root because: unsupported directory copy.");
+                continue;
+            }
+
+            if (state.action == State.ACTION_OPEN && root.isEmpty()) {
+                if (DEBUG) Log.d(TAG, "Excluding empty root because: ACTION_OPEN.");
+                continue;
+            }
+
+            if (state.action == State.ACTION_GET_CONTENT && root.isEmpty()) {
+                if (DEBUG) Log.d(TAG, "Excluding empty root because: ACTION_GET_CONTENT.");
+                continue;
+            }
+
             final boolean overlap =
                     MimePredicate.mimeMatches(root.derivedMimeTypes, state.acceptMimes) ||
                     MimePredicate.mimeMatches(state.acceptMimes, root.derivedMimeTypes);
             if (!overlap) {
-                continue;
-            }
-
-            // Exclude roots from the calling package.
-            if (state.excludedAuthorities.contains(root.authority)) {
                 if (DEBUG) Log.d(
-                        TAG, "Excluding root " + root.authority + " from calling package.");
+                        TAG, "Excluding root because: unsupported content types > "
+                        + state.acceptMimes);
                 continue;
             }
 
-            if (DEBUG) Log.d(
-                    TAG, "Including root " + root + " in roots list.");
+            if (state.excludedAuthorities.contains(root.authority)) {
+                if (DEBUG) Log.d(TAG, "Excluding root because: owned by calling package.");
+                continue;
+            }
+
+            if (DEBUG) Log.d(TAG, "Including " + root);
             matching.add(root);
         }
         return matching;
diff --git a/packages/DocumentsUI/src/com/android/documentsui/SearchViewManager.java b/packages/DocumentsUI/src/com/android/documentsui/SearchViewManager.java
index 0496862..63dc2ee 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/SearchViewManager.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/SearchViewManager.java
@@ -61,7 +61,8 @@
     }
 
     public void install(DocumentsToolbar actionBar) {
-        assert (mActionBar == null);
+        // assert(mActionBar == null);
+
         mActionBar = actionBar;
         mMenu = actionBar.getSearchMenu();
         mView = (SearchView) mMenu.getActionView();
@@ -145,8 +146,6 @@
 
     private void onSearchExpanded() {
         mSearchExpanded = true;
-        mView.setBackgroundColor(
-                mView.getResources().getColor(R.color.menu_search_background, null));
     }
 
     boolean isSearching() {
@@ -179,9 +178,6 @@
             return false;
         }
 
-        mView.setBackgroundColor(
-                mView.getResources().getColor(android.R.color.transparent, null));
-
         // Refresh the directory if a search was done
         if (mCurrentSearch != null) {
             mCurrentSearch = null;
diff --git a/packages/DocumentsUI/src/com/android/documentsui/Shared.java b/packages/DocumentsUI/src/com/android/documentsui/Shared.java
index a288fe8..26900a7 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/Shared.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/Shared.java
@@ -17,9 +17,12 @@
 package com.android.documentsui;
 
 import android.content.Context;
+import android.content.res.Configuration;
 import android.text.TextUtils;
 import android.text.format.DateUtils;
 import android.text.format.Time;
+import android.view.WindowManager;
+import android.app.AlertDialog;
 
 import java.text.Collator;
 import java.util.ArrayList;
@@ -28,6 +31,10 @@
 /** @hide */
 public final class Shared {
 
+    public static final String TAG = "Documents";
+
+    public static final boolean DEBUG = true;
+
     /** Intent action name to pick a copy destination. */
     public static final String ACTION_PICK_COPY_DESTINATION =
             "com.android.documentsui.PICK_COPY_DESTINATION";
@@ -79,9 +86,6 @@
      */
     public static final String EXTRA_IGNORE_STATE = "ignoreState";
 
-    public static final boolean DEBUG = true;
-    public static final String TAG = "Documents";
-
 
     /**
      * String prefix used to indicate the document is a directory.
@@ -154,4 +158,15 @@
 
         return sCollator.compare(lhs, rhs);
     }
+
+    public static boolean isHardwareKeyboardAvailable(Context context) {
+        return context.getResources().getConfiguration().keyboard != Configuration.KEYBOARD_NOKEYS;
+    }
+
+    public static void ensureKeyboardPresent(Context context, AlertDialog dialog) {
+        if (!isHardwareKeyboardAvailable(context)) {
+            dialog.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE);
+        }
+    }
+
 }
diff --git a/packages/DocumentsUI/src/com/android/documentsui/Snackbars.java b/packages/DocumentsUI/src/com/android/documentsui/Snackbars.java
index 48c1a73..b4d7971 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/Snackbars.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/Snackbars.java
@@ -16,8 +16,6 @@
 
 package com.android.documentsui;
 
-import static com.android.internal.util.Preconditions.checkNotNull;
-
 import android.app.Activity;
 import android.support.design.widget.Snackbar;
 import android.view.View;
@@ -26,12 +24,13 @@
     private Snackbars() {}
 
     public static final Snackbar makeSnackbar(Activity activity, int messageId, int duration) {
-        return Snackbars.makeSnackbar(activity, activity.getResources().getText(messageId), duration);
+        return Snackbars.makeSnackbar(
+                activity, activity.getResources().getText(messageId), duration);
     }
 
-    public static final Snackbar makeSnackbar(Activity activity, CharSequence message, int duration)
-    {
-        final View view = checkNotNull(activity.findViewById(R.id.coordinator_layout));
+    public static final Snackbar makeSnackbar(
+            Activity activity, CharSequence message, int duration) {
+        final View view = activity.findViewById(R.id.coordinator_layout);
         return Snackbar.make(view, message, duration);
     }
 }
diff --git a/packages/DocumentsUI/src/com/android/documentsui/State.java b/packages/DocumentsUI/src/com/android/documentsui/State.java
index 62f9ea7..16b7660 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/State.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/State.java
@@ -43,13 +43,15 @@
 
     private static final String TAG = "State";
 
-    public static final int ACTION_OPEN = 1;
-    public static final int ACTION_CREATE = 2;
-    public static final int ACTION_GET_CONTENT = 3;
-    public static final int ACTION_OPEN_TREE = 4;
-    public static final int ACTION_MANAGE = 5;
-    public static final int ACTION_BROWSE = 6;
-    public static final int ACTION_PICK_COPY_DESTINATION = 8;
+    // File manager and related private picking activity.
+    public static final int ACTION_BROWSE = 1;
+    public static final int ACTION_PICK_COPY_DESTINATION = 2;
+
+    // All public picking activities
+    public static final int ACTION_OPEN = 3;
+    public static final int ACTION_CREATE = 4;
+    public static final int ACTION_GET_CONTENT = 5;
+    public static final int ACTION_OPEN_TREE = 6;
 
     @IntDef(flag = true, value = {
             MODE_UNKNOWN,
@@ -82,9 +84,11 @@
     public boolean forceSize;
     public boolean showSize;
     public boolean localOnly;
-    public boolean forceAdvanced;
-    public boolean showAdvanced;
     public boolean restored;
+    /*
+     * Indicates handler was an external app, like photos.
+     */
+    public boolean external;
 
     // Indicates that a copy operation (or move) includes a directory.
     // Why? Directory creation isn't supported by some roots (like Downloads).
@@ -181,9 +185,8 @@
         out.writeInt(forceSize ? 1 : 0);
         out.writeInt(showSize ? 1 : 0);
         out.writeInt(localOnly ? 1 : 0);
-        out.writeInt(forceAdvanced ? 1 : 0);
-        out.writeInt(showAdvanced ? 1 : 0);
         out.writeInt(restored ? 1 : 0);
+        out.writeInt(external ? 1 : 0);
         DurableUtils.writeToParcel(out, stack);
         out.writeMap(dirState);
         out.writeParcelable(selectedDocuments, 0);
@@ -211,9 +214,8 @@
             state.forceSize = in.readInt() != 0;
             state.showSize = in.readInt() != 0;
             state.localOnly = in.readInt() != 0;
-            state.forceAdvanced = in.readInt() != 0;
-            state.showAdvanced = in.readInt() != 0;
             state.restored = in.readInt() != 0;
+            state.external = in.readInt() != 0;
             DurableUtils.readFromParcel(in, state.stack);
             in.readMap(state.dirState, loader);
             state.selectedDocuments = in.readParcelable(loader);
diff --git a/packages/DocumentsUI/src/com/android/documentsui/dirlist/DirectoryFragment.java b/packages/DocumentsUI/src/com/android/documentsui/dirlist/DirectoryFragment.java
index 90c2d1b..95aa067 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/dirlist/DirectoryFragment.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/dirlist/DirectoryFragment.java
@@ -17,27 +17,24 @@
 package com.android.documentsui.dirlist;
 
 import static com.android.documentsui.Shared.DEBUG;
-import static com.android.documentsui.State.ACTION_MANAGE;
 import static com.android.documentsui.State.MODE_GRID;
 import static com.android.documentsui.State.MODE_LIST;
 import static com.android.documentsui.State.SORT_ORDER_UNKNOWN;
 import static com.android.documentsui.model.DocumentInfo.getCursorInt;
 import static com.android.documentsui.model.DocumentInfo.getCursorString;
-import static com.android.internal.util.Preconditions.checkNotNull;
-import static com.android.internal.util.Preconditions.checkState;
-import static com.google.common.base.Preconditions.checkArgument;
 
 import android.annotation.IntDef;
 import android.annotation.StringRes;
 import android.app.Activity;
 import android.app.ActivityManager;
+import android.app.AlertDialog;
 import android.app.Fragment;
 import android.app.FragmentManager;
 import android.app.FragmentTransaction;
 import android.app.LoaderManager.LoaderCallbacks;
 import android.content.ClipData;
-import android.content.ContentResolver;
 import android.content.Context;
+import android.content.DialogInterface;
 import android.content.Intent;
 import android.content.Loader;
 import android.database.Cursor;
@@ -66,6 +63,7 @@
 import android.view.ActionMode;
 import android.view.DragEvent;
 import android.view.GestureDetector;
+import android.view.HapticFeedbackConstants;
 import android.view.KeyEvent;
 import android.view.LayoutInflater;
 import android.view.Menu;
@@ -109,6 +107,7 @@
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
+import java.util.Objects;
 
 /**
  * Display the documents inside a single directory.
@@ -145,13 +144,8 @@
     public @interface RequestCode {}
     public static final int REQUEST_COPY_DESTINATION = 1;
 
-    static final boolean DEBUG_ENABLE_DND = true;
-
     private static final String TAG = "DirectoryFragment";
     private static final int LOADER_ID = 42;
-    private static final int DELETE_UNDO_TIMEOUT = 5000;
-    private static final int DELETE_JOB_DELAY = 5500;
-    private static final int EMPTY_REVEAL_DURATION = 250;
 
     private Model mModel;
     private MultiSelectManager mSelectionManager;
@@ -174,6 +168,7 @@
     private GridLayoutManager mLayout;
     private int mColumnCount = 1;  // This will get updated when layout changes.
 
+    private LayoutInflater mInflater;
     private MessageBar mMessageBar;
     private View mProgressBar;
 
@@ -188,13 +183,12 @@
     @Override
     public View onCreateView(
             LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
+        mInflater = inflater;
         final View view = inflater.inflate(R.layout.fragment_directory, container, false);
 
         mMessageBar = MessageBar.create(getChildFragmentManager());
         mProgressBar = view.findViewById(R.id.progressbar);
-
         mEmptyView = view.findViewById(android.R.id.empty);
-
         mRecView = (RecyclerView) view.findViewById(R.id.dir_list);
         mRecView.setRecyclerListener(
                 new RecyclerListener() {
@@ -206,17 +200,16 @@
 
         mRecView.setItemAnimator(new DirectoryItemAnimator(getActivity()));
 
-        // TODO: Add a divider between views (which might use RecyclerView.ItemDecoration).
-        if (DEBUG_ENABLE_DND) {
-            setupDragAndDropOnDirectoryView(mRecView);
-        }
+        // Make the recycler and the empty views responsive to drop events.
+        mRecView.setOnDragListener(mOnDragListener);
+        mEmptyView.setOnDragListener(mOnDragListener);
 
         return view;
     }
 
     @Override
     public void onDestroyView() {
-        super.onDestroyView();
+        mSelectionManager.clearSelection();
 
         // Cancel any outstanding thumbnail requests
         final int count = mRecView.getChildCount();
@@ -224,6 +217,8 @@
             final View view = mRecView.getChildAt(i);
             cancelThumbnailTask(view);
         }
+
+        super.onDestroyView();
     }
 
     @Override
@@ -286,16 +281,6 @@
         mTuner = FragmentTuner.pick(getContext(), state);
         mClipper = new DocumentClipper(context);
 
-        boolean hideGridTitles;
-        if (mType == TYPE_RECENT_OPEN) {
-            // Hide titles when showing recents for picking images/videos
-            hideGridTitles = MimePredicate.mimeMatches(
-                    MimePredicate.VISUAL_MIMES, state.acceptMimes);
-        } else {
-            hideGridTitles = (mDocument != null) && mDocument.isGridTitlesHidden();
-        }
-        GridDocumentHolder.setHideTitles(hideGridTitles);
-
         final ActivityManager am = (ActivityManager) context.getSystemService(
                 Context.ACTIVITY_SERVICE);
         boolean svelte = am.isLowRamDevice() && (mType == TYPE_RECENT_OPEN);
@@ -309,12 +294,15 @@
     public void onSaveInstanceState(Bundle outState) {
         super.onSaveInstanceState(outState);
 
+        mSelectionManager.getSelection(mSelection);
+
         outState.putInt(Shared.EXTRA_TYPE, mType);
         outState.putParcelable(Shared.EXTRA_ROOT, mRoot);
         outState.putParcelable(Shared.EXTRA_DOC, mDocument);
         outState.putString(Shared.EXTRA_QUERY, mQuery);
-        outState.putParcelable(Shared.EXTRA_SELECTION, mSelectionManager.getSelection());
+        outState.putParcelable(Shared.EXTRA_SELECTION, mSelection);
         outState.putBoolean(Shared.EXTRA_SEARCH_MODE, mSearchMode);
+
     }
 
     @Override
@@ -359,7 +347,9 @@
 
     private boolean handleViewItem(String id) {
         final Cursor cursor = mModel.getItem(id);
-        checkNotNull(cursor, "Cursor cannot be null.");
+
+        assert(cursor != null);
+
         final String docMimeType = getCursorString(cursor, Document.COLUMN_MIME_TYPE);
         final int docFlags = getCursorInt(cursor, Document.COLUMN_FLAGS);
         if (mTuner.isDocumentEnabled(docMimeType, docFlags)) {
@@ -430,7 +420,8 @@
         int cellMargin = 2 * getResources().getDimensionPixelSize(R.dimen.grid_item_margin);
         int viewPadding = mRecView.getPaddingLeft() + mRecView.getPaddingRight();
 
-        checkState(mRecView.getWidth() > 0);
+        assert(mRecView.getWidth() > 0);
+
         int columnCount = Math.max(1,
                 (mRecView.getWidth() - viewPadding) / (cellWidth + cellMargin));
 
@@ -471,7 +462,9 @@
         public boolean onBeforeItemStateChange(String modelId, boolean selected) {
             if (selected) {
                 final Cursor cursor = mModel.getItem(modelId);
-                checkNotNull(cursor, "Cursor cannot be null.");
+
+                assert(cursor != null);
+
                 final String docMimeType = getCursorString(cursor, Document.COLUMN_MIME_TYPE);
                 final int docFlags = getCursorInt(cursor, Document.COLUMN_FLAGS);
                 return mTuner.canSelectType(docMimeType, docFlags);
@@ -524,7 +517,8 @@
             getActivity().getWindow().setStatusBarColor(color.data);
 
             if (mActionMode != null) {
-                mActionMode.setTitle(String.valueOf(mSelected.size()));
+                mActionMode.setTitle(Shared.getQuantityString(getActivity(),
+                        R.plurals.elements_selected, mSelected.size()));
             }
         }
 
@@ -542,6 +536,8 @@
 
         @Override
         public boolean onCreateActionMode(ActionMode mode, Menu menu) {
+            mRecView.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
+
             int size = mSelectionManager.getSelection().size();
             mode.getMenuInflater().inflate(R.menu.mode_directory, menu);
             mode.setTitle(TextUtils.formatSelectedCount(size));
@@ -564,7 +560,7 @@
         }
 
         private void updateActionMenu() {
-            checkNotNull(mMenu);
+            assert(mMenu != null);
 
             // Delegate update logic to our owning action, since specialized logic is desired.
             mTuner.updateActionMenu(mMenu, mType, canDeleteSelection(), canRenameSelection());
@@ -584,18 +580,17 @@
 
                 case R.id.menu_share:
                     shareDocuments(selection);
-                    mode.finish();
                     return true;
 
                 case R.id.menu_delete:
-                    // Exit selection mode first, so we avoid deselecting deleted documents.
-                    mode.finish();
-                    deleteDocuments(selection);
+                    // Pass mode along to the delete function so it can
+                    // end action mode when documents are deleted.
+                    // It won't end action mode if user cancels the delete.
+                    deleteDocuments(selection, mode);
                     return true;
 
                 case R.id.menu_copy_to:
                     transferDocuments(selection, FileOperationService.OPERATION_COPY);
-                    mode.finish();
                     return true;
 
                 case R.id.menu_move_to:
@@ -613,8 +608,10 @@
                     return true;
 
                 case R.id.menu_rename:
-                    renameDocuments(selection);
+                    // Exit selection mode first, so we avoid deselecting deleted
+                    // (renamed) documents.
                     mode.finish();
+                    renameDocuments(selection);
                     return true;
 
                 default:
@@ -698,52 +695,56 @@
         }.execute(selected);
     }
 
-    private void deleteDocuments(final Selection selected) {
+    private void deleteDocuments(final Selection selected, final ActionMode mode) {
+        assert(!selected.isEmpty());
 
-        checkArgument(!selected.isEmpty());
         final DocumentInfo srcParent = getDisplayState().stack.peek();
         new GetDocumentsTask() {
             @Override
-            void onDocumentsReady(List<DocumentInfo> docs) {
-                // Hide the files in the UI.
-                final SparseArray<String> hidden = mAdapter.hide(selected.getAll());
+            void onDocumentsReady(final List<DocumentInfo> docs) {
 
-                checkState(DELETE_JOB_DELAY > DELETE_UNDO_TIMEOUT);
-                String operationId = FileOperations.delete(
-                        getActivity(), docs, srcParent, getDisplayState().stack,
-                        DELETE_JOB_DELAY);
-                showDeleteSnackbar(hidden, operationId);
-            }
-        }.execute(selected);
-    }
+                TextView message =
+                        (TextView) mInflater.inflate(R.layout.dialog_delete_confirmation, null);
+                message.setText(
+                        Shared.getQuantityString(
+                                getActivity(),
+                                R.plurals.delete_confirmation_message,
+                                docs.size()));
 
-    private void showDeleteSnackbar(final SparseArray<String> hidden, final String jobId) {
-
-        Context context = getActivity();
-        String message = Shared.getQuantityString(context, R.plurals.deleting, hidden.size());
-
-        // Show a snackbar informing the user that files will be deleted, and give them an option to
-        // cancel.
-        final Activity activity = getActivity();
-        Snackbars.makeSnackbar(activity, message, DELETE_UNDO_TIMEOUT)
-                .setAction(
-                        R.string.undo,
-                        new View.OnClickListener() {
-                            @Override
-                            public void onClick(View view) {}
-                        })
-                .setCallback(
-                        new Snackbar.Callback() {
-                            @Override
-                            public void onDismissed(Snackbar snackbar, int event) {
-                                if (event == Snackbar.Callback.DISMISS_EVENT_ACTION) {
-                                    // If the delete was cancelled, just unhide the files.
-                                    FileOperations.cancel(activity, jobId);
-                                    mAdapter.unhide(hidden);
-                                }
+                // This "insta-hides" files that are being deleted, because
+                // the delete operation may be not execute immediately (it
+                // may be queued up on the FileOperationService.)
+                // To hide the files locally, we call the hide method on the adapter
+                // ...which a live object...cannot be parceled.
+                // For that reason, for now, we implement this dialog NOT
+                // as a fragment (which can survive rotation and have its own state),
+                // but as a simple runtime dialog. So rotating a device with an
+                // active delete dialog...results in that dialog disappearing.
+                // We can do better, but don't have cycles for it now.
+                new AlertDialog.Builder(getActivity())
+                    .setView(message)
+                    .setPositiveButton(
+                         android.R.string.yes,
+                         new DialogInterface.OnClickListener() {
+                            public void onClick(DialogInterface dialog, int id) {
+                                // Finish selection mode first which clears selection so we
+                                // don't end up trying to deselect deleted documents.
+                                // This is done here, rather in the onActionItemClicked
+                                // so we can avoid de-selecting items in the case where
+                                // the user cancels the delete.
+                                mode.finish();
+                                // Hide the files in the UI...since the operation
+                                // might be queued up on FileOperationService.
+                                // We're walking a line here.
+                                mAdapter.hide(selected.getAll());
+                                FileOperations.delete(
+                                        getActivity(), docs, srcParent, getDisplayState().stack);
                             }
                         })
-                .show();
+                    .setNegativeButton(android.R.string.no, null)
+                    .show();
+            }
+        }.execute(selected);
     }
 
     private void transferDocuments(final Selection selected, final @OpType int mode) {
@@ -795,7 +796,7 @@
     private void renameDocuments(Selection selected) {
         // Batch renaming not supported
         // Rename option is only available in menu when 1 document selected
-        checkArgument(selected.size() == 1);
+        assert(selected.size() == 1);
 
         new GetDocumentsTask() {
             @Override
@@ -813,9 +814,7 @@
 
     @Override
     public void onBindDocumentHolder(DocumentHolder holder, Cursor cursor) {
-        if (DEBUG_ENABLE_DND) {
-            setupDragAndDropOnDocumentView(holder.itemView, cursor);
-        }
+        setupDragAndDropOnDocumentView(holder.itemView, cursor);
     }
 
     @Override
@@ -910,7 +909,8 @@
     }
 
     private void copyFromClipData(final ClipData clipData, final DocumentInfo destination) {
-        checkNotNull(clipData);
+        assert(clipData != null);
+
         new AsyncTask<Void, Void, List<DocumentInfo>>() {
 
             @Override
@@ -952,25 +952,6 @@
         FileOperations.copy(getActivity(), docs, tmpStack);
     }
 
-    private ClipData getClipDataFromDocuments(List<DocumentInfo> docs) {
-        Context context = getActivity();
-        final ContentResolver resolver = context.getContentResolver();
-        ClipData clipData = null;
-        for (DocumentInfo doc : docs) {
-            final Uri uri = DocumentsContract.buildDocumentUri(doc.authority, doc.documentId);
-            if (clipData == null) {
-                // TODO: figure out what this string should be.
-                // Currently it is not displayed anywhere in the UI, but this might change.
-                final String label = "";
-                clipData = ClipData.newUri(resolver, label, uri);
-            } else {
-                // TODO: update list of mime types in ClipData.
-                clipData.addItem(new ClipData.Item(uri));
-            }
-        }
-        return clipData;
-    }
-
     public void copySelectedToClipboard() {
         Selection selection = mSelectionManager.getSelection(new Selection());
         if (!selection.isEmpty()) {
@@ -980,7 +961,7 @@
     }
 
     void copySelectionToClipboard(Selection selection) {
-        checkArgument(!selection.isEmpty());
+        assert(!selection.isEmpty());
         new GetDocumentsTask() {
             @Override
             void onDocumentsReady(List<DocumentInfo> docs) {
@@ -1039,11 +1020,6 @@
         mFocusManager.restoreLastFocus();
     }
 
-    private void setupDragAndDropOnDirectoryView(View view) {
-        // Listen for drops on non-directory items and empty space.
-        view.setOnDragListener(mOnDragListener);
-    }
-
     private void setupDragAndDropOnDocumentView(View view, Cursor cursor) {
         final String docMimeType = getCursorString(cursor, Document.COLUMN_MIME_TYPE);
         if (Document.MIME_TYPE_DIR.equals(docMimeType)) {
@@ -1052,6 +1028,7 @@
             view.setOnDragListener(mOnDragListener);
         }
 
+        // Make all items draggable.
         view.setOnLongClickListener(mDragHelper);
     }
 
@@ -1072,27 +1049,47 @@
                     return true;
 
                 case DragEvent.ACTION_DRAG_LOCATION:
+                    return true;
+
                 case DragEvent.ACTION_DRAG_ENDED:
+                    if (event.getResult()) {
+                        // Exit selection mode if the drop was handled.
+                        mSelectionManager.clearSelection();
+                    }
                     return true;
 
                 case DragEvent.ACTION_DROP:
-                    String dstId = getModelId(v);
-                    DocumentInfo dstDir = null;
-                    if (dstId != null) {
-                        Cursor dstCursor = mModel.getItem(dstId);
-                        checkNotNull(dstCursor, "Cursor cannot be null.");
-                        dstDir = DocumentInfo.fromDirectoryCursor(dstCursor);
-                        // TODO: Do not drop into the directory where the documents came from.
-                    }
-                    copyFromClipData(event.getClipData(), dstDir);
-                    // Clean up the UI.
+                    // After a drop event, always stop highlighting the target.
                     setDropTargetHighlight(v, false);
-                    mSelectionManager.clearSelection();
+                    // Don't copy from the cwd into the cwd. Note: this currently doesn't work for
+                    // multi-window drag, because localState isn't carried over from one process to
+                    // another.
+                    Object src = event.getLocalState();
+                    DocumentInfo dst = getDestination(v);
+                    if (Objects.equals(src, dst)) {
+                        return false;
+                    }
+                    copyFromClipData(event.getClipData(), dst);
                     return true;
             }
             return false;
         }
 
+        private DocumentInfo getDestination(View v) {
+            String id = getModelId(v);
+            if (id != null) {
+                Cursor dstCursor = mModel.getItem(id);
+                assert(dstCursor != null);
+                return DocumentInfo.fromDirectoryCursor(dstCursor);
+            }
+
+            if (v == mRecView || v == mEmptyView) {
+                return getDisplayState().stack.peek();
+            }
+
+            return null;
+        }
+
         private void setDropTargetHighlight(View v, boolean highlight) {
             // Note: use exact comparison - this code is searching for views which are children of
             // the RecyclerView instance in the UI.
@@ -1155,10 +1152,11 @@
         }
 
         final Cursor cursor = mModel.getItem(modelId);
-        checkNotNull(cursor, "Cursor cannot be null.");
-        final DocumentInfo doc = DocumentInfo.fromDirectoryCursor(cursor);
 
-        return Lists.newArrayList(doc);
+        assert(cursor != null);
+
+        return Lists.newArrayList(
+                DocumentInfo.fromDirectoryCursor(cursor));
     }
 
     private Drawable getDragShadowIcon(List<DocumentInfo> docs) {
@@ -1308,6 +1306,11 @@
                 showDirectory();
                 mAdapter.notifyDataSetChanged();
             }
+
+            if (!model.isLoading()) {
+                ((BaseActivity) getActivity()).notifyDirectoryLoaded(
+                    model.doc != null ? model.doc.derivedUri : null);
+            }
         }
 
         @Override
@@ -1324,10 +1327,10 @@
                 if (docs.isEmpty()) {
                     return false;
                 }
-                v.startDrag(
-                        getClipDataFromDocuments(docs),
+                v.startDragAndDrop(
+                        mClipper.getClipDataForDocuments(docs),
                         new DrawableShadowBuilder(getDragShadowIcon(docs)),
-                        null,
+                        getDisplayState().stack.peek(),
                         View.DRAG_FLAG_GLOBAL | View.DRAG_FLAG_GLOBAL_URI_READ |
                                 View.DRAG_FLAG_GLOBAL_URI_WRITE
                 );
@@ -1479,6 +1482,7 @@
         args.putParcelable(Shared.EXTRA_ROOT, root);
         args.putParcelable(Shared.EXTRA_DOC, doc);
         args.putString(Shared.EXTRA_QUERY, query);
+        args.putParcelable(Shared.EXTRA_SELECTION, new Selection());
 
         final FragmentTransaction ft = fm.beginTransaction();
         switch (anim) {
@@ -1487,10 +1491,10 @@
                 break;
             case ANIM_ENTER:
                 args.putBoolean(Shared.EXTRA_IGNORE_STATE, true);
-                ft.setCustomAnimations(R.animator.dir_enter, R.animator.dir_frozen);
+                ft.setCustomAnimations(R.animator.dir_enter, R.animator.fade_out);
                 break;
             case ANIM_LEAVE:
-                ft.setCustomAnimations(R.animator.dir_frozen, R.animator.dir_leave);
+                ft.setCustomAnimations(R.animator.fade_in, R.animator.dir_leave);
                 break;
         }
 
@@ -1533,7 +1537,7 @@
                         mRoot.authority, mRoot.rootId, mQuery)
                         : DocumentsContract.buildChildDocumentsUri(
                                 mDocument.authority, mDocument.documentId);
-                if (state.action == ACTION_MANAGE) {
+                if (mTuner.enableManagedMode()) {
                     contentsUri = DocumentsContract.setManageMode(contentsUri);
                 }
                 return new DirectoryLoader(
@@ -1542,6 +1546,7 @@
             case TYPE_RECENT_OPEN:
                 final RootsCache roots = DocumentsApplication.getRootsCache(context);
                 return new RecentsLoader(context, roots, state);
+
             default:
                 throw new IllegalStateException("Unknown type " + mType);
         }
diff --git a/packages/DocumentsUI/src/com/android/documentsui/dirlist/DocumentHolder.java b/packages/DocumentsUI/src/com/android/documentsui/dirlist/DocumentHolder.java
index 2967a90..5edda38 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/dirlist/DocumentHolder.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/dirlist/DocumentHolder.java
@@ -16,9 +16,7 @@
 
 package com.android.documentsui.dirlist;
 
-import static com.android.internal.util.Preconditions.checkNotNull;
-import static com.android.internal.util.Preconditions.checkState;
-
+import android.annotation.ColorInt;
 import android.content.Context;
 import android.database.Cursor;
 import android.graphics.Rect;
@@ -38,17 +36,19 @@
         extends RecyclerView.ViewHolder
         implements View.OnKeyListener {
 
+    static final float DISABLED_ALPHA = 0.3f;
+
     public @Nullable String modelId;
 
-    final int mSelectedItemColor;
-    final int mDefaultItemColor;
-    final boolean mAlwaysShowSummary;
     final Context mContext;
+    final @ColorInt int mDefaultBgColor;
+    final @ColorInt int mSelectedBgColor;
 
     DocumentHolder.EventListener mEventListener;
     private View.OnKeyListener mKeyListener;
     private View mSelectionHotspot;
 
+
     public DocumentHolder(Context context, ViewGroup parent, int layout) {
         this(context, inflateLayout(context, parent, layout));
     }
@@ -60,9 +60,8 @@
 
         mContext = context;
 
-        mDefaultItemColor = context.getColor(R.color.item_doc_background);
-        mSelectedItemColor = context.getColor(R.color.item_doc_background_selected);
-        mAlwaysShowSummary = context.getResources().getBoolean(R.bool.always_show_summary);
+        mDefaultBgColor = context.getColor(R.color.item_doc_background);
+        mSelectedBgColor = context.getColor(R.color.item_doc_background_selected);
 
         mSelectionHotspot = itemView.findViewById(R.id.icon_check);
     }
@@ -83,7 +82,7 @@
      */
     public void setSelected(boolean selected) {
         itemView.setActivated(selected);
-        itemView.setBackgroundColor(selected ? mSelectedItemColor : mDefaultItemColor);
+        itemView.setBackgroundColor(selected ? mSelectedBgColor : mDefaultBgColor);
     }
 
     /**
@@ -91,32 +90,33 @@
      * @param highlighted
      */
     public void setHighlighted(boolean highlighted) {
-        itemView.setBackgroundColor(highlighted ? mSelectedItemColor : mDefaultItemColor);
+        itemView.setBackgroundColor(highlighted ? mSelectedBgColor : mDefaultBgColor);
+    }
+
+    public void setEnabled(boolean enabled) {
+        setEnabledRecursive(itemView, enabled);
     }
 
     @Override
     public boolean onKey(View v, int keyCode, KeyEvent event) {
         // Event listener should always be set.
-        checkNotNull(mEventListener);
+        assert(mEventListener != null);
+
         return mEventListener.onKey(this,  keyCode,  event);
     }
 
     public void addEventListener(DocumentHolder.EventListener listener) {
         // Just handle one for now; switch to a list if necessary.
-        checkState(mEventListener == null);
+        assert(mEventListener == null);
         mEventListener = listener;
     }
 
     public void addOnKeyListener(View.OnKeyListener listener) {
         // Just handle one for now; switch to a list if necessary.
-        checkState(mKeyListener == null);
+        assert(mKeyListener == null);
         mKeyListener = listener;
     }
 
-    public void setEnabled(boolean enabled) {
-        setEnabledRecursive(itemView, enabled);
-    }
-
     public boolean onSingleTapUp(MotionEvent event) {
         if (Events.isMouseEvent(event)) {
             // Mouse clicks select.
diff --git a/packages/DocumentsUI/src/com/android/documentsui/dirlist/DocumentsAdapter.java b/packages/DocumentsUI/src/com/android/documentsui/dirlist/DocumentsAdapter.java
index 0930c22..0bbecf9 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/dirlist/DocumentsAdapter.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/dirlist/DocumentsAdapter.java
@@ -74,13 +74,6 @@
     abstract public SparseArray<String> hide(String... ids);
 
     /**
-     * Unhides a set of previously hidden items.
-     *
-     * @param ids A sparse array of IDs from a previous call to {@link #hide}.
-     */
-    abstract void unhide(SparseArray<String> ids);
-
-    /**
      * Returns a class that yields the span size for a particular element. This is
      * primarily useful in {@link SectionBreakDocumentsAdapterWrapper} where
      * we adjust sizes.
diff --git a/packages/DocumentsUI/src/com/android/documentsui/dirlist/FragmentTuner.java b/packages/DocumentsUI/src/com/android/documentsui/dirlist/FragmentTuner.java
index 8ef8910..0ee7623 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/dirlist/FragmentTuner.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/dirlist/FragmentTuner.java
@@ -19,10 +19,9 @@
 import static com.android.documentsui.State.ACTION_BROWSE;
 import static com.android.documentsui.State.ACTION_CREATE;
 import static com.android.documentsui.State.ACTION_GET_CONTENT;
-import static com.android.documentsui.State.ACTION_MANAGE;
 import static com.android.documentsui.State.ACTION_OPEN;
 import static com.android.documentsui.State.ACTION_OPEN_TREE;
-import static com.android.internal.util.Preconditions.checkArgument;
+import static com.android.documentsui.State.ACTION_PICK_COPY_DESTINATION;
 
 import android.content.Context;
 import android.provider.DocumentsContract.Document;
@@ -54,8 +53,6 @@
         switch (state.action) {
             case ACTION_BROWSE:
                 return new FilesTuner(context, state);
-            case ACTION_MANAGE:
-                return new DownloadsTuner(context, state);
             default:
                 return new DocumentsTuner(context, state);
         }
@@ -83,6 +80,12 @@
     abstract void onModelLoaded(Model model, @ResultType int resultType, boolean isSearch);
 
     /**
+     * When managed mode is enabled, active downloads will be visible in the UI.
+     * Presumably this should only be true when in the downloads directory.
+     */
+    abstract boolean enableManagedMode();
+
+    /**
      * Provides support for Platform specific specializations of DirectoryFragment.
      */
     private static final class DocumentsTuner extends FragmentTuner {
@@ -152,47 +155,36 @@
 
         @Override
         void onModelLoaded(Model model, @ResultType int resultType, boolean isSearch) {
+            boolean showDrawer = false;
+
+            if (mState.restored) {
+                showDrawer = true;
+            }
+            if (MimePredicate.mimeMatches(MimePredicate.VISUAL_MIMES, mState.acceptMimes)) {
+                showDrawer = false;
+            }
+            if (mState.external && mState.action == ACTION_GET_CONTENT) {
+                showDrawer = true;
+            }
+            if (mState.action == ACTION_PICK_COPY_DESTINATION) {
+                showDrawer = true;
+            }
+
             // When launched into empty root, open drawer.
-            if (model.isEmpty() && !mState.hasInitialLocationChanged() && !isSearch) {
+            if (model.isEmpty()) {
+                showDrawer = true;
+            }
+
+            if (showDrawer && !mState.hasInitialLocationChanged() && !isSearch) {
                 // This noops on layouts without drawer, so no need to guard.
                 ((BaseActivity) mContext).setRootsDrawerOpen(true);
             }
         }
-    }
-
-    /**
-     * Provides support for Platform specific specializations of DirectoryFragment.
-     */
-    private static final class DownloadsTuner extends FragmentTuner {
-
-        public DownloadsTuner(Context context, State state) {
-            super(context, state);
-        }
 
         @Override
-        public void updateActionMenu(
-                Menu menu, @ResultType int resultType, boolean canDelete, boolean canRename) {
-            checkArgument(resultType != DirectoryFragment.TYPE_RECENT_OPEN);
-
-            MenuItem open = menu.findItem(R.id.menu_open);
-            MenuItem delete = menu.findItem(R.id.menu_delete);
-            MenuItem copyTo = menu.findItem(R.id.menu_copy_to);
-            MenuItem moveTo = menu.findItem(R.id.menu_move_to);
-            MenuItem rename = menu.findItem(R.id.menu_rename);
-            MenuItem copy = menu.findItem(R.id.menu_copy_to_clipboard);
-
-            open.setVisible(false);
-            delete.setVisible(canDelete);
-            copy.setEnabled(true);  // to clipboard
-            copyTo.setVisible(true);
-            copyTo.setEnabled(true);
-            moveTo.setVisible(true);
-            moveTo.setEnabled(true);
-            rename.setVisible(false);
+        public boolean enableManagedMode() {
+            return false;
         }
-
-        @Override
-        void onModelLoaded(Model model, @ResultType int resultType, boolean isSearch) {}
     }
 
     /**
@@ -234,6 +226,17 @@
                 ((BaseActivity) mContext).setRootsDrawerOpen(true);
             }
         }
+
+        @Override
+        public boolean enableManagedMode() {
+            // When in downloads top level directory, we also show active downloads.
+            // And while we don't allow folders in Downloads, we do allow Zip files in
+            // downloads that themselves can be opened and viewed like directories.
+            // This method helps us understand when to kick in on those special behaviors.
+            return mState.stack.root != null
+                    && mState.stack.root.isDownloads()
+                    && mState.stack.size() == 1;
+        }
     }
 
     private static boolean isDirectory(String mimeType) {
diff --git a/packages/DocumentsUI/src/com/android/documentsui/dirlist/GridDirectoryHolder.java b/packages/DocumentsUI/src/com/android/documentsui/dirlist/GridDirectoryHolder.java
index a0ff1b5..90b2341 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/dirlist/GridDirectoryHolder.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/dirlist/GridDirectoryHolder.java
@@ -17,7 +17,6 @@
 package com.android.documentsui.dirlist;
 
 import static com.android.documentsui.model.DocumentInfo.getCursorString;
-import static com.android.internal.util.Preconditions.checkNotNull;
 
 import android.content.Context;
 import android.database.Cursor;
@@ -58,7 +57,7 @@
      * @param state Current display state.
      */
     public void bind(Cursor cursor, String modelId, State state) {
-        checkNotNull(cursor, "Cursor cannot be null.");
+        assert(cursor != null);
 
         this.modelId = modelId;
 
diff --git a/packages/DocumentsUI/src/com/android/documentsui/dirlist/GridDocumentHolder.java b/packages/DocumentsUI/src/com/android/documentsui/dirlist/GridDocumentHolder.java
index 8eaed17e..c8641a8 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/dirlist/GridDocumentHolder.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/dirlist/GridDocumentHolder.java
@@ -19,8 +19,8 @@
 import static com.android.documentsui.model.DocumentInfo.getCursorInt;
 import static com.android.documentsui.model.DocumentInfo.getCursorLong;
 import static com.android.documentsui.model.DocumentInfo.getCursorString;
-import static com.android.internal.util.Preconditions.checkNotNull;
 
+import android.annotation.ColorInt;
 import android.content.Context;
 import android.database.Cursor;
 import android.net.Uri;
@@ -38,6 +38,7 @@
 import com.android.documentsui.State;
 
 final class GridDocumentHolder extends DocumentHolder {
+
     private static boolean mHideTitles;
 
     final TextView mTitle;
@@ -49,9 +50,13 @@
     final ImageView mIconCheck;
     final IconHelper mIconHelper;
 
+    private final @ColorInt int mDisabledBgColor;
+
     public GridDocumentHolder(Context context, ViewGroup parent, IconHelper iconHelper) {
         super(context, parent, R.layout.item_doc_grid);
 
+        mDisabledBgColor = context.getColor(R.color.item_doc_background_disabled);
+
         mTitle = (TextView) itemView.findViewById(android.R.id.title);
         mDate = (TextView) itemView.findViewById(R.id.date);
         mSize = (TextView) itemView.findViewById(R.id.size);
@@ -65,13 +70,35 @@
 
     @Override
     public void setSelected(boolean selected) {
-        super.setSelected(selected);
+        // We always want to make sure our check box disappears if we're not selected,
+        // even if the item is disabled. This is because this object can be reused
+        // and this method will be called to setup initial state.
         float checkAlpha = selected ? 1f : 0f;
-
         mIconCheck.animate().alpha(checkAlpha).start();
+
+        // But it should be an error to be set to selected && be disabled.
+        if (!itemView.isEnabled()) {
+            assert(!selected);
+            return;
+        }
+
+        super.setSelected(selected);
+
         mIconMimeSm.animate().alpha(1f - checkAlpha).start();
     }
 
+    public void setEnabled(boolean enabled) {
+        super.setEnabled(enabled);
+
+        // Text colors enabled/disabled is handle via a color set.
+        itemView.setBackgroundColor(enabled ? mDefaultBgColor : mDisabledBgColor);
+        float imgAlpha = enabled ? 1f : DISABLED_ALPHA;
+
+        mIconMimeLg.setAlpha(imgAlpha);
+        mIconMimeSm.setAlpha(imgAlpha);
+        mIconThumb.setAlpha(imgAlpha);
+    }
+
     /**
      * Bind this view to the given document for display.
      * @param cursor Pointing to the item to be bound.
@@ -79,9 +106,9 @@
      * @param state Current display state.
      */
     public void bind(Cursor cursor, String modelId, State state) {
-        this.modelId = modelId;
+        assert(cursor != null);
 
-        checkNotNull(cursor, "Cursor cannot be null.");
+        this.modelId = modelId;
 
         final String docAuthority = getCursorString(cursor, RootCursorWrapper.COLUMN_AUTHORITY);
         final String docId = getCursorString(cursor, Document.COLUMN_DOCUMENT_ID);
@@ -123,12 +150,4 @@
             mSize.setText(Formatter.formatFileSize(mContext, docSize));
         }
     }
-
-    /**
-     * Sets whether to hide titles on subsequently created GridDocumentHolder items.
-     * @param hideTitles
-     */
-    public static void setHideTitles(boolean hideTitles) {
-        mHideTitles = hideTitles;
-    }
 }
diff --git a/packages/DocumentsUI/src/com/android/documentsui/dirlist/ListDocumentHolder.java b/packages/DocumentsUI/src/com/android/documentsui/dirlist/ListDocumentHolder.java
index be6413b..3a1be11 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/dirlist/ListDocumentHolder.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/dirlist/ListDocumentHolder.java
@@ -19,7 +19,6 @@
 import static com.android.documentsui.model.DocumentInfo.getCursorInt;
 import static com.android.documentsui.model.DocumentInfo.getCursorLong;
 import static com.android.documentsui.model.DocumentInfo.getCursorString;
-import static com.android.internal.util.Preconditions.checkNotNull;
 
 import android.content.Context;
 import android.database.Cursor;
@@ -30,6 +29,7 @@
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.ImageView;
+import android.widget.LinearLayout;
 import android.widget.TextView;
 
 import com.android.documentsui.R;
@@ -39,9 +39,10 @@
 
 final class ListDocumentHolder extends DocumentHolder {
     final TextView mTitle;
-    final TextView mSummary;
+    final LinearLayout mDetails;  // Container of date/size/summary
     final TextView mDate;
     final TextView mSize;
+    final TextView mSummary;
     final ImageView mIconMime;
     final ImageView mIconThumb;
     final ImageView mIconCheck;
@@ -51,26 +52,47 @@
         super(context, parent, R.layout.item_doc_list);
 
         mTitle = (TextView) itemView.findViewById(android.R.id.title);
-        mSummary = (TextView) itemView.findViewById(android.R.id.summary);
         mDate = (TextView) itemView.findViewById(R.id.date);
         mSize = (TextView) itemView.findViewById(R.id.size);
+        mSummary = (TextView) itemView.findViewById(android.R.id.summary);
         mIconMime = (ImageView) itemView.findViewById(R.id.icon_mime);
         mIconThumb = (ImageView) itemView.findViewById(R.id.icon_thumb);
         mIconCheck = (ImageView) itemView.findViewById(R.id.icon_check);
+        // Warning: mDetails view doesn't exists in layout-sw720dp-land layout
+        mDetails = (LinearLayout) itemView.findViewById(R.id.line2);
 
         mIconHelper = iconHelper;
     }
 
     @Override
     public void setSelected(boolean selected) {
-        super.setSelected(selected);
+        // We always want to make sure our check box disappears if we're not selected,
+        // even if the item is disabled. But it should be an error (see assert below)
+        // to be set to selected && be disabled.
         float checkAlpha = selected ? 1f : 0f;
-
         mIconCheck.animate().alpha(checkAlpha).start();
+
+        if (!itemView.isEnabled()) {
+            assert(!selected);
+            return;
+        }
+
+        super.setSelected(selected);
+
         mIconMime.animate().alpha(1f - checkAlpha).start();
         mIconThumb.animate().alpha(1f - checkAlpha).start();
     }
 
+    @Override
+    public void setEnabled(boolean enabled) {
+        super.setEnabled(enabled);
+
+        // Text colors enabled/disabled is handle via a color set.
+        final float imgAlpha = enabled ? 1f : DISABLED_ALPHA;
+        mIconMime.setAlpha(imgAlpha);
+        mIconThumb.setAlpha(imgAlpha);
+    }
+
     /**
      * Bind this view to the given document for display.
      * @param cursor Pointing to the item to be bound.
@@ -79,9 +101,9 @@
      */
     @Override
     public void bind(Cursor cursor, String modelId, State state) {
-        this.modelId = modelId;
+        assert(cursor != null);
 
-        checkNotNull(cursor, "Cursor cannot be null.");
+        this.modelId = modelId;
 
         final String docAuthority = getCursorString(cursor, RootCursorWrapper.COLUMN_AUTHORITY);
         final String docId = getCursorString(cursor, Document.COLUMN_DOCUMENT_ID);
@@ -92,6 +114,7 @@
         final int docFlags = getCursorInt(cursor, Document.COLUMN_FLAGS);
         final String docSummary = getCursorString(cursor, Document.COLUMN_SUMMARY);
         final long docSize = getCursorLong(cursor, Document.COLUMN_SIZE);
+        final boolean isDirectory = Document.MIME_TYPE_DIR.equals(docMimeType);
 
         mIconHelper.stopLoading(mIconThumb);
 
@@ -106,32 +129,39 @@
         mTitle.setText(docDisplayName, TextView.BufferType.SPANNABLE);
         mTitle.setVisibility(View.VISIBLE);
 
-        if (docSummary != null) {
-            mSummary.setText(docSummary);
-            mSummary.setVisibility(View.VISIBLE);
+
+        boolean hasDetails = false;
+        if (isDirectory) {
+            // Note, we don't show any details for any directory...ever.
+            hasDetails = false;
         } else {
-            mSummary.setVisibility(View.INVISIBLE);
+            if (docSummary != null) {
+                hasDetails = true;
+                mSummary.setText(docSummary);
+                mSummary.setVisibility(View.VISIBLE);
+            } else {
+                mSummary.setVisibility(View.INVISIBLE);
+            }
+
+            if (docLastModified > 0) {
+                hasDetails = true;
+                mDate.setText(Shared.formatTime(mContext, docLastModified));
+            } else {
+                mDate.setText(null);
+            }
+
+            if (state.showSize && docSize > -1) {
+                hasDetails = true;
+                mSize.setVisibility(View.VISIBLE);
+                mSize.setText(Formatter.formatFileSize(mContext, docSize));
+            } else {
+                mSize.setVisibility(View.GONE);
+            }
         }
 
-        if (docLastModified == -1) {
-            mDate.setText(null);
-        } else {
-            mDate.setText(Shared.formatTime(mContext, docLastModified));
+        // mDetails view doesn't exists in layout-sw720dp-land layout
+        if (mDetails != null) {
+            mDetails.setVisibility(hasDetails ? View.VISIBLE : View.GONE);
         }
-
-        if (!state.showSize || Document.MIME_TYPE_DIR.equals(docMimeType) || docSize == -1) {
-            mSize.setVisibility(View.GONE);
-        } else {
-            mSize.setVisibility(View.VISIBLE);
-            mSize.setText(Formatter.formatFileSize(mContext, docSize));
-        }
-    }
-
-    @Override
-    public void setEnabled(boolean enabled) {
-        super.setEnabled(enabled);
-        final float iconAlpha = enabled ? 1f : 0.5f;
-        mIconMime.setAlpha(iconAlpha);
-        mIconThumb.setAlpha(iconAlpha);
     }
 }
diff --git a/packages/DocumentsUI/src/com/android/documentsui/dirlist/Model.java b/packages/DocumentsUI/src/com/android/documentsui/dirlist/Model.java
index 9684a5a..ab4f5c4 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/dirlist/Model.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/dirlist/Model.java
@@ -22,11 +22,9 @@
 import static com.android.documentsui.State.SORT_ORDER_SIZE;
 import static com.android.documentsui.model.DocumentInfo.getCursorLong;
 import static com.android.documentsui.model.DocumentInfo.getCursorString;
-import static com.android.internal.util.Preconditions.checkNotNull;
 
 import android.database.Cursor;
 import android.os.Bundle;
-import android.os.Looper;
 import android.provider.DocumentsContract;
 import android.provider.DocumentsContract.Document;
 import android.support.annotation.Nullable;
@@ -61,11 +59,12 @@
      * A sorted array of model IDs for the files currently in the Model.  Sort order is determined
      * by {@link #mSortOrder}
      */
-    private List<String> mIds = new ArrayList<>();
+    private String mIds[] = new String[0];
     private int mSortOrder = SORT_ORDER_DISPLAY_NAME;
 
     @Nullable String info;
     @Nullable String error;
+    @Nullable DocumentInfo doc;
 
     /**
      * Generates a Model ID for a cursor entry that refers to a document. The Model ID is a unique
@@ -109,10 +108,11 @@
         if (result == null) {
             mCursor = null;
             mCursorCount = 0;
-            mIds.clear();
+            mIds = new String[0];
             mPositions.clear();
             info = null;
             error = null;
+            doc = null;
             mIsLoading = false;
             notifyUpdateListeners();
             return;
@@ -127,6 +127,7 @@
         mCursor = result.cursor;
         mCursorCount = mCursor.getCount();
         mSortOrder = result.sortOrder;
+        doc = result.doc;
 
         updateModelData();
 
@@ -151,7 +152,7 @@
      */
     private void updateModelData() {
         int[] positions = new int[mCursorCount];
-        mIds.clear();
+        mIds = new String[mCursorCount];
         String[] stringValues = new String[mCursorCount];
         long[] longValues = null;
 
@@ -163,7 +164,7 @@
         for (int pos = 0; pos < mCursorCount; ++pos) {
             mCursor.moveToNext();
             positions[pos] = pos;
-            mIds.add(createModelId(mCursor));
+            mIds[pos] = createModelId(mCursor);
 
             switch(mSortOrder) {
                 case SORT_ORDER_DISPLAY_NAME:
@@ -200,7 +201,7 @@
         // Populate the positions.
         mPositions.clear();
         for (int i = 0; i < mCursorCount; ++i) {
-            mPositions.put(mIds.get(i), positions[i]);
+            mPositions.put(mIds[i], positions[i]);
         }
     }
 
@@ -213,12 +214,12 @@
      * @param positions Cursor positions to be sorted.
      * @param ids Model IDs to be sorted.
      */
-    private static void binarySort(String[] sortKey, int[] positions, List<String> ids) {
+    private static void binarySort(String[] sortKey, int[] positions, String[] ids) {
         final int count = positions.length;
         for (int start = 1; start < count; start++) {
             final int pivotPosition = positions[start];
             final String pivotValue = sortKey[start];
-            final String pivotId = ids.get(start);
+            final String pivotId = ids[start];
 
             int left = 0;
             int right = start;
@@ -242,23 +243,21 @@
                 case 2:
                     positions[left + 2] = positions[left + 1];
                     sortKey[left + 2] = sortKey[left + 1];
-                    ids.set(left + 2, ids.get(left + 1));
+                    ids[left + 2] = ids[left + 1];
                 case 1:
                     positions[left + 1] = positions[left];
                     sortKey[left + 1] = sortKey[left];
-                    ids.set(left + 1, ids.get(left));
+                    ids[left + 1] = ids[left];
                     break;
                 default:
                     System.arraycopy(positions, left, positions, left + 1, n);
                     System.arraycopy(sortKey, left, sortKey, left + 1, n);
-                    for (int i = n; i >= 1; --i) {
-                        ids.set(left + i, ids.get(left + i - 1));
-                    }
+                    System.arraycopy(ids, left, ids, left + 1, n);
             }
 
             positions[left] = pivotPosition;
             sortKey[left] = pivotValue;
-            ids.set(left, pivotId);
+            ids[left] = pivotId;
         }
     }
 
@@ -274,13 +273,13 @@
      * @param ids Model IDs to be sorted.
      */
     private static void binarySort(
-            long[] sortKey, String[] mimeTypes, int[] positions, List<String> ids) {
+            long[] sortKey, String[] mimeTypes, int[] positions, String[] ids) {
         final int count = positions.length;
         for (int start = 1; start < count; start++) {
             final int pivotPosition = positions[start];
             final long pivotValue = sortKey[start];
             final String pivotMime = mimeTypes[start];
-            final String pivotId = ids.get(start);
+            final String pivotId = ids[start];
 
             int left = 0;
             int right = start;
@@ -309,7 +308,7 @@
                 // have identical numerical sort keys.  One common example of this scenario is seen
                 // when sorting a set of active downloads by mod time.
                 if (compare == 0) {
-                    compare = pivotId.compareTo(ids.get(mid));
+                    compare = pivotId.compareTo(ids[mid]);
                 }
 
                 if (compare < 0) {
@@ -325,26 +324,24 @@
                     positions[left + 2] = positions[left + 1];
                     sortKey[left + 2] = sortKey[left + 1];
                     mimeTypes[left + 2] = mimeTypes[left + 1];
-                    ids.set(left + 2, ids.get(left + 1));
+                    ids[left + 2] = ids[left + 1];
                 case 1:
                     positions[left + 1] = positions[left];
                     sortKey[left + 1] = sortKey[left];
                     mimeTypes[left + 1] = mimeTypes[left];
-                    ids.set(left + 1, ids.get(left));
+                    ids[left + 1] = ids[left];
                     break;
                 default:
                     System.arraycopy(positions, left, positions, left + 1, n);
                     System.arraycopy(sortKey, left, sortKey, left + 1, n);
                     System.arraycopy(mimeTypes, left, mimeTypes, left + 1, n);
-                    for (int i = n; i >= 1; --i) {
-                        ids.set(left + i, ids.get(left + i - 1));
-                    }
+                    System.arraycopy(ids, left, ids, left + 1, n);
             }
 
             positions[left] = pivotPosition;
             sortKey[left] = pivotValue;
             mimeTypes[left] = pivotMime;
-            ids.set(left, pivotId);
+            ids[left] = pivotId;
         }
     }
 
@@ -381,9 +378,9 @@
         final List<DocumentInfo> docs =  new ArrayList<>(size);
         for (String modelId: items.getAll()) {
             final Cursor cursor = getItem(modelId);
-            checkNotNull(cursor, "Cursor cannot be null.");
-            final DocumentInfo doc = DocumentInfo.fromDirectoryCursor(cursor);
-            docs.add(doc);
+            assert(cursor != null);
+
+            docs.add(DocumentInfo.fromDirectoryCursor(cursor));
         }
         return docs;
     }
@@ -412,7 +409,7 @@
      * @return An ordered array of model IDs representing the documents in the model. It is sorted
      *         according to the current sort order, which was set by the last model update.
      */
-    public List<String> getModelIds() {
+    public String[] getModelIds() {
         return mIds;
     }
 }
diff --git a/packages/DocumentsUI/src/com/android/documentsui/dirlist/ModelBackedDocumentsAdapter.java b/packages/DocumentsUI/src/com/android/documentsui/dirlist/ModelBackedDocumentsAdapter.java
index dd27790..149ecdd 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/dirlist/ModelBackedDocumentsAdapter.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/dirlist/ModelBackedDocumentsAdapter.java
@@ -29,6 +29,7 @@
 import android.view.ViewGroup;
 
 import com.android.documentsui.State;
+
 import com.google.common.collect.Sets;
 
 import java.util.ArrayList;
@@ -117,8 +118,13 @@
         final String docMimeType = getCursorString(cursor, Document.COLUMN_MIME_TYPE);
         final int docFlags = getCursorInt(cursor, Document.COLUMN_FLAGS);
 
+        boolean enabled = mEnv.isDocumentEnabled(docMimeType, docFlags);
+        boolean selected = mEnv.isSelected(modelId);
+        if (!enabled) {
+            assert(!selected);
+        }
+        holder.setEnabled(enabled);
         holder.setSelected(mEnv.isSelected(modelId));
-        holder.setEnabled(mEnv.isDocumentEnabled(docMimeType, docFlags));
 
         mEnv.onBindDocumentHolder(holder, cursor);
     }
@@ -134,8 +140,8 @@
             Log.d(TAG, "Updating model with hidden ids: " + mHiddenIds);
         }
 
-        List<String> modelIds = model.getModelIds();
-        mModelIds = new ArrayList<>(modelIds.size());
+        String[] modelIds = model.getModelIds();
+        mModelIds = new ArrayList<>(modelIds.length);
         for (String id : modelIds) {
             if (!mHiddenIds.contains(id)) {
                 mModelIds.add(id);
@@ -181,28 +187,6 @@
     }
 
     @Override
-    public void unhide(SparseArray<String> ids) {
-        if (DEBUG) Log.d(TAG, "Unhiding ids: " + ids);
-
-        // An ArrayList can shrink at runtime...and in fact
-        // it does when we clear it completely.
-        // This means we can't call add(pos, id) without
-        // first checking the list size.
-        List<String> oldIds = mModelIds;
-        mModelIds = new ArrayList<>(oldIds.size() + ids.size());
-        mModelIds.addAll(oldIds);
-
-        // Finally insert the unhidden items.
-        for (int i = 0; i < ids.size(); i++) {
-            int pos = ids.keyAt(i);
-            String id = ids.get(pos);
-            mHiddenIds.remove(id);
-            mModelIds.add(pos, id);
-            notifyItemInserted(pos);
-        }
-    }
-
-    @Override
     public List<String> getModelIds() {
         return mModelIds;
     }
diff --git a/packages/DocumentsUI/src/com/android/documentsui/dirlist/MultiSelectManager.java b/packages/DocumentsUI/src/com/android/documentsui/dirlist/MultiSelectManager.java
index 4cf1048..b0cc09a 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/dirlist/MultiSelectManager.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/dirlist/MultiSelectManager.java
@@ -19,9 +19,6 @@
 import static com.android.documentsui.Shared.DEBUG;
 import static com.android.documentsui.dirlist.ModelBackedDocumentsAdapter.ITEM_TYPE_DIRECTORY;
 import static com.android.documentsui.dirlist.ModelBackedDocumentsAdapter.ITEM_TYPE_DOCUMENT;
-import static com.android.internal.util.Preconditions.checkArgument;
-import static com.android.internal.util.Preconditions.checkNotNull;
-import static com.android.internal.util.Preconditions.checkState;
 
 import android.annotation.IntDef;
 import android.graphics.Point;
@@ -134,8 +131,12 @@
             @SelectionMode int mode,
             @Nullable Selection initialSelection) {
 
-        mEnvironment = checkNotNull(environment, "'environment' cannot be null.");
-        mAdapter = checkNotNull(adapter, "'adapter' cannot be null.");
+        assert(environment != null);
+        assert(adapter != null);
+
+        mEnvironment = environment;
+        mAdapter = adapter;
+
         mSingleSelect = mode == MODE_SINGLE;
         if (initialSelection != null) {
             mSelection.copyFrom(initialSelection);
@@ -168,8 +169,8 @@
 
                     @Override
                     public void onItemRangeRemoved(int startPosition, int itemCount) {
-                        checkState(startPosition >= 0);
-                        checkState(itemCount > 0);
+                        assert(startPosition >= 0);
+                        assert(itemCount > 0);
 
                         mSelection.cancelProvisionalSelection();
                         // Remove any disappeared IDs from the selection.
@@ -356,7 +357,8 @@
      * @param modelId
      */
     public void toggleSelection(String modelId) {
-        checkNotNull(modelId);
+        assert(modelId != null);
+
         boolean changed = false;
         if (mSelection.contains(modelId)) {
             changed = attemptDeselect(modelId);
@@ -389,7 +391,8 @@
      * @param pos The new end position for the selection range.
      */
     void snapRangeSelection(int pos) {
-        checkNotNull(mRanger);
+        assert(mRanger != null);
+
         mRanger.snapSelection(pos);
         notifySelectionChanged();
     }
@@ -436,7 +439,7 @@
      * @param selected New selection state.
      */
     private void updateRange(int begin, int end, boolean selected) {
-        checkState(end >= begin);
+        assert(end >= begin);
         for (int i = begin; i <= end; i++) {
             String id = mAdapter.getModelId(i);
             if (id == null) {
@@ -474,7 +477,7 @@
      * @return True if the update was applied.
      */
     private boolean attemptDeselect(String id) {
-        checkArgument(id != null);
+        assert(id != null);
         if (notifyBeforeItemStateChange(id, false)) {
             mSelection.remove(id);
             notifyItemStateChanged(id, false);
@@ -491,7 +494,7 @@
      * @return True if the update was applied.
      */
     private boolean attemptSelect(String id) {
-        checkArgument(id != null);
+        assert(id != null);
         boolean canSelect = notifyBeforeItemStateChange(id, true);
         if (!canSelect) {
             return false;
@@ -519,7 +522,7 @@
      * (identified by {@code position}) changes.
      */
     private void notifyItemStateChanged(String id, boolean selected) {
-        checkArgument(id != null);
+        assert(id != null);
         int lastListener = mCallbacks.size() - 1;
         for (int i = lastListener; i > -1; i--) {
             mCallbacks.get(i).onItemStateChanged(id, selected);
@@ -555,8 +558,8 @@
         }
 
         private void snapSelection(int position) {
-            checkState(mRanger != null);
-            checkArgument(position != RecyclerView.NO_POSITION);
+            assert(mRanger != null);
+            assert(position != RecyclerView.NO_POSITION);
 
             if (mEnd == UNDEFINED || mEnd == mBegin) {
                 // Reset mEnd so it can be established in establishRange.
@@ -568,7 +571,7 @@
         }
 
         private void establishRange(int position) {
-            checkState(mRanger.mEnd == UNDEFINED);
+            assert(mRanger.mEnd == UNDEFINED);
 
             if (position == mBegin) {
                 mEnd = position;
@@ -584,8 +587,8 @@
         }
 
         private void reviseRange(int position) {
-            checkState(mEnd != UNDEFINED);
-            checkState(mBegin != mEnd);
+            assert(mEnd != UNDEFINED);
+            assert(mBegin != mEnd);
 
             if (position == mEnd) {
                 if (DEBUG) Log.i(TAG, "Skipping no-op revision click on mEndRange.");
@@ -1185,7 +1188,7 @@
          * @param input
          */
         private void processInputEvent(InputEvent input) {
-            checkArgument(input.isMouseEvent());
+            assert(input.isMouseEvent());
 
             if (shouldStop(input)) {
                 endBandSelect();
@@ -1199,7 +1202,6 @@
             }
 
             mCurrentPosition = input.getOrigin();
-            mModel.resizeSelection(input.getOrigin());
             scrollViewIfNecessary();
             resizeBandSelectRectangle();
         }
@@ -1488,6 +1490,7 @@
          *     top-left of the viewport would have a relative origin of (0, 0), even though its
          *     absolute point has a higher y-value.
          */
+        @VisibleForTesting
         void resizeSelection(Point relativePointer) {
             mPointer = mHelper.createAbsolutePoint(relativePointer);
             updateModel();
@@ -1615,7 +1618,7 @@
         private void updateSelection(Rect rect) {
             int columnStart =
                     Collections.binarySearch(mColumnBounds, new Limits(rect.left, rect.left));
-            checkState(columnStart >= 0);
+            assert(columnStart >= 0);
             int columnEnd = columnStart;
 
             for (int i = columnStart; i < mColumnBounds.size()
diff --git a/packages/DocumentsUI/src/com/android/documentsui/dirlist/RenameDocumentFragment.java b/packages/DocumentsUI/src/com/android/documentsui/dirlist/RenameDocumentFragment.java
index 38a71ec..884abbb 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/dirlist/RenameDocumentFragment.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/dirlist/RenameDocumentFragment.java
@@ -17,7 +17,6 @@
 package com.android.documentsui.dirlist;
 
 import static com.android.documentsui.Shared.TAG;
-import static com.android.internal.util.Preconditions.checkArgument;
 
 import android.app.AlertDialog;
 import android.app.Dialog;
@@ -36,9 +35,9 @@
 import android.support.design.widget.Snackbar;
 import android.util.Log;
 import android.view.KeyEvent;
-import android.view.inputmethod.EditorInfo;
 import android.view.LayoutInflater;
 import android.view.View;
+import android.view.inputmethod.EditorInfo;
 import android.widget.EditText;
 import android.widget.TextView;
 import android.widget.TextView.OnEditorActionListener;
@@ -93,6 +92,9 @@
 
         final AlertDialog dialog = builder.create();
 
+        // Workaround for the problem - virtual keyboard doesn't show on the phone.
+        Shared.ensureKeyboardPresent(context, dialog);
+
         mEditText.setOnEditorActionListener(
                 new OnEditorActionListener() {
                     @Override
@@ -205,7 +207,7 @@
 
         @Override
         protected DocumentInfo doInBackground(DocumentInfo... document) {
-            checkArgument(document.length == 1);
+            assert(document.length == 1);
             final ContentResolver resolver = mActivity.getContentResolver();
             ContentProviderClient client = null;
 
diff --git a/packages/DocumentsUI/src/com/android/documentsui/dirlist/SectionBreakDocumentsAdapterWrapper.java b/packages/DocumentsUI/src/com/android/documentsui/dirlist/SectionBreakDocumentsAdapterWrapper.java
index 2485ad9..b698059 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/dirlist/SectionBreakDocumentsAdapterWrapper.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/dirlist/SectionBreakDocumentsAdapterWrapper.java
@@ -16,8 +16,6 @@
 
 package com.android.documentsui.dirlist;
 
-import static com.android.internal.util.Preconditions.checkArgument;
-
 import android.content.Context;
 import android.database.Cursor;
 import android.support.v7.widget.GridLayoutManager;
@@ -171,13 +169,6 @@
     }
 
     @Override
-    void unhide(SparseArray<String> ids) {
-        // NOTE: We hear about these changes and adjust break position
-        // in our AdapterDataObserver.
-        mDelegate.unhide(ids);
-    }
-
-    @Override
     List<String> getModelIds() {
         return mDelegate.getModelIds();
     }
@@ -204,12 +195,12 @@
         }
 
         public void onItemRangeChanged(int positionStart, int itemCount, Object payload) {
-            checkArgument(itemCount == 1);
+            assert(itemCount == 1);
             notifyItemRangeChanged(toViewPosition(positionStart), itemCount, payload);
         }
 
         public void onItemRangeInserted(int positionStart, int itemCount) {
-            checkArgument(itemCount == 1);
+            assert(itemCount == 1);
             if (positionStart < mBreakPosition) {
                 mBreakPosition++;
             }
@@ -217,7 +208,7 @@
         }
 
         public void onItemRangeRemoved(int positionStart, int itemCount) {
-            checkArgument(itemCount == 1);
+            assert(itemCount == 1);
             if (positionStart < mBreakPosition) {
                 mBreakPosition--;
             }
diff --git a/packages/DocumentsUI/src/com/android/documentsui/model/DocumentInfo.java b/packages/DocumentsUI/src/com/android/documentsui/model/DocumentInfo.java
index d74121e..d5327f9 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/model/DocumentInfo.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/model/DocumentInfo.java
@@ -245,10 +245,6 @@
         return (flags & Document.FLAG_SUPPORTS_RENAME) != 0;
     }
 
-    public boolean isGridTitlesHidden() {
-        return (flags & Document.FLAG_DIR_HIDE_GRID_TITLES) != 0;
-    }
-
     public boolean isArchive() {
         return (flags & Document.FLAG_ARCHIVE) != 0;
     }
diff --git a/packages/DocumentsUI/src/com/android/documentsui/model/RootInfo.java b/packages/DocumentsUI/src/com/android/documentsui/model/RootInfo.java
index 3897058..3eaf10a 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/model/RootInfo.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/model/RootInfo.java
@@ -16,6 +16,7 @@
 
 package com.android.documentsui.model;
 
+import static com.android.documentsui.Shared.DEBUG;
 import static com.android.documentsui.Shared.compareToIgnoreCaseNullable;
 import static com.android.documentsui.model.DocumentInfo.getCursorInt;
 import static com.android.documentsui.model.DocumentInfo.getCursorLong;
@@ -31,6 +32,7 @@
 import android.provider.DocumentsContract;
 import android.provider.DocumentsContract.Root;
 import android.text.TextUtils;
+import android.util.Log;
 
 import com.android.documentsui.IconUtils;
 import com.android.documentsui.R;
@@ -47,6 +49,8 @@
  * Representation of a {@link Root}.
  */
 public class RootInfo implements Durable, Parcelable, Comparable<RootInfo> {
+
+    private static final String TAG = "RootInfo";
     private static final int VERSION_INIT = 1;
     private static final int VERSION_DROP_TYPE = 2;
 
@@ -59,6 +63,8 @@
             TYPE_DOWNLOADS,
             TYPE_LOCAL,
             TYPE_MTP,
+            TYPE_SD,
+            TYPE_USB,
             TYPE_OTHER
     })
     @Retention(RetentionPolicy.SOURCE)
@@ -70,7 +76,9 @@
     public static final int TYPE_DOWNLOADS = 5;
     public static final int TYPE_LOCAL = 6;
     public static final int TYPE_MTP = 7;
-    public static final int TYPE_OTHER = 8;
+    public static final int TYPE_SD = 8;
+    public static final int TYPE_USB = 9;
+    public static final int TYPE_OTHER = 10;
 
     public String authority;
     public String rootId;
@@ -185,33 +193,40 @@
     private void deriveFields() {
         derivedMimeTypes = (mimeTypes != null) ? mimeTypes.split("\n") : null;
 
-        // TODO: remove these special case icons
         if (isHome()) {
+            derivedType = TYPE_LOCAL;
             derivedIcon = R.drawable.ic_root_documents;
-            derivedType = TYPE_LOCAL;
-        } else if (isExternalStorage()) {
-            derivedIcon = R.drawable.ic_root_smartphone;
-            derivedType = TYPE_LOCAL;
-            // TODO: Apply SD card icon to SD devices.
-        } else if (isDownloads()) {
-            derivedIcon = R.drawable.ic_root_download;
-            derivedType = TYPE_DOWNLOADS;
-        } else if (isImages()) {
-            derivedIcon = R.drawable.ic_doc_image;
-            derivedType = TYPE_IMAGES;
-        } else if (isVideos()) {
-            derivedIcon = R.drawable.ic_doc_video;
-            derivedType = TYPE_VIDEO;
-        } else if (isAudio()) {
-            derivedIcon = R.drawable.ic_doc_audio;
-            derivedType = TYPE_AUDIO;
-        } else if (isRecents()) {
-            derivedType = TYPE_RECENTS;
         } else if (isMtp()) {
             derivedType = TYPE_MTP;
+            derivedIcon = R.drawable.ic_usb_storage;
+        } else if (isUsb()) {
+            derivedType = TYPE_USB;
+            derivedIcon = R.drawable.ic_usb_storage;
+        } else if (isSd()) {
+            derivedType = TYPE_SD;
+            derivedIcon = R.drawable.ic_sd_storage;
+        } else if (isExternalStorage()) {
+            derivedType = TYPE_LOCAL;
+            derivedIcon = R.drawable.ic_root_smartphone;
+        } else if (isDownloads()) {
+            derivedType = TYPE_DOWNLOADS;
+            derivedIcon = R.drawable.ic_root_download;
+        } else if (isImages()) {
+            derivedType = TYPE_IMAGES;
+            derivedIcon = R.drawable.ic_doc_image;
+        } else if (isVideos()) {
+            derivedType = TYPE_VIDEO;
+            derivedIcon = R.drawable.ic_doc_video;
+        } else if (isAudio()) {
+            derivedType = TYPE_AUDIO;
+            derivedIcon = R.drawable.ic_doc_audio;
+        } else if (isRecents()) {
+            derivedType = TYPE_RECENTS;
         } else {
             derivedType = TYPE_OTHER;
         }
+
+        if (DEBUG) Log.d(TAG, "Finished deriving fields: " + this);
     }
 
     public Uri getUri() {
@@ -283,10 +298,6 @@
         return (flags & Root.FLAG_SUPPORTS_SEARCH) != 0;
     }
 
-    public boolean isAdvanced() {
-        return (flags & Root.FLAG_ADVANCED) != 0;
-    }
-
     public boolean isLocalOnly() {
         return (flags & Root.FLAG_LOCAL_ONLY) != 0;
     }
@@ -295,6 +306,14 @@
         return (flags & Root.FLAG_EMPTY) != 0;
     }
 
+    public boolean isSd() {
+        return (flags & Root.FLAG_REMOVABLE_SD) != 0;
+    }
+
+    public boolean isUsb() {
+        return (flags & Root.FLAG_REMOVABLE_USB) != 0;
+    }
+
     public Drawable loadIcon(Context context) {
         if (derivedIcon != 0) {
             return context.getDrawable(derivedIcon);
@@ -362,7 +381,14 @@
 
     @Override
     public String toString() {
-        return "Root{authority=" + authority + ", rootId=" + rootId + ", title=" + title + "}";
+        return "Root{"
+                + "authority=" + authority
+                + ", rootId=" + rootId
+                + ", title=" + title
+                + ", isUsb=" + isUsb()
+                + ", isSd=" + isSd()
+                + ", isMtp=" + isMtp()
+                + "}";
     }
 
     public String getDirectoryString() {
diff --git a/packages/DocumentsUI/src/com/android/documentsui/services/CopyJob.java b/packages/DocumentsUI/src/com/android/documentsui/services/CopyJob.java
index 844d07a..9ed2abf 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/services/CopyJob.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/services/CopyJob.java
@@ -29,7 +29,6 @@
 import static com.android.documentsui.services.FileOperationService.EXTRA_OPERATION;
 import static com.android.documentsui.services.FileOperationService.EXTRA_SRC_LIST;
 import static com.android.documentsui.services.FileOperationService.OPERATION_COPY;
-import static com.google.common.base.Preconditions.checkArgument;
 
 import android.annotation.StringRes;
 import android.app.Notification;
@@ -67,12 +66,15 @@
 import java.util.List;
 
 class CopyJob extends Job {
+
     private static final String TAG = "CopyJob";
-    private static final int PROGRESS_INTERVAL_MILLIS = 1000;
+    private static final int PROGRESS_INTERVAL_MILLIS = 500;
+
     final List<DocumentInfo> mSrcs;
     final ArrayList<DocumentInfo> convertedFiles = new ArrayList<>();
 
     private long mStartTime = -1;
+
     private long mBatchSize;
     private long mBytesCopied;
     private long mLastNotificationTime;
@@ -92,7 +94,7 @@
             String id, DocumentStack stack, List<DocumentInfo> srcs) {
         super(service, appContext, listener, OPERATION_COPY, id, stack);
 
-        checkArgument(!srcs.isEmpty());
+        assert(!srcs.isEmpty());
         this.mSrcs = srcs;
     }
 
@@ -105,7 +107,7 @@
             @OpType int opType, String id, DocumentStack destination, List<DocumentInfo> srcs) {
         super(service, appContext, listener, opType, id, destination);
 
-        checkArgument(!srcs.isEmpty());
+        assert(!srcs.isEmpty());
         this.mSrcs = srcs;
     }
 
@@ -297,18 +299,15 @@
             if ((src.flags & Document.FLAG_SUPPORTS_COPY) != 0) {
                 try {
                     if (DocumentsContract.copyDocument(getClient(src), src.derivedUri,
-                            dstDirInfo.derivedUri) == null) {
-                        throw new ResourceException("Provider side copy failed for document %s.",
-                                src.derivedUri);
+                            dstDirInfo.derivedUri) != null) {
+                        return;
                     }
-                } catch (ResourceException e) {
-                    throw e;
                 } catch (RemoteException | RuntimeException e) {
-                    throw new ResourceException(
-                            "Provider side copy failed for document %s due to an exception.",
-                            src.derivedUri, e);
+                    Log.e(TAG, "Provider side copy failed for: " + src.derivedUri
+                            + " due to an exception: " + e);
                 }
-                return;
+                // If optimized copy fails, then fallback to byte-by-byte copy.
+                if (DEBUG) Log.d(TAG, "Fallback to byte-by-byte copy for: " + src.derivedUri);
             }
         }
 
@@ -496,8 +495,8 @@
             try {
                 while ((len = in.read(buffer)) != -1) {
                     if (isCanceled()) {
-                        throw new ResourceException("Canceled copy mid-copy of %s",
-                                src.derivedUri);
+                        if (DEBUG) Log.d(TAG, "Canceled copy mid-copy of: " + src.derivedUri);
+                        return;
                     }
                     out.write(buffer, 0, len);
                     makeCopyProgress(len);
diff --git a/packages/DocumentsUI/src/com/android/documentsui/services/DeleteJob.java b/packages/DocumentsUI/src/com/android/documentsui/services/DeleteJob.java
index 25bca4f..8f45162 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/services/DeleteJob.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/services/DeleteJob.java
@@ -57,8 +57,8 @@
     @Override
     Builder createProgressBuilder() {
         return super.createProgressBuilder(
-                service.getString(R.string.move_notification_title),
-                R.drawable.ic_menu_copy,
+                service.getString(R.string.delete_notification_title),
+                R.drawable.ic_menu_delete,
                 service.getString(android.R.string.cancel),
                 R.drawable.ic_cab_cancel);
     }
diff --git a/packages/DocumentsUI/src/com/android/documentsui/services/FileOperationService.java b/packages/DocumentsUI/src/com/android/documentsui/services/FileOperationService.java
index 05a3f11..580fa38 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/services/FileOperationService.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/services/FileOperationService.java
@@ -17,9 +17,6 @@
 package com.android.documentsui.services;
 
 import static com.android.documentsui.Shared.DEBUG;
-import static com.android.internal.util.Preconditions.checkArgument;
-import static com.android.internal.util.Preconditions.checkNotNull;
-import static com.android.internal.util.Preconditions.checkState;
 
 import android.annotation.IntDef;
 import android.app.NotificationManager;
@@ -136,12 +133,12 @@
 
         String jobId = intent.getStringExtra(EXTRA_JOB_ID);
         @OpType int operationType = intent.getIntExtra(EXTRA_OPERATION, OPERATION_UNKNOWN);
-        checkArgument(jobId != null);
+        assert(jobId != null);
 
         if (intent.hasExtra(EXTRA_CANCEL)) {
             handleCancel(intent);
         } else {
-            checkArgument(operationType != OPERATION_UNKNOWN);
+            assert(operationType != OPERATION_UNKNOWN);
             handleOperation(intent, serviceId, jobId, operationType);
         }
 
@@ -173,9 +170,9 @@
             mWakeLock.acquire();
         }
 
-        checkState(job != null);
+        assert(job != null);
         int delay = intent.getIntExtra(EXTRA_DELAY, DEFAULT_DELAY);
-        checkArgument(delay <= MAX_DELAY);
+        assert(delay <= MAX_DELAY);
         if (DEBUG) Log.d(
                 TAG, "Scheduling job " + job.id + " to run in " + delay + " milliseconds.");
         ScheduledFuture<?> future = executor.schedule(job, delay, TimeUnit.MILLISECONDS);
@@ -188,8 +185,10 @@
      * @param intent The cancellation intent.
      */
     private void handleCancel(Intent intent) {
-        checkArgument(intent.hasExtra(EXTRA_CANCEL));
-        String jobId = checkNotNull(intent.getStringExtra(EXTRA_JOB_ID));
+        assert(intent.hasExtra(EXTRA_CANCEL));
+        assert(intent.getStringExtra(EXTRA_JOB_ID) != null);
+
+        String jobId = intent.getStringExtra(EXTRA_JOB_ID);
 
         if (DEBUG) Log.d(TAG, "handleCancel: " + jobId);
 
@@ -253,7 +252,8 @@
                 throw new UnsupportedOperationException();
         }
 
-        return checkNotNull(job);
+        assert(job != null);
+        return job;
     }
 
     @GuardedBy("mRunning")
@@ -261,7 +261,7 @@
         if (DEBUG) Log.d(TAG, "deleteJob: " + job.id);
 
         JobRecord record = mRunning.remove(job.id);
-        checkArgument(record != null);
+        assert(record != null);
         record.job.cleanup();
 
         if (mRunning.isEmpty()) {
diff --git a/packages/DocumentsUI/src/com/android/documentsui/services/FileOperations.java b/packages/DocumentsUI/src/com/android/documentsui/services/FileOperations.java
index 9d017ee..b53e165 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/services/FileOperations.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/services/FileOperations.java
@@ -22,7 +22,6 @@
 import static com.android.documentsui.Shared.asArrayList;
 import static com.android.documentsui.Shared.getQuantityString;
 import static com.android.documentsui.services.FileOperationService.EXTRA_CANCEL;
-import static com.android.documentsui.services.FileOperationService.EXTRA_DELAY;
 import static com.android.documentsui.services.FileOperationService.EXTRA_JOB_ID;
 import static com.android.documentsui.services.FileOperationService.EXTRA_OPERATION;
 import static com.android.documentsui.services.FileOperationService.EXTRA_SRC_LIST;
@@ -165,19 +164,16 @@
      *     Use {@link #createJobId} if you don't have one handy.
      * @param srcDocs A list of src files to copy.
      * @param srcParent Parent of all the source documents.
-     * @param delay Number of milliseconds to wait before executing the job.
      * @return Id of the job.
      */
     public static String delete(
             Activity activity, List<DocumentInfo> srcDocs, DocumentInfo srcParent,
-            DocumentStack location, int delay) {
+            DocumentStack location) {
         String jobId = createJobId();
-        if (DEBUG) Log.d(TAG, "Initiating 'delete' operation id " + jobId
-                + " delayed by " + delay + " milliseconds.");
+        if (DEBUG) Log.d(TAG, "Initiating 'delete' operation id " + jobId + ".");
 
         Intent intent = createBaseIntent(OPERATION_DELETE, activity, jobId, srcDocs, srcParent,
                 location);
-        intent.putExtra(EXTRA_DELAY, delay);
         activity.startService(intent);
 
         return jobId;
diff --git a/packages/DocumentsUI/src/com/android/documentsui/services/Job.java b/packages/DocumentsUI/src/com/android/documentsui/services/Job.java
index afb3374..c723ac6 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/services/Job.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/services/Job.java
@@ -23,8 +23,6 @@
 import static com.android.documentsui.services.FileOperationService.EXTRA_OPERATION;
 import static com.android.documentsui.services.FileOperationService.EXTRA_SRC_LIST;
 import static com.android.documentsui.services.FileOperationService.OPERATION_UNKNOWN;
-import static com.android.internal.util.Preconditions.checkArgument;
-import static com.android.internal.util.Preconditions.checkNotNull;
 
 import android.annotation.DrawableRes;
 import android.annotation.PluralsRes;
@@ -98,7 +96,7 @@
     Job(Context service, Context appContext, Listener listener,
             @OpType int operationType, String id, DocumentStack stack) {
 
-        checkArgument(operationType != OPERATION_UNKNOWN);
+        assert(operationType != OPERATION_UNKNOWN);
 
         this.service = service;
         this.appContext = appContext;
@@ -150,7 +148,8 @@
             mClients.put(doc.authority, client);
         }
 
-        return checkNotNull(client);
+        assert(client != null);
+        return client;
     }
 
     final void cleanup() {
@@ -201,8 +200,8 @@
     }
 
     Notification getSetupNotification(String content) {
-        mProgressBuilder.setProgress(0, 0, true);
-        mProgressBuilder.setContentText(content);
+        mProgressBuilder.setProgress(0, 0, true)
+                .setContentText(content);
         return mProgressBuilder.build();
     }
 
@@ -221,6 +220,7 @@
                 .setCategory(Notification.CATEGORY_ERROR)
                 .setSmallIcon(icon)
                 .setAutoCancel(true);
+
         return errorBuilder.build();
     }
 
diff --git a/packages/DocumentsUI/src/com/android/documentsui/services/MoveJob.java b/packages/DocumentsUI/src/com/android/documentsui/services/MoveJob.java
index b5826a4..aaa7596 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/services/MoveJob.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/services/MoveJob.java
@@ -16,12 +16,12 @@
 
 package com.android.documentsui.services;
 
+import static com.android.documentsui.Shared.DEBUG;
 import static com.android.documentsui.services.FileOperationService.OPERATION_MOVE;
 
 import android.app.Notification;
 import android.app.Notification.Builder;
 import android.content.Context;
-import android.net.Uri;
 import android.os.RemoteException;
 import android.provider.DocumentsContract;
 import android.provider.DocumentsContract.Document;
@@ -37,6 +37,7 @@
 final class MoveJob extends CopyJob {
 
     private static final String TAG = "MoveJob";
+
     final DocumentInfo mSrcParent;
 
     /**
@@ -71,7 +72,7 @@
 
     @Override
     public Notification getProgressNotification() {
-        return getProgressNotification(R.string.copy_preparing);
+        return getProgressNotification(R.string.copy_remaining);
     }
 
     @Override
@@ -92,16 +93,15 @@
                 try {
                     if (DocumentsContract.moveDocument(getClient(src), src.derivedUri,
                             srcParent != null ? srcParent.derivedUri : mSrcParent.derivedUri,
-                            dest.derivedUri) == null) {
-                        throw new ResourceException("Provider side move failed for document %s.",
-                                src.derivedUri);
+                            dest.derivedUri) != null) {
+                        return;
                     }
-                } catch (RuntimeException | RemoteException e) {
-                    throw new ResourceException(
-                            "Provider side move failed for document %s due to an exception.",
-                            src.derivedUri, e);
+                } catch (RemoteException | RuntimeException e) {
+                    Log.e(TAG, "Provider side move failed for: " + src.derivedUri
+                            + " due to an exception: " + e);
                 }
-                return;
+                // If optimized move fails, then fallback to byte-by-byte copy.
+                if (DEBUG) Log.d(TAG, "Fallback to byte-by-byte move for: " + src.derivedUri);
             }
         }
 
diff --git a/packages/DocumentsUI/tests/Android.mk b/packages/DocumentsUI/tests/Android.mk
index b65ac98..3983f78 100644
--- a/packages/DocumentsUI/tests/Android.mk
+++ b/packages/DocumentsUI/tests/Android.mk
@@ -7,8 +7,8 @@
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
-LOCAL_JAVA_LIBRARIES := android.test.runner
-LOCAL_STATIC_JAVA_LIBRARIES := android-support-v4 mockito-target ub-uiautomator
+LOCAL_JAVA_LIBRARIES := android-support-v4 android.test.runner
+LOCAL_STATIC_JAVA_LIBRARIES := mockito-target ub-uiautomator
 
 LOCAL_PACKAGE_NAME := DocumentsUITests
 LOCAL_INSTRUMENTATION_FOR := DocumentsUI
diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/ActivityTest.java b/packages/DocumentsUI/tests/src/com/android/documentsui/ActivityTest.java
index adcfef3..683fd6c 100644
--- a/packages/DocumentsUI/tests/src/com/android/documentsui/ActivityTest.java
+++ b/packages/DocumentsUI/tests/src/com/android/documentsui/ActivityTest.java
@@ -32,8 +32,11 @@
 import android.support.test.uiautomator.UiDevice;
 import android.support.test.uiautomator.UiObjectNotFoundException;
 import android.test.ActivityInstrumentationTestCase2;
+import android.util.Log;
 import android.view.MotionEvent;
 
+import com.android.documentsui.BaseActivity;
+import com.android.documentsui.EventListener;
 import com.android.documentsui.bots.DirectoryListBot;
 import com.android.documentsui.bots.KeyboardBot;
 import com.android.documentsui.bots.RootsListBot;
@@ -64,7 +67,6 @@
 
     public RootInfo rootDir0;
     public RootInfo rootDir1;
-
     ContentResolver mResolver;
     DocumentsProviderHelper mDocsHelper;
     ContentProviderClient mClient;
@@ -84,6 +86,23 @@
         return rootDir0;
     }
 
+    /**
+     * Returns the authority of the testing provider begin used.
+     * By default it's StubProvider's authority.
+     * @return Authority of the provider.
+     */
+    protected String getTestingProviderAuthority() {
+        return DEFAULT_AUTHORITY;
+    }
+
+    /**
+     * Resolves testing roots.
+     */
+    protected void setupTestingRoots() throws RemoteException {
+        rootDir0 = mDocsHelper.getRoot(ROOT_0_ID);
+        rootDir1 = mDocsHelper.getRoot(ROOT_1_ID);
+    }
+
     @Override
     public void setUp() throws Exception {
         device = UiDevice.getInstance(getInstrumentation());
@@ -93,18 +112,14 @@
         bots = new Bots(device, context, TIMEOUT);
 
         Configurator.getInstance().setToolType(MotionEvent.TOOL_TYPE_MOUSE);
-        bots.main.revealLauncher();
 
         mResolver = context.getContentResolver();
-        mClient = mResolver.acquireUnstableContentProviderClient(DEFAULT_AUTHORITY);
-        mDocsHelper = new DocumentsProviderHelper(DEFAULT_AUTHORITY, mClient);
+        mClient = mResolver.acquireUnstableContentProviderClient(getTestingProviderAuthority());
+        mDocsHelper = new DocumentsProviderHelper(getTestingProviderAuthority(), mClient);
 
-        rootDir0 = mDocsHelper.getRoot(ROOT_0_ID);
-        rootDir1 = mDocsHelper.getRoot(ROOT_1_ID);
+        setupTestingRoots();
 
         launchActivity();
-
-        bots.main.revealApp();
         resetStorage();
     }
 
diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/DocumentsProviderHelper.java b/packages/DocumentsUI/tests/src/com/android/documentsui/DocumentsProviderHelper.java
index af478ea..16ed2d9 100644
--- a/packages/DocumentsUI/tests/src/com/android/documentsui/DocumentsProviderHelper.java
+++ b/packages/DocumentsUI/tests/src/com/android/documentsui/DocumentsProviderHelper.java
@@ -106,13 +106,15 @@
         return createDocument(root.documentId, mimeType, name);
     }
 
-    public Uri createDocumentWithFlags(String documentId, String mimeType, String name, int flags)
+    public Uri createDocumentWithFlags(String documentId, String mimeType, String name, int flags,
+            String... streamTypes)
             throws RemoteException {
         Bundle in = new Bundle();
         in.putInt(StubProvider.EXTRA_FLAGS, flags);
         in.putString(StubProvider.EXTRA_PARENT_ID, documentId);
         in.putString(Document.COLUMN_MIME_TYPE, mimeType);
         in.putString(Document.COLUMN_DISPLAY_NAME, name);
+        in.putStringArrayList(StubProvider.EXTRA_STREAM_TYPES, Lists.newArrayList(streamTypes));
 
         Bundle out = mClient.call("createDocumentWithFlags", null, in);
         Uri uri = out.getParcelable(DocumentsContract.EXTRA_URI);
diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/DownloadsActivityUiTest.java b/packages/DocumentsUI/tests/src/com/android/documentsui/DownloadsActivityUiTest.java
deleted file mode 100644
index 79d7887..0000000
--- a/packages/DocumentsUI/tests/src/com/android/documentsui/DownloadsActivityUiTest.java
+++ /dev/null
@@ -1,102 +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.documentsui;
-
-import static com.android.documentsui.StubProvider.ROOT_0_ID;
-
-import android.content.Intent;
-import android.os.RemoteException;
-import android.provider.DocumentsContract;
-import android.support.test.uiautomator.By;
-import android.support.test.uiautomator.Until;
-import android.test.suitebuilder.annotation.LargeTest;
-
-@LargeTest
-public class DownloadsActivityUiTest extends ActivityTest<DownloadsActivity> {
-
-    public DownloadsActivityUiTest() {
-        super(DownloadsActivity.class);
-    }
-
-    @Override
-    void launchActivity() {
-        final Intent intent = new Intent(DocumentsContract.ACTION_MANAGE_ROOT);
-        intent.setDataAndType(rootDir0.getUri(), DocumentsContract.Root.MIME_TYPE_ITEM);
-        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
-        setActivityIntent(intent);
-        getActivity();  // Launch the activity.
-    }
-
-    @Override
-    void initTestFiles() throws RemoteException {
-        mDocsHelper.createDocument(rootDir0, "text/plain", "file0.log");
-        mDocsHelper.createDocument(rootDir0, "image/png", "file1.png");
-        mDocsHelper.createDocument(rootDir0, "text/csv", "file2.csv");
-    }
-
-    public void testWindowTitle() throws Exception {
-        initTestFiles();
-
-        bots.main.assertWindowTitle(ROOT_0_ID);
-    }
-
-    public void testFilesListed() throws Exception {
-        initTestFiles();
-
-        bots.directory.assertDocumentsPresent("file0.log", "file1.png", "file2.csv");
-    }
-
-    public void testFilesList_LiveUpdate() throws Exception {
-        initTestFiles();
-
-        mDocsHelper.createDocument(rootDir0, "yummers/sandwich", "Ham & Cheese.sandwich");
-
-        bots.directory.waitForDocument("Ham & Cheese.sandwich");
-        bots.directory.assertDocumentsPresent(
-                "file0.log", "file1.png", "file2.csv", "Ham & Cheese.sandwich");
-    }
-
-    public void testDeleteDocument() throws Exception {
-        initTestFiles();
-
-        bots.directory.clickDocument("file1.png");
-        device.waitForIdle();
-        bots.main.menuDelete().click();
-
-        bots.directory.waitForDeleteSnackbar();
-        bots.directory.assertDocumentsAbsent("file1.png");
-
-        bots.directory.waitForDeleteSnackbarGone();
-        bots.directory.assertDocumentsAbsent("file1.png");
-    }
-
-    public void testSupportsShare() throws Exception {
-        initTestFiles();
-
-        bots.directory.clickDocument("file1.png");
-        device.waitForIdle();
-        assertNotNull(bots.main.menuShare());
-    }
-
-    public void testClosesOnBack() throws Exception {
-        DownloadsActivity activity = getActivity();
-        device.pressBack();
-        device.wait(Until.gone(By.text(ROOT_0_ID)), TIMEOUT);  // wait for the window to go away
-        assertTrue(activity.isDestroyed());
-    }
-}
diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/FilesActivityUiTest.java b/packages/DocumentsUI/tests/src/com/android/documentsui/FilesActivityUiTest.java
index 38e1257..056e6ed 100644
--- a/packages/DocumentsUI/tests/src/com/android/documentsui/FilesActivityUiTest.java
+++ b/packages/DocumentsUI/tests/src/com/android/documentsui/FilesActivityUiTest.java
@@ -21,6 +21,7 @@
 
 import android.os.RemoteException;
 import android.test.suitebuilder.annotation.LargeTest;
+import android.test.suitebuilder.annotation.Suppress;
 import android.view.KeyEvent;
 
 import com.android.documentsui.model.RootInfo;
@@ -71,11 +72,11 @@
         bots.directory.assertDocumentsPresent("file0.log", "file1.png", "file2.csv");
     }
 
-    public void testLoadsHomeDirectoryByDefault() throws Exception {
+    public void testLoadsDownloadsDirectoryByDefault() throws Exception {
         initTestFiles();
 
         device.waitForIdle();
-        bots.main.assertWindowTitle("Documents");
+        bots.main.assertWindowTitle("Downloads");
     }
 
     public void testRootClickSetsWindowTitle() throws Exception {
@@ -119,27 +120,27 @@
         device.waitForIdle();
         bots.main.menuDelete().click();
 
-        bots.directory.waitForDeleteSnackbar();
+        bots.main.findDialogOkButton().click();
+
         bots.directory.assertDocumentsAbsent("file1.png");
+    }
 
-        bots.directory.waitForDeleteSnackbarGone();
-        bots.directory.assertDocumentsAbsent("file1.png");
+    public void testDeleteDocument_Cancel() throws Exception {
+        initTestFiles();
 
-        // Now delete from another root.
-        bots.roots.openRoot(ROOT_1_ID);
+        bots.roots.openRoot(ROOT_0_ID);
 
-        bots.directory.clickDocument("poodles.text");
+        bots.directory.clickDocument("file1.png");
         device.waitForIdle();
         bots.main.menuDelete().click();
 
-        bots.directory.waitForDeleteSnackbar();
-        bots.directory.assertDocumentsAbsent("poodles.text");
+        bots.main.findDialogCancelButton().click();
 
-        bots.directory.waitForDeleteSnackbarGone();
-        bots.directory.assertDocumentsAbsent("poodles.text");
+        bots.directory.assertDocumentsPresent("file1.png");
     }
 
     // Tests that pressing tab switches focus between the roots and directory listings.
+    @Suppress
     public void testKeyboard_tab() throws Exception {
         bots.main.pressKey(KeyEvent.KEYCODE_TAB);
         bots.roots.assertHasFocus();
@@ -148,6 +149,7 @@
     }
 
     // Tests that arrow keys do not switch focus away from the dir list.
+    @Suppress
     public void testKeyboard_arrowsDirList() throws Exception {
         for (int i = 0; i < 10; i++) {
             bots.main.pressKey(KeyEvent.KEYCODE_DPAD_LEFT);
diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/RenameDocumentUiTest.java b/packages/DocumentsUI/tests/src/com/android/documentsui/RenameDocumentUiTest.java
index 2833418..9a06807 100644
--- a/packages/DocumentsUI/tests/src/com/android/documentsui/RenameDocumentUiTest.java
+++ b/packages/DocumentsUI/tests/src/com/android/documentsui/RenameDocumentUiTest.java
@@ -16,9 +16,8 @@
 
 package com.android.documentsui;
 
-import static com.android.documentsui.StubProvider.ROOT_0_ID;
-
 import android.test.suitebuilder.annotation.LargeTest;
+import android.test.suitebuilder.annotation.Suppress;
 
 @LargeTest
 public class RenameDocumentUiTest extends ActivityTest<FilesActivity> {
@@ -73,6 +72,7 @@
         device.pressBack();
     }
 
+    @Suppress
     public void testRenameFile_OkButton() throws Exception {
         bots.directory.selectDocument(fileName1);
         bots.main.openOverflowMenu();
@@ -80,7 +80,7 @@
         bots.main.setDialogText(newName);
 
         device.waitForIdle(TIMEOUT);
-        bots.main.findRenameDialogOkButton().click();
+        bots.main.findDialogOkButton().click();
         device.waitForIdle(TIMEOUT);
 
         bots.directory.assertDocumentsAbsent(fileName1);
@@ -101,6 +101,7 @@
         bots.directory.assertDocumentsCount(4);
     }
 
+    @Suppress
     public void testRenameFile_Cancel() throws Exception {
         bots.directory.selectDocument(fileName1);
         bots.main.openOverflowMenu();
@@ -108,7 +109,7 @@
         bots.main.setDialogText(newName);
 
         device.waitForIdle(TIMEOUT);
-        bots.main.findRenameDialogCancelButton().click();
+        bots.main.findDialogCancelButton().click();
         device.waitForIdle(TIMEOUT);
 
         bots.directory.assertDocumentsPresent(fileName1);
diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/RootsCacheTest.java b/packages/DocumentsUI/tests/src/com/android/documentsui/RootsCacheTest.java
index 7d3498e..e73dd8c 100644
--- a/packages/DocumentsUI/tests/src/com/android/documentsui/RootsCacheTest.java
+++ b/packages/DocumentsUI/tests/src/com/android/documentsui/RootsCacheTest.java
@@ -16,6 +16,9 @@
 
 package com.android.documentsui;
 
+import static com.android.documentsui.RootsCache.getMatchingRoots;
+import static com.google.common.collect.Lists.newArrayList;
+
 import android.test.AndroidTestCase;
 import android.test.suitebuilder.annotation.SmallTest;
 
@@ -28,23 +31,18 @@
 @SmallTest
 public class RootsCacheTest extends AndroidTestCase {
 
-    private static RootInfo buildForMimeTypes(String... mimeTypes) {
-        final RootInfo root = new RootInfo();
-        root.derivedMimeTypes = mimeTypes;
-        return root;
-    }
+    private static RootInfo mNull = new RootInfo();
+    private static RootInfo mEmpty = buildForMimeTypes();
+    private static RootInfo mWild = buildForMimeTypes("*/*");
+    private static RootInfo mImages = buildForMimeTypes("image/*");
+    private static RootInfo mAudio = buildForMimeTypes(
+            "audio/*", "application/ogg", "application/x-flac");
+    private static RootInfo mDocs = buildForMimeTypes(
+            "application/msword", "application/vnd.ms-excel");
+    private static RootInfo mMalformed1 = buildForMimeTypes("meow");
+    private static RootInfo mMalformed2 = buildForMimeTypes("*/meow");
 
-    private RootInfo mNull = new RootInfo();
-    private RootInfo mEmpty = buildForMimeTypes();
-    private RootInfo mWild = buildForMimeTypes("*/*");
-    private RootInfo mImages = buildForMimeTypes("image/*");
-    private RootInfo mAudio = buildForMimeTypes("audio/*", "application/ogg", "application/x-flac");
-    private RootInfo mDocs = buildForMimeTypes("application/msword", "application/vnd.ms-excel");
-    private RootInfo mMalformed1 = buildForMimeTypes("meow");
-    private RootInfo mMalformed2 = buildForMimeTypes("*/meow");
-
-    private List<RootInfo> mRoots = Lists.newArrayList(
-            mNull, mWild, mEmpty, mImages, mAudio, mDocs, mMalformed1, mMalformed2);
+    private List<RootInfo> mRoots;
 
     private State mState;
 
@@ -52,70 +50,86 @@
     protected void setUp() throws Exception {
         super.setUp();
 
+        mRoots = Lists.newArrayList(
+                mNull, mWild, mEmpty, mImages, mAudio, mDocs, mMalformed1, mMalformed2);
+
         mState = new State();
         mState.action = State.ACTION_OPEN;
-        mState.showAdvanced = true;
         mState.localOnly = false;
     }
 
-    public void testMatchingRootsEverything() throws Exception {
+    public void testMatchingRoots_Everything() throws Exception {
         mState.acceptMimes = new String[] { "*/*" };
         assertContainsExactly(
-                Lists.newArrayList(mNull, mWild, mImages, mAudio, mDocs, mMalformed1, mMalformed2),
-                RootsCache.getMatchingRoots(mRoots, mState));
+                newArrayList(mNull, mWild, mImages, mAudio, mDocs, mMalformed1, mMalformed2),
+                getMatchingRoots(mRoots, mState));
     }
 
-    public void testMatchingRootsPngOrWild() throws Exception {
+    public void testMatchingRoots_DirectoryCopy() throws Exception {
+        RootInfo downloads = buildForMimeTypes("*/*");
+        downloads.authority = "com.android.providers.downloads.documents";
+        mRoots.add(downloads);
+
+        mState.acceptMimes = new String[] { "*/*" };
+        mState.directoryCopy = true;
+
+        // basically we're asserting that the results don't contain downloads
+        assertContainsExactly(
+                newArrayList(mNull, mWild, mImages, mAudio, mDocs, mMalformed1, mMalformed2),
+                getMatchingRoots(mRoots, mState));
+    }
+
+    public void testMatchingRoots_PngOrWild() throws Exception {
         mState.acceptMimes = new String[] { "image/png", "*/*" };
         assertContainsExactly(
-                Lists.newArrayList(mNull, mWild, mImages, mAudio, mDocs, mMalformed1, mMalformed2),
-                RootsCache.getMatchingRoots(mRoots, mState));
+                newArrayList(mNull, mWild, mImages, mAudio, mDocs, mMalformed1, mMalformed2),
+                getMatchingRoots(mRoots, mState));
     }
 
-    public void testMatchingRootsAudioWild() throws Exception {
+    public void testMatchingRoots_AudioWild() throws Exception {
         mState.acceptMimes = new String[] { "audio/*" };
         assertContainsExactly(
-                Lists.newArrayList(mNull, mWild, mAudio),
-                RootsCache.getMatchingRoots(mRoots, mState));
+                newArrayList(mNull, mWild, mAudio),
+                getMatchingRoots(mRoots, mState));
     }
 
-    public void testMatchingRootsAudioWildOrImageWild() throws Exception {
+    public void testMatchingRoots_AudioWildOrImageWild() throws Exception {
         mState.acceptMimes = new String[] { "audio/*", "image/*" };
         assertContainsExactly(
-                Lists.newArrayList(mNull, mWild, mAudio, mImages),
-                RootsCache.getMatchingRoots(mRoots, mState));
+                newArrayList(mNull, mWild, mAudio, mImages),
+                getMatchingRoots(mRoots, mState));
     }
 
-    public void testMatchingRootsAudioSpecific() throws Exception {
+    public void testMatchingRoots_AudioSpecific() throws Exception {
         mState.acceptMimes = new String[] { "audio/mpeg" };
         assertContainsExactly(
-                Lists.newArrayList(mNull, mWild, mAudio),
-                RootsCache.getMatchingRoots(mRoots, mState));
+                newArrayList(mNull, mWild, mAudio),
+                getMatchingRoots(mRoots, mState));
     }
 
-    public void testMatchingRootsDocument() throws Exception {
+    public void testMatchingRoots_Document() throws Exception {
         mState.acceptMimes = new String[] { "application/msword" };
         assertContainsExactly(
-                Lists.newArrayList(mNull, mWild, mDocs),
-                RootsCache.getMatchingRoots(mRoots, mState));
+                newArrayList(mNull, mWild, mDocs),
+                getMatchingRoots(mRoots, mState));
     }
 
-    public void testMatchingRootsApplication() throws Exception {
+    public void testMatchingRoots_Application() throws Exception {
         mState.acceptMimes = new String[] { "application/*" };
         assertContainsExactly(
-                Lists.newArrayList(mNull, mWild, mAudio, mDocs),
-                RootsCache.getMatchingRoots(mRoots, mState));
+                newArrayList(mNull, mWild, mAudio, mDocs),
+                getMatchingRoots(mRoots, mState));
     }
 
-    public void testMatchingRootsFlacOrPng() throws Exception {
+    public void testMatchingRoots_FlacOrPng() throws Exception {
         mState.acceptMimes = new String[] { "application/x-flac", "image/png" };
         assertContainsExactly(
-                Lists.newArrayList(mNull, mWild, mAudio, mImages),
-                RootsCache.getMatchingRoots(mRoots, mState));
+                newArrayList(mNull, mWild, mAudio, mImages),
+                getMatchingRoots(mRoots, mState));
     }
 
     public void testExcludedAuthorities() throws Exception {
-        final List<RootInfo> roots = Lists.newArrayList();
+        final List<RootInfo> roots = newArrayList();
 
         // Set up some roots
         for (int i = 0; i < 5; ++i) {
@@ -124,7 +138,7 @@
             roots.add(root);
         }
         // Make some allowed authorities
-        List<RootInfo> allowedRoots = Lists.newArrayList(
+        List<RootInfo> allowedRoots = newArrayList(
             roots.get(0), roots.get(2), roots.get(4));
         // Set up the excluded authority list
         for (RootInfo root: roots) {
@@ -136,7 +150,7 @@
 
         assertContainsExactly(
             allowedRoots,
-            RootsCache.getMatchingRoots(roots, mState));
+            getMatchingRoots(roots, mState));
     }
 
     private static void assertContainsExactly(List<?> expected, List<?> actual) {
@@ -145,4 +159,10 @@
             assertTrue(actual.contains(o));
         }
     }
+
+    private static RootInfo buildForMimeTypes(String... mimeTypes) {
+        final RootInfo root = new RootInfo();
+        root.derivedMimeTypes = mimeTypes;
+        return root;
+    }
 }
diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/RootsUiTest.java b/packages/DocumentsUI/tests/src/com/android/documentsui/RootsUiTest.java
index 6141832..621410a 100644
--- a/packages/DocumentsUI/tests/src/com/android/documentsui/RootsUiTest.java
+++ b/packages/DocumentsUI/tests/src/com/android/documentsui/RootsUiTest.java
@@ -17,8 +17,10 @@
 package com.android.documentsui;
 
 import static com.android.documentsui.StubProvider.ROOT_0_ID;
+import static com.android.documentsui.StubProvider.ROOT_1_ID;
 
 import android.test.suitebuilder.annotation.LargeTest;
+import android.test.suitebuilder.annotation.Suppress;
 
 @LargeTest
 public class RootsUiTest extends ActivityTest<FilesActivity> {
@@ -42,4 +44,14 @@
         bots.main.assertWindowTitle(ROOT_0_ID);
         assertDefaultContentOfTestDir0();
     }
+
+    @Suppress
+    public void testRootChanged_ClearSelection() throws Exception {
+        bots.directory.selectDocument(fileName1);
+        bots.main.assertInActionMode(true);
+
+        bots.roots.openRoot(ROOT_1_ID);
+        bots.main.assertInActionMode(false);
+    }
+
 }
diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/SearchViewUiTest.java b/packages/DocumentsUI/tests/src/com/android/documentsui/SearchViewUiTest.java
index 8c3fd90..a9451a6 100644
--- a/packages/DocumentsUI/tests/src/com/android/documentsui/SearchViewUiTest.java
+++ b/packages/DocumentsUI/tests/src/com/android/documentsui/SearchViewUiTest.java
@@ -20,6 +20,7 @@
 import static com.android.documentsui.StubProvider.ROOT_1_ID;
 
 import android.test.suitebuilder.annotation.LargeTest;
+import android.test.suitebuilder.annotation.Suppress;
 
 @LargeTest
 public class SearchViewUiTest extends ActivityTest<FilesActivity> {
@@ -28,6 +29,7 @@
         super(FilesActivity.class);
     }
 
+    @Suppress
     public void testSearchView_ExpandsOnClick() throws Exception {
         bots.main.openSearchView();
         bots.main.assertSearchTextFiledAndIcon(true, false);
@@ -41,6 +43,7 @@
         bots.main.assertSearchTextFiledAndIcon(false, true);
     }
 
+    @Suppress
     public void testSearchView_ClearsTextOnBack() throws Exception {
         String query = "file2";
         bots.main.openSearchView();
@@ -51,6 +54,7 @@
         bots.main.assertSearchTextFiledAndIcon(false, true);
     }
 
+    @Suppress
     public void testSearch_ResultsFound() throws Exception {
         initTestFiles();
         assertDefaultContentOfTestDir0();
@@ -68,6 +72,7 @@
         bots.main.assertSearchTextField(false, query);
     }
 
+    @Suppress
     public void testSearchResultsFound_ClearsOnBack() throws Exception {
         initTestFiles();
         assertDefaultContentOfTestDir0();
@@ -82,6 +87,7 @@
         assertDefaultContentOfTestDir0();
     }
 
+    @Suppress
     public void testSearch_NoResults() throws Exception {
         initTestFiles();
         assertDefaultContentOfTestDir0();
@@ -101,6 +107,7 @@
         bots.main.assertSearchTextField(false, query);
     }
 
+    @Suppress
     public void testSearchNoResults_ClearsOnBack() throws Exception {
         initTestFiles();
         assertDefaultContentOfTestDir0();
@@ -116,6 +123,7 @@
         assertDefaultContentOfTestDir0();
     }
 
+    @Suppress
     public void testSearchResultsFound_ClearsOnDirectoryChange() throws Exception {
         initTestFiles();
         assertDefaultContentOfTestDir0();
diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/StubProvider.java b/packages/DocumentsUI/tests/src/com/android/documentsui/StubProvider.java
index 2527650..f71ce5d 100644
--- a/packages/DocumentsUI/tests/src/com/android/documentsui/StubProvider.java
+++ b/packages/DocumentsUI/tests/src/com/android/documentsui/StubProvider.java
@@ -518,28 +518,29 @@
         String rootId = extras.getString(EXTRA_PARENT_ID);
         String mimeType = extras.getString(Document.COLUMN_MIME_TYPE);
         String name = extras.getString(Document.COLUMN_DISPLAY_NAME);
+        List<String> streamTypes = extras.getStringArrayList(EXTRA_STREAM_TYPES);
         int flags = extras.getInt(EXTRA_FLAGS);
 
         Bundle out = new Bundle();
         String documentId = null;
         try {
-            documentId = createDocument(rootId, mimeType, name, flags);
+            documentId = createDocument(rootId, mimeType, name, flags, streamTypes);
             Uri uri = DocumentsContract.buildDocumentUri(mAuthority, documentId);
             out.putParcelable(DocumentsContract.EXTRA_URI, uri);
         } catch (FileNotFoundException e) {
-            Log.d(TAG, "Cretaing document with flags failed" + name);
+            Log.d(TAG, "Creating document with flags failed" + name);
         }
         return out;
     }
 
-    public String createDocument(String parentId, String mimeType, String displayName, int flags)
-            throws FileNotFoundException {
+    public String createDocument(String parentId, String mimeType, String displayName, int flags,
+            List<String> streamTypes) throws FileNotFoundException {
 
         StubDocument parent = mStorage.get(parentId);
         File file = createFile(parent, mimeType, displayName);
 
         final StubDocument document = StubDocument.createDocumentWithFlags(file, mimeType, parent,
-                flags);
+                flags, streamTypes);
         mStorage.put(document.documentId, document);
         Log.d(TAG, "Created document " + document.documentId);
         notifyParentChanged(document.parentId);
@@ -787,8 +788,9 @@
         }
 
         public static StubDocument createDocumentWithFlags(
-                File file, String mimeType, StubDocument parent, int flags) {
-            return new StubDocument(file, mimeType, new ArrayList<String>(), flags, parent);
+                File file, String mimeType, StubDocument parent, int flags,
+                List<String> streamTypes) {
+            return new StubDocument(file, mimeType, streamTypes, flags, parent);
         }
 
         public static StubDocument createVirtualDocument(
diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/bots/UiBot.java b/packages/DocumentsUI/tests/src/com/android/documentsui/bots/UiBot.java
index fe2a3c3..11f5194 100644
--- a/packages/DocumentsUI/tests/src/com/android/documentsui/bots/UiBot.java
+++ b/packages/DocumentsUI/tests/src/com/android/documentsui/bots/UiBot.java
@@ -88,6 +88,11 @@
         assertEquals(searchIconExists, findSearchViewIcon().exists());
     }
 
+    public void assertInActionMode(boolean inActionMode) {
+        UiObject actionModeBar = findActionModeBar();
+        assertEquals(inActionMode, actionModeBar.exists());
+    }
+
     public void openSearchView() throws UiObjectNotFoundException {
         UiObject searchView = findSearchView();
         searchView.click();
@@ -168,12 +173,16 @@
         return findObject("android:id/content", "android:id/text1");
     }
 
-    public UiObject findRenameDialogOkButton() {
-        return findObject("android:id/content", "android:id/button1");
+    public UiObject findDialogOkButton() {
+        UiObject object = findObject("android:id/content", "android:id/button1");
+        object.waitForExists(mTimeout);
+        return object;
     }
 
-    public UiObject findRenameDialogCancelButton() {
-        return findObject("android:id/content", "android:id/button2");
+    public UiObject findDialogCancelButton() {
+        UiObject object = findObject("android:id/content", "android:id/button2");
+        object.waitForExists(mTimeout);
+        return object;
     }
 
     UiObject findMenuLabelWithName(String label) {
@@ -203,16 +212,6 @@
         return mDevice.findObject(selector);
     }
 
-    public void revealLauncher() {
-        mDevice.pressHome();
-        mDevice.wait(Until.hasObject(By.pkg(LAUNCHER_PKG).depth(0)), mTimeout);
-    }
-
-    public void revealApp() {
-        mDevice.wait(Until.hasObject(By.pkg(TARGET_PKG).depth(0)), mTimeout);
-        mDevice.waitForIdle();
-    }
-
     public void pressKey(int keyCode) {
         mDevice.pressKeyCode(keyCode);
     }
diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/dirlist/ModelBackedDocumentsAdapterTest.java b/packages/DocumentsUI/tests/src/com/android/documentsui/dirlist/ModelBackedDocumentsAdapterTest.java
index 2244be9..7ab51ba2 100644
--- a/packages/DocumentsUI/tests/src/com/android/documentsui/dirlist/ModelBackedDocumentsAdapterTest.java
+++ b/packages/DocumentsUI/tests/src/com/android/documentsui/dirlist/ModelBackedDocumentsAdapterTest.java
@@ -68,33 +68,11 @@
 
     // Tests that the item count is correct.
     public void testHide_ItemCount() {
-        List<String> ids = mModel.getModelIds();
-        mAdapter.hide(ids.get(0), ids.get(1));
+        String[] ids = mModel.getModelIds();
+        mAdapter.hide(ids[0], ids[1]);
         assertEquals(mModel.getItemCount() - 2, mAdapter.getItemCount());
     }
 
-    // Tests that the items can be hidden and unhidden.
-    public void testUnhide_ItemCount() {
-        List<String> ids = mModel.getModelIds();
-        SparseArray<String> hidden = mAdapter.hide(ids.toArray(new String[ids.size()]));
-        mAdapter.unhide(hidden);
-        assertEquals(mModel.getItemCount(), mAdapter.getItemCount());
-    }
-
-    // Tests that the items can be hidden and unhidden.
-    public void testUnhide_PreservesOrder() {
-        List<String> ids = mModel.getModelIds();
-        SparseArray<String> hidden = mAdapter.hide(
-                ids.get(0), ids.get(1), ids.get(5), ids.get(9));
-        mAdapter.unhide(hidden);
-
-        // Finally ensure the restored items are in the original order
-        // by checking them against the model.
-        for (int i = 0; i < mAdapter.getItemCount(); i++) {
-            assertEquals(mModel.idForPosition(i), mAdapter.getModelId(i));
-        }
-    }
-
     private final class TestEnvironment implements DocumentsAdapter.Environment {
         private final Context testContext;
 
diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/dirlist/ModelTest.java b/packages/DocumentsUI/tests/src/com/android/documentsui/dirlist/ModelTest.java
index 4b0bc41..c6ad511 100644
--- a/packages/DocumentsUI/tests/src/com/android/documentsui/dirlist/ModelTest.java
+++ b/packages/DocumentsUI/tests/src/com/android/documentsui/dirlist/ModelTest.java
@@ -107,7 +107,7 @@
 
         assertTrue(model.isEmpty());
         assertEquals(0, model.getItemCount());
-        assertEquals(0, model.getModelIds().size());
+        assertEquals(0, model.getModelIds().length);
     }
 
     // Tests that the item count is correct.
@@ -165,10 +165,10 @@
 
     // Tests the base case for Model.getItem.
     public void testGetItem() {
-        List<String> ids = model.getModelIds();
-        assertEquals(ITEM_COUNT, ids.size());
+        String[] ids = model.getModelIds();
+        assertEquals(ITEM_COUNT, ids.length);
         for (int i = 0; i < ITEM_COUNT; ++i) {
-            Cursor c = model.getItem(ids.get(i));
+            Cursor c = model.getItem(ids[i]);
             assertEquals(i, c.getPosition());
         }
     }
@@ -292,14 +292,14 @@
         r.sortOrder = State.SORT_ORDER_LAST_MODIFIED;
         model.update(r);
 
-        List<String> ids = model.getModelIds();
+        String[] ids = model.getModelIds();
 
         // Check that all items were accounted for
-        assertEquals(ITEM_COUNT + DL_COUNT, ids.size());
+        assertEquals(ITEM_COUNT + DL_COUNT, ids.length);
 
         // Check that active downloads are sorted to the top.
         for (int i = 0; i < DL_COUNT; i++) {
-            assertTrue(currentDownloads.contains(ids.get(i)));
+            assertTrue(currentDownloads.contains(ids[i]));
         }
     }
 
@@ -316,11 +316,11 @@
     }
 
     private Selection positionToSelection(int... positions) {
-        List<String> ids = model.getModelIds();
+        String[] ids = model.getModelIds();
         Selection s = new Selection();
         // Construct a selection of the given positions.
         for (int p: positions) {
-            s.add(ids.get(p));
+            s.add(ids[p]);
         }
         return s;
     }
diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/dirlist/TestDocumentsAdapter.java b/packages/DocumentsUI/tests/src/com/android/documentsui/dirlist/TestDocumentsAdapter.java
index 267f47d..e170dbb 100644
--- a/packages/DocumentsUI/tests/src/com/android/documentsui/dirlist/TestDocumentsAdapter.java
+++ b/packages/DocumentsUI/tests/src/com/android/documentsui/dirlist/TestDocumentsAdapter.java
@@ -61,11 +61,6 @@
     }
 
     @Override
-    void unhide(SparseArray<String> ids) {
-        throw new UnsupportedOperationException();
-    }
-
-    @Override
     public DocumentHolder onCreateViewHolder(ViewGroup parent, int viewType) {
         throw new UnsupportedOperationException();
     }
diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/services/CopyJobTest.java b/packages/DocumentsUI/tests/src/com/android/documentsui/services/CopyJobTest.java
index 543396e..bb7c01a 100644
--- a/packages/DocumentsUI/tests/src/com/android/documentsui/services/CopyJobTest.java
+++ b/packages/DocumentsUI/tests/src/com/android/documentsui/services/CopyJobTest.java
@@ -16,6 +16,10 @@
 
 package com.android.documentsui.services;
 
+import static com.google.common.collect.Lists.newArrayList;
+
+import android.net.Uri;
+import android.provider.DocumentsContract.Document;
 import android.test.suitebuilder.annotation.MediumTest;
 
 import com.android.documentsui.model.DocumentInfo;
@@ -38,6 +42,21 @@
         runCopyVirtualNonTypedFileTest();
     }
 
+    public void testCopy_BackendSideVirtualTypedFile_Fallback() throws Exception {
+        mDocs.assertChildCount(mDestRoot, 0);
+
+        Uri testFile = mDocs.createDocumentWithFlags(
+                mSrcRoot.documentId, "virtual/mime-type", "tokyo.sth",
+                Document.FLAG_VIRTUAL_DOCUMENT | Document.FLAG_SUPPORTS_COPY
+                        | Document.FLAG_SUPPORTS_MOVE, "application/pdf");
+
+        createJob(newArrayList(testFile)).run();
+
+        mJobListener.waitForFinished();
+        mDocs.assertChildCount(mDestRoot, 1);
+        mDocs.assertHasFile(mDestRoot, "tokyo.sth.pdf");  // Copy should convert file to PDF.
+    }
+
     public void testCopyEmptyDir() throws Exception {
         runCopyEmptyDirTest();
     }
diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/services/MoveJobTest.java b/packages/DocumentsUI/tests/src/com/android/documentsui/services/MoveJobTest.java
index 749264a..24181d6 100644
--- a/packages/DocumentsUI/tests/src/com/android/documentsui/services/MoveJobTest.java
+++ b/packages/DocumentsUI/tests/src/com/android/documentsui/services/MoveJobTest.java
@@ -59,6 +59,21 @@
         mDocs.assertChildCount(mSrcRoot, 1);
     }
 
+    public void testMove_BackendSideVirtualTypedFile_Fallback() throws Exception {
+        Uri testFile = mDocs.createDocumentWithFlags(
+                mSrcRoot.documentId, "virtual/mime-type", "tokyo.sth",
+                Document.FLAG_VIRTUAL_DOCUMENT | Document.FLAG_SUPPORTS_COPY
+                        | Document.FLAG_SUPPORTS_MOVE, "application/pdf");
+
+        createJob(newArrayList(testFile)).run();
+        mJobListener.waitForFinished();
+
+        // Should have failed, source not deleted. Moving by bytes for virtual files
+        // is not supported.
+        mDocs.assertChildCount(mDestRoot, 0);
+        mDocs.assertChildCount(mSrcRoot, 1);
+    }
+
     public void testMoveEmptyDir() throws Exception {
         runCopyEmptyDirTest();
 
diff --git a/packages/ExtServices/AndroidManifest.xml b/packages/ExtServices/AndroidManifest.xml
index 100b35c..519db66 100644
--- a/packages/ExtServices/AndroidManifest.xml
+++ b/packages/ExtServices/AndroidManifest.xml
@@ -15,18 +15,27 @@
 -->
 
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
     package="android.ext.services"
     android:versionCode="1"
     android:versionName="1"
     coreApp="true">
 
     <application android:label="@string/app_name"
-        android:allowBackup="false"
         android:forceDeviceEncrypted="true"
         android:encryptionAware="true">
 
         <library android:name="android.ext.services"/>
 
+        <service android:name=".notification.Ranker"
+                android:label="@string/notification_ranker"
+                android:permission="android.permission.BIND_NOTIFICATION_RANKER_SERVICE"
+                android:exported="true">
+            <intent-filter>
+                <action android:name="android.service.notification.NotificationRankerService" />
+            </intent-filter>
+        </service>
+
     </application>
 
 </manifest>
diff --git a/packages/ExtServices/res/values/strings.xml b/packages/ExtServices/res/values/strings.xml
index 531e517..0763403 100644
--- a/packages/ExtServices/res/values/strings.xml
+++ b/packages/ExtServices/res/values/strings.xml
@@ -16,4 +16,5 @@
 
 <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_name">Android Services Library</string>
+    <string name="notification_ranker">Android Notification Ranking Service</string>
 </resources>
diff --git a/packages/ExtServices/src/android/ext/services/notification/Ranker.java b/packages/ExtServices/src/android/ext/services/notification/Ranker.java
new file mode 100644
index 0000000..0b2b1a4
--- /dev/null
+++ b/packages/ExtServices/src/android/ext/services/notification/Ranker.java
@@ -0,0 +1,46 @@
+/*
+ * 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.ext.services.notification;
+
+import android.service.notification.NotificationRankerService;
+import android.service.notification.StatusBarNotification;
+import android.util.Log;
+
+/**
+ * Class that provides an updatable ranker module for the notification manager..
+ */
+public final class Ranker extends NotificationRankerService {
+    private static final String TAG = "RocketRanker";
+    private static final boolean DEBUG =  Log.isLoggable(TAG, Log.DEBUG);;
+
+    @Override
+    public Adjustment onNotificationEnqueued(StatusBarNotification sbn, int importance,
+            boolean user) {
+        if (DEBUG) Log.i(TAG, "ENQUEUED " + sbn.getKey());
+        return null;
+    }
+
+    @Override
+    public void onNotificationPosted(StatusBarNotification sbn) {
+        if (DEBUG) Log.i(TAG, "POSTED " + sbn.getKey());
+    }
+
+    @Override
+    public void onListenerConnected() {
+        if (DEBUG) Log.i(TAG, "CONNECTED");
+    }
+}
\ No newline at end of file
diff --git a/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java b/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
index 97dfd47..9a51b05 100644
--- a/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
+++ b/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
@@ -34,6 +34,7 @@
 import android.os.ParcelFileDescriptor;
 import android.os.ParcelFileDescriptor.OnCloseListener;
 import android.os.UserHandle;
+import android.os.storage.DiskInfo;
 import android.os.storage.StorageManager;
 import android.os.storage.VolumeInfo;
 import android.provider.DocumentsContract;
@@ -41,6 +42,7 @@
 import android.provider.DocumentsContract.Root;
 import android.provider.DocumentsProvider;
 import android.provider.MediaStore;
+import android.provider.Settings;
 import android.support.provider.DocumentArchiveHelper;
 import android.text.TextUtils;
 import android.util.ArrayMap;
@@ -62,6 +64,7 @@
 public class ExternalStorageProvider extends DocumentsProvider {
     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";
@@ -136,10 +139,25 @@
             if (volume.getType() == VolumeInfo.TYPE_EMULATED) {
                 // We currently only support a single emulated volume mounted at
                 // a time, and it's always considered the primary
+                if (DEBUG) Log.d(TAG, "Found primary volume: " + volume);
                 rootId = ROOT_ID_PRIMARY_EMULATED;
+
                 if (VolumeInfo.ID_EMULATED_INTERNAL.equals(volume.getId())) {
-                    title = getContext().getString(R.string.root_internal_storage);
+                    // This is basically the user's primary device storage.
+                    // Use device name for the volume since this is likely same thing
+                    // the user sees when they mount their phone on another device.
+                    String deviceName = Settings.Global.getString(
+                            getContext().getContentResolver(), Settings.Global.DEVICE_NAME);
+
+                    // Device name should always be set. In case it isn't, though,
+                    // fall back to a localized "Internal Storage" string.
+                    title = !TextUtils.isEmpty(deviceName)
+                            ? deviceName
+                            : getContext().getString(R.string.root_internal_storage);
                 } else {
+                    // This should cover all other storage devices, like an SD card
+                    // or USB OTG drive plugged in. Using getBestVolumeDescription()
+                    // will give us a nice string like "Samsung SD card" or "SanDisk USB drive"
                     final VolumeInfo privateVol = mStorageManager.findPrivateForEmulated(volume);
                     title = mStorageManager.getBestVolumeDescription(privateVol);
                 }
@@ -167,10 +185,17 @@
             root.flags = Root.FLAG_LOCAL_ONLY
                     | Root.FLAG_SUPPORTS_SEARCH | Root.FLAG_SUPPORTS_IS_CHILD;
 
+            final DiskInfo disk = volume.getDisk();
+            if (DEBUG) Log.d(TAG, "Disk for root " + rootId + " is " + disk);
+            if (disk != null && disk.isSd()) {
+                root.flags |= Root.FLAG_REMOVABLE_SD;
+            } else if (disk != null && disk.isUsb()) {
+                root.flags |= Root.FLAG_REMOVABLE_USB;
+            }
+
             if (volume.isPrimary()) {
                 // save off the primary volume for subsequent "Home" dir initialization.
                 primaryVolume = volume;
-                root.flags |= Root.FLAG_ADVANCED;
             }
             // Dunno when this would NOT be the case, but never hurts to be correct.
             if (volume.isMountedWritable()) {
@@ -193,8 +218,9 @@
             }
         }
 
-        // Finally, if primary storage is available we add the "Home" directory,
-        // creating it as needed.
+        // Finally, if primary storage is available we add the "Documents" directory.
+        // If I recall correctly the actual directory is created on demand
+        // by calling either getPathForUser, or getInternalPathForUser.
         if (primaryVolume != null && primaryVolume.isVisible()) {
             final RootInfo root = new RootInfo();
             root.rootId = ROOT_ID_HOME;
@@ -211,8 +237,7 @@
                 root.flags |= Root.FLAG_SUPPORTS_CREATE;
             }
 
-            // Create the "Home" directory on disk, but don't the localized root.title
-            // since the directories shouldn't be localized.
+            // Create the "Documents" directory on disk (don't use the localized title).
             root.visiblePath = new File(
                     primaryVolume.getPathForUser(userId), Environment.DIRECTORY_DOCUMENTS);
             root.path = new File(
@@ -391,6 +416,10 @@
             if (mArchiveHelper.isArchivedDocument(docId)) {
                 return mArchiveHelper.isChildDocument(parentDocId, docId);
             }
+            // Archives do not contain regular files.
+            if (mArchiveHelper.isArchivedDocument(parentDocId)) {
+                return false;
+            }
 
             final File parent = getFileForDocId(parentDocId).getCanonicalFile();
             final File doc = getFileForDocId(docId).getCanonicalFile();
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityContainer.java b/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityContainer.java
index 409f6a7..b1d42e7 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityContainer.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityContainer.java
@@ -519,6 +519,9 @@
     @Override
     public void showPromptReason(int reason) {
         if (mCurrentSecuritySelection != SecurityMode.None) {
+            if (reason != PROMPT_REASON_NONE) {
+                Log.i(TAG, "Strong auth required, reason: " + reason);
+            }
             getSecurityView(mCurrentSecuritySelection).showPromptReason(reason);
         }
     }
diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/AppFuse.java b/packages/MtpDocumentsProvider/src/com/android/mtp/AppFuse.java
index 6a98405..38435f4 100644
--- a/packages/MtpDocumentsProvider/src/com/android/mtp/AppFuse.java
+++ b/packages/MtpDocumentsProvider/src/com/android/mtp/AppFuse.java
@@ -133,6 +133,8 @@
             return mCallback.readObjectBytes(inode, offset, size, mBuffer);
         } catch (IOException e) {
             return -OsConstants.EIO;
+        } catch (UnsupportedOperationException e) {
+            return -OsConstants.ENOTSUP;
         }
     }
 
diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/DocumentLoader.java b/packages/MtpDocumentsProvider/src/com/android/mtp/DocumentLoader.java
index 712dbcb..0705214 100644
--- a/packages/MtpDocumentsProvider/src/com/android/mtp/DocumentLoader.java
+++ b/packages/MtpDocumentsProvider/src/com/android/mtp/DocumentLoader.java
@@ -47,16 +47,16 @@
     static final int NUM_LOADING_ENTRIES = 20;
     static final int NOTIFY_PERIOD_MS = 500;
 
-    private final int mDeviceId;
+    private final MtpDeviceRecord mDevice;
     private final MtpManager mMtpManager;
     private final ContentResolver mResolver;
     private final MtpDatabase mDatabase;
     private final TaskList mTaskList = new TaskList();
     private Thread mBackgroundThread;
 
-    DocumentLoader(int deviceId, MtpManager mtpManager, ContentResolver resolver,
+    DocumentLoader(MtpDeviceRecord device, MtpManager mtpManager, ContentResolver resolver,
                    MtpDatabase database) {
-        mDeviceId = deviceId;
+        mDevice = device;
         mMtpManager = mtpManager;
         mResolver = resolver;
         mDatabase = database;
@@ -69,7 +69,7 @@
      */
     synchronized Cursor queryChildDocuments(String[] columnNames, Identifier parent)
             throws IOException {
-        Preconditions.checkArgument(parent.mDeviceId == mDeviceId);
+        Preconditions.checkArgument(parent.mDeviceId == mDevice.deviceId);
         LoaderTask task = mTaskList.findTask(parent);
         if (task == null) {
             if (parent.mDocumentId == null) {
@@ -81,7 +81,7 @@
             // 3. startAddingChildDocuemnts.
             // 4. stopAddingChildDocuments - It removes the new document added at the step 2,
             //     because it is not updated between start/stopAddingChildDocuments.
-            task = LoaderTask.create(mDatabase, mMtpManager, parent);
+            task = LoaderTask.create(mDatabase, mMtpManager, mDevice.operationsSupported, parent);
             task.fillDocuments(loadDocuments(
                     mMtpManager,
                     parent.mDeviceId,
@@ -123,7 +123,7 @@
             return task;
         }
 
-        final Identifier identifier = mDatabase.getUnmappedDocumentsParent(mDeviceId);
+        final Identifier identifier = mDatabase.getUnmappedDocumentsParent(mDevice.deviceId);
         if (identifier != null) {
             final LoaderTask existingTask = mTaskList.findTask(identifier);
             if (existingTask != null) {
@@ -131,7 +131,8 @@
                 mTaskList.remove(existingTask);
             }
             try {
-                final LoaderTask newTask = LoaderTask.create(mDatabase, mMtpManager, identifier);
+                final LoaderTask newTask = LoaderTask.create(
+                        mDatabase, mMtpManager, mDevice.operationsSupported, identifier);
                 mTaskList.addFirst(newTask);
                 return newTask;
             } catch (IOException exception) {
@@ -275,14 +276,19 @@
         static final int STATE_ERROR = 2;
 
         final MtpDatabase mDatabase;
+        final int[] mOperationsSupported;
         final Identifier mIdentifier;
         final int[] mObjectHandles;
         Date mLastNotified;
         int mNumLoaded;
         Exception mError;
 
-        LoaderTask(MtpDatabase database, Identifier identifier, int[] objectHandles) {
+        LoaderTask(MtpDatabase database, int[] operationsSupported, Identifier identifier,
+                int[] objectHandles) {
+            Preconditions.checkNotNull(operationsSupported);
+            Preconditions.checkNotNull(objectHandles);
             mDatabase = database;
+            mOperationsSupported = operationsSupported;
             mIdentifier = identifier;
             mObjectHandles = objectHandles;
             mNumLoaded = 0;
@@ -355,7 +361,8 @@
                     mDatabase.getMapper().startAddingDocuments(mIdentifier.mDocumentId);
                 }
                 mDatabase.getMapper().putChildDocuments(
-                        mIdentifier.mDeviceId, mIdentifier.mDocumentId, objectInfoList);
+                        mIdentifier.mDeviceId, mIdentifier.mDocumentId, mOperationsSupported,
+                        objectInfoList);
                 mNumLoaded += objectInfoList.length;
                 if (getState() != STATE_LOADING) {
                     mDatabase.getMapper().stopAddingDocuments(mIdentifier.mDocumentId);
@@ -394,7 +401,8 @@
         /**
          * Creates a LoaderTask that loads children of the given document.
          */
-        static LoaderTask create(MtpDatabase database, MtpManager manager, Identifier parent)
+        static LoaderTask create(MtpDatabase database, MtpManager manager,
+                int[] operationsSupported, Identifier parent)
                 throws IOException {
             int parentHandle = parent.mObjectHandle;
             // Need to pass the special value MtpManager.OBJECT_HANDLE_ROOT_CHILDREN to
@@ -402,7 +410,7 @@
             if (parent.mDocumentType == MtpDatabaseConstants.DOCUMENT_TYPE_STORAGE) {
                 parentHandle = MtpManager.OBJECT_HANDLE_ROOT_CHILDREN;
             }
-            return new LoaderTask(database, parent, manager.getObjectHandles(
+            return new LoaderTask(database, operationsSupported, parent, manager.getObjectHandles(
                     parent.mDeviceId, parent.mStorageId, parentHandle));
         }
     }
diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/Mapper.java b/packages/MtpDocumentsProvider/src/com/android/mtp/Mapper.java
index 9578e6b..8058183 100644
--- a/packages/MtpDocumentsProvider/src/com/android/mtp/Mapper.java
+++ b/packages/MtpDocumentsProvider/src/com/android/mtp/Mapper.java
@@ -89,7 +89,8 @@
      * @return If roots are added or removed from the database.
      * @throws FileNotFoundException
      */
-    synchronized boolean putStorageDocuments(String parentDocumentId, MtpRoot[] roots)
+    synchronized boolean putStorageDocuments(
+            String parentDocumentId, int[] operationsSupported, MtpRoot[] roots)
             throws FileNotFoundException {
         final SQLiteDatabase database = mDatabase.getSQLiteDatabase();
         database.beginTransaction();
@@ -100,7 +101,11 @@
                 valuesList[i] = new ContentValues();
                 extraValuesList[i] = new ContentValues();
                 MtpDatabase.getStorageDocumentValues(
-                        valuesList[i], extraValuesList[i], parentDocumentId, roots[i]);
+                        valuesList[i],
+                        extraValuesList[i],
+                        parentDocumentId,
+                        operationsSupported,
+                        roots[i]);
             }
             final boolean changed = putDocuments(
                     parentDocumentId,
@@ -125,12 +130,14 @@
      * @param documents List of document information.
      * @throws FileNotFoundException
      */
-    synchronized void putChildDocuments(int deviceId, String parentId, MtpObjectInfo[] documents)
+    synchronized void putChildDocuments(
+            int deviceId, String parentId, int[] operationsSupported, MtpObjectInfo[] documents)
             throws FileNotFoundException {
         final ContentValues[] valuesList = new ContentValues[documents.length];
         for (int i = 0; i < documents.length; i++) {
             valuesList[i] = new ContentValues();
-            MtpDatabase.getObjectDocumentValues(valuesList[i], deviceId, parentId, documents[i]);
+            MtpDatabase.getObjectDocumentValues(
+                    valuesList[i], deviceId, parentId, operationsSupported, documents[i]);
         }
         putDocuments(
                 parentId,
diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDatabase.java b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDatabase.java
index e14109a..72ad2f6 100644
--- a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDatabase.java
+++ b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDatabase.java
@@ -32,6 +32,7 @@
 import android.media.MediaFile;
 import android.mtp.MtpConstants;
 import android.mtp.MtpObjectInfo;
+import android.net.Uri;
 import android.provider.DocumentsContract;
 import android.provider.DocumentsContract.Document;
 import android.provider.DocumentsContract.Root;
@@ -40,8 +41,9 @@
 import com.android.internal.util.Preconditions;
 
 import java.io.FileNotFoundException;
-import java.io.IOException;
+import java.util.HashSet;
 import java.util.Objects;
+import java.util.Set;
 
 /**
  * Database for MTP objects.
@@ -372,9 +374,10 @@
      * @param info
      * @return Document ID of added document.
      */
-    String putNewDocument(int deviceId, String parentDocumentId, MtpObjectInfo info) {
+    String putNewDocument(
+            int deviceId, String parentDocumentId, int[] operationsSupported, MtpObjectInfo info) {
         final ContentValues values = new ContentValues();
-        getObjectDocumentValues(values, deviceId, parentDocumentId, info);
+        getObjectDocumentValues(values, deviceId, parentDocumentId, operationsSupported, info);
         mDatabase.beginTransaction();
         try {
             final long id = mDatabase.insert(TABLE_DOCUMENTS, null, values);
@@ -582,9 +585,10 @@
         }
     }
 
-    void updateObject(String documentId, int deviceId, String parentId, MtpObjectInfo info) {
+    void updateObject(String documentId, int deviceId, String parentId, int[] operationsSupported,
+                      MtpObjectInfo info) {
         final ContentValues values = new ContentValues();
-        getObjectDocumentValues(values, deviceId, parentId, info);
+        getObjectDocumentValues(values, deviceId, parentId, operationsSupported, info);
 
         mDatabase.beginTransaction();
         try {
@@ -604,7 +608,7 @@
      * @param deviceId Device to find documents.
      * @return Identifier of found document or null.
      */
-    public @Nullable Identifier getUnmappedDocumentsParent(int deviceId) {
+    @Nullable Identifier getUnmappedDocumentsParent(int deviceId) {
         final String fromClosure =
                 TABLE_DOCUMENTS + " AS child INNER JOIN " +
                 TABLE_DOCUMENTS + " AS parent ON " +
@@ -641,6 +645,65 @@
         }
     }
 
+    /**
+     * Removes metadata except for data used by outgoingPersistedUriPermissions.
+     */
+    void cleanDatabase(Uri[] outgoingPersistedUris) {
+        mDatabase.beginTransaction();
+        try {
+            final Set<String> ids = new HashSet<>();
+            for (final Uri uri : outgoingPersistedUris) {
+                String documentId = DocumentsContract.getDocumentId(uri);
+                while (documentId != null) {
+                    if (ids.contains(documentId)) {
+                        break;
+                    }
+                    ids.add(documentId);
+                    try (final Cursor cursor = mDatabase.query(
+                            TABLE_DOCUMENTS,
+                            strings(COLUMN_PARENT_DOCUMENT_ID),
+                            SELECTION_DOCUMENT_ID,
+                            strings(documentId),
+                            null,
+                            null,
+                            null)) {
+                        documentId = cursor.moveToNext() ? cursor.getString(0) : null;
+                    }
+                }
+            }
+            deleteDocumentsAndRoots(
+                    Document.COLUMN_DOCUMENT_ID + " NOT IN " + getIdList(ids), null);
+            mDatabase.setTransactionSuccessful();
+        } finally {
+            mDatabase.endTransaction();
+        }
+    }
+
+    int getLastBootCount() {
+        try (final Cursor cursor = mDatabase.query(
+                TABLE_LAST_BOOT_COUNT, strings(COLUMN_VALUE), null, null, null, null, null)) {
+            if (cursor.moveToNext()) {
+                return cursor.getInt(0);
+            } else {
+                return 0;
+            }
+        }
+    }
+
+    void setLastBootCount(int value) {
+        Preconditions.checkArgumentNonnegative(value, "Boot count must not be negative.");
+        mDatabase.beginTransaction();
+        try {
+            final ContentValues values = new ContentValues();
+            values.put(COLUMN_VALUE, value);
+            mDatabase.delete(TABLE_LAST_BOOT_COUNT, null, null);
+            mDatabase.insert(TABLE_LAST_BOOT_COUNT, null, values);
+            mDatabase.setTransactionSuccessful();
+        } finally {
+            mDatabase.endTransaction();
+        }
+    }
+
     private static class OpenHelper extends SQLiteOpenHelper {
         public OpenHelper(Context context, int flags) {
             super(context,
@@ -653,12 +716,14 @@
         public void onCreate(SQLiteDatabase db) {
             db.execSQL(QUERY_CREATE_DOCUMENTS);
             db.execSQL(QUERY_CREATE_ROOT_EXTRA);
+            db.execSQL(QUERY_CREATE_LAST_BOOT_COUNT);
         }
 
         @Override
         public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
-            db.execSQL("DROP TABLE " + TABLE_DOCUMENTS);
-            db.execSQL("DROP TABLE " + TABLE_ROOT_EXTRA);
+            db.execSQL("DROP TABLE IF EXISTS " + TABLE_DOCUMENTS);
+            db.execSQL("DROP TABLE IF EXISTS " + TABLE_ROOT_EXTRA);
+            db.execSQL("DROP TABLE IF EXISTS " + TABLE_LAST_BOOT_COUNT);
             onCreate(db);
         }
     }
@@ -689,9 +754,7 @@
         values.putNull(Document.COLUMN_SIZE);
 
         extraValues.clear();
-        extraValues.put(
-                Root.COLUMN_FLAGS,
-                Root.FLAG_SUPPORTS_IS_CHILD | Root.FLAG_SUPPORTS_CREATE);
+        extraValues.put(Root.COLUMN_FLAGS, getRootFlags(device.operationsSupported));
         extraValues.putNull(Root.COLUMN_AVAILABLE_BYTES);
         extraValues.putNull(Root.COLUMN_CAPACITY_BYTES);
         extraValues.put(Root.COLUMN_MIME_TYPES, "");
@@ -700,12 +763,16 @@
     /**
      * Gets {@link ContentValues} for the given root.
      * @param values {@link ContentValues} that receives values.
+     * @param extraValues {@link ContentValues} that receives extra values for roots.
+     * @param parentDocumentId Parent document ID.
+     * @param supportedOperations Array of Operation code supported by the device.
      * @param root Root to be converted {@link ContentValues}.
      */
     static void getStorageDocumentValues(
             ContentValues values,
             ContentValues extraValues,
             String parentDocumentId,
+            int[] operationsSupported,
             MtpRoot root) {
         values.clear();
         values.put(COLUMN_DEVICE_ID, root.mDeviceId);
@@ -722,9 +789,7 @@
         values.put(Document.COLUMN_FLAGS, 0);
         values.put(Document.COLUMN_SIZE, root.mMaxCapacity - root.mFreeSpace);
 
-        extraValues.put(
-                Root.COLUMN_FLAGS,
-                Root.FLAG_SUPPORTS_IS_CHILD | Root.FLAG_SUPPORTS_CREATE);
+        extraValues.put(Root.COLUMN_FLAGS, getRootFlags(operationsSupported));
         extraValues.put(Root.COLUMN_AVAILABLE_BYTES, root.mFreeSpace);
         extraValues.put(Root.COLUMN_CAPACITY_BYTES, root.mMaxCapacity);
         extraValues.put(Root.COLUMN_MIME_TYPES, "");
@@ -738,20 +803,10 @@
      * @param info MTP object info.
      */
     static void getObjectDocumentValues(
-            ContentValues values, int deviceId, String parentId, MtpObjectInfo info) {
+            ContentValues values, int deviceId, String parentId, int[] operationsSupported,
+            MtpObjectInfo info) {
         values.clear();
         final String mimeType = getMimeType(info);
-        int flag = 0;
-        if (info.getProtectionStatus() == 0) {
-            flag |= Document.FLAG_SUPPORTS_DELETE |
-                    Document.FLAG_SUPPORTS_WRITE;
-            if (mimeType == Document.MIME_TYPE_DIR) {
-                flag |= Document.FLAG_DIR_SUPPORTS_CREATE;
-            }
-        }
-        if (info.getThumbCompressedSize() > 0) {
-            flag |= Document.FLAG_SUPPORTS_THUMBNAIL;
-        }
         values.put(COLUMN_DEVICE_ID, deviceId);
         values.put(COLUMN_STORAGE_ID, info.getStorageId());
         values.put(COLUMN_OBJECT_HANDLE, info.getObjectHandle());
@@ -765,8 +820,10 @@
                 Document.COLUMN_LAST_MODIFIED,
                 info.getDateModified() != 0 ? info.getDateModified() : null);
         values.putNull(Document.COLUMN_ICON);
-        values.put(Document.COLUMN_FLAGS, flag);
-        values.put(Document.COLUMN_SIZE, info.getCompressedSize());
+        values.put(Document.COLUMN_FLAGS, getDocumentFlags(
+                operationsSupported, mimeType, info.getThumbCompressedSizeLong(),
+                info.getProtectionStatus()));
+        values.put(Document.COLUMN_SIZE, info.getCompressedSizeLong());
     }
 
     private static String getMimeType(MtpObjectInfo info) {
@@ -785,6 +842,38 @@
         return "application/octet-stream";
     }
 
+    private static int getRootFlags(int[] operationsSupported) {
+        int rootFlag = Root.FLAG_SUPPORTS_IS_CHILD;
+        if (MtpDeviceRecord.isWritingSupported(operationsSupported)) {
+            rootFlag |= Root.FLAG_SUPPORTS_CREATE;
+        }
+        return rootFlag;
+    }
+
+    private static int getDocumentFlags(
+            int[] operationsSupported, String mimeType, long thumbnailSize, int protectionState) {
+        int flag = 0;
+        if (MtpDeviceRecord.isWritingSupported(operationsSupported) &&
+                protectionState == MtpConstants.PROTECTION_STATUS_NONE) {
+            flag |= Document.FLAG_SUPPORTS_WRITE;
+        }
+        if (MtpDeviceRecord.isSupported(
+                operationsSupported, MtpConstants.OPERATION_DELETE_OBJECT) &&
+                (protectionState == MtpConstants.PROTECTION_STATUS_NONE ||
+                 protectionState == MtpConstants.PROTECTION_STATUS_NON_TRANSFERABLE_DATA)) {
+            flag |= Document.FLAG_SUPPORTS_DELETE;
+        }
+        if (mimeType.equals(Document.MIME_TYPE_DIR) &&
+                MtpDeviceRecord.isWritingSupported(operationsSupported) &&
+                protectionState == MtpConstants.PROTECTION_STATUS_NONE) {
+            flag |= Document.FLAG_DIR_SUPPORTS_CREATE;
+        }
+        if (thumbnailSize > 0) {
+            flag |= Document.FLAG_SUPPORTS_THUMBNAIL;
+        }
+        return flag;
+    }
+
     static String[] strings(Object... args) {
         final String[] results = new String[args.length];
         for (int i = 0; i < args.length; i++) {
@@ -792,4 +881,16 @@
         }
         return results;
     }
+
+    private static String getIdList(Set<String> ids) {
+        String result = "(";
+        for (final String id : ids) {
+            if (result.length() > 1) {
+                result += ",";
+            }
+            result += id;
+        }
+        result += ")";
+        return result;
+    }
 }
diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDatabaseConstants.java b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDatabaseConstants.java
index ff4b89f..6d98e34 100644
--- a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDatabaseConstants.java
+++ b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDatabaseConstants.java
@@ -30,7 +30,7 @@
  * Class containing MtpDatabase constants.
  */
 class MtpDatabaseConstants {
-    static final int DATABASE_VERSION = 4;
+    static final int DATABASE_VERSION = 5;
     static final String DATABASE_NAME = "database";
 
     static final int FLAG_DATABASE_IN_MEMORY = 1;
@@ -48,6 +48,11 @@
     static final String TABLE_ROOT_EXTRA = "RootExtra";
 
     /**
+     * Table containing last boot count.
+     */
+    static final String TABLE_LAST_BOOT_COUNT = "LastBootCount";
+
+    /**
      * 'FROM' closure of joining TABLE_DOCUMENTS and TABLE_ROOT_EXTRA.
      */
     static final String JOIN_ROOTS = createJoinFromClosure(
@@ -62,7 +67,13 @@
     static final String COLUMN_PARENT_DOCUMENT_ID = "parent_document_id";
     static final String COLUMN_DOCUMENT_TYPE = "document_type";
     static final String COLUMN_ROW_STATE = "row_state";
-    static final String COLUMN_MAPPING_KEY = "column_mapping_key";
+    static final String COLUMN_MAPPING_KEY = "mapping_key";
+
+    /**
+     * Value for TABLE_LAST_BOOT_COUNT.
+     * Type: INTEGER
+     */
+    static final String COLUMN_VALUE = "value";
 
     /**
      * The state represents that the row has a valid object handle.
@@ -133,6 +144,9 @@
             Root.COLUMN_CAPACITY_BYTES + " INTEGER," +
             Root.COLUMN_MIME_TYPES + " TEXT NOT NULL);";
 
+    static final String QUERY_CREATE_LAST_BOOT_COUNT =
+            "CREATE TABLE " + TABLE_LAST_BOOT_COUNT + " (value INTEGER NOT NULL);";
+
     /**
      * Map for columns names to provide DocumentContract.Root compatible columns.
      * @see SQLiteQueryBuilder#setProjectionMap(Map)
diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDeviceRecord.java b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDeviceRecord.java
index 71716bd..393c4de 100644
--- a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDeviceRecord.java
+++ b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDeviceRecord.java
@@ -17,6 +17,7 @@
 package com.android.mtp;
 
 import android.annotation.Nullable;
+import android.mtp.MtpConstants;
 
 class MtpDeviceRecord {
     public final int deviceId;
@@ -38,4 +39,29 @@
         this.operationsSupported = operationsSupported;
         this.eventsSupported = eventsSupported;
     }
+
+    /**
+     * Helper method to check operations/events are supported by the device or not.
+     */
+    static boolean isSupported(@Nullable int[] supportedList, int code) {
+        if (supportedList == null) {
+            return false;
+        }
+        for (int i = 0; i < supportedList.length; i++) {
+            if (supportedList[i] == code) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    static boolean isPartialReadSupported(@Nullable int[] supportedList, long fileSize) {
+        return fileSize <= 0xffffffffl &&
+                 isSupported(supportedList, MtpConstants.OPERATION_GET_PARTIAL_OBJECT);
+    }
+
+    static boolean isWritingSupported(@Nullable int[] supportedList) {
+        return isSupported(supportedList, MtpConstants.OPERATION_SEND_OBJECT_INFO) &&
+                isSupported(supportedList, MtpConstants.OPERATION_SEND_OBJECT);
+    }
 }
diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocumentsProvider.java b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocumentsProvider.java
index 4849978..d4d4591 100644
--- a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocumentsProvider.java
+++ b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocumentsProvider.java
@@ -17,6 +17,7 @@
 package com.android.mtp;
 
 import android.content.ContentResolver;
+import android.content.UriPermission;
 import android.content.res.AssetFileDescriptor;
 import android.content.res.Resources;
 import android.database.Cursor;
@@ -25,6 +26,7 @@
 import android.media.MediaFile;
 import android.mtp.MtpConstants;
 import android.mtp.MtpObjectInfo;
+import android.net.Uri;
 import android.os.Bundle;
 import android.os.CancellationSignal;
 import android.os.ParcelFileDescriptor;
@@ -33,6 +35,8 @@
 import android.provider.DocumentsContract.Root;
 import android.provider.DocumentsContract;
 import android.provider.DocumentsProvider;
+import android.provider.Settings;
+import android.provider.Settings.SettingNotFoundException;
 import android.util.Log;
 
 import com.android.internal.annotations.GuardedBy;
@@ -42,6 +46,7 @@
 import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
 
 /**
@@ -95,6 +100,21 @@
         mRootScanner = new RootScanner(mResolver, mMtpManager, mDatabase);
         mAppFuse = new AppFuse(TAG, new AppFuseCallback());
         mIntentSender = new ServiceIntentSender(getContext());
+
+        // Check boot count and cleans database if it's first time to launch MtpDocumentsProvider
+        // after booting.
+        final int bootCount = Settings.Global.getInt(mResolver, Settings.Global.BOOT_COUNT, -1);
+        final int lastBootCount = mDatabase.getLastBootCount();
+        if (bootCount != -1 && bootCount != lastBootCount) {
+            mDatabase.setLastBootCount(bootCount);
+            final List<UriPermission> permissions = mResolver.getOutgoingPersistedUriPermissions();
+            final Uri[] uris = new Uri[permissions.size()];
+            for (int i = 0; i < permissions.size(); i++) {
+                uris[i] = permissions.get(i).getUri();
+            }
+            mDatabase.cleanDatabase(uris);
+        }
+
         // TODO: Mount AppFuse on demands.
         try {
             mAppFuse.mount(getContext().getSystemService(StorageManager.class));
@@ -122,6 +142,7 @@
         mRootScanner = new RootScanner(mResolver, mMtpManager, mDatabase);
         mAppFuse = new AppFuse(TAG, new AppFuseCallback());
         mIntentSender = intentSender;
+
         // TODO: Mount AppFuse on demands.
         try {
             mAppFuse.mount(storageManager);
@@ -201,6 +222,7 @@
         final Identifier identifier = mDatabase.createIdentifier(documentId);
         try {
             openDevice(identifier.mDeviceId);
+            final MtpDeviceRecord device = getDeviceToolkit(identifier.mDeviceId).mDeviceRecord;
             switch (mode) {
                 case "r":
                     final long fileSize = getFileSize(documentId);
@@ -208,7 +230,8 @@
                     // 4GB. Fallback to non-seekable file descriptor.
                     // TODO: Use getPartialObject64 for MTP devices that support Android vendor
                     // extension.
-                    if (fileSize <= 0xffffffffl) {
+                    if (MtpDeviceRecord.isPartialReadSupported(
+                            device.operationsSupported, fileSize)) {
                         return mAppFuse.openFile(Integer.parseInt(documentId));
                     } else {
                         return getPipeManager(identifier).readDocument(mMtpManager, identifier);
@@ -216,8 +239,13 @@
                 case "w":
                     // TODO: Clear the parent document loader task (if exists) and call notify
                     // when writing is completed.
-                    return getPipeManager(identifier).writeDocument(
-                            getContext(), mMtpManager, identifier);
+                    if (MtpDeviceRecord.isWritingSupported(device.operationsSupported)) {
+                        return getPipeManager(identifier).writeDocument(
+                                getContext(), mMtpManager, identifier, device.operationsSupported);
+                    } else {
+                        throw new UnsupportedOperationException(
+                                "The device does not support writing operation.");
+                    }
                 case "rw":
                     // TODO: Add support for "rw" mode.
                     throw new UnsupportedOperationException(
@@ -290,6 +318,10 @@
         try {
             final Identifier parentId = mDatabase.createIdentifier(parentDocumentId);
             openDevice(parentId.mDeviceId);
+            final MtpDeviceRecord record = getDeviceToolkit(parentId.mDeviceId).mDeviceRecord;
+            if (!MtpDeviceRecord.isWritingSupported(record.operationsSupported)) {
+                throw new UnsupportedOperationException();
+            }
             final ParcelFileDescriptor pipe[] = ParcelFileDescriptor.createReliablePipe();
             pipe[0].close();  // 0 bytes for a new document.
             final int formatCode = Document.MIME_TYPE_DIR.equals(mimeType) ?
@@ -305,7 +337,8 @@
             final MtpObjectInfo infoWithHandle =
                     new MtpObjectInfo.Builder(info).setObjectHandle(objectHandle).build();
             final String documentId = mDatabase.putNewDocument(
-                    parentId.mDeviceId, parentDocumentId, infoWithHandle);
+                    parentId.mDeviceId, parentDocumentId, record.operationsSupported,
+                    infoWithHandle);
             getDocumentLoader(parentId).clearTask(parentId);
             notifyChildDocumentsChange(parentDocumentId);
             return documentId;
@@ -323,9 +356,9 @@
             if (DEBUG) {
                 Log.d(TAG, "Open device " + deviceId);
             }
-            mMtpManager.openDevice(deviceId);
+            final MtpDeviceRecord device = mMtpManager.openDevice(deviceId);
             final DeviceToolkit toolkit =
-                    new DeviceToolkit(deviceId, mMtpManager, mResolver, mDatabase);
+                    new DeviceToolkit(mMtpManager, mResolver, mDatabase, device);
             mDeviceToolkits.put(deviceId, toolkit);
             mIntentSender.sendUpdateNotificationIntent();
             try {
@@ -347,20 +380,15 @@
         mIntentSender.sendUpdateNotificationIntent();
     }
 
-    int[] getOpenedDeviceIds() {
+    MtpDeviceRecord[] getOpenedDeviceRecordsCache() {
         synchronized (mDeviceListLock) {
-            return mMtpManager.getOpenedDeviceIds();
-        }
-    }
-
-    String getDeviceName(int deviceId) throws IOException {
-        synchronized (mDeviceListLock) {
-            for (final MtpDeviceRecord device : mMtpManager.getDevices()) {
-                if (device.deviceId == deviceId) {
-                    return device.name;
-                }
+            final MtpDeviceRecord[] records = new MtpDeviceRecord[mDeviceToolkits.size()];
+            int i = 0;
+            for (final DeviceToolkit toolkit : mDeviceToolkits.values()) {
+                records[i] = toolkit.mDeviceRecord;
+                i++;
             }
-            throw new IOException("Not found the device: " + Integer.toString(deviceId));
+            return records;
         }
     }
 
@@ -391,9 +419,13 @@
     public void shutdown() {
         synchronized (mDeviceListLock) {
             try {
-                for (final int id : mMtpManager.getOpenedDeviceIds()) {
+                // Copy the opened key set because it will be modified when closing devices.
+                final Integer[] keySet =
+                        mDeviceToolkits.keySet().toArray(new Integer[mDeviceToolkits.size()]);
+                for (final int id : keySet) {
                     closeDeviceInternal(id);
                 }
+                mRootScanner.pause();
             } catch (InterruptedException|IOException e) {
                 // It should fail unit tests by throwing runtime exception.
                 throw new RuntimeException(e);
@@ -429,10 +461,10 @@
         if (DEBUG) {
             Log.d(TAG, "Close device " + deviceId);
         }
-        getDeviceToolkit(deviceId).mDocumentLoader.close();
+        getDeviceToolkit(deviceId).close();
         mDeviceToolkits.remove(deviceId);
         mMtpManager.closeDevice(deviceId);
-        if (getOpenedDeviceIds().length == 0) {
+        if (mDeviceToolkits.size() == 0) {
             mRootScanner.pause();
         }
     }
@@ -485,14 +517,24 @@
         return cursor;
     }
 
-    private static class DeviceToolkit {
+    private static class DeviceToolkit implements AutoCloseable {
         public final PipeManager mPipeManager;
         public final DocumentLoader mDocumentLoader;
+        public final MtpDeviceRecord mDeviceRecord;
 
-        public DeviceToolkit(
-                int deviceId, MtpManager manager, ContentResolver resolver, MtpDatabase database) {
+        public DeviceToolkit(MtpManager manager,
+                             ContentResolver resolver,
+                             MtpDatabase database,
+                             MtpDeviceRecord record) {
             mPipeManager = new PipeManager(database);
-            mDocumentLoader = new DocumentLoader(deviceId, manager, resolver, database);
+            mDocumentLoader = new DocumentLoader(record, manager, resolver, database);
+            mDeviceRecord = record;
+        }
+
+        @Override
+        public void close() throws InterruptedException {
+            mPipeManager.close();
+            mDocumentLoader.close();
         }
     }
 
@@ -501,8 +543,13 @@
         public long readObjectBytes(
                 int inode, long offset, long size, byte[] buffer) throws IOException {
             final Identifier identifier = mDatabase.createIdentifier(Integer.toString(inode));
-            return mMtpManager.getPartialObject(
-                    identifier.mDeviceId, identifier.mObjectHandle, offset, size, buffer);
+            final MtpDeviceRecord record = getDeviceToolkit(identifier.mDeviceId).mDeviceRecord;
+            if (MtpDeviceRecord.isPartialReadSupported(record.operationsSupported, offset)) {
+                return mMtpManager.getPartialObject(
+                        identifier.mDeviceId, identifier.mObjectHandle, offset, size, buffer);
+            } else {
+                throw new UnsupportedOperationException();
+            }
         }
 
         @Override
diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocumentsService.java b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocumentsService.java
index 9c4952b..9b42b78 100644
--- a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocumentsService.java
+++ b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocumentsService.java
@@ -67,38 +67,25 @@
      */
     private boolean updateForegroundState() {
         final MtpDocumentsProvider provider = MtpDocumentsProvider.getInstance();
-        final int[] deviceIds = provider.getOpenedDeviceIds();
         int notificationId = 0;
         Notification notification = null;
         // TODO: Hide notification if the device has already been removed.
-        for (final int deviceId : deviceIds) {
-            try {
-                final String title = getResources().getString(
-                        R.string.accessing_notification_title,
-                        provider.getDeviceName(deviceIds[0]));
-                final String description = getResources().getString(
-                        R.string.accessing_notification_description);
-                notificationId = deviceId;
-                notification = new Notification.Builder(this)
-                        .setLocalOnly(true)
-                        .setContentTitle(title)
-                        .setContentText(description)
-                        .setSmallIcon(com.android.internal.R.drawable.stat_sys_data_usb)
-                        .setCategory(Notification.CATEGORY_SYSTEM)
-                        .setPriority(Notification.PRIORITY_LOW)
-                        .build();
-                mNotificationManager.notify(deviceId, notification);
-            } catch (IOException exp) {
-                logErrorMessage(exp);
-                // If we failed to obtain device name, it looks the device is unusable.
-                // Because this is the last device we opened, we should hide the notification
-                // for the case.
-                try {
-                    provider.closeDevice(deviceIds[0]);
-                } catch (IOException | InterruptedException closeError) {
-                    logErrorMessage(closeError);
-                }
-            }
+        for (final MtpDeviceRecord record : provider.getOpenedDeviceRecordsCache()) {
+            final String title = getResources().getString(
+                    R.string.accessing_notification_title,
+                    record.name);
+            final String description = getResources().getString(
+                    R.string.accessing_notification_description);
+            notificationId = record.deviceId;
+            notification = new Notification.Builder(this)
+                    .setLocalOnly(true)
+                    .setContentTitle(title)
+                    .setContentText(description)
+                    .setSmallIcon(com.android.internal.R.drawable.stat_sys_data_usb)
+                    .setCategory(Notification.CATEGORY_SYSTEM)
+                    .setPriority(Notification.PRIORITY_LOW)
+                    .build();
+            mNotificationManager.notify(record.deviceId, notification);
         }
 
         if (notification != null) {
diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpManager.java b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpManager.java
index 37dc761..0202343 100644
--- a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpManager.java
+++ b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpManager.java
@@ -65,16 +65,14 @@
      */
     private static final int PROTOCOL_MTP = 0;
 
-
     private final UsbManager mManager;
-    // TODO: Save and restore the set of opened device.
     private final SparseArray<MtpDevice> mDevices = new SparseArray<>();
 
     MtpManager(Context context) {
         mManager = (UsbManager) context.getSystemService(Context.USB_SERVICE);
     }
 
-    synchronized void openDevice(int deviceId) throws IOException {
+    synchronized MtpDeviceRecord openDevice(int deviceId) throws IOException {
         UsbDevice rawDevice = null;
         for (final UsbDevice candidate : mManager.getDeviceList().values()) {
             if (candidate.getDeviceId() == deviceId) {
@@ -113,6 +111,8 @@
         }
 
         mDevices.put(deviceId, device);
+
+        return createDeviceRecord(rawDevice);
     }
 
     synchronized void closeDevice(int deviceId) throws IOException {
@@ -126,45 +126,11 @@
             if (!isMtpDevice(device)) {
                 continue;
             }
-            final MtpDevice mtpDevice = mDevices.get(device.getDeviceId());
-            final boolean opened = mtpDevice != null;
-            final String name = device.getProductName();
-            MtpRoot[] roots;
-            int[] operationsSupported = null;
-            int[] eventsSupported = null;
-            if (opened) {
-                try {
-                    roots = getRoots(device.getDeviceId());
-                } catch (IOException exp) {
-                    Log.e(MtpDocumentsProvider.TAG, "Failed to open device", exp);
-                    // If we failed to fetch roots for the device, we still returns device model
-                    // with an empty set of roots so that the device is shown DocumentsUI as long as
-                    // the device is physically connected.
-                    roots = new MtpRoot[0];
-                }
-                final MtpDeviceInfo info = mtpDevice.getDeviceInfo();
-                if (info != null) {
-                    operationsSupported = mtpDevice.getDeviceInfo().getOperationsSupported();
-                    eventsSupported = mtpDevice.getDeviceInfo().getEventsSupported();
-                }
-            } else {
-                roots = new MtpRoot[0];
-            }
-            devices.add(new MtpDeviceRecord(
-                    device.getDeviceId(), name, device.getSerialNumber(), opened, roots,
-                    operationsSupported, eventsSupported));
+            devices.add(createDeviceRecord(device));
         }
         return devices.toArray(new MtpDeviceRecord[devices.size()]);
     }
 
-    synchronized int[] getOpenedDeviceIds() {
-        final int[] result = new int[mDevices.size()];
-        for (int i = 0; i < result.length; i++) {
-            result[i] = mDevices.keyAt(i);
-        }
-        return result;
-    }
-
     MtpObjectInfo getObjectInfo(int deviceId, int objectHandle)
             throws IOException {
         final MtpDevice device = getDevice(deviceId);
@@ -177,7 +143,12 @@
             throws IOException {
         final MtpDevice device = getDevice(deviceId);
         synchronized (device) {
-            return device.getObjectHandles(storageId, 0 /* all format */, parentObjectHandle);
+            final int[] handles =
+                    device.getObjectHandles(storageId, 0 /* all format */, parentObjectHandle);
+            if (handles == null) {
+                throw new IOException("Failed to fetch object handles.");
+            }
+            return handles;
         }
     }
 
@@ -189,7 +160,6 @@
         }
     }
 
-    @VisibleForTesting
     long getPartialObject(int deviceId, int objectHandle, long offset, long size, byte[] buffer)
             throws IOException {
         final MtpDevice device = getDevice(deviceId);
@@ -281,6 +251,36 @@
         }
     }
 
+    private MtpDeviceRecord createDeviceRecord(UsbDevice device) {
+        final MtpDevice mtpDevice = mDevices.get(device.getDeviceId());
+        final boolean opened = mtpDevice != null;
+        final String name = device.getProductName();
+        MtpRoot[] roots;
+        int[] operationsSupported = null;
+        int[] eventsSupported = null;
+        if (opened) {
+            try {
+                roots = getRoots(device.getDeviceId());
+            } catch (IOException exp) {
+                Log.e(MtpDocumentsProvider.TAG, "Failed to open device", exp);
+                // If we failed to fetch roots for the device, we still returns device model
+                // with an empty set of roots so that the device is shown DocumentsUI as long as
+                // the device is physically connected.
+                roots = new MtpRoot[0];
+            }
+            final MtpDeviceInfo info = mtpDevice.getDeviceInfo();
+            if (info != null) {
+                operationsSupported = mtpDevice.getDeviceInfo().getOperationsSupported();
+                eventsSupported = mtpDevice.getDeviceInfo().getEventsSupported();
+            }
+        } else {
+            roots = new MtpRoot[0];
+        }
+        return new MtpDeviceRecord(
+                device.getDeviceId(), name, device.getSerialNumber(), opened, roots,
+                operationsSupported, eventsSupported);
+    }
+
     static boolean isMtpDevice(UsbDevice device) {
         for (int i = 0; i < device.getInterfaceCount(); i++) {
             final UsbInterface usbInterface = device.getInterface(i);
diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/PipeManager.java b/packages/MtpDocumentsProvider/src/com/android/mtp/PipeManager.java
index 645bfcd..c10a65e 100644
--- a/packages/MtpDocumentsProvider/src/com/android/mtp/PipeManager.java
+++ b/packages/MtpDocumentsProvider/src/com/android/mtp/PipeManager.java
@@ -26,8 +26,14 @@
 import java.io.IOException;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
+import java.util.concurrent.TimeUnit;
 
 class PipeManager {
+    /**
+     * Milliseconds we wait for background thread when pausing.
+     */
+    private final static long AWAIT_TERMINATION_TIMEOUT = 2000;
+
     final ExecutorService mExecutor;
     final MtpDatabase mDatabase;
 
@@ -46,9 +52,11 @@
         return task.getReadingFileDescriptor();
     }
 
-    ParcelFileDescriptor writeDocument(Context context, MtpManager model, Identifier identifier)
+    ParcelFileDescriptor writeDocument(Context context, MtpManager model, Identifier identifier,
+                                       int[] operationsSupported)
             throws IOException {
-        final Task task = new WriteDocumentTask(context, model, identifier, mDatabase);
+        final Task task = new WriteDocumentTask(
+                context, model, identifier, operationsSupported, mDatabase);
         mExecutor.execute(task);
         return task.getWritingFileDescriptor();
     }
@@ -103,13 +111,18 @@
     private static class WriteDocumentTask extends Task {
         private final Context mContext;
         private final MtpDatabase mDatabase;
+        private final int[] mOperationsSupported;
 
-        WriteDocumentTask(
-                Context context, MtpManager model, Identifier identifier, MtpDatabase database)
+        WriteDocumentTask(Context context,
+                          MtpManager model,
+                          Identifier identifier,
+                          int[] supportedOperations,
+                          MtpDatabase database)
                 throws IOException {
             super(model, identifier);
             mContext = context;
             mDatabase = database;
+            mOperationsSupported = supportedOperations;
         }
 
         @Override
@@ -160,6 +173,7 @@
                         mIdentifier.mDocumentId,
                         mIdentifier.mDeviceId,
                         parentIdentifier.mDocumentId,
+                        mOperationsSupported,
                         newObjectInfo);
             } catch (IOException error) {
                 Log.w(MtpDocumentsProvider.TAG,
@@ -195,7 +209,8 @@
         }
     }
 
-    void close() {
-        mExecutor.shutdown();
+    boolean close() throws InterruptedException {
+        mExecutor.shutdownNow();
+        return mExecutor.awaitTermination(AWAIT_TERMINATION_TIMEOUT, TimeUnit.MILLISECONDS);
     }
 }
diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/RootScanner.java b/packages/MtpDocumentsProvider/src/com/android/mtp/RootScanner.java
index a48bf12..2f66c5c 100644
--- a/packages/MtpDocumentsProvider/src/com/android/mtp/RootScanner.java
+++ b/packages/MtpDocumentsProvider/src/com/android/mtp/RootScanner.java
@@ -26,7 +26,6 @@
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
-import java.util.concurrent.FutureTask;
 import java.util.concurrent.TimeUnit;
 
 final class RootScanner {
@@ -56,7 +55,7 @@
     final MtpDatabase mDatabase;
 
     ExecutorService mExecutor;
-    FutureTask<Void> mCurrentTask;
+    private UpdateRootsRunnable mCurrentTask;
 
     RootScanner(
             ContentResolver resolver,
@@ -84,13 +83,12 @@
             mExecutor = Executors.newSingleThreadExecutor();
         }
         if (mCurrentTask != null) {
-            // Cancel previous task.
-            mCurrentTask.cancel(true);
+            // Stop previous task.
+            mCurrentTask.stop();
         }
-        final UpdateRootsRunnable runnable = new UpdateRootsRunnable();
-        mCurrentTask = new FutureTask<Void>(runnable, null);
-        mExecutor.submit(mCurrentTask);
-        return runnable.mFirstScanCompleted;
+        mCurrentTask = new UpdateRootsRunnable();
+        mExecutor.execute(mCurrentTask);
+        return mCurrentTask.mFirstScanCompleted;
     }
 
     /**
@@ -112,13 +110,21 @@
      * Runnable to scan roots and update the database information.
      */
     private final class UpdateRootsRunnable implements Runnable {
+        /**
+         * Count down latch that specifies the runnable is stopped.
+         */
+        final CountDownLatch mStopped = new CountDownLatch(1);
+
+        /**
+         * Count down latch that specifies the first scan is completed.
+         */
         final CountDownLatch mFirstScanCompleted = new CountDownLatch(1);
 
         @Override
         public void run() {
             Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
             int pollingCount = 0;
-            while (true) {
+            while (mStopped.getCount() > 0) {
                 boolean changed = false;
 
                 // Update devices.
@@ -149,7 +155,8 @@
                     }
                     try {
                         mDatabase.getMapper().startAddingDocuments(documentId);
-                        if (mDatabase.getMapper().putStorageDocuments(documentId, device.roots)) {
+                        if (mDatabase.getMapper().putStorageDocuments(
+                                documentId, device.eventsSupported, device.roots)) {
                             changed = true;
                         }
                         if (mDatabase.getMapper().stopAddingDocuments(documentId)) {
@@ -170,12 +177,16 @@
                     // Use SHORT_POLLING_PERIOD for the first SHORT_POLLING_TIMES because it is
                     // more likely to add new root just after the device is added.
                     // TODO: Use short interval only for a device that is just added.
-                    Thread.sleep(pollingCount > SHORT_POLLING_TIMES ?
-                        LONG_POLLING_INTERVAL : SHORT_POLLING_INTERVAL);
+                    mStopped.await(pollingCount > SHORT_POLLING_TIMES ?
+                            LONG_POLLING_INTERVAL : SHORT_POLLING_INTERVAL, TimeUnit.MILLISECONDS);
                 } catch (InterruptedException exp) {
                     break;
                 }
             }
         }
+
+        void stop() {
+            mStopped.countDown();
+        }
     }
 }
diff --git a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/DocumentLoaderTest.java b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/DocumentLoaderTest.java
index b75a9e6..db25421 100644
--- a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/DocumentLoaderTest.java
+++ b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/DocumentLoaderTest.java
@@ -48,14 +48,20 @@
         mDatabase.getMapper().stopAddingDocuments(null);
 
         mDatabase.getMapper().startAddingDocuments("1");
-        mDatabase.getMapper().putStorageDocuments("1", new MtpRoot[] {
+        mDatabase.getMapper().putStorageDocuments("1", new int[0], new MtpRoot[] {
                 new MtpRoot(0, 0, "Storage", 1000, 1000, "")
         });
         mDatabase.getMapper().stopAddingDocuments("1");
 
         mManager = new BlockableTestMtpManager(getContext());
         mResolver = new TestContentResolver();
-        mLoader = new DocumentLoader(0, mManager, mResolver, mDatabase);
+        mLoader = new DocumentLoader(
+                new MtpDeviceRecord(
+                        0, "Device", "Key", true, new MtpRoot[0],
+                        TestUtil.OPERATIONS_SUPPORTED, new int[0]),
+                mManager,
+                mResolver,
+                mDatabase);
     }
 
     @Override
diff --git a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDatabaseTest.java b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDatabaseTest.java
index 05c9c57..e49a935 100644
--- a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDatabaseTest.java
+++ b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDatabaseTest.java
@@ -19,6 +19,7 @@
 import android.database.Cursor;
 import android.mtp.MtpConstants;
 import android.mtp.MtpObjectInfo;
+import android.net.Uri;
 import android.provider.DocumentsContract;
 import android.provider.DocumentsContract.Document;
 import android.provider.DocumentsContract.Root;
@@ -26,14 +27,16 @@
 import android.test.suitebuilder.annotation.SmallTest;
 
 import java.io.FileNotFoundException;
+import java.util.Arrays;
 
 import static android.provider.DocumentsContract.Document.*;
 import static com.android.mtp.MtpDatabase.strings;
 import static com.android.mtp.MtpDatabaseConstants.*;
+import static com.android.mtp.TestUtil.OPERATIONS_SUPPORTED;
 
 @SmallTest
 public class MtpDatabaseTest extends AndroidTestCase {
-    private final String[] COLUMN_NAMES = new String[] {
+    private static final String[] COLUMN_NAMES = new String[] {
         DocumentsContract.Document.COLUMN_DOCUMENT_ID,
         MtpDatabaseConstants.COLUMN_DEVICE_ID,
         MtpDatabaseConstants.COLUMN_STORAGE_ID,
@@ -75,13 +78,10 @@
     }
 
     public void testPutSingleStorageDocuments() throws Exception {
-        mDatabase.getMapper().startAddingDocuments(null);
-        mDatabase.getMapper().putDeviceDocument(new MtpDeviceRecord(
-                0, "Device", null /* deviceKey */, true, new MtpRoot[0], null, null));
-        mDatabase.getMapper().stopAddingDocuments(null);
+        addTestDevice();
 
         mDatabase.getMapper().startAddingDocuments("1");
-        mDatabase.getMapper().putStorageDocuments("1", new MtpRoot[] {
+        mDatabase.getMapper().putStorageDocuments("1", OPERATIONS_SUPPORTED, new MtpRoot[] {
                 new MtpRoot(0, 1, "Storage", 1000, 2000, "")
         });
         mDatabase.getMapper().stopAddingDocuments("1");
@@ -143,7 +143,7 @@
         addTestDevice();
 
         mDatabase.getMapper().startAddingDocuments("1");
-        mDatabase.getMapper().putStorageDocuments("1", new MtpRoot[] {
+        mDatabase.getMapper().putStorageDocuments("1", OPERATIONS_SUPPORTED, new MtpRoot[] {
                 new MtpRoot(0, 1, "Storage", 1000, 2000, ""),
                 new MtpRoot(0, 2, "Storage", 2000, 4000, ""),
                 new MtpRoot(0, 3, "/@#%&<>Storage", 3000, 6000,"")
@@ -194,7 +194,7 @@
         addTestStorage("1");
 
         mDatabase.getMapper().startAddingDocuments("2");
-        mDatabase.getMapper().putChildDocuments(0, "2", new MtpObjectInfo[] {
+        mDatabase.getMapper().putChildDocuments(0, "2", OPERATIONS_SUPPORTED, new MtpObjectInfo[] {
                 createDocument(100, "note.txt", MtpConstants.FORMAT_TEXT, 1024),
                 createDocument(101, "image.jpg", MtpConstants.FORMAT_EXIF_JPEG, 2 * 1024 * 1024),
                 createDocument(102, "music.mp3", MtpConstants.FORMAT_MP3, 3 * 1024 * 1024)
@@ -263,6 +263,58 @@
         cursor.close();
     }
 
+    public void testPutChildDocuments_operationsSupported() throws Exception {
+        addTestDevice();
+        addTestStorage("1");
+
+        // Put a document with empty supported operations.
+        mDatabase.getMapper().startAddingDocuments("2");
+        mDatabase.getMapper().putChildDocuments(0, "2", new int[0], new MtpObjectInfo[] {
+                createDocument(100, "note.txt", MtpConstants.FORMAT_TEXT, 1024)
+        });
+        mDatabase.getMapper().stopAddingDocuments("2");
+
+        try (final Cursor cursor =
+                mDatabase.queryChildDocuments(strings(Document.COLUMN_FLAGS), "2")) {
+            assertEquals(1, cursor.getCount());
+            cursor.moveToNext();
+            assertEquals(0, cursor.getInt(0));
+        }
+
+        // Put a document with writable operations.
+        mDatabase.getMapper().startAddingDocuments("2");
+        mDatabase.getMapper().putChildDocuments(0, "2", new int[] {
+                MtpConstants.OPERATION_SEND_OBJECT,
+                MtpConstants.OPERATION_SEND_OBJECT_INFO,
+        }, new MtpObjectInfo[] {
+                createDocument(100, "note.txt", MtpConstants.FORMAT_TEXT, 1024)
+        });
+        mDatabase.getMapper().stopAddingDocuments("2");
+
+        try (final Cursor cursor =
+                mDatabase.queryChildDocuments(strings(Document.COLUMN_FLAGS), "2")) {
+            assertEquals(1, cursor.getCount());
+            cursor.moveToNext();
+            assertEquals(Document.FLAG_SUPPORTS_WRITE, cursor.getInt(0));
+        }
+
+        // Put a document with deletable operations.
+        mDatabase.getMapper().startAddingDocuments("2");
+        mDatabase.getMapper().putChildDocuments(0, "2", new int[] {
+                MtpConstants.OPERATION_DELETE_OBJECT
+        }, new MtpObjectInfo[] {
+                createDocument(100, "note.txt", MtpConstants.FORMAT_TEXT, 1024)
+        });
+        mDatabase.getMapper().stopAddingDocuments("2");
+
+        try (final Cursor cursor =
+                mDatabase.queryChildDocuments(strings(Document.COLUMN_FLAGS), "2")) {
+            assertEquals(1, cursor.getCount());
+            cursor.moveToNext();
+            assertEquals(Document.FLAG_SUPPORTS_DELETE, cursor.getInt(0));
+        }
+    }
+
     public void testRestoreIdForRootDocuments() throws Exception {
         final String[] columns = new String[] {
                 DocumentsContract.Document.COLUMN_DOCUMENT_ID,
@@ -273,7 +325,7 @@
         // Add device and two storages.
         addTestDevice();
         mDatabase.getMapper().startAddingDocuments("1");
-        mDatabase.getMapper().putStorageDocuments("1", new MtpRoot[] {
+        mDatabase.getMapper().putStorageDocuments("1", OPERATIONS_SUPPORTED, new MtpRoot[] {
                 new MtpRoot(0, 100, "Storage A", 1000, 0, ""),
                 new MtpRoot(0, 101, "Storage B", 1001, 0, "")
         });
@@ -304,7 +356,7 @@
 
         // Add two storages, but one's name is different from previous one.
         mDatabase.getMapper().startAddingDocuments("1");
-        mDatabase.getMapper().putStorageDocuments("1", new MtpRoot[] {
+        mDatabase.getMapper().putStorageDocuments("1", OPERATIONS_SUPPORTED, new MtpRoot[] {
                 new MtpRoot(0, 200, "Storage A", 2000, 0, ""),
                 new MtpRoot(0, 202, "Storage C", 2002, 0, "")
         });
@@ -337,7 +389,7 @@
         addTestStorage("1");
 
         mDatabase.getMapper().startAddingDocuments("2");
-        mDatabase.getMapper().putChildDocuments(0, "2", new MtpObjectInfo[] {
+        mDatabase.getMapper().putChildDocuments(0, "2", OPERATIONS_SUPPORTED, new MtpObjectInfo[] {
                 createDocument(100, "note.txt", MtpConstants.FORMAT_TEXT, 1024),
                 createDocument(101, "image.jpg", MtpConstants.FORMAT_EXIF_JPEG, 2 * 1024 * 1024),
                 createDocument(102, "music.mp3", MtpConstants.FORMAT_MP3, 3 * 1024 * 1024)
@@ -355,7 +407,7 @@
         }
 
         mDatabase.getMapper().startAddingDocuments("2");
-        mDatabase.getMapper().putChildDocuments(0, "2", new MtpObjectInfo[] {
+        mDatabase.getMapper().putChildDocuments(0, "2", OPERATIONS_SUPPORTED, new MtpObjectInfo[] {
                 createDocument(200, "note.txt", MtpConstants.FORMAT_TEXT, 1024),
                 createDocument(203, "video.mp4", MtpConstants.FORMAT_MP4_CONTAINER, 1024),
         });
@@ -398,10 +450,10 @@
 
         mDatabase.getMapper().startAddingDocuments("1");
         mDatabase.getMapper().startAddingDocuments("2");
-        mDatabase.getMapper().putStorageDocuments("1", new MtpRoot[] {
+        mDatabase.getMapper().putStorageDocuments("1", OPERATIONS_SUPPORTED, new MtpRoot[] {
                 new MtpRoot(0, 100, "Storage", 0, 0, "")
         });
-        mDatabase.getMapper().putStorageDocuments("2", new MtpRoot[] {
+        mDatabase.getMapper().putStorageDocuments("2", OPERATIONS_SUPPORTED, new MtpRoot[] {
                 new MtpRoot(1, 100, "Storage", 0, 0, "")
         });
 
@@ -442,10 +494,10 @@
 
         mDatabase.getMapper().startAddingDocuments("1");
         mDatabase.getMapper().startAddingDocuments("2");
-        mDatabase.getMapper().putStorageDocuments("1", new MtpRoot[] {
+        mDatabase.getMapper().putStorageDocuments("1", OPERATIONS_SUPPORTED, new MtpRoot[] {
                 new MtpRoot(0, 200, "Storage", 2000, 0, "")
         });
-        mDatabase.getMapper().putStorageDocuments("2", new MtpRoot[] {
+        mDatabase.getMapper().putStorageDocuments("2", OPERATIONS_SUPPORTED, new MtpRoot[] {
                 new MtpRoot(1, 300, "Storage", 3000, 0, "")
         });
         mDatabase.getMapper().stopAddingDocuments("1");
@@ -488,7 +540,7 @@
         addTestDevice();
         addTestStorage("1");
         mDatabase.getMapper().startAddingDocuments("2");
-        mDatabase.getMapper().putChildDocuments(0, "2", new MtpObjectInfo[] {
+        mDatabase.getMapper().putChildDocuments(0, "2", OPERATIONS_SUPPORTED, new MtpObjectInfo[] {
                 createDocument(50, "A", MtpConstants.FORMAT_ASSOCIATION, 0),
                 createDocument(51, "B", MtpConstants.FORMAT_ASSOCIATION, 0),
         });
@@ -497,10 +549,10 @@
         // Put note.txt in each directory.
         mDatabase.getMapper().startAddingDocuments("3");
         mDatabase.getMapper().startAddingDocuments("4");
-        mDatabase.getMapper().putChildDocuments(0, "3", new MtpObjectInfo[] {
+        mDatabase.getMapper().putChildDocuments(0, "3", OPERATIONS_SUPPORTED, new MtpObjectInfo[] {
                 createDocument(100, "note.txt", MtpConstants.FORMAT_TEXT, 1024),
         });
-        mDatabase.getMapper().putChildDocuments(0, "4", new MtpObjectInfo[] {
+        mDatabase.getMapper().putChildDocuments(0, "4", OPERATIONS_SUPPORTED, new MtpObjectInfo[] {
                 createDocument(101, "note.txt", MtpConstants.FORMAT_TEXT, 1024),
         });
 
@@ -511,7 +563,7 @@
         addTestDevice();
         addTestStorage("1");
         mDatabase.getMapper().startAddingDocuments("2");
-        mDatabase.getMapper().putChildDocuments(0, "2", new MtpObjectInfo[] {
+        mDatabase.getMapper().putChildDocuments(0, "2", OPERATIONS_SUPPORTED, new MtpObjectInfo[] {
                 createDocument(50, "A", MtpConstants.FORMAT_ASSOCIATION, 0),
                 createDocument(51, "B", MtpConstants.FORMAT_ASSOCIATION, 0),
         });
@@ -520,10 +572,10 @@
         // Add note.txt in each directory again.
         mDatabase.getMapper().startAddingDocuments("3");
         mDatabase.getMapper().startAddingDocuments("4");
-        mDatabase.getMapper().putChildDocuments(0, "3", new MtpObjectInfo[] {
+        mDatabase.getMapper().putChildDocuments(0, "3", OPERATIONS_SUPPORTED, new MtpObjectInfo[] {
                 createDocument(200, "note.txt", MtpConstants.FORMAT_TEXT, 1024),
         });
-        mDatabase.getMapper().putChildDocuments(0, "4", new MtpObjectInfo[] {
+        mDatabase.getMapper().putChildDocuments(0, "4", OPERATIONS_SUPPORTED, new MtpObjectInfo[] {
                 createDocument(201, "note.txt", MtpConstants.FORMAT_TEXT, 1024),
         });
         mDatabase.getMapper().stopAddingDocuments("3");
@@ -562,7 +614,7 @@
         addTestDevice();
 
         mDatabase.getMapper().startAddingDocuments("1");
-        mDatabase.getMapper().putStorageDocuments("1", new MtpRoot[] {
+        mDatabase.getMapper().putStorageDocuments("1", OPERATIONS_SUPPORTED, new MtpRoot[] {
                 new MtpRoot(0, 100, "Storage", 0, 0, ""),
         });
         mDatabase.getMapper().clearMapping();
@@ -576,7 +628,7 @@
         }
 
         mDatabase.getMapper().startAddingDocuments("1");
-        mDatabase.getMapper().putStorageDocuments("1", new MtpRoot[] {
+        mDatabase.getMapper().putStorageDocuments("1", OPERATIONS_SUPPORTED, new MtpRoot[] {
                 new MtpRoot(0, 200, "Storage", 2000, 0, ""),
         });
         mDatabase.getMapper().clearMapping();
@@ -584,7 +636,7 @@
         addTestDevice();
 
         mDatabase.getMapper().startAddingDocuments("1");
-        mDatabase.getMapper().putStorageDocuments("1", new MtpRoot[] {
+        mDatabase.getMapper().putStorageDocuments("1", OPERATIONS_SUPPORTED, new MtpRoot[] {
                 new MtpRoot(0, 300, "Storage", 3000, 0, ""),
         });
         mDatabase.getMapper().stopAddingDocuments("1");
@@ -625,7 +677,7 @@
         // Add a device and two storages that has same name.
         addTestDevice();
         mDatabase.getMapper().startAddingDocuments("1");
-        mDatabase.getMapper().putStorageDocuments("1", new MtpRoot[] {
+        mDatabase.getMapper().putStorageDocuments("1", OPERATIONS_SUPPORTED, new MtpRoot[] {
                 new MtpRoot(0, 200, "Storage", 2000, 0, ""),
                 new MtpRoot(0, 201, "Storage", 2001, 0, ""),
         });
@@ -658,13 +710,13 @@
         // The client code should be able to replace existing rows with new information.
         // Add one.
         mDatabase.getMapper().startAddingDocuments("1");
-        mDatabase.getMapper().putStorageDocuments("1", new MtpRoot[] {
+        mDatabase.getMapper().putStorageDocuments("1", OPERATIONS_SUPPORTED, new MtpRoot[] {
                 new MtpRoot(0, 100, "Storage A", 0, 0, ""),
         });
         mDatabase.getMapper().stopAddingDocuments("1");
         // Replace it.
         mDatabase.getMapper().startAddingDocuments("1");
-        mDatabase.getMapper().putStorageDocuments("1", new MtpRoot[] {
+        mDatabase.getMapper().putStorageDocuments("1", OPERATIONS_SUPPORTED, new MtpRoot[] {
                 new MtpRoot(0, 100, "Storage B", 1000, 1000, ""),
         });
         mDatabase.getMapper().stopAddingDocuments("1");
@@ -703,7 +755,7 @@
         // Add one.
         addTestDevice();
         mDatabase.getMapper().startAddingDocuments("1");
-        mDatabase.getMapper().putStorageDocuments("1", new MtpRoot[] {
+        mDatabase.getMapper().putStorageDocuments("1", OPERATIONS_SUPPORTED, new MtpRoot[] {
                 new MtpRoot(0, 100, "Storage A", 0, 0, ""),
         });
         mDatabase.getMapper().clearMapping();
@@ -717,11 +769,11 @@
 
             // Add one.
             mDatabase.getMapper().startAddingDocuments("1");
-            mDatabase.getMapper().putStorageDocuments("1", new MtpRoot[] {
+            mDatabase.getMapper().putStorageDocuments("1", OPERATIONS_SUPPORTED, new MtpRoot[] {
                     new MtpRoot(0, 101, "Storage B", 1000, 1000, ""),
             });
             // Add one more before resolving unmapped documents.
-            mDatabase.getMapper().putStorageDocuments("1", new MtpRoot[] {
+            mDatabase.getMapper().putStorageDocuments("1", OPERATIONS_SUPPORTED, new MtpRoot[] {
                     new MtpRoot(0, 102, "Storage B", 1000, 1000, ""),
             });
             mDatabase.getMapper().stopAddingDocuments("1");
@@ -763,7 +815,7 @@
         }
 
         mDatabase.getMapper().startAddingDocuments("1");
-        mDatabase.getMapper().putStorageDocuments("1", new MtpRoot[] {
+        mDatabase.getMapper().putStorageDocuments("1", OPERATIONS_SUPPORTED, new MtpRoot[] {
                 new MtpRoot(0, 100, "Storage A", 0, 0, "")
         });
         mDatabase.getMapper().stopAddingDocuments("1");
@@ -778,7 +830,7 @@
         }
 
         mDatabase.getMapper().startAddingDocuments("1");
-        mDatabase.getMapper().putStorageDocuments("1", new MtpRoot[] {
+        mDatabase.getMapper().putStorageDocuments("1", OPERATIONS_SUPPORTED, new MtpRoot[] {
                 new MtpRoot(0, 100, "Storage A", 0, 0, ""),
                 new MtpRoot(0, 101, "Storage B", 0, 0, "")
         });
@@ -798,18 +850,15 @@
         addTestDevice();
 
         mDatabase.getMapper().startAddingDocuments("1");
-        mDatabase.getMapper().putStorageDocuments("1", new MtpRoot[] {
+        mDatabase.getMapper().putStorageDocuments("1", OPERATIONS_SUPPORTED, new MtpRoot[] {
                 new MtpRoot(0, 100, "Storage A", 0, 0, ""),
         });
         mDatabase.getMapper().stopAddingDocuments("1");
 
         mDatabase.getMapper().startAddingDocuments("2");
-        mDatabase.getMapper().putChildDocuments(
-                0,
-                "2",
-                new MtpObjectInfo[] {
-                        createDocument(200, "note.txt", MtpConstants.FORMAT_TEXT, 1024),
-                });
+        mDatabase.getMapper().putChildDocuments(0, "2", OPERATIONS_SUPPORTED, new MtpObjectInfo[] {
+                createDocument(200, "note.txt", MtpConstants.FORMAT_TEXT, 1024),
+        });
         mDatabase.getMapper().stopAddingDocuments("2");
 
         assertEquals("2", mDatabase.getParentIdentifier("3").mDocumentId);
@@ -820,21 +869,15 @@
         addTestStorage("1");
 
         mDatabase.getMapper().startAddingDocuments("2");
-        mDatabase.getMapper().putChildDocuments(
-                0,
-                "2",
-                new MtpObjectInfo[] {
-                        createDocument(200, "dir", MtpConstants.FORMAT_ASSOCIATION, 1024),
-                });
+        mDatabase.getMapper().putChildDocuments(0, "2", OPERATIONS_SUPPORTED, new MtpObjectInfo[] {
+                createDocument(200, "dir", MtpConstants.FORMAT_ASSOCIATION, 1024),
+        });
         mDatabase.getMapper().stopAddingDocuments("2");
 
         mDatabase.getMapper().startAddingDocuments("3");
-        mDatabase.getMapper().putChildDocuments(
-                0,
-                "3",
-                new MtpObjectInfo[] {
-                        createDocument(200, "note.txt", MtpConstants.FORMAT_TEXT, 1024),
-                });
+        mDatabase.getMapper().putChildDocuments(0, "3", OPERATIONS_SUPPORTED, new MtpObjectInfo[] {
+                createDocument(200, "note.txt", MtpConstants.FORMAT_TEXT, 1024),
+        });
         mDatabase.getMapper().stopAddingDocuments("3");
 
         mDatabase.deleteDocument("3");
@@ -863,7 +906,8 @@
         assertEquals(
                 "3",
                 mDatabase.putNewDocument(
-                        0, "2", createDocument(200, "note.txt", MtpConstants.FORMAT_TEXT, 1024)));
+                        0, "2", OPERATIONS_SUPPORTED,
+                        createDocument(200, "note.txt", MtpConstants.FORMAT_TEXT, 1024)));
 
         {
             final Cursor cursor =
@@ -881,8 +925,7 @@
 
         mDatabase.getMapper().startAddingDocuments("2");
         mDatabase.putNewDocument(
-                0,
-                "2",
+                0, "2", OPERATIONS_SUPPORTED,
                 createDocument(201, "note.txt", MtpConstants.FORMAT_TEXT, 1024));
         mDatabase.getMapper().stopAddingDocuments("2");
 
@@ -982,6 +1025,62 @@
         assertFalse(mDatabase.getMapper().stopAddingDocuments(null));
     }
 
+    public void testSetBootCount() {
+        assertEquals(0, mDatabase.getLastBootCount());
+        mDatabase.setLastBootCount(10);
+        assertEquals(10, mDatabase.getLastBootCount());
+        try {
+            mDatabase.setLastBootCount(-1);
+            fail();
+        } catch (IllegalArgumentException e) {}
+    }
+
+    public void testCleanDatabase() throws FileNotFoundException {
+        // Add tree.
+        addTestDevice();
+        addTestStorage("1");
+        mDatabase.getMapper().startAddingDocuments("2");
+        mDatabase.getMapper().putChildDocuments(0, "2", OPERATIONS_SUPPORTED, new MtpObjectInfo[] {
+                createDocument(100, "apple.txt", MtpConstants.FORMAT_TEXT, 1024),
+                createDocument(101, "orange.txt", MtpConstants.FORMAT_TEXT, 1024),
+        });
+        mDatabase.getMapper().stopAddingDocuments("2");
+
+        // Disconnect the device.
+        mDatabase.getMapper().startAddingDocuments(null);
+        mDatabase.getMapper().stopAddingDocuments(null);
+
+        // Clean database.
+        mDatabase.cleanDatabase(new Uri[] {
+                DocumentsContract.buildDocumentUri(MtpDocumentsProvider.AUTHORITY, "3")
+        });
+
+        // Add tree again.
+        addTestDevice();
+        addTestStorage("1");
+        mDatabase.getMapper().startAddingDocuments("2");
+        mDatabase.getMapper().putChildDocuments(0, "2", OPERATIONS_SUPPORTED, new MtpObjectInfo[] {
+                createDocument(100, "apple.txt", MtpConstants.FORMAT_TEXT, 1024),
+                createDocument(101, "orange.txt", MtpConstants.FORMAT_TEXT, 1024),
+        });
+        mDatabase.getMapper().stopAddingDocuments("2");
+
+        try (final Cursor cursor = mDatabase.queryChildDocuments(
+                strings(COLUMN_DOCUMENT_ID, Document.COLUMN_DISPLAY_NAME), "2")) {
+            assertEquals(2, cursor.getCount());
+
+            // Persistent uri uses the same ID.
+            cursor.moveToNext();
+            assertEquals("3", cursor.getString(0));
+            assertEquals("apple.txt", cursor.getString(1));
+
+            // Others does not.
+            cursor.moveToNext();
+            assertEquals("5", cursor.getString(0));
+            assertEquals("orange.txt", cursor.getString(1));
+        }
+    }
+
     private void addTestDevice() throws FileNotFoundException {
         TestUtil.addTestDevice(mDatabase);
     }
diff --git a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDocumentsProviderTest.java b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDocumentsProviderTest.java
index 884d132..d6ad0f3 100644
--- a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDocumentsProviderTest.java
+++ b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDocumentsProviderTest.java
@@ -38,6 +38,7 @@
 import java.util.concurrent.TimeoutException;
 
 import static com.android.mtp.MtpDatabase.strings;
+import static com.android.mtp.TestUtil.OPERATIONS_SUPPORTED;
 
 @MediumTest
 public class MtpDocumentsProviderTest extends AndroidTestCase {
@@ -77,7 +78,7 @@
                             2048 /* total space */,
                             "" /* no volume identifier */)
                 },
-                null,
+                OPERATIONS_SUPPORTED,
                 null));
 
         mProvider.resumeRootScanner();
@@ -98,7 +99,7 @@
         } catch (Throwable error) {
             assertTrue(error instanceof IOException);
         }
-        assertEquals(0, mProvider.getOpenedDeviceIds().length);
+        assertEquals(0, mProvider.getOpenedDeviceRecordsCache().length);
 
         // Check if the following notification is the first one or not.
         mMtpManager.addValidDevice(new MtpDeviceRecord(
@@ -115,7 +116,7 @@
                             2048 /* total space */,
                             "" /* no volume identifier */)
                 },
-                null,
+                OPERATIONS_SUPPORTED,
                 null));
         mProvider.resumeRootScanner();
         mResolver.waitForNotification(ROOTS_URI, 1);
@@ -139,7 +140,7 @@
                             2048 /* total space */,
                             "" /* no volume identifier */)
                 },
-                null,
+                OPERATIONS_SUPPORTED,
                 null));
         mMtpManager.setObjectHandles(0, 1, -1, new int[0]);
         mProvider.resumeRootScanner();
@@ -155,16 +156,16 @@
             assertEquals(1, cursor.getLong(1));
         }
         {
-            final int [] openedDevice = mProvider.getOpenedDeviceIds();
+            final MtpDeviceRecord[] openedDevice = mProvider.getOpenedDeviceRecordsCache();
             assertEquals(0, openedDevice.length);
         }
         // Device is opened automatically when querying its children.
         try (final Cursor cursor = mProvider.queryChildDocuments("1", null, null)) {}
 
         {
-            final int [] openedDevice = mProvider.getOpenedDeviceIds();
+            final MtpDeviceRecord[] openedDevice = mProvider.getOpenedDeviceRecordsCache();
             assertEquals(1, openedDevice.length);
-            assertEquals(0, openedDevice[0]);
+            assertEquals(0, openedDevice[0].deviceId);
         }
     }
 
@@ -184,7 +185,7 @@
                                 2048 /* total space */,
                                 "" /* no volume identifier */)
                 },
-                null,
+                OPERATIONS_SUPPORTED,
                 null));
         mMtpManager.addValidDevice(new MtpDeviceRecord(
                 1,
@@ -200,7 +201,7 @@
                             4096 /* total space */,
                             "Identifier B" /* no volume identifier */)
                 },
-                null,
+                new int[0] /* No operations supported */,
                 null));
 
         {
@@ -225,7 +226,7 @@
             cursor.moveToNext();
             cursor.moveToNext();
             assertEquals("2", cursor.getString(0));
-            assertEquals(Root.FLAG_SUPPORTS_IS_CHILD | Root.FLAG_SUPPORTS_CREATE, cursor.getInt(1));
+            assertEquals(Root.FLAG_SUPPORTS_IS_CHILD, cursor.getInt(1));
             assertEquals(R.drawable.ic_root_mtp, cursor.getInt(2));
             assertEquals("Device B Storage B", cursor.getString(3));
             assertEquals("2", cursor.getString(4));
@@ -241,7 +242,7 @@
                 "Device key A",
                 false /* unopened */,
                 new MtpRoot[0],
-                null,
+                OPERATIONS_SUPPORTED,
                 null));
         mMtpManager.addValidDevice(new MtpDeviceRecord(
                 1,
@@ -257,7 +258,7 @@
                             4096 /* total space */,
                             "Identifier B" /* no volume identifier */)
                 },
-                null,
+                OPERATIONS_SUPPORTED,
                 null));
         {
             mProvider.openDevice(0);
@@ -411,7 +412,7 @@
         assertEquals("image/jpeg", cursor.getString(1));
         assertEquals("image.jpg", cursor.getString(2));
         assertEquals(0, cursor.getLong(3));
-        assertEquals(DocumentsContract.Document.FLAG_SUPPORTS_THUMBNAIL, cursor.getInt(4));
+        assertEquals(Document.FLAG_SUPPORTS_THUMBNAIL, cursor.getInt(4));
         assertEquals(1024 * 1024 * 5, cursor.getInt(5));
 
         cursor.close();
@@ -544,14 +545,14 @@
     public void testBusyDevice() throws Exception {
         mMtpManager = new TestMtpManager(getContext()) {
             @Override
-            void openDevice(int deviceId) throws IOException {
+            MtpDeviceRecord openDevice(int deviceId) throws IOException {
                 throw new BusyDeviceException();
             }
         };
         setupProvider(MtpDatabaseConstants.FLAG_DATABASE_IN_MEMORY);
         mMtpManager.addValidDevice(new MtpDeviceRecord(
-                0, "Device A", null /* deviceKey */, false /* unopened */, new MtpRoot[0], null,
-                null));
+                0, "Device A", null /* deviceKey */, false /* unopened */, new MtpRoot[0],
+                OPERATIONS_SUPPORTED, null));
 
         mProvider.resumeRootScanner();
         mResolver.waitForNotification(ROOTS_URI, 1);
@@ -571,7 +572,8 @@
     public void testLockedDevice() throws Exception {
         setupProvider(MtpDatabaseConstants.FLAG_DATABASE_IN_MEMORY);
         mMtpManager.addValidDevice(new MtpDeviceRecord(
-                0, "Device A", null, false /* unopened */, new MtpRoot[0], null, null));
+                0, "Device A", null, false /* unopened */, new MtpRoot[0], OPERATIONS_SUPPORTED,
+                null));
 
         mProvider.resumeRootScanner();
         mResolver.waitForNotification(ROOTS_URI, 1);
@@ -594,7 +596,7 @@
                 0,
                 "Device A",
                 "device key",
-                true /* unopened */,
+                true /* opened */,
                 new MtpRoot[] {
                     new MtpRoot(
                             0 /* deviceId */,
@@ -604,7 +606,7 @@
                             2048 /* total space */,
                             "" /* no volume identifier */)
                 },
-                null,
+                OPERATIONS_SUPPORTED,
                 null));
 
         final String[] names = strings("Directory A", "Directory B", "Directory C");
@@ -661,6 +663,60 @@
         }
     }
 
+    public void testCreateDocument_noWritingSupport() throws Exception {
+        setupProvider(MtpDatabaseConstants.FLAG_DATABASE_IN_MEMORY);
+        mMtpManager.addValidDevice(new MtpDeviceRecord(
+                0, "Device A", null /* deviceKey */, false /* unopened */,
+                new MtpRoot[] {
+                        new MtpRoot(
+                                0 /* deviceId */,
+                                1 /* storageId */,
+                                "Storage A" /* volume description */,
+                                1024 /* free space */,
+                                2048 /* total space */,
+                                "" /* no volume identifier */)
+                },
+                new int[0] /* no operations supported */, null));
+        mProvider.resumeRootScanner();
+        mResolver.waitForNotification(ROOTS_URI, 1);
+        try {
+            mProvider.createDocument("1", "text/palin", "note.txt");
+            fail();
+        } catch (UnsupportedOperationException exception) {}
+    }
+
+    public void testOpenDocument_noWritingSupport() throws Exception {
+        setupProvider(MtpDatabaseConstants.FLAG_DATABASE_IN_MEMORY);
+        mMtpManager.addValidDevice(new MtpDeviceRecord(
+                0, "Device A", null /* deviceKey */, false /* unopened */,
+                new MtpRoot[] {
+                        new MtpRoot(
+                                0 /* deviceId */,
+                                1 /* storageId */,
+                                "Storage A" /* volume description */,
+                                1024 /* free space */,
+                                2048 /* total space */,
+                                "" /* no volume identifier */)
+                },
+                new int[0] /* no operations supported */, null));
+        mMtpManager.setObjectHandles(
+                0, 1, MtpManager.OBJECT_HANDLE_ROOT_CHILDREN, new int[] { 100 });
+        mMtpManager.setObjectInfo(
+                0, new MtpObjectInfo.Builder().setObjectHandle(100).setName("note.txt").build());
+        mProvider.resumeRootScanner();
+        mResolver.waitForNotification(ROOTS_URI, 1);
+        try (final Cursor cursor = mProvider.queryChildDocuments(
+                "1", strings(Document.COLUMN_DOCUMENT_ID), null)) {
+            assertEquals(1, cursor.getCount());
+            cursor.moveToNext();
+            assertEquals("3", cursor.getString(0));
+        }
+        try {
+            mProvider.openDocument("3", "w", null);
+            fail();
+        } catch (UnsupportedOperationException exception) {}
+    }
+
     private void setupProvider(int flag) {
         mDatabase = new MtpDatabase(getContext(), flag);
         mProvider = new MtpDocumentsProvider();
@@ -691,7 +747,7 @@
         final int changeCount = mResolver.getChangeCount(ROOTS_URI);
         mMtpManager.addValidDevice(
                 new MtpDeviceRecord(deviceId, "Device", null /* deviceKey */, false /* unopened */,
-                roots, null, null));
+                roots, OPERATIONS_SUPPORTED, null));
         mProvider.openDevice(deviceId);
         mResolver.waitForNotification(ROOTS_URI, changeCount + 1);
         return getStrings(mProvider.queryRoots(strings(DocumentsContract.Root.COLUMN_ROOT_ID)));
diff --git a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/PipeManagerTest.java b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/PipeManagerTest.java
index 94f87ff..cdddd81 100644
--- a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/PipeManagerTest.java
+++ b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/PipeManagerTest.java
@@ -45,6 +45,11 @@
         mPipeManager = new PipeManager(mDatabase, mExecutor);
     }
 
+    @Override
+    protected void tearDown() throws Exception {
+        assertTrue(mPipeManager.close());
+    }
+
     public void testReadDocument_basic() throws Exception {
         mtpManager.setImportFileBytes(0, 1, HELLO_BYTES);
         final ParcelFileDescriptor descriptor = mPipeManager.readDocument(
@@ -67,7 +72,9 @@
         final MtpObjectInfo info =
                 new MtpObjectInfo.Builder().setObjectHandle(1).setName("note.txt").build();
         mDatabase.getMapper().startAddingDocuments("2");
-        mDatabase.getMapper().putChildDocuments(0, "2", new MtpObjectInfo[] { info });
+        mDatabase.getMapper().putChildDocuments(
+                0, "2", TestUtil.OPERATIONS_SUPPORTED,
+                new MtpObjectInfo[] { info });
         mDatabase.getMapper().stopAddingDocuments("2");
         // Create a placeholder file which should be replaced by a real file later.
         mtpManager.setObjectInfo(0, info);
@@ -76,7 +83,8 @@
         final ParcelFileDescriptor descriptor = mPipeManager.writeDocument(
                 getContext(),
                 mtpManager,
-                new Identifier(0, 0, 1, "2", MtpDatabaseConstants.DOCUMENT_TYPE_OBJECT));
+                new Identifier(0, 0, 1, "2", MtpDatabaseConstants.DOCUMENT_TYPE_OBJECT),
+                TestUtil.OPERATIONS_SUPPORTED);
         final ParcelFileDescriptor.AutoCloseOutputStream outputStream =
                 new ParcelFileDescriptor.AutoCloseOutputStream(descriptor);
         outputStream.write(HELLO_BYTES, 0, HELLO_BYTES.length);
diff --git a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/TestMtpManager.java b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/TestMtpManager.java
index 3043ce8..5171bd2 100644
--- a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/TestMtpManager.java
+++ b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/TestMtpManager.java
@@ -22,6 +22,7 @@
 import android.util.SparseArray;
 
 import java.io.IOException;
+import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.HashMap;
 import java.util.Map;
@@ -84,16 +85,16 @@
     }
 
     @Override
-    void openDevice(int deviceId) throws IOException {
+    MtpDeviceRecord openDevice(int deviceId) throws IOException {
         final MtpDeviceRecord device = mDevices.get(deviceId);
         if (device == null) {
             throw new IOException();
         }
-        mDevices.put(
-                deviceId,
-                new MtpDeviceRecord(
-                        device.deviceId, device.name, device.deviceKey, true, device.roots, null,
-                        null));
+        final MtpDeviceRecord record = new MtpDeviceRecord(
+                device.deviceId, device.name, device.deviceKey, true, device.roots,
+                device.operationsSupported, device.eventsSupported);
+        mDevices.put(deviceId, record);
+        return record;
     }
 
     @Override
@@ -105,7 +106,7 @@
         mDevices.put(
                 deviceId,
                 new MtpDeviceRecord(device.deviceId, device.name, device.deviceKey, false,
-                        device.roots, null, null));
+                        device.roots, device.operationsSupported, device.eventsSupported));
     }
 
     @Override
@@ -198,19 +199,6 @@
     }
 
     @Override
-    int[] getOpenedDeviceIds() {
-        final int[] result = new int[mDevices.size()];
-        int count = 0;
-        for (int i = 0; i < mDevices.size(); i++) {
-            final MtpDeviceRecord device = mDevices.valueAt(i);
-            if (device.opened) {
-                result[count++] = device.deviceId;
-            }
-        }
-        return Arrays.copyOf(result, count);
-    }
-
-    @Override
     byte[] getObject(int deviceId, int objectHandle, int expectedSize) throws IOException {
         return mImportFileBytes.get(pack(deviceId, objectHandle));
     }
diff --git a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/TestUtil.java b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/TestUtil.java
index 34dd77b..5ceab01 100644
--- a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/TestUtil.java
+++ b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/TestUtil.java
@@ -19,6 +19,7 @@
 import android.hardware.usb.UsbDevice;
 import android.hardware.usb.UsbDeviceConnection;
 import android.hardware.usb.UsbManager;
+import android.mtp.MtpConstants;
 import android.os.SystemClock;
 
 import java.io.FileNotFoundException;
@@ -32,6 +33,13 @@
 final class TestUtil {
     private TestUtil() {}
 
+    static final int[] OPERATIONS_SUPPORTED = new int[] {
+            MtpConstants.OPERATION_GET_PARTIAL_OBJECT,
+            MtpConstants.OPERATION_SEND_OBJECT,
+            MtpConstants.OPERATION_SEND_OBJECT_INFO,
+            MtpConstants.OPERATION_DELETE_OBJECT,
+    };
+
     /**
      * Requests permission for a MTP device and returns the first MTP device that has at least one
      * storage.
@@ -59,14 +67,14 @@
     static void addTestDevice(MtpDatabase database) throws FileNotFoundException {
         database.getMapper().startAddingDocuments(null);
         database.getMapper().putDeviceDocument(new MtpDeviceRecord(
-                0, "Device", "device_key", /* opened is */ true, new MtpRoot[0], null,
-                null));
+                0, "Device", "device_key", /* opened is */ true, new MtpRoot[0],
+                OPERATIONS_SUPPORTED, null));
         database.getMapper().stopAddingDocuments(null);
     }
 
     static void addTestStorage(MtpDatabase database, String parentId) throws FileNotFoundException {
         database.getMapper().startAddingDocuments(parentId);
-        database.getMapper().putStorageDocuments(parentId, new MtpRoot[] {
+        database.getMapper().putStorageDocuments(parentId, OPERATIONS_SUPPORTED, new MtpRoot[] {
                 new MtpRoot(0, 100, "Storage", 1024, 1024, ""),
         });
         database.getMapper().stopAddingDocuments(parentId);
diff --git a/packages/PrintSpooler/AndroidManifest.xml b/packages/PrintSpooler/AndroidManifest.xml
index af9d251..1bdb6d8 100644
--- a/packages/PrintSpooler/AndroidManifest.xml
+++ b/packages/PrintSpooler/AndroidManifest.xml
@@ -63,7 +63,7 @@
             android:name=".ui.PrintActivity"
             android:configChanges="screenSize|smallestScreenSize|orientation"
             android:permission="android.permission.BIND_PRINT_SPOOLER_SERVICE"
-            android:theme="@style/PrintActivity">
+            android:theme="@style/Theme.PrintActivity">
             <intent-filter>
                 <action android:name="android.print.PRINT_DIALOG" />
                 <category android:name="android.intent.category.DEFAULT" />
@@ -74,7 +74,14 @@
         <activity
             android:name=".ui.SelectPrinterActivity"
             android:label="@string/all_printers_label"
-            android:theme="@android:style/Theme.Material.Settings"
+            android:theme="@style/Theme.SelectPrinterActivity"
+            android:exported="false">
+        </activity>
+
+        <activity
+            android:name=".ui.AddPrinterActivity"
+            android:label="@string/print_add_printer"
+            android:theme="@style/Theme.AddPrinterActivity"
             android:exported="false">
         </activity>
 
diff --git a/packages/PrintSpooler/res/drawable/ic_add.xml b/packages/PrintSpooler/res/drawable/ic_add.xml
index 1442b1b..f728e7d 100644
--- a/packages/PrintSpooler/res/drawable/ic_add.xml
+++ b/packages/PrintSpooler/res/drawable/ic_add.xml
@@ -21,5 +21,5 @@
         android:viewportHeight="24.0">
     <path
         android:pathData="M19,13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z"
-        android:fillColor="#FFFFFF"/>
+        android:fillColor="?android:attr/colorAccent"/>
 </vector>
\ No newline at end of file
diff --git a/packages/PrintSpooler/res/drawable/ic_print.xml b/packages/PrintSpooler/res/drawable/ic_print.xml
index dc6e0fb..e5e4d075 100644
--- a/packages/PrintSpooler/res/drawable/ic_print.xml
+++ b/packages/PrintSpooler/res/drawable/ic_print.xml
@@ -16,4 +16,4 @@
 
 <bitmap xmlns:android="http://schemas.android.com/apk/res/android"
     android:src="@*android:drawable/ic_print"
-    android:tint="@color/promoted_action_background_color" />
+    android:tint="?android:attr/colorAccent" />
diff --git a/packages/PrintSpooler/res/drawable/page_selector_background.xml b/packages/PrintSpooler/res/drawable/page_selector_background.xml
index 7f1da31..4d32328 100644
--- a/packages/PrintSpooler/res/drawable/page_selector_background.xml
+++ b/packages/PrintSpooler/res/drawable/page_selector_background.xml
@@ -22,14 +22,14 @@
         android:state_selected="true">
         <bitmap
             android:src="@drawable/ic_check_circle"
-            android:tint="@color/promoted_action_background_color">
+            android:tint="?android:attr/colorAccent">
         </bitmap>
     </item>
 
     <item>
         <bitmap
             android:src="@drawable/ic_remove_circle"
-            android:tint="@color/promoted_action_background_color">
+            android:tint="?android:attr/colorAccent">
         </bitmap>
     </item>
 
diff --git a/packages/PrintSpooler/res/drawable/print_button_background.xml b/packages/PrintSpooler/res/drawable/print_button_background.xml
index aec8474..ad16547 100644
--- a/packages/PrintSpooler/res/drawable/print_button_background.xml
+++ b/packages/PrintSpooler/res/drawable/print_button_background.xml
@@ -18,7 +18,7 @@
     android:shape="oval">
 
     <solid
-        android:color="@color/promoted_action_background_color">
+        android:color="?android:attr/colorAccent">
     </solid>
 
     <size
diff --git a/packages/PrintSpooler/res/layout/add_printer_activity.xml b/packages/PrintSpooler/res/layout/add_printer_activity.xml
new file mode 100644
index 0000000..117bba1
--- /dev/null
+++ b/packages/PrintSpooler/res/layout/add_printer_activity.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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+        android:orientation="vertical"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:paddingTop="16dip"
+        android:paddingBottom="16dip">
+
+    <ListView android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_marginTop="-16dip"
+            android:id="@android:id/list" />
+
+</LinearLayout>
diff --git a/packages/PrintSpooler/res/layout/add_printer_list_header.xml b/packages/PrintSpooler/res/layout/add_printer_list_header.xml
new file mode 100644
index 0000000..ff342cb
--- /dev/null
+++ b/packages/PrintSpooler/res/layout/add_printer_list_header.xml
@@ -0,0 +1,28 @@
+<?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"
+        android:layout_width="fill_parent"
+        android:layout_height="?android:attr/listPreferredItemHeightSmall"
+        android:paddingStart="?android:attr/listPreferredItemPaddingStart"
+        android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
+        android:orientation="horizontal"
+        android:gravity="start|center_vertical">
+
+    <TextView android:id="@+id/text"
+            style="?android:attr/listSeparatorTextViewStyle" />
+
+</LinearLayout>
diff --git a/packages/PrintSpooler/res/layout/add_printer_list_item.xml b/packages/PrintSpooler/res/layout/add_printer_list_item.xml
new file mode 100644
index 0000000..1a2e774
--- /dev/null
+++ b/packages/PrintSpooler/res/layout/add_printer_list_item.xml
@@ -0,0 +1,46 @@
+<?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"
+    android:layout_width="fill_parent"
+    android:layout_height="?android:attr/listPreferredItemHeightSmall"
+    android:paddingStart="?android:attr/listPreferredItemPaddingStart"
+    android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
+    android:orientation="horizontal"
+    android:gravity="start|center_vertical">
+
+    <ImageView
+        android:layout_width="24dip"
+        android:layout_height="24dip"
+        android:layout_gravity="center_vertical"
+        android:contentDescription="@null"
+        android:layout_marginEnd="16dip"
+        android:src="@drawable/ic_add" />
+
+    <RelativeLayout
+        android:layout_width="fill_parent"
+        android:layout_height="wrap_content"
+        android:layout_marginStart="16dip">
+
+        <TextView
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:textAppearance="?android:attr/textAppearanceListItem"
+            android:text="@string/print_add_printer" />
+
+    </RelativeLayout>
+
+</LinearLayout>
diff --git a/packages/PrintSpooler/res/layout/all_print_services_list_item.xml b/packages/PrintSpooler/res/layout/all_print_services_list_item.xml
new file mode 100644
index 0000000..a2471c6
--- /dev/null
+++ b/packages/PrintSpooler/res/layout/all_print_services_list_item.xml
@@ -0,0 +1,38 @@
+<?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"
+    android:layout_width="fill_parent"
+    android:layout_height="?android:attr/listPreferredItemHeightSmall"
+    android:paddingStart="?android:attr/listPreferredItemPaddingStart"
+    android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
+    android:orientation="horizontal"
+    android:gravity="start|center_vertical">
+
+    <RelativeLayout
+        android:layout_width="fill_parent"
+        android:layout_height="wrap_content"
+        android:layout_marginStart="56dip">
+
+        <TextView
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:textAppearance="?android:attr/textAppearanceListItem"
+            android:text="@string/all_services_title" />
+
+    </RelativeLayout>
+
+</LinearLayout>
diff --git a/packages/PrintSpooler/res/layout/disabled_print_services_list_item.xml b/packages/PrintSpooler/res/layout/disabled_print_services_list_item.xml
new file mode 100644
index 0000000..73d0933
--- /dev/null
+++ b/packages/PrintSpooler/res/layout/disabled_print_services_list_item.xml
@@ -0,0 +1,55 @@
+<?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"
+    android:layout_width="fill_parent"
+    android:layout_height="?android:attr/listPreferredItemHeight"
+    android:paddingStart="?android:attr/listPreferredItemPaddingStart"
+    android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
+    android:orientation="horizontal"
+    android:gravity="start|center_vertical">
+
+    <ImageView
+        android:id="@+id/icon"
+        android:layout_width="40dip"
+        android:layout_height="40dip"
+        android:layout_gravity="center_vertical"
+        android:contentDescription="@null" />
+
+    <RelativeLayout
+        android:layout_width="fill_parent"
+        android:layout_height="wrap_content"
+        android:layout_marginStart="16dip">
+
+        <TextView
+            android:id="@+id/title"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:textAppearance="?android:attr/textAppearanceListItem"
+            android:singleLine="true"
+            android:ellipsize="end" />
+
+        <TextView
+            android:id="@+id/subtitle"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_below="@id/title"
+            android:textAppearance="?android:attr/textAppearanceListItemSecondary"
+            android:text="@string/enable_print_service" />
+
+    </RelativeLayout>
+
+</LinearLayout>
diff --git a/packages/PrintSpooler/res/layout/enabled_print_services_list_item.xml b/packages/PrintSpooler/res/layout/enabled_print_services_list_item.xml
new file mode 100644
index 0000000..c13487a
--- /dev/null
+++ b/packages/PrintSpooler/res/layout/enabled_print_services_list_item.xml
@@ -0,0 +1,54 @@
+<?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"
+    android:layout_width="fill_parent"
+    android:layout_height="?android:attr/listPreferredItemHeight"
+    android:paddingStart="?android:attr/listPreferredItemPaddingStart"
+    android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
+    android:orientation="horizontal"
+    android:gravity="start|center_vertical">
+
+    <ImageView
+        android:id="@+id/icon"
+        android:layout_width="40dip"
+        android:layout_height="40dip"
+        android:layout_gravity="center_vertical"
+        android:contentDescription="@null" />
+
+    <RelativeLayout
+        android:layout_width="fill_parent"
+        android:layout_height="wrap_content"
+        android:layout_marginStart="16dip">
+
+        <TextView
+            android:id="@+id/title"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:textAppearance="?android:attr/textAppearanceListItem"
+            android:singleLine="true"
+            android:ellipsize="end" />
+
+        <TextView
+            android:id="@+id/subtitle"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_below="@id/title"
+            android:textAppearance="?android:attr/textAppearanceListItemSecondary" />
+
+    </RelativeLayout>
+
+</LinearLayout>
diff --git a/packages/PrintSpooler/res/layout/printer_dropdown_item.xml b/packages/PrintSpooler/res/layout/printer_dropdown_item.xml
index defbf8d..103c157 100644
--- a/packages/PrintSpooler/res/layout/printer_dropdown_item.xml
+++ b/packages/PrintSpooler/res/layout/printer_dropdown_item.xml
@@ -16,10 +16,8 @@
 
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
       android:layout_width="fill_parent"
-      android:layout_height="wrap_content"
-      android:paddingStart="8dip"
-      android:paddingEnd="8dip"
-      android:minHeight="56dip"
+      android:layout_height="?android:attr/listPreferredItemHeightSmall"
+      style="?android:attr/spinnerItemStyle"
       android:orientation="horizontal"
       android:gravity="start|center_vertical">
 
@@ -33,10 +31,9 @@
         android:visibility="invisible">
     </ImageView>
 
-    <LinearLayout
+    <RelativeLayout
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
-        android:orientation="vertical"
         android:layout_marginStart="8dip"
         android:duplicateParentState="true">
 
@@ -47,8 +44,6 @@
             android:textAppearance="?android:attr/textAppearanceMedium"
             android:singleLine="true"
             android:ellipsize="end"
-            android:textIsSelectable="false"
-            android:gravity="top|start"
             android:textColor="?android:attr/textColorPrimary"
             android:duplicateParentState="true">
         </TextView>
@@ -57,15 +52,15 @@
             android:id="@+id/subtitle"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
+            android:layout_below="@id/title"
             android:textAppearance="?android:attr/textAppearanceSmall"
             android:singleLine="true"
             android:ellipsize="end"
-            android:textIsSelectable="false"
             android:visibility="gone"
             android:textColor="?android:attr/textColorSecondary"
             android:duplicateParentState="true">
         </TextView>
 
-    </LinearLayout>
+    </RelativeLayout>
 
 </LinearLayout>
diff --git a/packages/PrintSpooler/res/layout/printer_dropdown_prompt.xml b/packages/PrintSpooler/res/layout/printer_dropdown_prompt.xml
index 11fef2d..60f7088 100644
--- a/packages/PrintSpooler/res/layout/printer_dropdown_prompt.xml
+++ b/packages/PrintSpooler/res/layout/printer_dropdown_prompt.xml
@@ -16,13 +16,10 @@
 
 <TextView xmlns:android="http://schemas.android.com/apk/res/android"
       android:layout_width="fill_parent"
-      android:layout_height="wrap_content"
+      android:layout_height="?android:attr/listPreferredItemHeightSmall"
       android:textAppearance="?android:attr/textAppearanceMedium"
-      android:textIsSelectable="false"
       android:textColor="?android:attr/textColorPrimary"
       android:paddingStart="20dip"
-      android:paddingEnd="8dip"
-      android:minHeight="56dip"
-      android:orientation="horizontal"
+      style="?android:attr/spinnerItemStyle"
       android:text="@string/destination_default_text"
       android:gravity="start|center_vertical" />
diff --git a/packages/PrintSpooler/res/layout/printer_list_item.xml b/packages/PrintSpooler/res/layout/printer_list_item.xml
index 1209aa6..0784bab 100644
--- a/packages/PrintSpooler/res/layout/printer_list_item.xml
+++ b/packages/PrintSpooler/res/layout/printer_list_item.xml
@@ -16,10 +16,9 @@
 
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="fill_parent"
-    android:layout_height="wrap_content"
+    android:layout_height="?android:attr/listPreferredItemHeight"
     android:paddingStart="?android:attr/listPreferredItemPaddingStart"
     android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
-    android:minHeight="?android:attr/listPreferredItemHeight"
     android:orientation="horizontal"
     android:gravity="start|center_vertical">
 
@@ -28,18 +27,15 @@
         android:layout_width="40dip"
         android:layout_height="40dip"
         android:layout_gravity="center_vertical"
-        android:layout_marginTop="8dip"
-        android:layout_marginBottom="8dip"
         android:duplicateParentState="true"
         android:contentDescription="@null"
         android:visibility="invisible">
     </ImageView>
 
     <RelativeLayout
-        android:layout_width="0dip"
+        android:layout_width="fill_parent"
         android:layout_weight="1"
         android:layout_height="wrap_content"
-        android:layout_gravity="center_vertical"
         android:layout_marginStart="16dip"
         android:duplicateParentState="true">
 
@@ -47,15 +43,9 @@
             android:id="@+id/title"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
-            android:textAppearance="?android:attr/textAppearanceMedium"
+            android:textAppearance="?android:attr/textAppearanceListItem"
             android:singleLine="true"
             android:ellipsize="end"
-            android:textIsSelectable="false"
-            android:layout_alignParentTop="true"
-            android:layout_alignParentStart="true"
-            android:fadingEdge="horizontal"
-            android:textAlignment="viewStart"
-            android:textColor="?android:attr/textColorPrimary"
             android:duplicateParentState="true">
         </TextView>
 
@@ -64,30 +54,31 @@
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:layout_below="@id/title"
-            android:layout_alignParentStart="true"
-            android:textAppearance="?android:attr/textAppearanceSmall"
+            android:textAppearance="?android:attr/textAppearanceListItemSecondary"
             android:singleLine="true"
             android:ellipsize="end"
-            android:textIsSelectable="false"
             android:visibility="gone"
-            android:textColor="?android:attr/textColorSecondary"
-            android:textAlignment="viewStart"
             android:duplicateParentState="true">
         </TextView>
 
     </RelativeLayout>
 
-    <ImageView
+    <!-- wrapper for image view to increase the touch target size -->
+    <LinearLayout
         android:id="@+id/more_info"
         android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_gravity="center_vertical"
-        android:paddingLeft="16dip"
-        android:contentDescription="@string/printer_info_desc"
-        android:src="@drawable/ic_info"
-        android:tint="?android:attr/colorControlNormal"
-        android:tintMode="src_in"
+        android:layout_height="fill_parent"
         android:visibility="gone">
-    </ImageView>
+
+        <ImageView
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_gravity="center_vertical"
+            android:paddingLeft="16dip"
+            android:contentDescription="@string/printer_info_desc"
+            android:src="@drawable/ic_info"
+            android:tint="?android:attr/colorControlNormal"
+            android:tintMode="src_in" />
+    </LinearLayout>
 
 </LinearLayout>
diff --git a/packages/PrintSpooler/res/layout/select_printer_activity.xml b/packages/PrintSpooler/res/layout/select_printer_activity.xml
index 77c500a..564802a 100644
--- a/packages/PrintSpooler/res/layout/select_printer_activity.xml
+++ b/packages/PrintSpooler/res/layout/select_printer_activity.xml
@@ -22,11 +22,7 @@
     <ListView
         android:id="@android:id/list"
         android:layout_width="fill_parent"
-        android:layout_height="fill_parent"
-        android:scrollbarStyle="outsideOverlay"
-        android:cacheColorHint="@android:color/transparent"
-        android:scrollbarAlwaysDrawVerticalTrack="true" >
-    </ListView>
+        android:layout_height="fill_parent" />
 
     <FrameLayout
         android:id="@+id/empty_print_state"
@@ -63,9 +59,18 @@
                 android:layout_width="fill_parent"
                 android:layout_height="wrap_content"
                 android:indeterminate="true"
-                style="@android:style/Widget.DeviceDefault.Light.ProgressBar.Horizontal">
+                style="?android:attr/progressBarStyleHorizontal">
             </ProgressBar>
 
+            <Button
+                    android:id="@+id/button"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    style="?android:attr/buttonBarButtonStyle"
+                    android:textAppearance="?android:attr/textAppearanceSmall"
+                    android:text="@string/print_add_printer"
+                    android:textAllCaps="true" />
+
         </LinearLayout>
 
     </FrameLayout>
diff --git a/packages/PrintSpooler/res/menu/select_printer_activity.xml b/packages/PrintSpooler/res/menu/select_printer_activity.xml
index 15cc139..60dfdca 100644
--- a/packages/PrintSpooler/res/menu/select_printer_activity.xml
+++ b/packages/PrintSpooler/res/menu/select_printer_activity.xml
@@ -26,12 +26,4 @@
         android:imeOptions="actionSearch">
     </item>
 
-    <item
-        android:id="@+id/action_add_printer"
-        android:title="@string/print_add_printer"
-        android:icon="@drawable/ic_add"
-        android:showAsAction="ifRoom"
-        android:alphabeticShortcut="a">
-    </item>
-
 </menu>
diff --git a/packages/PrintSpooler/res/values-af/strings.xml b/packages/PrintSpooler/res/values-af/strings.xml
index 57ba2b6..c8478f2 100644
--- a/packages/PrintSpooler/res/values-af/strings.xml
+++ b/packages/PrintSpooler/res/values-af/strings.xml
@@ -61,11 +61,17 @@
     </plurals>
     <string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> – <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="printer_info_desc" msgid="7181988788991581654">"Meer inligting oor hierdie drukker"</string>
-    <string name="print_services_disabled_toast" msgid="1205302482388937547">"Sommige drukdienste is gedeaktiveer."</string>
-    <string name="choose_print_service" msgid="3740309762324459694">"Kies drukdiens"</string>
+    <string name="print_services_disabled_toast" msgid="9089060734685174685">"Sommige drukdienste is gedeaktiveer"</string>
     <string name="print_searching_for_printers" msgid="6550424555079932867">"Soek tans vir drukkers"</string>
     <string name="print_no_print_services" msgid="8561247706423327966">"Geen drukdienste is geaktiveer nie"</string>
     <string name="print_no_printers" msgid="4869403323900054866">"Geen drukkers gekry nie"</string>
+    <string name="cannot_add_printer" msgid="7840348733668023106">"Kan nie drukkers byvoeg nie"</string>
+    <string name="select_to_add_printers" msgid="3800709038689830974">"Kies om drukker by te voeg"</string>
+    <string name="enable_print_service" msgid="3482815747043533842">"Kies om te aktiveer"</string>
+    <string name="enabled_services_title" msgid="7036986099096582296">"Geaktiveerde dienste"</string>
+    <string name="recommended_services_title" msgid="3799434882937956924">"Aanbevole dienste"</string>
+    <string name="disabled_services_title" msgid="7313253167968363211">"Gedeaktiveerde dienste"</string>
+    <string name="all_services_title" msgid="5578662754874906455">"Alle dienste"</string>
     <string name="printing_notification_title_template" msgid="295903957762447362">"Druk tans <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
     <string name="cancelling_notification_title_template" msgid="1821759594704703197">"Kanselleer tans <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
     <string name="failed_notification_title_template" msgid="2256217208186530973">"Drukkerfout by <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/PrintSpooler/res/values-am/strings.xml b/packages/PrintSpooler/res/values-am/strings.xml
index a2182fb..d4426cc 100644
--- a/packages/PrintSpooler/res/values-am/strings.xml
+++ b/packages/PrintSpooler/res/values-am/strings.xml
@@ -61,11 +61,17 @@
     </plurals>
     <string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="printer_info_desc" msgid="7181988788991581654">"ተጨማሪ የዚህ አታሚ መረጃ"</string>
-    <string name="print_services_disabled_toast" msgid="1205302482388937547">"አንዳንድ የህትመት አገልግሎቶች ተሰናክለዋል።"</string>
-    <string name="choose_print_service" msgid="3740309762324459694">"የህትመት አገልግሎት ይምረጡ"</string>
+    <string name="print_services_disabled_toast" msgid="9089060734685174685">"አንዳንድ የህትመት አገልግሎቶች ተሰናክለዋል"</string>
     <string name="print_searching_for_printers" msgid="6550424555079932867">"አታሚዎችን በመፈለግ ላይ"</string>
     <string name="print_no_print_services" msgid="8561247706423327966">"ምንም የህትመት አገልግሎቶች አልነቁም"</string>
     <string name="print_no_printers" msgid="4869403323900054866">"ምንም አታሚዎች አልተገኙም"</string>
+    <string name="cannot_add_printer" msgid="7840348733668023106">"አታሚዎችን ማከል አልተቻለም"</string>
+    <string name="select_to_add_printers" msgid="3800709038689830974">"አታሚን ለማከል ይምረጡ"</string>
+    <string name="enable_print_service" msgid="3482815747043533842">"ለማንቃት ይምረጡ"</string>
+    <string name="enabled_services_title" msgid="7036986099096582296">"የነቁ አገልግሎቶች"</string>
+    <string name="recommended_services_title" msgid="3799434882937956924">"የሚመከሩ አገልግሎቶች"</string>
+    <string name="disabled_services_title" msgid="7313253167968363211">"የተሰናከሉ አገልግሎቶች"</string>
+    <string name="all_services_title" msgid="5578662754874906455">"ሁሉም አገልግሎቶች"</string>
     <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>
diff --git a/packages/PrintSpooler/res/values-ar/strings.xml b/packages/PrintSpooler/res/values-ar/strings.xml
index eab1339..2e1b6d0 100644
--- a/packages/PrintSpooler/res/values-ar/strings.xml
+++ b/packages/PrintSpooler/res/values-ar/strings.xml
@@ -65,11 +65,17 @@
     </plurals>
     <string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="printer_info_desc" msgid="7181988788991581654">"مزيد من المعلومات حول هذه الطابعة"</string>
-    <string name="print_services_disabled_toast" msgid="1205302482388937547">"بعض خدمات الطباعة معطَّلة."</string>
-    <string name="choose_print_service" msgid="3740309762324459694">"اختر خدمة طباعة"</string>
+    <string name="print_services_disabled_toast" msgid="9089060734685174685">"بعض خدمات الطباعة معطَّلة"</string>
     <string name="print_searching_for_printers" msgid="6550424555079932867">"البحث عن طابعات"</string>
     <string name="print_no_print_services" msgid="8561247706423327966">"لم يتم تمكين أي خدمات طباعة"</string>
     <string name="print_no_printers" msgid="4869403323900054866">"لم يتم العثور على طابعات"</string>
+    <string name="cannot_add_printer" msgid="7840348733668023106">"تعذرت إضافة طابعات"</string>
+    <string name="select_to_add_printers" msgid="3800709038689830974">"اختر لإضافة طابعة"</string>
+    <string name="enable_print_service" msgid="3482815747043533842">"حدد للتمكين"</string>
+    <string name="enabled_services_title" msgid="7036986099096582296">"الخدمات الممكنة"</string>
+    <string name="recommended_services_title" msgid="3799434882937956924">"الخدمات الموصى بها"</string>
+    <string name="disabled_services_title" msgid="7313253167968363211">"الخدمات المعطَّلة"</string>
+    <string name="all_services_title" msgid="5578662754874906455">"جميع الخدمات"</string>
     <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>
diff --git a/packages/PrintSpooler/res/values-az-rAZ/strings.xml b/packages/PrintSpooler/res/values-az-rAZ/strings.xml
index bff477d..5490b84 100644
--- a/packages/PrintSpooler/res/values-az-rAZ/strings.xml
+++ b/packages/PrintSpooler/res/values-az-rAZ/strings.xml
@@ -61,11 +61,17 @@
     </plurals>
     <string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="printer_info_desc" msgid="7181988788991581654">"Bu printer haqqında daha ətraflı məlumat"</string>
-    <string name="print_services_disabled_toast" msgid="1205302482388937547">"Bəzi çap xidmətləri deaktiv edilib."</string>
-    <string name="choose_print_service" msgid="3740309762324459694">"Çap xidmətini seçin"</string>
+    <string name="print_services_disabled_toast" msgid="9089060734685174685">"Bəzi çap xidmətləri deaktiv edilib."</string>
     <string name="print_searching_for_printers" msgid="6550424555079932867">"Printer axtarılır"</string>
     <string name="print_no_print_services" msgid="8561247706423327966">"Heç bir çap xidməti aktiv edilməyib"</string>
     <string name="print_no_printers" msgid="4869403323900054866">"Heç bir printer tapılmadı"</string>
+    <string name="cannot_add_printer" msgid="7840348733668023106">"Printerlər əlavə edilmədi"</string>
+    <string name="select_to_add_printers" msgid="3800709038689830974">"Printer əlavə etmək üçün seçin"</string>
+    <string name="enable_print_service" msgid="3482815747043533842">"Aktiv etmək üçün seçin"</string>
+    <string name="enabled_services_title" msgid="7036986099096582296">"Aktiv edilmiş xidmətlər"</string>
+    <string name="recommended_services_title" msgid="3799434882937956924">"Tövsiyə olunan xidmətlər"</string>
+    <string name="disabled_services_title" msgid="7313253167968363211">"Deaktiv edilmiş xidmətlər"</string>
+    <string name="all_services_title" msgid="5578662754874906455">"Bütün xidmətlər"</string>
     <string name="printing_notification_title_template" msgid="295903957762447362">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> çap edilir"</string>
     <string name="cancelling_notification_title_template" msgid="1821759594704703197">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> ləğv edilir"</string>
     <string name="failed_notification_title_template" msgid="2256217208186530973">"Printer xətası <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/PrintSpooler/res/values-b+sr+Latn/strings.xml b/packages/PrintSpooler/res/values-b+sr+Latn/strings.xml
index b28aa29..0574dae 100644
--- a/packages/PrintSpooler/res/values-b+sr+Latn/strings.xml
+++ b/packages/PrintSpooler/res/values-b+sr+Latn/strings.xml
@@ -62,11 +62,17 @@
     </plurals>
     <string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> – <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="printer_info_desc" msgid="7181988788991581654">"Još informacija o ovom štampaču"</string>
-    <string name="print_services_disabled_toast" msgid="1205302482388937547">"Neke usluge štampanja su onemogućene."</string>
-    <string name="choose_print_service" msgid="3740309762324459694">"Izaberite uslugu štampanja"</string>
+    <string name="print_services_disabled_toast" msgid="9089060734685174685">"Neke usluge štampanja su onemogućene"</string>
     <string name="print_searching_for_printers" msgid="6550424555079932867">"Pretraga štampača"</string>
     <string name="print_no_print_services" msgid="8561247706423327966">"Nijedna usluga štampanja nije omogućena"</string>
     <string name="print_no_printers" msgid="4869403323900054866">"Nije pronađen nijedan štampač"</string>
+    <string name="cannot_add_printer" msgid="7840348733668023106">"Nije moguće dodati štampače"</string>
+    <string name="select_to_add_printers" msgid="3800709038689830974">"Izaberite da biste dodali štampač"</string>
+    <string name="enable_print_service" msgid="3482815747043533842">"Izaberite da biste omogućili"</string>
+    <string name="enabled_services_title" msgid="7036986099096582296">"Omogućene usluge"</string>
+    <string name="recommended_services_title" msgid="3799434882937956924">"Preporučene usluge"</string>
+    <string name="disabled_services_title" msgid="7313253167968363211">"Onemogućene usluge"</string>
+    <string name="all_services_title" msgid="5578662754874906455">"Sve usluge"</string>
     <string name="printing_notification_title_template" msgid="295903957762447362">"Štampa se <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
     <string name="cancelling_notification_title_template" msgid="1821759594704703197">"Otkazuje se <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
     <string name="failed_notification_title_template" msgid="2256217208186530973">"Greška štampača <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/PrintSpooler/res/values-bg/strings.xml b/packages/PrintSpooler/res/values-bg/strings.xml
index e8de8ea..88af8e4 100644
--- a/packages/PrintSpooler/res/values-bg/strings.xml
+++ b/packages/PrintSpooler/res/values-bg/strings.xml
@@ -61,11 +61,17 @@
     </plurals>
     <string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> – <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="printer_info_desc" msgid="7181988788991581654">"Още информация за този принтер"</string>
-    <string name="print_services_disabled_toast" msgid="1205302482388937547">"Някои услуги за отпечатване са деактивирани."</string>
-    <string name="choose_print_service" msgid="3740309762324459694">"Избиране на услуга за отпечатване"</string>
+    <string name="print_services_disabled_toast" msgid="9089060734685174685">"Някои услуги за отпечатване са деактивирани"</string>
     <string name="print_searching_for_printers" msgid="6550424555079932867">"Търсене на принтери"</string>
     <string name="print_no_print_services" msgid="8561247706423327966">"Няма активирани услуги за отпечатване"</string>
     <string name="print_no_printers" msgid="4869403323900054866">"Няма намерени принтери"</string>
+    <string name="cannot_add_printer" msgid="7840348733668023106">"Не могат да се добавят принтери"</string>
+    <string name="select_to_add_printers" msgid="3800709038689830974">"Изберете, за да добавите принтер"</string>
+    <string name="enable_print_service" msgid="3482815747043533842">"Изберете, за да активирате"</string>
+    <string name="enabled_services_title" msgid="7036986099096582296">"Активирани услуги"</string>
+    <string name="recommended_services_title" msgid="3799434882937956924">"Препоръчителни услуги"</string>
+    <string name="disabled_services_title" msgid="7313253167968363211">"Деактивирани услуги"</string>
+    <string name="all_services_title" msgid="5578662754874906455">"Всички услуги"</string>
     <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>
diff --git a/packages/PrintSpooler/res/values-bn-rBD/strings.xml b/packages/PrintSpooler/res/values-bn-rBD/strings.xml
index a1ca494..c61ef74 100644
--- a/packages/PrintSpooler/res/values-bn-rBD/strings.xml
+++ b/packages/PrintSpooler/res/values-bn-rBD/strings.xml
@@ -16,7 +16,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_label" msgid="4469836075319831821">"মুদ্রণ স্পোলার"</string>
+    <string name="app_label" msgid="4469836075319831821">"প্রিন্ট স্পোলার"</string>
     <string name="more_options_button" msgid="2243228396432556771">"আরো বিকল্প"</string>
     <string name="label_destination" msgid="9132510997381599275">"গন্তব্য"</string>
     <string name="label_copies" msgid="3634531042822968308">"প্রতিলিপিগুলি"</string>
@@ -31,22 +31,22 @@
     <string name="template_all_pages" msgid="3322235982020148762">"সমস্ত <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
     <string name="template_page_range" msgid="428638530038286328">"<xliff:g id="PAGE_COUNT">%1$s</xliff:g> এর পরিসর"</string>
     <string name="pages_range_example" msgid="8558694453556945172">"যেমন, ১—৫,৮,১১—১৩"</string>
-    <string name="print_preview" msgid="8010217796057763343">"মুদ্রণ পূর্বরূপ"</string>
+    <string name="print_preview" msgid="8010217796057763343">"প্রিন্ট পূর্বরূপ"</string>
     <string name="install_for_print_preview" msgid="6366303997385509332">"পূর্বরূপ দেখার জন্য PDF ভিউয়ার ইনস্টল করুন"</string>
-    <string name="printing_app_crashed" msgid="854477616686566398">"মুদ্রণ অ্যাপ্লিকেশান ক্র্যাশ করছে"</string>
-    <string name="generating_print_job" msgid="3119608742651698916">"মুদ্রণ কার্য তৈরি করা হচ্ছে"</string>
+    <string name="printing_app_crashed" msgid="854477616686566398">"প্রিন্ট অ্যাপ্লিকেশান ক্র্যাশ করছে"</string>
+    <string name="generating_print_job" msgid="3119608742651698916">"প্রিন্ট কার্য তৈরি করা হচ্ছে"</string>
     <string name="save_as_pdf" msgid="5718454119847596853">"PDF হিসাবে সংরক্ষণ করুন"</string>
     <string name="all_printers" msgid="5018829726861876202">"সমস্ত মুদ্রক…"</string>
-    <string name="print_dialog" msgid="32628687461331979">"মুদ্রণ ডায়লগ"</string>
+    <string name="print_dialog" msgid="32628687461331979">"প্রিন্ট ডায়লগ"</string>
     <string name="current_page_template" msgid="1386638343571771292">"<xliff:g id="CURRENT_PAGE">%1$d</xliff:g> /<xliff:g id="PAGE_COUNT">%2$d</xliff:g>"</string>
     <string name="page_description_template" msgid="6831239682256197161">"<xliff:g id="PAGE_COUNT">%2$d</xliff:g>টির মধ্যে <xliff:g id="CURRENT_PAGE">%1$d</xliff:g> নম্বর পৃষ্ঠা"</string>
     <string name="summary_template" msgid="8899734908625669193">"সারাংশ, <xliff:g id="COPIES">%1$s</xliff:g>টি অনুলিপি, কাগজের আকার <xliff:g id="PAPER_SIZE">%2$s</xliff:g>"</string>
     <string name="expand_handle" msgid="7282974448109280522">"প্রসারিত করার হ্যান্ডেল"</string>
     <string name="collapse_handle" msgid="6886637989442507451">"সঙ্কুচিত করার হ্যান্ডেল"</string>
-    <string name="print_button" msgid="645164566271246268">"মুদ্রণ করুন"</string>
+    <string name="print_button" msgid="645164566271246268">"প্রিন্ট করুন"</string>
     <string name="savetopdf_button" msgid="2976186791686924743">"PDF হিসাবে সংরক্ষণ করুন"</string>
-    <string name="print_options_expanded" msgid="6944679157471691859">"মুদ্রণ বিকল্প প্রসারিত হয়েছে"</string>
-    <string name="print_options_collapsed" msgid="7455930445670414332">"মুদ্রণ বিকল্প সংকুচিত হয়েছে"</string>
+    <string name="print_options_expanded" msgid="6944679157471691859">"প্রিন্ট বিকল্প প্রসারিত হয়েছে"</string>
+    <string name="print_options_collapsed" msgid="7455930445670414332">"প্রিন্ট বিকল্প সংকুচিত হয়েছে"</string>
     <string name="search" msgid="5421724265322228497">"অনুসন্ধান করুন"</string>
     <string name="all_printers_label" msgid="3178848870161526399">"সমস্ত মুদ্রক"</string>
     <string name="add_print_service_label" msgid="5356702546188981940">"পরিষেবা যোগ করুন"</string>
@@ -61,12 +61,18 @@
     </plurals>
     <string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="printer_info_desc" msgid="7181988788991581654">"এই মুদ্রকটির বিষয়ে আরো তথ্য"</string>
-    <string name="print_services_disabled_toast" msgid="1205302482388937547">"কিছু মুদ্রণ পরিষেবা অক্ষম করা হয়েছে৷"</string>
-    <string name="choose_print_service" msgid="3740309762324459694">"মুদ্রণ পরিষেবা চয়ন করুন"</string>
+    <string name="print_services_disabled_toast" msgid="9089060734685174685">"কিছু মুদ্রণ পরিষেবা অক্ষম করা আছে"</string>
     <string name="print_searching_for_printers" msgid="6550424555079932867">"মুদ্রকগুলি অনুসন্ধান করা হচ্ছে"</string>
-    <string name="print_no_print_services" msgid="8561247706423327966">"মুদ্রণ পরিষেবা সক্ষম নেই"</string>
+    <string name="print_no_print_services" msgid="8561247706423327966">"প্রিন্ট পরিষেবা সক্ষম নেই"</string>
     <string name="print_no_printers" msgid="4869403323900054866">"কোনো মুদ্রক পাওয়া যায়নি"</string>
-    <string name="printing_notification_title_template" msgid="295903957762447362">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> মুদ্রণ করা হচ্ছে"</string>
+    <string name="cannot_add_printer" msgid="7840348733668023106">"মুদ্রকগুলি যোগ করা যাবে না"</string>
+    <string name="select_to_add_printers" msgid="3800709038689830974">"মুদ্রক যোগ করতে নির্বাচন করুন"</string>
+    <string name="enable_print_service" msgid="3482815747043533842">"সক্ষম করতে নির্বাচন করুন"</string>
+    <string name="enabled_services_title" msgid="7036986099096582296">"সক্ষম করা পরিষেবাগুলি"</string>
+    <string name="recommended_services_title" msgid="3799434882937956924">"প্রস্তাবিত পরিষেবাগুলি"</string>
+    <string name="disabled_services_title" msgid="7313253167968363211">"অক্ষম করা পরিষেবাগুলি"</string>
+    <string name="all_services_title" msgid="5578662754874906455">"সমস্ত পরিষেবা"</string>
+    <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="blocked_notification_title_template" msgid="1175435827331588646">"মুদ্রক <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> অবরুদ্ধ করেছে"</string>
diff --git a/packages/PrintSpooler/res/values-bs-rBA/strings.xml b/packages/PrintSpooler/res/values-bs-rBA/strings.xml
new file mode 100644
index 0000000..7465c3c
--- /dev/null
+++ b/packages/PrintSpooler/res/values-bs-rBA/strings.xml
@@ -0,0 +1,105 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_label" msgid="4469836075319831821">"Štampanje na čekanju"</string>
+    <string name="more_options_button" msgid="2243228396432556771">"Više opcija"</string>
+    <string name="label_destination" msgid="9132510997381599275">"Odredište"</string>
+    <string name="label_copies" msgid="3634531042822968308">"Kopije"</string>
+    <string name="label_copies_summary" msgid="3861966063536529540">"Primjeraka:"</string>
+    <string name="label_paper_size" msgid="908654383827777759">"Veličina papira"</string>
+    <string name="label_paper_size_summary" msgid="5668204981332138168">"Veličina papira:"</string>
+    <string name="label_color" msgid="1108690305218188969">"U boji"</string>
+    <string name="label_duplex" msgid="5370037254347072243">"Dvostrano"</string>
+    <string name="label_orientation" msgid="2853142581990496477">"Orijentacija"</string>
+    <string name="label_pages" msgid="7768589729282182230">"Stranicā"</string>
+    <string name="destination_default_text" msgid="5422708056807065710">"Odaberite štampač"</string>
+    <string name="template_all_pages" msgid="3322235982020148762">"Sve stranice (<xliff:g id="PAGE_COUNT">%1$s</xliff:g>)"</string>
+    <string name="template_page_range" msgid="428638530038286328">"Opseg od <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
+    <string name="pages_range_example" msgid="8558694453556945172">"npr. 1—5,8,11—13"</string>
+    <string name="print_preview" msgid="8010217796057763343">"Pregled prije štampanja"</string>
+    <string name="install_for_print_preview" msgid="6366303997385509332">"Instaliraj PDF preglednik za prikaz"</string>
+    <string name="printing_app_crashed" msgid="854477616686566398">"Aplikacija za štampanje je prestala raditi"</string>
+    <string name="generating_print_job" msgid="3119608742651698916">"Kreiranje zadatka za štampu"</string>
+    <string name="save_as_pdf" msgid="5718454119847596853">"Sačuvaj kao PDF"</string>
+    <string name="all_printers" msgid="5018829726861876202">"Svi štampači…"</string>
+    <string name="print_dialog" msgid="32628687461331979">"Dijaloški okvir za štampanje"</string>
+    <string name="current_page_template" msgid="1386638343571771292">"<xliff:g id="CURRENT_PAGE">%1$d</xliff:g> /<xliff:g id="PAGE_COUNT">%2$d</xliff:g>"</string>
+    <string name="page_description_template" msgid="6831239682256197161">"Strana <xliff:g id="CURRENT_PAGE">%1$d</xliff:g> od <xliff:g id="PAGE_COUNT">%2$d</xliff:g>"</string>
+    <string name="summary_template" msgid="8899734908625669193">"Rezime, primjeraka <xliff:g id="COPIES">%1$s</xliff:g>, veličina papira <xliff:g id="PAPER_SIZE">%2$s</xliff:g>"</string>
+    <string name="expand_handle" msgid="7282974448109280522">"Regulator za proširivanje"</string>
+    <string name="collapse_handle" msgid="6886637989442507451">"Regulator za skupljanje"</string>
+    <string name="print_button" msgid="645164566271246268">"Štampaj"</string>
+    <string name="savetopdf_button" msgid="2976186791686924743">"Sačuvaj u PDF"</string>
+    <string name="print_options_expanded" msgid="6944679157471691859">"Opcije za štampanje su proširene"</string>
+    <string name="print_options_collapsed" msgid="7455930445670414332">"Opcije za štampanje su skupljene"</string>
+    <string name="search" msgid="5421724265322228497">"Traži"</string>
+    <string name="all_printers_label" msgid="3178848870161526399">"Svi štampači"</string>
+    <string name="add_print_service_label" msgid="5356702546188981940">"Dodaj uslugu"</string>
+    <string name="print_search_box_shown_utterance" msgid="7967404953901376090">"Okvir za pretraživanje je prikazan"</string>
+    <string name="print_search_box_hidden_utterance" msgid="5727755169343113351">"Okvir za pretraživanje je skriven"</string>
+    <string name="print_add_printer" msgid="1088656468360653455">"Dodaj štampač"</string>
+    <string name="print_select_printer" msgid="7388760939873368698">"Izaberite štampač"</string>
+    <string name="print_forget_printer" msgid="5035287497291910766">"Zaboravi ovaj štampač"</string>
+    <plurals name="print_search_result_count_utterance" formatted="false" msgid="6997663738361080868">
+      <item quantity="one"><xliff:g id="COUNT_1">%1$s</xliff:g> štampač je pronađen</item>
+      <item quantity="few"><xliff:g id="COUNT_1">%1$s</xliff:g> štampača su pronađena</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%1$s</xliff:g> štampača je pronađeno</item>
+    </plurals>
+    <string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
+    <string name="printer_info_desc" msgid="7181988788991581654">"Više informacija o ovom štampaču"</string>
+    <string name="print_services_disabled_toast" msgid="9089060734685174685">"Neke usluge za štampanje su isključene"</string>
+    <string name="print_searching_for_printers" msgid="6550424555079932867">"Traženje štampača"</string>
+    <string name="print_no_print_services" msgid="8561247706423327966">"Usluga za štampanje nije uključena"</string>
+    <string name="print_no_printers" msgid="4869403323900054866">"Nijedan štampač nije pronađen"</string>
+    <string name="cannot_add_printer" msgid="7840348733668023106">"Ne mogu se dodati štampači"</string>
+    <string name="select_to_add_printers" msgid="3800709038689830974">"Odaberite da biste dodali štampač"</string>
+    <string name="enable_print_service" msgid="3482815747043533842">"Odaberite da biste uključili"</string>
+    <string name="enabled_services_title" msgid="7036986099096582296">"Uključene usluge"</string>
+    <string name="recommended_services_title" msgid="3799434882937956924">"Preporučene usluge"</string>
+    <string name="disabled_services_title" msgid="7313253167968363211">"Isključene usluge"</string>
+    <string name="all_services_title" msgid="5578662754874906455">"Sve usluge"</string>
+    <string name="printing_notification_title_template" msgid="295903957762447362">"Štampa se <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
+    <string name="cancelling_notification_title_template" msgid="1821759594704703197">"Otkazivanje <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
+    <string name="failed_notification_title_template" msgid="2256217208186530973">"Greška pri štampanju <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
+    <string name="blocked_notification_title_template" msgid="1175435827331588646">"Štampač je blokirao <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
+    <string name="cancel" msgid="4373674107267141885">"Otkaži"</string>
+    <string name="restart" msgid="2472034227037808749">"Ponovo pokreni"</string>
+    <string name="no_connection_to_printer" msgid="2159246915977282728">"Nema konekcije sa štampačem"</string>
+    <string name="reason_unknown" msgid="5507940196503246139">"nepoznat"</string>
+    <string name="printer_unavailable" msgid="2434170617003315690">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> – nedostupan"</string>
+    <string name="print_service_security_warning_title" msgid="2160752291246775320">"Zaista želite koristiti uslugu <xliff:g id="SERVICE">%1$s</xliff:g>?"</string>
+    <string name="print_service_security_warning_summary" msgid="1427434625361692006">"Moguće je da dokument prije štampanja prođe kroz jedan ili više servera."</string>
+  <string-array name="color_mode_labels">
+    <item msgid="7602948745415174937">"Crno-bijela"</item>
+    <item msgid="2762241247228983754">"U boji"</item>
+  </string-array>
+  <string-array name="duplex_mode_labels">
+    <item msgid="3882302912790928315">"Nije podržano"</item>
+    <item msgid="7296563835355641719">"Po dužoj strani"</item>
+    <item msgid="79513688117503758">"Po kraćoj strani"</item>
+  </string-array>
+  <string-array name="orientation_labels">
+    <item msgid="4061931020926489228">"Uspravno"</item>
+    <item msgid="3199660090246166812">"Vodoravno"</item>
+  </string-array>
+    <string name="print_write_error_message" msgid="5787642615179572543">"Nije moguće pisati u fajl"</string>
+    <string name="print_error_default_message" msgid="8602678405502922346">"Nažalost, nije uspjelo. Pokušajte ponovo."</string>
+    <string name="print_error_retry" msgid="1426421728784259538">"Ponovi"</string>
+    <string name="print_error_printer_unavailable" msgid="8985614415253203381">"Štampač trenutno nije dostupan."</string>
+    <string name="print_preparing_preview" msgid="3939930735671364712">"Priprema pregleda..."</string>
+</resources>
diff --git a/packages/PrintSpooler/res/values-ca/strings.xml b/packages/PrintSpooler/res/values-ca/strings.xml
index aa6f992..482100a 100644
--- a/packages/PrintSpooler/res/values-ca/strings.xml
+++ b/packages/PrintSpooler/res/values-ca/strings.xml
@@ -61,11 +61,17 @@
     </plurals>
     <string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="printer_info_desc" msgid="7181988788991581654">"Més informació sobre aquesta impressora"</string>
-    <string name="print_services_disabled_toast" msgid="1205302482388937547">"Hi ha serveis d\'impressió que estan desactivats."</string>
-    <string name="choose_print_service" msgid="3740309762324459694">"Selecció del servei d\'impressió"</string>
+    <string name="print_services_disabled_toast" msgid="9089060734685174685">"Alguns serveis d\'impressió estan desactivats"</string>
     <string name="print_searching_for_printers" msgid="6550424555079932867">"Cerca d\'impressores"</string>
     <string name="print_no_print_services" msgid="8561247706423327966">"No hi ha cap servei d\'impressió activat"</string>
     <string name="print_no_printers" msgid="4869403323900054866">"No s\'ha trobat cap impressora"</string>
+    <string name="cannot_add_printer" msgid="7840348733668023106">"No poden afegir impressores"</string>
+    <string name="select_to_add_printers" msgid="3800709038689830974">"Selecciona per afegir una impressora"</string>
+    <string name="enable_print_service" msgid="3482815747043533842">"Selecciona\'ls per activar-los"</string>
+    <string name="enabled_services_title" msgid="7036986099096582296">"Serveis activats"</string>
+    <string name="recommended_services_title" msgid="3799434882937956924">"Serveis recomanats"</string>
+    <string name="disabled_services_title" msgid="7313253167968363211">"Serveis desactivats"</string>
+    <string name="all_services_title" msgid="5578662754874906455">"Tots els serveis"</string>
     <string name="printing_notification_title_template" msgid="295903957762447362">"S\'està imprimint <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
     <string name="cancelling_notification_title_template" msgid="1821759594704703197">"S\'està cancel·lant <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
     <string name="failed_notification_title_template" msgid="2256217208186530973">"Error d\'impressora <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/PrintSpooler/res/values-cs/strings.xml b/packages/PrintSpooler/res/values-cs/strings.xml
index 4bc22d4..a4c412c 100644
--- a/packages/PrintSpooler/res/values-cs/strings.xml
+++ b/packages/PrintSpooler/res/values-cs/strings.xml
@@ -63,11 +63,17 @@
     </plurals>
     <string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> – <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="printer_info_desc" msgid="7181988788991581654">"Další informace o této tiskárně"</string>
-    <string name="print_services_disabled_toast" msgid="1205302482388937547">"Některé tiskové služby nejsou aktivovány."</string>
-    <string name="choose_print_service" msgid="3740309762324459694">"Zvolte službu tisku"</string>
+    <string name="print_services_disabled_toast" msgid="9089060734685174685">"Některé tiskové služby nejsou aktivovány"</string>
     <string name="print_searching_for_printers" msgid="6550424555079932867">"Vyhledávání tiskáren"</string>
     <string name="print_no_print_services" msgid="8561247706423327966">"Nejsou aktivovány žádné tiskové služby"</string>
     <string name="print_no_printers" msgid="4869403323900054866">"Nebyly nalezeny žádné tiskárny"</string>
+    <string name="cannot_add_printer" msgid="7840348733668023106">"Tiskárny nelze přidat"</string>
+    <string name="select_to_add_printers" msgid="3800709038689830974">"Výběrem přidáte tiskárnu"</string>
+    <string name="enable_print_service" msgid="3482815747043533842">"Výběrem službu aktivujete"</string>
+    <string name="enabled_services_title" msgid="7036986099096582296">"Aktivované služby"</string>
+    <string name="recommended_services_title" msgid="3799434882937956924">"Doporučené služby"</string>
+    <string name="disabled_services_title" msgid="7313253167968363211">"Deaktivované služby"</string>
+    <string name="all_services_title" msgid="5578662754874906455">"Všechny služby"</string>
     <string name="printing_notification_title_template" msgid="295903957762447362">"Tisk úlohy <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
     <string name="cancelling_notification_title_template" msgid="1821759594704703197">"Rušení úlohy <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
     <string name="failed_notification_title_template" msgid="2256217208186530973">"Chyba tiskárny u úlohy <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/PrintSpooler/res/values-da/strings.xml b/packages/PrintSpooler/res/values-da/strings.xml
index b8be624..9ee252167 100644
--- a/packages/PrintSpooler/res/values-da/strings.xml
+++ b/packages/PrintSpooler/res/values-da/strings.xml
@@ -61,11 +61,17 @@
     </plurals>
     <string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> – <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="printer_info_desc" msgid="7181988788991581654">"Flere oplysninger om denne printer"</string>
-    <string name="print_services_disabled_toast" msgid="1205302482388937547">"Nogle udskrivningstjenester er deaktiveret."</string>
-    <string name="choose_print_service" msgid="3740309762324459694">"Vælg udskriftstjeneste"</string>
+    <string name="print_services_disabled_toast" msgid="9089060734685174685">"Nogle udskrivningstjenester er deaktiveret"</string>
     <string name="print_searching_for_printers" msgid="6550424555079932867">"Søger efter printere"</string>
     <string name="print_no_print_services" msgid="8561247706423327966">"Ingen udskrivningstjenester er aktiveret"</string>
     <string name="print_no_printers" msgid="4869403323900054866">"Der blev ikke fundet nogen printere"</string>
+    <string name="cannot_add_printer" msgid="7840348733668023106">"Der kan ikke tilføjes printere"</string>
+    <string name="select_to_add_printers" msgid="3800709038689830974">"Vælg for at tilføje en printer"</string>
+    <string name="enable_print_service" msgid="3482815747043533842">"Vælg for at aktivere"</string>
+    <string name="enabled_services_title" msgid="7036986099096582296">"Aktiverede tjenester"</string>
+    <string name="recommended_services_title" msgid="3799434882937956924">"Anbefalede tjenester"</string>
+    <string name="disabled_services_title" msgid="7313253167968363211">"Deaktiverede tjenester"</string>
+    <string name="all_services_title" msgid="5578662754874906455">"Alle tjenester"</string>
     <string name="printing_notification_title_template" msgid="295903957762447362">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> udskrives"</string>
     <string name="cancelling_notification_title_template" msgid="1821759594704703197">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> annulleres"</string>
     <string name="failed_notification_title_template" msgid="2256217208186530973">"Udskriften <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> mislykkedes"</string>
diff --git a/packages/PrintSpooler/res/values-de/strings.xml b/packages/PrintSpooler/res/values-de/strings.xml
index bcb7e73..ef451b7 100644
--- a/packages/PrintSpooler/res/values-de/strings.xml
+++ b/packages/PrintSpooler/res/values-de/strings.xml
@@ -61,11 +61,17 @@
     </plurals>
     <string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> – <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="printer_info_desc" msgid="7181988788991581654">"Weitere Informationen über diesen Drucker"</string>
-    <string name="print_services_disabled_toast" msgid="1205302482388937547">"Einige Druckdienste sind deaktiviert."</string>
-    <string name="choose_print_service" msgid="3740309762324459694">"Druckdienst auswählen"</string>
+    <string name="print_services_disabled_toast" msgid="9089060734685174685">"Einige Druckdienste sind deaktiviert"</string>
     <string name="print_searching_for_printers" msgid="6550424555079932867">"Suche nach Druckern"</string>
     <string name="print_no_print_services" msgid="8561247706423327966">"Keine Druckdienste aktiviert"</string>
     <string name="print_no_printers" msgid="4869403323900054866">"Keine Drucker gefunden"</string>
+    <string name="cannot_add_printer" msgid="7840348733668023106">"Hinzufügen von Druckern nicht möglich"</string>
+    <string name="select_to_add_printers" msgid="3800709038689830974">"Auswählen, um Drucker hinzuzufügen"</string>
+    <string name="enable_print_service" msgid="3482815747043533842">"Zum Aktivieren auswählen"</string>
+    <string name="enabled_services_title" msgid="7036986099096582296">"Aktivierte Dienste"</string>
+    <string name="recommended_services_title" msgid="3799434882937956924">"Empfohlene Dienste"</string>
+    <string name="disabled_services_title" msgid="7313253167968363211">"Deaktivierte Dienste"</string>
+    <string name="all_services_title" msgid="5578662754874906455">"Alle Dienste"</string>
     <string name="printing_notification_title_template" msgid="295903957762447362">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> wird gedruckt..."</string>
     <string name="cancelling_notification_title_template" msgid="1821759594704703197">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> wird abgebrochen..."</string>
     <string name="failed_notification_title_template" msgid="2256217208186530973">"Druckerfehler <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/PrintSpooler/res/values-el/strings.xml b/packages/PrintSpooler/res/values-el/strings.xml
index d9a4aeb..9be81c1 100644
--- a/packages/PrintSpooler/res/values-el/strings.xml
+++ b/packages/PrintSpooler/res/values-el/strings.xml
@@ -61,11 +61,17 @@
     </plurals>
     <string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="printer_info_desc" msgid="7181988788991581654">"Περισσότερες πληροφορίες σχετικά με αυτόν τον εκτυπωτή"</string>
-    <string name="print_services_disabled_toast" msgid="1205302482388937547">"Κάποιες υπηρ. εκτύπωσης είναι απενεργοποιημένες."</string>
-    <string name="choose_print_service" msgid="3740309762324459694">"Επιλέξτε υπηρεσία εκτύπωσης"</string>
+    <string name="print_services_disabled_toast" msgid="9089060734685174685">"Ορισμένες υπηρ. εκτύπωσης είναι απενεργοποιημένες"</string>
     <string name="print_searching_for_printers" msgid="6550424555079932867">"Αναζήτηση για εκτυπωτές"</string>
     <string name="print_no_print_services" msgid="8561247706423327966">"Δεν έχουν ενεργοποιηθεί υπηρεσίες εκτύπωσης"</string>
     <string name="print_no_printers" msgid="4869403323900054866">"Δεν βρέθηκαν εκτυπωτές"</string>
+    <string name="cannot_add_printer" msgid="7840348733668023106">"Δεν είναι δυνατή η προσθήκη εκτυπωτών"</string>
+    <string name="select_to_add_printers" msgid="3800709038689830974">"Επιλέξτε για την προσθήκη εκτυπωτή"</string>
+    <string name="enable_print_service" msgid="3482815747043533842">"Επιλέξτε για ενεργοποίηση"</string>
+    <string name="enabled_services_title" msgid="7036986099096582296">"Ενεργοποιημένες υπηρεσίες"</string>
+    <string name="recommended_services_title" msgid="3799434882937956924">"Προτεινόμενες υπηρεσίες"</string>
+    <string name="disabled_services_title" msgid="7313253167968363211">"Υπηρεσίες για άτομα με αναπηρία"</string>
+    <string name="all_services_title" msgid="5578662754874906455">"Όλες οι υπηρεσίες"</string>
     <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>
diff --git a/packages/PrintSpooler/res/values-en-rAU/strings.xml b/packages/PrintSpooler/res/values-en-rAU/strings.xml
index d8a9437..8b58011 100644
--- a/packages/PrintSpooler/res/values-en-rAU/strings.xml
+++ b/packages/PrintSpooler/res/values-en-rAU/strings.xml
@@ -61,11 +61,17 @@
     </plurals>
     <string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="printer_info_desc" msgid="7181988788991581654">"More information about this printer"</string>
-    <string name="print_services_disabled_toast" msgid="1205302482388937547">"Some print services are disabled."</string>
-    <string name="choose_print_service" msgid="3740309762324459694">"Choose print service"</string>
+    <string name="print_services_disabled_toast" msgid="9089060734685174685">"Some print services are disabled"</string>
     <string name="print_searching_for_printers" msgid="6550424555079932867">"Searching for printers"</string>
     <string name="print_no_print_services" msgid="8561247706423327966">"No print services enabled"</string>
     <string name="print_no_printers" msgid="4869403323900054866">"No printers found"</string>
+    <string name="cannot_add_printer" msgid="7840348733668023106">"Cannot add printers"</string>
+    <string name="select_to_add_printers" msgid="3800709038689830974">"Select to add printer"</string>
+    <string name="enable_print_service" msgid="3482815747043533842">"Select to enable"</string>
+    <string name="enabled_services_title" msgid="7036986099096582296">"Enabled services"</string>
+    <string name="recommended_services_title" msgid="3799434882937956924">"Recommended services"</string>
+    <string name="disabled_services_title" msgid="7313253167968363211">"Disabled services"</string>
+    <string name="all_services_title" msgid="5578662754874906455">"All services"</string>
     <string name="printing_notification_title_template" msgid="295903957762447362">"Printing <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
     <string name="cancelling_notification_title_template" msgid="1821759594704703197">"Cancelling <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
     <string name="failed_notification_title_template" msgid="2256217208186530973">"Printer error <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/PrintSpooler/res/values-en-rGB/strings.xml b/packages/PrintSpooler/res/values-en-rGB/strings.xml
index d8a9437..8b58011 100644
--- a/packages/PrintSpooler/res/values-en-rGB/strings.xml
+++ b/packages/PrintSpooler/res/values-en-rGB/strings.xml
@@ -61,11 +61,17 @@
     </plurals>
     <string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="printer_info_desc" msgid="7181988788991581654">"More information about this printer"</string>
-    <string name="print_services_disabled_toast" msgid="1205302482388937547">"Some print services are disabled."</string>
-    <string name="choose_print_service" msgid="3740309762324459694">"Choose print service"</string>
+    <string name="print_services_disabled_toast" msgid="9089060734685174685">"Some print services are disabled"</string>
     <string name="print_searching_for_printers" msgid="6550424555079932867">"Searching for printers"</string>
     <string name="print_no_print_services" msgid="8561247706423327966">"No print services enabled"</string>
     <string name="print_no_printers" msgid="4869403323900054866">"No printers found"</string>
+    <string name="cannot_add_printer" msgid="7840348733668023106">"Cannot add printers"</string>
+    <string name="select_to_add_printers" msgid="3800709038689830974">"Select to add printer"</string>
+    <string name="enable_print_service" msgid="3482815747043533842">"Select to enable"</string>
+    <string name="enabled_services_title" msgid="7036986099096582296">"Enabled services"</string>
+    <string name="recommended_services_title" msgid="3799434882937956924">"Recommended services"</string>
+    <string name="disabled_services_title" msgid="7313253167968363211">"Disabled services"</string>
+    <string name="all_services_title" msgid="5578662754874906455">"All services"</string>
     <string name="printing_notification_title_template" msgid="295903957762447362">"Printing <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
     <string name="cancelling_notification_title_template" msgid="1821759594704703197">"Cancelling <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
     <string name="failed_notification_title_template" msgid="2256217208186530973">"Printer error <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/PrintSpooler/res/values-en-rIN/strings.xml b/packages/PrintSpooler/res/values-en-rIN/strings.xml
index d8a9437..8b58011 100644
--- a/packages/PrintSpooler/res/values-en-rIN/strings.xml
+++ b/packages/PrintSpooler/res/values-en-rIN/strings.xml
@@ -61,11 +61,17 @@
     </plurals>
     <string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="printer_info_desc" msgid="7181988788991581654">"More information about this printer"</string>
-    <string name="print_services_disabled_toast" msgid="1205302482388937547">"Some print services are disabled."</string>
-    <string name="choose_print_service" msgid="3740309762324459694">"Choose print service"</string>
+    <string name="print_services_disabled_toast" msgid="9089060734685174685">"Some print services are disabled"</string>
     <string name="print_searching_for_printers" msgid="6550424555079932867">"Searching for printers"</string>
     <string name="print_no_print_services" msgid="8561247706423327966">"No print services enabled"</string>
     <string name="print_no_printers" msgid="4869403323900054866">"No printers found"</string>
+    <string name="cannot_add_printer" msgid="7840348733668023106">"Cannot add printers"</string>
+    <string name="select_to_add_printers" msgid="3800709038689830974">"Select to add printer"</string>
+    <string name="enable_print_service" msgid="3482815747043533842">"Select to enable"</string>
+    <string name="enabled_services_title" msgid="7036986099096582296">"Enabled services"</string>
+    <string name="recommended_services_title" msgid="3799434882937956924">"Recommended services"</string>
+    <string name="disabled_services_title" msgid="7313253167968363211">"Disabled services"</string>
+    <string name="all_services_title" msgid="5578662754874906455">"All services"</string>
     <string name="printing_notification_title_template" msgid="295903957762447362">"Printing <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
     <string name="cancelling_notification_title_template" msgid="1821759594704703197">"Cancelling <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
     <string name="failed_notification_title_template" msgid="2256217208186530973">"Printer error <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/PrintSpooler/res/values-es-rUS/strings.xml b/packages/PrintSpooler/res/values-es-rUS/strings.xml
index 19cbee7..8fa6094 100644
--- a/packages/PrintSpooler/res/values-es-rUS/strings.xml
+++ b/packages/PrintSpooler/res/values-es-rUS/strings.xml
@@ -61,11 +61,17 @@
     </plurals>
     <string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="printer_info_desc" msgid="7181988788991581654">"Más información sobre esta impresora"</string>
-    <string name="print_services_disabled_toast" msgid="1205302482388937547">"Hay servicios de impresión inhabilitados."</string>
-    <string name="choose_print_service" msgid="3740309762324459694">"Elegir servicio de impresión"</string>
+    <string name="print_services_disabled_toast" msgid="9089060734685174685">"Hay servicios de impresión inhabilitados"</string>
     <string name="print_searching_for_printers" msgid="6550424555079932867">"Buscando impresoras"</string>
     <string name="print_no_print_services" msgid="8561247706423327966">"No hay servicios de impresión habilitados"</string>
     <string name="print_no_printers" msgid="4869403323900054866">"No se encontraron impresoras"</string>
+    <string name="cannot_add_printer" msgid="7840348733668023106">"No es posible agregar impresoras"</string>
+    <string name="select_to_add_printers" msgid="3800709038689830974">"Seleccionar para agregar impresoras"</string>
+    <string name="enable_print_service" msgid="3482815747043533842">"Seleccionar para habilitar"</string>
+    <string name="enabled_services_title" msgid="7036986099096582296">"Servicios habilitados"</string>
+    <string name="recommended_services_title" msgid="3799434882937956924">"Servicios recomendados"</string>
+    <string name="disabled_services_title" msgid="7313253167968363211">"Servicios inhabilitados"</string>
+    <string name="all_services_title" msgid="5578662754874906455">"Todos los servicios"</string>
     <string name="printing_notification_title_template" msgid="295903957762447362">"Imprimiendo <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
     <string name="cancelling_notification_title_template" msgid="1821759594704703197">"Cancelando <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
     <string name="failed_notification_title_template" msgid="2256217208186530973">"Error de impresora <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/PrintSpooler/res/values-es/strings.xml b/packages/PrintSpooler/res/values-es/strings.xml
index d13ccda..a0ce57a 100644
--- a/packages/PrintSpooler/res/values-es/strings.xml
+++ b/packages/PrintSpooler/res/values-es/strings.xml
@@ -61,11 +61,17 @@
     </plurals>
     <string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="printer_info_desc" msgid="7181988788991581654">"Más información sobre esta impresora"</string>
-    <string name="print_services_disabled_toast" msgid="1205302482388937547">"Algunos servicios de impresión están inhabilitados."</string>
-    <string name="choose_print_service" msgid="3740309762324459694">"Seleccionar servicio de impresión"</string>
+    <string name="print_services_disabled_toast" msgid="9089060734685174685">"Algunos servicios de impresión están inhabilitados"</string>
     <string name="print_searching_for_printers" msgid="6550424555079932867">"Buscando impresoras"</string>
     <string name="print_no_print_services" msgid="8561247706423327966">"No hay servicios de impresión habilitados"</string>
     <string name="print_no_printers" msgid="4869403323900054866">"No se encontraron impresoras"</string>
+    <string name="cannot_add_printer" msgid="7840348733668023106">"No se pueden añadir impresoras"</string>
+    <string name="select_to_add_printers" msgid="3800709038689830974">"Seleccionar para añadir una impresora"</string>
+    <string name="enable_print_service" msgid="3482815747043533842">"Seleccionar para habilitar"</string>
+    <string name="enabled_services_title" msgid="7036986099096582296">"Servicios habilitados"</string>
+    <string name="recommended_services_title" msgid="3799434882937956924">"Servicios recomendados"</string>
+    <string name="disabled_services_title" msgid="7313253167968363211">"Servicios inhabilitados"</string>
+    <string name="all_services_title" msgid="5578662754874906455">"Todos los servicios"</string>
     <string name="printing_notification_title_template" msgid="295903957762447362">"Imprimiendo <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
     <string name="cancelling_notification_title_template" msgid="1821759594704703197">"Cancelando <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
     <string name="failed_notification_title_template" msgid="2256217208186530973">"Error de impresora <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
@@ -91,7 +97,7 @@
     <item msgid="3199660090246166812">"Horizontal"</item>
   </string-array>
     <string name="print_write_error_message" msgid="5787642615179572543">"Error al escribir en el archivo"</string>
-    <string name="print_error_default_message" msgid="8602678405502922346">"No ha funcionado. Repítelo."</string>
+    <string name="print_error_default_message" msgid="8602678405502922346">"No ha funcionado. Prueba de nuevo."</string>
     <string name="print_error_retry" msgid="1426421728784259538">"Reintentar"</string>
     <string name="print_error_printer_unavailable" msgid="8985614415253203381">"Esta impresora no está disponible en este momento."</string>
     <string name="print_preparing_preview" msgid="3939930735671364712">"Preparando vista previa…"</string>
diff --git a/packages/PrintSpooler/res/values-et-rEE/strings.xml b/packages/PrintSpooler/res/values-et-rEE/strings.xml
index f03eb37..6dde083 100644
--- a/packages/PrintSpooler/res/values-et-rEE/strings.xml
+++ b/packages/PrintSpooler/res/values-et-rEE/strings.xml
@@ -61,11 +61,17 @@
     </plurals>
     <string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> – <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="printer_info_desc" msgid="7181988788991581654">"Lisateave selle printeri kohta"</string>
-    <string name="print_services_disabled_toast" msgid="1205302482388937547">"Mõned printimisteenused on keelatud."</string>
-    <string name="choose_print_service" msgid="3740309762324459694">"Prinditeenuse valimine"</string>
+    <string name="print_services_disabled_toast" msgid="9089060734685174685">"Mõned printimisteenused on keelatud"</string>
     <string name="print_searching_for_printers" msgid="6550424555079932867">"Printerite otsimine"</string>
     <string name="print_no_print_services" msgid="8561247706423327966">"Ühtegi printimisteenust pole lubatud"</string>
     <string name="print_no_printers" msgid="4869403323900054866">"Printereid ei leitud"</string>
+    <string name="cannot_add_printer" msgid="7840348733668023106">"Printereid ei saa lisada"</string>
+    <string name="select_to_add_printers" msgid="3800709038689830974">"Valige printeri lisamiseks"</string>
+    <string name="enable_print_service" msgid="3482815747043533842">"Valige lubamiseks"</string>
+    <string name="enabled_services_title" msgid="7036986099096582296">"Lubatud teenused"</string>
+    <string name="recommended_services_title" msgid="3799434882937956924">"Soovitatud teenused"</string>
+    <string name="disabled_services_title" msgid="7313253167968363211">"Keelatud teenused"</string>
+    <string name="all_services_title" msgid="5578662754874906455">"Kõik teenused"</string>
     <string name="printing_notification_title_template" msgid="295903957762447362">"Prinditöö <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> printimine"</string>
     <string name="cancelling_notification_title_template" msgid="1821759594704703197">"Prinditöö <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> tühistamine"</string>
     <string name="failed_notification_title_template" msgid="2256217208186530973">"Printeri viga: <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/PrintSpooler/res/values-eu-rES/strings.xml b/packages/PrintSpooler/res/values-eu-rES/strings.xml
index d4255e2..858444b 100644
--- a/packages/PrintSpooler/res/values-eu-rES/strings.xml
+++ b/packages/PrintSpooler/res/values-eu-rES/strings.xml
@@ -61,11 +61,17 @@
     </plurals>
     <string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="printer_info_desc" msgid="7181988788991581654">"Informazio gehiago inprimagailuari buruz"</string>
-    <string name="print_services_disabled_toast" msgid="1205302482388937547">"Desgaituta daude inprimatzeko zerbitzu batzuk."</string>
-    <string name="choose_print_service" msgid="3740309762324459694">"Aukeratu inprimatze-zerbitzua"</string>
+    <string name="print_services_disabled_toast" msgid="9089060734685174685">"Desgaituta daude inprimatzeko zerbitzu batzuk"</string>
     <string name="print_searching_for_printers" msgid="6550424555079932867">"Inprimagailuak bilatzen"</string>
     <string name="print_no_print_services" msgid="8561247706423327966">"Ez dago gaituta inprimatzeko zerbitzurik"</string>
     <string name="print_no_printers" msgid="4869403323900054866">"Ez da inprimagailurik aurkitu"</string>
+    <string name="cannot_add_printer" msgid="7840348733668023106">"Ezin da gehitu inprimagailurik"</string>
+    <string name="select_to_add_printers" msgid="3800709038689830974">"Hautatu inprimagailua gehitzeko"</string>
+    <string name="enable_print_service" msgid="3482815747043533842">"Hautatu gehitzeko"</string>
+    <string name="enabled_services_title" msgid="7036986099096582296">"Gaitutako zerbitzuak"</string>
+    <string name="recommended_services_title" msgid="3799434882937956924">"Gomendatutako zerbitzuak"</string>
+    <string name="disabled_services_title" msgid="7313253167968363211">"Desgaitutako zerbitzuak"</string>
+    <string name="all_services_title" msgid="5578662754874906455">"Zerbitzu guztiak"</string>
     <string name="printing_notification_title_template" msgid="295903957762447362">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> inprimatzen"</string>
     <string name="cancelling_notification_title_template" msgid="1821759594704703197">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> bertan behera uzten"</string>
     <string name="failed_notification_title_template" msgid="2256217208186530973">"Errorea <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> inprimatzean"</string>
diff --git a/packages/PrintSpooler/res/values-fa/strings.xml b/packages/PrintSpooler/res/values-fa/strings.xml
index 907123c..7c69c27 100644
--- a/packages/PrintSpooler/res/values-fa/strings.xml
+++ b/packages/PrintSpooler/res/values-fa/strings.xml
@@ -61,11 +61,17 @@
     </plurals>
     <string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="printer_info_desc" msgid="7181988788991581654">"اطلاعات بیشتر درباره چاپگر"</string>
-    <string name="print_services_disabled_toast" msgid="1205302482388937547">"بعضی از خدمات چاپ غیرفعال هستند."</string>
-    <string name="choose_print_service" msgid="3740309762324459694">"انتخاب سرویس چاپ"</string>
+    <string name="print_services_disabled_toast" msgid="9089060734685174685">"بعضی از خدمات چاپ غیرفعال هستند"</string>
     <string name="print_searching_for_printers" msgid="6550424555079932867">"درحال جستجوی چاپگرها"</string>
     <string name="print_no_print_services" msgid="8561247706423327966">"هیچ خدمات چاپی فعال نیست"</string>
     <string name="print_no_printers" msgid="4869403323900054866">"هیچ چاپگری یافت نشد"</string>
+    <string name="cannot_add_printer" msgid="7840348733668023106">"نمی‌توان چاپگر اضافه کرد"</string>
+    <string name="select_to_add_printers" msgid="3800709038689830974">"برای افزودن چاپگر، انتخاب کنید"</string>
+    <string name="enable_print_service" msgid="3482815747043533842">"برای فعال کردن، انتخاب کنید"</string>
+    <string name="enabled_services_title" msgid="7036986099096582296">"خدمات فعال"</string>
+    <string name="recommended_services_title" msgid="3799434882937956924">"خدمات توصیه‌شده"</string>
+    <string name="disabled_services_title" msgid="7313253167968363211">"خدمات غیرفعال"</string>
+    <string name="all_services_title" msgid="5578662754874906455">"همه خدمات"</string>
     <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>
diff --git a/packages/PrintSpooler/res/values-fi/strings.xml b/packages/PrintSpooler/res/values-fi/strings.xml
index f57b884..dfd98f8 100644
--- a/packages/PrintSpooler/res/values-fi/strings.xml
+++ b/packages/PrintSpooler/res/values-fi/strings.xml
@@ -61,11 +61,17 @@
     </plurals>
     <string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> – <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="printer_info_desc" msgid="7181988788991581654">"Lisätietoja tästä tulostimesta"</string>
-    <string name="print_services_disabled_toast" msgid="1205302482388937547">"Osa tulostuspalveluista on poistettu käytöstä."</string>
-    <string name="choose_print_service" msgid="3740309762324459694">"Valitse tulostuspalvelu"</string>
+    <string name="print_services_disabled_toast" msgid="9089060734685174685">"Osa tulostuspalveluista on poistettu käytöstä."</string>
     <string name="print_searching_for_printers" msgid="6550424555079932867">"Etsitään tulostimia"</string>
     <string name="print_no_print_services" msgid="8561247706423327966">"Ei käytössä olevia tulostuspalveluita"</string>
     <string name="print_no_printers" msgid="4869403323900054866">"Tulostimia ei löydy"</string>
+    <string name="cannot_add_printer" msgid="7840348733668023106">"Tulostimien lisääminen ei onnistu."</string>
+    <string name="select_to_add_printers" msgid="3800709038689830974">"Valitse palvelu tulostimen lisäämistä varten."</string>
+    <string name="enable_print_service" msgid="3482815747043533842">"Valitse käyttöön otettavat palvelut."</string>
+    <string name="enabled_services_title" msgid="7036986099096582296">"Käytössä olevat palvelut"</string>
+    <string name="recommended_services_title" msgid="3799434882937956924">"Suositellut palvelut"</string>
+    <string name="disabled_services_title" msgid="7313253167968363211">"Käytöstä poistetut palvelut"</string>
+    <string name="all_services_title" msgid="5578662754874906455">"Kaikki palvelut"</string>
     <string name="printing_notification_title_template" msgid="295903957762447362">"Tulostetaan <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
     <string name="cancelling_notification_title_template" msgid="1821759594704703197">"Peruutetaan työ <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
     <string name="failed_notification_title_template" msgid="2256217208186530973">"Tulostinvirhe työlle <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/PrintSpooler/res/values-fr-rCA/strings.xml b/packages/PrintSpooler/res/values-fr-rCA/strings.xml
index 949ba55..a95d565 100644
--- a/packages/PrintSpooler/res/values-fr-rCA/strings.xml
+++ b/packages/PrintSpooler/res/values-fr-rCA/strings.xml
@@ -61,11 +61,17 @@
     </plurals>
     <string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="printer_info_desc" msgid="7181988788991581654">"Plus d\'information sur cette imprimante"</string>
-    <string name="print_services_disabled_toast" msgid="1205302482388937547">"Certains services d\'impression sont désactivés."</string>
-    <string name="choose_print_service" msgid="3740309762324459694">"Sélectionner le service d\'impression"</string>
+    <string name="print_services_disabled_toast" msgid="9089060734685174685">"Certains services d\'impression sont désactivés"</string>
     <string name="print_searching_for_printers" msgid="6550424555079932867">"Recherche d\'imprimantes en cours..."</string>
     <string name="print_no_print_services" msgid="8561247706423327966">"Aucun service d\'impression activé"</string>
     <string name="print_no_printers" msgid="4869403323900054866">"Aucune imprimante trouvée"</string>
+    <string name="cannot_add_printer" msgid="7840348733668023106">"Impossible d’ajouter des imprimantes"</string>
+    <string name="select_to_add_printers" msgid="3800709038689830974">"Sélectionnez pour ajouter une imprimante"</string>
+    <string name="enable_print_service" msgid="3482815747043533842">"Sélectionner pour activer"</string>
+    <string name="enabled_services_title" msgid="7036986099096582296">"Services activés"</string>
+    <string name="recommended_services_title" msgid="3799434882937956924">"Services recommandés"</string>
+    <string name="disabled_services_title" msgid="7313253167968363211">"Services désactivés"</string>
+    <string name="all_services_title" msgid="5578662754874906455">"Tous les services"</string>
     <string name="printing_notification_title_template" msgid="295903957762447362">"Impression de <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> en cours…"</string>
     <string name="cancelling_notification_title_template" msgid="1821759594704703197">"Annulation de « <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> »…"</string>
     <string name="failed_notification_title_template" msgid="2256217208186530973">"Erreur impression : « <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> »"</string>
diff --git a/packages/PrintSpooler/res/values-fr/strings.xml b/packages/PrintSpooler/res/values-fr/strings.xml
index 1fcc040..dd1f490 100644
--- a/packages/PrintSpooler/res/values-fr/strings.xml
+++ b/packages/PrintSpooler/res/values-fr/strings.xml
@@ -61,11 +61,17 @@
     </plurals>
     <string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> – <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="printer_info_desc" msgid="7181988788991581654">"Plus d\'informations sur cette imprimante"</string>
-    <string name="print_services_disabled_toast" msgid="1205302482388937547">"Certains services d\'impression sont désactivés."</string>
-    <string name="choose_print_service" msgid="3740309762324459694">"Sélectionner le service d\'impression"</string>
+    <string name="print_services_disabled_toast" msgid="9089060734685174685">"Certains services d\'impression sont désactivés."</string>
     <string name="print_searching_for_printers" msgid="6550424555079932867">"Recherche d\'imprimantes en cours"</string>
     <string name="print_no_print_services" msgid="8561247706423327966">"Aucun service d\'impression activé"</string>
     <string name="print_no_printers" msgid="4869403323900054866">"Aucune imprimante trouvée"</string>
+    <string name="cannot_add_printer" msgid="7840348733668023106">"Impossible d\'ajouter des imprimantes"</string>
+    <string name="select_to_add_printers" msgid="3800709038689830974">"Sélectionnez pour ajouter une imprimante."</string>
+    <string name="enable_print_service" msgid="3482815747043533842">"Sélectionnez pour activer."</string>
+    <string name="enabled_services_title" msgid="7036986099096582296">"Services activés"</string>
+    <string name="recommended_services_title" msgid="3799434882937956924">"Services recommandés"</string>
+    <string name="disabled_services_title" msgid="7313253167968363211">"Services désactivés"</string>
+    <string name="all_services_title" msgid="5578662754874906455">"Tous les services"</string>
     <string name="printing_notification_title_template" msgid="295903957762447362">"Impression de \"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>\" en cours…"</string>
     <string name="cancelling_notification_title_template" msgid="1821759594704703197">"Annulation de \"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>\" en cours…"</string>
     <string name="failed_notification_title_template" msgid="2256217208186530973">"Erreur impression pour \"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>\""</string>
diff --git a/packages/PrintSpooler/res/values-gl-rES/strings.xml b/packages/PrintSpooler/res/values-gl-rES/strings.xml
index 2e60960..81e080e 100644
--- a/packages/PrintSpooler/res/values-gl-rES/strings.xml
+++ b/packages/PrintSpooler/res/values-gl-rES/strings.xml
@@ -61,11 +61,17 @@
     </plurals>
     <string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="printer_info_desc" msgid="7181988788991581654">"Máis información sobre esta impresora"</string>
-    <string name="print_services_disabled_toast" msgid="1205302482388937547">"Algúns servizos de impresión están desactivados."</string>
-    <string name="choose_print_service" msgid="3740309762324459694">"Escoller servizo de impresión"</string>
+    <string name="print_services_disabled_toast" msgid="9089060734685174685">"Algúns servizos de impresión están desactivados"</string>
     <string name="print_searching_for_printers" msgid="6550424555079932867">"Busca de impresoras"</string>
     <string name="print_no_print_services" msgid="8561247706423327966">"Non hai servizos de impresión activados"</string>
     <string name="print_no_printers" msgid="4869403323900054866">"Non se atopou ningunha impresora"</string>
+    <string name="cannot_add_printer" msgid="7840348733668023106">"Non se poden engadir impresoras"</string>
+    <string name="select_to_add_printers" msgid="3800709038689830974">"Selecciona un servizo para engadirlle impresora"</string>
+    <string name="enable_print_service" msgid="3482815747043533842">"Selecciona un servizo para activalo"</string>
+    <string name="enabled_services_title" msgid="7036986099096582296">"Servizos activados"</string>
+    <string name="recommended_services_title" msgid="3799434882937956924">"Servizos recomendados"</string>
+    <string name="disabled_services_title" msgid="7313253167968363211">"Servizos desactivados"</string>
+    <string name="all_services_title" msgid="5578662754874906455">"Todos os servizos"</string>
     <string name="printing_notification_title_template" msgid="295903957762447362">"Imprimindo <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
     <string name="cancelling_notification_title_template" msgid="1821759594704703197">"Cancelando <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
     <string name="failed_notification_title_template" msgid="2256217208186530973">"Erro da impresora <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/PrintSpooler/res/values-gu-rIN/strings.xml b/packages/PrintSpooler/res/values-gu-rIN/strings.xml
index 4ba969c..44ede86 100644
--- a/packages/PrintSpooler/res/values-gu-rIN/strings.xml
+++ b/packages/PrintSpooler/res/values-gu-rIN/strings.xml
@@ -61,11 +61,17 @@
     </plurals>
     <string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="printer_info_desc" msgid="7181988788991581654">"આ પ્રિન્ટર વિશે વધુ માહિતી"</string>
-    <string name="print_services_disabled_toast" msgid="1205302482388937547">"કેટલીક છાપ સેવાઓ અક્ષમ કરેલ છે."</string>
-    <string name="choose_print_service" msgid="3740309762324459694">"પ્રિન્ટ સેવા પસંદ કરો"</string>
+    <string name="print_services_disabled_toast" msgid="9089060734685174685">"કેટલીક છાપવાની સેવાઓ અક્ષમ કરેલ છે"</string>
     <string name="print_searching_for_printers" msgid="6550424555079932867">"પ્રિન્ટર્સ માટે શોધી રહ્યું છે"</string>
     <string name="print_no_print_services" msgid="8561247706423327966">"કોઈ છાપ સેવાઓ સક્ષમ કરેલ નથી"</string>
     <string name="print_no_printers" msgid="4869403323900054866">"કોઈ પ્રિન્ટર મળ્યા નથી"</string>
+    <string name="cannot_add_printer" msgid="7840348733668023106">"પ્રિન્ટર્સ ઉમેરી શકતાં નથી"</string>
+    <string name="select_to_add_printers" msgid="3800709038689830974">"પ્રિન્ટર ઉમેરવા માટે પસંદ કરો"</string>
+    <string name="enable_print_service" msgid="3482815747043533842">"સક્ષમ કરવા માટે પસંદ કરો"</string>
+    <string name="enabled_services_title" msgid="7036986099096582296">"સક્ષમ કરેલી સેવાઓ"</string>
+    <string name="recommended_services_title" msgid="3799434882937956924">"ભલામણ કરેલી સેવાઓ"</string>
+    <string name="disabled_services_title" msgid="7313253167968363211">"અક્ષમ કરેલી સેવાઓ"</string>
+    <string name="all_services_title" msgid="5578662754874906455">"બધી સેવાઓ"</string>
     <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>
diff --git a/packages/PrintSpooler/res/values-hi/strings.xml b/packages/PrintSpooler/res/values-hi/strings.xml
index 1061346..f75630e 100644
--- a/packages/PrintSpooler/res/values-hi/strings.xml
+++ b/packages/PrintSpooler/res/values-hi/strings.xml
@@ -61,11 +61,17 @@
     </plurals>
     <string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="printer_info_desc" msgid="7181988788991581654">"इस प्रिंटर के बारे में अधिक जानकारी"</string>
-    <string name="print_services_disabled_toast" msgid="1205302482388937547">"कुछ प्रिंट सेवाएं अक्षम हैं."</string>
-    <string name="choose_print_service" msgid="3740309762324459694">"प्रिंट सेवा चुनें"</string>
+    <string name="print_services_disabled_toast" msgid="9089060734685174685">"कुछ प्रिंट सेवाएं अक्षम हैं"</string>
     <string name="print_searching_for_printers" msgid="6550424555079932867">"प्रिंटर खोज रहा है"</string>
     <string name="print_no_print_services" msgid="8561247706423327966">"कोई भी प्रिंट सेवा सक्षम नहीं है"</string>
     <string name="print_no_printers" msgid="4869403323900054866">"कोई प्रिंटर नहीं मिले"</string>
+    <string name="cannot_add_printer" msgid="7840348733668023106">"प्रिंटर जोड़े नहीं जा सकते"</string>
+    <string name="select_to_add_printers" msgid="3800709038689830974">"प्रिंटर जोड़ने के लिए चुनें"</string>
+    <string name="enable_print_service" msgid="3482815747043533842">"सक्षम करने के लिए चुनें"</string>
+    <string name="enabled_services_title" msgid="7036986099096582296">"सक्षम सेवाएं"</string>
+    <string name="recommended_services_title" msgid="3799434882937956924">"सुझाई गई सेवाएं"</string>
+    <string name="disabled_services_title" msgid="7313253167968363211">"अक्षम सेवाएं"</string>
+    <string name="all_services_title" msgid="5578662754874906455">"सभी सेवाएं"</string>
     <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>
diff --git a/packages/PrintSpooler/res/values-hr/strings.xml b/packages/PrintSpooler/res/values-hr/strings.xml
index 4a7d29f..bd29d02 100644
--- a/packages/PrintSpooler/res/values-hr/strings.xml
+++ b/packages/PrintSpooler/res/values-hr/strings.xml
@@ -62,11 +62,17 @@
     </plurals>
     <string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> – <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="printer_info_desc" msgid="7181988788991581654">"Više informacija o ovom pisaču"</string>
-    <string name="print_services_disabled_toast" msgid="1205302482388937547">"Neke su usluge ispisa onemogućene."</string>
-    <string name="choose_print_service" msgid="3740309762324459694">"Odaberite uslugu ispisa"</string>
+    <string name="print_services_disabled_toast" msgid="9089060734685174685">"Neke su usluge ispisa onemogućene"</string>
     <string name="print_searching_for_printers" msgid="6550424555079932867">"Traženje pisača"</string>
     <string name="print_no_print_services" msgid="8561247706423327966">"Nije omogućena nijedna usluga ispisa"</string>
     <string name="print_no_printers" msgid="4869403323900054866">"Nije pronađen nijedan pisač"</string>
+    <string name="cannot_add_printer" msgid="7840348733668023106">"Ne možete dodati pisače"</string>
+    <string name="select_to_add_printers" msgid="3800709038689830974">"Odaberite da biste dodali pisač"</string>
+    <string name="enable_print_service" msgid="3482815747043533842">"Odaberite za omogućavanje"</string>
+    <string name="enabled_services_title" msgid="7036986099096582296">"Omogućene usluge"</string>
+    <string name="recommended_services_title" msgid="3799434882937956924">"Preporučene usluge"</string>
+    <string name="disabled_services_title" msgid="7313253167968363211">"Onemogućene usluge"</string>
+    <string name="all_services_title" msgid="5578662754874906455">"Sve usluge"</string>
     <string name="printing_notification_title_template" msgid="295903957762447362">"Ispisivanje <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
     <string name="cancelling_notification_title_template" msgid="1821759594704703197">"Otkazivanje zadatka <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
     <string name="failed_notification_title_template" msgid="2256217208186530973">"Pogreška pisača <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/PrintSpooler/res/values-hu/strings.xml b/packages/PrintSpooler/res/values-hu/strings.xml
index 5aae2e4..356cb76 100644
--- a/packages/PrintSpooler/res/values-hu/strings.xml
+++ b/packages/PrintSpooler/res/values-hu/strings.xml
@@ -61,11 +61,17 @@
     </plurals>
     <string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> – <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="printer_info_desc" msgid="7181988788991581654">"További információ erről a nyomtatóról"</string>
-    <string name="print_services_disabled_toast" msgid="1205302482388937547">"Egyes nyomtatási szolgáltatások le vannak tiltva."</string>
-    <string name="choose_print_service" msgid="3740309762324459694">"Nyomtatási szolgáltatás kiválasztása"</string>
+    <string name="print_services_disabled_toast" msgid="9089060734685174685">"Egyes nyomtatási szolgáltatások le vannak tiltva"</string>
     <string name="print_searching_for_printers" msgid="6550424555079932867">"Nyomtatók keresése"</string>
     <string name="print_no_print_services" msgid="8561247706423327966">"Nincs engedélyezett nyomtatási szolgáltatás"</string>
     <string name="print_no_printers" msgid="4869403323900054866">"Nem található nyomtató"</string>
+    <string name="cannot_add_printer" msgid="7840348733668023106">"Nem lehet nyomtatókat hozzáadni"</string>
+    <string name="select_to_add_printers" msgid="3800709038689830974">"Nyomtató hozzáadásához válassza ki"</string>
+    <string name="enable_print_service" msgid="3482815747043533842">"Az engedélyezéshez válassza ki"</string>
+    <string name="enabled_services_title" msgid="7036986099096582296">"Engedélyezett szolgáltatások"</string>
+    <string name="recommended_services_title" msgid="3799434882937956924">"Javasolt szolgáltatások"</string>
+    <string name="disabled_services_title" msgid="7313253167968363211">"Letiltott szolgáltatások"</string>
+    <string name="all_services_title" msgid="5578662754874906455">"Minden szolgáltatás"</string>
     <string name="printing_notification_title_template" msgid="295903957762447362">"A(z) <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> nyomtatása"</string>
     <string name="cancelling_notification_title_template" msgid="1821759594704703197">"A(z) <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> törlése"</string>
     <string name="failed_notification_title_template" msgid="2256217208186530973">"Nyomtatási hiba: <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/PrintSpooler/res/values-hy-rAM/strings.xml b/packages/PrintSpooler/res/values-hy-rAM/strings.xml
index 179c384..2d10166 100644
--- a/packages/PrintSpooler/res/values-hy-rAM/strings.xml
+++ b/packages/PrintSpooler/res/values-hy-rAM/strings.xml
@@ -61,11 +61,17 @@
     </plurals>
     <string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="printer_info_desc" msgid="7181988788991581654">"Հավելյալ տեղեկություններ այս տպիչի մասին"</string>
-    <string name="print_services_disabled_toast" msgid="1205302482388937547">"Տպելու որոշ ծառայությունները կասեցված են:"</string>
-    <string name="choose_print_service" msgid="3740309762324459694">"Ընտրեք տպելու ծառայությունը"</string>
+    <string name="print_services_disabled_toast" msgid="9089060734685174685">"Տպելու որոշ ծառայությունները կասեցված են"</string>
     <string name="print_searching_for_printers" msgid="6550424555079932867">"Տպիչների որոնում"</string>
     <string name="print_no_print_services" msgid="8561247706423327966">"Ակտիվացված տպման ծառայություններ չկան"</string>
     <string name="print_no_printers" msgid="4869403323900054866">"Տպիչներ չեն գտնվել"</string>
+    <string name="cannot_add_printer" msgid="7840348733668023106">"Չեն կարող ավելացնել տպիչներ"</string>
+    <string name="select_to_add_printers" msgid="3800709038689830974">"Ընտրեք՝ տպիչ ավելացնելու համար"</string>
+    <string name="enable_print_service" msgid="3482815747043533842">"Ընտրեք՝ միացնելու համար"</string>
+    <string name="enabled_services_title" msgid="7036986099096582296">"Միացված ծառայությունները"</string>
+    <string name="recommended_services_title" msgid="3799434882937956924">"Խորհուրդ տրվող ծառայությունները"</string>
+    <string name="disabled_services_title" msgid="7313253167968363211">"Կասեցված ծառայությունները"</string>
+    <string name="all_services_title" msgid="5578662754874906455">"Բոլոր ծառայությունները"</string>
     <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>
diff --git a/packages/PrintSpooler/res/values-in/strings.xml b/packages/PrintSpooler/res/values-in/strings.xml
index 7286f7a..8e20d27 100644
--- a/packages/PrintSpooler/res/values-in/strings.xml
+++ b/packages/PrintSpooler/res/values-in/strings.xml
@@ -61,11 +61,17 @@
     </plurals>
     <string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="printer_info_desc" msgid="7181988788991581654">"Informasi selengkapnya tentang printer ini"</string>
-    <string name="print_services_disabled_toast" msgid="1205302482388937547">"Beberapa layanan cetak dinonaktifkan."</string>
-    <string name="choose_print_service" msgid="3740309762324459694">"Pilih layanan cetak"</string>
+    <string name="print_services_disabled_toast" msgid="9089060734685174685">"Beberapa layanan cetak dinonaktifkan"</string>
     <string name="print_searching_for_printers" msgid="6550424555079932867">"Mencari printer"</string>
     <string name="print_no_print_services" msgid="8561247706423327966">"Tidak ada layanan cetak yang aktif"</string>
     <string name="print_no_printers" msgid="4869403323900054866">"Tidak ditemukan printer"</string>
+    <string name="cannot_add_printer" msgid="7840348733668023106">"Tidak dapat menambahkan printer"</string>
+    <string name="select_to_add_printers" msgid="3800709038689830974">"Pilih untuk menambahkan printer"</string>
+    <string name="enable_print_service" msgid="3482815747043533842">"Pilih untuk mengaktifkan"</string>
+    <string name="enabled_services_title" msgid="7036986099096582296">"Layanan diaktifkan"</string>
+    <string name="recommended_services_title" msgid="3799434882937956924">"Layanan yang disarankan"</string>
+    <string name="disabled_services_title" msgid="7313253167968363211">"Layanan dinonaktifkan"</string>
+    <string name="all_services_title" msgid="5578662754874906455">"Semua layanan"</string>
     <string name="printing_notification_title_template" msgid="295903957762447362">"Mencetak <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
     <string name="cancelling_notification_title_template" msgid="1821759594704703197">"Membatalkan <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
     <string name="failed_notification_title_template" msgid="2256217208186530973">"Ada kesalahan printer <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/PrintSpooler/res/values-is-rIS/strings.xml b/packages/PrintSpooler/res/values-is-rIS/strings.xml
index 9ea49a9..73660fb 100644
--- a/packages/PrintSpooler/res/values-is-rIS/strings.xml
+++ b/packages/PrintSpooler/res/values-is-rIS/strings.xml
@@ -61,11 +61,17 @@
     </plurals>
     <string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> – <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="printer_info_desc" msgid="7181988788991581654">"Frekari upplýsingar um þennan prentara"</string>
-    <string name="print_services_disabled_toast" msgid="1205302482388937547">"Hluti prentþjónustunnar er óvirkur."</string>
-    <string name="choose_print_service" msgid="3740309762324459694">"Veldu prentþjónustu"</string>
+    <string name="print_services_disabled_toast" msgid="9089060734685174685">"Hluti prentþjónustunnar er óvirkur"</string>
     <string name="print_searching_for_printers" msgid="6550424555079932867">"Leitar að prentara"</string>
     <string name="print_no_print_services" msgid="8561247706423327966">"Engin prentþjónusta er virk"</string>
     <string name="print_no_printers" msgid="4869403323900054866">"Engir prentarar fundust"</string>
+    <string name="cannot_add_printer" msgid="7840348733668023106">"Ekki er hægt að bæta við prenturum"</string>
+    <string name="select_to_add_printers" msgid="3800709038689830974">"Veldu til að bæta prentara við"</string>
+    <string name="enable_print_service" msgid="3482815747043533842">"Veldu til að virkja"</string>
+    <string name="enabled_services_title" msgid="7036986099096582296">"Virkjaðar þjónustur"</string>
+    <string name="recommended_services_title" msgid="3799434882937956924">"Þjónusta sem mælt er með"</string>
+    <string name="disabled_services_title" msgid="7313253167968363211">"Þjónusta við fatlaða"</string>
+    <string name="all_services_title" msgid="5578662754874906455">"Öll þjónusta"</string>
     <string name="printing_notification_title_template" msgid="295903957762447362">"Prentar <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
     <string name="cancelling_notification_title_template" msgid="1821759594704703197">"Hættir við <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
     <string name="failed_notification_title_template" msgid="2256217208186530973">"Prentaravilla <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/PrintSpooler/res/values-it/strings.xml b/packages/PrintSpooler/res/values-it/strings.xml
index c19d012..46a570d 100644
--- a/packages/PrintSpooler/res/values-it/strings.xml
+++ b/packages/PrintSpooler/res/values-it/strings.xml
@@ -61,11 +61,17 @@
     </plurals>
     <string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="printer_info_desc" msgid="7181988788991581654">"Ulteriori informazioni su questa stampante"</string>
-    <string name="print_services_disabled_toast" msgid="1205302482388937547">"Alcuni servizi di stampa sono disattivati."</string>
-    <string name="choose_print_service" msgid="3740309762324459694">"Scegli servizio di stampa"</string>
+    <string name="print_services_disabled_toast" msgid="9089060734685174685">"Alcuni servizi di stampa sono disattivati"</string>
     <string name="print_searching_for_printers" msgid="6550424555079932867">"Ricerca di stampanti"</string>
     <string name="print_no_print_services" msgid="8561247706423327966">"Non è stato attivato alcun servizio di stampa"</string>
     <string name="print_no_printers" msgid="4869403323900054866">"Nessuna stampante trovata"</string>
+    <string name="cannot_add_printer" msgid="7840348733668023106">"Impossibile aggiungere stampanti"</string>
+    <string name="select_to_add_printers" msgid="3800709038689830974">"Seleziona per aggiungere stampanti"</string>
+    <string name="enable_print_service" msgid="3482815747043533842">"Seleziona per attivare"</string>
+    <string name="enabled_services_title" msgid="7036986099096582296">"Servizi abilitati"</string>
+    <string name="recommended_services_title" msgid="3799434882937956924">"Servizi consigliati"</string>
+    <string name="disabled_services_title" msgid="7313253167968363211">"Servizi disattivati"</string>
+    <string name="all_services_title" msgid="5578662754874906455">"Tutti i servizi"</string>
     <string name="printing_notification_title_template" msgid="295903957762447362">"Stampa di <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
     <string name="cancelling_notification_title_template" msgid="1821759594704703197">"Annullamento di <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
     <string name="failed_notification_title_template" msgid="2256217208186530973">"Errore della stampante: <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/PrintSpooler/res/values-iw/strings.xml b/packages/PrintSpooler/res/values-iw/strings.xml
index 00bf27c..c26c3d1 100644
--- a/packages/PrintSpooler/res/values-iw/strings.xml
+++ b/packages/PrintSpooler/res/values-iw/strings.xml
@@ -63,11 +63,17 @@
     </plurals>
     <string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="printer_info_desc" msgid="7181988788991581654">"מידע נוסף על מדפסת זו"</string>
-    <string name="print_services_disabled_toast" msgid="1205302482388937547">"שירותי הדפסה מסוימים מושבתים."</string>
-    <string name="choose_print_service" msgid="3740309762324459694">"בחר שירות הדפסה"</string>
+    <string name="print_services_disabled_toast" msgid="9089060734685174685">"שירותי הדפסה מסוימים מושבתים"</string>
     <string name="print_searching_for_printers" msgid="6550424555079932867">"מחפש מדפסות"</string>
     <string name="print_no_print_services" msgid="8561247706423327966">"לא הופעלו שירותי הדפסה"</string>
     <string name="print_no_printers" msgid="4869403323900054866">"לא נמצאו מדפסות"</string>
+    <string name="cannot_add_printer" msgid="7840348733668023106">"לא ניתן להוסיף מדפסות"</string>
+    <string name="select_to_add_printers" msgid="3800709038689830974">"בחר כדי להוסיף מדפסת"</string>
+    <string name="enable_print_service" msgid="3482815747043533842">"בחר כדי להפעיל"</string>
+    <string name="enabled_services_title" msgid="7036986099096582296">"שירותים מופעלים"</string>
+    <string name="recommended_services_title" msgid="3799434882937956924">"שירותים מומלצים"</string>
+    <string name="disabled_services_title" msgid="7313253167968363211">"שירותים מושבתים"</string>
+    <string name="all_services_title" msgid="5578662754874906455">"כל השירותים"</string>
     <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>
diff --git a/packages/PrintSpooler/res/values-ja/strings.xml b/packages/PrintSpooler/res/values-ja/strings.xml
index e0fc79a..a6e243f 100644
--- a/packages/PrintSpooler/res/values-ja/strings.xml
+++ b/packages/PrintSpooler/res/values-ja/strings.xml
@@ -61,11 +61,17 @@
     </plurals>
     <string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="printer_info_desc" msgid="7181988788991581654">"このプリンタの詳細"</string>
-    <string name="print_services_disabled_toast" msgid="1205302482388937547">"一部の印刷サービスは無効になっています。"</string>
-    <string name="choose_print_service" msgid="3740309762324459694">"印刷サービスの選択"</string>
+    <string name="print_services_disabled_toast" msgid="9089060734685174685">"一部の印刷サービスは無効になっています"</string>
     <string name="print_searching_for_printers" msgid="6550424555079932867">"プリンタの検索中"</string>
     <string name="print_no_print_services" msgid="8561247706423327966">"使用できる印刷サービスがありません"</string>
     <string name="print_no_printers" msgid="4869403323900054866">"プリンタが見つかりません"</string>
+    <string name="cannot_add_printer" msgid="7840348733668023106">"プリンタは追加できません"</string>
+    <string name="select_to_add_printers" msgid="3800709038689830974">"選択してプリンタを追加"</string>
+    <string name="enable_print_service" msgid="3482815747043533842">"選択して有効にする"</string>
+    <string name="enabled_services_title" msgid="7036986099096582296">"有効になっているサービス"</string>
+    <string name="recommended_services_title" msgid="3799434882937956924">"推奨されているサービス"</string>
+    <string name="disabled_services_title" msgid="7313253167968363211">"無効になっているサービス"</string>
+    <string name="all_services_title" msgid="5578662754874906455">"すべてのサービス"</string>
     <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>
diff --git a/packages/PrintSpooler/res/values-ka-rGE/strings.xml b/packages/PrintSpooler/res/values-ka-rGE/strings.xml
index ad1468a..2608ed4 100644
--- a/packages/PrintSpooler/res/values-ka-rGE/strings.xml
+++ b/packages/PrintSpooler/res/values-ka-rGE/strings.xml
@@ -61,11 +61,17 @@
     </plurals>
     <string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> — <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="printer_info_desc" msgid="7181988788991581654">"დამატებითი ინფორმაცია ამ პრინტერის შესახებ"</string>
-    <string name="print_services_disabled_toast" msgid="1205302482388937547">"ბეჭდვის ზოგიერთი სერვისი გათიშულია."</string>
-    <string name="choose_print_service" msgid="3740309762324459694">"აირჩიეთ ბეჭდვის სერვისი"</string>
+    <string name="print_services_disabled_toast" msgid="9089060734685174685">"ბეჭდვის ზოგიერთი სერვისი გათიშულია"</string>
     <string name="print_searching_for_printers" msgid="6550424555079932867">"მიმდინარეობს პრინტერების ძიება"</string>
     <string name="print_no_print_services" msgid="8561247706423327966">"ბეჭდვის სერვისები გააქტიურებული არ არის"</string>
     <string name="print_no_printers" msgid="4869403323900054866">"პრინტერები ვერ მოიძებნა"</string>
+    <string name="cannot_add_printer" msgid="7840348733668023106">"პრინტერების დამატება ვერ მოხერხდება"</string>
+    <string name="select_to_add_printers" msgid="3800709038689830974">"აირჩიეთ პრინტერის დასამატებლად"</string>
+    <string name="enable_print_service" msgid="3482815747043533842">"აირჩიეთ ჩასართავად"</string>
+    <string name="enabled_services_title" msgid="7036986099096582296">"ჩართული სერვისები"</string>
+    <string name="recommended_services_title" msgid="3799434882937956924">"რეკომენდებული სერვისები"</string>
+    <string name="disabled_services_title" msgid="7313253167968363211">"გათიშული სერვისები"</string>
+    <string name="all_services_title" msgid="5578662754874906455">"ყველა სერვისი"</string>
     <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>
diff --git a/packages/PrintSpooler/res/values-kk-rKZ/strings.xml b/packages/PrintSpooler/res/values-kk-rKZ/strings.xml
index d0337a6..def0c3c 100644
--- a/packages/PrintSpooler/res/values-kk-rKZ/strings.xml
+++ b/packages/PrintSpooler/res/values-kk-rKZ/strings.xml
@@ -61,11 +61,17 @@
     </plurals>
     <string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="printer_info_desc" msgid="7181988788991581654">"Осы принтер туралы қосымша ақпарат"</string>
-    <string name="print_services_disabled_toast" msgid="1205302482388937547">"Кейбір басып шығару қызметтері өшірілген."</string>
-    <string name="choose_print_service" msgid="3740309762324459694">"Принтер қызметін таңдау"</string>
+    <string name="print_services_disabled_toast" msgid="9089060734685174685">"Кейбір басып шығару қызметтері өшірілген."</string>
     <string name="print_searching_for_printers" msgid="6550424555079932867">"Принтерлерді іздеу"</string>
     <string name="print_no_print_services" msgid="8561247706423327966">"Басып шығару қызметтері қосылмаған"</string>
     <string name="print_no_printers" msgid="4869403323900054866">"Ешқандай принтер табылмады"</string>
+    <string name="cannot_add_printer" msgid="7840348733668023106">"Принтерлерді қосу мүмкін емес"</string>
+    <string name="select_to_add_printers" msgid="3800709038689830974">"Принтерді қосу үшін таңдаңыз"</string>
+    <string name="enable_print_service" msgid="3482815747043533842">"Қосу үшін таңдаңыз"</string>
+    <string name="enabled_services_title" msgid="7036986099096582296">"Қосылған қызметтер"</string>
+    <string name="recommended_services_title" msgid="3799434882937956924">"Ұсынылған қызметтер"</string>
+    <string name="disabled_services_title" msgid="7313253167968363211">"Өшірілген қызметтер"</string>
+    <string name="all_services_title" msgid="5578662754874906455">"Барлық қызметтер"</string>
     <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>
diff --git a/packages/PrintSpooler/res/values-km-rKH/strings.xml b/packages/PrintSpooler/res/values-km-rKH/strings.xml
index c9431e9..24048cf 100644
--- a/packages/PrintSpooler/res/values-km-rKH/strings.xml
+++ b/packages/PrintSpooler/res/values-km-rKH/strings.xml
@@ -61,11 +61,17 @@
     </plurals>
     <string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="printer_info_desc" msgid="7181988788991581654">"ព័ត៌មានបន្ថែមអំពីម៉ាស៊ីបោះពុម្ពនេះ"</string>
-    <string name="print_services_disabled_toast" msgid="1205302482388937547">"សេវាកម្មបោះពុម្ពមួយចំនួនត្រូវបានបិទដំណើរការ"</string>
-    <string name="choose_print_service" msgid="3740309762324459694">"ជ្រើស​សេវា​បោះពុម្ព"</string>
+    <string name="print_services_disabled_toast" msgid="9089060734685174685">"សេវាកម្មបោះពុម្ពមួយចំនួនត្រូវបានបិទដំណើរការ"</string>
     <string name="print_searching_for_printers" msgid="6550424555079932867">"ស្វែងរក​ម៉ាស៊ីន​បោះពុម្ព"</string>
     <string name="print_no_print_services" msgid="8561247706423327966">"គ្មានការបើកដំណើរការសេវាបោះពុម្ពទេ"</string>
     <string name="print_no_printers" msgid="4869403323900054866">"រក​មិន​ឃើញ​ម៉ាស៊ីន​បោះពុម្ព"</string>
+    <string name="cannot_add_printer" msgid="7840348733668023106">"មិនអាចបន្ថែមម៉ាស៊ីនបោះពុម្ពបានទេ"</string>
+    <string name="select_to_add_printers" msgid="3800709038689830974">"ជ្រើសដើម្បីបន្ថែមម៉ាស៊ីនបោះពុម្ព"</string>
+    <string name="enable_print_service" msgid="3482815747043533842">"ជ្រើសដើម្បីបើកដំណើរការ"</string>
+    <string name="enabled_services_title" msgid="7036986099096582296">"សេវាកម្មដែលបើកដំណើរការ"</string>
+    <string name="recommended_services_title" msgid="3799434882937956924">"សេវាកម្មដែលបានណែនាំ"</string>
+    <string name="disabled_services_title" msgid="7313253167968363211">"សេវាកម្មដែលបិទដំណើរការ"</string>
+    <string name="all_services_title" msgid="5578662754874906455">"សេវាកម្មទាំងអស់"</string>
     <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>
diff --git a/packages/PrintSpooler/res/values-kn-rIN/strings.xml b/packages/PrintSpooler/res/values-kn-rIN/strings.xml
index fc5149a..af20965 100644
--- a/packages/PrintSpooler/res/values-kn-rIN/strings.xml
+++ b/packages/PrintSpooler/res/values-kn-rIN/strings.xml
@@ -61,11 +61,17 @@
     </plurals>
     <string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="printer_info_desc" msgid="7181988788991581654">"ಈ ಪ್ರಿಂಟರ್ ಬಗ್ಗೆ ಇನ್ನಷ್ಟು ಮಾಹಿತಿ"</string>
-    <string name="print_services_disabled_toast" msgid="1205302482388937547">"ಕೆಲವು ಮುದ್ರಣ ಸೇವೆಗಳನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಲಾಗಿದೆ."</string>
-    <string name="choose_print_service" msgid="3740309762324459694">"ಮುದ್ರಣ ಸೇವೆಯನ್ನು ಆಯ್ಕೆಮಾಡಿ"</string>
+    <string name="print_services_disabled_toast" msgid="9089060734685174685">"ಕೆಲವು ಮುದ್ರಣ ಸೇವೆಗಳನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಲಾಗಿದೆ"</string>
     <string name="print_searching_for_printers" msgid="6550424555079932867">"ಪ್ರಿಂಟರ್‌‌ಗಳಿಗಾಗಿ ಹುಡುಕಲಾಗುತ್ತಿದೆ"</string>
     <string name="print_no_print_services" msgid="8561247706423327966">"ಯಾವುದೇ ಮುದ್ರಣ ಸೇವೆಗಳನ್ನು ಸಕ್ರಿಯಗೊಳಿಸಿಲ್ಲ"</string>
     <string name="print_no_printers" msgid="4869403323900054866">"ಯಾವುದೇ ಮುದ್ರಕಗಳು ಕಂಡುಬಂದಿಲ್ಲ"</string>
+    <string name="cannot_add_printer" msgid="7840348733668023106">"ಪ್ರಿಂಟರ್‌ಗಳನ್ನು ಸೇರಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ"</string>
+    <string name="select_to_add_printers" msgid="3800709038689830974">"ಪ್ರಿಂಟರ್ ಸೇರಿಸಲು ಆಯ್ಕೆಮಾಡಿ"</string>
+    <string name="enable_print_service" msgid="3482815747043533842">"ಸಕ್ರಿಯಗೊಳಿಸಲು ಆಯ್ಕೆಮಾಡಿ"</string>
+    <string name="enabled_services_title" msgid="7036986099096582296">"ಸಕ್ರಿಯಗೊಳಿಸಲಾದ ಸೇವೆಗಳು"</string>
+    <string name="recommended_services_title" msgid="3799434882937956924">"ಶಿಫಾರಸು ಮಾಡಲಾದ ಸೇವೆಗಳು"</string>
+    <string name="disabled_services_title" msgid="7313253167968363211">"ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಲಾದ ಸೇವೆಗಳು"</string>
+    <string name="all_services_title" msgid="5578662754874906455">"ಎಲ್ಲ ಸೇವೆಗಳು"</string>
     <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>
diff --git a/packages/PrintSpooler/res/values-ko/strings.xml b/packages/PrintSpooler/res/values-ko/strings.xml
index 2faff1f..0b297a2 100644
--- a/packages/PrintSpooler/res/values-ko/strings.xml
+++ b/packages/PrintSpooler/res/values-ko/strings.xml
@@ -61,11 +61,17 @@
     </plurals>
     <string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="printer_info_desc" msgid="7181988788991581654">"이 프린터에 대한 정보 더보기"</string>
-    <string name="print_services_disabled_toast" msgid="1205302482388937547">"프린트 서비스 일부가 사용 중지되었습니다."</string>
-    <string name="choose_print_service" msgid="3740309762324459694">"인쇄 서비스 선택"</string>
+    <string name="print_services_disabled_toast" msgid="9089060734685174685">"프린트 서비스 일부가 사용 중지되었습니다."</string>
     <string name="print_searching_for_printers" msgid="6550424555079932867">"프린터 검색 중"</string>
     <string name="print_no_print_services" msgid="8561247706423327966">"사용 가능한 프린트 서비스 없음"</string>
     <string name="print_no_printers" msgid="4869403323900054866">"프린터 없음"</string>
+    <string name="cannot_add_printer" msgid="7840348733668023106">"프린터를 추가할 수 없음"</string>
+    <string name="select_to_add_printers" msgid="3800709038689830974">"프린터를 추가하려면 선택하세요."</string>
+    <string name="enable_print_service" msgid="3482815747043533842">"사용 설정하려면 선택하세요."</string>
+    <string name="enabled_services_title" msgid="7036986099096582296">"사용 설정된 서비스"</string>
+    <string name="recommended_services_title" msgid="3799434882937956924">"권장 서비스"</string>
+    <string name="disabled_services_title" msgid="7313253167968363211">"사용 중지된 서비스"</string>
+    <string name="all_services_title" msgid="5578662754874906455">"모든 서비스"</string>
     <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>
diff --git a/packages/PrintSpooler/res/values-ky-rKG/strings.xml b/packages/PrintSpooler/res/values-ky-rKG/strings.xml
index a01e4a8..85b2526 100644
--- a/packages/PrintSpooler/res/values-ky-rKG/strings.xml
+++ b/packages/PrintSpooler/res/values-ky-rKG/strings.xml
@@ -61,11 +61,17 @@
     </plurals>
     <string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="printer_info_desc" msgid="7181988788991581654">"Бул принтер жөнүндө көбүрөөк маалымат"</string>
-    <string name="print_services_disabled_toast" msgid="1205302482388937547">"Басып чыгаруу кызматтарынын айрымы өчүрүлгөн."</string>
-    <string name="choose_print_service" msgid="3740309762324459694">"Принтер кызматын тандоо"</string>
+    <string name="print_services_disabled_toast" msgid="9089060734685174685">"Басып чыгаруу кызматтарынын айрымы өчүрүлгөн"</string>
     <string name="print_searching_for_printers" msgid="6550424555079932867">"Принтерлер изделүүдө"</string>
     <string name="print_no_print_services" msgid="8561247706423327966">"Принтер-кызматтары иштетилген эмес"</string>
     <string name="print_no_printers" msgid="4869403323900054866">"Принтерлер табылган жок"</string>
+    <string name="cannot_add_printer" msgid="7840348733668023106">"Принтерлер кошулбай жатат"</string>
+    <string name="select_to_add_printers" msgid="3800709038689830974">"Принтер кошуу үчүн тандаңыз"</string>
+    <string name="enable_print_service" msgid="3482815747043533842">"Иштетүү үчүн тандаңыз"</string>
+    <string name="enabled_services_title" msgid="7036986099096582296">"Иштетилген кызматтар"</string>
+    <string name="recommended_services_title" msgid="3799434882937956924">"Сунушталган кызматтар"</string>
+    <string name="disabled_services_title" msgid="7313253167968363211">"Өчүрүлгөн кызматтар"</string>
+    <string name="all_services_title" msgid="5578662754874906455">"Бардык кызматтар"</string>
     <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>
diff --git a/packages/PrintSpooler/res/values-lo-rLA/strings.xml b/packages/PrintSpooler/res/values-lo-rLA/strings.xml
index b5d13b5..81ace83 100644
--- a/packages/PrintSpooler/res/values-lo-rLA/strings.xml
+++ b/packages/PrintSpooler/res/values-lo-rLA/strings.xml
@@ -61,11 +61,17 @@
     </plurals>
     <string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="printer_info_desc" msgid="7181988788991581654">"ຂໍ້ມູນເພີ່ມເຕີມກ່ຽວກັບເຄື່ອງພິມນີ້"</string>
-    <string name="print_services_disabled_toast" msgid="1205302482388937547">"ບາງການບໍລິການພິມຖືກປິດນຳໃຊ້."</string>
-    <string name="choose_print_service" msgid="3740309762324459694">"ເລືອກບໍລິການການພິມ"</string>
+    <string name="print_services_disabled_toast" msgid="9089060734685174685">"ບາງການບໍລິການພິມຖືກປິດການນຳໃຊ້"</string>
     <string name="print_searching_for_printers" msgid="6550424555079932867">"ກຳລັງຊອກຫາເຄື່ອງພິມ"</string>
     <string name="print_no_print_services" msgid="8561247706423327966">"ບໍ່​ມີ​ການ​ບໍ​ລິ​ການ​ພິມ​ເປີດ​ໃຊ້​ງານ​ໄວ້"</string>
     <string name="print_no_printers" msgid="4869403323900054866">"ບໍ່ພົບເຄື່ອງພິມ"</string>
+    <string name="cannot_add_printer" msgid="7840348733668023106">"ບໍ່ສາມາດເພີ່ມເຄື່ອງພິມໄດ້"</string>
+    <string name="select_to_add_printers" msgid="3800709038689830974">"ເລືອກເພື່ອເພີ່ມເຄື່ອງພິມ"</string>
+    <string name="enable_print_service" msgid="3482815747043533842">"ເລືອກເພື່ອເປີດໃຊ້"</string>
+    <string name="enabled_services_title" msgid="7036986099096582296">"ບໍລິການທີ່ເປີດໃຊ້"</string>
+    <string name="recommended_services_title" msgid="3799434882937956924">"ບໍລິການທີ່ແນະນຳ"</string>
+    <string name="disabled_services_title" msgid="7313253167968363211">"ບໍລິການທີ່ຖືກປິດການນຳໃຊ້"</string>
+    <string name="all_services_title" msgid="5578662754874906455">"ບໍລິການທັງໝົດ"</string>
     <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>
diff --git a/packages/PrintSpooler/res/values-lt/strings.xml b/packages/PrintSpooler/res/values-lt/strings.xml
index 3b8f143..40bc7f1 100644
--- a/packages/PrintSpooler/res/values-lt/strings.xml
+++ b/packages/PrintSpooler/res/values-lt/strings.xml
@@ -63,11 +63,17 @@
     </plurals>
     <string name="printer_extended_description_template" msgid="1366699227703381874">"„<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g>“ – <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="printer_info_desc" msgid="7181988788991581654">"Daugiau informacijos apie šį spausdintuvą"</string>
-    <string name="print_services_disabled_toast" msgid="1205302482388937547">"Kai kurios spausdinimo paslaugos išjungtos."</string>
-    <string name="choose_print_service" msgid="3740309762324459694">"Pasirinkite spausdinimo paslaugą"</string>
+    <string name="print_services_disabled_toast" msgid="9089060734685174685">"Kai kurios spausdinimo paslaugos išjungtos"</string>
     <string name="print_searching_for_printers" msgid="6550424555079932867">"Ieškoma spausdintuvų"</string>
     <string name="print_no_print_services" msgid="8561247706423327966">"Neįgalinta jokių spausdinimo paslaugų"</string>
     <string name="print_no_printers" msgid="4869403323900054866">"Nerasta spausdintuvų"</string>
+    <string name="cannot_add_printer" msgid="7840348733668023106">"Nepavyko pridėti spausdintuvų"</string>
+    <string name="select_to_add_printers" msgid="3800709038689830974">"Pasirinkite, kad pridėtumėte spausdintuvą"</string>
+    <string name="enable_print_service" msgid="3482815747043533842">"Pasirinkite, kad įgalintumėte"</string>
+    <string name="enabled_services_title" msgid="7036986099096582296">"Įgalintos paslaugos"</string>
+    <string name="recommended_services_title" msgid="3799434882937956924">"Rekomenduojamos paslaugos"</string>
+    <string name="disabled_services_title" msgid="7313253167968363211">"Išjungtos paslaugos"</string>
+    <string name="all_services_title" msgid="5578662754874906455">"Visos paslaugos"</string>
     <string name="printing_notification_title_template" msgid="295903957762447362">"Spausdinama: <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
     <string name="cancelling_notification_title_template" msgid="1821759594704703197">"Atšaukiama: <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
     <string name="failed_notification_title_template" msgid="2256217208186530973">"Spausdintuvo klaida: <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/PrintSpooler/res/values-lv/strings.xml b/packages/PrintSpooler/res/values-lv/strings.xml
index 762d0bd..11e689b 100644
--- a/packages/PrintSpooler/res/values-lv/strings.xml
+++ b/packages/PrintSpooler/res/values-lv/strings.xml
@@ -62,11 +62,17 @@
     </plurals>
     <string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> — <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="printer_info_desc" msgid="7181988788991581654">"Plašāka informācija par šo printeri"</string>
-    <string name="print_services_disabled_toast" msgid="1205302482388937547">"Daži drukas pakalpojumi ir atspējoti."</string>
-    <string name="choose_print_service" msgid="3740309762324459694">"Izvēlieties drukāšanas pakalpojumu"</string>
+    <string name="print_services_disabled_toast" msgid="9089060734685174685">"Daži drukas pakalpojumi ir atspējoti."</string>
     <string name="print_searching_for_printers" msgid="6550424555079932867">"Printeru meklēšana"</string>
     <string name="print_no_print_services" msgid="8561247706423327966">"Nav iespējots neviens drukas pakalpojums"</string>
     <string name="print_no_printers" msgid="4869403323900054866">"Netika atrasts neviens printeris."</string>
+    <string name="cannot_add_printer" msgid="7840348733668023106">"Nevar pievienot printerus"</string>
+    <string name="select_to_add_printers" msgid="3800709038689830974">"Atlasiet, lai pievienotu printeri"</string>
+    <string name="enable_print_service" msgid="3482815747043533842">"Izvēlieties, lai iespējotu"</string>
+    <string name="enabled_services_title" msgid="7036986099096582296">"Iespējotie pakalpojumi"</string>
+    <string name="recommended_services_title" msgid="3799434882937956924">"Ieteiktie pakalpojumi"</string>
+    <string name="disabled_services_title" msgid="7313253167968363211">"Atspējotie pakalpojumi"</string>
+    <string name="all_services_title" msgid="5578662754874906455">"Visi pakalpojumi"</string>
     <string name="printing_notification_title_template" msgid="295903957762447362">"Notiek darba <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> drukāšana…"</string>
     <string name="cancelling_notification_title_template" msgid="1821759594704703197">"Pārtrauc drukas darbu <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>…"</string>
     <string name="failed_notification_title_template" msgid="2256217208186530973">"Printera kļūda ar darbu <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/PrintSpooler/res/values-mk-rMK/strings.xml b/packages/PrintSpooler/res/values-mk-rMK/strings.xml
index de6d3e9..bc2b498 100644
--- a/packages/PrintSpooler/res/values-mk-rMK/strings.xml
+++ b/packages/PrintSpooler/res/values-mk-rMK/strings.xml
@@ -61,11 +61,17 @@
     </plurals>
     <string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="printer_info_desc" msgid="7181988788991581654">"Повеќе информации за овој печатач"</string>
-    <string name="print_services_disabled_toast" msgid="1205302482388937547">"Некои услуги за печатење се оневозможени."</string>
-    <string name="choose_print_service" msgid="3740309762324459694">"Избери услуга печатење"</string>
+    <string name="print_services_disabled_toast" msgid="9089060734685174685">"Некои услуги за печатење се оневозможени"</string>
     <string name="print_searching_for_printers" msgid="6550424555079932867">"Пребарување печатачи"</string>
     <string name="print_no_print_services" msgid="8561247706423327966">"Нема овозможени услуги за печатење"</string>
     <string name="print_no_printers" msgid="4869403323900054866">"Не се пронајдени печатачи"</string>
+    <string name="cannot_add_printer" msgid="7840348733668023106">"Не може да се додадат печатачи"</string>
+    <string name="select_to_add_printers" msgid="3800709038689830974">"Изберете додавање печатач"</string>
+    <string name="enable_print_service" msgid="3482815747043533842">"Изберете да се овозможи"</string>
+    <string name="enabled_services_title" msgid="7036986099096582296">"Овозможени услуги"</string>
+    <string name="recommended_services_title" msgid="3799434882937956924">"Препорачани услуги"</string>
+    <string name="disabled_services_title" msgid="7313253167968363211">"Оневозможени услуги"</string>
+    <string name="all_services_title" msgid="5578662754874906455">"Сите услуги"</string>
     <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>
diff --git a/packages/PrintSpooler/res/values-ml-rIN/strings.xml b/packages/PrintSpooler/res/values-ml-rIN/strings.xml
index 7a33e14..ade7fb39 100644
--- a/packages/PrintSpooler/res/values-ml-rIN/strings.xml
+++ b/packages/PrintSpooler/res/values-ml-rIN/strings.xml
@@ -61,11 +61,17 @@
     </plurals>
     <string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="printer_info_desc" msgid="7181988788991581654">"ഈ പ്രിന്ററിനെ കുറിച്ചുള്ള കൂടുതൽ വിവരങ്ങൾ"</string>
-    <string name="print_services_disabled_toast" msgid="1205302482388937547">"ചില പ്രിന്റ് സേവനങ്ങൾ പ്രവർത്തനരഹിതമാക്കിയിരിക്കുന്നു."</string>
-    <string name="choose_print_service" msgid="3740309762324459694">"പ്രിന്റ് സേവനം തിരഞ്ഞെടുക്കുക"</string>
+    <string name="print_services_disabled_toast" msgid="9089060734685174685">"ചില പ്രിന്റ് സേവനങ്ങൾ പ്രവർത്തനരഹിതമാക്കി"</string>
     <string name="print_searching_for_printers" msgid="6550424555079932867">"പ്രിന്ററുകൾക്കായി തിരയുന്നു"</string>
     <string name="print_no_print_services" msgid="8561247706423327966">"പ്രിന്റ് സേവനങ്ങളൊന്നും പ്രവർത്തനക്ഷമാക്കിയിട്ടില്ല"</string>
     <string name="print_no_printers" msgid="4869403323900054866">"പ്രിന്ററുകളൊന്നും കണ്ടെത്തിയില്ല"</string>
+    <string name="cannot_add_printer" msgid="7840348733668023106">"പ്രിന്ററുകൾ ചേർക്കാൻ കഴിയില്ല"</string>
+    <string name="select_to_add_printers" msgid="3800709038689830974">"പ്രിന്റർ ചേർക്കാൻ തിരഞ്ഞെടുക്കുക"</string>
+    <string name="enable_print_service" msgid="3482815747043533842">"പ്രവർത്തനക്ഷമമാക്കാൻ തിരഞ്ഞെടുക്കുക"</string>
+    <string name="enabled_services_title" msgid="7036986099096582296">"പ്രവർത്തനക്ഷമമാക്കിയ സേവനങ്ങൾ"</string>
+    <string name="recommended_services_title" msgid="3799434882937956924">"ശുപാർശ ചെയ്യപ്പെടുന്ന സേവനങ്ങൾ"</string>
+    <string name="disabled_services_title" msgid="7313253167968363211">"പ്രവർത്തനരഹിതമാക്കിയ സേവനങ്ങൾ"</string>
+    <string name="all_services_title" msgid="5578662754874906455">"എല്ലാ സേവനങ്ങളും"</string>
     <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>
diff --git a/packages/PrintSpooler/res/values-mn-rMN/strings.xml b/packages/PrintSpooler/res/values-mn-rMN/strings.xml
index c94e56d..133d88c 100644
--- a/packages/PrintSpooler/res/values-mn-rMN/strings.xml
+++ b/packages/PrintSpooler/res/values-mn-rMN/strings.xml
@@ -61,11 +61,17 @@
     </plurals>
     <string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="printer_info_desc" msgid="7181988788991581654">"Энэ хэвлэгчийн талаарх дэлгэрэнгүй мэдээлэл"</string>
-    <string name="print_services_disabled_toast" msgid="1205302482388937547">"Зарим хэвлэх үйлчилгээг идэвхгүй болгосон байна."</string>
-    <string name="choose_print_service" msgid="3740309762324459694">"Хэвлэх үйлчилгээг сонгох"</string>
+    <string name="print_services_disabled_toast" msgid="9089060734685174685">"Зарим хэвлэх үйлчилгээг идэвхгүй болгосон байна"</string>
     <string name="print_searching_for_printers" msgid="6550424555079932867">"Принтер хайж байна"</string>
     <string name="print_no_print_services" msgid="8561247706423327966">"Хэвлэх үйлчилгээг идэвхжүүлээгүй"</string>
     <string name="print_no_printers" msgid="4869403323900054866">"Принтер олдсонгүй"</string>
+    <string name="cannot_add_printer" msgid="7840348733668023106">"Хэвлэгч нэмэх боломжгүй байна"</string>
+    <string name="select_to_add_printers" msgid="3800709038689830974">"Хэвлэгч нэмэхийн тулд сонгох"</string>
+    <string name="enable_print_service" msgid="3482815747043533842">"Идэвхжүүлэхийн тулд сонгох"</string>
+    <string name="enabled_services_title" msgid="7036986099096582296">"Идэвхжүүлсэн үйлчилгээ"</string>
+    <string name="recommended_services_title" msgid="3799434882937956924">"Санал болгосон үйлчилгээ"</string>
+    <string name="disabled_services_title" msgid="7313253167968363211">"Идэвхгүй болгосон үйлчилгээ"</string>
+    <string name="all_services_title" msgid="5578662754874906455">"Бүх үйлчилгээ"</string>
     <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>
diff --git a/packages/PrintSpooler/res/values-mr-rIN/strings.xml b/packages/PrintSpooler/res/values-mr-rIN/strings.xml
index ab25010..2b3b29f 100644
--- a/packages/PrintSpooler/res/values-mr-rIN/strings.xml
+++ b/packages/PrintSpooler/res/values-mr-rIN/strings.xml
@@ -61,11 +61,17 @@
     </plurals>
     <string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="printer_info_desc" msgid="7181988788991581654">"या प्रिंटर विषयी अधिक माहिती"</string>
-    <string name="print_services_disabled_toast" msgid="1205302482388937547">"काही मुद्रण सेवा अक्षम केल्या आहेत."</string>
-    <string name="choose_print_service" msgid="3740309762324459694">"मुद्रण सेवा निवडा"</string>
+    <string name="print_services_disabled_toast" msgid="9089060734685174685">"काही मुद्रण सेवा अक्षम केल्या आहेत"</string>
     <string name="print_searching_for_printers" msgid="6550424555079932867">"प्रिंटर शोधत आहे"</string>
     <string name="print_no_print_services" msgid="8561247706423327966">"कोणत्याही मुद्रण सेवा सक्षम केलेल्या नाहीत"</string>
     <string name="print_no_printers" msgid="4869403323900054866">"कोणतेही प्रिंटर आढळले नाही"</string>
+    <string name="cannot_add_printer" msgid="7840348733668023106">"प्रिंटर जोडू शकत नाही"</string>
+    <string name="select_to_add_printers" msgid="3800709038689830974">"प्रिंटर जोडण्यासाठी निवडा"</string>
+    <string name="enable_print_service" msgid="3482815747043533842">"सक्षम करण्यासाठी निवडा"</string>
+    <string name="enabled_services_title" msgid="7036986099096582296">"सक्षम केलेल्या सेवा"</string>
+    <string name="recommended_services_title" msgid="3799434882937956924">"शिफारस केलेल्या सेवा"</string>
+    <string name="disabled_services_title" msgid="7313253167968363211">"अक्षम केलल्या सेवा"</string>
+    <string name="all_services_title" msgid="5578662754874906455">"सर्व सेवा"</string>
     <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>
diff --git a/packages/PrintSpooler/res/values-ms-rMY/strings.xml b/packages/PrintSpooler/res/values-ms-rMY/strings.xml
index 917ae8a..73104e1 100644
--- a/packages/PrintSpooler/res/values-ms-rMY/strings.xml
+++ b/packages/PrintSpooler/res/values-ms-rMY/strings.xml
@@ -61,11 +61,17 @@
     </plurals>
     <string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="printer_info_desc" msgid="7181988788991581654">"Maklumat lanjut tentang pencetak ini"</string>
-    <string name="print_services_disabled_toast" msgid="1205302482388937547">"Sesetengah perkhidmatan cetak dilumpuhkan."</string>
-    <string name="choose_print_service" msgid="3740309762324459694">"Pilih perkhidmatan cetak"</string>
+    <string name="print_services_disabled_toast" msgid="9089060734685174685">"Sesetengah perkhidmatan cetak dilumpuhkan"</string>
     <string name="print_searching_for_printers" msgid="6550424555079932867">"Mencari pencetak"</string>
     <string name="print_no_print_services" msgid="8561247706423327966">"Perkhidmatan cetak tidak didayakan"</string>
     <string name="print_no_printers" msgid="4869403323900054866">"Tiada pencetak ditemui"</string>
+    <string name="cannot_add_printer" msgid="7840348733668023106">"Tidak dapat menambahkan pencetak"</string>
+    <string name="select_to_add_printers" msgid="3800709038689830974">"Pilih untuk menambahkan pencetak"</string>
+    <string name="enable_print_service" msgid="3482815747043533842">"Pilih untuk mendayakan"</string>
+    <string name="enabled_services_title" msgid="7036986099096582296">"Perkhidmatan yang didayakan"</string>
+    <string name="recommended_services_title" msgid="3799434882937956924">"Perkhidmatan yang disyorkan"</string>
+    <string name="disabled_services_title" msgid="7313253167968363211">"Perkhidmatan yang dilumpuhkan"</string>
+    <string name="all_services_title" msgid="5578662754874906455">"Semua perkhidmatan"</string>
     <string name="printing_notification_title_template" msgid="295903957762447362">"Mencetak <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
     <string name="cancelling_notification_title_template" msgid="1821759594704703197">"Membatalkan <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
     <string name="failed_notification_title_template" msgid="2256217208186530973">"Ralat pencetak <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/PrintSpooler/res/values-my-rMM/strings.xml b/packages/PrintSpooler/res/values-my-rMM/strings.xml
index 4d4c95b..8cec068 100644
--- a/packages/PrintSpooler/res/values-my-rMM/strings.xml
+++ b/packages/PrintSpooler/res/values-my-rMM/strings.xml
@@ -61,11 +61,17 @@
     </plurals>
     <string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="printer_info_desc" msgid="7181988788991581654">"ဤပရင်တာ အကြောင်း ပိုမိုလေ့လာပါ"</string>
-    <string name="print_services_disabled_toast" msgid="1205302482388937547">"ပရင့်ထုတ်ရေး အချို့ဝန်ဆောင်မှုများကို ပိတ်ထားပါသည်။"</string>
-    <string name="choose_print_service" msgid="3740309762324459694">"စာထုတ်ရန် ဝန်ဆောင်မှုကို ရွေးချယ်ပါ"</string>
+    <string name="print_services_disabled_toast" msgid="9089060734685174685">"အချို့ပုံနှိပ်ဝန်ဆောင်မှုများကို ပိတ်ထားပါသည်"</string>
     <string name="print_searching_for_printers" msgid="6550424555079932867">"စာထုတ်စက်များကို ရှာနေပါသည်"</string>
     <string name="print_no_print_services" msgid="8561247706423327966">"ပုံနှိပ်ထုတ်ယူရေး ဝန်ဆောင်မှုများ ဖွင့်မထားပါ"</string>
     <string name="print_no_printers" msgid="4869403323900054866">"စာထုတ်စက် တစ်ခုမှ မတွေ့ရှိပါ"</string>
+    <string name="cannot_add_printer" msgid="7840348733668023106">"ပုံနှိပ်စက်များကို ထည့်၍မရပါ"</string>
+    <string name="select_to_add_printers" msgid="3800709038689830974">"ပုံနှိပ်စက်ထည့်ရန် ရွေးပါ"</string>
+    <string name="enable_print_service" msgid="3482815747043533842">"ဖွင့်ရန် ရွေးပါ"</string>
+    <string name="enabled_services_title" msgid="7036986099096582296">"ဖွင့်ထားသည့် ဝန်ဆောင်မှုများ"</string>
+    <string name="recommended_services_title" msgid="3799434882937956924">"အကြံပြုထားသည့် ဝန်ဆောင်မှုများ"</string>
+    <string name="disabled_services_title" msgid="7313253167968363211">"ပိတ်ထားသည့် ဝန်ဆောင်မှုများ"</string>
+    <string name="all_services_title" msgid="5578662754874906455">"ဝန်ဆောင်မှုများ အားလုံး"</string>
     <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>
diff --git a/packages/PrintSpooler/res/values-nb/strings.xml b/packages/PrintSpooler/res/values-nb/strings.xml
index 9efa5d1..0a6f6c3 100644
--- a/packages/PrintSpooler/res/values-nb/strings.xml
+++ b/packages/PrintSpooler/res/values-nb/strings.xml
@@ -61,11 +61,17 @@
     </plurals>
     <string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> – <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="printer_info_desc" msgid="7181988788991581654">"Mer informasjon om denne printeren"</string>
-    <string name="print_services_disabled_toast" msgid="1205302482388937547">"Noen utskriftstjenester er slått av."</string>
-    <string name="choose_print_service" msgid="3740309762324459694">"Velg utskriftstjeneste"</string>
+    <string name="print_services_disabled_toast" msgid="9089060734685174685">"Noen utskriftstjenester er slått av"</string>
     <string name="print_searching_for_printers" msgid="6550424555079932867">"Søker etter skrivere"</string>
     <string name="print_no_print_services" msgid="8561247706423327966">"Ingen utskriftstjenester er slått på"</string>
     <string name="print_no_printers" msgid="4869403323900054866">"Fant ingen skrivere"</string>
+    <string name="cannot_add_printer" msgid="7840348733668023106">"Kan ikke legge til skrivere"</string>
+    <string name="select_to_add_printers" msgid="3800709038689830974">"Velg for å legge til skrivere"</string>
+    <string name="enable_print_service" msgid="3482815747043533842">"Velg for å slå på"</string>
+    <string name="enabled_services_title" msgid="7036986099096582296">"Tjenester som er slått på"</string>
+    <string name="recommended_services_title" msgid="3799434882937956924">"Anbefalte tjenester"</string>
+    <string name="disabled_services_title" msgid="7313253167968363211">"Tjenester som er slått av"</string>
+    <string name="all_services_title" msgid="5578662754874906455">"Alle tjenester"</string>
     <string name="printing_notification_title_template" msgid="295903957762447362">"Skriver ut <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
     <string name="cancelling_notification_title_template" msgid="1821759594704703197">"Avbryter <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
     <string name="failed_notification_title_template" msgid="2256217208186530973">"Skriverfeil <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/PrintSpooler/res/values-ne-rNP/strings.xml b/packages/PrintSpooler/res/values-ne-rNP/strings.xml
index 281a65d..e12c8df 100644
--- a/packages/PrintSpooler/res/values-ne-rNP/strings.xml
+++ b/packages/PrintSpooler/res/values-ne-rNP/strings.xml
@@ -61,11 +61,17 @@
     </plurals>
     <string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="printer_info_desc" msgid="7181988788991581654">"यस प्रिन्टरको बारेमा थप जानकारी"</string>
-    <string name="print_services_disabled_toast" msgid="1205302482388937547">"केही मुद्रण सेवाहरू असक्षम छन्।"</string>
-    <string name="choose_print_service" msgid="3740309762324459694">"प्रिन्ट सेवा छनौट गर्नुहोस्"</string>
+    <string name="print_services_disabled_toast" msgid="9089060734685174685">"केही मुद्रण सम्बन्धी सेवाहरूलाई असक्षम गरिएको छ"</string>
     <string name="print_searching_for_printers" msgid="6550424555079932867">"प्रिन्टरहरू खोज्दै"</string>
     <string name="print_no_print_services" msgid="8561247706423327966">"कुनै पनि मुद्रण सेवाहरू सक्रिय छैनन्"</string>
     <string name="print_no_printers" msgid="4869403323900054866">"कुनै प्रिन्टरहरू भेटाइएन"</string>
+    <string name="cannot_add_printer" msgid="7840348733668023106">"प्रिन्टरहरू थप्न सक्दैन"</string>
+    <string name="select_to_add_printers" msgid="3800709038689830974">"प्रिन्टर थप्नका लागि चयन गर्नुहोस्"</string>
+    <string name="enable_print_service" msgid="3482815747043533842">"सक्षम गर्नका लागि चयन गर्नुहोस्"</string>
+    <string name="enabled_services_title" msgid="7036986099096582296">"सेवाहरूलाई सक्षम गर्नुहोस्"</string>
+    <string name="recommended_services_title" msgid="3799434882937956924">"सिफारिस गरिएका सेवाहरू"</string>
+    <string name="disabled_services_title" msgid="7313253167968363211">"असक्षम गरिएका सेवाहरू"</string>
+    <string name="all_services_title" msgid="5578662754874906455">"सबै सेवाहरू"</string>
     <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>
diff --git a/packages/PrintSpooler/res/values-nl/strings.xml b/packages/PrintSpooler/res/values-nl/strings.xml
index eef9880..4afdb86 100644
--- a/packages/PrintSpooler/res/values-nl/strings.xml
+++ b/packages/PrintSpooler/res/values-nl/strings.xml
@@ -61,11 +61,17 @@
     </plurals>
     <string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="printer_info_desc" msgid="7181988788991581654">"Meer informatie over deze printer"</string>
-    <string name="print_services_disabled_toast" msgid="1205302482388937547">"Sommige afdrukservices zijn uitgeschakeld."</string>
-    <string name="choose_print_service" msgid="3740309762324459694">"Afdrukservice kiezen"</string>
+    <string name="print_services_disabled_toast" msgid="9089060734685174685">"Sommige afdrukservices zijn uitgeschakeld"</string>
     <string name="print_searching_for_printers" msgid="6550424555079932867">"Printers zoeken"</string>
     <string name="print_no_print_services" msgid="8561247706423327966">"Geen afdrukservices ingeschakeld"</string>
     <string name="print_no_printers" msgid="4869403323900054866">"Geen printers gevonden"</string>
+    <string name="cannot_add_printer" msgid="7840348733668023106">"Kan geen printers toevoegen"</string>
+    <string name="select_to_add_printers" msgid="3800709038689830974">"Selecteer om printer toe te voegen"</string>
+    <string name="enable_print_service" msgid="3482815747043533842">"Selecteer om in te schakelen"</string>
+    <string name="enabled_services_title" msgid="7036986099096582296">"Ingeschakelde services"</string>
+    <string name="recommended_services_title" msgid="3799434882937956924">"Aanbevolen services"</string>
+    <string name="disabled_services_title" msgid="7313253167968363211">"Uitgeschakelde services"</string>
+    <string name="all_services_title" msgid="5578662754874906455">"Alle services"</string>
     <string name="printing_notification_title_template" msgid="295903957762447362">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> afdrukken"</string>
     <string name="cancelling_notification_title_template" msgid="1821759594704703197">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> annuleren"</string>
     <string name="failed_notification_title_template" msgid="2256217208186530973">"Printerfout <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/PrintSpooler/res/values-pa-rIN/strings.xml b/packages/PrintSpooler/res/values-pa-rIN/strings.xml
index 7d7860c..1886ef5 100644
--- a/packages/PrintSpooler/res/values-pa-rIN/strings.xml
+++ b/packages/PrintSpooler/res/values-pa-rIN/strings.xml
@@ -61,11 +61,17 @@
     </plurals>
     <string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="printer_info_desc" msgid="7181988788991581654">"ਇਸ ਪ੍ਰਿੰਟਰ ਬਾਰੇ ਹੋਰ ਜਾਣਕਾਰੀ"</string>
-    <string name="print_services_disabled_toast" msgid="1205302482388937547">"ਕੁਝ ਪ੍ਰਿੰਟ ਸੇਵਾਵਾਂ ਅਯੋਗ ਬਣਾਈਆਂ ਗਈਆਂ ਹਨ।"</string>
-    <string name="choose_print_service" msgid="3740309762324459694">"ਪ੍ਰਿੰਟ ਸੇਵਾ ਚੁਣੋ"</string>
+    <string name="print_services_disabled_toast" msgid="9089060734685174685">"ਕੁਝ ਪ੍ਰਿੰਟ ਸੇਵਾਵਾਂ ਅਯੋਗ ਬਣਾਈਆਂ ਗਈਆਂ ਹਨ"</string>
     <string name="print_searching_for_printers" msgid="6550424555079932867">"ਪ੍ਰਿੰਟਰ ਖੋਜ ਰਿਹਾ ਹੈ"</string>
     <string name="print_no_print_services" msgid="8561247706423327966">"ਪ੍ਰਿੰਟ ਸੇਵਾਵਾਂ ਯੋਗ ਨਹੀਂ ਬਣਾਈਆਂ ਗਈਆਂ"</string>
     <string name="print_no_printers" msgid="4869403323900054866">"ਕੋਈ ਪ੍ਰਿੰਟਰ ਨਹੀਂ ਮਿਲੇ"</string>
+    <string name="cannot_add_printer" msgid="7840348733668023106">"ਪ੍ਰਿੰਟਰ ਸ਼ਾਮਲ ਨਹੀਂ ਕੀਤੇ ਜਾ ਸਕਦੇ"</string>
+    <string name="select_to_add_printers" msgid="3800709038689830974">"ਪ੍ਰਿੰਟਰ ਸ਼ਾਮਲ ਕਰਨ ਲਈ ਚੁਣੋ"</string>
+    <string name="enable_print_service" msgid="3482815747043533842">"ਯੋਗ ਬਣਾਉਣ ਲਈ ਚੁਣੋ"</string>
+    <string name="enabled_services_title" msgid="7036986099096582296">"ਯੋਗ ਬਣਾਈਆਂ ਗਈਆਂ ਸੇਵਾਵਾਂ"</string>
+    <string name="recommended_services_title" msgid="3799434882937956924">"ਸਿਫ਼ਾਰਸ਼ ਕੀਤੀਆਂ ਸੇਵਾਵਾਂ"</string>
+    <string name="disabled_services_title" msgid="7313253167968363211">"ਅਯੋਗ ਬਣਾਈਆਂ ਗਈਆਂ ਸੇਵਾਵਾਂ"</string>
+    <string name="all_services_title" msgid="5578662754874906455">"ਸਾਰੀਆਂ ਸੇਵਾਵਾਂ"</string>
     <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>
diff --git a/packages/PrintSpooler/res/values-pl/strings.xml b/packages/PrintSpooler/res/values-pl/strings.xml
index 6837edf..45649bb 100644
--- a/packages/PrintSpooler/res/values-pl/strings.xml
+++ b/packages/PrintSpooler/res/values-pl/strings.xml
@@ -63,11 +63,17 @@
     </plurals>
     <string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> – <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="printer_info_desc" msgid="7181988788991581654">"Więcej informacji o tej drukarce"</string>
-    <string name="print_services_disabled_toast" msgid="1205302482388937547">"Niektóre usługi drukowania są wyłączone."</string>
-    <string name="choose_print_service" msgid="3740309762324459694">"Wybierz usługę drukowania"</string>
+    <string name="print_services_disabled_toast" msgid="9089060734685174685">"Niektóre usługi drukowania są wyłączone"</string>
     <string name="print_searching_for_printers" msgid="6550424555079932867">"Szukanie drukarek"</string>
     <string name="print_no_print_services" msgid="8561247706423327966">"Brak włączonych usług drukowania"</string>
     <string name="print_no_printers" msgid="4869403323900054866">"Nie znaleziono drukarek"</string>
+    <string name="cannot_add_printer" msgid="7840348733668023106">"Nie można dodawać drukarek"</string>
+    <string name="select_to_add_printers" msgid="3800709038689830974">"Wybierz, by dodać drukarkę"</string>
+    <string name="enable_print_service" msgid="3482815747043533842">"Wybierz, by włączyć usługę"</string>
+    <string name="enabled_services_title" msgid="7036986099096582296">"Włączone usługi"</string>
+    <string name="recommended_services_title" msgid="3799434882937956924">"Polecane usługi"</string>
+    <string name="disabled_services_title" msgid="7313253167968363211">"Wyłączone usługi"</string>
+    <string name="all_services_title" msgid="5578662754874906455">"Wszystkie usługi"</string>
     <string name="printing_notification_title_template" msgid="295903957762447362">"Drukowanie: <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
     <string name="cancelling_notification_title_template" msgid="1821759594704703197">"Anulowanie: <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
     <string name="failed_notification_title_template" msgid="2256217208186530973">"Błąd drukarki: <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/PrintSpooler/res/values-pt-rBR/strings.xml b/packages/PrintSpooler/res/values-pt-rBR/strings.xml
index c9713c9..58eb24f 100644
--- a/packages/PrintSpooler/res/values-pt-rBR/strings.xml
+++ b/packages/PrintSpooler/res/values-pt-rBR/strings.xml
@@ -61,11 +61,17 @@
     </plurals>
     <string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="printer_info_desc" msgid="7181988788991581654">"Mais informações sobre essa impressora"</string>
-    <string name="print_services_disabled_toast" msgid="1205302482388937547">"Alguns serviços de impressão estão desativados."</string>
-    <string name="choose_print_service" msgid="3740309762324459694">"Selecione o serviço de impressão"</string>
+    <string name="print_services_disabled_toast" msgid="9089060734685174685">"Alguns serviços de impressão estão desativados"</string>
     <string name="print_searching_for_printers" msgid="6550424555079932867">"Procurando impressoras"</string>
     <string name="print_no_print_services" msgid="8561247706423327966">"Nenhum serviço de impressão ativado"</string>
     <string name="print_no_printers" msgid="4869403323900054866">"Nenhuma impressora encontrada"</string>
+    <string name="cannot_add_printer" msgid="7840348733668023106">"Não é possível adicionar impressoras"</string>
+    <string name="select_to_add_printers" msgid="3800709038689830974">"Selecione para adicionar uma impressora"</string>
+    <string name="enable_print_service" msgid="3482815747043533842">"Selecione para ativar"</string>
+    <string name="enabled_services_title" msgid="7036986099096582296">"Serviços ativados"</string>
+    <string name="recommended_services_title" msgid="3799434882937956924">"Serviços recomendados"</string>
+    <string name="disabled_services_title" msgid="7313253167968363211">"Serviços desativados"</string>
+    <string name="all_services_title" msgid="5578662754874906455">"Todos os serviços"</string>
     <string name="printing_notification_title_template" msgid="295903957762447362">"Imprimindo <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
     <string name="cancelling_notification_title_template" msgid="1821759594704703197">"Cancelando <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
     <string name="failed_notification_title_template" msgid="2256217208186530973">"Erro ao imprimir <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/PrintSpooler/res/values-pt-rPT/strings.xml b/packages/PrintSpooler/res/values-pt-rPT/strings.xml
index 9fabc0f..370bbb9 100644
--- a/packages/PrintSpooler/res/values-pt-rPT/strings.xml
+++ b/packages/PrintSpooler/res/values-pt-rPT/strings.xml
@@ -61,11 +61,17 @@
     </plurals>
     <string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> – <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="printer_info_desc" msgid="7181988788991581654">"Mais informações acerca desta impressora"</string>
-    <string name="print_services_disabled_toast" msgid="1205302482388937547">"Alguns serviços de impressão estão desativados."</string>
-    <string name="choose_print_service" msgid="3740309762324459694">"Escolher o serviço de impressão"</string>
+    <string name="print_services_disabled_toast" msgid="9089060734685174685">"Alguns serviços de impressão estão desativados"</string>
     <string name="print_searching_for_printers" msgid="6550424555079932867">"A procurar impressoras"</string>
     <string name="print_no_print_services" msgid="8561247706423327966">"Nenhum serviço de impressão ativado"</string>
     <string name="print_no_printers" msgid="4869403323900054866">"Nenhuma impressora encontrada"</string>
+    <string name="cannot_add_printer" msgid="7840348733668023106">"Não é possível adicionar impressoras"</string>
+    <string name="select_to_add_printers" msgid="3800709038689830974">"Selecione para adicionar uma impressora"</string>
+    <string name="enable_print_service" msgid="3482815747043533842">"Selecione para ativar"</string>
+    <string name="enabled_services_title" msgid="7036986099096582296">"Serviços ativados"</string>
+    <string name="recommended_services_title" msgid="3799434882937956924">"Serviços recomendados"</string>
+    <string name="disabled_services_title" msgid="7313253167968363211">"Serviços desativados"</string>
+    <string name="all_services_title" msgid="5578662754874906455">"Todos os serviços"</string>
     <string name="printing_notification_title_template" msgid="295903957762447362">"A imprimir <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
     <string name="cancelling_notification_title_template" msgid="1821759594704703197">"A cancelar <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
     <string name="failed_notification_title_template" msgid="2256217208186530973">"Erro da impressora <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/PrintSpooler/res/values-pt/strings.xml b/packages/PrintSpooler/res/values-pt/strings.xml
index c9713c9..58eb24f 100644
--- a/packages/PrintSpooler/res/values-pt/strings.xml
+++ b/packages/PrintSpooler/res/values-pt/strings.xml
@@ -61,11 +61,17 @@
     </plurals>
     <string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="printer_info_desc" msgid="7181988788991581654">"Mais informações sobre essa impressora"</string>
-    <string name="print_services_disabled_toast" msgid="1205302482388937547">"Alguns serviços de impressão estão desativados."</string>
-    <string name="choose_print_service" msgid="3740309762324459694">"Selecione o serviço de impressão"</string>
+    <string name="print_services_disabled_toast" msgid="9089060734685174685">"Alguns serviços de impressão estão desativados"</string>
     <string name="print_searching_for_printers" msgid="6550424555079932867">"Procurando impressoras"</string>
     <string name="print_no_print_services" msgid="8561247706423327966">"Nenhum serviço de impressão ativado"</string>
     <string name="print_no_printers" msgid="4869403323900054866">"Nenhuma impressora encontrada"</string>
+    <string name="cannot_add_printer" msgid="7840348733668023106">"Não é possível adicionar impressoras"</string>
+    <string name="select_to_add_printers" msgid="3800709038689830974">"Selecione para adicionar uma impressora"</string>
+    <string name="enable_print_service" msgid="3482815747043533842">"Selecione para ativar"</string>
+    <string name="enabled_services_title" msgid="7036986099096582296">"Serviços ativados"</string>
+    <string name="recommended_services_title" msgid="3799434882937956924">"Serviços recomendados"</string>
+    <string name="disabled_services_title" msgid="7313253167968363211">"Serviços desativados"</string>
+    <string name="all_services_title" msgid="5578662754874906455">"Todos os serviços"</string>
     <string name="printing_notification_title_template" msgid="295903957762447362">"Imprimindo <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
     <string name="cancelling_notification_title_template" msgid="1821759594704703197">"Cancelando <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
     <string name="failed_notification_title_template" msgid="2256217208186530973">"Erro ao imprimir <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/PrintSpooler/res/values-ro/strings.xml b/packages/PrintSpooler/res/values-ro/strings.xml
index 7364eb0..1097d56 100644
--- a/packages/PrintSpooler/res/values-ro/strings.xml
+++ b/packages/PrintSpooler/res/values-ro/strings.xml
@@ -62,11 +62,17 @@
     </plurals>
     <string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> – <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="printer_info_desc" msgid="7181988788991581654">"Mai multe informații despre această imprimantă"</string>
-    <string name="print_services_disabled_toast" msgid="1205302482388937547">"Unele servicii de printare sunt dezactivate."</string>
-    <string name="choose_print_service" msgid="3740309762324459694">"Alegeți serviciul de printare"</string>
+    <string name="print_services_disabled_toast" msgid="9089060734685174685">"Unele servicii de printare sunt dezactivate"</string>
     <string name="print_searching_for_printers" msgid="6550424555079932867">"Se caută imprimante"</string>
     <string name="print_no_print_services" msgid="8561247706423327966">"Niciun serviciu de printare activat"</string>
     <string name="print_no_printers" msgid="4869403323900054866">"Nu au fost găsite imprimante"</string>
+    <string name="cannot_add_printer" msgid="7840348733668023106">"Nu pot fi adăugate imprimante"</string>
+    <string name="select_to_add_printers" msgid="3800709038689830974">"Selectați pentru a adăuga o imprimantă"</string>
+    <string name="enable_print_service" msgid="3482815747043533842">"Selectați pentru a activa"</string>
+    <string name="enabled_services_title" msgid="7036986099096582296">"Servicii activate"</string>
+    <string name="recommended_services_title" msgid="3799434882937956924">"Servicii recomandate"</string>
+    <string name="disabled_services_title" msgid="7313253167968363211">"Servicii dezactivate"</string>
+    <string name="all_services_title" msgid="5578662754874906455">"Toate serviciile"</string>
     <string name="printing_notification_title_template" msgid="295903957762447362">"Se printează <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
     <string name="cancelling_notification_title_template" msgid="1821759594704703197">"Se anulează <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
     <string name="failed_notification_title_template" msgid="2256217208186530973">"Eroare de printare: <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/PrintSpooler/res/values-ru/strings.xml b/packages/PrintSpooler/res/values-ru/strings.xml
index d3d0d3f..24b1e0d 100644
--- a/packages/PrintSpooler/res/values-ru/strings.xml
+++ b/packages/PrintSpooler/res/values-ru/strings.xml
@@ -63,11 +63,17 @@
     </plurals>
     <string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> – <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="printer_info_desc" msgid="7181988788991581654">"Подробные сведения о принтере"</string>
-    <string name="print_services_disabled_toast" msgid="1205302482388937547">"Некоторые службы печати отключены."</string>
-    <string name="choose_print_service" msgid="3740309762324459694">"Выберите службу печати"</string>
+    <string name="print_services_disabled_toast" msgid="9089060734685174685">"Некоторые службы печати отключены"</string>
     <string name="print_searching_for_printers" msgid="6550424555079932867">"Поиск принтеров…"</string>
     <string name="print_no_print_services" msgid="8561247706423327966">"Службы печати недоступны"</string>
     <string name="print_no_printers" msgid="4869403323900054866">"Ничего не найдено"</string>
+    <string name="cannot_add_printer" msgid="7840348733668023106">"Невозможно добавить принтеры"</string>
+    <string name="select_to_add_printers" msgid="3800709038689830974">"Выберите, чтобы добавить принтер"</string>
+    <string name="enable_print_service" msgid="3482815747043533842">"Выберите, чтобы включить"</string>
+    <string name="enabled_services_title" msgid="7036986099096582296">"Включенные службы"</string>
+    <string name="recommended_services_title" msgid="3799434882937956924">"Рекомендуемые службы"</string>
+    <string name="disabled_services_title" msgid="7313253167968363211">"Отключенные службы"</string>
+    <string name="all_services_title" msgid="5578662754874906455">"Все службы печати"</string>
     <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>
diff --git a/packages/PrintSpooler/res/values-si-rLK/strings.xml b/packages/PrintSpooler/res/values-si-rLK/strings.xml
index 610442d..707c151 100644
--- a/packages/PrintSpooler/res/values-si-rLK/strings.xml
+++ b/packages/PrintSpooler/res/values-si-rLK/strings.xml
@@ -61,11 +61,17 @@
     </plurals>
     <string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="printer_info_desc" msgid="7181988788991581654">"මෙම මුද්‍රණ යන්ත්‍රය ගැන තවත් තොරතුරු"</string>
-    <string name="print_services_disabled_toast" msgid="1205302482388937547">"සමහර මුද්‍රණ සේවා අබලයි."</string>
-    <string name="choose_print_service" msgid="3740309762324459694">"මුද්‍රණ සේවාව තෝරන්න"</string>
+    <string name="print_services_disabled_toast" msgid="9089060734685174685">"සමහර මුද්‍රණ සේවා අබලයි"</string>
     <string name="print_searching_for_printers" msgid="6550424555079932867">"මුද්‍රණ යන්ත්‍ර සොයමින්"</string>
     <string name="print_no_print_services" msgid="8561247706423327966">"මුද්‍රණ සේවා සබල නැත"</string>
     <string name="print_no_printers" msgid="4869403323900054866">"මුද්‍රණ යන්ත්‍ර සොයා නොගැනුණි"</string>
+    <string name="cannot_add_printer" msgid="7840348733668023106">"මුද්‍රණ යන්ත්‍ර එක් කළ නොහැකිය"</string>
+    <string name="select_to_add_printers" msgid="3800709038689830974">"මුද්‍රණ යන්ත්‍රය එක් කිරීමට තෝරන්න"</string>
+    <string name="enable_print_service" msgid="3482815747043533842">"සබල කිරීමට තෝරන්න"</string>
+    <string name="enabled_services_title" msgid="7036986099096582296">"සබල කළ සේවා"</string>
+    <string name="recommended_services_title" msgid="3799434882937956924">"නිර්දේශිත සේවා"</string>
+    <string name="disabled_services_title" msgid="7313253167968363211">"අබල කළ සේවා"</string>
+    <string name="all_services_title" msgid="5578662754874906455">"සියලු සේවා"</string>
     <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>
diff --git a/packages/PrintSpooler/res/values-sk/strings.xml b/packages/PrintSpooler/res/values-sk/strings.xml
index 603d1d2..1f13b54 100644
--- a/packages/PrintSpooler/res/values-sk/strings.xml
+++ b/packages/PrintSpooler/res/values-sk/strings.xml
@@ -63,11 +63,17 @@
     </plurals>
     <string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> – <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="printer_info_desc" msgid="7181988788991581654">"Ďalšie informácie o tejto tlačiarni"</string>
-    <string name="print_services_disabled_toast" msgid="1205302482388937547">"Niektoré tlačové služby sú vypnuté."</string>
-    <string name="choose_print_service" msgid="3740309762324459694">"Výber tlačovej služby"</string>
+    <string name="print_services_disabled_toast" msgid="9089060734685174685">"Niektoré tlačové služby sú zakázané"</string>
     <string name="print_searching_for_printers" msgid="6550424555079932867">"Vyhľadávanie tlačiarní"</string>
     <string name="print_no_print_services" msgid="8561247706423327966">"Žiadne tlačové služby nie sú aktivované"</string>
     <string name="print_no_printers" msgid="4869403323900054866">"Nenašli sa žiadne tlačiarne"</string>
+    <string name="cannot_add_printer" msgid="7840348733668023106">"Nie je možné pridať tlačiarne"</string>
+    <string name="select_to_add_printers" msgid="3800709038689830974">"Výber služby na pridanie tlačiarne"</string>
+    <string name="enable_print_service" msgid="3482815747043533842">"Vyberte a povoľte"</string>
+    <string name="enabled_services_title" msgid="7036986099096582296">"Povolené služby"</string>
+    <string name="recommended_services_title" msgid="3799434882937956924">"Odporúčané služby"</string>
+    <string name="disabled_services_title" msgid="7313253167968363211">"Zakázané služby"</string>
+    <string name="all_services_title" msgid="5578662754874906455">"Všetky služby"</string>
     <string name="printing_notification_title_template" msgid="295903957762447362">"Prebieha tlač úlohy <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
     <string name="cancelling_notification_title_template" msgid="1821759594704703197">"Prebieha zrušenie úlohy <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
     <string name="failed_notification_title_template" msgid="2256217208186530973">"Chyba tlačiarne – úloha <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/PrintSpooler/res/values-sl/strings.xml b/packages/PrintSpooler/res/values-sl/strings.xml
index 4a08269..3f8a5e6 100644
--- a/packages/PrintSpooler/res/values-sl/strings.xml
+++ b/packages/PrintSpooler/res/values-sl/strings.xml
@@ -63,11 +63,17 @@
     </plurals>
     <string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> – <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="printer_info_desc" msgid="7181988788991581654">"Več informacij o tem tiskalniku"</string>
-    <string name="print_services_disabled_toast" msgid="1205302482388937547">"Nekatere tiskalne storitve so onemogočene."</string>
-    <string name="choose_print_service" msgid="3740309762324459694">"Izberite tiskalno storitev"</string>
+    <string name="print_services_disabled_toast" msgid="9089060734685174685">"Nekatere tiskalne storitve so onemogočene"</string>
     <string name="print_searching_for_printers" msgid="6550424555079932867">"Iskanje tiskalnikov"</string>
     <string name="print_no_print_services" msgid="8561247706423327966">"Ni omogočenih tiskalnih storitev"</string>
     <string name="print_no_printers" msgid="4869403323900054866">"Tiskalnikov ni mogoče najti"</string>
+    <string name="cannot_add_printer" msgid="7840348733668023106">"Tiskalnikov ni mogoče dodati"</string>
+    <string name="select_to_add_printers" msgid="3800709038689830974">"Izberite za dodajanje tiskalnika"</string>
+    <string name="enable_print_service" msgid="3482815747043533842">"Izberite, če želite omogočiti"</string>
+    <string name="enabled_services_title" msgid="7036986099096582296">"Omogočene storitve"</string>
+    <string name="recommended_services_title" msgid="3799434882937956924">"Priporočene storitve"</string>
+    <string name="disabled_services_title" msgid="7313253167968363211">"Onemogočene storitve"</string>
+    <string name="all_services_title" msgid="5578662754874906455">"Vse storitve"</string>
     <string name="printing_notification_title_template" msgid="295903957762447362">"Tiskanje: <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
     <string name="cancelling_notification_title_template" msgid="1821759594704703197">"Preklic: <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
     <string name="failed_notification_title_template" msgid="2256217208186530973">"Napaka tiskalnika: <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/PrintSpooler/res/values-sq-rAL/strings.xml b/packages/PrintSpooler/res/values-sq-rAL/strings.xml
index b0902ef..0b843d7 100644
--- a/packages/PrintSpooler/res/values-sq-rAL/strings.xml
+++ b/packages/PrintSpooler/res/values-sq-rAL/strings.xml
@@ -61,11 +61,17 @@
     </plurals>
     <string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="printer_info_desc" msgid="7181988788991581654">"Më shumë informacione mbi këtë printer"</string>
-    <string name="print_services_disabled_toast" msgid="1205302482388937547">"Disa shërbime printimi janë çaktivizuar."</string>
-    <string name="choose_print_service" msgid="3740309762324459694">"Zgjidh shërbimin e printimit"</string>
+    <string name="print_services_disabled_toast" msgid="9089060734685174685">"Disa shërbime printimi janë çaktivizuar"</string>
     <string name="print_searching_for_printers" msgid="6550424555079932867">"Po kërkon për printerë"</string>
     <string name="print_no_print_services" msgid="8561247706423327966">"Nuk ka shërbime printimi të aktivizuara"</string>
     <string name="print_no_printers" msgid="4869403323900054866">"Nuk u gjet asnjë printer"</string>
+    <string name="cannot_add_printer" msgid="7840348733668023106">"Nuk mund të shtohen printerë"</string>
+    <string name="select_to_add_printers" msgid="3800709038689830974">"Zgjidh për të shtuar printer"</string>
+    <string name="enable_print_service" msgid="3482815747043533842">"Zgjidh për të aktivizuar"</string>
+    <string name="enabled_services_title" msgid="7036986099096582296">"Shërbimet e aktivizuara"</string>
+    <string name="recommended_services_title" msgid="3799434882937956924">"Shërbimet e rekomanduara"</string>
+    <string name="disabled_services_title" msgid="7313253167968363211">"Shërbimet e çaktivizuara"</string>
+    <string name="all_services_title" msgid="5578662754874906455">"Të gjitha shërbimet"</string>
     <string name="printing_notification_title_template" msgid="295903957762447362">"Po printon <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
     <string name="cancelling_notification_title_template" msgid="1821759594704703197">"Po anulon <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
     <string name="failed_notification_title_template" msgid="2256217208186530973">"Printeri ndeshi në gabim gjatë punës: <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/PrintSpooler/res/values-sr/strings.xml b/packages/PrintSpooler/res/values-sr/strings.xml
index feb2940..8baa23c 100644
--- a/packages/PrintSpooler/res/values-sr/strings.xml
+++ b/packages/PrintSpooler/res/values-sr/strings.xml
@@ -62,11 +62,17 @@
     </plurals>
     <string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> – <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="printer_info_desc" msgid="7181988788991581654">"Још информација о овом штампачу"</string>
-    <string name="print_services_disabled_toast" msgid="1205302482388937547">"Неке услуге штампања су онемогућене."</string>
-    <string name="choose_print_service" msgid="3740309762324459694">"Изаберите услугу штампања"</string>
+    <string name="print_services_disabled_toast" msgid="9089060734685174685">"Неке услуге штампања су онемогућене"</string>
     <string name="print_searching_for_printers" msgid="6550424555079932867">"Претрага штампача"</string>
     <string name="print_no_print_services" msgid="8561247706423327966">"Ниједна услуга штампања није омогућена"</string>
     <string name="print_no_printers" msgid="4869403323900054866">"Није пронађен ниједан штампач"</string>
+    <string name="cannot_add_printer" msgid="7840348733668023106">"Није могуће додати штампаче"</string>
+    <string name="select_to_add_printers" msgid="3800709038689830974">"Изаберите да бисте додали штампач"</string>
+    <string name="enable_print_service" msgid="3482815747043533842">"Изаберите да бисте омогућили"</string>
+    <string name="enabled_services_title" msgid="7036986099096582296">"Омогућене услуге"</string>
+    <string name="recommended_services_title" msgid="3799434882937956924">"Препоручене услуге"</string>
+    <string name="disabled_services_title" msgid="7313253167968363211">"Онемогућене услуге"</string>
+    <string name="all_services_title" msgid="5578662754874906455">"Све услуге"</string>
     <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>
diff --git a/packages/PrintSpooler/res/values-sv/strings.xml b/packages/PrintSpooler/res/values-sv/strings.xml
index cf398c7..64b6b20 100644
--- a/packages/PrintSpooler/res/values-sv/strings.xml
+++ b/packages/PrintSpooler/res/values-sv/strings.xml
@@ -61,11 +61,17 @@
     </plurals>
     <string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> – <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="printer_info_desc" msgid="7181988788991581654">"Mer information om den här skrivaren"</string>
-    <string name="print_services_disabled_toast" msgid="1205302482388937547">"Några utskriftstjänster har inaktiverats."</string>
-    <string name="choose_print_service" msgid="3740309762324459694">"Välj utskriftstjänst"</string>
+    <string name="print_services_disabled_toast" msgid="9089060734685174685">"Några utskriftstjänster har inaktiverats"</string>
     <string name="print_searching_for_printers" msgid="6550424555079932867">"Söker efter skrivare"</string>
     <string name="print_no_print_services" msgid="8561247706423327966">"Inga utskriftstjänster har aktiverats"</string>
     <string name="print_no_printers" msgid="4869403323900054866">"Det gick inte att hitta några skrivare"</string>
+    <string name="cannot_add_printer" msgid="7840348733668023106">"Det går inte att lägga till skrivare"</string>
+    <string name="select_to_add_printers" msgid="3800709038689830974">"Lägg till en skrivare"</string>
+    <string name="enable_print_service" msgid="3482815747043533842">"Välj om du vill aktivera"</string>
+    <string name="enabled_services_title" msgid="7036986099096582296">"Aktiverade tjänster"</string>
+    <string name="recommended_services_title" msgid="3799434882937956924">"Rekommenderade tjänster"</string>
+    <string name="disabled_services_title" msgid="7313253167968363211">"Inaktiverade tjänster"</string>
+    <string name="all_services_title" msgid="5578662754874906455">"Alla tjänster"</string>
     <string name="printing_notification_title_template" msgid="295903957762447362">"Skriver ut <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
     <string name="cancelling_notification_title_template" msgid="1821759594704703197">"Avbryter <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
     <string name="failed_notification_title_template" msgid="2256217208186530973">"Skrivarfel för <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/PrintSpooler/res/values-sw/strings.xml b/packages/PrintSpooler/res/values-sw/strings.xml
index 7e00b70..b3ffa71 100644
--- a/packages/PrintSpooler/res/values-sw/strings.xml
+++ b/packages/PrintSpooler/res/values-sw/strings.xml
@@ -61,11 +61,17 @@
     </plurals>
     <string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="printer_info_desc" msgid="7181988788991581654">"Maelezo zaidi kuhusu printa hii"</string>
-    <string name="print_services_disabled_toast" msgid="1205302482388937547">"Baadhi ya huduma za uchapishaji zimezimwa."</string>
-    <string name="choose_print_service" msgid="3740309762324459694">"Chagua huduma ya printa"</string>
+    <string name="print_services_disabled_toast" msgid="9089060734685174685">"Baadhi ya huduma za uchapishaji haziruhusiwi"</string>
     <string name="print_searching_for_printers" msgid="6550424555079932867">"Inatafuta printa"</string>
     <string name="print_no_print_services" msgid="8561247706423327966">"Huduma za kuchapisha hazijawashwa"</string>
     <string name="print_no_printers" msgid="4869403323900054866">"Hakuna printa zilizopatikana"</string>
+    <string name="cannot_add_printer" msgid="7840348733668023106">"Haiwezi kuongeza printa"</string>
+    <string name="select_to_add_printers" msgid="3800709038689830974">"Chagua printa ya kuongeza"</string>
+    <string name="enable_print_service" msgid="3482815747043533842">"Chagua ili uruhusu"</string>
+    <string name="enabled_services_title" msgid="7036986099096582296">"Huduma zinazoruhusiwa"</string>
+    <string name="recommended_services_title" msgid="3799434882937956924">"Huduma zinazopendekezwa"</string>
+    <string name="disabled_services_title" msgid="7313253167968363211">"Huduma ambazo haziruhusiwi"</string>
+    <string name="all_services_title" msgid="5578662754874906455">"Huduma zote"</string>
     <string name="printing_notification_title_template" msgid="295903957762447362">"Inachapisha <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
     <string name="cancelling_notification_title_template" msgid="1821759594704703197">"Inaghairi <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
     <string name="failed_notification_title_template" msgid="2256217208186530973">"Hitilafu ya kuchapisha <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/PrintSpooler/res/values-ta-rIN/strings.xml b/packages/PrintSpooler/res/values-ta-rIN/strings.xml
index ae0b774..7ae3cbc 100644
--- a/packages/PrintSpooler/res/values-ta-rIN/strings.xml
+++ b/packages/PrintSpooler/res/values-ta-rIN/strings.xml
@@ -61,11 +61,17 @@
     </plurals>
     <string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="printer_info_desc" msgid="7181988788991581654">"இந்தப் பிரிண்டர் பற்றிய கூடுதல் தகவல்"</string>
-    <string name="print_services_disabled_toast" msgid="1205302482388937547">"சில அச்சுப் பொறிகள் முடக்கப்பட்டன."</string>
-    <string name="choose_print_service" msgid="3740309762324459694">"அச்சுப் பொறியைத் தேர்வுசெய்யவும்"</string>
+    <string name="print_services_disabled_toast" msgid="9089060734685174685">"சில அச்சுப் பொறிகள் முடக்கப்பட்டன"</string>
     <string name="print_searching_for_printers" msgid="6550424555079932867">"அச்சுப்பொறிகளைத் தேடுகிறது"</string>
     <string name="print_no_print_services" msgid="8561247706423327966">"அச்சுப் பொறிகள் இல்லை"</string>
     <string name="print_no_printers" msgid="4869403323900054866">"பிரிண்டர்கள் எதுவுமில்லை"</string>
+    <string name="cannot_add_printer" msgid="7840348733668023106">"பிரிண்டர்களைச் சேர்க்க முடியவில்லை"</string>
+    <string name="select_to_add_printers" msgid="3800709038689830974">"பிரிண்டரைச் சேர்க்க, தேர்ந்தெடுக்கவும்"</string>
+    <string name="enable_print_service" msgid="3482815747043533842">"இயக்குவதற்குத் தேர்ந்தெடுக்கவும்"</string>
+    <string name="enabled_services_title" msgid="7036986099096582296">"இயக்கப்பட்ட அச்சுப் பொறிகள்"</string>
+    <string name="recommended_services_title" msgid="3799434882937956924">"பரிந்துரைக்கப்படும் அச்சுப் பொறிகள்"</string>
+    <string name="disabled_services_title" msgid="7313253167968363211">"முடக்கப்பட்ட அச்சுப் பொறிகள்"</string>
+    <string name="all_services_title" msgid="5578662754874906455">"எல்லா அச்சுப் பொறிகளும்"</string>
     <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>
diff --git a/packages/PrintSpooler/res/values-te-rIN/strings.xml b/packages/PrintSpooler/res/values-te-rIN/strings.xml
index 5fd8d60..9e8dea2 100644
--- a/packages/PrintSpooler/res/values-te-rIN/strings.xml
+++ b/packages/PrintSpooler/res/values-te-rIN/strings.xml
@@ -61,11 +61,17 @@
     </plurals>
     <string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="printer_info_desc" msgid="7181988788991581654">"ఈ ప్రింటర్ గురించి మరింత సమాచారం"</string>
-    <string name="print_services_disabled_toast" msgid="1205302482388937547">"కొన్ని ముద్రణ సేవలు నిలిపివేయబడ్డాయి."</string>
-    <string name="choose_print_service" msgid="3740309762324459694">"ముద్రణ సేవను ఎంచుకోండి"</string>
+    <string name="print_services_disabled_toast" msgid="9089060734685174685">"కొన్ని ముద్రణ సేవలు నిలిపివేయబడ్డాయి"</string>
     <string name="print_searching_for_printers" msgid="6550424555079932867">"ప్రింటర్‌ల కోసం శోధిస్తోంది"</string>
     <string name="print_no_print_services" msgid="8561247706423327966">"ముద్రణ సేవలు ఏవీ ప్రారంభించలేదు"</string>
     <string name="print_no_printers" msgid="4869403323900054866">"ప్రింటర్‌లు కనుగొనబడలేదు"</string>
+    <string name="cannot_add_printer" msgid="7840348733668023106">"ప్రింటర్‌లను జోడించడం సాధ్యపడలేదు"</string>
+    <string name="select_to_add_printers" msgid="3800709038689830974">"ప్రింటర్‌ను జోడించడానికి ఎంచుకోండి"</string>
+    <string name="enable_print_service" msgid="3482815747043533842">"ప్రారంభించడానికి ఎంచుకోండి"</string>
+    <string name="enabled_services_title" msgid="7036986099096582296">"ప్రారంభించిన సేవలు"</string>
+    <string name="recommended_services_title" msgid="3799434882937956924">"సిఫార్సు చేయబడిన సేవలు"</string>
+    <string name="disabled_services_title" msgid="7313253167968363211">"నిలిపివేసిన సేవలు"</string>
+    <string name="all_services_title" msgid="5578662754874906455">"అన్ని సేవలు"</string>
     <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>
diff --git a/packages/PrintSpooler/res/values-th/strings.xml b/packages/PrintSpooler/res/values-th/strings.xml
index ebd5e2a..c623dd7 100644
--- a/packages/PrintSpooler/res/values-th/strings.xml
+++ b/packages/PrintSpooler/res/values-th/strings.xml
@@ -61,11 +61,17 @@
     </plurals>
     <string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="printer_info_desc" msgid="7181988788991581654">"ข้อมูลเพิ่มเติมเกี่ยวกับเครื่องพิมพ์นี้"</string>
-    <string name="print_services_disabled_toast" msgid="1205302482388937547">"บริการพิมพ์บางอย่างถูกปิดใช้"</string>
-    <string name="choose_print_service" msgid="3740309762324459694">"เลือกบริการพิมพ์"</string>
+    <string name="print_services_disabled_toast" msgid="9089060734685174685">"บริการพิมพ์บางอย่างปิดใช้อยู่"</string>
     <string name="print_searching_for_printers" msgid="6550424555079932867">"กำลังค้นหาเครื่องพิมพ์"</string>
     <string name="print_no_print_services" msgid="8561247706423327966">"ไม่ได้เปิดใช้บริการพิมพ์"</string>
     <string name="print_no_printers" msgid="4869403323900054866">"ไม่พบเครื่องพิมพ์"</string>
+    <string name="cannot_add_printer" msgid="7840348733668023106">"เพิ่มเครื่องพิมพ์ไม่ได้"</string>
+    <string name="select_to_add_printers" msgid="3800709038689830974">"เลือกเพื่อเพิ่มเครื่องพิมพ์"</string>
+    <string name="enable_print_service" msgid="3482815747043533842">"เลือกเพื่อเปิดใช้"</string>
+    <string name="enabled_services_title" msgid="7036986099096582296">"บริการที่เปิดใช้"</string>
+    <string name="recommended_services_title" msgid="3799434882937956924">"บริการที่แนะนำ"</string>
+    <string name="disabled_services_title" msgid="7313253167968363211">"บริการที่ปิดใช้"</string>
+    <string name="all_services_title" msgid="5578662754874906455">"บริการทั้งหมด"</string>
     <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>
diff --git a/packages/PrintSpooler/res/values-tl/strings.xml b/packages/PrintSpooler/res/values-tl/strings.xml
index ebe869b..0494cf6 100644
--- a/packages/PrintSpooler/res/values-tl/strings.xml
+++ b/packages/PrintSpooler/res/values-tl/strings.xml
@@ -61,11 +61,17 @@
     </plurals>
     <string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="printer_info_desc" msgid="7181988788991581654">"Higit pang impormasyon tungkol sa printer na ito"</string>
-    <string name="print_services_disabled_toast" msgid="1205302482388937547">"Naka-disable ang ilang serbisyo sa pag-print."</string>
-    <string name="choose_print_service" msgid="3740309762324459694">"Pumili ng serbisyo ng pag-print"</string>
+    <string name="print_services_disabled_toast" msgid="9089060734685174685">"Naka-disable ang ilang serbisyo sa pag-print"</string>
     <string name="print_searching_for_printers" msgid="6550424555079932867">"Naghahanap ng mga printer"</string>
     <string name="print_no_print_services" msgid="8561247706423327966">"Walang mga naka-enable na serbisyo sa pag-print"</string>
     <string name="print_no_printers" msgid="4869403323900054866">"Walang mga printer na nakita"</string>
+    <string name="cannot_add_printer" msgid="7840348733668023106">"Hindi makapagdagdag ng mga printer"</string>
+    <string name="select_to_add_printers" msgid="3800709038689830974">"Piliin upang magdagdag ng printer"</string>
+    <string name="enable_print_service" msgid="3482815747043533842">"Piliin upang i-enable"</string>
+    <string name="enabled_services_title" msgid="7036986099096582296">"Mga naka-enable na serbisyo"</string>
+    <string name="recommended_services_title" msgid="3799434882937956924">"Mga inirerekomendang serbisyo"</string>
+    <string name="disabled_services_title" msgid="7313253167968363211">"Mga naka-disable na serbisyo"</string>
+    <string name="all_services_title" msgid="5578662754874906455">"Lahat ng serbisyo"</string>
     <string name="printing_notification_title_template" msgid="295903957762447362">"Pini-print ang <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
     <string name="cancelling_notification_title_template" msgid="1821759594704703197">"Kinakansela ang <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
     <string name="failed_notification_title_template" msgid="2256217208186530973">"Error sa printer <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/PrintSpooler/res/values-tr/strings.xml b/packages/PrintSpooler/res/values-tr/strings.xml
index 9cd42ab..2818f36 100644
--- a/packages/PrintSpooler/res/values-tr/strings.xml
+++ b/packages/PrintSpooler/res/values-tr/strings.xml
@@ -61,11 +61,17 @@
     </plurals>
     <string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="printer_info_desc" msgid="7181988788991581654">"Bu yazıcıyla ilgili daha fazla bilgi"</string>
-    <string name="print_services_disabled_toast" msgid="1205302482388937547">"Bazı yazdırma hizmetleri devre dışı."</string>
-    <string name="choose_print_service" msgid="3740309762324459694">"Yazdırma hizmetini seçin"</string>
+    <string name="print_services_disabled_toast" msgid="9089060734685174685">"Bazı yazdırma hizmetleri devre dışı bırakıldı"</string>
     <string name="print_searching_for_printers" msgid="6550424555079932867">"Yazıcılar aranıyor"</string>
     <string name="print_no_print_services" msgid="8561247706423327966">"Etkin yazıcı hizmeti yok"</string>
     <string name="print_no_printers" msgid="4869403323900054866">"Yazıcı bulunamadı"</string>
+    <string name="cannot_add_printer" msgid="7840348733668023106">"Yazıcı eklenemiyor"</string>
+    <string name="select_to_add_printers" msgid="3800709038689830974">"Yazıcı eklemek için seçin"</string>
+    <string name="enable_print_service" msgid="3482815747043533842">"Etkinleştirmek için seçin"</string>
+    <string name="enabled_services_title" msgid="7036986099096582296">"Etkin hizmetler"</string>
+    <string name="recommended_services_title" msgid="3799434882937956924">"Önerilen hizmetler"</string>
+    <string name="disabled_services_title" msgid="7313253167968363211">"Devre dışı bırakılmış hizmetler"</string>
+    <string name="all_services_title" msgid="5578662754874906455">"Tüm hizmetler"</string>
     <string name="printing_notification_title_template" msgid="295903957762447362">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> yazdırılıyor"</string>
     <string name="cancelling_notification_title_template" msgid="1821759594704703197">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> iptal ediliyor"</string>
     <string name="failed_notification_title_template" msgid="2256217208186530973">"Yazıcı hatası: <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/PrintSpooler/res/values-uk/strings.xml b/packages/PrintSpooler/res/values-uk/strings.xml
index 1082147..41051af 100644
--- a/packages/PrintSpooler/res/values-uk/strings.xml
+++ b/packages/PrintSpooler/res/values-uk/strings.xml
@@ -63,11 +63,17 @@
     </plurals>
     <string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> – <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="printer_info_desc" msgid="7181988788991581654">"Докладніше про цей принтер"</string>
-    <string name="print_services_disabled_toast" msgid="1205302482388937547">"Деякі служби друку вимкнено."</string>
-    <string name="choose_print_service" msgid="3740309762324459694">"Вибрати службу друку"</string>
+    <string name="print_services_disabled_toast" msgid="9089060734685174685">"Деякі служби друку вимкнено"</string>
     <string name="print_searching_for_printers" msgid="6550424555079932867">"Пошук принтерів"</string>
     <string name="print_no_print_services" msgid="8561247706423327966">"Немає служб друку"</string>
     <string name="print_no_printers" msgid="4869403323900054866">"Принтери не знайдено"</string>
+    <string name="cannot_add_printer" msgid="7840348733668023106">"Не можна додати принтери"</string>
+    <string name="select_to_add_printers" msgid="3800709038689830974">"Виберіть, щоб додати принтер"</string>
+    <string name="enable_print_service" msgid="3482815747043533842">"Виберіть, щоб увімкнути"</string>
+    <string name="enabled_services_title" msgid="7036986099096582296">"Увімкнені служби"</string>
+    <string name="recommended_services_title" msgid="3799434882937956924">"Рекомендовані служби"</string>
+    <string name="disabled_services_title" msgid="7313253167968363211">"Вимкнені служби"</string>
+    <string name="all_services_title" msgid="5578662754874906455">"Усі служби"</string>
     <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>
diff --git a/packages/PrintSpooler/res/values-ur-rPK/strings.xml b/packages/PrintSpooler/res/values-ur-rPK/strings.xml
index 56f1093..a94b16f 100644
--- a/packages/PrintSpooler/res/values-ur-rPK/strings.xml
+++ b/packages/PrintSpooler/res/values-ur-rPK/strings.xml
@@ -61,11 +61,17 @@
     </plurals>
     <string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="printer_info_desc" msgid="7181988788991581654">"اس پرنٹر کے بارے میں مزید معلومات"</string>
-    <string name="print_services_disabled_toast" msgid="1205302482388937547">"پرنٹ کی کچھ سروسز غیر فعال ہیں۔"</string>
-    <string name="choose_print_service" msgid="3740309762324459694">"پرنٹ سروس منتخب کریں"</string>
+    <string name="print_services_disabled_toast" msgid="9089060734685174685">"پرنٹ کی کچھ سروسز غیر فعال ہیں"</string>
     <string name="print_searching_for_printers" msgid="6550424555079932867">"پرنٹرز تلاش کر رہا ہے"</string>
     <string name="print_no_print_services" msgid="8561247706423327966">"کوئی پرنٹ سروس فعال نہیں"</string>
     <string name="print_no_printers" msgid="4869403323900054866">"کوئی پرنٹرز نہيں ملے"</string>
+    <string name="cannot_add_printer" msgid="7840348733668023106">"پرنٹرز شامل نہیں ہو سکتے"</string>
+    <string name="select_to_add_printers" msgid="3800709038689830974">"پرنٹر شامل کرنے کیلئے منتخب کریں"</string>
+    <string name="enable_print_service" msgid="3482815747043533842">"فعال کرنے کیلئے منتخب کریں"</string>
+    <string name="enabled_services_title" msgid="7036986099096582296">"فعال کردہ سروسز"</string>
+    <string name="recommended_services_title" msgid="3799434882937956924">"تجویز کردہ سروسز"</string>
+    <string name="disabled_services_title" msgid="7313253167968363211">"غیر فعال کردہ سروسز"</string>
+    <string name="all_services_title" msgid="5578662754874906455">"تمام سروسز"</string>
     <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>
diff --git a/packages/PrintSpooler/res/values-uz-rUZ/strings.xml b/packages/PrintSpooler/res/values-uz-rUZ/strings.xml
index 30b218e..ee6266f 100644
--- a/packages/PrintSpooler/res/values-uz-rUZ/strings.xml
+++ b/packages/PrintSpooler/res/values-uz-rUZ/strings.xml
@@ -61,11 +61,17 @@
     </plurals>
     <string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> – <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="printer_info_desc" msgid="7181988788991581654">"Printer haqida batafsil ma’lumot"</string>
-    <string name="print_services_disabled_toast" msgid="1205302482388937547">"Bir qancha chop etish xizmatlari o‘chirilgan."</string>
-    <string name="choose_print_service" msgid="3740309762324459694">"Chop etish xizmatini tanlang"</string>
+    <string name="print_services_disabled_toast" msgid="9089060734685174685">"Bir qancha chop etish xizmatlari o‘chirilgan"</string>
     <string name="print_searching_for_printers" msgid="6550424555079932867">"Printerlar qidirilmoqda"</string>
     <string name="print_no_print_services" msgid="8561247706423327966">"Hech qaysi chop etish xizmati yoqilmagan"</string>
     <string name="print_no_printers" msgid="4869403323900054866">"Printerlar topilmadi"</string>
+    <string name="cannot_add_printer" msgid="7840348733668023106">"Printerlarni qo‘shib bo‘lmaydi"</string>
+    <string name="select_to_add_printers" msgid="3800709038689830974">"Printer qo‘shish uchun tanlang"</string>
+    <string name="enable_print_service" msgid="3482815747043533842">"Yoqish uchun tanlang"</string>
+    <string name="enabled_services_title" msgid="7036986099096582296">"Yoqilgan xizmatlar"</string>
+    <string name="recommended_services_title" msgid="3799434882937956924">"Tavsiya etilgan xizmatlar"</string>
+    <string name="disabled_services_title" msgid="7313253167968363211">"O‘chirilgan xizmatlar"</string>
+    <string name="all_services_title" msgid="5578662754874906455">"Barcha xizmatlar"</string>
     <string name="printing_notification_title_template" msgid="295903957762447362">"Chop etilmoqda: <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> bekor qilinmoqda"</string>
     <string name="failed_notification_title_template" msgid="2256217208186530973">"Printerda xatolik: <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/PrintSpooler/res/values-vi/strings.xml b/packages/PrintSpooler/res/values-vi/strings.xml
index 32aaf63..df9e1a4 100644
--- a/packages/PrintSpooler/res/values-vi/strings.xml
+++ b/packages/PrintSpooler/res/values-vi/strings.xml
@@ -61,11 +61,17 @@
     </plurals>
     <string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="printer_info_desc" msgid="7181988788991581654">"Thông tin khác về máy in này"</string>
-    <string name="print_services_disabled_toast" msgid="1205302482388937547">"Một số dịch vụ in bị vô hiệu hóa."</string>
-    <string name="choose_print_service" msgid="3740309762324459694">"Chọn dịch vụ in"</string>
+    <string name="print_services_disabled_toast" msgid="9089060734685174685">"Một số dịch vụ in đã bị tắt"</string>
     <string name="print_searching_for_printers" msgid="6550424555079932867">"Đang tìm kiếm máy in"</string>
     <string name="print_no_print_services" msgid="8561247706423327966">"Chưa kích hoạt dịch vụ in nào"</string>
     <string name="print_no_printers" msgid="4869403323900054866">"Không tìm thấy máy in"</string>
+    <string name="cannot_add_printer" msgid="7840348733668023106">"Không thể thêm máy in"</string>
+    <string name="select_to_add_printers" msgid="3800709038689830974">"Chọn để thêm máy in"</string>
+    <string name="enable_print_service" msgid="3482815747043533842">"Chọn để bật"</string>
+    <string name="enabled_services_title" msgid="7036986099096582296">"Dịch vụ đã bật"</string>
+    <string name="recommended_services_title" msgid="3799434882937956924">"Dịch vụ được đề xuất"</string>
+    <string name="disabled_services_title" msgid="7313253167968363211">"Dịch vụ đã tắt"</string>
+    <string name="all_services_title" msgid="5578662754874906455">"Tất cả dịch vụ"</string>
     <string name="printing_notification_title_template" msgid="295903957762447362">"In <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
     <string name="cancelling_notification_title_template" msgid="1821759594704703197">"Hủy <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
     <string name="failed_notification_title_template" msgid="2256217208186530973">"Lỗi máy in <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/PrintSpooler/res/values-zh-rCN/strings.xml b/packages/PrintSpooler/res/values-zh-rCN/strings.xml
index 42cf3b1..fb30e44 100644
--- a/packages/PrintSpooler/res/values-zh-rCN/strings.xml
+++ b/packages/PrintSpooler/res/values-zh-rCN/strings.xml
@@ -61,11 +61,17 @@
     </plurals>
     <string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="printer_info_desc" msgid="7181988788991581654">"关于此打印机的更多信息"</string>
-    <string name="print_services_disabled_toast" msgid="1205302482388937547">"部分打印服务已停用。"</string>
-    <string name="choose_print_service" msgid="3740309762324459694">"选择打印服务"</string>
+    <string name="print_services_disabled_toast" msgid="9089060734685174685">"部分打印服务已停用"</string>
     <string name="print_searching_for_printers" msgid="6550424555079932867">"正在搜索打印机"</string>
     <string name="print_no_print_services" msgid="8561247706423327966">"未启用任何打印服务"</string>
     <string name="print_no_printers" msgid="4869403323900054866">"找不到打印机"</string>
+    <string name="cannot_add_printer" msgid="7840348733668023106">"无法添加打印机"</string>
+    <string name="select_to_add_printers" msgid="3800709038689830974">"选择即可添加打印机"</string>
+    <string name="enable_print_service" msgid="3482815747043533842">"选择即可启用"</string>
+    <string name="enabled_services_title" msgid="7036986099096582296">"已启用的服务"</string>
+    <string name="recommended_services_title" msgid="3799434882937956924">"推荐的服务"</string>
+    <string name="disabled_services_title" msgid="7313253167968363211">"已停用的服务"</string>
+    <string name="all_services_title" msgid="5578662754874906455">"所有服务"</string>
     <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>
diff --git a/packages/PrintSpooler/res/values-zh-rHK/strings.xml b/packages/PrintSpooler/res/values-zh-rHK/strings.xml
index 0a458ad..f7c8fc9 100644
--- a/packages/PrintSpooler/res/values-zh-rHK/strings.xml
+++ b/packages/PrintSpooler/res/values-zh-rHK/strings.xml
@@ -61,11 +61,17 @@
     </plurals>
     <string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="printer_info_desc" msgid="7181988788991581654">"此打印機詳情"</string>
-    <string name="print_services_disabled_toast" msgid="1205302482388937547">"已停用部分列印服務。"</string>
-    <string name="choose_print_service" msgid="3740309762324459694">"選擇列印服務"</string>
+    <string name="print_services_disabled_toast" msgid="9089060734685174685">"部分列印服務已停用"</string>
     <string name="print_searching_for_printers" msgid="6550424555079932867">"正在搜尋打印機"</string>
     <string name="print_no_print_services" msgid="8561247706423327966">"沒有已啟用的列印服務"</string>
     <string name="print_no_printers" msgid="4869403323900054866">"找不到打印機"</string>
+    <string name="cannot_add_printer" msgid="7840348733668023106">"無法新增印表機"</string>
+    <string name="select_to_add_printers" msgid="3800709038689830974">"選擇即可新增印表機"</string>
+    <string name="enable_print_service" msgid="3482815747043533842">"選取即可啟用"</string>
+    <string name="enabled_services_title" msgid="7036986099096582296">"已啟用的服務"</string>
+    <string name="recommended_services_title" msgid="3799434882937956924">"推薦服務"</string>
+    <string name="disabled_services_title" msgid="7313253167968363211">"已停用的服務"</string>
+    <string name="all_services_title" msgid="5578662754874906455">"所有服務"</string>
     <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>
diff --git a/packages/PrintSpooler/res/values-zh-rTW/strings.xml b/packages/PrintSpooler/res/values-zh-rTW/strings.xml
index 7a30011..aa18f3c 100644
--- a/packages/PrintSpooler/res/values-zh-rTW/strings.xml
+++ b/packages/PrintSpooler/res/values-zh-rTW/strings.xml
@@ -61,11 +61,17 @@
     </plurals>
     <string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="printer_info_desc" msgid="7181988788991581654">"查看這台印表機的詳細資訊"</string>
-    <string name="print_services_disabled_toast" msgid="1205302482388937547">"部分列印服務已停用。"</string>
-    <string name="choose_print_service" msgid="3740309762324459694">"選擇列印服務"</string>
+    <string name="print_services_disabled_toast" msgid="9089060734685174685">"已停用部分列印服務"</string>
     <string name="print_searching_for_printers" msgid="6550424555079932867">"正在搜尋印表機"</string>
     <string name="print_no_print_services" msgid="8561247706423327966">"未啟用任何列印服務"</string>
     <string name="print_no_printers" msgid="4869403323900054866">"找不到印表機"</string>
+    <string name="cannot_add_printer" msgid="7840348733668023106">"無法新增印表機"</string>
+    <string name="select_to_add_printers" msgid="3800709038689830974">"選取即可新增印表機"</string>
+    <string name="enable_print_service" msgid="3482815747043533842">"選取即可啟用"</string>
+    <string name="enabled_services_title" msgid="7036986099096582296">"已啟用的列印服務"</string>
+    <string name="recommended_services_title" msgid="3799434882937956924">"建議的列印服務"</string>
+    <string name="disabled_services_title" msgid="7313253167968363211">"已停用的列印服務"</string>
+    <string name="all_services_title" msgid="5578662754874906455">"所有列印服務"</string>
     <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>
diff --git a/packages/PrintSpooler/res/values-zu/strings.xml b/packages/PrintSpooler/res/values-zu/strings.xml
index f57b58c..9cfcb33 100644
--- a/packages/PrintSpooler/res/values-zu/strings.xml
+++ b/packages/PrintSpooler/res/values-zu/strings.xml
@@ -61,11 +61,17 @@
     </plurals>
     <string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="printer_info_desc" msgid="7181988788991581654">"Olunye ulwazi mayelana nale phrinta"</string>
-    <string name="print_services_disabled_toast" msgid="1205302482388937547">"Amanye amasevisi wokuphrinta akhutshaziwe."</string>
-    <string name="choose_print_service" msgid="3740309762324459694">"Khetha isevisi yephrinta"</string>
+    <string name="print_services_disabled_toast" msgid="9089060734685174685">"Amanye amasevisi okuphrinta akhutshaziwe"</string>
     <string name="print_searching_for_printers" msgid="6550424555079932867">"Isesha amaphrinta"</string>
     <string name="print_no_print_services" msgid="8561247706423327966">"Amasevisi ephrinta akavuliwe."</string>
     <string name="print_no_printers" msgid="4869403323900054866">"Awekho amaphrinta atholiwe"</string>
+    <string name="cannot_add_printer" msgid="7840348733668023106">"Ayikwazi ukungeza amaphrinta"</string>
+    <string name="select_to_add_printers" msgid="3800709038689830974">"Khetha ukuze ungeze iphrinta"</string>
+    <string name="enable_print_service" msgid="3482815747043533842">"Khetha ukuze unike amandla"</string>
+    <string name="enabled_services_title" msgid="7036986099096582296">"Amasevisi anikwe amandla"</string>
+    <string name="recommended_services_title" msgid="3799434882937956924">"Amasevisi anconyiwe"</string>
+    <string name="disabled_services_title" msgid="7313253167968363211">"Amasevisi akhutshaziwe"</string>
+    <string name="all_services_title" msgid="5578662754874906455">"Onke amasevisi"</string>
     <string name="printing_notification_title_template" msgid="295903957762447362">"Iphrinta i-<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
     <string name="cancelling_notification_title_template" msgid="1821759594704703197">"Ikhansela i-<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
     <string name="failed_notification_title_template" msgid="2256217208186530973">"Iphutha lephrinta ye-<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/PrintSpooler/res/values/colors.xml b/packages/PrintSpooler/res/values/colors.xml
index d1bec32..47e616e 100644
--- a/packages/PrintSpooler/res/values/colors.xml
+++ b/packages/PrintSpooler/res/values/colors.xml
@@ -22,8 +22,6 @@
 
     <color name="print_preview_background_color">#F2F1F2</color>
 
-    <color name="promoted_action_background_color">#FF80CBC4</color>
-
     <color name="material_grey_500">#ffa3a3a3</color>
 
 </resources>
diff --git a/packages/PrintSpooler/res/values/donottranslate.xml b/packages/PrintSpooler/res/values/donottranslate.xml
index 8069a1d..589043b 100644
--- a/packages/PrintSpooler/res/values/donottranslate.xml
+++ b/packages/PrintSpooler/res/values/donottranslate.xml
@@ -25,4 +25,6 @@
     <string name="mediasize_default">ISO_A4</string>
     <string name="mediasize_standard">@string/mediasize_standard_iso</string>
 
+    <string name="uri_package_details">market://details?id=%1$s</string>
+
 </resources>
diff --git a/packages/PrintSpooler/res/values/strings.xml b/packages/PrintSpooler/res/values/strings.xml
index 76292a1..4b56622 100644
--- a/packages/PrintSpooler/res/values/strings.xml
+++ b/packages/PrintSpooler/res/values/strings.xml
@@ -129,7 +129,7 @@
     <!-- Utterance to announce that the search box is hidden. This is spoken to a blind user. [CHAR LIMIT=none] -->
     <string name="print_search_box_hidden_utterance">Search box hidden</string>
 
-    <!-- Title of the action bar button to got to add a printer. [CHAR LIMIT=25] -->
+    <!-- Label of add printers button when no printers are found. [CHAR LIMIT=25] -->
     <string name="print_add_printer">Add printer</string>
 
     <!-- Title of the menu item to select a printer. [CHAR LIMIT=25] -->
@@ -151,12 +151,7 @@
     <string name="printer_info_desc">More information about this printer</string>
 
     <!-- Notification that print services as disabled. [CHAR LIMIT=50] -->
-    <string name="print_services_disabled_toast">Some print services are disabled.</string>
-
-    <!-- Add printer dialog  -->
-
-    <!-- Title for the alert dialog for selecting a print service. [CHAR LIMIT=50] -->
-    <string name="choose_print_service">Choose print service</string>
+    <string name="print_services_disabled_toast">Some print services are disabled</string>
 
     <!-- Title for the prompt shown as a placeholder if no printers are found while not searching. [CHAR LIMIT=50] -->
     <string name="print_searching_for_printers">Searching for printers</string>
@@ -167,6 +162,29 @@
     <!-- Title for the prompt shown as a placeholder if there are no printers while searching. [CHAR LIMIT=50] -->
     <string name="print_no_printers">No printers found</string>
 
+    <!-- Add printer activity -->
+
+    <!-- Subtitle for services that cannot add printers. [CHAR LIMIT=50] -->
+    <string name="cannot_add_printer">Cannot add printers</string>
+
+    <!-- Subtitle for services that can add printers. [CHAR LIMIT=50] -->
+    <string name="select_to_add_printers">Select to add printer</string>
+
+    <!-- Subtitle for disabled services. [CHAR LIMIT=50] -->
+    <string name="enable_print_service">Select to enable</string>
+
+    <!-- Header for the list of enabled print services. [CHAR LIMIT=50] -->
+    <string name="enabled_services_title">Enabled services</string>
+
+    <!-- Header for the list of recommended print services. [CHAR LIMIT=50] -->
+    <string name="recommended_services_title">Recommended services</string>
+
+    <!-- Header for the list of disabled print services. [CHAR LIMIT=50] -->
+    <string name="disabled_services_title">Disabled services</string>
+
+    <!-- Label for the list item that links to the list of all print services. [CHAR LIMIT=50] -->
+    <string name="all_services_title">All services</string>
+
     <!-- Notifications -->
 
     <!-- Template for the notification label for a printing print job. [CHAR LIMIT=25] -->
diff --git a/packages/PrintSpooler/res/values/styles.xml b/packages/PrintSpooler/res/values/styles.xml
new file mode 100644
index 0000000..1e63a67e
--- /dev/null
+++ b/packages/PrintSpooler/res/values/styles.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<resources>
+    <!-- Preference styles -->
+    <eat-comment/>
+
+    <style name="ListItemSecondary" parent="@android:style/TextAppearance.Material.Body1">
+        <item name="android:textColor">?android:attr/textColorSecondary</item>
+    </style>
+
+    <style name="ListSeparator">
+        <item name="android:layout_width">match_parent</item>
+        <item name="android:layout_height">wrap_content</item>
+        <item name="android:layout_marginTop">16dip</item>
+        <item name="android:layout_marginBottom">16dip</item>
+        <item name="android:textColor">?android:attr/colorAccent</item>
+        <item name="android:fontFamily">sans-serif-medium</item>
+        <item name="android:textSize">14sp</item>
+    </style>
+</resources>
diff --git a/packages/PrintSpooler/res/values/themes.xml b/packages/PrintSpooler/res/values/themes.xml
index 05de5b7..a968ffa 100644
--- a/packages/PrintSpooler/res/values/themes.xml
+++ b/packages/PrintSpooler/res/values/themes.xml
@@ -15,8 +15,17 @@
 -->
 
 <resources>
+    <style name="Theme.AddPrinterActivity" parent="@android:style/Theme.DeviceDefault.Light.Dialog">
+        <item name="android:listSeparatorTextViewStyle">@style/ListSeparator</item>
+        <item name="android:textAppearanceListItemSecondary">@style/ListItemSecondary</item>
+    </style>
 
-    <style name="PrintActivity" parent="@android:style/Theme.DeviceDefault">
+    <style name="Theme.SelectPrinterActivity"
+           parent="android:style/Theme.DeviceDefault.Light.DarkActionBar">
+        <item name="android:textAppearanceListItemSecondary">@style/ListItemSecondary</item>
+    </style>
+
+    <style name="Theme.PrintActivity" parent="@android:style/Theme.DeviceDefault">
         <item name="android:windowIsTranslucent">true</item>
         <item name="android:windowBackground">@android:color/transparent</item>
         <item name="android:windowContentOverlay">@null</item>
diff --git a/packages/PrintSpooler/src/com/android/printspooler/model/PageContentRepository.java b/packages/PrintSpooler/src/com/android/printspooler/model/PageContentRepository.java
index ac97ad0..f8b1343 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/model/PageContentRepository.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/model/PageContentRepository.java
@@ -862,6 +862,9 @@
                 // Take a note that the content is rendered.
                 renderedPage.state = RenderedPage.STATE_RENDERED;
 
+                // Invalidate all caches of the old state of the bitmap
+                mRenderedPage.content.invalidateSelf();
+
                 // Announce success if needed.
                 if (mCallback != null) {
                     mCallback.onPageContentAvailable(renderedPage.content);
diff --git a/packages/PrintSpooler/src/com/android/printspooler/ui/AddPrinterActivity.java b/packages/PrintSpooler/src/com/android/printspooler/ui/AddPrinterActivity.java
new file mode 100644
index 0000000..f2b3e6e
--- /dev/null
+++ b/packages/PrintSpooler/src/com/android/printspooler/ui/AddPrinterActivity.java
@@ -0,0 +1,563 @@
+/*
+ * 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.printspooler.ui;
+
+import android.annotation.IntRange;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.app.ListActivity;
+import android.app.LoaderManager;
+import android.content.ActivityNotFoundException;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.Loader;
+import android.database.DataSetObserver;
+import android.net.Uri;
+import android.os.Bundle;
+import android.print.PrintManager;
+import android.print.PrintServicesLoader;
+import android.printservice.PrintServiceInfo;
+import android.provider.Settings;
+import android.text.TextUtils;
+import android.util.Log;
+import android.util.Pair;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.Adapter;
+import android.widget.AdapterView;
+import android.widget.BaseAdapter;
+import android.widget.ImageView;
+import android.widget.TextView;
+import com.android.printspooler.R;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * This is an activity for adding a printer or. It consists of a list fed from three adapters:
+ * <ul>
+ *     <li>{@link #mEnabledServicesAdapter} for all enabled services. If a service has an {@link
+ *         PrintServiceInfo#getAddPrintersActivityName() add printer activity} this is started
+ *         when the item is clicked.</li>
+ *     <li>{@link #mDisabledServicesAdapter} for all disabled services. Once clicked the settings page
+ *         for this service is opened.</li>
+ *     <li>{@link RecommendedServicesAdapter} for a link to all services. If this item is clicked
+ *         the market app is opened to show all print services.</li>
+ * </ul>
+ */
+public class AddPrinterActivity extends ListActivity implements
+        LoaderManager.LoaderCallbacks<List<PrintServiceInfo>>,
+        AdapterView.OnItemClickListener {
+    private static final String LOG_TAG = "AddPrinterActivity";
+
+    /** Ids for the loaders */
+    private static final int LOADER_ID_ENABLED_SERVICES = 1;
+    private static final int LOADER_ID_DISABLED_SERVICES = 2;
+
+    /**
+     * The enabled services list. This is filled from the {@link #LOADER_ID_ENABLED_SERVICES}
+     * loader in {@link #onLoadFinished}.
+     */
+    private EnabledServicesAdapter mEnabledServicesAdapter;
+
+    /**
+     * The disabled services list. This is filled from the {@link #LOADER_ID_DISABLED_SERVICES}
+     * loader in {@link #onLoadFinished}.
+     */
+    private DisabledServicesAdapter mDisabledServicesAdapter;
+
+    @Override
+    protected void onCreate(@Nullable Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        setContentView(R.layout.add_printer_activity);
+
+        mEnabledServicesAdapter = new EnabledServicesAdapter();
+        mDisabledServicesAdapter = new DisabledServicesAdapter();
+
+        ArrayList<ActionAdapter> adapterList = new ArrayList<>(3);
+        adapterList.add(mEnabledServicesAdapter);
+        adapterList.add(new RecommendedServicesAdapter());
+        adapterList.add(mDisabledServicesAdapter);
+
+        setListAdapter(new CombinedAdapter(adapterList));
+
+        getListView().setOnItemClickListener(this);
+
+        getLoaderManager().initLoader(LOADER_ID_ENABLED_SERVICES, null, this);
+        getLoaderManager().initLoader(LOADER_ID_DISABLED_SERVICES, null, this);
+        // TODO: Load recommended services
+    }
+
+    @Override
+    public Loader<List<PrintServiceInfo>> onCreateLoader(int id, Bundle args) {
+        switch (id) {
+            case LOADER_ID_ENABLED_SERVICES:
+                return new PrintServicesLoader(
+                        (PrintManager) getSystemService(Context.PRINT_SERVICE), this,
+                        PrintManager.ENABLED_SERVICES);
+            case LOADER_ID_DISABLED_SERVICES:
+                return new PrintServicesLoader(
+                        (PrintManager) getSystemService(Context.PRINT_SERVICE), this,
+                        PrintManager.DISABLED_SERVICES);
+            // TODO: Load recommended services
+            default:
+                // not reached
+                return null;
+        }
+    }
+
+    @Override
+    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
+        ((ActionAdapter) getListAdapter()).performAction(position);
+    }
+
+    @Override
+    public void onLoadFinished(Loader<List<PrintServiceInfo>> loader,
+            List<PrintServiceInfo> data) {
+        switch (loader.getId()) {
+            case LOADER_ID_ENABLED_SERVICES:
+                mEnabledServicesAdapter.updateData(data);
+                break;
+            case LOADER_ID_DISABLED_SERVICES:
+                mDisabledServicesAdapter.updateData(data);
+                break;
+            // TODO: Load recommended services
+            default:
+                // not reached
+        }
+    }
+
+    @Override
+    public void onLoaderReset(Loader<List<PrintServiceInfo>> loader) {
+        if (!isFinishing()) {
+            switch (loader.getId()) {
+                case LOADER_ID_ENABLED_SERVICES:
+                    mEnabledServicesAdapter.updateData(null);
+                    break;
+                case LOADER_ID_DISABLED_SERVICES:
+                    mDisabledServicesAdapter.updateData(null);
+                    break;
+                // TODO: Reset recommended services
+                default:
+                    // not reached
+            }
+        }
+    }
+
+    /**
+     * Marks an adapter that can can perform an action for a position in it's list.
+     */
+    private abstract class ActionAdapter extends BaseAdapter {
+        /**
+         * Perform the action for a position in the list.
+         *
+         * @param position The position of the item
+         */
+        abstract void performAction(@IntRange(from = 0) int position);
+
+        @Override
+        public boolean areAllItemsEnabled() {
+            return false;
+        }
+    }
+
+    /**
+     * An adapter presenting multiple sub adapters as a single combined adapter.
+     */
+    private class CombinedAdapter extends ActionAdapter {
+        /** The adapters to combine */
+        private final @NonNull ArrayList<ActionAdapter> mAdapters;
+
+        /**
+         * Create a combined adapter.
+         *
+         * @param adapters the list of adapters to combine
+         */
+        CombinedAdapter(@NonNull ArrayList<ActionAdapter> adapters) {
+            mAdapters = adapters;
+
+            final int numAdapters = mAdapters.size();
+            for (int i = 0; i < numAdapters; i++) {
+                mAdapters.get(i).registerDataSetObserver(new DataSetObserver() {
+                    @Override
+                    public void onChanged() {
+                        notifyDataSetChanged();
+                    }
+
+                    @Override
+                    public void onInvalidated() {
+                        notifyDataSetChanged();
+                    }
+                });
+            }
+        }
+
+        @Override
+        public int getCount() {
+            int totalCount = 0;
+
+            final int numAdapters = mAdapters.size();
+            for (int i = 0; i < numAdapters; i++) {
+                totalCount += mAdapters.get(i).getCount();
+            }
+
+            return totalCount;
+        }
+
+        /**
+         * Find the sub adapter and the position in the sub-adapter the position in the combined
+         * adapter refers to.
+         *
+         * @param position The position in the combined adapter
+         *
+         * @return The pair of adapter and position in sub adapter
+         */
+        private @NonNull Pair<ActionAdapter, Integer> getSubAdapter(int position) {
+            final int numAdapters = mAdapters.size();
+            for (int i = 0; i < numAdapters; i++) {
+                ActionAdapter adapter = mAdapters.get(i);
+
+                if (position < adapter.getCount()) {
+                    return new Pair<>(adapter, position);
+                } else {
+                    position -= adapter.getCount();
+                }
+            }
+
+            throw new IllegalArgumentException("Invalid position");
+        }
+
+        @Override
+        public int getItemViewType(int position) {
+            int numLowerViewTypes = 0;
+
+            final int numAdapters = mAdapters.size();
+            for (int i = 0; i < numAdapters; i++) {
+                Adapter adapter = mAdapters.get(i);
+
+                if (position < adapter.getCount()) {
+                    return numLowerViewTypes + adapter.getItemViewType(position);
+                } else {
+                    numLowerViewTypes += adapter.getViewTypeCount();
+                    position -= adapter.getCount();
+                }
+            }
+
+            throw new IllegalArgumentException("Invalid position");
+        }
+
+        @Override
+        public int getViewTypeCount() {
+            int totalViewCount = 0;
+
+            final int numAdapters = mAdapters.size();
+            for (int i = 0; i < numAdapters; i++) {
+                totalViewCount += mAdapters.get(i).getViewTypeCount();
+            }
+
+            return totalViewCount;
+        }
+
+        @Override
+        public View getView(int position, View convertView, ViewGroup parent) {
+            Pair<ActionAdapter, Integer> realPosition = getSubAdapter(position);
+
+            return realPosition.first.getView(realPosition.second, convertView, parent);
+        }
+
+        @Override
+        public Object getItem(int position) {
+            Pair<ActionAdapter, Integer> realPosition = getSubAdapter(position);
+
+            return realPosition.first.getItem(realPosition.second);
+        }
+
+        @Override
+        public long getItemId(int position) {
+            return position;
+        }
+
+        @Override
+        public boolean isEnabled(int position) {
+            Pair<ActionAdapter, Integer> realPosition = getSubAdapter(position);
+
+            return realPosition.first.isEnabled(realPosition.second);
+        }
+
+        @Override
+        public void performAction(@IntRange(from = 0) int position) {
+            Pair<ActionAdapter, Integer> realPosition = getSubAdapter(position);
+
+            realPosition.first.performAction(realPosition.second);
+        }
+    }
+    
+    /**
+     * Superclass for all adapters that just display a list of {@link PrintServiceInfo}.
+     */
+    private abstract class PrintServiceInfoAdapter extends ActionAdapter {
+        /**
+         * Raw data of the list.
+         *
+         * @see #updateData(List)
+         */
+        private @NonNull List<PrintServiceInfo> mServices;
+
+        /**
+         * Create a new adapter.
+         */
+        PrintServiceInfoAdapter() {
+            mServices = Collections.emptyList();
+        }
+
+        /**
+         * Update the data.
+         *
+         * @param services The new raw data.
+         */
+        void updateData(@Nullable List<PrintServiceInfo> services) {
+            if (services == null || services.isEmpty()) {
+                mServices = Collections.emptyList();
+            } else {
+                mServices = services;
+            }
+
+            notifyDataSetChanged();
+        }
+
+        @Override
+        public int getViewTypeCount() {
+            return 2;
+        }
+
+        @Override
+        public int getItemViewType(int position) {
+            if (position == 0) {
+                return 0;
+            } else {
+                return 1;
+            }
+        }
+
+        @Override
+        public int getCount() {
+            if (mServices.isEmpty()) {
+                return 0;
+            } else {
+                return mServices.size() + 1;
+            }
+        }
+
+        @Override
+        public Object getItem(int position) {
+            if (position == 0) {
+                return null;
+            } else {
+                return mServices.get(position - 1);
+            }
+        }
+
+        @Override
+        public boolean isEnabled(int position) {
+            return position != 0;
+        }
+
+        @Override
+        public long getItemId(int position) {
+            return position;
+        }
+    }
+
+    /**
+     * Adapter for the enabled services.
+     */
+    private class EnabledServicesAdapter extends PrintServiceInfoAdapter {
+        @Override
+        public void performAction(@IntRange(from = 0) int position) {
+            PrintServiceInfo service = (PrintServiceInfo) getItem(position);
+            String addPrinterActivityName = service.getAddPrintersActivityName();
+
+            if (!TextUtils.isEmpty(addPrinterActivityName)) {
+                Intent intent = new Intent(Intent.ACTION_MAIN);
+                intent.setComponent(new ComponentName(service.getComponentName().getPackageName(),
+                        addPrinterActivityName));
+
+                try {
+                    startActivity(intent);
+                } catch (ActivityNotFoundException e) {
+                    Log.e(LOG_TAG, "Cannot start add printers activity", e);
+                }
+            }
+        }
+
+        @Override
+        public View getView(int position, View convertView, ViewGroup parent) {
+            if (position == 0) {
+                if (convertView == null) {
+                    convertView = getLayoutInflater().inflate(R.layout.add_printer_list_header,
+                            parent, false);
+                }
+
+                ((TextView) convertView.findViewById(R.id.text))
+                        .setText(R.string.enabled_services_title);
+
+                return convertView;
+            }
+
+            if (convertView == null) {
+                convertView = getLayoutInflater().inflate(R.layout.enabled_print_services_list_item,
+                        parent, false);
+            }
+
+            PrintServiceInfo service = (PrintServiceInfo) getItem(position);
+
+            TextView title = (TextView) convertView.findViewById(R.id.title);
+            ImageView icon = (ImageView) convertView.findViewById(R.id.icon);
+            TextView subtitle = (TextView) convertView.findViewById(R.id.subtitle);
+
+            title.setText(service.getResolveInfo().loadLabel(getPackageManager()));
+            icon.setImageDrawable(service.getResolveInfo().loadIcon(getPackageManager()));
+
+            if (TextUtils.isEmpty(service.getAddPrintersActivityName())) {
+                subtitle.setText(getString(R.string.cannot_add_printer));
+            } else {
+                subtitle.setText(getString(R.string.select_to_add_printers));
+            }
+
+            return convertView;
+        }
+    }
+
+    /**
+     * Adapter for the disabled services.
+     */
+    private class DisabledServicesAdapter extends PrintServiceInfoAdapter {
+        @Override
+        public void performAction(@IntRange(from = 0) int position) {
+            ((PrintManager) getSystemService(Context.PRINT_SERVICE)).setPrintServiceEnabled(
+                    ((PrintServiceInfo) getItem(position)).getComponentName(), true);
+        }
+
+        @Override
+        public View getView(int position, View convertView, ViewGroup parent) {
+            if (position == 0) {
+                if (convertView == null) {
+                    convertView = getLayoutInflater().inflate(R.layout.add_printer_list_header,
+                            parent, false);
+                }
+
+                ((TextView) convertView.findViewById(R.id.text))
+                        .setText(R.string.disabled_services_title);
+
+                return convertView;
+            }
+
+            if (convertView == null) {
+                convertView = getLayoutInflater().inflate(
+                        R.layout.disabled_print_services_list_item, parent, false);
+            }
+
+            PrintServiceInfo service = (PrintServiceInfo) getItem(position);
+
+            TextView title = (TextView) convertView.findViewById(R.id.title);
+            ImageView icon = (ImageView) convertView.findViewById(R.id.icon);
+
+            title.setText(service.getResolveInfo().loadLabel(getPackageManager()));
+            icon.setImageDrawable(service.getResolveInfo().loadIcon(getPackageManager()));
+
+            return convertView;
+        }
+    }
+
+    /**
+     * Adapter for the recommended services.
+     */
+    private class RecommendedServicesAdapter extends ActionAdapter {
+        @Override
+        public int getCount() {
+            return 2;
+        }
+
+        @Override
+        public int getViewTypeCount() {
+            return 2;
+        }
+
+        @Override
+        public int getItemViewType(int position) {
+            if (position == 0) {
+                return 0;
+            } else {
+                return 1;
+            }
+        }
+
+        @Override
+        public Object getItem(int position) {
+            return null;
+        }
+
+        @Override
+        public long getItemId(int position) {
+            return position;
+        }
+
+        @Override
+        public View getView(int position, View convertView, ViewGroup parent) {
+            if (position == 0) {
+                if (convertView == null) {
+                    convertView = getLayoutInflater().inflate(R.layout.add_printer_list_header,
+                            parent, false);
+                }
+
+                ((TextView) convertView.findViewById(R.id.text))
+                        .setText(R.string.recommended_services_title);
+
+                return convertView;
+            }
+
+            if (convertView == null) {
+                convertView = getLayoutInflater().inflate(R.layout.all_print_services_list_item,
+                        parent, false);
+            }
+
+            return convertView;
+        }
+
+        @Override
+        public boolean isEnabled(int position) {
+            return position != 0;
+        }
+
+        @Override
+        public void performAction(@IntRange(from = 0) int position) {
+            String searchUri = Settings.Secure
+                    .getString(getContentResolver(), Settings.Secure.PRINT_SERVICE_SEARCH_URI);
+
+            if (searchUri != null) {
+                try {
+                    startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(searchUri)));
+                } catch (ActivityNotFoundException e) {
+                    Log.e(LOG_TAG, "Cannot start market", e);
+                }
+            }
+        }
+    }
+}
diff --git a/packages/PrintSpooler/src/com/android/printspooler/ui/FusedPrintersProvider.java b/packages/PrintSpooler/src/com/android/printspooler/ui/FusedPrintersProvider.java
index 46a2098..3b5513a 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/ui/FusedPrintersProvider.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/ui/FusedPrintersProvider.java
@@ -16,7 +16,10 @@
 
 package com.android.printspooler.ui;
 
+import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.app.Activity;
+import android.app.LoaderManager;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Loader;
@@ -28,9 +31,11 @@
 import android.location.LocationRequest;
 import android.os.AsyncTask;
 import android.os.Bundle;
+import android.os.Handler;
 import android.os.Looper;
 import android.os.SystemClock;
 import android.print.PrintManager;
+import android.print.PrintServicesLoader;
 import android.print.PrinterDiscoverySession;
 import android.print.PrinterDiscoverySession.OnPrintersChangeListener;
 import android.print.PrinterId;
@@ -127,11 +132,11 @@
         }
     }
 
-    public FusedPrintersProvider(Context context) {
-        super(context);
+    public FusedPrintersProvider(Activity activity, int internalLoaderId) {
+        super(activity);
         mLocationLock = new Object();
-        mPersistenceManager = new PersistenceManager(context);
-        mLocationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
+        mPersistenceManager = new PersistenceManager(activity, internalLoaderId);
+        mLocationManager = (LocationManager) activity.getSystemService(Context.LOCATION_SERVICE);
     }
 
     public void addHistoricalPrinter(PrinterInfo printer) {
@@ -383,7 +388,6 @@
         mPrinters.clear();
         if (mDiscoverySession != null) {
             mDiscoverySession.destroy();
-            mDiscoverySession = null;
         }
     }
 
@@ -499,7 +503,8 @@
         updatePrinters(mDiscoverySession.getPrinters(), newFavoritePrinters, getCurrentLocation());
     }
 
-    private final class PersistenceManager {
+    private final class PersistenceManager implements
+            LoaderManager.LoaderCallbacks<List<PrintServiceInfo>> {
         private static final String PERSIST_FILE_NAME = "printer_history.xml";
 
         private static final String TAG_PRINTERS = "printers";
@@ -520,6 +525,15 @@
 
         private final AtomicFile mStatePersistFile;
 
+        /**
+         * Whether the enabled print services have been updated since last time the history was
+         * read.
+         */
+        private boolean mAreEnabledServicesUpdated;
+
+        /** The enabled services read when they were last updated */
+        private @NonNull List<PrintServiceInfo> mEnabledServices;
+
         private List<Pair<PrinterInfo, Location>> mHistoricalPrinters = new ArrayList<>();
 
         private boolean mReadHistoryCompleted;
@@ -528,9 +542,52 @@
 
         private volatile long mLastReadHistoryTimestamp;
 
-        private PersistenceManager(Context context) {
-            mStatePersistFile = new AtomicFile(new File(context.getFilesDir(),
+        private PersistenceManager(final Activity activity, final int internalLoaderId) {
+            mStatePersistFile = new AtomicFile(new File(activity.getFilesDir(),
                     PERSIST_FILE_NAME));
+
+            // Initialize enabled services to make sure they are set are the read task might be done
+            // before the loader updated the services the first time.
+            mEnabledServices = ((PrintManager) activity
+                    .getSystemService(Context.PRINT_SERVICE))
+                    .getPrintServices(PrintManager.ENABLED_SERVICES);
+
+            mAreEnabledServicesUpdated = true;
+
+            // Cannot start a loader while starting another, hence delay this loader
+            (new Handler(activity.getMainLooper())).post(new Runnable() {
+                @Override
+                public void run() {
+                    activity.getLoaderManager().initLoader(internalLoaderId, null,
+                            PersistenceManager.this);
+                }
+            });
+        }
+
+
+        @Override
+        public Loader<List<PrintServiceInfo>> onCreateLoader(int id, Bundle args) {
+            return new PrintServicesLoader(
+                    (PrintManager) getContext().getSystemService(Context.PRINT_SERVICE),
+                    getContext(), PrintManager.ENABLED_SERVICES);
+        }
+
+        @Override
+        public void onLoadFinished(Loader<List<PrintServiceInfo>> loader,
+                List<PrintServiceInfo> services) {
+            mAreEnabledServicesUpdated = true;
+            mEnabledServices = services;
+
+            // Ask the fused printer provider to reload which will cause the persistence manager to
+            // reload the history and reconsider the enabled services.
+            if (isStarted()) {
+                forceLoad();
+            }
+        }
+
+        @Override
+        public void onLoaderReset(Loader<List<PrintServiceInfo>> loader) {
+            // no data is cached
         }
 
         public boolean isReadHistoryInProgress() {
@@ -644,7 +701,8 @@
         }
 
         public boolean isHistoryChanged() {
-            return mLastReadHistoryTimestamp != mStatePersistFile.getBaseFile().lastModified();
+            return mAreEnabledServicesUpdated ||
+                    mLastReadHistoryTimestamp != mStatePersistFile.getBaseFile().lastModified();
         }
 
         /**
@@ -738,19 +796,15 @@
                 }
 
                 // Ignore printer records whose target services are not enabled.
-                PrintManager printManager = (PrintManager) getContext()
-                        .getSystemService(Context.PRINT_SERVICE);
-                List<PrintServiceInfo> services = printManager
-                        .getEnabledPrintServices();
-
                 Set<ComponentName> enabledComponents = new ArraySet<>();
-                final int installedServiceCount = services.size();
+                final int installedServiceCount = mEnabledServices.size();
                 for (int i = 0; i < installedServiceCount; i++) {
-                    ServiceInfo serviceInfo = services.get(i).getResolveInfo().serviceInfo;
+                    ServiceInfo serviceInfo = mEnabledServices.get(i).getResolveInfo().serviceInfo;
                     ComponentName componentName = new ComponentName(
                             serviceInfo.packageName, serviceInfo.name);
                     enabledComponents.add(componentName);
                 }
+                mAreEnabledServicesUpdated = false;
 
                 final int printerCount = printers.size();
                 for (int i = printerCount - 1; i >= 0; i--) {
diff --git a/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java b/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java
index 64f5cc6..ad4823e 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java
@@ -22,11 +22,13 @@
 import android.app.DialogFragment;
 import android.app.Fragment;
 import android.app.FragmentTransaction;
+import android.app.LoaderManager;
 import android.content.ActivityNotFoundException;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.DialogInterface;
 import android.content.Intent;
+import android.content.Loader;
 import android.content.ServiceConnection;
 import android.content.SharedPreferences;
 import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
@@ -51,10 +53,12 @@
 import android.print.PrintDocumentInfo;
 import android.print.PrintJobInfo;
 import android.print.PrintManager;
+import android.print.PrintServicesLoader;
 import android.print.PrinterCapabilitiesInfo;
 import android.print.PrinterId;
 import android.print.PrinterInfo;
 import android.printservice.PrintService;
+import android.printservice.PrintServiceInfo;
 import android.provider.DocumentsContract;
 import android.text.Editable;
 import android.text.TextUtils;
@@ -94,7 +98,6 @@
 import com.android.printspooler.util.MediaSizeUtils;
 import com.android.printspooler.util.MediaSizeUtils.MediaSizeComparator;
 import com.android.printspooler.util.PageRangeUtils;
-import com.android.printspooler.util.PrintOptionUtils;
 import com.android.printspooler.widget.PrintContentView;
 import com.android.printspooler.widget.PrintContentView.OptionsStateChangeListener;
 import com.android.printspooler.widget.PrintContentView.OptionsStateController;
@@ -113,12 +116,14 @@
 import java.util.Collection;
 import java.util.Collections;
 import java.util.List;
+import java.util.Objects;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
 public class PrintActivity extends Activity implements RemotePrintDocument.UpdateResultCallbacks,
         PrintErrorFragment.OnActionListener, PageAdapter.ContentCallbacks,
-        OptionsStateChangeListener, OptionsStateController {
+        OptionsStateChangeListener, OptionsStateController,
+        LoaderManager.LoaderCallbacks<List<PrintServiceInfo>> {
     private static final String LOG_TAG = "PrintActivity";
 
     private static final boolean DEBUG = false;
@@ -129,6 +134,10 @@
 
     private static final String HAS_PRINTED_PREF = "has_printed";
 
+    private static final int LOADER_ID_ENABLED_PRINT_SERVICES = 1;
+    private static final int LOADER_ID_PRINT_REGISTRY = 2;
+    private static final int LOADER_ID_PRINT_REGISTRY_INT = 3;
+
     private static final int ORIENTATION_PORTRAIT = 0;
     private static final int ORIENTATION_LANDSCAPE = 1;
 
@@ -139,7 +148,7 @@
     private static final int DEST_ADAPTER_MAX_ITEM_COUNT = 9;
 
     private static final int DEST_ADAPTER_ITEM_ID_SAVE_AS_PDF = Integer.MAX_VALUE;
-    private static final int DEST_ADAPTER_ITEM_ID_ALL_PRINTERS = Integer.MAX_VALUE - 1;
+    private static final int DEST_ADAPTER_ITEM_ID_MORE = Integer.MAX_VALUE - 1;
 
     private static final int STATE_INITIALIZING = 0;
     private static final int STATE_CONFIGURING = 1;
@@ -236,6 +245,15 @@
 
     private int mUiState = UI_STATE_PREVIEW;
 
+    /** Observer for changes to the printers */
+    private PrintersObserver mPrintersObserver;
+
+    /** Advances options activity name for current printer */
+    private ComponentName mAdvancedPrintOptionsActivity;
+
+    /** Whether at least one print services is enabled or not */
+    private boolean mArePrintServicesEnabled;
+
     @Override
     public void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
@@ -275,6 +293,8 @@
                 }
             }
         });
+
+        getLoaderManager().initLoader(LOADER_ID_ENABLED_PRINT_SERVICES, null, this);
     }
 
     private void onConnectedToPrintSpooler(final IBinder documentAdapter) {
@@ -289,7 +309,7 @@
             public void run() {
                 onPrinterRegistryReady(documentAdapter);
             }
-        });
+        }, LOADER_ID_PRINT_REGISTRY, LOADER_ID_PRINT_REGISTRY_INT);
     }
 
     private void onPrinterRegistryReady(IBinder documentAdapter) {
@@ -713,15 +733,12 @@
     }
 
     private void startAdvancedPrintOptionsActivity(PrinterInfo printer) {
-        ComponentName serviceName = printer.getId().getServiceName();
-
-        String activityName = PrintOptionUtils.getAdvancedOptionsActivityName(this, serviceName);
-        if (TextUtils.isEmpty(activityName)) {
+        if (mAdvancedPrintOptionsActivity == null) {
             return;
         }
 
         Intent intent = new Intent(Intent.ACTION_MAIN);
-        intent.setComponent(new ComponentName(serviceName.getPackageName(), activityName));
+        intent.setComponent(mAdvancedPrintOptionsActivity);
 
         List<ResolveInfo> resolvedActivities = getPackageManager()
                 .queryIntentActivities(intent, 0);
@@ -731,7 +748,10 @@
 
         // The activity is a component name, therefore it is one or none.
         if (resolvedActivities.get(0).activityInfo.exported) {
-            intent.putExtra(PrintService.EXTRA_PRINT_JOB_INFO, mPrintJob);
+            PrintJobInfo.Builder printJobBuilder = new PrintJobInfo.Builder(mPrintJob);
+            printJobBuilder.setPages(mSelectedPages);
+
+            intent.putExtra(PrintService.EXTRA_PRINT_JOB_INFO, printJobBuilder.build());
             intent.putExtra(PrintService.EXTRA_PRINTER_INFO, printer);
             intent.putExtra(PrintService.EXTRA_PRINT_DOCUMENT_INFO,
                     mPrintedDocument.getDocumentInfo().info);
@@ -759,10 +779,14 @@
         // Take the advanced options without interpretation.
         mPrintJob.setAdvancedOptions(printJobInfo.getAdvancedOptions());
 
-        // Take copies without interpretation as the advanced print dialog
-        // cannot create a print job info with invalid copies.
-        mCopiesEditText.setText(String.valueOf(printJobInfo.getCopies()));
-        mPrintJob.setCopies(printJobInfo.getCopies());
+        if (printJobInfo.getCopies() < 1) {
+            Log.w(LOG_TAG, "Cannot apply return value from advanced options activity. Copies " +
+                    "must be 1 or more. Actual value is: " + printJobInfo.getCopies() + ". " +
+                    "Ignoring.");
+        } else {
+            mCopiesEditText.setText(String.valueOf(printJobInfo.getCopies()));
+            mPrintJob.setCopies(printJobInfo.getCopies());
+        }
 
         PrintAttributes currAttributes = mPrintJob.getAttributes();
         PrintAttributes newAttributes = printJobInfo.getAttributes();
@@ -771,7 +795,7 @@
             // Take the media size only if the current printer supports is.
             MediaSize oldMediaSize = currAttributes.getMediaSize();
             MediaSize newMediaSize = newAttributes.getMediaSize();
-            if (!oldMediaSize.equals(newMediaSize)) {
+            if (newMediaSize != null && !oldMediaSize.equals(newMediaSize)) {
                 final int mediaSizeCount = mMediaSizeSpinnerAdapter.getCount();
                 MediaSize newMediaSizePortrait = newAttributes.getMediaSize().asPortrait();
                 for (int i = 0; i < mediaSizeCount; i++) {
@@ -1184,7 +1208,8 @@
         mCopiesEditText.addTextChangedListener(new EditTextWatcher());
 
         // Destination.
-        mDestinationSpinnerAdapter.registerDataSetObserver(new PrintersObserver());
+        mPrintersObserver = new PrintersObserver();
+        mDestinationSpinnerAdapter.registerDataSetObserver(mPrintersObserver);
         mDestinationSpinner = (Spinner) findViewById(R.id.destination_spinner);
         mDestinationSpinner.setAdapter(mDestinationSpinnerAdapter);
         mDestinationSpinner.setOnItemSelectedListener(itemSelectedListener);
@@ -1272,6 +1297,59 @@
         }
     }
 
+    @Override
+    public Loader<List<PrintServiceInfo>> onCreateLoader(int id, Bundle args) {
+        return new PrintServicesLoader((PrintManager) getSystemService(Context.PRINT_SERVICE), this,
+                PrintManager.ENABLED_SERVICES);
+    }
+
+    @Override
+    public void onLoadFinished(Loader<List<PrintServiceInfo>> loader,
+            List<PrintServiceInfo> services) {
+        ComponentName newAdvancedPrintOptionsActivity = null;
+        if (mCurrentPrinter != null && services != null) {
+            final int numServices = services.size();
+            for (int i = 0; i < numServices; i++) {
+                PrintServiceInfo service = services.get(i);
+
+                if (service.getComponentName().equals(mCurrentPrinter.getId().getServiceName())) {
+                    String advancedOptionsActivityName = service.getAdvancedOptionsActivityName();
+
+                    if (!TextUtils.isEmpty(advancedOptionsActivityName)) {
+                        newAdvancedPrintOptionsActivity = new ComponentName(
+                                service.getComponentName().getPackageName(),
+                                advancedOptionsActivityName);
+
+                        break;
+                    }
+                }
+            }
+        }
+
+        if (!Objects.equals(newAdvancedPrintOptionsActivity, mAdvancedPrintOptionsActivity)) {
+            mAdvancedPrintOptionsActivity = newAdvancedPrintOptionsActivity;
+            updateOptionsUi();
+        }
+
+        boolean newArePrintServicesEnabled = services != null && !services.isEmpty();
+        if (mArePrintServicesEnabled != newArePrintServicesEnabled) {
+            mArePrintServicesEnabled = newArePrintServicesEnabled;
+
+            // Reload mDestinationSpinnerAdapter as mArePrintServicesEnabled changed and the adapter
+            // reads that in DestinationAdapter#getMoreItemTitle
+            if (mDestinationSpinnerAdapter != null) {
+                mDestinationSpinnerAdapter.notifyDataSetChanged();
+            }
+        }
+    }
+
+    @Override
+    public void onLoaderReset(Loader<List<PrintServiceInfo>> loader) {
+        if (!isFinishing()) {
+            onLoadFinished(loader, null);
+        }
+    }
+
     /**
      * A dialog that asks the user to approve a {@link PrintService}. This dialog is automatically
      * dismissed if the same {@link PrintService} gets approved by another
@@ -1711,9 +1789,7 @@
         }
 
         // Advanced print options
-        ComponentName serviceName = mCurrentPrinter.getId().getServiceName();
-        if (!TextUtils.isEmpty(PrintOptionUtils.getAdvancedOptionsActivityName(
-                this, serviceName))) {
+        if (mAdvancedPrintOptionsActivity != null) {
             mMoreOptionsButton.setVisibility(View.VISIBLE);
             mMoreOptionsButton.setEnabled(true);
         } else {
@@ -1962,6 +2038,10 @@
             mPrinterRegistry.setTrackedPrinter(null);
         }
 
+        if (mPrintersObserver != null) {
+            mDestinationSpinnerAdapter.unregisterDataSetObserver(mPrintersObserver);
+        }
+
         if (mState != STATE_INITIALIZING) {
             mProgressMessageController.cancel();
             mSpoolerProvider.destroy();
@@ -2201,14 +2281,14 @@
                 if (position == 0) {
                     return DEST_ADAPTER_ITEM_ID_SAVE_AS_PDF;
                 } else if (position == 1) {
-                    return DEST_ADAPTER_ITEM_ID_ALL_PRINTERS;
+                    return DEST_ADAPTER_ITEM_ID_MORE;
                 }
             } else {
                 if (position == 1) {
                     return DEST_ADAPTER_ITEM_ID_SAVE_AS_PDF;
                 }
                 if (position == getCount() - 1) {
-                    return DEST_ADAPTER_ITEM_ID_ALL_PRINTERS;
+                    return DEST_ADAPTER_ITEM_ID_MORE;
                 }
             }
             return position;
@@ -2221,6 +2301,14 @@
             return view;
         }
 
+        private String getMoreItemTitle() {
+            if (mArePrintServicesEnabled) {
+                return getString(R.string.all_printers);
+            } else {
+                return getString(R.string.print_add_printer);
+            }
+        }
+
         @Override
         public View getView(int position, View convertView, ViewGroup parent) {
             if (mShowDestinationPrompt) {
@@ -2249,7 +2337,7 @@
                     title = printerHolder.printer.getName();
                     icon = getResources().getDrawable(R.drawable.ic_menu_savetopdf, null);
                 } else if (position == 1) {
-                    title = getString(R.string.all_printers);
+                    title = getMoreItemTitle();
                 }
             } else {
                 if (position == 1 && getPdfPrinter() != null) {
@@ -2257,7 +2345,7 @@
                     title = printerHolder.printer.getName();
                     icon = getResources().getDrawable(R.drawable.ic_menu_savetopdf, null);
                 } else if (position == getCount() - 1) {
-                    title = getString(R.string.all_printers);
+                    title = getMoreItemTitle();
                 } else {
                     PrinterHolder printerHolder = (PrinterHolder) getItem(position);
                     PrinterInfo printInfo = printerHolder.printer;
@@ -2292,7 +2380,7 @@
                 }
                 iconView.setImageDrawable(icon);
             } else {
-                iconView.setVisibility(View.GONE);
+                iconView.setVisibility(View.INVISIBLE);
             }
 
             return convertView;
@@ -2337,6 +2425,7 @@
                 PrinterInfo updatedPrinter = newPrintersMap.remove(oldPrinterId);
                 if (updatedPrinter != null) {
                     printerHolder.printer = updatedPrinter;
+                    printerHolder.removed = false;
                 } else {
                     printerHolder.removed = true;
                 }
@@ -2442,6 +2531,7 @@
             PrinterCapabilitiesInfo oldCapab = oldPrinterState.getCapabilities();
             PrinterCapabilitiesInfo newCapab = newPrinterState.getCapabilities();
 
+            final boolean hadCabab = oldCapab != null;
             final boolean hasCapab = newCapab != null;
             final boolean gotCapab = oldCapab == null && newCapab != null;
             final boolean lostCapab = oldCapab != null && newCapab == null;
@@ -2460,23 +2550,31 @@
 
             mCurrentPrinter = newPrinterState;
 
-            if ((isActive && gotCapab) || (becameActive && hasCapab)) {
-                if (hasCapab && capabChanged) {
-                    updatePrintAttributesFromCapabilities(newCapab);
-                    updatePrintPreviewController(false);
-                }
-                onPrinterAvailable(newPrinterState);
-            } else if ((becameInactive && hasCapab) || (isActive && lostCapab)) {
-                onPrinterUnavailable(newPrinterState);
-            }
-
             final boolean updateNeeded = ((capabChanged && hasCapab && isActive)
                     || (becameActive && hasCapab) || (isActive && gotCapab));
 
+            if (capabChanged && hasCapab) {
+                updatePrintAttributesFromCapabilities(newCapab);
+            }
+
+            if (updateNeeded) {
+                updatePrintPreviewController(false);
+            }
+
+            if ((isActive && gotCapab) || (becameActive && hasCapab)) {
+                onPrinterAvailable(newPrinterState);
+            } else if ((becameInactive && hadCabab) || (isActive && lostCapab)) {
+                onPrinterUnavailable(newPrinterState);
+            }
+
             if (updateNeeded && canUpdateDocument()) {
                 updateDocument(false);
             }
 
+            // Force a reload of the enabled print services to update mAdvancedPrintOptionsActivity
+            // in onLoadFinished();
+            getLoaderManager().getLoader(LOADER_ID_ENABLED_PRINT_SERVICES).forceLoad();
+
             updateOptionsUi();
             updateSummary();
         }
@@ -2502,7 +2600,7 @@
                     return;
                 }
 
-                if (id == DEST_ADAPTER_ITEM_ID_ALL_PRINTERS) {
+                if (id == DEST_ADAPTER_ITEM_ID_MORE) {
                     startSelectPrinterActivity();
                     return;
                 }
@@ -2536,6 +2634,10 @@
                 }
 
                 mPrinterAvailabilityDetector.updatePrinter(currentPrinter);
+
+                // Force a reload of the enabled print services to update
+                // mAdvancedPrintOptionsActivity in onLoadFinished();
+                getLoaderManager().getLoader(LOADER_ID_ENABLED_PRINT_SERVICES).forceLoad();
             } else if (spinner == mMediaSizeSpinner) {
                 SpinnerItem<MediaSize> mediaItem = mMediaSizeSpinnerAdapter.getItem(position);
                 PrintAttributes attributes = mPrintJob.getAttributes();
diff --git a/packages/PrintSpooler/src/com/android/printspooler/ui/PrinterRegistry.java b/packages/PrintSpooler/src/com/android/printspooler/ui/PrinterRegistry.java
index 6d60bb8..86366dd 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/ui/PrinterRegistry.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/ui/PrinterRegistry.java
@@ -33,7 +33,7 @@
 
 public class PrinterRegistry {
 
-    private static final int LOADER_ID_PRINTERS_LOADER = 1;
+    private final int mLoaderId;
 
     private final Activity mActivity;
 
@@ -52,12 +52,17 @@
         public void onPrintersInvalid();
     }
 
-    public PrinterRegistry(Activity activity, Runnable readyCallback) {
+    public PrinterRegistry(Activity activity, Runnable readyCallback, int loaderId,
+            int internalLoaderId) {
+        mLoaderId = loaderId;
         mActivity = activity;
         mReadyCallback = readyCallback;
         mHandler = new MyHandler(activity.getMainLooper());
-        activity.getLoaderManager().initLoader(LOADER_ID_PRINTERS_LOADER,
-                null, mLoaderCallbacks);
+
+        Bundle loaderData = new Bundle(1);
+        loaderData.putInt(null, internalLoaderId);
+
+        activity.getLoaderManager().initLoader(loaderId, loaderData, mLoaderCallbacks);
     }
 
     public void setOnPrintersChangeListener(OnPrintersChangeListener listener) {
@@ -106,7 +111,7 @@
     }
 
     private FusedPrintersProvider getPrinterProvider() {
-        Loader<?> loader = mActivity.getLoaderManager().getLoader(LOADER_ID_PRINTERS_LOADER);
+        Loader<?> loader = mActivity.getLoaderManager().getLoader(mLoaderId);
         return (FusedPrintersProvider) loader;
     }
 
@@ -114,38 +119,34 @@
             new LoaderCallbacks<List<PrinterInfo>>() {
         @Override
         public void onLoaderReset(Loader<List<PrinterInfo>> loader) {
-            if (loader.getId() == LOADER_ID_PRINTERS_LOADER) {
-                mPrinters.clear();
-                if (mOnPrintersChangeListener != null) {
-                    // Post a message as we are in onLoadFinished and certain operations
-                    // are not allowed in this callback, such as fragment transactions.
-                    // Clients should not handle this explicitly.
-                    mHandler.obtainMessage(MyHandler.MSG_PRINTERS_INVALID,
-                            mOnPrintersChangeListener).sendToTarget();
-                }
+            mPrinters.clear();
+            if (mOnPrintersChangeListener != null) {
+                // Post a message as we are in onLoadFinished and certain operations
+                // are not allowed in this callback, such as fragment transactions.
+                // Clients should not handle this explicitly.
+                mHandler.obtainMessage(MyHandler.MSG_PRINTERS_INVALID,
+                        mOnPrintersChangeListener).sendToTarget();
             }
         }
 
         // LoaderCallbacks#onLoadFinished
         @Override
         public void onLoadFinished(Loader<List<PrinterInfo>> loader, List<PrinterInfo> printers) {
-            if (loader.getId() == LOADER_ID_PRINTERS_LOADER) {
-                mPrinters.clear();
-                mPrinters.addAll(printers);
-                if (mOnPrintersChangeListener != null) {
-                    // Post a message as we are in onLoadFinished and certain operations
-                    // are not allowed in this callback, such as fragment transactions.
-                    // Clients should not handle this explicitly.
-                    SomeArgs args = SomeArgs.obtain();
-                    args.arg1 = mOnPrintersChangeListener;
-                    args.arg2 = printers;
-                    mHandler.obtainMessage(MyHandler.MSG_PRINTERS_CHANGED, args).sendToTarget();
-                }
-                if (!mReady) {
-                    mReady = true;
-                    if (mReadyCallback != null) {
-                        mReadyCallback.run();
-                    }
+            mPrinters.clear();
+            mPrinters.addAll(printers);
+            if (mOnPrintersChangeListener != null) {
+                // Post a message as we are in onLoadFinished and certain operations
+                // are not allowed in this callback, such as fragment transactions.
+                // Clients should not handle this explicitly.
+                SomeArgs args = SomeArgs.obtain();
+                args.arg1 = mOnPrintersChangeListener;
+                args.arg2 = printers;
+                mHandler.obtainMessage(MyHandler.MSG_PRINTERS_CHANGED, args).sendToTarget();
+            }
+            if (!mReady) {
+                mReady = true;
+                if (mReadyCallback != null) {
+                    mReadyCallback.run();
                 }
             }
         }
@@ -153,10 +154,7 @@
         // LoaderCallbacks#onCreateLoader
         @Override
         public Loader<List<PrinterInfo>> onCreateLoader(int id, Bundle args) {
-            if (id == LOADER_ID_PRINTERS_LOADER) {
-                return new FusedPrintersProvider(mActivity);
-            }
-            return null;
+            return new FusedPrintersProvider(mActivity, args.getInt(null));
         }
     };
 
diff --git a/packages/PrintSpooler/src/com/android/printspooler/ui/SelectPrinterActivity.java b/packages/PrintSpooler/src/com/android/printspooler/ui/SelectPrinterActivity.java
index 4f7624a..e53a522 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/ui/SelectPrinterActivity.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/ui/SelectPrinterActivity.java
@@ -17,31 +17,18 @@
 package com.android.printspooler.ui;
 
 import android.app.Activity;
-import android.app.AlertDialog;
-import android.app.Dialog;
-import android.app.DialogFragment;
-import android.app.Fragment;
-import android.app.FragmentTransaction;
-import android.content.ActivityNotFoundException;
-import android.content.ComponentName;
+import android.app.LoaderManager;
 import android.content.Context;
-import android.content.DialogInterface;
 import android.content.Intent;
 import android.content.IntentSender.SendIntentException;
-import android.content.pm.ActivityInfo;
+import android.content.Loader;
 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.database.ContentObserver;
 import android.database.DataSetObserver;
 import android.graphics.drawable.Drawable;
-import android.graphics.drawable.Icon;
-import android.net.Uri;
 import android.os.Bundle;
-import android.os.Handler;
 import android.print.PrintManager;
+import android.print.PrintServicesLoader;
 import android.print.PrinterId;
 import android.print.PrinterInfo;
 import android.printservice.PrintServiceInfo;
@@ -59,17 +46,16 @@
 import android.view.accessibility.AccessibilityManager;
 import android.widget.AdapterView;
 import android.widget.AdapterView.AdapterContextMenuInfo;
-import android.widget.ArrayAdapter;
 import android.widget.BaseAdapter;
 import android.widget.Filter;
 import android.widget.Filterable;
 import android.widget.ImageView;
+import android.widget.LinearLayout;
 import android.widget.ListView;
 import android.widget.SearchView;
 import android.widget.TextView;
 import android.widget.Toast;
 
-import com.android.internal.content.PackageMonitor;
 import com.android.printspooler.R;
 
 import java.util.ArrayList;
@@ -78,35 +64,33 @@
 /**
  * This is an activity for selecting a printer.
  */
-public final class SelectPrinterActivity extends Activity {
+public final class SelectPrinterActivity extends Activity implements
+        LoaderManager.LoaderCallbacks<List<PrintServiceInfo>> {
 
     private static final String LOG_TAG = "SelectPrinterFragment";
 
+    private static final int LOADER_ID_PRINT_REGISTRY = 1;
+    private static final int LOADER_ID_PRINT_REGISTRY_INT = 2;
+    private static final int LOADER_ID_ENABLED_PRINT_SERVICES = 3;
+
     public static final String INTENT_EXTRA_PRINTER_ID = "INTENT_EXTRA_PRINTER_ID";
 
-    private static final String FRAGMENT_TAG_ADD_PRINTER_DIALOG =
-            "FRAGMENT_TAG_ADD_PRINTER_DIALOG";
-
-    private static final String FRAGMENT_ARGUMENT_PRINT_SERVICE_INFOS =
-            "FRAGMENT_ARGUMENT_PRINT_SERVICE_INFOS";
-
     private static final String EXTRA_PRINTER_ID = "EXTRA_PRINTER_ID";
 
+    private static final String KEY_NOT_FIRST_CREATE = "KEY_NOT_FIRST_CREATE";
+
     /** If there are any enabled print services */
     private boolean mHasEnabledPrintServices;
 
-    private final ArrayList<PrintServiceInfo> mAddPrinterServices =
-            new ArrayList<>();
-
     private PrinterRegistry mPrinterRegistry;
 
     private ListView mListView;
 
     private AnnounceFilterResult mAnnounceFilterResult;
 
-    /** Monitor if new print services get enabled or disabled */
-    private ContentObserver mPrintServicesDisabledObserver;
-    private PackageMonitor mPackageObserver;
+    private void startAddPrinterActivity() {
+        startActivity(new Intent(this, AddPrinterActivity.class));
+    }
 
     @Override
     public void onCreate(Bundle savedInstanceState) {
@@ -115,7 +99,8 @@
 
         setContentView(R.layout.select_printer_activity);
 
-        mPrinterRegistry = new PrinterRegistry(this, null);
+        mPrinterRegistry = new PrinterRegistry(this, null, LOADER_ID_PRINT_REGISTRY,
+                LOADER_ID_PRINT_REGISTRY_INT);
 
         // Hook up the list view.
         mListView = (ListView) findViewById(android.R.id.list);
@@ -145,22 +130,67 @@
                 }
 
                 PrinterInfo printer = (PrinterInfo) mListView.getAdapter().getItem(position);
-                onPrinterSelected(printer.getId());
+
+                if (printer == null) {
+                    startAddPrinterActivity();
+                } else {
+                    onPrinterSelected(printer.getId());
+                }
+            }
+        });
+
+        findViewById(R.id.button).setOnClickListener(new OnClickListener() {
+            @Override public void onClick(View v) {
+                startAddPrinterActivity();
             }
         });
 
         registerForContextMenu(mListView);
 
-        // Display a notification about disabled services if there are disabled services
-        String disabledServicesSetting = Settings.Secure.getString(getContentResolver(),
-                Settings.Secure.DISABLED_PRINT_SERVICES);
-        if (!TextUtils.isEmpty(disabledServicesSetting)) {
-            Toast.makeText(this, getString(R.string.print_services_disabled_toast),
-                    Toast.LENGTH_LONG).show();
+        getLoaderManager().initLoader(LOADER_ID_ENABLED_PRINT_SERVICES, null, this);
+
+        // On first creation:
+        //
+        // If no services are installed, instantly open add printer dialog.
+        // If some are disabled and some are enabled show a toast to notify the user
+        if (savedInstanceState == null || !savedInstanceState.getBoolean(KEY_NOT_FIRST_CREATE)) {
+            List<PrintServiceInfo> allServices =
+                    ((PrintManager) getSystemService(Context.PRINT_SERVICE))
+                            .getPrintServices(PrintManager.ALL_SERVICES);
+            boolean hasEnabledServices = false;
+            boolean hasDisabledServices = false;
+
+            if (allServices != null) {
+                final int numServices = allServices.size();
+                for (int i = 0; i < numServices; i++) {
+                    if (allServices.get(i).isEnabled()) {
+                        hasEnabledServices = true;
+                    } else {
+                        hasDisabledServices = true;
+                    }
+                }
+            }
+
+            if (!hasEnabledServices) {
+                startAddPrinterActivity();
+            } else if (hasDisabledServices) {
+                String disabledServicesSetting = Settings.Secure.getString(getContentResolver(),
+                        Settings.Secure.DISABLED_PRINT_SERVICES);
+                if (!TextUtils.isEmpty(disabledServicesSetting)) {
+                    Toast.makeText(this, getString(R.string.print_services_disabled_toast),
+                            Toast.LENGTH_LONG).show();
+                }
+            }
         }
     }
 
     @Override
+    protected void onSaveInstanceState(Bundle outState) {
+        super.onSaveInstanceState(outState);
+        outState.putBoolean(KEY_NOT_FIRST_CREATE, true);
+    }
+
+    @Override
     public boolean onCreateOptionsMenu(Menu menu) {
         super.onCreateOptionsMenu(menu);
 
@@ -249,60 +279,13 @@
      * Adjust the UI if the enabled print services changed.
      */
     private synchronized void onPrintServicesUpdate() {
-        updateServicesWithAddPrinterActivity();
         updateEmptyView((DestinationAdapter)mListView.getAdapter());
         invalidateOptionsMenu();
     }
 
-    /**
-     * Register listener for changes to the enabled print services.
-     */
-    private void registerServiceMonitor() {
-        // Listen for services getting disabled
-        mPrintServicesDisabledObserver = new ContentObserver(new Handler()) {
-            @Override
-            public void onChange(boolean selfChange) {
-                onPrintServicesUpdate();
-            }
-        };
-
-        // Listen for services getting installed or uninstalled
-        mPackageObserver = new PackageMonitor() {
-            @Override
-            public void onPackageModified(String packageName) {
-                onPrintServicesUpdate();
-            }
-
-            @Override
-            public void onPackageRemoved(String packageName, int uid) {
-                onPrintServicesUpdate();
-            }
-
-            @Override
-            public void onPackageAdded(String packageName, int uid) {
-                onPrintServicesUpdate();
-            }
-        };
-
-        getContentResolver().registerContentObserver(
-                Settings.Secure.getUriFor(Settings.Secure.DISABLED_PRINT_SERVICES), false,
-                mPrintServicesDisabledObserver);
-
-        mPackageObserver.register(this, getMainLooper(), false);
-    }
-
-    /**
-     * Unregister the listeners for changes to the enabled print services.
-     */
-    private void unregisterServiceMonitorIfNeeded() {
-        getContentResolver().unregisterContentObserver(mPrintServicesDisabledObserver);
-        mPackageObserver.unregister();
-    }
-
     @Override
     public void onStart() {
         super.onStart();
-        registerServiceMonitor();
         onPrintServicesUpdate();
     }
 
@@ -316,19 +299,9 @@
 
     @Override
     public void onStop() {
-        unregisterServiceMonitorIfNeeded();
         super.onStop();
     }
 
-    @Override
-    public boolean onOptionsItemSelected(MenuItem item) {
-        if (item.getItemId() == R.id.action_add_printer) {
-            showAddPrinterSelectionDialog();
-            return true;
-        }
-        return super.onOptionsItemSelected(item);
-    }
-
     private void onPrinterSelected(PrinterId printerId) {
         Intent intent = new Intent();
         intent.putExtra(INTENT_EXTRA_PRINTER_ID, printerId);
@@ -336,68 +309,6 @@
         finish();
     }
 
-    private void updateServicesWithAddPrinterActivity() {
-        mHasEnabledPrintServices = true;
-        mAddPrinterServices.clear();
-
-        // Get all enabled print services.
-        PrintManager printManager = (PrintManager) getSystemService(Context.PRINT_SERVICE);
-        List<PrintServiceInfo> enabledServices = printManager.getEnabledPrintServices();
-
-        // No enabled print services - done.
-        if (enabledServices.isEmpty()) {
-            mHasEnabledPrintServices = false;
-            return;
-        }
-
-        // Find the services with valid add printers activities.
-        final int enabledServiceCount = enabledServices.size();
-        for (int i = 0; i < enabledServiceCount; i++) {
-            PrintServiceInfo enabledService = enabledServices.get(i);
-
-            // No add printers activity declared - next.
-            if (TextUtils.isEmpty(enabledService.getAddPrintersActivityName())) {
-                continue;
-            }
-
-            ServiceInfo serviceInfo = enabledService.getResolveInfo().serviceInfo;
-            ComponentName addPrintersComponentName = new ComponentName(
-                    serviceInfo.packageName, enabledService.getAddPrintersActivityName());
-            Intent addPritnersIntent = new Intent()
-                .setComponent(addPrintersComponentName);
-
-            // The add printers activity is valid - add it.
-            PackageManager pm = getPackageManager();
-            List<ResolveInfo> resolvedActivities = pm.queryIntentActivities(addPritnersIntent, 0);
-            if (!resolvedActivities.isEmpty()) {
-                // The activity is a component name, therefore it is one or none.
-                ActivityInfo activityInfo = resolvedActivities.get(0).activityInfo;
-                if (activityInfo.exported
-                        && (activityInfo.permission == null
-                                || pm.checkPermission(activityInfo.permission, getPackageName())
-                                        == PackageManager.PERMISSION_GRANTED)) {
-                    mAddPrinterServices.add(enabledService);
-                }
-            }
-        }
-    }
-
-    private void showAddPrinterSelectionDialog() {
-        FragmentTransaction transaction = getFragmentManager().beginTransaction();
-        Fragment oldFragment = getFragmentManager().findFragmentByTag(
-                FRAGMENT_TAG_ADD_PRINTER_DIALOG);
-        if (oldFragment != null) {
-            transaction.remove(oldFragment);
-        }
-        AddPrinterAlertDialogFragment newFragment = new AddPrinterAlertDialogFragment();
-        Bundle arguments = new Bundle();
-        arguments.putParcelableArrayList(FRAGMENT_ARGUMENT_PRINT_SERVICE_INFOS,
-                mAddPrinterServices);
-        newFragment.setArguments(arguments);
-        transaction.add(newFragment, FRAGMENT_TAG_ADD_PRINTER_DIALOG);
-        transaction.commit();
-    }
-
     public void updateEmptyView(DestinationAdapter adapter) {
         if (mListView.getEmptyView() == null) {
             View emptyView = findViewById(R.id.empty_print_state);
@@ -426,71 +337,28 @@
         }
     }
 
-    public static class AddPrinterAlertDialogFragment extends DialogFragment {
+    @Override
+    public Loader<List<PrintServiceInfo>> onCreateLoader(int id, Bundle args) {
+        return new PrintServicesLoader((PrintManager) getSystemService(Context.PRINT_SERVICE), this,
+                PrintManager.ENABLED_SERVICES);
+    }
 
-        private String mAddPrintServiceItem;
+    @Override
+    public void onLoadFinished(Loader<List<PrintServiceInfo>> loader,
+            List<PrintServiceInfo> data) {
+        if (data == null || data.isEmpty()) {
+            mHasEnabledPrintServices = false;
+        } else {
+            mHasEnabledPrintServices = true;
+        }
 
-        @Override
-        @SuppressWarnings("unchecked")
-        public Dialog onCreateDialog(Bundle savedInstanceState) {
-            AlertDialog.Builder builder = new AlertDialog.Builder(getActivity())
-                    .setTitle(R.string.choose_print_service);
+        onPrintServicesUpdate();
+    }
 
-            final List<PrintServiceInfo> printServices = (List<PrintServiceInfo>) (List<?>)
-                    getArguments().getParcelableArrayList(FRAGMENT_ARGUMENT_PRINT_SERVICE_INFOS);
-
-            final ArrayAdapter<String> adapter = new ArrayAdapter<>(
-                    getActivity(), android.R.layout.simple_list_item_1);
-            final int printServiceCount = printServices.size();
-            for (int i = 0; i < printServiceCount; i++) {
-                PrintServiceInfo printService = printServices.get(i);
-                adapter.add(printService.getResolveInfo().loadLabel(
-                        getActivity().getPackageManager()).toString());
-            }
-
-            final String searchUri = Settings.Secure.getString(getActivity().getContentResolver(),
-                    Settings.Secure.PRINT_SERVICE_SEARCH_URI);
-            final Intent viewIntent;
-            if (!TextUtils.isEmpty(searchUri)) {
-                Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(searchUri));
-                if (getActivity().getPackageManager().resolveActivity(intent, 0) != null) {
-                    viewIntent = intent;
-                    mAddPrintServiceItem = getString(R.string.add_print_service_label);
-                    adapter.add(mAddPrintServiceItem);
-                } else {
-                    viewIntent = null;
-                }
-            } else {
-                viewIntent = null;
-            }
-
-            builder.setAdapter(adapter, new DialogInterface.OnClickListener() {
-                @Override
-                public void onClick(DialogInterface dialog, int which) {
-                    String item = adapter.getItem(which);
-                    if (item.equals(mAddPrintServiceItem)) {
-                        try {
-                            startActivity(viewIntent);
-                        } catch (ActivityNotFoundException anfe) {
-                            Log.w(LOG_TAG, "Couldn't start add printer activity", anfe);
-                        }
-                    } else {
-                        PrintServiceInfo printService = printServices.get(which);
-                        ComponentName componentName = new ComponentName(
-                                printService.getResolveInfo().serviceInfo.packageName,
-                                printService.getAddPrintersActivityName());
-                        Intent intent = new Intent(Intent.ACTION_MAIN);
-                        intent.setComponent(componentName);
-                        try {
-                            startActivity(intent);
-                        } catch (ActivityNotFoundException anfe) {
-                            Log.w(LOG_TAG, "Couldn't start add printer activity", anfe);
-                        }
-                    }
-                }
-            });
-
-            return builder.create();
+    @Override
+    public void onLoaderReset(Loader<List<PrintServiceInfo>> loader) {
+        if (!isFinishing()) {
+            onLoadFinished(loader, null);
         }
     }
 
@@ -592,14 +460,40 @@
         @Override
         public int getCount() {
             synchronized (mLock) {
-                return mFilteredPrinters.size();
+                if (mFilteredPrinters.isEmpty()) {
+                    return 0;
+                } else {
+                    // Add "add printer" item to the end of the list. If the list is empty there is
+                    // a link on the empty view
+                    return mFilteredPrinters.size() + 1;
+                }
+            }
+        }
+
+        @Override
+        public int getViewTypeCount() {
+            return 2;
+        }
+
+        @Override
+        public int getItemViewType(int position) {
+            // Use separate view types for the "add printer" item an the items referring to printers
+            if (getItem(position) == null) {
+                return 0;
+            } else {
+                return 1;
             }
         }
 
         @Override
         public Object getItem(int position) {
             synchronized (mLock) {
-                return mFilteredPrinters.get(position);
+                if (position < mFilteredPrinters.size()) {
+                    return mFilteredPrinters.get(position);
+                } else {
+                    // Return null to mark this as the "add printer item"
+                    return null;
+                }
             }
         }
 
@@ -615,6 +509,18 @@
 
         @Override
         public View getView(int position, View convertView, ViewGroup parent) {
+            final PrinterInfo printer = (PrinterInfo) getItem(position);
+
+            // Handle "add printer item"
+            if (printer == null) {
+                if (convertView == null) {
+                    convertView = getLayoutInflater().inflate(R.layout.add_printer_list_item,
+                            parent, false);
+                }
+
+                return convertView;
+            }
+
             if (convertView == null) {
                 convertView = getLayoutInflater().inflate(
                         R.layout.printer_list_item, parent, false);
@@ -622,7 +528,6 @@
 
             convertView.setEnabled(isActionable(position));
 
-            final PrinterInfo printer = (PrinterInfo) getItem(position);
 
             CharSequence title = printer.getName();
             Drawable icon = printer.loadIcon(SelectPrinterActivity.this);
@@ -661,7 +566,7 @@
                 subtitleView.setVisibility(View.GONE);
             }
 
-            ImageView moreInfoView = (ImageView) convertView.findViewById(R.id.more_info);
+            LinearLayout moreInfoView = (LinearLayout) convertView.findViewById(R.id.more_info);
             if (printer.getInfoIntent() != null) {
                 moreInfoView.setVisibility(View.VISIBLE);
                 moreInfoView.setOnClickListener(new OnClickListener() {
@@ -699,7 +604,12 @@
 
         public boolean isActionable(int position) {
             PrinterInfo printer =  (PrinterInfo) getItem(position);
-            return printer.getStatus() != PrinterInfo.STATUS_UNAVAILABLE;
+
+            if (printer == null) {
+                return true;
+            } else {
+                return printer.getStatus() != PrinterInfo.STATUS_UNAVAILABLE;
+            }
         }
     }
 
diff --git a/packages/PrintSpooler/src/com/android/printspooler/util/PrintOptionUtils.java b/packages/PrintSpooler/src/com/android/printspooler/util/PrintOptionUtils.java
deleted file mode 100644
index 446952d..0000000
--- a/packages/PrintSpooler/src/com/android/printspooler/util/PrintOptionUtils.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.printspooler.util;
-
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.pm.ServiceInfo;
-import android.print.PrintManager;
-import android.printservice.PrintServiceInfo;
-
-import java.util.List;
-
-public class PrintOptionUtils {
-
-    private PrintOptionUtils() {
-        /* ignore - hide constructor */
-    }
-
-    /**
-     * Gets the advanced options activity name for a print service.
-     *
-     * @param context Context for accessing system resources.
-     * @param serviceName The print service name.
-     * @return The advanced options activity name or null.
-     */
-    public static String getAdvancedOptionsActivityName(Context context,
-            ComponentName serviceName) {
-        PrintManager printManager = (PrintManager) context.getSystemService(
-                Context.PRINT_SERVICE);
-        List<PrintServiceInfo> printServices = printManager.getEnabledPrintServices();
-        final int printServiceCount = printServices.size();
-        for (int i = 0; i < printServiceCount; i ++) {
-            PrintServiceInfo printServiceInfo = printServices.get(i);
-            ServiceInfo serviceInfo = printServiceInfo.getResolveInfo().serviceInfo;
-            if (serviceInfo.name.equals(serviceName.getClassName())
-                    && serviceInfo.packageName.equals(serviceName.getPackageName())) {
-                return printServiceInfo.getAdvancedOptionsActivityName();
-            }
-        }
-        return null;
-    }
-}
diff --git a/packages/SettingsLib/res/drawable/ic_info.xml b/packages/SettingsLib/res/drawable/ic_info.xml
new file mode 100644
index 0000000..afe7e6b
--- /dev/null
+++ b/packages/SettingsLib/res/drawable/ic_info.xml
@@ -0,0 +1,25 @@
+<!--
+    Copyright (C) 2016 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="24dp"
+        android:height="24dp"
+        android:viewportWidth="24"
+        android:viewportHeight="24"
+        android:tint="?android:attr/colorAccent">
+    <path
+        android:fillColor="@android:color/white"
+        android:pathData="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-6h2v6zm0-8h-2V7h2v2z"/>
+</vector>
diff --git a/packages/SettingsLib/res/drawable/ic_settings_lock_outline.xml b/packages/SettingsLib/res/drawable/ic_settings_lock_outline.xml
deleted file mode 100644
index b3d7cf9..0000000
--- a/packages/SettingsLib/res/drawable/ic_settings_lock_outline.xml
+++ /dev/null
@@ -1,27 +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.
--->
-
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="21dp"
-        android:height="21dp"
-        android:viewportWidth="21.0"
-        android:viewportHeight="21.0"
-        android:tint="?android:attr/colorAccent">
-    <path
-            android:fillColor="@android:color/white"
-            android:pathData="M8,16c1.1,0,2-0.9,2-2s-0.9-2-2-2s-2,0.9-2,2S6.9,16,8,16zM14,7h-1V5c0-2.8-2.2-5-5-5S3,2.2,3,5v2H2C0.9,7,0,7.9,0,9v10c0,1.1,0.9,2,2,2h12c1.1,0,2-0.9,2-2V9C16,7.9,15.1,7,14,7z M4.9,5c0-1.7,1.4-3.1,3.1-3.1s3.1,1.4,3.1,3.1v2H4.9V5z M14,19H2V9h12V19z" />
-</vector>
diff --git a/packages/SystemUI/res/drawable/qs_background_secondary.xml b/packages/SettingsLib/res/layout/restricted_icon.xml
similarity index 65%
copy from packages/SystemUI/res/drawable/qs_background_secondary.xml
copy to packages/SettingsLib/res/layout/restricted_icon.xml
index 31c0162..724a524 100644
--- a/packages/SystemUI/res/drawable/qs_background_secondary.xml
+++ b/packages/SettingsLib/res/layout/restricted_icon.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2014 The Android Open Source Project
+<!-- Copyright (C) 2016 The Android Open Source Project
 
      Licensed under the Apache License, Version 2.0 (the "License");
      you may not use this file except in compliance with the License.
@@ -13,9 +13,8 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-<shape xmlns:android="http://schemas.android.com/apk/res/android">
-    <solid android:color="@color/system_secondary_color" />
-    <corners
-        android:topLeftRadius="0dp"
-        android:topRightRadius="0dp" />
-</shape>
+<ImageView xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/restricted_icon"
+    android:layout_width="@dimen/restricted_icon_size"
+    android:layout_height="@dimen/restricted_icon_size"
+    android:src="@drawable/ic_info" />
\ No newline at end of file
diff --git a/packages/SettingsLib/res/layout/restricted_switch_widget.xml b/packages/SettingsLib/res/layout/restricted_switch_widget.xml
new file mode 100644
index 0000000..6183812
--- /dev/null
+++ b/packages/SettingsLib/res/layout/restricted_switch_widget.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.
+-->
+<merge xmlns:android="http://schemas.android.com/apk/res/android">
+    <ImageView xmlns:android="http://schemas.android.com/apk/res/android"
+        android:id="@+id/restricted_icon"
+        android:layout_width="@dimen/restricted_icon_size"
+        android:layout_height="@dimen/restricted_icon_size"
+        android:src="@drawable/ic_info"
+        android:gravity="end|center_vertical" />
+    <!-- Based off frameworks/base/core/res/res/layout/preference_widget_switch.xml -->
+    <Switch xmlns:android="http://schemas.android.com/apk/res/android"
+        android:id="@+android:id/switch_widget"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:focusable="false"
+        android:clickable="false"
+        android:background="@null" />
+</merge>
\ No newline at end of file
diff --git a/packages/SettingsLib/res/layout/settings_with_drawer.xml b/packages/SettingsLib/res/layout/settings_with_drawer.xml
index 9e5d029..67296a6 100644
--- a/packages/SettingsLib/res/layout/settings_with_drawer.xml
+++ b/packages/SettingsLib/res/layout/settings_with_drawer.xml
@@ -17,14 +17,15 @@
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:id="@+id/drawer_layout"
     android:layout_width="match_parent"
-    android:layout_height="match_parent">
+    android:layout_height="match_parent"
+    android:background="?android:attr/colorPrimaryDark">
     <!-- The main content view -->
     <LinearLayout
         android:id="@+id/content_parent"
         android:layout_width="match_parent"
         android:layout_height="match_parent"
         android:orientation="vertical"
-        android:fitsSystemWindows="false" >
+        android:fitsSystemWindows="true" >
         <FrameLayout
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
@@ -36,14 +37,14 @@
                 android:layout_height="wrap_content"
                 android:navigationContentDescription="@*android:string/action_bar_up_description"
                 android:theme="?android:attr/actionBarTheme"
-                android:paddingTop="@*android:dimen/status_bar_height"
                 style="?android:attr/toolbarStyle"
                 android:background="?android:attr/colorPrimary" />
         </FrameLayout>
         <FrameLayout
             android:id="@+id/content_frame"
             android:layout_width="match_parent"
-            android:layout_height="fill_parent" />
+            android:layout_height="fill_parent"
+            android:background="?android:attr/windowBackground" />
     </LinearLayout>
     <!-- The navigation drawer -->
     <ListView android:id="@+id/left_drawer"
diff --git a/packages/SettingsLib/res/layout/usage_view.xml b/packages/SettingsLib/res/layout/usage_view.xml
index 28981f8..aa1a046 100644
--- a/packages/SettingsLib/res/layout/usage_view.xml
+++ b/packages/SettingsLib/res/layout/usage_view.xml
@@ -22,7 +22,8 @@
     <LinearLayout
         android:id="@+id/graph_label_group"
         android:layout_width="match_parent"
-        android:layout_height="@dimen/usage_graph_area_height"
+        android:layout_height="0dp"
+        android:layout_weight="1"
         android:orientation="horizontal"
         android:clipChildren="false"
         android:clipToPadding="false">
@@ -37,6 +38,7 @@
                 layout="@layout/usage_side_label" />
 
             <Space
+                android:id="@+id/space1"
                 android:layout_width="wrap_content"
                 android:layout_height="0dp"
                 android:layout_weight="1" />
@@ -45,6 +47,7 @@
                 layout="@layout/usage_side_label" />
 
             <Space
+                android:id="@+id/space2"
                 android:layout_width="wrap_content"
                 android:layout_height="0dp"
                 android:layout_weight="1" />
diff --git a/packages/SettingsLib/res/values-af/strings.xml b/packages/SettingsLib/res/values-af/strings.xml
index b32e3e1..a408c08 100644
--- a/packages/SettingsLib/res/values-af/strings.xml
+++ b/packages/SettingsLib/res/values-af/strings.xml
@@ -102,8 +102,7 @@
     <string name="tts_default_rate_title" msgid="6030550998379310088">"Spraaktempo"</string>
     <string name="tts_default_rate_summary" msgid="4061815292287182801">"Spoed waarteen die teks gepraat word"</string>
     <string name="tts_default_pitch_title" msgid="6135942113172488671">"Toonhoogte"</string>
-    <!-- no translation found for tts_default_pitch_summary (1944885882882650009) -->
-    <skip />
+    <string name="tts_default_pitch_summary" msgid="1944885882882650009">"Beïnvloed die klank van die gesintetiseerde spraak"</string>
     <string name="tts_default_lang_title" msgid="8018087612299820556">"Taal"</string>
     <string name="tts_lang_use_system" msgid="2679252467416513208">"Gebruik stelseltaal"</string>
     <string name="tts_lang_not_selected" msgid="7395787019276734765">"Taal nie gekies nie"</string>
@@ -279,7 +278,7 @@
     <string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"Laat loop WebView-leweraars in \'n geïsoleerde proses."</string>
     <string name="select_webview_provider_title" msgid="4628592979751918907">"WebView-implementering"</string>
     <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Stel WebView-implementering"</string>
-    <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"Die gekose WebView-toepassing is gedeaktiveer, maar moet geaktiveer wees om gebruik te word. Wil jy dit aktiveer?"</string>
+    <string name="select_webview_provider_toast_text" msgid="8168796505966635684">"Die gekose WebView-toepassing is ongeldig want die lys toepassingskeuses het verouderd geraak. Die lys moet nou opgedateer word."</string>
     <string name="convert_to_file_encryption" msgid="3060156730651061223">"Skakel om na lêerenkripsie"</string>
     <string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Skakel om …"</string>
     <string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Lêerenkripsie is reeds uitgevoer"</string>
@@ -312,6 +311,8 @@
     <string name="battery_info_status_not_charging" msgid="2820070506621483576">"Laai nie"</string>
     <string name="battery_info_status_full" msgid="2824614753861462808">"Vol"</string>
     <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Beheer deur administrateur"</string>
+    <string name="enabled_by_admin" msgid="2386503803463071894">"Geaktiveer deur administrateur"</string>
+    <string name="disabled_by_admin" msgid="3669999613095206948">"Gedeaktiveer deur administrateur"</string>
     <string name="home" msgid="8263346537524314127">"Tuis"</string>
     <string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g> gelede"</string>
     <string name="remaining_length_format" msgid="7886337596669190587">"<xliff:g id="ID_1">%1$s</xliff:g> oor"</string>
diff --git a/packages/SettingsLib/res/values-am/strings.xml b/packages/SettingsLib/res/values-am/strings.xml
index 9b3a94a..7ae97e2 100644
--- a/packages/SettingsLib/res/values-am/strings.xml
+++ b/packages/SettingsLib/res/values-am/strings.xml
@@ -102,8 +102,7 @@
     <string name="tts_default_rate_title" msgid="6030550998379310088">" የንግግር ደረጃ"</string>
     <string name="tts_default_rate_summary" msgid="4061815292287182801">"የተነገረበትን ፅሁፍ አፍጥን"</string>
     <string name="tts_default_pitch_title" msgid="6135942113172488671">"ቅላፄ"</string>
-    <!-- no translation found for tts_default_pitch_summary (1944885882882650009) -->
-    <skip />
+    <string name="tts_default_pitch_summary" msgid="1944885882882650009">"በሲንተሲስ በተሠራው ድምፅ ላይ ተፅዕኖ ያሳድራል"</string>
     <string name="tts_default_lang_title" msgid="8018087612299820556">"ቋንቋ"</string>
     <string name="tts_lang_use_system" msgid="2679252467416513208">"የስርዓት ቋንቋ ተጠቀም"</string>
     <string name="tts_lang_not_selected" msgid="7395787019276734765">"ቋንቋ አልተመረጠም"</string>
@@ -279,7 +278,7 @@
     <string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"የWebView ምስል ሰሪዎችን በተገለለ ሂደት ውስጥ አሂድ።"</string>
     <string name="select_webview_provider_title" msgid="4628592979751918907">"የWebView ትግበራ"</string>
     <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"የWebView ትግበራን ያዘጋጁ"</string>
-    <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"የተመረጠው WebView ትግበራ ተሰናክሏል፣ እና ጥቅም ላይ እንዲውል መንቃት አለበት፣ ሊያነቁት ይፈልጋሉ?"</string>
+    <string name="select_webview_provider_toast_text" msgid="8168796505966635684">"የትግበራ ምርጫዎች ዝርዝር እድገት ስላላሳየ የተመረጠው የWebView ትግበራ አይሠራም። ዝርዝሩ አሁን መዘመን አለበት።"</string>
     <string name="convert_to_file_encryption" msgid="3060156730651061223">"ወደ ፋይል ምሥጠራ ቀይር"</string>
     <string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"ለውጥ…"</string>
     <string name="convert_to_file_encryption_done" msgid="7859766358000523953">"ፋይል አስቀድሞ ተመስጥሯል"</string>
@@ -312,6 +311,8 @@
     <string name="battery_info_status_not_charging" msgid="2820070506621483576">"ኃይል  እየሞላ አይደለም"</string>
     <string name="battery_info_status_full" msgid="2824614753861462808">"ሙሉነው"</string>
     <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"በአስተዳዳሪ ቁጥጥር የተደረገበት"</string>
+    <string name="enabled_by_admin" msgid="2386503803463071894">"በአስተዳዳሪ የነቃ"</string>
+    <string name="disabled_by_admin" msgid="3669999613095206948">"በአስተዳዳሪ የተሰናከለ"</string>
     <string name="home" msgid="8263346537524314127">"መነሻ"</string>
     <string name="charge_length_format" msgid="8978516217024434156">"ከ<xliff:g id="ID_1">%1$s</xliff:g> በፊት"</string>
     <string name="remaining_length_format" msgid="7886337596669190587">"<xliff:g id="ID_1">%1$s</xliff:g> ቀርቷል"</string>
diff --git a/packages/SettingsLib/res/values-ar/strings.xml b/packages/SettingsLib/res/values-ar/strings.xml
index 7dec197..eb76e1f 100644
--- a/packages/SettingsLib/res/values-ar/strings.xml
+++ b/packages/SettingsLib/res/values-ar/strings.xml
@@ -102,8 +102,7 @@
     <string name="tts_default_rate_title" msgid="6030550998379310088">"معدل سرعة الكلام"</string>
     <string name="tts_default_rate_summary" msgid="4061815292287182801">"سرعة نطق الكلام"</string>
     <string name="tts_default_pitch_title" msgid="6135942113172488671">"درجة الصوت"</string>
-    <!-- no translation found for tts_default_pitch_summary (1944885882882650009) -->
-    <skip />
+    <string name="tts_default_pitch_summary" msgid="1944885882882650009">"للتأثير في نبرة الكلام المُرَكَّب"</string>
     <string name="tts_default_lang_title" msgid="8018087612299820556">"اللغة"</string>
     <string name="tts_lang_use_system" msgid="2679252467416513208">"استخدام لغة النظام"</string>
     <string name="tts_lang_not_selected" msgid="7395787019276734765">"اللغة غير محددة"</string>
@@ -279,7 +278,7 @@
     <string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"تشغيل أجهزة عرض الويب في عملية منفصلة."</string>
     <string name="select_webview_provider_title" msgid="4628592979751918907">"‏تطبيق WebView"</string>
     <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"‏تعيين تطبيق WebView"</string>
-    <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"‏إن تنفيذ ميزة WebView التي تم اختيارها معطَّل، ويجب تمكين هذه الميزة ليتسنى استخدامها، فهل تريد تمكينها؟"</string>
+    <string name="select_webview_provider_toast_text" msgid="8168796505966635684">"‏التنفيذ الذي تم اختياره لطريقة WebView غير صالح لأن قائمة خيارات التنفيذ أصبحت قديمة. يجب أن يتم تحديث القائمة الآن."</string>
     <string name="convert_to_file_encryption" msgid="3060156730651061223">"التحويل إلى تشفير ملفات"</string>
     <string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"تحويل…"</string>
     <string name="convert_to_file_encryption_done" msgid="7859766358000523953">"تم استخدام تشفير ملفات من قبل"</string>
@@ -312,6 +311,8 @@
     <string name="battery_info_status_not_charging" msgid="2820070506621483576">"لا يتم الشحن"</string>
     <string name="battery_info_status_full" msgid="2824614753861462808">"ممتلئة"</string>
     <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"إعدادات يتحكم فيها المشرف"</string>
+    <string name="enabled_by_admin" msgid="2386503803463071894">"تم التمكين بواسطة المشرف"</string>
+    <string name="disabled_by_admin" msgid="3669999613095206948">"تم التعطيل بواسطة المشرف"</string>
     <string name="home" msgid="8263346537524314127">"الشاشة الرئيسية"</string>
     <string name="charge_length_format" msgid="8978516217024434156">"قبل <xliff:g id="ID_1">%1$s</xliff:g>"</string>
     <string name="remaining_length_format" msgid="7886337596669190587">"يتبقى <xliff:g id="ID_1">%1$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-az-rAZ/strings.xml b/packages/SettingsLib/res/values-az-rAZ/strings.xml
index b8a2437..9903397 100644
--- a/packages/SettingsLib/res/values-az-rAZ/strings.xml
+++ b/packages/SettingsLib/res/values-az-rAZ/strings.xml
@@ -102,8 +102,7 @@
     <string name="tts_default_rate_title" msgid="6030550998379310088">"Nitq diapazonu"</string>
     <string name="tts_default_rate_summary" msgid="4061815292287182801">"Mətnin səsləndirilmə sürəti"</string>
     <string name="tts_default_pitch_title" msgid="6135942113172488671">"Pitç"</string>
-    <!-- no translation found for tts_default_pitch_summary (1944885882882650009) -->
-    <skip />
+    <string name="tts_default_pitch_summary" msgid="1944885882882650009">"Sintez olunmuş nitqin tonuna təsir edir"</string>
     <string name="tts_default_lang_title" msgid="8018087612299820556">"Dil"</string>
     <string name="tts_lang_use_system" msgid="2679252467416513208">"Sistem dili işlədin"</string>
     <string name="tts_lang_not_selected" msgid="7395787019276734765">"Dil seçilməyib"</string>
@@ -279,7 +278,7 @@
     <string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"WebView rendererləri təcrid olunmuş prosesdə işlədin."</string>
     <string name="select_webview_provider_title" msgid="4628592979751918907">"WebView icrası"</string>
     <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"WebView icrasını ayarlayın"</string>
-    <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"Seçilmiş WebView icrası deaktiv edildi, istifadəsi üçün aktiv edilməlidir, aktivləşdirmək istəyirsiniz?"</string>
+    <string name="select_webview_provider_toast_text" msgid="8168796505966635684">"Seçilmiş WebView icrası yararsızdır cünki, icra seçimlərinin siyahısı köhnədir. Bu siyahı güncəllənməlidir."</string>
     <string name="convert_to_file_encryption" msgid="3060156730651061223">"Fayl şifrələnməsinə çevirin"</string>
     <string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Çevirin..."</string>
     <string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Fayl artıq şifrələnib"</string>
@@ -312,6 +311,8 @@
     <string name="battery_info_status_not_charging" msgid="2820070506621483576">"Enerji doldurulmur"</string>
     <string name="battery_info_status_full" msgid="2824614753861462808">"Tam"</string>
     <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Admin tərəfindən nəzarət olunur"</string>
+    <string name="enabled_by_admin" msgid="2386503803463071894">"Administrator tərəfindən aktiv edildi"</string>
+    <string name="disabled_by_admin" msgid="3669999613095206948">"Administrator tərəfindən deaktiv edildi"</string>
     <string name="home" msgid="8263346537524314127">"Əsas səhifə"</string>
     <string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g> əvvəl"</string>
     <string name="remaining_length_format" msgid="7886337596669190587">"<xliff:g id="ID_1">%1$s</xliff:g> qalıb"</string>
diff --git a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
index b3621cf..f570d09 100644
--- a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
+++ b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
@@ -102,8 +102,7 @@
     <string name="tts_default_rate_title" msgid="6030550998379310088">"Brzina govora"</string>
     <string name="tts_default_rate_summary" msgid="4061815292287182801">"Brzina izgovaranja teksta"</string>
     <string name="tts_default_pitch_title" msgid="6135942113172488671">"Nivo"</string>
-    <!-- no translation found for tts_default_pitch_summary (1944885882882650009) -->
-    <skip />
+    <string name="tts_default_pitch_summary" msgid="1944885882882650009">"Utiče na ton sintetizovanog govora"</string>
     <string name="tts_default_lang_title" msgid="8018087612299820556">"Jezik"</string>
     <string name="tts_lang_use_system" msgid="2679252467416513208">"Koristi jezik sistema"</string>
     <string name="tts_lang_not_selected" msgid="7395787019276734765">"Jezik nije izabran"</string>
@@ -279,7 +278,7 @@
     <string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"Pokrećite WebView prikazivače u okviru izolovanog procesa."</string>
     <string name="select_webview_provider_title" msgid="4628592979751918907">"Primena WebView-a"</string>
     <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Podesite primenu WebView-a"</string>
-    <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"Izabrana primena WebView-a je onemogućena, a mora da bude omogućena radi korišćenja. Želite li da je omogućite?"</string>
+    <string name="select_webview_provider_toast_text" msgid="8168796505966635684">"Izabrana primena WebView-a je nevažeća zato što je lista mogućnosti za primenu zastarela. Sada bi trebalo da ažurirate listu."</string>
     <string name="convert_to_file_encryption" msgid="3060156730651061223">"Konvertuj u šifrovanje datoteka"</string>
     <string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Konvertuj..."</string>
     <string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Već se koristi šifrovanje datoteka"</string>
@@ -312,6 +311,8 @@
     <string name="battery_info_status_not_charging" msgid="2820070506621483576">"Ne puni se"</string>
     <string name="battery_info_status_full" msgid="2824614753861462808">"Puno"</string>
     <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Kontroliše administrator"</string>
+    <string name="enabled_by_admin" msgid="2386503803463071894">"Omogućio je administrator"</string>
+    <string name="disabled_by_admin" msgid="3669999613095206948">"Onemogućio je administrator"</string>
     <string name="home" msgid="8263346537524314127">"Početni"</string>
     <string name="charge_length_format" msgid="8978516217024434156">"Pre <xliff:g id="ID_1">%1$s</xliff:g>"</string>
     <string name="remaining_length_format" msgid="7886337596669190587">"Još <xliff:g id="ID_1">%1$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-bg/strings.xml b/packages/SettingsLib/res/values-bg/strings.xml
index 569de20..72652c9 100644
--- a/packages/SettingsLib/res/values-bg/strings.xml
+++ b/packages/SettingsLib/res/values-bg/strings.xml
@@ -102,8 +102,7 @@
     <string name="tts_default_rate_title" msgid="6030550998379310088">"Скорост на речта"</string>
     <string name="tts_default_rate_summary" msgid="4061815292287182801">"Скорост, с която се изговаря текстът"</string>
     <string name="tts_default_pitch_title" msgid="6135942113172488671">"Височина"</string>
-    <!-- no translation found for tts_default_pitch_summary (1944885882882650009) -->
-    <skip />
+    <string name="tts_default_pitch_summary" msgid="1944885882882650009">"Отразява се на тона на синтезирания говор"</string>
     <string name="tts_default_lang_title" msgid="8018087612299820556">"Език"</string>
     <string name="tts_lang_use_system" msgid="2679252467416513208">"Използване на системния език"</string>
     <string name="tts_lang_not_selected" msgid="7395787019276734765">"Езикът не е избран"</string>
@@ -279,7 +278,7 @@
     <string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"Програми за визуализация на WebView: Изпъл. в изолиран процес."</string>
     <string name="select_webview_provider_title" msgid="4628592979751918907">"Внедряване на WebView"</string>
     <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Задаване на внедряването на WebView"</string>
-    <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"Избраното внедряване на WebView е деактивирано и трябва да го активирате, за да се използва. Искате ли да го направите?"</string>
+    <string name="select_webview_provider_toast_text" msgid="8168796505966635684">"Избраната реализация на WebView е невалидна, тъй като списъкът с възможни реализации е остарял. Той следва да се актуализира сега."</string>
     <string name="convert_to_file_encryption" msgid="3060156730651061223">"Преобразуване към шифроване на ниво файл"</string>
     <string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Преобразуване…"</string>
     <string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Данните вече са шифровани на ниво файл"</string>
@@ -312,6 +311,8 @@
     <string name="battery_info_status_not_charging" msgid="2820070506621483576">"Не се зарежда"</string>
     <string name="battery_info_status_full" msgid="2824614753861462808">"Пълна"</string>
     <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Контролира се от администратор"</string>
+    <string name="enabled_by_admin" msgid="2386503803463071894">"Активирано от администратора"</string>
+    <string name="disabled_by_admin" msgid="3669999613095206948">"Деактивирано от администратора"</string>
     <string name="home" msgid="8263346537524314127">"Начало"</string>
     <string name="charge_length_format" msgid="8978516217024434156">"Преди <xliff:g id="ID_1">%1$s</xliff:g>"</string>
     <string name="remaining_length_format" msgid="7886337596669190587">"Оставащо време: <xliff:g id="ID_1">%1$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-bn-rBD/strings.xml b/packages/SettingsLib/res/values-bn-rBD/strings.xml
index 3c81cf2..b863773 100644
--- a/packages/SettingsLib/res/values-bn-rBD/strings.xml
+++ b/packages/SettingsLib/res/values-bn-rBD/strings.xml
@@ -278,7 +278,7 @@
     <string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"একটি বিচ্ছিন্ন প্রক্রিয়ায় ওয়েবভিউ রেন্ডারারগুলি চালান৷"</string>
     <string name="select_webview_provider_title" msgid="4628592979751918907">"ওয়েবভিউ প্রয়োগ"</string>
     <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"ওয়েবভিউ প্রয়োগ সেট করুন"</string>
-    <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"নির্বাচিত ওয়েবভিউ প্রয়োগটি অক্ষম করা আছে এবং ব্যবহার করার জন্য অবশ্যই সক্ষম করতে হবে, আপনি কি এটিকে সক্ষম করতে চান?"</string>
+    <string name="select_webview_provider_toast_text" msgid="8168796505966635684">"প্রয়োগ করার জন্য বেছে নেওয়া ওয়েবভিউটি অবৈধ, কারণ প্রয়োগের চয়নগুলি পুরানো হয়ে গেছে৷ এই তালিকাটিকে এখনই আপডেট করা উচিৎ৷"</string>
     <string name="convert_to_file_encryption" msgid="3060156730651061223">"ফাইল এনক্রিপশান রূপান্তর করুন"</string>
     <string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"রূপান্তর করুন..."</string>
     <string name="convert_to_file_encryption_done" msgid="7859766358000523953">"ফাইল ইতিমধ্যেই এনক্রিপ্ট করা রয়েছে"</string>
@@ -311,6 +311,8 @@
     <string name="battery_info_status_not_charging" msgid="2820070506621483576">"চার্জ হচ্ছে না"</string>
     <string name="battery_info_status_full" msgid="2824614753861462808">"পূর্ণ"</string>
     <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"প্রশাসকের দ্বারা নিয়ন্ত্রিত"</string>
+    <string name="enabled_by_admin" msgid="2386503803463071894">"প্রশাসক সক্ষম করেছেন"</string>
+    <string name="disabled_by_admin" msgid="3669999613095206948">"প্রশাসক অক্ষম করেছেন"</string>
     <string name="home" msgid="8263346537524314127">"হোম"</string>
     <string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g> আগে"</string>
     <string name="remaining_length_format" msgid="7886337596669190587">"<xliff:g id="ID_1">%1$s</xliff:g> বাকী আছে"</string>
diff --git a/packages/SettingsLib/res/values-bs-rBA/strings.xml b/packages/SettingsLib/res/values-bs-rBA/strings.xml
index 13d84ab..542c3ce 100644
--- a/packages/SettingsLib/res/values-bs-rBA/strings.xml
+++ b/packages/SettingsLib/res/values-bs-rBA/strings.xml
@@ -102,8 +102,7 @@
     <string name="tts_default_rate_title" msgid="6030550998379310088">"Brzina govora"</string>
     <string name="tts_default_rate_summary" msgid="4061815292287182801">"Brzina kojom se izgovara tekst"</string>
     <string name="tts_default_pitch_title" msgid="6135942113172488671">"Visina"</string>
-    <!-- no translation found for tts_default_pitch_summary (1944885882882650009) -->
-    <skip />
+    <string name="tts_default_pitch_summary" msgid="1944885882882650009">"Utječe na ton sintetiziranog govora"</string>
     <string name="tts_default_lang_title" msgid="8018087612299820556">"Jezik"</string>
     <string name="tts_lang_use_system" msgid="2679252467416513208">"Koristi sistemski jezik"</string>
     <string name="tts_lang_not_selected" msgid="7395787019276734765">"Jezik nije izabran"</string>
@@ -279,7 +278,7 @@
     <string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"Pokrenite WebView operatera u izolovanom procesu."</string>
     <string name="select_webview_provider_title" msgid="4628592979751918907">"Postavljanje WebViewa"</string>
     <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Podesi WebView"</string>
-    <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"Postavljanje izabranog WebViewa je onemogućeno. Da bi se mogao koristiti, mora biti omogućen. Želite li ga omogućiti?"</string>
+    <string name="select_webview_provider_toast_text" msgid="8168796505966635684">"Primjena izabranog prikaza weba ne važi jer je spisak izbora primjene zastario. Spisak se sada treba ažurirati."</string>
     <string name="convert_to_file_encryption" msgid="3060156730651061223">"Pretvori u šifrirani fajl"</string>
     <string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Pretvaranje…"</string>
     <string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Fajl je već šifriran"</string>
@@ -312,6 +311,8 @@
     <string name="battery_info_status_not_charging" msgid="2820070506621483576">"Ne puni se"</string>
     <string name="battery_info_status_full" msgid="2824614753861462808">"Puna"</string>
     <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Pod kontrolom administratora"</string>
+    <string name="enabled_by_admin" msgid="2386503803463071894">"Omogućio administrator"</string>
+    <string name="disabled_by_admin" msgid="3669999613095206948">"Onemogućio je administrator"</string>
     <string name="home" msgid="8263346537524314127">"Početna stranica"</string>
     <string name="charge_length_format" msgid="8978516217024434156">"prije <xliff:g id="ID_1">%1$s</xliff:g>"</string>
     <string name="remaining_length_format" msgid="7886337596669190587">"Još otprilike <xliff:g id="ID_1">%1$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-ca/strings.xml b/packages/SettingsLib/res/values-ca/strings.xml
index ceb2b6a..e2c4495 100644
--- a/packages/SettingsLib/res/values-ca/strings.xml
+++ b/packages/SettingsLib/res/values-ca/strings.xml
@@ -102,8 +102,7 @@
     <string name="tts_default_rate_title" msgid="6030550998379310088">"Velocitat de veu"</string>
     <string name="tts_default_rate_summary" msgid="4061815292287182801">"Velocitat de lectura del text"</string>
     <string name="tts_default_pitch_title" msgid="6135942113172488671">"To"</string>
-    <!-- no translation found for tts_default_pitch_summary (1944885882882650009) -->
-    <skip />
+    <string name="tts_default_pitch_summary" msgid="1944885882882650009">"Afecta el to de la veu sintetitzada"</string>
     <string name="tts_default_lang_title" msgid="8018087612299820556">"Idioma"</string>
     <string name="tts_lang_use_system" msgid="2679252467416513208">"Utilitza l\'idioma del sistema"</string>
     <string name="tts_lang_not_selected" msgid="7395787019276734765">"No has seleccionat cap idioma"</string>
@@ -275,11 +274,11 @@
     <string name="inactive_app_active_summary" msgid="4174921824958516106">"Aplicació activa. Toca per desactivar-la."</string>
     <string name="runningservices_settings_title" msgid="8097287939865165213">"Serveis en execució"</string>
     <string name="runningservices_settings_summary" msgid="854608995821032748">"Visualitza i controla els serveis en execució"</string>
-    <string name="enable_webview_multiprocess" msgid="3405948012467585908">"Activa WebView de multiprocés"</string>
+    <string name="enable_webview_multiprocess" msgid="3405948012467585908">"Activa WebView amb multiprocés"</string>
     <string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"Executa els renderitzadors de WebView en un procés aïllat."</string>
     <string name="select_webview_provider_title" msgid="4628592979751918907">"Implementació de WebView"</string>
     <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Configura la implementació de WebView"</string>
-    <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"La implementació de WebView que has triat està desactivada i s\'ha d\'activar per utilitzar-la. Vols activar-la?"</string>
+    <string name="select_webview_provider_toast_text" msgid="8168796505966635684">"La implementació de WebView que s\'ha triat no és vàlida perquè la llista d\'opcions d\'implementació ha quedat inactiva. Ara la llista ja hauria d\'estar actualitzada."</string>
     <string name="convert_to_file_encryption" msgid="3060156730651061223">"Converteix en l\'encriptació de fitxers"</string>
     <string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Converteix…"</string>
     <string name="convert_to_file_encryption_done" msgid="7859766358000523953">"El fitxer ja està encriptat"</string>
@@ -312,6 +311,8 @@
     <string name="battery_info_status_not_charging" msgid="2820070506621483576">"No s\'està carregant"</string>
     <string name="battery_info_status_full" msgid="2824614753861462808">"Plena"</string>
     <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Controlat per l\'administrador"</string>
+    <string name="enabled_by_admin" msgid="2386503803463071894">"Opció activada per l\'administrador"</string>
+    <string name="disabled_by_admin" msgid="3669999613095206948">"Opció desactivada per l\'administrador"</string>
     <string name="home" msgid="8263346537524314127">"Inici"</string>
     <string name="charge_length_format" msgid="8978516217024434156">"Fa <xliff:g id="ID_1">%1$s</xliff:g>"</string>
     <string name="remaining_length_format" msgid="7886337596669190587">"Temps restant: <xliff:g id="ID_1">%1$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-cs/strings.xml b/packages/SettingsLib/res/values-cs/strings.xml
index b03f2d8..f713ceb 100644
--- a/packages/SettingsLib/res/values-cs/strings.xml
+++ b/packages/SettingsLib/res/values-cs/strings.xml
@@ -102,8 +102,7 @@
     <string name="tts_default_rate_title" msgid="6030550998379310088">"Rychlost řeči"</string>
     <string name="tts_default_rate_summary" msgid="4061815292287182801">"Rychlost mluveného textu"</string>
     <string name="tts_default_pitch_title" msgid="6135942113172488671">"Výška"</string>
-    <!-- no translation found for tts_default_pitch_summary (1944885882882650009) -->
-    <skip />
+    <string name="tts_default_pitch_summary" msgid="1944885882882650009">"Určuje tón syntetizované řeči"</string>
     <string name="tts_default_lang_title" msgid="8018087612299820556">"Jazyk"</string>
     <string name="tts_lang_use_system" msgid="2679252467416513208">"Použít jazyk systému"</string>
     <string name="tts_lang_not_selected" msgid="7395787019276734765">"Nebyl vybrán jazyk"</string>
@@ -279,7 +278,7 @@
     <string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"Spouštět moduly vykreslení WebView jako samostatné procesy."</string>
     <string name="select_webview_provider_title" msgid="4628592979751918907">"Implementace WebView"</string>
     <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Nastavte implementaci WebView"</string>
-    <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"Vybraná implementace WebView je zakázána a nelze ji použít. Chcete ji povolit a použít?"</string>
+    <string name="select_webview_provider_toast_text" msgid="8168796505966635684">"Vybraná implementace WebView není platná, protože seznam možností implementace je zastaralý. Seznam je potřeba aktualizovat."</string>
     <string name="convert_to_file_encryption" msgid="3060156730651061223">"Převést na šifrování souborů"</string>
     <string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Převést…"</string>
     <string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Obsah je již na úrovni souborů zašifrován"</string>
@@ -312,6 +311,8 @@
     <string name="battery_info_status_not_charging" msgid="2820070506621483576">"Nenabíjí se"</string>
     <string name="battery_info_status_full" msgid="2824614753861462808">"Nabitá"</string>
     <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Spravováno administrátorem"</string>
+    <string name="enabled_by_admin" msgid="2386503803463071894">"Povoleno administrátorem"</string>
+    <string name="disabled_by_admin" msgid="3669999613095206948">"Zakázáno administrátorem"</string>
     <string name="home" msgid="8263346537524314127">"Plocha"</string>
     <string name="charge_length_format" msgid="8978516217024434156">"před <xliff:g id="ID_1">%1$s</xliff:g>"</string>
     <string name="remaining_length_format" msgid="7886337596669190587">"Zbývající čas: <xliff:g id="ID_1">%1$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-da/strings.xml b/packages/SettingsLib/res/values-da/strings.xml
index 2401a2f..d1d7b23 100644
--- a/packages/SettingsLib/res/values-da/strings.xml
+++ b/packages/SettingsLib/res/values-da/strings.xml
@@ -102,8 +102,7 @@
     <string name="tts_default_rate_title" msgid="6030550998379310088">"Talehastighed"</string>
     <string name="tts_default_rate_summary" msgid="4061815292287182801">"Oplæsningshastighed for tekst"</string>
     <string name="tts_default_pitch_title" msgid="6135942113172488671">"Toneleje"</string>
-    <!-- no translation found for tts_default_pitch_summary (1944885882882650009) -->
-    <skip />
+    <string name="tts_default_pitch_summary" msgid="1944885882882650009">"Påvirker tonen af den syntetiserede tale"</string>
     <string name="tts_default_lang_title" msgid="8018087612299820556">"Sprog"</string>
     <string name="tts_lang_use_system" msgid="2679252467416513208">"Brug systemsprog"</string>
     <string name="tts_lang_not_selected" msgid="7395787019276734765">"Der er ikke valgt sprog"</string>
@@ -279,7 +278,7 @@
     <string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"Kør WebView-gengivelse i en isoleret proces."</string>
     <string name="select_webview_provider_title" msgid="4628592979751918907">"WebView-implementering"</string>
     <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Konfigurer WebView-implementering"</string>
-    <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"Den valgte WebView-implementering er deaktiveret og skal aktiveres, før den kan bruges. Vil du aktivere den?"</string>
+    <string name="select_webview_provider_toast_text" msgid="8168796505966635684">"Den valgte WebView-implementering er ugyldig, da listen over implementeringsvalg var forældet. Listen bør nu være opdateret."</string>
     <string name="convert_to_file_encryption" msgid="3060156730651061223">"Konvertér til filkryptering"</string>
     <string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Konvertér…"</string>
     <string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Allerede filkrypteret"</string>
@@ -312,6 +311,8 @@
     <string name="battery_info_status_not_charging" msgid="2820070506621483576">"Oplader ikke"</string>
     <string name="battery_info_status_full" msgid="2824614753861462808">"Fuld"</string>
     <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Kontrolleret af administratoren"</string>
+    <string name="enabled_by_admin" msgid="2386503803463071894">"Aktiveret af administratoren"</string>
+    <string name="disabled_by_admin" msgid="3669999613095206948">"Deaktiveret af administratoren"</string>
     <string name="home" msgid="8263346537524314127">"Start"</string>
     <string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g> siden"</string>
     <string name="remaining_length_format" msgid="7886337596669190587">"<xliff:g id="ID_1">%1$s</xliff:g> tilbage"</string>
diff --git a/packages/SettingsLib/res/values-de/strings.xml b/packages/SettingsLib/res/values-de/strings.xml
index 687e962..fbd1207 100644
--- a/packages/SettingsLib/res/values-de/strings.xml
+++ b/packages/SettingsLib/res/values-de/strings.xml
@@ -102,8 +102,7 @@
     <string name="tts_default_rate_title" msgid="6030550998379310088">"Sprechgeschwindigkeit"</string>
     <string name="tts_default_rate_summary" msgid="4061815292287182801">"Geschwindigkeit, mit der der Text gesprochen wird"</string>
     <string name="tts_default_pitch_title" msgid="6135942113172488671">"Tonlage"</string>
-    <!-- no translation found for tts_default_pitch_summary (1944885882882650009) -->
-    <skip />
+    <string name="tts_default_pitch_summary" msgid="1944885882882650009">"Beeinflusst den Ton der künstlichen Sprache"</string>
     <string name="tts_default_lang_title" msgid="8018087612299820556">"Sprache"</string>
     <string name="tts_lang_use_system" msgid="2679252467416513208">"Systemsprache verwenden"</string>
     <string name="tts_lang_not_selected" msgid="7395787019276734765">"Keine Sprache ausgewählt"</string>
@@ -279,7 +278,7 @@
     <string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"WebView-Renderer isoliert ausführen."</string>
     <string name="select_webview_provider_title" msgid="4628592979751918907">"WebView-Implementierung"</string>
     <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"WebView-Implementierung festlegen"</string>
-    <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"Die ausgewählte WebView-Implementierung ist deaktiviert. Um sie nutzen zu können, muss sie aktiviert sein. Möchtest du sie aktivieren?"</string>
+    <string name="select_webview_provider_toast_text" msgid="8168796505966635684">"Die ausgewählte WebView-Implementierung ist ungültig, weil die Liste der Implementierungsmöglichkeiten veraltet war. Die Liste sollte jetzt aktualisiert sein."</string>
     <string name="convert_to_file_encryption" msgid="3060156730651061223">"Zu Dateiverschlüsselung wechseln"</string>
     <string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Wechseln…"</string>
     <string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Dateiverschlüsselung wird bereits verwendet."</string>
@@ -312,6 +311,8 @@
     <string name="battery_info_status_not_charging" msgid="2820070506621483576">"Wird nicht geladen"</string>
     <string name="battery_info_status_full" msgid="2824614753861462808">"Voll"</string>
     <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Durch den Administrator verwaltet"</string>
+    <string name="enabled_by_admin" msgid="2386503803463071894">"Vom Administrator aktiviert"</string>
+    <string name="disabled_by_admin" msgid="3669999613095206948">"Vom Administrator deaktiviert"</string>
     <string name="home" msgid="8263346537524314127">"Startseite"</string>
     <string name="charge_length_format" msgid="8978516217024434156">"Vor <xliff:g id="ID_1">%1$s</xliff:g>"</string>
     <string name="remaining_length_format" msgid="7886337596669190587">"Noch <xliff:g id="ID_1">%1$s</xliff:g> verbleibend"</string>
diff --git a/packages/SettingsLib/res/values-el/strings.xml b/packages/SettingsLib/res/values-el/strings.xml
index 0b6d2c4..dce2cf7 100644
--- a/packages/SettingsLib/res/values-el/strings.xml
+++ b/packages/SettingsLib/res/values-el/strings.xml
@@ -102,8 +102,7 @@
     <string name="tts_default_rate_title" msgid="6030550998379310088">"Ταχύτητα λόγου"</string>
     <string name="tts_default_rate_summary" msgid="4061815292287182801">"Ταχύτητα με την οποία εκφωνείται το κείμενο"</string>
     <string name="tts_default_pitch_title" msgid="6135942113172488671">"Τόνος"</string>
-    <!-- no translation found for tts_default_pitch_summary (1944885882882650009) -->
-    <skip />
+    <string name="tts_default_pitch_summary" msgid="1944885882882650009">"Επηρεάζει τον τόνο της σύνθεσης ομιλίας"</string>
     <string name="tts_default_lang_title" msgid="8018087612299820556">"Γλώσσα"</string>
     <string name="tts_lang_use_system" msgid="2679252467416513208">"Χρήση γλώσσας συστήματος"</string>
     <string name="tts_lang_not_selected" msgid="7395787019276734765">"Δεν έχει επιλεγεί γλώσσα"</string>
@@ -279,7 +278,7 @@
     <string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"Εκτέλεση λειτ.απόδοσης WebView σε μια απομονωμένη διεργασία."</string>
     <string name="select_webview_provider_title" msgid="4628592979751918907">"Υλοποίηση WebView"</string>
     <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Ορισμός υλοποίησης WebView"</string>
-    <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"Η επιλεγμένη ενσωμάτωση WebView είναι απενεργοποιημένη και θα πρέπει να ενεργοποιηθεί για να χρησιμοποιηθεί. Θέλετε να την ενεργοποιήσετε;"</string>
+    <string name="select_webview_provider_toast_text" msgid="8168796505966635684">"Η επιλεγμένη υλοποίηση WebView δεν είναι έγκυρη επειδή η λίστα των επιλογών υλοποίησης δεν είναι ενημερωμένη. Η λίστα θα πρέπει να ενημερωθεί."</string>
     <string name="convert_to_file_encryption" msgid="3060156730651061223">"Μετατροπή σε κρυπτογράφηση αρχείου"</string>
     <string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Μετατροπή…"</string>
     <string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Με κρυπτογράφηση αρχείου"</string>
@@ -312,6 +311,8 @@
     <string name="battery_info_status_not_charging" msgid="2820070506621483576">"Δεν φορτίζει"</string>
     <string name="battery_info_status_full" msgid="2824614753861462808">"Πλήρης"</string>
     <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Ελέγχονται από το διαχειριστή"</string>
+    <string name="enabled_by_admin" msgid="2386503803463071894">"Ενεργοποιήθηκε από το διαχειριστή"</string>
+    <string name="disabled_by_admin" msgid="3669999613095206948">"Απενεργοποιήθηκε από το διαχειριστή"</string>
     <string name="home" msgid="8263346537524314127">"Αρχική οθόνη"</string>
     <string name="charge_length_format" msgid="8978516217024434156">"Πριν από <xliff:g id="ID_1">%1$s</xliff:g>"</string>
     <string name="remaining_length_format" msgid="7886337596669190587">"Απομένουν <xliff:g id="ID_1">%1$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-en-rAU/strings.xml b/packages/SettingsLib/res/values-en-rAU/strings.xml
index eeb54dd..4821a71 100644
--- a/packages/SettingsLib/res/values-en-rAU/strings.xml
+++ b/packages/SettingsLib/res/values-en-rAU/strings.xml
@@ -278,7 +278,7 @@
     <string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"Run WebView renderers in an isolated process."</string>
     <string name="select_webview_provider_title" msgid="4628592979751918907">"WebView implementation"</string>
     <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Set WebView implementation"</string>
-    <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"The chosen WebView implementation is disabled and must be enabled to be used, do you wish to enable it?"</string>
+    <string name="select_webview_provider_toast_text" msgid="8168796505966635684">"The chosen WebView implementation is invalid because the list of implementation choices grew stale. The list should now be updated."</string>
     <string name="convert_to_file_encryption" msgid="3060156730651061223">"Convert to file encryption"</string>
     <string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Convert…"</string>
     <string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Already file encrypted"</string>
@@ -311,6 +311,8 @@
     <string name="battery_info_status_not_charging" msgid="2820070506621483576">"Not charging"</string>
     <string name="battery_info_status_full" msgid="2824614753861462808">"Full"</string>
     <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Controlled by admin"</string>
+    <string name="enabled_by_admin" msgid="2386503803463071894">"Enabled by administrator"</string>
+    <string name="disabled_by_admin" msgid="3669999613095206948">"Disabled by administrator"</string>
     <string name="home" msgid="8263346537524314127">"Home"</string>
     <string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g> ago"</string>
     <string name="remaining_length_format" msgid="7886337596669190587">"<xliff:g id="ID_1">%1$s</xliff:g> left"</string>
diff --git a/packages/SettingsLib/res/values-en-rGB/strings.xml b/packages/SettingsLib/res/values-en-rGB/strings.xml
index eeb54dd..4821a71 100644
--- a/packages/SettingsLib/res/values-en-rGB/strings.xml
+++ b/packages/SettingsLib/res/values-en-rGB/strings.xml
@@ -278,7 +278,7 @@
     <string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"Run WebView renderers in an isolated process."</string>
     <string name="select_webview_provider_title" msgid="4628592979751918907">"WebView implementation"</string>
     <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Set WebView implementation"</string>
-    <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"The chosen WebView implementation is disabled and must be enabled to be used, do you wish to enable it?"</string>
+    <string name="select_webview_provider_toast_text" msgid="8168796505966635684">"The chosen WebView implementation is invalid because the list of implementation choices grew stale. The list should now be updated."</string>
     <string name="convert_to_file_encryption" msgid="3060156730651061223">"Convert to file encryption"</string>
     <string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Convert…"</string>
     <string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Already file encrypted"</string>
@@ -311,6 +311,8 @@
     <string name="battery_info_status_not_charging" msgid="2820070506621483576">"Not charging"</string>
     <string name="battery_info_status_full" msgid="2824614753861462808">"Full"</string>
     <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Controlled by admin"</string>
+    <string name="enabled_by_admin" msgid="2386503803463071894">"Enabled by administrator"</string>
+    <string name="disabled_by_admin" msgid="3669999613095206948">"Disabled by administrator"</string>
     <string name="home" msgid="8263346537524314127">"Home"</string>
     <string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g> ago"</string>
     <string name="remaining_length_format" msgid="7886337596669190587">"<xliff:g id="ID_1">%1$s</xliff:g> left"</string>
diff --git a/packages/SettingsLib/res/values-en-rIN/strings.xml b/packages/SettingsLib/res/values-en-rIN/strings.xml
index eeb54dd..4821a71 100644
--- a/packages/SettingsLib/res/values-en-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-en-rIN/strings.xml
@@ -278,7 +278,7 @@
     <string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"Run WebView renderers in an isolated process."</string>
     <string name="select_webview_provider_title" msgid="4628592979751918907">"WebView implementation"</string>
     <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Set WebView implementation"</string>
-    <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"The chosen WebView implementation is disabled and must be enabled to be used, do you wish to enable it?"</string>
+    <string name="select_webview_provider_toast_text" msgid="8168796505966635684">"The chosen WebView implementation is invalid because the list of implementation choices grew stale. The list should now be updated."</string>
     <string name="convert_to_file_encryption" msgid="3060156730651061223">"Convert to file encryption"</string>
     <string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Convert…"</string>
     <string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Already file encrypted"</string>
@@ -311,6 +311,8 @@
     <string name="battery_info_status_not_charging" msgid="2820070506621483576">"Not charging"</string>
     <string name="battery_info_status_full" msgid="2824614753861462808">"Full"</string>
     <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Controlled by admin"</string>
+    <string name="enabled_by_admin" msgid="2386503803463071894">"Enabled by administrator"</string>
+    <string name="disabled_by_admin" msgid="3669999613095206948">"Disabled by administrator"</string>
     <string name="home" msgid="8263346537524314127">"Home"</string>
     <string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g> ago"</string>
     <string name="remaining_length_format" msgid="7886337596669190587">"<xliff:g id="ID_1">%1$s</xliff:g> left"</string>
diff --git a/packages/SettingsLib/res/values-es-rUS/strings.xml b/packages/SettingsLib/res/values-es-rUS/strings.xml
index b0b47f3..2d0ce02 100644
--- a/packages/SettingsLib/res/values-es-rUS/strings.xml
+++ b/packages/SettingsLib/res/values-es-rUS/strings.xml
@@ -102,8 +102,7 @@
     <string name="tts_default_rate_title" msgid="6030550998379310088">"Velocidad de voz"</string>
     <string name="tts_default_rate_summary" msgid="4061815292287182801">"Velocidad en la que se habla el texto"</string>
     <string name="tts_default_pitch_title" msgid="6135942113172488671">"Sonido"</string>
-    <!-- no translation found for tts_default_pitch_summary (1944885882882650009) -->
-    <skip />
+    <string name="tts_default_pitch_summary" msgid="1944885882882650009">"Afecta el tono de la voz sintetizada"</string>
     <string name="tts_default_lang_title" msgid="8018087612299820556">"Idioma"</string>
     <string name="tts_lang_use_system" msgid="2679252467416513208">"Usar el idioma del sistema"</string>
     <string name="tts_lang_not_selected" msgid="7395787019276734765">"Idioma no seleccionado"</string>
@@ -279,7 +278,7 @@
     <string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"Ejecutar procesadores de WebView en un proceso aislado."</string>
     <string name="select_webview_provider_title" msgid="4628592979751918907">"Implementación de WebView"</string>
     <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Configurar la implementación de WebView"</string>
-    <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"La implementación de WebView que elegiste está inhabilitada. Debes habilitarla para poder usarla. ¿Quieres hacerlo?"</string>
+    <string name="select_webview_provider_toast_text" msgid="8168796505966635684">"La implementación de WebView elegida no es válida debido a que las opciones de la lista de implementación están inactivas. Debes actualizar la lista."</string>
     <string name="convert_to_file_encryption" msgid="3060156730651061223">"Convertir a encriptación de archivo"</string>
     <string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Convertir…"</string>
     <string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Ya está encriptado"</string>
@@ -312,6 +311,8 @@
     <string name="battery_info_status_not_charging" msgid="2820070506621483576">"No se realiza la carga"</string>
     <string name="battery_info_status_full" msgid="2824614753861462808">"Cargado"</string>
     <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Controlada por el administrador"</string>
+    <string name="enabled_by_admin" msgid="2386503803463071894">"Habilitada por el administrador"</string>
+    <string name="disabled_by_admin" msgid="3669999613095206948">"Inhabilitada por el administrador"</string>
     <string name="home" msgid="8263346537524314127">"Página principal"</string>
     <string name="charge_length_format" msgid="8978516217024434156">"Hace <xliff:g id="ID_1">%1$s</xliff:g>"</string>
     <string name="remaining_length_format" msgid="7886337596669190587">"Falta <xliff:g id="ID_1">%1$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-es/strings.xml b/packages/SettingsLib/res/values-es/strings.xml
index 9eb22c1..8dcf6ab 100644
--- a/packages/SettingsLib/res/values-es/strings.xml
+++ b/packages/SettingsLib/res/values-es/strings.xml
@@ -102,8 +102,7 @@
     <string name="tts_default_rate_title" msgid="6030550998379310088">"Velocidad de la voz"</string>
     <string name="tts_default_rate_summary" msgid="4061815292287182801">"Velocidad a la que se lee el texto"</string>
     <string name="tts_default_pitch_title" msgid="6135942113172488671">"Tono"</string>
-    <!-- no translation found for tts_default_pitch_summary (1944885882882650009) -->
-    <skip />
+    <string name="tts_default_pitch_summary" msgid="1944885882882650009">"Afecta al tono de la síntesis de voz"</string>
     <string name="tts_default_lang_title" msgid="8018087612299820556">"Idioma"</string>
     <string name="tts_lang_use_system" msgid="2679252467416513208">"Usar idioma del sistema"</string>
     <string name="tts_lang_not_selected" msgid="7395787019276734765">"Idioma no seleccionado"</string>
@@ -279,7 +278,7 @@
     <string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"Ejecuta procesadores de WebView en un proceso aislado."</string>
     <string name="select_webview_provider_title" msgid="4628592979751918907">"Implementación de WebView"</string>
     <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Establecer implementación de WebView"</string>
-    <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"La implementación de WebView seleccionada está inhabilitada y debes habilitarla para utilizarla. ¿Quieres hacerlo?"</string>
+    <string name="select_webview_provider_toast_text" msgid="8168796505966635684">"La implementación de WebView seleccionada no es válida porque la lista de opciones de implementación estaba inactiva. Esta ya debería estar actualizada."</string>
     <string name="convert_to_file_encryption" msgid="3060156730651061223">"Convertir a cifrado de archivo"</string>
     <string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Convertir…"</string>
     <string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Ya está cifrado"</string>
@@ -312,6 +311,8 @@
     <string name="battery_info_status_not_charging" msgid="2820070506621483576">"No se está cargando"</string>
     <string name="battery_info_status_full" msgid="2824614753861462808">"Completa"</string>
     <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Controlada por el administrador"</string>
+    <string name="enabled_by_admin" msgid="2386503803463071894">"Habilitado por el administrador"</string>
+    <string name="disabled_by_admin" msgid="3669999613095206948">"Inhabilitado por el administrador"</string>
     <string name="home" msgid="8263346537524314127">"Inicio"</string>
     <string name="charge_length_format" msgid="8978516217024434156">"Hace <xliff:g id="ID_1">%1$s</xliff:g>"</string>
     <string name="remaining_length_format" msgid="7886337596669190587">"Tiempo restante: <xliff:g id="ID_1">%1$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-et-rEE/strings.xml b/packages/SettingsLib/res/values-et-rEE/strings.xml
index afd707b..62dd7ab 100644
--- a/packages/SettingsLib/res/values-et-rEE/strings.xml
+++ b/packages/SettingsLib/res/values-et-rEE/strings.xml
@@ -102,8 +102,7 @@
     <string name="tts_default_rate_title" msgid="6030550998379310088">"Kõnekiirus"</string>
     <string name="tts_default_rate_summary" msgid="4061815292287182801">"Teksti rääkimise kiirus"</string>
     <string name="tts_default_pitch_title" msgid="6135942113172488671">"Helikõrgus"</string>
-    <!-- no translation found for tts_default_pitch_summary (1944885882882650009) -->
-    <skip />
+    <string name="tts_default_pitch_summary" msgid="1944885882882650009">"Mõjutab sünteesitud kõne tooni"</string>
     <string name="tts_default_lang_title" msgid="8018087612299820556">"Keel"</string>
     <string name="tts_lang_use_system" msgid="2679252467416513208">"Süsteemi keele kasutamine"</string>
     <string name="tts_lang_not_selected" msgid="7395787019276734765">"Keelt pole valitud"</string>
@@ -279,7 +278,7 @@
     <string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"WebView\' renderdajad käitatakse eraldi protsessis."</string>
     <string name="select_webview_provider_title" msgid="4628592979751918907">"WebView\' rakendamine"</string>
     <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"WebView\' rakendamise seadistamine"</string>
-    <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"Valitud WebView\' rakendamisviis on keelatud ja see tuleb kasutamiseks lubada. Kas soovite selle lubada?"</string>
+    <string name="select_webview_provider_toast_text" msgid="8168796505966635684">"Valitud WebView\' rakendamine on sobimatu, kuna rakendamisvalikute loend aegus. Loendit tuleb nüüd värskendada."</string>
     <string name="convert_to_file_encryption" msgid="3060156730651061223">"Teisendamine failikrüpteeringuga andmeteks"</string>
     <string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Teisenda …"</string>
     <string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Juba failikrüpteeringuga"</string>
@@ -312,6 +311,8 @@
     <string name="battery_info_status_not_charging" msgid="2820070506621483576">"Ei lae"</string>
     <string name="battery_info_status_full" msgid="2824614753861462808">"Täis"</string>
     <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Juhib administraator"</string>
+    <string name="enabled_by_admin" msgid="2386503803463071894">"Administraator on lubanud"</string>
+    <string name="disabled_by_admin" msgid="3669999613095206948">"Administraator on keelanud"</string>
     <string name="home" msgid="8263346537524314127">"Avaekraan"</string>
     <string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g> tagasi"</string>
     <string name="remaining_length_format" msgid="7886337596669190587">"<xliff:g id="ID_1">%1$s</xliff:g> on jäänud"</string>
diff --git a/packages/SettingsLib/res/values-eu-rES/strings.xml b/packages/SettingsLib/res/values-eu-rES/strings.xml
index fb29afe..cb6f0b4 100644
--- a/packages/SettingsLib/res/values-eu-rES/strings.xml
+++ b/packages/SettingsLib/res/values-eu-rES/strings.xml
@@ -102,8 +102,7 @@
     <string name="tts_default_rate_title" msgid="6030550998379310088">"Hizketaren abiadura"</string>
     <string name="tts_default_rate_summary" msgid="4061815292287182801">"Testua zer abiaduran esaten den"</string>
     <string name="tts_default_pitch_title" msgid="6135942113172488671">"Tonua"</string>
-    <!-- no translation found for tts_default_pitch_summary (1944885882882650009) -->
-    <skip />
+    <string name="tts_default_pitch_summary" msgid="1944885882882650009">"Hizketa sintetizatuaren tonuari eragiten dio"</string>
     <string name="tts_default_lang_title" msgid="8018087612299820556">"Hizkuntza"</string>
     <string name="tts_lang_use_system" msgid="2679252467416513208">"Erabili sistemaren hizkuntza"</string>
     <string name="tts_lang_not_selected" msgid="7395787019276734765">"Ez da hizkuntza hautatu"</string>
@@ -279,7 +278,7 @@
     <string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"Exekutatu WebView errendatzaileak prozesu isolatu batean."</string>
     <string name="select_webview_provider_title" msgid="4628592979751918907">"WebView implementation"</string>
     <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Set WebView implementation"</string>
-    <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"Desgaituta dago aukeratu den WebView inplementazioa. Erabili nahi izanez gero, gaitu egin behar duzu. Gaitu nahi al duzu?"</string>
+    <string name="select_webview_provider_toast_text" msgid="8168796505966635684">"Aukeratutako WebView inplementazioak ez du balio inplementazioen aukeren zerrenda zaharkituta gelditu delako. Zerrenda eguneratu behar da."</string>
     <string name="convert_to_file_encryption" msgid="3060156730651061223">"Eman fitxategietan oinarritutako enkriptatzea"</string>
     <string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Enkriptatu…"</string>
     <string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Fitxategietan oinarritutako enkriptatzea dauka dagoeneko"</string>
@@ -312,6 +311,8 @@
     <string name="battery_info_status_not_charging" msgid="2820070506621483576">"Ez da kargatzen ari"</string>
     <string name="battery_info_status_full" msgid="2824614753861462808">"Beteta"</string>
     <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Administratzaileak kontrolatzen du"</string>
+    <string name="enabled_by_admin" msgid="2386503803463071894">"Administratzaileak gaitu du"</string>
+    <string name="disabled_by_admin" msgid="3669999613095206948">"Administratzaileak desgaitu du"</string>
     <string name="home" msgid="8263346537524314127">"Hasierako pantaila"</string>
     <string name="charge_length_format" msgid="8978516217024434156">"Duela <xliff:g id="ID_1">%1$s</xliff:g>"</string>
     <string name="remaining_length_format" msgid="7886337596669190587">"<xliff:g id="ID_1">%1$s</xliff:g> guztiz kargatu arte"</string>
diff --git a/packages/SettingsLib/res/values-fa/strings.xml b/packages/SettingsLib/res/values-fa/strings.xml
index 8f07b22..e7cbd1e 100644
--- a/packages/SettingsLib/res/values-fa/strings.xml
+++ b/packages/SettingsLib/res/values-fa/strings.xml
@@ -102,8 +102,7 @@
     <string name="tts_default_rate_title" msgid="6030550998379310088">"سرعت گفتار"</string>
     <string name="tts_default_rate_summary" msgid="4061815292287182801">"سرعتی که متن خوانده می‌شود"</string>
     <string name="tts_default_pitch_title" msgid="6135942113172488671">"زیر و بمی صدا"</string>
-    <!-- no translation found for tts_default_pitch_summary (1944885882882650009) -->
-    <skip />
+    <string name="tts_default_pitch_summary" msgid="1944885882882650009">"بر صدای متن گفته شده تأثیر می‌گذارد"</string>
     <string name="tts_default_lang_title" msgid="8018087612299820556">"زبان"</string>
     <string name="tts_lang_use_system" msgid="2679252467416513208">"استفاده از زبان سیستم"</string>
     <string name="tts_lang_not_selected" msgid="7395787019276734765">"زبان انتخاب نشده است"</string>
@@ -275,11 +274,11 @@
     <string name="inactive_app_active_summary" msgid="4174921824958516106">"فعال. برای تغییر حالت ضربه بزنید."</string>
     <string name="runningservices_settings_title" msgid="8097287939865165213">"سرویس‌های در حال اجرا"</string>
     <string name="runningservices_settings_summary" msgid="854608995821032748">"مشاهده و کنترل سرویس‌های در حال اجرای فعلی"</string>
-    <string name="enable_webview_multiprocess" msgid="3405948012467585908">"‏فعال کردن WebView چند پردازشی"</string>
-    <string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"‏اجرای تولیدکننده تصویر WebView در یک پردازش مجزا."</string>
-    <string name="select_webview_provider_title" msgid="4628592979751918907">"‏اجرای WebView"</string>
-    <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"‏تنظیم اجرای WebView"</string>
-    <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"‏پیاده‌سازی WebView انتخاب‌شده غیرفعال شده است و برای استفاده شدن باید فعال شود؛ می‌خواهید آن را فعال کنید؟"</string>
+    <string name="enable_webview_multiprocess" msgid="3405948012467585908">"فعال کردن وب‌نمای چندپردازشی"</string>
+    <string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"اجرای تولیدکننده تصویر وب‌نما در یک پردازش مجزا."</string>
+    <string name="select_webview_provider_title" msgid="4628592979751918907">"اجرای وب‌نما"</string>
+    <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"تنظیم اجرای وب‌نما"</string>
+    <string name="select_webview_provider_toast_text" msgid="8168796505966635684">"اجرای وب‌نمای انتخابی نامعتبر است چون فهرست گزینه‌های اجرای انتخابی قدیمی شده است. این فهرست اکنون باید به‌روزرسانی شود."</string>
     <string name="convert_to_file_encryption" msgid="3060156730651061223">"تبدیل به رمزگذاری برحسب فایل"</string>
     <string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"تبدیل…"</string>
     <string name="convert_to_file_encryption_done" msgid="7859766358000523953">"از قبل به رمزگذاری بر حسب فایل تبدیل شده است"</string>
@@ -312,6 +311,8 @@
     <string name="battery_info_status_not_charging" msgid="2820070506621483576">"شارژ نمی‌شود"</string>
     <string name="battery_info_status_full" msgid="2824614753861462808">"پر"</string>
     <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"توسط سرپرست سیستم کنترل می‌شود"</string>
+    <string name="enabled_by_admin" msgid="2386503803463071894">"سرپرست آن را فعال کرده است"</string>
+    <string name="disabled_by_admin" msgid="3669999613095206948">"سرپرست آن را غیرفعال کرده است"</string>
     <string name="home" msgid="8263346537524314127">"صفحه اصلی"</string>
     <string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g> قبل"</string>
     <string name="remaining_length_format" msgid="7886337596669190587">"<xliff:g id="ID_1">%1$s</xliff:g> باقی مانده است"</string>
diff --git a/packages/SettingsLib/res/values-fi/strings.xml b/packages/SettingsLib/res/values-fi/strings.xml
index cdff87ba..bb3ad97 100644
--- a/packages/SettingsLib/res/values-fi/strings.xml
+++ b/packages/SettingsLib/res/values-fi/strings.xml
@@ -102,8 +102,7 @@
     <string name="tts_default_rate_title" msgid="6030550998379310088">"Puheen nopeus"</string>
     <string name="tts_default_rate_summary" msgid="4061815292287182801">"Tekstin puhumisnopeus"</string>
     <string name="tts_default_pitch_title" msgid="6135942113172488671">"Äänenkorkeus"</string>
-    <!-- no translation found for tts_default_pitch_summary (1944885882882650009) -->
-    <skip />
+    <string name="tts_default_pitch_summary" msgid="1944885882882650009">"Tämä vaikuttaa syntetisoidun puheen äänensävyyn."</string>
     <string name="tts_default_lang_title" msgid="8018087612299820556">"Kieli"</string>
     <string name="tts_lang_use_system" msgid="2679252467416513208">"Käytä järjestelmän kieltä"</string>
     <string name="tts_lang_not_selected" msgid="7395787019276734765">"Kieltä ei ole valittu"</string>
@@ -279,7 +278,7 @@
     <string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"Suorita WebView\'n hahmontajat erillisinä prosesseina."</string>
     <string name="select_webview_provider_title" msgid="4628592979751918907">"WebView-käyttöönotto"</string>
     <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Määritä WebView-käyttöönotto"</string>
-    <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"Valittu WebView-käyttöönotto on poistettu käytöstä. Haluatko ottaa sen käyttöön?"</string>
+    <string name="select_webview_provider_toast_text" msgid="8168796505966635684">"Valittu WebView-toteutus ei kelpaa, sillä toteutusvaihtoehtojen lista vanhentui. Listan pitäisi nyt olla ajan tasalla."</string>
     <string name="convert_to_file_encryption" msgid="3060156730651061223">"Muunna tiedostojen salaukseksi"</string>
     <string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Muunna…"</string>
     <string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Tiedostot on jo salattu."</string>
@@ -312,6 +311,8 @@
     <string name="battery_info_status_not_charging" msgid="2820070506621483576">"Ei laturissa"</string>
     <string name="battery_info_status_full" msgid="2824614753861462808">"Täynnä"</string>
     <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Järjestelmänvalvoja hallinnoi tätä asetusta."</string>
+    <string name="enabled_by_admin" msgid="2386503803463071894">"Järjestelmänvalvojan käyttöön ottama"</string>
+    <string name="disabled_by_admin" msgid="3669999613095206948">"Järjestelmänvalvojan käytöstä poistama"</string>
     <string name="home" msgid="8263346537524314127">"Aloitusnäyttö"</string>
     <string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g> sitten"</string>
     <string name="remaining_length_format" msgid="7886337596669190587">"<xliff:g id="ID_1">%1$s</xliff:g> jäljellä"</string>
diff --git a/packages/SettingsLib/res/values-fr-rCA/strings.xml b/packages/SettingsLib/res/values-fr-rCA/strings.xml
index a4552a5..1f12f18 100644
--- a/packages/SettingsLib/res/values-fr-rCA/strings.xml
+++ b/packages/SettingsLib/res/values-fr-rCA/strings.xml
@@ -102,8 +102,7 @@
     <string name="tts_default_rate_title" msgid="6030550998379310088">"Cadence"</string>
     <string name="tts_default_rate_summary" msgid="4061815292287182801">"Vitesse à laquelle le texte est énoncé"</string>
     <string name="tts_default_pitch_title" msgid="6135942113172488671">"Ton"</string>
-    <!-- no translation found for tts_default_pitch_summary (1944885882882650009) -->
-    <skip />
+    <string name="tts_default_pitch_summary" msgid="1944885882882650009">"Touche le ton utilisé pour la synthèse vocale"</string>
     <string name="tts_default_lang_title" msgid="8018087612299820556">"Langue"</string>
     <string name="tts_lang_use_system" msgid="2679252467416513208">"Utiliser la langue du système"</string>
     <string name="tts_lang_not_selected" msgid="7395787019276734765">"Langue non sélectionnée"</string>
@@ -279,7 +278,7 @@
     <string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"Exécuter moteurs de rendu WebView dans un processus isolé."</string>
     <string name="select_webview_provider_title" msgid="4628592979751918907">"Mise en œuvre WebView"</string>
     <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Définir la mise en œuvre WebView"</string>
-    <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"La mise en œuvre WebView sélectionnée est désactivée. Vous devez l\'activer pour l\'utiliser. Souhaitez-vous l\'activer?"</string>
+    <string name="select_webview_provider_toast_text" msgid="8168796505966635684">"La mise en œuvre WebView sélectionnée n\'est pas valide, car la liste de sélections de mises en œuvre est désormais obsolète. Cette liste devrait être mise à jour."</string>
     <string name="convert_to_file_encryption" msgid="3060156730651061223">"Convertir en chiffrement basé sur un fichier"</string>
     <string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Convertir..."</string>
     <string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Déjà chiffré par un fichier"</string>
@@ -312,6 +311,8 @@
     <string name="battery_info_status_not_charging" msgid="2820070506621483576">"N\'est pas en charge"</string>
     <string name="battery_info_status_full" msgid="2824614753861462808">"Pleine"</string>
     <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Contrôlé par l\'administrateur"</string>
+    <string name="enabled_by_admin" msgid="2386503803463071894">"Activé par l\'administrateur"</string>
+    <string name="disabled_by_admin" msgid="3669999613095206948">"Désactivé par l\'administrateur"</string>
     <string name="home" msgid="8263346537524314127">"Accueil"</string>
     <string name="charge_length_format" msgid="8978516217024434156">"Il y a <xliff:g id="ID_1">%1$s</xliff:g>"</string>
     <string name="remaining_length_format" msgid="7886337596669190587">"Durée restante :<xliff:g id="ID_1">%1$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-fr/strings.xml b/packages/SettingsLib/res/values-fr/strings.xml
index 09c6e78..3dc2a6a 100644
--- a/packages/SettingsLib/res/values-fr/strings.xml
+++ b/packages/SettingsLib/res/values-fr/strings.xml
@@ -102,8 +102,7 @@
     <string name="tts_default_rate_title" msgid="6030550998379310088">"Cadence"</string>
     <string name="tts_default_rate_summary" msgid="4061815292287182801">"Vitesse à laquelle le texte est énoncé"</string>
     <string name="tts_default_pitch_title" msgid="6135942113172488671">"Ton"</string>
-    <!-- no translation found for tts_default_pitch_summary (1944885882882650009) -->
-    <skip />
+    <string name="tts_default_pitch_summary" msgid="1944885882882650009">"Affecte le ton utilisé pour la synthèse vocale"</string>
     <string name="tts_default_lang_title" msgid="8018087612299820556">"Langue"</string>
     <string name="tts_lang_use_system" msgid="2679252467416513208">"Utiliser la langue du système"</string>
     <string name="tts_lang_not_selected" msgid="7395787019276734765">"Langue non sélectionnée"</string>
@@ -279,7 +278,7 @@
     <string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"Exécuter moteurs de rendu WebView dans un processus isolé."</string>
     <string name="select_webview_provider_title" msgid="4628592979751918907">"Mise en œuvre WebView"</string>
     <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Définir la mise en œuvre WebView"</string>
-    <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"La mise en œuvre WebView sélectionnée est désactivée. Vous devez l\'activer pour l\'utiliser. Souhaitez-vous l\'activer ?"</string>
+    <string name="select_webview_provider_toast_text" msgid="8168796505966635684">"La mise en œuvre WebView sélectionnée n\'est pas valide, car la liste de sélections de mises en œuvre est désormais obsolète. Cette liste ne doit pas être mise à jour."</string>
     <string name="convert_to_file_encryption" msgid="3060156730651061223">"Convertir en chiffrement basé sur un fichier"</string>
     <string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Convertir…"</string>
     <string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Déjà chiffré via un fichier"</string>
@@ -312,6 +311,8 @@
     <string name="battery_info_status_not_charging" msgid="2820070506621483576">"Débranchée"</string>
     <string name="battery_info_status_full" msgid="2824614753861462808">"pleine"</string>
     <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Contrôlé par l\'administrateur"</string>
+    <string name="enabled_by_admin" msgid="2386503803463071894">"Activé par l\'administrateur"</string>
+    <string name="disabled_by_admin" msgid="3669999613095206948">"Désactivé par l\'administrateur"</string>
     <string name="home" msgid="8263346537524314127">"Accueil"</string>
     <string name="charge_length_format" msgid="8978516217024434156">"Il y a <xliff:g id="ID_1">%1$s</xliff:g>"</string>
     <string name="remaining_length_format" msgid="7886337596669190587">"Il reste <xliff:g id="ID_1">%1$s</xliff:g>."</string>
diff --git a/packages/SettingsLib/res/values-gl-rES/strings.xml b/packages/SettingsLib/res/values-gl-rES/strings.xml
index 861756f..3715919 100644
--- a/packages/SettingsLib/res/values-gl-rES/strings.xml
+++ b/packages/SettingsLib/res/values-gl-rES/strings.xml
@@ -102,8 +102,7 @@
     <string name="tts_default_rate_title" msgid="6030550998379310088">"Velocidade da fala"</string>
     <string name="tts_default_rate_summary" msgid="4061815292287182801">"Velocidade á que se di o texto"</string>
     <string name="tts_default_pitch_title" msgid="6135942113172488671">"Ton"</string>
-    <!-- no translation found for tts_default_pitch_summary (1944885882882650009) -->
-    <skip />
+    <string name="tts_default_pitch_summary" msgid="1944885882882650009">"Afecta ao ton da voz sintetizada"</string>
     <string name="tts_default_lang_title" msgid="8018087612299820556">"Idioma"</string>
     <string name="tts_lang_use_system" msgid="2679252467416513208">"Utilizar idioma do sistema"</string>
     <string name="tts_lang_not_selected" msgid="7395787019276734765">"Idioma non seleccionado"</string>
@@ -279,7 +278,7 @@
     <string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"Executa os procesadores de WebView nun proceso illado."</string>
     <string name="select_webview_provider_title" msgid="4628592979751918907">"Implementación de WebView"</string>
     <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Definir implementación de WebView"</string>
-    <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"A implementación de WebView escollida está desactivada e, para poder usala, debe estar activada. Queres activala?"</string>
+    <string name="select_webview_provider_toast_text" msgid="8168796505966635684">"A implementación de WebView seleccionada non é válida porque a lista de opcións de implementación estaba inactiva. A lista xa debería estar actualizada."</string>
     <string name="convert_to_file_encryption" msgid="3060156730651061223">"Converter no encriptado baseado en ficheiros"</string>
     <string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Converter..."</string>
     <string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Xa se encriptou o ficheiro"</string>
@@ -312,6 +311,8 @@
     <string name="battery_info_status_not_charging" msgid="2820070506621483576">"Non está cargando"</string>
     <string name="battery_info_status_full" msgid="2824614753861462808">"Completa"</string>
     <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Opción controlada polo administrador"</string>
+    <string name="enabled_by_admin" msgid="2386503803463071894">"Activado polo administrador"</string>
+    <string name="disabled_by_admin" msgid="3669999613095206948">"Desactivado polo administrador"</string>
     <string name="home" msgid="8263346537524314127">"Inicio"</string>
     <string name="charge_length_format" msgid="8978516217024434156">"Hai <xliff:g id="ID_1">%1$s</xliff:g>"</string>
     <string name="remaining_length_format" msgid="7886337596669190587">"Tempo restante: <xliff:g id="ID_1">%1$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-gu-rIN/strings.xml b/packages/SettingsLib/res/values-gu-rIN/strings.xml
index c5cac9d..c77aeb6 100644
--- a/packages/SettingsLib/res/values-gu-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-gu-rIN/strings.xml
@@ -102,8 +102,7 @@
     <string name="tts_default_rate_title" msgid="6030550998379310088">"વાણી દર"</string>
     <string name="tts_default_rate_summary" msgid="4061815292287182801">"ટેક્સ્ટ બોલાયેલ છે તે ઝડપ"</string>
     <string name="tts_default_pitch_title" msgid="6135942113172488671">"પિચ"</string>
-    <!-- no translation found for tts_default_pitch_summary (1944885882882650009) -->
-    <skip />
+    <string name="tts_default_pitch_summary" msgid="1944885882882650009">"સિન્થેસાઇઝ કરેલ વાણીના ટોન પર અસર કરે છે"</string>
     <string name="tts_default_lang_title" msgid="8018087612299820556">"ભાષા"</string>
     <string name="tts_lang_use_system" msgid="2679252467416513208">"સિસ્ટમ ભાષાનો ઉપયોગ કરો"</string>
     <string name="tts_lang_not_selected" msgid="7395787019276734765">"ભાષા પસંદ કરેલ નથી"</string>
@@ -279,7 +278,7 @@
     <string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"પૃથક પ્રક્રિયામાં WebView રેંડરર્સ ચલાવો."</string>
     <string name="select_webview_provider_title" msgid="4628592979751918907">"WebView અમલીકરણ"</string>
     <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"WebView અમલીકરણ સેટ કરો"</string>
-    <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"પસંદ કરેલ WebView અમલીકરણ અક્ષમ કરેલ છે અને ઉપયોગ કરવા માટે સક્ષમ કરવું આવશ્યક છે, શું તમે તેને સક્ષમ કરવા માગો છો?"</string>
+    <string name="select_webview_provider_toast_text" msgid="8168796505966635684">"પસંદ કરેલ WebView અમલીકરણ અમાન્ય છે કારણ કે અમલીકરણ પસંદગીઓની સૂચિમાં જૂની છે. સૂચિ હવે અપડેટ કરવી જોઈએ."</string>
     <string name="convert_to_file_encryption" msgid="3060156730651061223">"ફાઇલ એન્ક્રિપ્શનમાં રૂપાંતરિત કરો"</string>
     <string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"રૂપાંતરિત કરો..."</string>
     <string name="convert_to_file_encryption_done" msgid="7859766358000523953">"ફાઇલ પહેલેથી જ એન્ક્રિપ્ટ કરેલ છે"</string>
@@ -312,6 +311,8 @@
     <string name="battery_info_status_not_charging" msgid="2820070506621483576">"ચાર્જ થઈ રહ્યું નથી"</string>
     <string name="battery_info_status_full" msgid="2824614753861462808">"પૂર્ણ"</string>
     <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"વ્યવસ્થાપક દ્વારા નિયંત્રિત"</string>
+    <string name="enabled_by_admin" msgid="2386503803463071894">"વ્યવસ્થાપક દ્વારા સક્ષમ કરેલ"</string>
+    <string name="disabled_by_admin" msgid="3669999613095206948">"વ્યવસ્થાપક દ્વારા અક્ષમ કરેલ"</string>
     <string name="home" msgid="8263346537524314127">"હોમ"</string>
     <string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g> પહેલાં"</string>
     <string name="remaining_length_format" msgid="7886337596669190587">"<xliff:g id="ID_1">%1$s</xliff:g> બાકી"</string>
diff --git a/packages/SettingsLib/res/values-hi/strings.xml b/packages/SettingsLib/res/values-hi/strings.xml
index 33e243b..e8a47cb 100644
--- a/packages/SettingsLib/res/values-hi/strings.xml
+++ b/packages/SettingsLib/res/values-hi/strings.xml
@@ -102,8 +102,7 @@
     <string name="tts_default_rate_title" msgid="6030550998379310088">"बोली दर"</string>
     <string name="tts_default_rate_summary" msgid="4061815292287182801">"बोलने की गति तय करें"</string>
     <string name="tts_default_pitch_title" msgid="6135942113172488671">"पिच"</string>
-    <!-- no translation found for tts_default_pitch_summary (1944885882882650009) -->
-    <skip />
+    <string name="tts_default_pitch_summary" msgid="1944885882882650009">"कृत्रिम बोली के लहजे को प्रभावित करता है"</string>
     <string name="tts_default_lang_title" msgid="8018087612299820556">"भाषा"</string>
     <string name="tts_lang_use_system" msgid="2679252467416513208">"सिस्‍टम भाषा का उपयोग करें"</string>
     <string name="tts_lang_not_selected" msgid="7395787019276734765">"भाषा नहीं चुनी गई है"</string>
@@ -279,7 +278,7 @@
     <string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"किसी अलग प्रक्रिया में WebView रेंडरर चलाएं."</string>
     <string name="select_webview_provider_title" msgid="4628592979751918907">"WebView कार्यान्वयन"</string>
     <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"WebView कार्यान्वयन सेट करें"</string>
-    <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"चुना गया WebView कार्यान्वयन अक्षम है और उसे उपयोग करने के लिए सक्षम किया जाना आवश्यक है, क्या आप उसे सक्षम करना चाहते हैं?"</string>
+    <string name="select_webview_provider_toast_text" msgid="8168796505966635684">"चुना गया WebView कार्यान्वयन अमान्य है क्योंकि कार्यान्वयन विकल्पों की सूची पुरानी हो चुकी है. सूची को अब अपडेट किया जाना चाहिए."</string>
     <string name="convert_to_file_encryption" msgid="3060156730651061223">"फ़ाइल एन्क्रिप्शन में रूपांतरित करें"</string>
     <string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"रूपांतरित करें..."</string>
     <string name="convert_to_file_encryption_done" msgid="7859766358000523953">"फ़ाइल पहले से एन्क्रिप्ट की हुई है"</string>
@@ -312,6 +311,8 @@
     <string name="battery_info_status_not_charging" msgid="2820070506621483576">"चार्ज नहीं हो रही है"</string>
     <string name="battery_info_status_full" msgid="2824614753861462808">"पूरी"</string>
     <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"व्यवस्थापक द्वारा नियंत्रित"</string>
+    <string name="enabled_by_admin" msgid="2386503803463071894">"व्यवस्थापक द्वारा सक्षम किया गया"</string>
+    <string name="disabled_by_admin" msgid="3669999613095206948">"व्यवस्थापक द्वारा अक्षम किया गया"</string>
     <string name="home" msgid="8263346537524314127">"होम"</string>
     <string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g> पहले"</string>
     <string name="remaining_length_format" msgid="7886337596669190587">"<xliff:g id="ID_1">%1$s</xliff:g> शेष"</string>
diff --git a/packages/SettingsLib/res/values-hr/strings.xml b/packages/SettingsLib/res/values-hr/strings.xml
index ed11c31..320ebc1 100644
--- a/packages/SettingsLib/res/values-hr/strings.xml
+++ b/packages/SettingsLib/res/values-hr/strings.xml
@@ -102,8 +102,7 @@
     <string name="tts_default_rate_title" msgid="6030550998379310088">"Brzina govora"</string>
     <string name="tts_default_rate_summary" msgid="4061815292287182801">"Brzina kojom se izgovara tekst"</string>
     <string name="tts_default_pitch_title" msgid="6135942113172488671">"Visina glasa"</string>
-    <!-- no translation found for tts_default_pitch_summary (1944885882882650009) -->
-    <skip />
+    <string name="tts_default_pitch_summary" msgid="1944885882882650009">"Utječe na ton sintetiziranog govora"</string>
     <string name="tts_default_lang_title" msgid="8018087612299820556">"Jezik"</string>
     <string name="tts_lang_use_system" msgid="2679252467416513208">"upotrijebi jezik sustava"</string>
     <string name="tts_lang_not_selected" msgid="7395787019276734765">"Jezik nije odabran"</string>
@@ -279,7 +278,7 @@
     <string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"Pokreni ispunjivače WebViewa u izoliranim procesima."</string>
     <string name="select_webview_provider_title" msgid="4628592979751918907">"Implementacija WebViewa"</string>
     <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Postavi implementaciju WebViewa"</string>
-    <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"Odabrana implementacija WebViewa onemogućena je i morate je omogućiti da biste je mogli upotrebljavati. Želite li je omogućiti?"</string>
+    <string name="select_webview_provider_toast_text" msgid="8168796505966635684">"Odabrana implementacija WebViewa nije važeća jer je popis odabira za implementaciju zastario. Popis se treba ažurirati."</string>
     <string name="convert_to_file_encryption" msgid="3060156730651061223">"Pretvori u enkripciju datoteka"</string>
     <string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Pretvori…"</string>
     <string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Enkripcija datoteka već je izvršena"</string>
@@ -312,6 +311,8 @@
     <string name="battery_info_status_not_charging" msgid="2820070506621483576">"Ne puni se"</string>
     <string name="battery_info_status_full" msgid="2824614753861462808">"Puna"</string>
     <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Kontrolira administrator"</string>
+    <string name="enabled_by_admin" msgid="2386503803463071894">"Omogućio administrator"</string>
+    <string name="disabled_by_admin" msgid="3669999613095206948">"Onemogućio administrator"</string>
     <string name="home" msgid="8263346537524314127">"Početni zaslon"</string>
     <string name="charge_length_format" msgid="8978516217024434156">"Prije <xliff:g id="ID_1">%1$s</xliff:g>"</string>
     <string name="remaining_length_format" msgid="7886337596669190587">"Još <xliff:g id="ID_1">%1$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-hu/strings.xml b/packages/SettingsLib/res/values-hu/strings.xml
index 2e0e4dd..4ea4528 100644
--- a/packages/SettingsLib/res/values-hu/strings.xml
+++ b/packages/SettingsLib/res/values-hu/strings.xml
@@ -278,7 +278,7 @@
     <string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"WebView-megjelenítők futtatása külön folyamatként."</string>
     <string name="select_webview_provider_title" msgid="4628592979751918907">"WebView-megvalósítás"</string>
     <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"WebView-megvalósítás beállítása"</string>
-    <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"A kiválasztott WebView-megvalósítás le van tiltva, a használathoz viszont engedélyezni kell. Szeretné engedélyezni?"</string>
+    <string name="select_webview_provider_toast_text" msgid="8168796505966635684">"A kiválasztott WebView-megvalósítás érvénytelen, mert a megvalósítási lehetőségeket tartalmazó lista elévült. A listát elvileg már frissítették."</string>
     <string name="convert_to_file_encryption" msgid="3060156730651061223">"Konvertálás fájlalapú titkosításra"</string>
     <string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Konvertálás…"</string>
     <string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Már fájlalapú titkosítást használ"</string>
@@ -311,6 +311,8 @@
     <string name="battery_info_status_not_charging" msgid="2820070506621483576">"Nem töltődik"</string>
     <string name="battery_info_status_full" msgid="2824614753861462808">"Feltöltve"</string>
     <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Rendszergazda által irányítva"</string>
+    <string name="enabled_by_admin" msgid="2386503803463071894">"Engedélyezve a rendszergazda által"</string>
+    <string name="disabled_by_admin" msgid="3669999613095206948">"Letiltva a rendszergazda által"</string>
     <string name="home" msgid="8263346537524314127">"Főoldal"</string>
     <string name="charge_length_format" msgid="8978516217024434156">"Ennyi ideje: <xliff:g id="ID_1">%1$s</xliff:g>"</string>
     <string name="remaining_length_format" msgid="7886337596669190587">"<xliff:g id="ID_1">%1$s</xliff:g> van hátra"</string>
diff --git a/packages/SettingsLib/res/values-hy-rAM/strings.xml b/packages/SettingsLib/res/values-hy-rAM/strings.xml
index 087211d..046ea48 100644
--- a/packages/SettingsLib/res/values-hy-rAM/strings.xml
+++ b/packages/SettingsLib/res/values-hy-rAM/strings.xml
@@ -102,8 +102,7 @@
     <string name="tts_default_rate_title" msgid="6030550998379310088">"Խոսքի գնահատական"</string>
     <string name="tts_default_rate_summary" msgid="4061815292287182801">"Տեքստի արտասանման արագությունը"</string>
     <string name="tts_default_pitch_title" msgid="6135942113172488671">"Բարձրություն"</string>
-    <!-- no translation found for tts_default_pitch_summary (1944885882882650009) -->
-    <skip />
+    <string name="tts_default_pitch_summary" msgid="1944885882882650009">"Ազդում է սինթեզած խոսքի ձայներանգի վրա"</string>
     <string name="tts_default_lang_title" msgid="8018087612299820556">"Լեզու"</string>
     <string name="tts_lang_use_system" msgid="2679252467416513208">"Օգտագործել համակարգի լեզուն"</string>
     <string name="tts_lang_not_selected" msgid="7395787019276734765">"Լեզուն ընտրված չէ"</string>
@@ -279,7 +278,7 @@
     <string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"Գործարկել WebView-ի մշակիչները առանձնացված գործընթացում:"</string>
     <string name="select_webview_provider_title" msgid="4628592979751918907">"WebView-ի իրականացում"</string>
     <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Ընտրեք WebView-ի իրականացումը"</string>
-    <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"WebView-ի իրականացման ընտրված եղանակն անջատված է և օգտագործելու համար պետք է նախ միացվի: Միացնե՞լ:"</string>
+    <string name="select_webview_provider_toast_text" msgid="8168796505966635684">"WebView-ի իրագործման ընտրված եղանակն անվավեր է, քանի որ իրագործման ընտրանքների ցանկը արդի չէ: Այն այժմ կթարմացվի:"</string>
     <string name="convert_to_file_encryption" msgid="3060156730651061223">"Վերածել ֆայլային գաղտնագրման"</string>
     <string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Փոխարկել…"</string>
     <string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Ֆայլային գաղտնագրումն արդեն կատարվել է"</string>
@@ -312,6 +311,8 @@
     <string name="battery_info_status_not_charging" msgid="2820070506621483576">"Չի լիցքավորվում"</string>
     <string name="battery_info_status_full" msgid="2824614753861462808">"Լիցքավորված"</string>
     <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Վերահսկվում է ադմինիստրատորի կողմից"</string>
+    <string name="enabled_by_admin" msgid="2386503803463071894">"Միացված է ադմինիստրատորի կողմից"</string>
+    <string name="disabled_by_admin" msgid="3669999613095206948">"Կասեցված է ադմինիստրատորի կողմից"</string>
     <string name="home" msgid="8263346537524314127">"Գլխավոր էջ"</string>
     <string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g> առաջ"</string>
     <string name="remaining_length_format" msgid="7886337596669190587">"Մնացել է <xliff:g id="ID_1">%1$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-in/strings.xml b/packages/SettingsLib/res/values-in/strings.xml
index eb16161..02c747a 100644
--- a/packages/SettingsLib/res/values-in/strings.xml
+++ b/packages/SettingsLib/res/values-in/strings.xml
@@ -278,7 +278,7 @@
     <string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"Jalankan perender WebView dalam proses yang terisolasi."</string>
     <string name="select_webview_provider_title" msgid="4628592979751918907">"Penerapan WebView"</string>
     <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Setel penerapan WebView"</string>
-    <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"Implementasi WebView yang dipilih telah dinonaktifkan, dan harus diaktifkan agar dapat digunakan. Ingin mengaktifkannya?"</string>
+    <string name="select_webview_provider_toast_text" msgid="8168796505966635684">"Implementasi WebView yang dipilih tidak valid karena daftar pilihan implementasi sudah usang. Daftar tersebut sekarang harus diperbarui."</string>
     <string name="convert_to_file_encryption" msgid="3060156730651061223">"Konversi ke enkripsi file"</string>
     <string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Konversi..."</string>
     <string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Sudah dienkripsi berbasis file"</string>
@@ -311,6 +311,8 @@
     <string name="battery_info_status_not_charging" msgid="2820070506621483576">"Tidak mengisi daya"</string>
     <string name="battery_info_status_full" msgid="2824614753861462808">"Penuh"</string>
     <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Dikontrol oleh admin"</string>
+    <string name="enabled_by_admin" msgid="2386503803463071894">"Diaktifkan oleh administrator"</string>
+    <string name="disabled_by_admin" msgid="3669999613095206948">"Dinonaktifkan oleh administrator"</string>
     <string name="home" msgid="8263346537524314127">"Layar Utama"</string>
     <string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g> lalu"</string>
     <string name="remaining_length_format" msgid="7886337596669190587">"Tersisa <xliff:g id="ID_1">%1$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-is-rIS/strings.xml b/packages/SettingsLib/res/values-is-rIS/strings.xml
index 5ff0540..17a2f08 100644
--- a/packages/SettingsLib/res/values-is-rIS/strings.xml
+++ b/packages/SettingsLib/res/values-is-rIS/strings.xml
@@ -102,8 +102,7 @@
     <string name="tts_default_rate_title" msgid="6030550998379310088">"Talhraði"</string>
     <string name="tts_default_rate_summary" msgid="4061815292287182801">"Hraði talaðs texta"</string>
     <string name="tts_default_pitch_title" msgid="6135942113172488671">"Tónhæð"</string>
-    <!-- no translation found for tts_default_pitch_summary (1944885882882650009) -->
-    <skip />
+    <string name="tts_default_pitch_summary" msgid="1944885882882650009">"Hefur áhrif á raddblæ talgervils"</string>
     <string name="tts_default_lang_title" msgid="8018087612299820556">"Tungumál"</string>
     <string name="tts_lang_use_system" msgid="2679252467416513208">"Nota tungumál kerfis"</string>
     <string name="tts_lang_not_selected" msgid="7395787019276734765">"Tungumál ekki valið"</string>
@@ -279,7 +278,7 @@
     <string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"Keyra WebView teiknun í lokuðu ferli."</string>
     <string name="select_webview_provider_title" msgid="4628592979751918907">"Innleiðing WebView"</string>
     <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Stilla innleiðingu WebView"</string>
-    <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"Slökkt er á valinni innleiðingu WebView. Kveikja þarf á henni til að hægt sé að nota hana. Viltu gera það?"</string>
+    <string name="select_webview_provider_toast_text" msgid="8168796505966635684">"Sú innleiðing WebView sem hér var valin er ógild vegna þess að innleiðingalistinn rann út. Uppfæra þarf listann."</string>
     <string name="convert_to_file_encryption" msgid="3060156730651061223">"Umbreyta í dulkóðun skráa"</string>
     <string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Umbreyta…"</string>
     <string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Þegar dulkóðað á grundvelli skráa"</string>
@@ -312,6 +311,8 @@
     <string name="battery_info_status_not_charging" msgid="2820070506621483576">"Ekki í hleðslu"</string>
     <string name="battery_info_status_full" msgid="2824614753861462808">"Fullhlaðin"</string>
     <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Stjórnað af kerfisstjóra"</string>
+    <string name="enabled_by_admin" msgid="2386503803463071894">"Virkjað af stjórnanda"</string>
+    <string name="disabled_by_admin" msgid="3669999613095206948">"Stjórnandi gerði óvirkt"</string>
     <string name="home" msgid="8263346537524314127">"Heim"</string>
     <string name="charge_length_format" msgid="8978516217024434156">"Fyrir <xliff:g id="ID_1">%1$s</xliff:g>"</string>
     <string name="remaining_length_format" msgid="7886337596669190587">"<xliff:g id="ID_1">%1$s</xliff:g> eftir"</string>
diff --git a/packages/SettingsLib/res/values-it/strings.xml b/packages/SettingsLib/res/values-it/strings.xml
index ca0df7a..9c75939 100644
--- a/packages/SettingsLib/res/values-it/strings.xml
+++ b/packages/SettingsLib/res/values-it/strings.xml
@@ -102,8 +102,7 @@
     <string name="tts_default_rate_title" msgid="6030550998379310088">"Velocità voce"</string>
     <string name="tts_default_rate_summary" msgid="4061815292287182801">"Velocità di pronuncia del testo"</string>
     <string name="tts_default_pitch_title" msgid="6135942113172488671">"Tono"</string>
-    <!-- no translation found for tts_default_pitch_summary (1944885882882650009) -->
-    <skip />
+    <string name="tts_default_pitch_summary" msgid="1944885882882650009">"Si applica al tono della sintesi vocale"</string>
     <string name="tts_default_lang_title" msgid="8018087612299820556">"Lingua"</string>
     <string name="tts_lang_use_system" msgid="2679252467416513208">"Usa lingua di sistema"</string>
     <string name="tts_lang_not_selected" msgid="7395787019276734765">"Lingua non selezionata"</string>
@@ -279,7 +278,7 @@
     <string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"Esegui renderer WebView in un processo isolato."</string>
     <string name="select_webview_provider_title" msgid="4628592979751918907">"Implementazione di WebView"</string>
     <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Imposta l\'implementazione di WebView"</string>
-    <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"L\'implementazione di WebView selezionata non è attiva e deve essere attivata per poterla utilizzare. Vuoi attivarla?"</string>
+    <string name="select_webview_provider_toast_text" msgid="8168796505966635684">"L\'implementazione WebView selezionata non è valida perché l\'elenco di opzioni di implementazione è obsoleto. Aggiorna l\'elenco."</string>
     <string name="convert_to_file_encryption" msgid="3060156730651061223">"Converti in crittografia basata su file"</string>
     <string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Converti..."</string>
     <string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Crittografia su base file già eseguita"</string>
@@ -312,6 +311,8 @@
     <string name="battery_info_status_not_charging" msgid="2820070506621483576">"Non in carica"</string>
     <string name="battery_info_status_full" msgid="2824614753861462808">"Carica"</string>
     <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Gestita dall\'amministratore"</string>
+    <string name="enabled_by_admin" msgid="2386503803463071894">"Attivata dall\'amministratore"</string>
+    <string name="disabled_by_admin" msgid="3669999613095206948">"Disattivata dall\'amministratore"</string>
     <string name="home" msgid="8263346537524314127">"Home page"</string>
     <string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g> fa"</string>
     <string name="remaining_length_format" msgid="7886337596669190587">"<xliff:g id="ID_1">%1$s</xliff:g> rimanenti"</string>
diff --git a/packages/SettingsLib/res/values-iw/strings.xml b/packages/SettingsLib/res/values-iw/strings.xml
index 280c443..429ce61 100644
--- a/packages/SettingsLib/res/values-iw/strings.xml
+++ b/packages/SettingsLib/res/values-iw/strings.xml
@@ -278,7 +278,7 @@
     <string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"הרץ מעבדי תצוגת אתר בהליך מבודד"</string>
     <string name="select_webview_provider_title" msgid="4628592979751918907">"‏יישום WebView"</string>
     <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"‏הגדרת יישום WebView"</string>
-    <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"‏יישום ה-WebView שנבחר מושבת, ויש להפעיל אותו כדי להשתמש בו. האם ברצונך להפעיל אותו?"</string>
+    <string name="select_webview_provider_toast_text" msgid="8168796505966635684">"‏יישום WebView שנבחר אינו חוקי שכן רשימת מבחר היישומים אינה פעילה יותר. יש צורך לעדכן את הרשימה."</string>
     <string name="convert_to_file_encryption" msgid="3060156730651061223">"המר להצפנת קבצים"</string>
     <string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"המר..."</string>
     <string name="convert_to_file_encryption_done" msgid="7859766358000523953">"הצפנת קבצים כבר מוגדרת"</string>
@@ -311,6 +311,8 @@
     <string name="battery_info_status_not_charging" msgid="2820070506621483576">"לא טוען"</string>
     <string name="battery_info_status_full" msgid="2824614753861462808">"מלא"</string>
     <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"נמצא בשליטת מנהל מערכת"</string>
+    <string name="enabled_by_admin" msgid="2386503803463071894">"הופעל על ידי מנהל המערכת"</string>
+    <string name="disabled_by_admin" msgid="3669999613095206948">"הושבת על ידי מנהל המערכת"</string>
     <string name="home" msgid="8263346537524314127">"דף הבית"</string>
     <string name="charge_length_format" msgid="8978516217024434156">"לפני <xliff:g id="ID_1">%1$s</xliff:g>"</string>
     <string name="remaining_length_format" msgid="7886337596669190587">"נשארו <xliff:g id="ID_1">%1$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-ja/strings.xml b/packages/SettingsLib/res/values-ja/strings.xml
index 4b33611..6c42110 100644
--- a/packages/SettingsLib/res/values-ja/strings.xml
+++ b/packages/SettingsLib/res/values-ja/strings.xml
@@ -102,8 +102,7 @@
     <string name="tts_default_rate_title" msgid="6030550998379310088">"音声の速度"</string>
     <string name="tts_default_rate_summary" msgid="4061815292287182801">"テキストの読み上げ速度"</string>
     <string name="tts_default_pitch_title" msgid="6135942113172488671">"音の高さ"</string>
-    <!-- no translation found for tts_default_pitch_summary (1944885882882650009) -->
-    <skip />
+    <string name="tts_default_pitch_summary" msgid="1944885882882650009">"合成音声のトーンに影響します"</string>
     <string name="tts_default_lang_title" msgid="8018087612299820556">"言語"</string>
     <string name="tts_lang_use_system" msgid="2679252467416513208">"システムの言語を使用"</string>
     <string name="tts_lang_not_selected" msgid="7395787019276734765">"言語が選択されていません"</string>
@@ -279,7 +278,7 @@
     <string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"別個のプロセスで WebView レンダラを実行します。"</string>
     <string name="select_webview_provider_title" msgid="4628592979751918907">"WebView の実装"</string>
     <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"WebView の実装の設定"</string>
-    <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"選択した WebView の実装は無効になっていますが、使用するには有効にする必要があります。有効にしますか?"</string>
+    <string name="select_webview_provider_toast_text" msgid="8168796505966635684">"選択した WebView の実装は無効です。これは実装の選択に使用するリストが古くなっているためです。リストを更新する必要があります。"</string>
     <string name="convert_to_file_encryption" msgid="3060156730651061223">"ファイル暗号化に変換する"</string>
     <string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"変換…"</string>
     <string name="convert_to_file_encryption_done" msgid="7859766358000523953">"ファイルは既に暗号化済みです"</string>
@@ -314,6 +313,8 @@
     <!-- no translation found for battery_info_status_full (2824614753861462808) -->
     <skip />
     <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"管理者により管理されています"</string>
+    <string name="enabled_by_admin" msgid="2386503803463071894">"管理者によって有効にされています"</string>
+    <string name="disabled_by_admin" msgid="3669999613095206948">"管理者によって無効にされています"</string>
     <string name="home" msgid="8263346537524314127">"ホーム"</string>
     <string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g>前"</string>
     <string name="remaining_length_format" msgid="7886337596669190587">"あと <xliff:g id="ID_1">%1$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-ka-rGE/strings.xml b/packages/SettingsLib/res/values-ka-rGE/strings.xml
index 9c33cc0..6dba53b 100644
--- a/packages/SettingsLib/res/values-ka-rGE/strings.xml
+++ b/packages/SettingsLib/res/values-ka-rGE/strings.xml
@@ -102,8 +102,7 @@
     <string name="tts_default_rate_title" msgid="6030550998379310088">"მეტყველების ტემპი"</string>
     <string name="tts_default_rate_summary" msgid="4061815292287182801">"ტექსტის თხრობის სიჩქარე"</string>
     <string name="tts_default_pitch_title" msgid="6135942113172488671">"სიმაღლე"</string>
-    <!-- no translation found for tts_default_pitch_summary (1944885882882650009) -->
-    <skip />
+    <string name="tts_default_pitch_summary" msgid="1944885882882650009">"გავლენას ახდენს სინთეზირებული ხმის სიძლიერეზე"</string>
     <string name="tts_default_lang_title" msgid="8018087612299820556">"ენა"</string>
     <string name="tts_lang_use_system" msgid="2679252467416513208">"სისტემის ენის გამოყენება"</string>
     <string name="tts_lang_not_selected" msgid="7395787019276734765">"ენა არჩეული არ არის"</string>
@@ -279,7 +278,7 @@
     <string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"WebView ვიზუალიზატორების იზოლირებულ პროცესში გაშვება."</string>
     <string name="select_webview_provider_title" msgid="4628592979751918907">"WebView რეალიზაცია"</string>
     <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"WebView რეალიზაციის დაყენება"</string>
-    <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"არჩეული WebView რეალიზაცია გათიშულია და გამოყენებამდე უნდა ჩაირთოს. გსურთ მისი ჩართვა?"</string>
+    <string name="select_webview_provider_toast_text" msgid="8168796505966635684">"არჩეული WebView რეალიზაცია არასწორია. რეალიზაციების სია მოძველდა და ახლა განახლდება."</string>
     <string name="convert_to_file_encryption" msgid="3060156730651061223">"ფაილების დაშიფვრაზე გარდაქმნა"</string>
     <string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"გარდაქმნა…"</string>
     <string name="convert_to_file_encryption_done" msgid="7859766358000523953">"უკვე დაშიფრულია ფაილების დონეზე"</string>
@@ -312,6 +311,8 @@
     <string name="battery_info_status_not_charging" msgid="2820070506621483576">"არ იტენება"</string>
     <string name="battery_info_status_full" msgid="2824614753861462808">"ბატარეა დატენილია"</string>
     <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"იმართება ადმინისტრატორის მიერ"</string>
+    <string name="enabled_by_admin" msgid="2386503803463071894">"ჩართულია ადმინისტრატორის მიერ"</string>
+    <string name="disabled_by_admin" msgid="3669999613095206948">"გათიშულია ადმინისტრატორის მიერ"</string>
     <string name="home" msgid="8263346537524314127">"მთავარი"</string>
     <string name="charge_length_format" msgid="8978516217024434156">"გავიდა <xliff:g id="ID_1">%1$s</xliff:g>"</string>
     <string name="remaining_length_format" msgid="7886337596669190587">"დარჩენილია <xliff:g id="ID_1">%1$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-kk-rKZ/strings.xml b/packages/SettingsLib/res/values-kk-rKZ/strings.xml
index 11d0cda..36843fd 100644
--- a/packages/SettingsLib/res/values-kk-rKZ/strings.xml
+++ b/packages/SettingsLib/res/values-kk-rKZ/strings.xml
@@ -102,8 +102,7 @@
     <string name="tts_default_rate_title" msgid="6030550998379310088">"Сөйлеу жылдамдығы"</string>
     <string name="tts_default_rate_summary" msgid="4061815292287182801">"Мәтіннің оқылу жылдамдығы"</string>
     <string name="tts_default_pitch_title" msgid="6135942113172488671">"Дауыс жиілігі"</string>
-    <!-- no translation found for tts_default_pitch_summary (1944885882882650009) -->
-    <skip />
+    <string name="tts_default_pitch_summary" msgid="1944885882882650009">"Синтезделген сөйлеу үніне әсер етеді"</string>
     <string name="tts_default_lang_title" msgid="8018087612299820556">"Тіл"</string>
     <string name="tts_lang_use_system" msgid="2679252467416513208">"Жүйелік тілді пайдалану"</string>
     <string name="tts_lang_not_selected" msgid="7395787019276734765">"Тіл таңдалған жоқ"</string>
@@ -279,7 +278,7 @@
     <string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"Веб-көрініс бейнелеушілерін оқшауланған процесте іске қосу."</string>
     <string name="select_webview_provider_title" msgid="4628592979751918907">"WebView ендіру"</string>
     <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"WebView ендіруін орнату"</string>
-    <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"Таңдалған веб-көріністі енгізу өшірілген және пайдалану үшін оны қосу керек. Оны қосу керек пе?"</string>
+    <string name="select_webview_provider_toast_text" msgid="8168796505966635684">"Таңдалған WebView ендіру жарамсыз, өйткені ендіру таңдауларының тізімі ескірген. Тізімді қазір жаңарту керек."</string>
     <string name="convert_to_file_encryption" msgid="3060156730651061223">"Файлды шифрлауға түрлендіру"</string>
     <string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Түрлендіру..."</string>
     <string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Файл шифрланып қойылған"</string>
@@ -312,6 +311,8 @@
     <string name="battery_info_status_not_charging" msgid="2820070506621483576">"Зарядталып тұрған жоқ"</string>
     <string name="battery_info_status_full" msgid="2824614753861462808">"Толық"</string>
     <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Әкімші басқарады"</string>
+    <string name="enabled_by_admin" msgid="2386503803463071894">"Әкімші қосқан"</string>
+    <string name="disabled_by_admin" msgid="3669999613095206948">"Әкімші өшірген"</string>
     <string name="home" msgid="8263346537524314127">"Негізгі бет"</string>
     <string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g> бұрын"</string>
     <string name="remaining_length_format" msgid="7886337596669190587">"<xliff:g id="ID_1">%1$s</xliff:g> қалды"</string>
diff --git a/packages/SettingsLib/res/values-km-rKH/strings.xml b/packages/SettingsLib/res/values-km-rKH/strings.xml
index 0f7a32a..9985a1e 100644
--- a/packages/SettingsLib/res/values-km-rKH/strings.xml
+++ b/packages/SettingsLib/res/values-km-rKH/strings.xml
@@ -102,8 +102,7 @@
     <string name="tts_default_rate_title" msgid="6030550998379310088">"អត្រា​និយាយ"</string>
     <string name="tts_default_rate_summary" msgid="4061815292287182801">"ល្បឿន​ពេល​អាន​​អត្ថបទ"</string>
     <string name="tts_default_pitch_title" msgid="6135942113172488671">"ឡើង​-ចុះ"</string>
-    <!-- no translation found for tts_default_pitch_summary (1944885882882650009) -->
-    <skip />
+    <string name="tts_default_pitch_summary" msgid="1944885882882650009">"ប៉ះពាល់ដល់សំឡេងនៃការនិយាយដែលបានបម្លែង"</string>
     <string name="tts_default_lang_title" msgid="8018087612299820556">"ភាសា"</string>
     <string name="tts_lang_use_system" msgid="2679252467416513208">"ប្រើ​ភាសា​ប្រព័ន្ធ"</string>
     <string name="tts_lang_not_selected" msgid="7395787019276734765">"មិន​បាន​ជ្រើស​ភាសា"</string>
@@ -279,7 +278,7 @@
     <string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"ដំណើរការកម្មវិធីបំលែង WebView ក្នុងដំណើរការដាច់ដោយឡែក"</string>
     <string name="select_webview_provider_title" msgid="4628592979751918907">"ការប្រតិបត្តិ WebView"</string>
     <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"កំណត់ការប្រតិបត្តិ WebView"</string>
-    <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"ការប្រតិបត្តិការ WebView ដែលបានជ្រើសត្រូវបានបិទដំណើរការ ប៉ុន្តែអ្នកត្រូវបើកដំណើរការវាដើម្បីប្រើ តើអ្នកចង់បើកដំណើរការវាដែរឬទេ?"</string>
+    <string name="select_webview_provider_toast_text" msgid="8168796505966635684">"ការអនុវត្ត WebView ដែលបានជ្រើសមិនត្រូវត្រឹមត្រូវទេ ដោយសារតែបញ្ជីជម្រើសនៃការអនុវត្តន៍ចាស់ហើយ។ គួរតែអាប់ដេតបញ្ជីនោះ។"</string>
     <string name="convert_to_file_encryption" msgid="3060156730651061223">"បម្លែងទៅជាការអ៊ីនគ្រីបឯកសារ"</string>
     <string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"បម្លែង…"</string>
     <string name="convert_to_file_encryption_done" msgid="7859766358000523953">"បានអ៊ីនគ្រីបឯកសាររួចហើយ"</string>
@@ -312,6 +311,8 @@
     <string name="battery_info_status_not_charging" msgid="2820070506621483576">"មិន​បញ្ចូលថ្ម"</string>
     <string name="battery_info_status_full" msgid="2824614753861462808">"ពេញ"</string>
     <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"គ្រប់គ្រងដោយអ្នកគ្រប់គ្រង"</string>
+    <string name="enabled_by_admin" msgid="2386503803463071894">"បានបើកដំណើរការដោយអ្នកគ្រប់គ្រង"</string>
+    <string name="disabled_by_admin" msgid="3669999613095206948">"បានបិទដំណើរការដោយអ្នកគ្រប់គ្រង"</string>
     <string name="home" msgid="8263346537524314127">"ដើម"</string>
     <string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g> មុន"</string>
     <string name="remaining_length_format" msgid="7886337596669190587">"នៅសល់ <xliff:g id="ID_1">%1$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-kn-rIN/strings.xml b/packages/SettingsLib/res/values-kn-rIN/strings.xml
index a728305..8ca9807 100644
--- a/packages/SettingsLib/res/values-kn-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-kn-rIN/strings.xml
@@ -102,8 +102,7 @@
     <string name="tts_default_rate_title" msgid="6030550998379310088">"ಧ್ವನಿಯ ದರ"</string>
     <string name="tts_default_rate_summary" msgid="4061815292287182801">"ಪಠ್ಯವನ್ನು ಹೇಳಿದ ವೇಗ"</string>
     <string name="tts_default_pitch_title" msgid="6135942113172488671">"ಪಿಚ್"</string>
-    <!-- no translation found for tts_default_pitch_summary (1944885882882650009) -->
-    <skip />
+    <string name="tts_default_pitch_summary" msgid="1944885882882650009">"ಸಂಯೋಜಿತ ಧ್ವನಿಯ ಟೋನ್ ಮೇಲೆ ಪರಿಣಾಮ ಬೀರುತ್ತದೆ"</string>
     <string name="tts_default_lang_title" msgid="8018087612299820556">"ಭಾಷೆ"</string>
     <string name="tts_lang_use_system" msgid="2679252467416513208">"ಸಿಸ್ಟಂ ಭಾಷೆಯನ್ನು ಬಳಸು"</string>
     <string name="tts_lang_not_selected" msgid="7395787019276734765">"ಭಾಷೆಯನ್ನು ಆಯ್ಕೆಮಾಡಲಾಗಿಲ್ಲ"</string>
@@ -279,7 +278,7 @@
     <string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"ಪ್ರತ್ಯೇಕಗೊಳಿಸಿದ ಪ್ರಕ್ರಿಯೆಯಲ್ಲಿ WebView ರೆಂಡರರ್‌‌ ರನ್‌ ಮಾಡಿ."</string>
     <string name="select_webview_provider_title" msgid="4628592979751918907">"WebView ಅನುಷ್ಠಾನಗೊಳಿಸುವಿಕೆ"</string>
     <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"WebView ಅನುಷ್ಠಾನಗೊಳಿಸುವಿಕೆಯನ್ನು ಹೊಂದಿಸಿ"</string>
-    <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"ಆಯ್ಕೆಮಾಡಲಾದ WebView ಅನುಷ್ಠಾನಗೊಳಿಸುವಿಕೆಯನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಲಾಗಿದೆ ಮತ್ತು ಬಳಸಲು ಸಕ್ರಿಯಗೊಳಿಸಬೇಕಾಗಿದೆ, ಇದನ್ನು ಸಕ್ರಿಯಗೊಳಿಸಲು ನೀವು ಬಯಸುತ್ತೀರಾ?"</string>
+    <string name="select_webview_provider_toast_text" msgid="8168796505966635684">"ಅನುಷ್ಠಾನ ಆಯ್ಕೆಗಳ ಪಟ್ಟಿ ಸ್ಥಬ್ದವಾಗಿರುವ ಕಾರಣ ಆಯ್ಕೆಮಾಡಿದ WebView ಅನುಷ್ಠಾನಗೊಳಿಸುವಿಕೆಯು ಅಮಾನ್ಯವಾಗಿದೆ. ಈಗ ಪಟ್ಟಿಯನ್ನು ಅಪ್‌‌ಡೇಟ್‌ ಮಾಡಬೇಕಾಗಿದೆ."</string>
     <string name="convert_to_file_encryption" msgid="3060156730651061223">"ಫೈಲ್ ಎನ್‌ಕ್ರಿಪ್ಶನ್‌ಗೆ ಪರಿವರ್ತಿಸು"</string>
     <string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"ಪರಿವರ್ತಿಸು…"</string>
     <string name="convert_to_file_encryption_done" msgid="7859766358000523953">"ಫೈಲ್ ಈಗಾಗಲೇ ಎನ್‌ಕ್ರಿಪ್ಟ್ ಮಾಡಲಾಗಿದೆ"</string>
@@ -312,6 +311,8 @@
     <string name="battery_info_status_not_charging" msgid="2820070506621483576">"ಚಾರ್ಜ್ ಆಗುತ್ತಿಲ್ಲ"</string>
     <string name="battery_info_status_full" msgid="2824614753861462808">"ಭರ್ತಿ"</string>
     <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"ನಿರ್ವಾಹಕರ ಮೂಲಕ ನಿಯಂತ್ರಿಸಲಾಗಿದೆ"</string>
+    <string name="enabled_by_admin" msgid="2386503803463071894">"ನಿರ್ವಾಹಕರಿಂದ ಸಕ್ರಿಯಗೊಳಿಸಲಾಗಿದೆ"</string>
+    <string name="disabled_by_admin" msgid="3669999613095206948">"ನಿರ್ವಾಹಕರಿಂದ ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಲಾಗಿದೆ"</string>
     <string name="home" msgid="8263346537524314127">"ಮುಖಪುಟ"</string>
     <string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g> ಹಿಂದೆ"</string>
     <string name="remaining_length_format" msgid="7886337596669190587">"<xliff:g id="ID_1">%1$s</xliff:g> ಉಳಿದಿದೆ"</string>
diff --git a/packages/SettingsLib/res/values-ko/strings.xml b/packages/SettingsLib/res/values-ko/strings.xml
index 43e3926..31e0378 100644
--- a/packages/SettingsLib/res/values-ko/strings.xml
+++ b/packages/SettingsLib/res/values-ko/strings.xml
@@ -102,8 +102,7 @@
     <string name="tts_default_rate_title" msgid="6030550998379310088">"말하는 속도"</string>
     <string name="tts_default_rate_summary" msgid="4061815292287182801">"텍스트를 읽어주는 속도"</string>
     <string name="tts_default_pitch_title" msgid="6135942113172488671">"피치"</string>
-    <!-- no translation found for tts_default_pitch_summary (1944885882882650009) -->
-    <skip />
+    <string name="tts_default_pitch_summary" msgid="1944885882882650009">"합성 음성의 어조에 영향을 미침"</string>
     <string name="tts_default_lang_title" msgid="8018087612299820556">"언어"</string>
     <string name="tts_lang_use_system" msgid="2679252467416513208">"시스템 언어 사용"</string>
     <string name="tts_lang_not_selected" msgid="7395787019276734765">"언어가 선택되지 않음"</string>
@@ -279,7 +278,7 @@
     <string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"단독 프로세스 내에서 WebView 렌더러를 실행합니다."</string>
     <string name="select_webview_provider_title" msgid="4628592979751918907">"WebView 구현"</string>
     <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"WebView 구현 설정"</string>
-    <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"선택한 WebView 구현이 사용 중지되어 있습니다. 사용하려면 사용 설정해야 합니다. 사용 설정하시겠습니까?"</string>
+    <string name="select_webview_provider_toast_text" msgid="8168796505966635684">"구현 선택 목록이 비활성화되어 선택한 WebView 구현이 잘못되었습니다. 목록을 지금 업데이트해야 합니다."</string>
     <string name="convert_to_file_encryption" msgid="3060156730651061223">"파일 암호화로 변환"</string>
     <string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"변환..."</string>
     <string name="convert_to_file_encryption_done" msgid="7859766358000523953">"파일이 이미 암호화됨"</string>
@@ -312,6 +311,8 @@
     <string name="battery_info_status_not_charging" msgid="2820070506621483576">"충전 안함"</string>
     <string name="battery_info_status_full" msgid="2824614753861462808">"충전 완료"</string>
     <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"관리자가 제어"</string>
+    <string name="enabled_by_admin" msgid="2386503803463071894">"관리자가 사용 설정함"</string>
+    <string name="disabled_by_admin" msgid="3669999613095206948">"관리자가 사용 중지함"</string>
     <string name="home" msgid="8263346537524314127">"홈"</string>
     <string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g> 전"</string>
     <string name="remaining_length_format" msgid="7886337596669190587">"<xliff:g id="ID_1">%1$s</xliff:g> 남음"</string>
diff --git a/packages/SettingsLib/res/values-ky-rKG/strings.xml b/packages/SettingsLib/res/values-ky-rKG/strings.xml
index e2c7f78..fd2d905 100644
--- a/packages/SettingsLib/res/values-ky-rKG/strings.xml
+++ b/packages/SettingsLib/res/values-ky-rKG/strings.xml
@@ -102,8 +102,7 @@
     <string name="tts_default_rate_title" msgid="6030550998379310088">"Кеп ылдамдыгы"</string>
     <string name="tts_default_rate_summary" msgid="4061815292287182801">"Текст айтылчу ылдамдык"</string>
     <string name="tts_default_pitch_title" msgid="6135942113172488671">"Негизги тон"</string>
-    <!-- no translation found for tts_default_pitch_summary (1944885882882650009) -->
-    <skip />
+    <string name="tts_default_pitch_summary" msgid="1944885882882650009">"Синтезделген кептин интонациясына таасирин тийгизет"</string>
     <string name="tts_default_lang_title" msgid="8018087612299820556">"Тил"</string>
     <string name="tts_lang_use_system" msgid="2679252467416513208">"Тутум тилин колдонуу"</string>
     <string name="tts_lang_not_selected" msgid="7395787019276734765">"Тил тандалган жок"</string>
@@ -279,7 +278,7 @@
     <string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"WebView рендерерлерин корголгон процессте иштетүү."</string>
     <string name="select_webview_provider_title" msgid="4628592979751918907">"WebView аткарылышы"</string>
     <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"WebView аткарылышын коюу"</string>
-    <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"WebView кызматын пайдалануу үчүн аны иштетүү керек. Иштетесизби?"</string>
+    <string name="select_webview_provider_toast_text" msgid="8168796505966635684">"Тандалган WebView кызматы колдоого алынбайт. Кызматтардын тизмеси эскирип калгандыктан ал азыр жаңыртылат."</string>
     <string name="convert_to_file_encryption" msgid="3060156730651061223">"Файл шифрлөөсүнө айландыруу"</string>
     <string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Айландыруу…"</string>
     <string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Файл мурунтан эле шифрленген"</string>
@@ -312,6 +311,8 @@
     <string name="battery_info_status_not_charging" msgid="2820070506621483576">"Кубатталган жок"</string>
     <string name="battery_info_status_full" msgid="2824614753861462808">"Толук"</string>
     <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Администратор тарабынан көзөмөлдөнөт"</string>
+    <string name="enabled_by_admin" msgid="2386503803463071894">"Администратор иштетип койгон"</string>
+    <string name="disabled_by_admin" msgid="3669999613095206948">"Администратор өчүрүп койгон"</string>
     <string name="home" msgid="8263346537524314127">"Башкы бет"</string>
     <string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g> мурун"</string>
     <string name="remaining_length_format" msgid="7886337596669190587">"<xliff:g id="ID_1">%1$s</xliff:g> калды"</string>
diff --git a/packages/SettingsLib/res/values-lo-rLA/strings.xml b/packages/SettingsLib/res/values-lo-rLA/strings.xml
index 9d5c60a..605f476 100644
--- a/packages/SettingsLib/res/values-lo-rLA/strings.xml
+++ b/packages/SettingsLib/res/values-lo-rLA/strings.xml
@@ -102,8 +102,7 @@
     <string name="tts_default_rate_title" msgid="6030550998379310088">"ອັດຕາການເວົ້າ"</string>
     <string name="tts_default_rate_summary" msgid="4061815292287182801">"ຄວາມໄວໃນການເວົ້າຂໍ້ຄວາມ"</string>
     <string name="tts_default_pitch_title" msgid="6135942113172488671">"ໂທນສຽງ"</string>
-    <!-- no translation found for tts_default_pitch_summary (1944885882882650009) -->
-    <skip />
+    <string name="tts_default_pitch_summary" msgid="1944885882882650009">"ມີຜົນກັບໂທນສຽງເວົ້າທີ່ສັງເຄາະ"</string>
     <string name="tts_default_lang_title" msgid="8018087612299820556">"ພາສາ"</string>
     <string name="tts_lang_use_system" msgid="2679252467416513208">"​ໃຊ້​ພາ​ສາ​ຂອງ​ລະ​ບົບ"</string>
     <string name="tts_lang_not_selected" msgid="7395787019276734765">"ບໍ່ໄດ້ເລືອກພາສາ"</string>
@@ -279,7 +278,7 @@
     <string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"ເປີດໃຊ້ຕົວປະມວນ WebView ໃນໂປຣເຊສທີ່ແຍກຈາກກັນໄດ້."</string>
     <string name="select_webview_provider_title" msgid="4628592979751918907">"ການຈັດຕັ້ງປະຕິບັດ WebView"</string>
     <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"ຕັ້ງການຈັດຕັ້ງປະຕິບັດ WebView"</string>
-    <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"ການຈັດຕັ້ງປະຕິບັດ WebView ທີ່ເລືອກຖືກປິດນຳໃຊ້, ແລະຕ້ອງຖືກເປີດນຳໃຊ້, ທ່ານຕ້ອງການເປີດນຳໃຊ້ມັນບໍ?"</string>
+    <string name="select_webview_provider_toast_text" msgid="8168796505966635684">"ການນຳໃຊ້ WebView ທີ່ເລືອກນັ້ນບໍ່ຖືກຕ້ອງເນື່ອງຈາກລາຍຊື່ຂອງການເລືອກນຳໃຊ້ນັ້ນເກົ່າເກີນໄປ. ລາຍຊື່ຕອນນີ້ແມ່ນອັບເດດແລ້ວ."</string>
     <string name="convert_to_file_encryption" msgid="3060156730651061223">"ປ່ຽນ​ເປັນ​ການ​ເຂົ້າ​ລະ​ຫັດ​ໄຟ​ລ໌"</string>
     <string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"ປ່ຽນ..."</string>
     <string name="convert_to_file_encryption_done" msgid="7859766358000523953">"ໄຟ​ລ໌​ເຂົ້າ​ລະ​ຫັດ​ຮຽບ​ຮ້ອຍ​ແລ້ວ"</string>
@@ -312,6 +311,8 @@
     <string name="battery_info_status_not_charging" msgid="2820070506621483576">"ບໍ່ໄດ້ສາກໄຟ"</string>
     <string name="battery_info_status_full" msgid="2824614753861462808">"ເຕັມ"</string>
     <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"ຄວບຄຸມໂດຍຜູ້ເບິ່ງແຍງ"</string>
+    <string name="enabled_by_admin" msgid="2386503803463071894">"ຖືກເປີດໃຊ້ໂດຍຜູ້ເບິ່ງແຍງລະບົບ"</string>
+    <string name="disabled_by_admin" msgid="3669999613095206948">"ຖືກປິດໄວ້ໂດຍຜູ້ເບິ່ງແຍງລະບົບ"</string>
     <string name="home" msgid="8263346537524314127">"​ໜ້າຫຼັກ"</string>
     <string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g> ກ່ອນນີ້"</string>
     <string name="remaining_length_format" msgid="7886337596669190587">"ຍັງເຫຼືອ <xliff:g id="ID_1">%1$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-lt/strings.xml b/packages/SettingsLib/res/values-lt/strings.xml
index 8bd4e43..253eeb3 100644
--- a/packages/SettingsLib/res/values-lt/strings.xml
+++ b/packages/SettingsLib/res/values-lt/strings.xml
@@ -102,8 +102,7 @@
     <string name="tts_default_rate_title" msgid="6030550998379310088">"Kalbėjimo greitis"</string>
     <string name="tts_default_rate_summary" msgid="4061815292287182801">"Greitis, kuriuo sakomas tekstas"</string>
     <string name="tts_default_pitch_title" msgid="6135942113172488671">"Garso aukštis"</string>
-    <!-- no translation found for tts_default_pitch_summary (1944885882882650009) -->
-    <skip />
+    <string name="tts_default_pitch_summary" msgid="1944885882882650009">"Daro poveikį susintetintai kalbai"</string>
     <string name="tts_default_lang_title" msgid="8018087612299820556">"Kalba"</string>
     <string name="tts_lang_use_system" msgid="2679252467416513208">"Naudoti sistemos kalbą"</string>
     <string name="tts_lang_not_selected" msgid="7395787019276734765">"Kalba nepasirinkta"</string>
@@ -279,7 +278,7 @@
     <string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"Paleisti „WebView“ pateikimo priemones vienam procesui."</string>
     <string name="select_webview_provider_title" msgid="4628592979751918907">"„WebView“ diegimas"</string>
     <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"„WebView“ diegimo nustatymas"</string>
-    <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"Pasirinktas „WebView“ diegimas išjungtas ir jį būtina įgalinti, kad būtų galima naudoti. Ar norite jį įgalinti?"</string>
+    <string name="select_webview_provider_toast_text" msgid="8168796505966635684">"Pasirinktas „WebView“ diegimas netinkamas, nes diegimo pasirinkimų sąrašas tapo neaktyvus. Sąrašas dabar turėtų būti atnaujintas."</string>
     <string name="convert_to_file_encryption" msgid="3060156730651061223">"Konvertuoti į failų šifruotę"</string>
     <string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Konvertuoti…"</string>
     <string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Jau konvertuota į failų šifruotę"</string>
@@ -312,6 +311,8 @@
     <string name="battery_info_status_not_charging" msgid="2820070506621483576">"Nekraunama"</string>
     <string name="battery_info_status_full" msgid="2824614753861462808">"Visiškai įkrautas"</string>
     <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Valdo administratorius"</string>
+    <string name="enabled_by_admin" msgid="2386503803463071894">"Įgalino administratorius"</string>
+    <string name="disabled_by_admin" msgid="3669999613095206948">"Išjungė administratorius"</string>
     <string name="home" msgid="8263346537524314127">"Pagrindinis ekranas"</string>
     <string name="charge_length_format" msgid="8978516217024434156">"Prieš <xliff:g id="ID_1">%1$s</xliff:g>"</string>
     <string name="remaining_length_format" msgid="7886337596669190587">"Liko <xliff:g id="ID_1">%1$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-lv/strings.xml b/packages/SettingsLib/res/values-lv/strings.xml
index 42bce6b..3323cd9 100644
--- a/packages/SettingsLib/res/values-lv/strings.xml
+++ b/packages/SettingsLib/res/values-lv/strings.xml
@@ -102,8 +102,7 @@
     <string name="tts_default_rate_title" msgid="6030550998379310088">"Runas ātrums"</string>
     <string name="tts_default_rate_summary" msgid="4061815292287182801">"Teksta ierunāšanas ātrums"</string>
     <string name="tts_default_pitch_title" msgid="6135942113172488671">"Tonis"</string>
-    <!-- no translation found for tts_default_pitch_summary (1944885882882650009) -->
-    <skip />
+    <string name="tts_default_pitch_summary" msgid="1944885882882650009">"Ietekmē sintezētās runas toni"</string>
     <string name="tts_default_lang_title" msgid="8018087612299820556">"Valoda"</string>
     <string name="tts_lang_use_system" msgid="2679252467416513208">"Izmantot sistēmas valodu"</string>
     <string name="tts_lang_not_selected" msgid="7395787019276734765">"Nav atlasīta valoda."</string>
@@ -279,7 +278,7 @@
     <string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"Atsevišķā procesā tiek palaisti WebView renderētāji."</string>
     <string name="select_webview_provider_title" msgid="4628592979751918907">"WebView ieviešana"</string>
     <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Iestatīt WebView ieviešanu"</string>
-    <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"Izvēlētā WebView ieviešana ir atspējota, un tā ir jāiespējo, lai to varētu izmantot. Vai vēlaties to iespējot?"</string>
+    <string name="select_webview_provider_toast_text" msgid="8168796505966635684">"Izvēlētā WebView ieviešana nav derīga, jo ieviešanas iespēju saraksts ir novecojis. Saraksts ir jāatjaunina."</string>
     <string name="convert_to_file_encryption" msgid="3060156730651061223">"Pārvērst par failu šifrējumu"</string>
     <string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Pārvērst…"</string>
     <string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Jau šifrēts failu līmenī"</string>
@@ -312,6 +311,8 @@
     <string name="battery_info_status_not_charging" msgid="2820070506621483576">"Nenotiek uzlāde"</string>
     <string name="battery_info_status_full" msgid="2824614753861462808">"Pilns"</string>
     <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Kontrolē administrators"</string>
+    <string name="enabled_by_admin" msgid="2386503803463071894">"Iespējojis administrators"</string>
+    <string name="disabled_by_admin" msgid="3669999613095206948">"Atspējojis administrators"</string>
     <string name="home" msgid="8263346537524314127">"Sākums"</string>
     <string name="charge_length_format" msgid="8978516217024434156">"Pirms šāda laika: <xliff:g id="ID_1">%1$s</xliff:g>"</string>
     <string name="remaining_length_format" msgid="7886337596669190587">"Atlikušais laiks: <xliff:g id="ID_1">%1$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-mk-rMK/strings.xml b/packages/SettingsLib/res/values-mk-rMK/strings.xml
index 16b6332..41c8600 100644
--- a/packages/SettingsLib/res/values-mk-rMK/strings.xml
+++ b/packages/SettingsLib/res/values-mk-rMK/strings.xml
@@ -102,8 +102,7 @@
     <string name="tts_default_rate_title" msgid="6030550998379310088">"Брзина на говор"</string>
     <string name="tts_default_rate_summary" msgid="4061815292287182801">"Брзина со која се кажува текстот"</string>
     <string name="tts_default_pitch_title" msgid="6135942113172488671">"Интензитет"</string>
-    <!-- no translation found for tts_default_pitch_summary (1944885882882650009) -->
-    <skip />
+    <string name="tts_default_pitch_summary" msgid="1944885882882650009">"Влијае на тонот на синтетизираниот говор"</string>
     <string name="tts_default_lang_title" msgid="8018087612299820556">"Јазик"</string>
     <string name="tts_lang_use_system" msgid="2679252467416513208">"Користете системски јазик"</string>
     <string name="tts_lang_not_selected" msgid="7395787019276734765">"Јазикот не е избран"</string>
@@ -279,7 +278,7 @@
     <string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"Активирајте ги WebView-прикажувачите во изолиран процес."</string>
     <string name="select_webview_provider_title" msgid="4628592979751918907">"Воведување WebView"</string>
     <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Поставете воведување WebView"</string>
-    <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"Избраната примена на WebView е оневозможена, а за да се користи, мора да се овозможи. Дали сакате да ја овозможите?"</string>
+    <string name="select_webview_provider_toast_text" msgid="8168796505966635684">"Избраната WebView имплементација е неважечка поради неажуриран список со избори за имплементација. Списокот ќе се ажурира сега."</string>
     <string name="convert_to_file_encryption" msgid="3060156730651061223">"Конвертирајте до шифрирање датотеки"</string>
     <string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Конвертирај..."</string>
     <string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Датотеката е веќе шифрирана"</string>
@@ -312,6 +311,8 @@
     <string name="battery_info_status_not_charging" msgid="2820070506621483576">"Не се полни"</string>
     <string name="battery_info_status_full" msgid="2824614753861462808">"Целосна"</string>
     <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Контролирано од администраторот"</string>
+    <string name="enabled_by_admin" msgid="2386503803463071894">"Овозможено од администраторот"</string>
+    <string name="disabled_by_admin" msgid="3669999613095206948">"Оневозможено од администраторот"</string>
     <string name="home" msgid="8263346537524314127">"Почетна страница"</string>
     <string name="charge_length_format" msgid="8978516217024434156">"Пред <xliff:g id="ID_1">%1$s</xliff:g>"</string>
     <string name="remaining_length_format" msgid="7886337596669190587">"Преостанаа <xliff:g id="ID_1">%1$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-ml-rIN/strings.xml b/packages/SettingsLib/res/values-ml-rIN/strings.xml
index 9e60615..80cf43e 100644
--- a/packages/SettingsLib/res/values-ml-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-ml-rIN/strings.xml
@@ -102,8 +102,7 @@
     <string name="tts_default_rate_title" msgid="6030550998379310088">"വായന നിരക്ക്"</string>
     <string name="tts_default_rate_summary" msgid="4061815292287182801">"വാചകം പറയുന്ന വേഗത"</string>
     <string name="tts_default_pitch_title" msgid="6135942113172488671">"പിച്ച്"</string>
-    <!-- no translation found for tts_default_pitch_summary (1944885882882650009) -->
-    <skip />
+    <string name="tts_default_pitch_summary" msgid="1944885882882650009">"സിന്തസൈസ് ചെയ്ത സംസാരത്തിന്റെ സ്വരഭേദത്തെ ബാധിക്കുന്നു"</string>
     <string name="tts_default_lang_title" msgid="8018087612299820556">"ഭാഷ"</string>
     <string name="tts_lang_use_system" msgid="2679252467416513208">"സി‌സ്റ്റം ഭാഷ ഉപയോഗിക്കുക"</string>
     <string name="tts_lang_not_selected" msgid="7395787019276734765">"ഭാഷ തിരഞ്ഞെടുത്തിട്ടില്ല"</string>
@@ -279,7 +278,7 @@
     <string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"ഒറ്റപ്പെട്ടൊരു പ്രോസസ്സിൽ WebView റെൻഡററുകൾ റൺ ചെയ്യുക."</string>
     <string name="select_webview_provider_title" msgid="4628592979751918907">"WebView നടപ്പാക്കൽ"</string>
     <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"WebView നടപ്പാക്കൽ സജ്ജമാക്കുക"</string>
-    <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"തിരഞ്ഞെടുത്ത WebView നടപ്പാക്കൽ പ്രവർത്തനരഹിതമാക്കി, ഉപയോഗിക്കുന്നതിന് ഇത് പ്രവർത്തനക്ഷമമാക്കണം, പ്രവർത്തനക്ഷമമാക്കാൻ ആഗ്രഹിക്കുന്നുണ്ടോ?"</string>
+    <string name="select_webview_provider_toast_text" msgid="8168796505966635684">"തിരഞ്ഞെടുത്ത WebView നടപ്പാക്കൽ അസാധുവാണ്, കാരണം നടപ്പാക്കൽ തിരഞ്ഞെടുപ്പുകളുടെ ലിസ്റ്റ് പഴകിപ്പോയി. ഈ ലിസ്റ്റിപ്പോൾ അപ്‌ഡേറ്റ് ചെയ്യേണ്ടതുണ്ട്."</string>
     <string name="convert_to_file_encryption" msgid="3060156730651061223">"ഫയൽ എൻക്രിപ്ഷനിലേക്ക് പരിവർത്തിപ്പിക്കുക"</string>
     <string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"പരിവർത്തിപ്പിക്കുക…"</string>
     <string name="convert_to_file_encryption_done" msgid="7859766358000523953">"ഇതിനകം തന്നെ ഫയൽ എൻക്രിപ്റ്റ് ചെയ്തു"</string>
@@ -312,6 +311,8 @@
     <string name="battery_info_status_not_charging" msgid="2820070506621483576">"ചാർജ്ജുചെയ്യുന്നില്ല"</string>
     <string name="battery_info_status_full" msgid="2824614753861462808">"നിറഞ്ഞു"</string>
     <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"അഡ്‌മിൻ നിയന്ത്രിക്കുന്നത്"</string>
+    <string name="enabled_by_admin" msgid="2386503803463071894">"അഡ്‌മിനിസ്ട്രേറ്റർ പ്രവർത്തനക്ഷമമാക്കി"</string>
+    <string name="disabled_by_admin" msgid="3669999613095206948">"അഡ്‌മിനിസ്ട്രേറ്റർ പ്രവർത്തനരഹിതമാക്കി"</string>
     <string name="home" msgid="8263346537524314127">"ഹോം"</string>
     <string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g> മുമ്പ്"</string>
     <string name="remaining_length_format" msgid="7886337596669190587">"<xliff:g id="ID_1">%1$s</xliff:g> ശേഷിക്കുന്നു"</string>
diff --git a/packages/SettingsLib/res/values-mn-rMN/strings.xml b/packages/SettingsLib/res/values-mn-rMN/strings.xml
index 5957a11..5e7ea15 100644
--- a/packages/SettingsLib/res/values-mn-rMN/strings.xml
+++ b/packages/SettingsLib/res/values-mn-rMN/strings.xml
@@ -102,8 +102,7 @@
     <string name="tts_default_rate_title" msgid="6030550998379310088">"Ярианы түвшин"</string>
     <string name="tts_default_rate_summary" msgid="4061815292287182801">"Текстийг унших хурд"</string>
     <string name="tts_default_pitch_title" msgid="6135942113172488671">"Авиа тон"</string>
-    <!-- no translation found for tts_default_pitch_summary (1944885882882650009) -->
-    <skip />
+    <string name="tts_default_pitch_summary" msgid="1944885882882650009">"Авоматаар үүссэн ярианы дуудлаганд нөлөөлдөг"</string>
     <string name="tts_default_lang_title" msgid="8018087612299820556">"Хэл"</string>
     <string name="tts_lang_use_system" msgid="2679252467416513208">"Системийн хэлийг ашиглах"</string>
     <string name="tts_lang_not_selected" msgid="7395787019276734765">"Хэл сонгогдоогүй байна"</string>
@@ -279,7 +278,7 @@
     <string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"WebView хөрвүүлэгчийг тусдаа боловсруулалтаар ажиллуулна уу."</string>
     <string name="select_webview_provider_title" msgid="4628592979751918907">"WebView хэрэгжилт"</string>
     <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"WebView хэрэгжилтийг тохируулах"</string>
-    <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"Сонгосон WebView хэрэгжүүлэлтийг идэвхгүй болгосон бөгөөд хэрэглэхийн тулд заавал идэвхжүүлэх шаардлагатай. Үүнийг идэвхжүүлэх үү?"</string>
+    <string name="select_webview_provider_toast_text" msgid="8168796505966635684">"Хэрэгжүүлэлтийн сонголтын жагсаалт хуучирсан тул сонгосон WebView хэрэгжүүлэлт хүчингүй байна. Жагсаалтыг одоо шинэчлэх болно."</string>
     <string name="convert_to_file_encryption" msgid="3060156730651061223">"Файлын шифрлэлт болгон хөрвүүлэх"</string>
     <string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Хөрвүүлэх..."</string>
     <string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Аль хэдийнэ файл шифрлэгдсэн"</string>
@@ -312,6 +311,8 @@
     <string name="battery_info_status_not_charging" msgid="2820070506621483576">"Цэнэглэхгүй байна"</string>
     <string name="battery_info_status_full" msgid="2824614753861462808">"Дүүрэн"</string>
     <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Админ удирдсан"</string>
+    <string name="enabled_by_admin" msgid="2386503803463071894">"Админ идэвхтэй болгосон"</string>
+    <string name="disabled_by_admin" msgid="3669999613095206948">"Админ идэвхгүй болгосон"</string>
     <string name="home" msgid="8263346537524314127">"Нүүр"</string>
     <string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g> өмнө"</string>
     <string name="remaining_length_format" msgid="7886337596669190587">"<xliff:g id="ID_1">%1$s</xliff:g> үлдсэн"</string>
diff --git a/packages/SettingsLib/res/values-mr-rIN/strings.xml b/packages/SettingsLib/res/values-mr-rIN/strings.xml
index 04d7f42..7a3d76d 100644
--- a/packages/SettingsLib/res/values-mr-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-mr-rIN/strings.xml
@@ -102,8 +102,7 @@
     <string name="tts_default_rate_title" msgid="6030550998379310088">"बोलण्याचा रेट"</string>
     <string name="tts_default_rate_summary" msgid="4061815292287182801">"ज्या गतीने मजकूर बोलला जातो ती"</string>
     <string name="tts_default_pitch_title" msgid="6135942113172488671">"पिच"</string>
-    <!-- no translation found for tts_default_pitch_summary (1944885882882650009) -->
-    <skip />
+    <string name="tts_default_pitch_summary" msgid="1944885882882650009">"संश्लेषित उच्चारांच्या आवाजास प्रभावित करते"</string>
     <string name="tts_default_lang_title" msgid="8018087612299820556">"भाषा"</string>
     <string name="tts_lang_use_system" msgid="2679252467416513208">"सिस्टम भाषा वापरा"</string>
     <string name="tts_lang_not_selected" msgid="7395787019276734765">"भाषा निवडलेली नाही"</string>
@@ -276,10 +275,10 @@
     <string name="runningservices_settings_title" msgid="8097287939865165213">"चालू सेवा"</string>
     <string name="runningservices_settings_summary" msgid="854608995821032748">"सध्या चालत असलेल्या सेवा पहा आणि नियंत्रित करा"</string>
     <string name="enable_webview_multiprocess" msgid="3405948012467585908">"एकाधिक प्रक्रिया WebView सक्षम करा"</string>
-    <string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"एक वेगळ्या प्रक्रियेत वेब दृश्य प्रस्तुतकर्ते चालवा."</string>
+    <string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"एक वेगळ्या प्रक्रियेत WebView प्रस्तुतकर्ते चालवा."</string>
     <string name="select_webview_provider_title" msgid="4628592979751918907">"वेबदृश्य अंमलबजावणी"</string>
     <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"वेबदृश्य अंमलबजावणी सेट करा"</string>
-    <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"निवडलेली WebView अंमलबजावणी अक्षम आहे आणि वापरण्यास सक्षम असणे आवश्यक आहे, आपण ती सक्षम करू इच्छिता?"</string>
+    <string name="select_webview_provider_toast_text" msgid="8168796505966635684">"अंमलबजावणीची निवडींची सूची जुनी झाली असल्याने निवडलेली WebView अंमलबजावणी अवैध आहे."</string>
     <string name="convert_to_file_encryption" msgid="3060156730651061223">"फाईल कूटबद्धीकरणावर रूपांतरित करा"</string>
     <string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"रूपांतरित करा..."</string>
     <string name="convert_to_file_encryption_done" msgid="7859766358000523953">"फाईल आधीपासून कूटबद्ध केली"</string>
@@ -312,6 +311,8 @@
     <string name="battery_info_status_not_charging" msgid="2820070506621483576">"चार्ज होत नाही"</string>
     <string name="battery_info_status_full" msgid="2824614753861462808">"पूर्ण"</string>
     <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"प्रशासकाने नियंत्रित केलेले"</string>
+    <string name="enabled_by_admin" msgid="2386503803463071894">"प्रशासकाने सक्षम केलेले"</string>
+    <string name="disabled_by_admin" msgid="3669999613095206948">"प्रशासकाने अक्षम केलेले"</string>
     <string name="home" msgid="8263346537524314127">"मुख्यपृष्ठ"</string>
     <string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g> पूर्वी"</string>
     <string name="remaining_length_format" msgid="7886337596669190587">"<xliff:g id="ID_1">%1$s</xliff:g> शिल्लक"</string>
diff --git a/packages/SettingsLib/res/values-ms-rMY/strings.xml b/packages/SettingsLib/res/values-ms-rMY/strings.xml
index 5fc87f0..3f29687 100644
--- a/packages/SettingsLib/res/values-ms-rMY/strings.xml
+++ b/packages/SettingsLib/res/values-ms-rMY/strings.xml
@@ -102,8 +102,7 @@
     <string name="tts_default_rate_title" msgid="6030550998379310088">"Kadar pertuturan"</string>
     <string name="tts_default_rate_summary" msgid="4061815292287182801">"Kelajuan pertuturan teks"</string>
     <string name="tts_default_pitch_title" msgid="6135942113172488671">"Pic"</string>
-    <!-- no translation found for tts_default_pitch_summary (1944885882882650009) -->
-    <skip />
+    <string name="tts_default_pitch_summary" msgid="1944885882882650009">"Mempengaruhi nada pertuturan disintesiskan"</string>
     <string name="tts_default_lang_title" msgid="8018087612299820556">"Bahasa"</string>
     <string name="tts_lang_use_system" msgid="2679252467416513208">"Gunakan bahasa sistem"</string>
     <string name="tts_lang_not_selected" msgid="7395787019276734765">"Bahasa tidak dipilih"</string>
@@ -279,7 +278,7 @@
     <string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"Jalankan pemapar WebView dalam proses terpencil."</string>
     <string name="select_webview_provider_title" msgid="4628592979751918907">"Pelaksanaan WebView"</string>
     <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Tetapkan pelaksanaan WebView"</string>
-    <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"Pelaksanaan WebView pilihan telah dilumpuhkan dan mesti didayakan untuk digunakan, adakah anda mahu mendayakannya?"</string>
+    <string name="select_webview_provider_toast_text" msgid="8168796505966635684">"Pelaksanaan WebView yang dipilih tidak sah kerana senarai pilihan pelaksanaan telah lapuk. Senarai itu seharusnya dikemas kini sekarang."</string>
     <string name="convert_to_file_encryption" msgid="3060156730651061223">"Tukar kepada penyulitan fail"</string>
     <string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Tukar..."</string>
     <string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Sudah disulitkan fail"</string>
@@ -312,6 +311,8 @@
     <string name="battery_info_status_not_charging" msgid="2820070506621483576">"Tidak mengecas"</string>
     <string name="battery_info_status_full" msgid="2824614753861462808">"Penuh"</string>
     <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Dikawal oleh pentadbir"</string>
+    <string name="enabled_by_admin" msgid="2386503803463071894">"Didayakan oleh pentadbir"</string>
+    <string name="disabled_by_admin" msgid="3669999613095206948">"Dilumpuhkan oleh pentadbir"</string>
     <string name="home" msgid="8263346537524314127">"Skrin Utama"</string>
     <string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g> yang lalu"</string>
     <string name="remaining_length_format" msgid="7886337596669190587">"<xliff:g id="ID_1">%1$s</xliff:g> lagi"</string>
diff --git a/packages/SettingsLib/res/values-my-rMM/strings.xml b/packages/SettingsLib/res/values-my-rMM/strings.xml
index 91cc7fe..71862a3 100644
--- a/packages/SettingsLib/res/values-my-rMM/strings.xml
+++ b/packages/SettingsLib/res/values-my-rMM/strings.xml
@@ -102,8 +102,7 @@
     <string name="tts_default_rate_title" msgid="6030550998379310088">"စကားပြောနှုန်း"</string>
     <string name="tts_default_rate_summary" msgid="4061815292287182801">"စာတမ်းအားပြောဆိုသော အမြန်နှုန်း"</string>
     <string name="tts_default_pitch_title" msgid="6135942113172488671">"အသံအနိမ့်အမြင့်"</string>
-    <!-- no translation found for tts_default_pitch_summary (1944885882882650009) -->
-    <skip />
+    <string name="tts_default_pitch_summary" msgid="1944885882882650009">"စက်ဖြင့်ထုတ်လုပ်ထားသည့် စကားသံကို အကျိုးသက်ရောက်မှုရှိပါမည်။"</string>
     <string name="tts_default_lang_title" msgid="8018087612299820556">"ဘာသာစကား"</string>
     <string name="tts_lang_use_system" msgid="2679252467416513208">"စနစ်၏ ဘာသာစကားကို အသုံးပြုရန်"</string>
     <string name="tts_lang_not_selected" msgid="7395787019276734765">"ဘာသာစကား မရွေးချယ်ထားပါ။"</string>
@@ -279,7 +278,7 @@
     <string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"လုပ်ငန်းဖြစ်စဉ်တစ်ခုတည်းအတွက် ဝဘ်မြင်ကွင်း အဖြစ်ပြုလုပ်ခြင်းကို ဖွင့်ပါ။"</string>
     <string name="select_webview_provider_title" msgid="4628592979751918907">"WebView အကောင်အထည်ဖော်မှု"</string>
     <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"WebView အကောင်အထည်ဖော်မှု သတ်မှတ်ပါ"</string>
-    <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"ရွေးချယ်ထားသည့် WebView လုပ်ဆောင်ခြင်းကို ပိတ်ထားသည်ပြီး အသုံးပြုရန်အတွက် ဖွင့်ရမည်၊ ဖွင့်လိုပါသလား။"</string>
+    <string name="select_webview_provider_toast_text" msgid="8168796505966635684">"ရွေးချယ်ထားသည့် ဝဘ်မြင်ကွင်းထည့်သွင်းမှု မမှန်ကန်ပါ၊ အဘယ့်ကြောင့်ဆိုသော် ရွေးချယ်ရန် ထည့်သွင်းမှုစာရင်းသည် အသစ်မဖြစ်တော့သောကြောင့်ဖြစ်သည်။ စာရင်းကို ယခုအပ်ဒိတ် ဖြစ်နေလောက်ပါပြီ။"</string>
     <string name="convert_to_file_encryption" msgid="3060156730651061223">"ဖိုင်လုံခြုံအောင်ပြုလုပ်ခြင်းသို့ ပြောင်းပါ"</string>
     <string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"ပြောင်းရန်…"</string>
     <string name="convert_to_file_encryption_done" msgid="7859766358000523953">"ဖိုင်ကို လုံခြုံအောင်ပြုလုပ်ပြီးပါပြီ"</string>
@@ -312,6 +311,8 @@
     <string name="battery_info_status_not_charging" msgid="2820070506621483576">"အားသွင်းမနေပါ"</string>
     <string name="battery_info_status_full" msgid="2824614753861462808">"အပြည့်"</string>
     <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"စီမံခန့်ခွဲသူမှ ထိန်းချုပ်ပါသည်"</string>
+    <string name="enabled_by_admin" msgid="2386503803463071894">"စီမံခန့်ခွဲသူမှ ဖွင့်ထားသည်"</string>
+    <string name="disabled_by_admin" msgid="3669999613095206948">"စီမံခန့်ခွဲသူမှ ပိတ်ထားသည်"</string>
     <string name="home" msgid="8263346537524314127">"ပင်မ"</string>
     <string name="charge_length_format" msgid="8978516217024434156">"ပြီးခဲ့သည့် <xliff:g id="ID_1">%1$s</xliff:g> က"</string>
     <string name="remaining_length_format" msgid="7886337596669190587">"<xliff:g id="ID_1">%1$s</xliff:g> ကျန်ပါသည်"</string>
diff --git a/packages/SettingsLib/res/values-nb/strings.xml b/packages/SettingsLib/res/values-nb/strings.xml
index d25df3f1..2ad14dc 100644
--- a/packages/SettingsLib/res/values-nb/strings.xml
+++ b/packages/SettingsLib/res/values-nb/strings.xml
@@ -102,8 +102,7 @@
     <string name="tts_default_rate_title" msgid="6030550998379310088">"Talehastighet"</string>
     <string name="tts_default_rate_summary" msgid="4061815292287182801">"Hvor raskt teksten leses"</string>
     <string name="tts_default_pitch_title" msgid="6135942113172488671">"Stemmeleie"</string>
-    <!-- no translation found for tts_default_pitch_summary (1944885882882650009) -->
-    <skip />
+    <string name="tts_default_pitch_summary" msgid="1944885882882650009">"Påvirker tonehøyden for syntetisert tale"</string>
     <string name="tts_default_lang_title" msgid="8018087612299820556">"Språk"</string>
     <string name="tts_lang_use_system" msgid="2679252467416513208">"Bruk systemspråk"</string>
     <string name="tts_lang_not_selected" msgid="7395787019276734765">"Språk er ikke valgt"</string>
@@ -279,7 +278,7 @@
     <string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"Kjør WebView-gjengivelser i en isolert prosess."</string>
     <string name="select_webview_provider_title" msgid="4628592979751918907">"WebView-implementering"</string>
     <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Angi WebView-implementering"</string>
-    <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"Den valgte implementeringen av nettvisningen er slått av – den må slås på for å brukes. Vil du slå den på?"</string>
+    <string name="select_webview_provider_toast_text" msgid="8168796505966635684">"Den valgte WebView-implementeringen er ugyldig fordi listen over implementeringsvalg er foreldet. Listen er nå oppdatert."</string>
     <string name="convert_to_file_encryption" msgid="3060156730651061223">"Konvertér til kryptert fil"</string>
     <string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Konvertér …"</string>
     <string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Allerede kryptert og lagret som fil"</string>
@@ -312,6 +311,8 @@
     <string name="battery_info_status_not_charging" msgid="2820070506621483576">"Lader ikke"</string>
     <string name="battery_info_status_full" msgid="2824614753861462808">"Fullt"</string>
     <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Kontrollert av administratoren"</string>
+    <string name="enabled_by_admin" msgid="2386503803463071894">"Slått på av administratoren"</string>
+    <string name="disabled_by_admin" msgid="3669999613095206948">"Avslått av administratoren"</string>
     <string name="home" msgid="8263346537524314127">"Startside"</string>
     <string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g> siden"</string>
     <string name="remaining_length_format" msgid="7886337596669190587">"<xliff:g id="ID_1">%1$s</xliff:g> gjenstår"</string>
diff --git a/packages/SettingsLib/res/values-ne-rNP/strings.xml b/packages/SettingsLib/res/values-ne-rNP/strings.xml
index 4ade997..6c8dc59 100644
--- a/packages/SettingsLib/res/values-ne-rNP/strings.xml
+++ b/packages/SettingsLib/res/values-ne-rNP/strings.xml
@@ -102,8 +102,7 @@
     <string name="tts_default_rate_title" msgid="6030550998379310088">"वाणी दर"</string>
     <string name="tts_default_rate_summary" msgid="4061815292287182801">"पाठ वाचन हुने गति"</string>
     <string name="tts_default_pitch_title" msgid="6135942113172488671">"पिच"</string>
-    <!-- no translation found for tts_default_pitch_summary (1944885882882650009) -->
-    <skip />
+    <string name="tts_default_pitch_summary" msgid="1944885882882650009">"संश्लेषित बोलीको टोनमा प्रभाव पार्छ"</string>
     <string name="tts_default_lang_title" msgid="8018087612299820556">"भाषा"</string>
     <string name="tts_lang_use_system" msgid="2679252467416513208">"प्रणाली भाषा प्रयोग गर्नुहोस्"</string>
     <string name="tts_lang_not_selected" msgid="7395787019276734765">"भाषा चयन गरिएको छैन"</string>
@@ -279,7 +278,7 @@
     <string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"एउटा पृथक प्रक्रियामा वेबभ्यु रेन्डररहरू चलाउनुहोस्।"</string>
     <string name="select_webview_provider_title" msgid="4628592979751918907">"WebView कार्यान्वयन"</string>
     <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"WebView कार्यान्वयन सेट गर्नुहोस्"</string>
-    <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"छनौट गरिएको WebView को कार्यान्वयन असक्षम गरिएको छ र प्रयोग गर्नका लागि सक्रिय गर्नुपर्छ, तपाईँ यसलाई सक्रिय गर्न चाहनुहुन्छ?"</string>
+    <string name="select_webview_provider_toast_text" msgid="8168796505966635684">"कार्यान्वयनको सूची पुरानो भइसकेको हुनाले छनोट गरिएको WebView को कार्यान्वयन अमान्य छ। सूची अब अद्यावधिक हुनुपर्छ।"</string>
     <string name="convert_to_file_encryption" msgid="3060156730651061223">"फाइल इन्क्रिप्सनमा रूपान्तरण गर्नुहोस्"</string>
     <string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"रुपान्तरण गर्नुहोस्…"</string>
     <string name="convert_to_file_encryption_done" msgid="7859766358000523953">"पहिल्यै फाइल इन्क्रिप्ट गरिएको छ"</string>
@@ -311,7 +310,9 @@
     <string name="battery_info_status_discharging" msgid="310932812698268588">"चार्ज भइरहेको छैन"</string>
     <string name="battery_info_status_not_charging" msgid="2820070506621483576">"चार्ज हुँदै छैन"</string>
     <string name="battery_info_status_full" msgid="2824614753861462808">"पूर्ण"</string>
-    <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"व्यवस्थापक द्वारा नियन्त्रित"</string>
+    <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"प्रशासकद्वारा नियन्त्रित"</string>
+    <string name="enabled_by_admin" msgid="2386503803463071894">"प्रशासकद्वारा सक्षम गरिएको छ"</string>
+    <string name="disabled_by_admin" msgid="3669999613095206948">"प्रशासकद्वारा असक्षम गरिएको छ"</string>
     <string name="home" msgid="8263346537524314127">"गृह"</string>
     <string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g> पहिले"</string>
     <string name="remaining_length_format" msgid="7886337596669190587">"<xliff:g id="ID_1">%1$s</xliff:g> बाँकी"</string>
diff --git a/packages/SettingsLib/res/values-nl/strings.xml b/packages/SettingsLib/res/values-nl/strings.xml
index 6432d9e..7f9df25 100644
--- a/packages/SettingsLib/res/values-nl/strings.xml
+++ b/packages/SettingsLib/res/values-nl/strings.xml
@@ -102,8 +102,7 @@
     <string name="tts_default_rate_title" msgid="6030550998379310088">"Spreeksnelheid"</string>
     <string name="tts_default_rate_summary" msgid="4061815292287182801">"Snelheid waarmee de tekst wordt gesproken"</string>
     <string name="tts_default_pitch_title" msgid="6135942113172488671">"Hoogte"</string>
-    <!-- no translation found for tts_default_pitch_summary (1944885882882650009) -->
-    <skip />
+    <string name="tts_default_pitch_summary" msgid="1944885882882650009">"Is van invloed op de toon van de synthetisch gegenereerde spraak"</string>
     <string name="tts_default_lang_title" msgid="8018087612299820556">"Taal"</string>
     <string name="tts_lang_use_system" msgid="2679252467416513208">"Systeemtaal gebruiken"</string>
     <string name="tts_lang_not_selected" msgid="7395787019276734765">"Taal niet geselecteerd"</string>
@@ -279,7 +278,7 @@
     <string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"WebView-weergaveprogramma\'s uitvoeren in geïsoleerd proces."</string>
     <string name="select_webview_provider_title" msgid="4628592979751918907">"WebView-implementatie"</string>
     <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"WebView-implementatie instellen"</string>
-    <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"De gekozen WebView-implementatie is uitgeschakeld en moet worden ingeschakeld voor gebruik. Wil je deze inschakelen?"</string>
+    <string name="select_webview_provider_toast_text" msgid="8168796505966635684">"De geselecteerde WebView-implementatie is ongeldig omdat de lijst met implementatiekeuzes was verouderd. De lijst is nu geüpdatet."</string>
     <string name="convert_to_file_encryption" msgid="3060156730651061223">"Converteren naar versleuteling op basis van bestanden"</string>
     <string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Converteren…"</string>
     <string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Al versleuteld op basis van bestanden"</string>
@@ -312,6 +311,8 @@
     <string name="battery_info_status_not_charging" msgid="2820070506621483576">"Wordt niet opgeladen"</string>
     <string name="battery_info_status_full" msgid="2824614753861462808">"Volledig"</string>
     <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Ingesteld door beheerder"</string>
+    <string name="enabled_by_admin" msgid="2386503803463071894">"Ingeschakeld door beheerder"</string>
+    <string name="disabled_by_admin" msgid="3669999613095206948">"Uitgeschakeld door beheerder"</string>
     <string name="home" msgid="8263346537524314127">"Startpagina"</string>
     <string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g> geleden"</string>
     <string name="remaining_length_format" msgid="7886337596669190587">"<xliff:g id="ID_1">%1$s</xliff:g> resterend"</string>
diff --git a/packages/SettingsLib/res/values-pa-rIN/strings.xml b/packages/SettingsLib/res/values-pa-rIN/strings.xml
index a65ff95..10d57f4 100644
--- a/packages/SettingsLib/res/values-pa-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-pa-rIN/strings.xml
@@ -102,8 +102,7 @@
     <string name="tts_default_rate_title" msgid="6030550998379310088">"ਸਪੀਚ ਰੇਟ"</string>
     <string name="tts_default_rate_summary" msgid="4061815292287182801">"ਸਪੀਡ ਜਿਸਤੇ ਟੈਕਸਟ ਬੋਲਿਆ ਜਾਂਦਾ ਹੈ"</string>
     <string name="tts_default_pitch_title" msgid="6135942113172488671">"ਪਿਚ"</string>
-    <!-- no translation found for tts_default_pitch_summary (1944885882882650009) -->
-    <skip />
+    <string name="tts_default_pitch_summary" msgid="1944885882882650009">"ਬਣਾਵਟੀ ਬੋਲੀ ਦੇ ਲਹਿਜੇ \'ਤੇ ਅਸਰ ਪਾਉਂਦੀ ਹੈ"</string>
     <string name="tts_default_lang_title" msgid="8018087612299820556">"ਭਾਸ਼ਾ"</string>
     <string name="tts_lang_use_system" msgid="2679252467416513208">"ਸਿਸਟਮ ਭਾਸ਼ਾ ਵਰਤੋ"</string>
     <string name="tts_lang_not_selected" msgid="7395787019276734765">"ਭਾਸ਼ਾ ਨਹੀਂ ਚੁਣੀ"</string>
@@ -279,7 +278,7 @@
     <string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"ਕਿਸੇ ਵੱਖ ਕੀਤੀ ਗਈ ਪ੍ਰਕਿਰਿਆ ਵਿੱਚ WebView ਰੈਂਡਰਰਾਂ ਨੂੰ ਚਲਾਓ।"</string>
     <string name="select_webview_provider_title" msgid="4628592979751918907">"WebView ਅਮਲ"</string>
     <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"WebView ਅਮਲ ਸੈੱਟ ਕਰੋ"</string>
-    <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"ਚੁਣਿਆ ਗਿਆ WebView ਅਮਲ ਅਯੋਗ ਬਣਾਇਆ ਗਿਆ ਹੈ, ਅਤੇ ਵਰਤੋਂ ਕਰਨ ਲਈ ਇਸ ਨੂੰ ਯੋਗ ਬਣਾਇਆ ਜਾਣਾ ਜ਼ਰੂਰੀ ਹੈ, ਕੀ ਤੁਸੀਂ ਇਸ ਨੂੰ ਯੋਗ ਬਣਾਉਣਾ ਚਾਹੁੰਦੇ ਹੋ?"</string>
+    <string name="select_webview_provider_toast_text" msgid="8168796505966635684">"ਚੁਣਿਆ ਗਿਆ WebView ਅਮਲ ਅਵੈਧ ਹੈ ਕਿਉਂਕਿ ਅਮਲ ਚੋਣਾਂ ਦੀ ਸੂਚੀ ਪੁਰਾਣੀ ਹੋ ਗਈ ਹੈ। ਸੂਚੀ ਨੂੰ ਹੁਣ ਅੱਪਡੇਟ ਕੀਤਾ ਜਾਣਾ ਚਾਹੀਦਾ ਹੈ।"</string>
     <string name="convert_to_file_encryption" msgid="3060156730651061223">"ਫ਼ਾਈਲ ਇਨਕ੍ਰਿਪਸ਼ਨ ਵਿੱਚ ਤਬਦੀਲ ਕਰੋ"</string>
     <string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"ਤਬਦੀਲ ਕਰੋ ..."</string>
     <string name="convert_to_file_encryption_done" msgid="7859766358000523953">"ਫ਼ਾਈਲ ਪਹਿਲਾਂ ਤੋਂ ਇਨਕ੍ਰਿਪਟਡ ਹੈ"</string>
@@ -312,6 +311,8 @@
     <string name="battery_info_status_not_charging" msgid="2820070506621483576">"ਚਾਰਜ ਨਹੀਂ ਹੋ ਰਿਹਾ"</string>
     <string name="battery_info_status_full" msgid="2824614753861462808">"ਪੂਰੀ"</string>
     <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"ਪ੍ਰਸ਼ਾਸਕ ਵੱਲੋਂ ਕੰਟਰੋਲ ਕੀਤੀ ਗਈ"</string>
+    <string name="enabled_by_admin" msgid="2386503803463071894">"ਪ੍ਰਸ਼ਾਸਕ ਵੱਲੋਂ ਯੋਗ ਬਣਾਈ ਗਈ"</string>
+    <string name="disabled_by_admin" msgid="3669999613095206948">"ਪ੍ਰਸ਼ਾਸਕ ਵੱਲੋਂ ਅਯੋਗ ਬਣਾਈ ਗਈ"</string>
     <string name="home" msgid="8263346537524314127">"ਮੁੱਖ ਸਕ੍ਰੀਨ"</string>
     <string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g> ਪਹਿਲਾਂ"</string>
     <string name="remaining_length_format" msgid="7886337596669190587">"<xliff:g id="ID_1">%1$s</xliff:g> ਬਾਕੀ"</string>
diff --git a/packages/SettingsLib/res/values-pl/strings.xml b/packages/SettingsLib/res/values-pl/strings.xml
index 77c08c0..3e89094 100644
--- a/packages/SettingsLib/res/values-pl/strings.xml
+++ b/packages/SettingsLib/res/values-pl/strings.xml
@@ -102,8 +102,7 @@
     <string name="tts_default_rate_title" msgid="6030550998379310088">"Szybkość mowy"</string>
     <string name="tts_default_rate_summary" msgid="4061815292287182801">"Szybkość czytania tekstu"</string>
     <string name="tts_default_pitch_title" msgid="6135942113172488671">"Tony"</string>
-    <!-- no translation found for tts_default_pitch_summary (1944885882882650009) -->
-    <skip />
+    <string name="tts_default_pitch_summary" msgid="1944885882882650009">"Wpływa na dźwięk syntezatora mowy"</string>
     <string name="tts_default_lang_title" msgid="8018087612299820556">"Język"</string>
     <string name="tts_lang_use_system" msgid="2679252467416513208">"Użyj języka systemu"</string>
     <string name="tts_lang_not_selected" msgid="7395787019276734765">"Nie wybrano języka"</string>
@@ -279,7 +278,7 @@
     <string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"Uruchom WebView jako izolowany proces."</string>
     <string name="select_webview_provider_title" msgid="4628592979751918907">"Implementacja WebView"</string>
     <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Ustaw implementację WebView"</string>
-    <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"Wybrana implementacja WebView jest wyłączona. Aby jej używać, musisz ją włączyć. Chcesz to zrobić?"</string>
+    <string name="select_webview_provider_toast_text" msgid="8168796505966635684">"Wybrana implementacja WebView jest nieprawidłowa – lista implementacji do wyboru straciła ważność. Musisz zaktualizować listę."</string>
     <string name="convert_to_file_encryption" msgid="3060156730651061223">"Przekształć na szyfrowanie plików"</string>
     <string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Przekształć…"</string>
     <string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Pliki są już zaszyfrowane"</string>
@@ -312,6 +311,8 @@
     <string name="battery_info_status_not_charging" msgid="2820070506621483576">"Nie podłączony"</string>
     <string name="battery_info_status_full" msgid="2824614753861462808">"Naładowana"</string>
     <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Kontrolowane przez administratora"</string>
+    <string name="enabled_by_admin" msgid="2386503803463071894">"Włączone przez administratora"</string>
+    <string name="disabled_by_admin" msgid="3669999613095206948">"Wyłączone przez administratora"</string>
     <string name="home" msgid="8263346537524314127">"Ekran główny"</string>
     <string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g> temu"</string>
     <string name="remaining_length_format" msgid="7886337596669190587">"Pozostało <xliff:g id="ID_1">%1$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-pt-rBR/strings.xml b/packages/SettingsLib/res/values-pt-rBR/strings.xml
index 37af1c4..c772ded 100644
--- a/packages/SettingsLib/res/values-pt-rBR/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rBR/strings.xml
@@ -102,8 +102,7 @@
     <string name="tts_default_rate_title" msgid="6030550998379310088">"Taxa de fala"</string>
     <string name="tts_default_rate_summary" msgid="4061815292287182801">"Velocidade em que o texto é falado"</string>
     <string name="tts_default_pitch_title" msgid="6135942113172488671">"Frequência do som"</string>
-    <!-- no translation found for tts_default_pitch_summary (1944885882882650009) -->
-    <skip />
+    <string name="tts_default_pitch_summary" msgid="1944885882882650009">"Afeta o tom da voz sintetizada"</string>
     <string name="tts_default_lang_title" msgid="8018087612299820556">"Idioma"</string>
     <string name="tts_lang_use_system" msgid="2679252467416513208">"Usar idioma do sistema"</string>
     <string name="tts_lang_not_selected" msgid="7395787019276734765">"Idioma não selecionado"</string>
@@ -279,7 +278,7 @@
     <string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"Executar renderizadores de WebView em um processo isolado."</string>
     <string name="select_webview_provider_title" msgid="4628592979751918907">"Implementação do WebView"</string>
     <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Configurar implementação do WebView"</string>
-    <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"A implementação do WebView escolhida está desativada e deve ser ativada para ser usada. Deseja ativá-la?"</string>
+    <string name="select_webview_provider_toast_text" msgid="8168796505966635684">"A implementação de WebView escolhida é inválida, porque a lista de opções de implementação estava desatualizada. A lista deve estar atualizada agora."</string>
     <string name="convert_to_file_encryption" msgid="3060156730651061223">"Converter para criptografia de arquivos"</string>
     <string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Converter..."</string>
     <string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Já criptografado com base em arquivos"</string>
@@ -312,6 +311,8 @@
     <string name="battery_info_status_not_charging" msgid="2820070506621483576">"Não está carregando"</string>
     <string name="battery_info_status_full" msgid="2824614753861462808">"Cheio"</string>
     <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Controlada pelo admin"</string>
+    <string name="enabled_by_admin" msgid="2386503803463071894">"Ativada pelo administrador"</string>
+    <string name="disabled_by_admin" msgid="3669999613095206948">"Desativada pelo administrador"</string>
     <string name="home" msgid="8263346537524314127">"Início"</string>
     <string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g> atrás"</string>
     <string name="remaining_length_format" msgid="7886337596669190587">"<xliff:g id="ID_1">%1$s</xliff:g> restante(s)"</string>
diff --git a/packages/SettingsLib/res/values-pt-rPT/strings.xml b/packages/SettingsLib/res/values-pt-rPT/strings.xml
index 46e16ce..2b3dcc7 100644
--- a/packages/SettingsLib/res/values-pt-rPT/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rPT/strings.xml
@@ -102,8 +102,7 @@
     <string name="tts_default_rate_title" msgid="6030550998379310088">"Taxa de voz"</string>
     <string name="tts_default_rate_summary" msgid="4061815292287182801">"Velocidade a que o texto é falado"</string>
     <string name="tts_default_pitch_title" msgid="6135942113172488671">"Tonalidade"</string>
-    <!-- no translation found for tts_default_pitch_summary (1944885882882650009) -->
-    <skip />
+    <string name="tts_default_pitch_summary" msgid="1944885882882650009">"Afeta o tom da voz sintetizada"</string>
     <string name="tts_default_lang_title" msgid="8018087612299820556">"Idioma"</string>
     <string name="tts_lang_use_system" msgid="2679252467416513208">"Utilizar idioma do sistema"</string>
     <string name="tts_lang_not_selected" msgid="7395787019276734765">"Idioma não selecionado"</string>
@@ -279,7 +278,7 @@
     <string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"Executar renderizadores WebView num processo isolado."</string>
     <string name="select_webview_provider_title" msgid="4628592979751918907">"Implementação WebView"</string>
     <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Definir implementação WebView"</string>
-    <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"A implementação WebView escolhida foi desativada e tem de ser ativada para poder ser utilizada. Pretende ativá-la?"</string>
+    <string name="select_webview_provider_toast_text" msgid="8168796505966635684">"A implementação WebView escolhida é inválida porque a lista de opções de implementação encontra-se desatualizada. A lista deve ser atualizada agora."</string>
     <string name="convert_to_file_encryption" msgid="3060156730651061223">"Converter para a encriptação de ficheiros"</string>
     <string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Converter..."</string>
     <string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Os ficheiros já estão encriptados"</string>
@@ -312,6 +311,8 @@
     <string name="battery_info_status_not_charging" msgid="2820070506621483576">"Não está a carregar"</string>
     <string name="battery_info_status_full" msgid="2824614753861462808">"Completo"</string>
     <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Controlado pelo administrador"</string>
+    <string name="enabled_by_admin" msgid="2386503803463071894">"Ativado pelo administrador"</string>
+    <string name="disabled_by_admin" msgid="3669999613095206948">"Desativado pelo administrador"</string>
     <string name="home" msgid="8263346537524314127">"Página inicial"</string>
     <string name="charge_length_format" msgid="8978516217024434156">"Há <xliff:g id="ID_1">%1$s</xliff:g>"</string>
     <string name="remaining_length_format" msgid="7886337596669190587">"Resta(m) <xliff:g id="ID_1">%1$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-pt/strings.xml b/packages/SettingsLib/res/values-pt/strings.xml
index 37af1c4..c772ded 100644
--- a/packages/SettingsLib/res/values-pt/strings.xml
+++ b/packages/SettingsLib/res/values-pt/strings.xml
@@ -102,8 +102,7 @@
     <string name="tts_default_rate_title" msgid="6030550998379310088">"Taxa de fala"</string>
     <string name="tts_default_rate_summary" msgid="4061815292287182801">"Velocidade em que o texto é falado"</string>
     <string name="tts_default_pitch_title" msgid="6135942113172488671">"Frequência do som"</string>
-    <!-- no translation found for tts_default_pitch_summary (1944885882882650009) -->
-    <skip />
+    <string name="tts_default_pitch_summary" msgid="1944885882882650009">"Afeta o tom da voz sintetizada"</string>
     <string name="tts_default_lang_title" msgid="8018087612299820556">"Idioma"</string>
     <string name="tts_lang_use_system" msgid="2679252467416513208">"Usar idioma do sistema"</string>
     <string name="tts_lang_not_selected" msgid="7395787019276734765">"Idioma não selecionado"</string>
@@ -279,7 +278,7 @@
     <string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"Executar renderizadores de WebView em um processo isolado."</string>
     <string name="select_webview_provider_title" msgid="4628592979751918907">"Implementação do WebView"</string>
     <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Configurar implementação do WebView"</string>
-    <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"A implementação do WebView escolhida está desativada e deve ser ativada para ser usada. Deseja ativá-la?"</string>
+    <string name="select_webview_provider_toast_text" msgid="8168796505966635684">"A implementação de WebView escolhida é inválida, porque a lista de opções de implementação estava desatualizada. A lista deve estar atualizada agora."</string>
     <string name="convert_to_file_encryption" msgid="3060156730651061223">"Converter para criptografia de arquivos"</string>
     <string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Converter..."</string>
     <string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Já criptografado com base em arquivos"</string>
@@ -312,6 +311,8 @@
     <string name="battery_info_status_not_charging" msgid="2820070506621483576">"Não está carregando"</string>
     <string name="battery_info_status_full" msgid="2824614753861462808">"Cheio"</string>
     <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Controlada pelo admin"</string>
+    <string name="enabled_by_admin" msgid="2386503803463071894">"Ativada pelo administrador"</string>
+    <string name="disabled_by_admin" msgid="3669999613095206948">"Desativada pelo administrador"</string>
     <string name="home" msgid="8263346537524314127">"Início"</string>
     <string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g> atrás"</string>
     <string name="remaining_length_format" msgid="7886337596669190587">"<xliff:g id="ID_1">%1$s</xliff:g> restante(s)"</string>
diff --git a/packages/SettingsLib/res/values-ro/strings.xml b/packages/SettingsLib/res/values-ro/strings.xml
index 5863c92..0322f55 100644
--- a/packages/SettingsLib/res/values-ro/strings.xml
+++ b/packages/SettingsLib/res/values-ro/strings.xml
@@ -102,8 +102,7 @@
     <string name="tts_default_rate_title" msgid="6030550998379310088">"Ritmul vorbirii"</string>
     <string name="tts_default_rate_summary" msgid="4061815292287182801">"Viteza cu care este vorbit textul"</string>
     <string name="tts_default_pitch_title" msgid="6135942113172488671">"Înălțime"</string>
-    <!-- no translation found for tts_default_pitch_summary (1944885882882650009) -->
-    <skip />
+    <string name="tts_default_pitch_summary" msgid="1944885882882650009">"Afectează tonalitatea vorbirii sintetizate"</string>
     <string name="tts_default_lang_title" msgid="8018087612299820556">"Limbă"</string>
     <string name="tts_lang_use_system" msgid="2679252467416513208">"Utilizați limba sistemului"</string>
     <string name="tts_lang_not_selected" msgid="7395787019276734765">"Nu ați selectat limba"</string>
@@ -279,7 +278,7 @@
     <string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"Rulați programele de redare WebView într-un proces izolat."</string>
     <string name="select_webview_provider_title" msgid="4628592979751918907">"Implementare WebView"</string>
     <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Setați implementarea WebView"</string>
-    <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"Implementarea WebView aleasă este dezactivată. Pentru a fi folosită, trebuie să fie activată. Doriți să o activați?"</string>
+    <string name="select_webview_provider_toast_text" msgid="8168796505966635684">"Implementarea WebView aleasă nu este validă, deoarece lista cu alegerile pentru implementare s-a învechit. Lista ar trebui să fie actualizată acum."</string>
     <string name="convert_to_file_encryption" msgid="3060156730651061223">"Faceți conversia la criptarea bazată pe sistemul de fișiere"</string>
     <string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Convertiți…"</string>
     <string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Criptarea bazată pe sistemul de fișiere este finalizată"</string>
@@ -312,6 +311,8 @@
     <string name="battery_info_status_not_charging" msgid="2820070506621483576">"Nu încarcă"</string>
     <string name="battery_info_status_full" msgid="2824614753861462808">"Complet"</string>
     <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Controlată de administrator"</string>
+    <string name="enabled_by_admin" msgid="2386503803463071894">"Activată de administrator"</string>
+    <string name="disabled_by_admin" msgid="3669999613095206948">"Dezactivată de administrator"</string>
     <string name="home" msgid="8263346537524314127">"Ecranul principal"</string>
     <string name="charge_length_format" msgid="8978516217024434156">"Acum <xliff:g id="ID_1">%1$s</xliff:g>"</string>
     <string name="remaining_length_format" msgid="7886337596669190587">"Timp rămas: <xliff:g id="ID_1">%1$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-ru/strings.xml b/packages/SettingsLib/res/values-ru/strings.xml
index 3c2affe..7548ace 100644
--- a/packages/SettingsLib/res/values-ru/strings.xml
+++ b/packages/SettingsLib/res/values-ru/strings.xml
@@ -102,8 +102,7 @@
     <string name="tts_default_rate_title" msgid="6030550998379310088">"Скорость речи"</string>
     <string name="tts_default_rate_summary" msgid="4061815292287182801">"Скорость чтения текста"</string>
     <string name="tts_default_pitch_title" msgid="6135942113172488671">"Тон"</string>
-    <!-- no translation found for tts_default_pitch_summary (1944885882882650009) -->
-    <skip />
+    <string name="tts_default_pitch_summary" msgid="1944885882882650009">"Влияет на высоту синтезированной речи"</string>
     <string name="tts_default_lang_title" msgid="8018087612299820556">"Язык"</string>
     <string name="tts_lang_use_system" msgid="2679252467416513208">"Язык системы"</string>
     <string name="tts_lang_not_selected" msgid="7395787019276734765">"Язык не выбран"</string>
@@ -275,11 +274,11 @@
     <string name="inactive_app_active_summary" msgid="4174921824958516106">"Включено. Нажмите, чтобы отключить."</string>
     <string name="runningservices_settings_title" msgid="8097287939865165213">"Работающие приложения"</string>
     <string name="runningservices_settings_summary" msgid="854608995821032748">"Просмотр и управление работающими приложениями"</string>
-    <string name="enable_webview_multiprocess" msgid="3405948012467585908">"Запуск неск. процессов WebView"</string>
-    <string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"Выполнять обработку WebView как отдельный процесс"</string>
+    <string name="enable_webview_multiprocess" msgid="3405948012467585908">"Включить многопроц. WebView"</string>
+    <string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"Выполнять обработчики WebView в изолированном процессе"</string>
     <string name="select_webview_provider_title" msgid="4628592979751918907">"Сервис WebView"</string>
     <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Настройки сервиса WebView"</string>
-    <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"Чтобы использовать сервис WebView, включите его. Сделать это?"</string>
+    <string name="select_webview_provider_toast_text" msgid="8168796505966635684">"Выбранный сервис WebView не поддерживается. Список сервисов устарел и сейчас будет обновлен."</string>
     <string name="convert_to_file_encryption" msgid="3060156730651061223">"Переход к шифрованию файлов"</string>
     <string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Перейти…"</string>
     <string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Шифрование файлов уже включено"</string>
@@ -312,6 +311,8 @@
     <string name="battery_info_status_not_charging" msgid="2820070506621483576">"Не заряжается"</string>
     <string name="battery_info_status_full" msgid="2824614753861462808">"Батарея заряжена"</string>
     <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Контролируется администратором"</string>
+    <string name="enabled_by_admin" msgid="2386503803463071894">"Включено администратором"</string>
+    <string name="disabled_by_admin" msgid="3669999613095206948">"Отключено администратором"</string>
     <string name="home" msgid="8263346537524314127">"Главная"</string>
     <string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g> назад"</string>
     <string name="remaining_length_format" msgid="7886337596669190587">"Осталось <xliff:g id="ID_1">%1$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-si-rLK/strings.xml b/packages/SettingsLib/res/values-si-rLK/strings.xml
index be6b6dd..f3d6dc3 100644
--- a/packages/SettingsLib/res/values-si-rLK/strings.xml
+++ b/packages/SettingsLib/res/values-si-rLK/strings.xml
@@ -102,8 +102,7 @@
     <string name="tts_default_rate_title" msgid="6030550998379310088">"කථන ශීඝ්‍රතාව"</string>
     <string name="tts_default_rate_summary" msgid="4061815292287182801">"පෙළ කථා කරනා වේගය"</string>
     <string name="tts_default_pitch_title" msgid="6135942113172488671">"තාරතාව"</string>
-    <!-- no translation found for tts_default_pitch_summary (1944885882882650009) -->
-    <skip />
+    <string name="tts_default_pitch_summary" msgid="1944885882882650009">"සංශ්ලේෂණය කළ කථනයෙහි ස්වරයට බලපායි"</string>
     <string name="tts_default_lang_title" msgid="8018087612299820556">"භාෂාව"</string>
     <string name="tts_lang_use_system" msgid="2679252467416513208">"පද්ධති භාෂාව භාවිතා කරන්න"</string>
     <string name="tts_lang_not_selected" msgid="7395787019276734765">"භාෂාව තෝරා ගෙන නැත"</string>
@@ -279,7 +278,7 @@
     <string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"හුදකලා වූ ක්‍රියාවලියක WebView විදහා දැක්වීම් ධාවනය කරන්න."</string>
     <string name="select_webview_provider_title" msgid="4628592979751918907">"WebView ක්‍රියාත්මක කිරීම"</string>
     <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"WebView ක්‍රියාත්මක කිරීම සකසන්න"</string>
-    <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"තෝරන ලද WebView ක්‍රියාත්මක කිරීම අබල අතර, භාවිත කිරීමට සබල කළ යුතුය, ඔබ එය සබල කිරීමට අදහස් කරන්නේද?"</string>
+    <string name="select_webview_provider_toast_text" msgid="8168796505966635684">"තෝරන ලද WebView ක්‍රියාත්මක කිරීම ක්‍රියාත්මක කිරීම් තේරීම් ලැයිස්තු යල් පැන ඇති නිසා වලංගු නැත. ලැයිස්තුව දැන් යාවත්කාලීන කළ යුතුය."</string>
     <string name="convert_to_file_encryption" msgid="3060156730651061223">"ගොනු සංකේතනයට පරිවර්තනය කරන්න"</string>
     <string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"පරිවර්තනය කරන්න..."</string>
     <string name="convert_to_file_encryption_done" msgid="7859766358000523953">"දැනටමත් ගොනුව සංකේතනය කර ඇත"</string>
@@ -312,6 +311,8 @@
     <string name="battery_info_status_not_charging" msgid="2820070506621483576">"ආරෝපණය නොවෙමින්"</string>
     <string name="battery_info_status_full" msgid="2824614753861462808">"පූර්ණ"</string>
     <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"පරිපාලක විසින් පාලනය කරන ලදී"</string>
+    <string name="enabled_by_admin" msgid="2386503803463071894">"පරිපාලක විසින් සබල කරන ලදී"</string>
+    <string name="disabled_by_admin" msgid="3669999613095206948">"පරිපාලක විසින් අබල කරන ලදී"</string>
     <string name="home" msgid="8263346537524314127">"මුල් පිටුව"</string>
     <string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g>කට පෙර"</string>
     <string name="remaining_length_format" msgid="7886337596669190587">"<xliff:g id="ID_1">%1$s</xliff:g>ක් ඉතිරිය"</string>
diff --git a/packages/SettingsLib/res/values-sk/strings.xml b/packages/SettingsLib/res/values-sk/strings.xml
index 5be89eb..712c348 100644
--- a/packages/SettingsLib/res/values-sk/strings.xml
+++ b/packages/SettingsLib/res/values-sk/strings.xml
@@ -102,8 +102,7 @@
     <string name="tts_default_rate_title" msgid="6030550998379310088">"Rýchlosť reči"</string>
     <string name="tts_default_rate_summary" msgid="4061815292287182801">"Rýchlosť hovoreného textu"</string>
     <string name="tts_default_pitch_title" msgid="6135942113172488671">"Výška"</string>
-    <!-- no translation found for tts_default_pitch_summary (1944885882882650009) -->
-    <skip />
+    <string name="tts_default_pitch_summary" msgid="1944885882882650009">"Určuje zvuk syntetizovaného hlasu"</string>
     <string name="tts_default_lang_title" msgid="8018087612299820556">"Jazyk"</string>
     <string name="tts_lang_use_system" msgid="2679252467416513208">"Používať jazyk systému"</string>
     <string name="tts_lang_not_selected" msgid="7395787019276734765">"Nebol vybratý jazyk"</string>
@@ -279,7 +278,7 @@
     <string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"Spúšťať vykresľovacie moduly WebView v izolovanom procese."</string>
     <string name="select_webview_provider_title" msgid="4628592979751918907">"Implementácia komponenta WebView"</string>
     <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Nastavenie implementácie komponenta WebView"</string>
-    <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"Zvolená implementácia technológie WebView je zakázaná. Ak ju chcete použiť, musíte ju najprv povoliť. Chcete ju povoliť?"</string>
+    <string name="select_webview_provider_toast_text" msgid="8168796505966635684">"Zvolená implementácia komponenta WebView nie je platná, pretože zoznam volieb implementácie nie je aktuálny. Zoznam by už mal byť aktualizovaný."</string>
     <string name="convert_to_file_encryption" msgid="3060156730651061223">"Konvertovať na šifrovanie súborov"</string>
     <string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Konvertovať…"</string>
     <string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Súbory sú už šifrované"</string>
@@ -312,6 +311,8 @@
     <string name="battery_info_status_not_charging" msgid="2820070506621483576">"Nenabíja sa"</string>
     <string name="battery_info_status_full" msgid="2824614753861462808">"Nabitá"</string>
     <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Ovládané správcom"</string>
+    <string name="enabled_by_admin" msgid="2386503803463071894">"Povolené správcom"</string>
+    <string name="disabled_by_admin" msgid="3669999613095206948">"Zakázané správcom"</string>
     <string name="home" msgid="8263346537524314127">"Domov"</string>
     <string name="charge_length_format" msgid="8978516217024434156">"pred <xliff:g id="ID_1">%1$s</xliff:g>"</string>
     <string name="remaining_length_format" msgid="7886337596669190587">"Zostáva <xliff:g id="ID_1">%1$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-sl/strings.xml b/packages/SettingsLib/res/values-sl/strings.xml
index 62cd3ce..2f23144 100644
--- a/packages/SettingsLib/res/values-sl/strings.xml
+++ b/packages/SettingsLib/res/values-sl/strings.xml
@@ -102,8 +102,7 @@
     <string name="tts_default_rate_title" msgid="6030550998379310088">"Hitrost govora"</string>
     <string name="tts_default_rate_summary" msgid="4061815292287182801">"Hitrost govorjenega besedila"</string>
     <string name="tts_default_pitch_title" msgid="6135942113172488671">"Višina tona"</string>
-    <!-- no translation found for tts_default_pitch_summary (1944885882882650009) -->
-    <skip />
+    <string name="tts_default_pitch_summary" msgid="1944885882882650009">"Vpliva na ton sintetiziranega govora"</string>
     <string name="tts_default_lang_title" msgid="8018087612299820556">"Jezik"</string>
     <string name="tts_lang_use_system" msgid="2679252467416513208">"Uporabi sistemski jezik"</string>
     <string name="tts_lang_not_selected" msgid="7395787019276734765">"Jezik ni izbran"</string>
@@ -275,11 +274,11 @@
     <string name="inactive_app_active_summary" msgid="4174921824958516106">"Aktivno. Dotaknite se za preklop."</string>
     <string name="runningservices_settings_title" msgid="8097287939865165213">"Zagnane storitve"</string>
     <string name="runningservices_settings_summary" msgid="854608995821032748">"Preglejte in nadzorujte storitve, ki so trenutno zagnane"</string>
-    <string name="enable_webview_multiprocess" msgid="3405948012467585908">"Omog. splet. pogl. z več proc."</string>
-    <string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"Izvajanje upodabljalnikov spletnega pogleda v loč. procesu."</string>
+    <string name="enable_webview_multiprocess" msgid="3405948012467585908">"Omogoči večprocesni WebView"</string>
+    <string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"Izvajanje upodabljalnikov za WebView v ločenem procesu."</string>
     <string name="select_webview_provider_title" msgid="4628592979751918907">"Izvedba spletnega pogleda"</string>
     <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Nastavitev izvedbe spletnega pogleda"</string>
-    <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"Izbrana izvedba spletnega pogleda je onemogočena in jo morate omogočiti, če jo želite uporabljati. Ali jo želite omogočiti?"</string>
+    <string name="select_webview_provider_toast_text" msgid="8168796505966635684">"Izbrana izvedba komponente WebView je neveljavna zaradi zastaranja seznama izbir za izvedbo. Seznam bi zdaj moral biti posodobljen."</string>
     <string name="convert_to_file_encryption" msgid="3060156730651061223">"Preklop na šifriranje podatkov"</string>
     <string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Preklop …"</string>
     <string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Šifriranje podatkov je že uveljavljeno"</string>
@@ -312,6 +311,8 @@
     <string name="battery_info_status_not_charging" msgid="2820070506621483576">"Se ne polni"</string>
     <string name="battery_info_status_full" msgid="2824614753861462808">"Poln"</string>
     <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Nadzira skrbnik"</string>
+    <string name="enabled_by_admin" msgid="2386503803463071894">"Omogočil skrbnik"</string>
+    <string name="disabled_by_admin" msgid="3669999613095206948">"Onemogočil skrbnik"</string>
     <string name="home" msgid="8263346537524314127">"Začetni zaslon"</string>
     <string name="charge_length_format" msgid="8978516217024434156">"Pred toliko časa: <xliff:g id="ID_1">%1$s</xliff:g>"</string>
     <string name="remaining_length_format" msgid="7886337596669190587">"Še <xliff:g id="ID_1">%1$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-sq-rAL/strings.xml b/packages/SettingsLib/res/values-sq-rAL/strings.xml
index 78e63e5..853dd2f 100644
--- a/packages/SettingsLib/res/values-sq-rAL/strings.xml
+++ b/packages/SettingsLib/res/values-sq-rAL/strings.xml
@@ -102,8 +102,7 @@
     <string name="tts_default_rate_title" msgid="6030550998379310088">"Shpejtësia e të folurit"</string>
     <string name="tts_default_rate_summary" msgid="4061815292287182801">"Shpejtësia me të cilën thuhet teksti"</string>
     <string name="tts_default_pitch_title" msgid="6135942113172488671">"Tonaliteti"</string>
-    <!-- no translation found for tts_default_pitch_summary (1944885882882650009) -->
-    <skip />
+    <string name="tts_default_pitch_summary" msgid="1944885882882650009">"Ndikon te toni i ligjërimit të sintetizuar"</string>
     <string name="tts_default_lang_title" msgid="8018087612299820556">"Gjuha"</string>
     <string name="tts_lang_use_system" msgid="2679252467416513208">"Përdor gjuhën e sistemit"</string>
     <string name="tts_lang_not_selected" msgid="7395787019276734765">"Nuk është përzgjedhur gjuha"</string>
@@ -279,7 +278,7 @@
     <string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"Ekzekuto renderizuesit e WebView në një proces të izoluar."</string>
     <string name="select_webview_provider_title" msgid="4628592979751918907">"Zbatimi i WebView"</string>
     <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Cakto zbatimin e WebView"</string>
-    <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"Është çaktivizuar zbatimi i zgjedhur i WebView dhe duhet të aktivizohet për t\'u përdorur, dëshiron ta aktivizosh?"</string>
+    <string name="select_webview_provider_toast_text" msgid="8168796505966635684">"Zbatimi i WebView të zgjedhur është i pavlefshëm sepse lista e zgjedhjeve të zbatimit është bërë e pavlefshme. Lista duhet të përditësohet tani."</string>
     <string name="convert_to_file_encryption" msgid="3060156730651061223">"Konverto në enkriptimin e skedarit"</string>
     <string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Konverto..."</string>
     <string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Enkriptimi i skedarit është kryer tashmë"</string>
@@ -312,6 +311,8 @@
     <string name="battery_info_status_not_charging" msgid="2820070506621483576">"Nuk po ngarkohet"</string>
     <string name="battery_info_status_full" msgid="2824614753861462808">"E mbushur"</string>
     <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Kontrolluar nga administratori"</string>
+    <string name="enabled_by_admin" msgid="2386503803463071894">"Aktivizuar nga administratori"</string>
+    <string name="disabled_by_admin" msgid="3669999613095206948">"Çaktivizuar nga administratori"</string>
     <string name="home" msgid="8263346537524314127">"Kreu"</string>
     <string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g> më parë"</string>
     <string name="remaining_length_format" msgid="7886337596669190587">"<xliff:g id="ID_1">%1$s</xliff:g> të mbetura"</string>
diff --git a/packages/SettingsLib/res/values-sr/strings.xml b/packages/SettingsLib/res/values-sr/strings.xml
index c7b3cbc..094a405 100644
--- a/packages/SettingsLib/res/values-sr/strings.xml
+++ b/packages/SettingsLib/res/values-sr/strings.xml
@@ -102,8 +102,7 @@
     <string name="tts_default_rate_title" msgid="6030550998379310088">"Брзина говора"</string>
     <string name="tts_default_rate_summary" msgid="4061815292287182801">"Брзина изговарања текста"</string>
     <string name="tts_default_pitch_title" msgid="6135942113172488671">"Ниво"</string>
-    <!-- no translation found for tts_default_pitch_summary (1944885882882650009) -->
-    <skip />
+    <string name="tts_default_pitch_summary" msgid="1944885882882650009">"Утиче на тон синтетизованог говора"</string>
     <string name="tts_default_lang_title" msgid="8018087612299820556">"Језик"</string>
     <string name="tts_lang_use_system" msgid="2679252467416513208">"Користи језик система"</string>
     <string name="tts_lang_not_selected" msgid="7395787019276734765">"Језик није изабран"</string>
@@ -279,7 +278,7 @@
     <string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"Покрећите WebView приказиваче у оквиру изолованог процеса."</string>
     <string name="select_webview_provider_title" msgid="4628592979751918907">"Примена WebView-а"</string>
     <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Подесите примену WebView-а"</string>
-    <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"Изабрана примена WebView-а је онемогућена, а мора да буде омогућена ради коришћења. Желите ли да је омогућите?"</string>
+    <string name="select_webview_provider_toast_text" msgid="8168796505966635684">"Изабрана примена WebView-а је неважећа зато што је листа могућности за примену застарела. Сада би требало да ажурирате листу."</string>
     <string name="convert_to_file_encryption" msgid="3060156730651061223">"Конвертуј у шифровање датотека"</string>
     <string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Конвертуј..."</string>
     <string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Већ се користи шифровање датотека"</string>
@@ -312,6 +311,8 @@
     <string name="battery_info_status_not_charging" msgid="2820070506621483576">"Не пуни се"</string>
     <string name="battery_info_status_full" msgid="2824614753861462808">"Пуно"</string>
     <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Контролише администратор"</string>
+    <string name="enabled_by_admin" msgid="2386503803463071894">"Омогућио је администратор"</string>
+    <string name="disabled_by_admin" msgid="3669999613095206948">"Онемогућио је администратор"</string>
     <string name="home" msgid="8263346537524314127">"Почетни"</string>
     <string name="charge_length_format" msgid="8978516217024434156">"Пре <xliff:g id="ID_1">%1$s</xliff:g>"</string>
     <string name="remaining_length_format" msgid="7886337596669190587">"Још <xliff:g id="ID_1">%1$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-sv/strings.xml b/packages/SettingsLib/res/values-sv/strings.xml
index 09baf91..e12d394 100644
--- a/packages/SettingsLib/res/values-sv/strings.xml
+++ b/packages/SettingsLib/res/values-sv/strings.xml
@@ -102,8 +102,7 @@
     <string name="tts_default_rate_title" msgid="6030550998379310088">"Talhastighet"</string>
     <string name="tts_default_rate_summary" msgid="4061815292287182801">"Talhastighet för texten"</string>
     <string name="tts_default_pitch_title" msgid="6135942113172488671">"Ton"</string>
-    <!-- no translation found for tts_default_pitch_summary (1944885882882650009) -->
-    <skip />
+    <string name="tts_default_pitch_summary" msgid="1944885882882650009">"Påverkar tonen i det syntetiska talet"</string>
     <string name="tts_default_lang_title" msgid="8018087612299820556">"Språk"</string>
     <string name="tts_lang_use_system" msgid="2679252467416513208">"Använd systemspråk"</string>
     <string name="tts_lang_not_selected" msgid="7395787019276734765">"Inget språk valt"</string>
@@ -279,7 +278,7 @@
     <string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"Kör WebView-renderare i en isolerad bearbetning."</string>
     <string name="select_webview_provider_title" msgid="4628592979751918907">"WebView-implementering"</string>
     <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Ange WebView-implementering"</string>
-    <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"Den valda WebView-implementeringen har inaktiverats och måste aktiveras om du ska kunna använda den. Vill du aktivera den?"</string>
+    <string name="select_webview_provider_toast_text" msgid="8168796505966635684">"Den valda WebView-implementeringen är ogiltig eftersom listan med implementeringsalternativ blev inaktuell. Listan ska nu ha uppdaterats."</string>
     <string name="convert_to_file_encryption" msgid="3060156730651061223">"Konvertera till filkryptering"</string>
     <string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Konvertera …"</string>
     <string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Filkryptering används redan"</string>
@@ -312,6 +311,8 @@
     <string name="battery_info_status_not_charging" msgid="2820070506621483576">"Laddar inte"</string>
     <string name="battery_info_status_full" msgid="2824614753861462808">"Fullt"</string>
     <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Strys av administratören"</string>
+    <string name="enabled_by_admin" msgid="2386503803463071894">"Har aktiverats av administratören"</string>
+    <string name="disabled_by_admin" msgid="3669999613095206948">"Har inaktiverats av administratören"</string>
     <string name="home" msgid="8263346537524314127">"Startsida"</string>
     <string name="charge_length_format" msgid="8978516217024434156">"för <xliff:g id="ID_1">%1$s</xliff:g> sedan"</string>
     <string name="remaining_length_format" msgid="7886337596669190587">"<xliff:g id="ID_1">%1$s</xliff:g> kvar"</string>
diff --git a/packages/SettingsLib/res/values-sw/strings.xml b/packages/SettingsLib/res/values-sw/strings.xml
index 17ec610..d5a9d1b 100644
--- a/packages/SettingsLib/res/values-sw/strings.xml
+++ b/packages/SettingsLib/res/values-sw/strings.xml
@@ -102,8 +102,7 @@
     <string name="tts_default_rate_title" msgid="6030550998379310088">"Kiwango cha usemaji"</string>
     <string name="tts_default_rate_summary" msgid="4061815292287182801">"Kasi ya kutamkwa kwa maneno"</string>
     <string name="tts_default_pitch_title" msgid="6135942113172488671">"Giza"</string>
-    <!-- no translation found for tts_default_pitch_summary (1944885882882650009) -->
-    <skip />
+    <string name="tts_default_pitch_summary" msgid="1944885882882650009">"Huathiri sauti ya matamshi yaliyounganishwa"</string>
     <string name="tts_default_lang_title" msgid="8018087612299820556">"Lugha"</string>
     <string name="tts_lang_use_system" msgid="2679252467416513208">"Tumia lugha ya mfumo"</string>
     <string name="tts_lang_not_selected" msgid="7395787019276734765">"Lugha haijachaguliwa"</string>
@@ -279,7 +278,7 @@
     <string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"Tekeleza vitoaji huduma vya WebView katika mchakato mahususi."</string>
     <string name="select_webview_provider_title" msgid="4628592979751918907">"Utekelezaji wa WebView"</string>
     <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Weka utekelezaji wa WebView"</string>
-    <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"Kipengee ulichochagua cha utekelezaji wa WebView kimezimwa. Ni lazima ukiwashe ili kitumike. Ungependa kukiwasha?"</string>
+    <string name="select_webview_provider_toast_text" msgid="8168796505966635684">"Utekelezaji wa WebView uliochaguliwa si sahihi kwa sababu orodha ya chaguo za utekelezaji imepitwa na muda. Ni sharti usasishe orodha sasa."</string>
     <string name="convert_to_file_encryption" msgid="3060156730651061223">"Badilisha kuwa usimbaji fiche wa faili"</string>
     <string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Badilisha..."</string>
     <string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Tayari faili imesimbwa kwa njia fiche"</string>
@@ -312,6 +311,8 @@
     <string name="battery_info_status_not_charging" msgid="2820070506621483576">"Haichaji"</string>
     <string name="battery_info_status_full" msgid="2824614753861462808">"Imejaa"</string>
     <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Imedhibitiwa na msimamizi"</string>
+    <string name="enabled_by_admin" msgid="2386503803463071894">"Msimamizi amewasha mapendeleo ya mipangilio"</string>
+    <string name="disabled_by_admin" msgid="3669999613095206948">"Msimamizi amezima mapendeleo ya mipangilio"</string>
     <string name="home" msgid="8263346537524314127">"Mwanzo"</string>
     <string name="charge_length_format" msgid="8978516217024434156">"Zimepita <xliff:g id="ID_1">%1$s</xliff:g>"</string>
     <string name="remaining_length_format" msgid="7886337596669190587">"Zimesalia <xliff:g id="ID_1">%1$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-ta-rIN/strings.xml b/packages/SettingsLib/res/values-ta-rIN/strings.xml
index 568c11d..5c7732f 100644
--- a/packages/SettingsLib/res/values-ta-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-ta-rIN/strings.xml
@@ -102,8 +102,7 @@
     <string name="tts_default_rate_title" msgid="6030550998379310088">"பேச்சு வீதம்"</string>
     <string name="tts_default_rate_summary" msgid="4061815292287182801">"பேசப்படும் உரையின் வேகம்"</string>
     <string name="tts_default_pitch_title" msgid="6135942113172488671">"ஒலித்திறன்"</string>
-    <!-- no translation found for tts_default_pitch_summary (1944885882882650009) -->
-    <skip />
+    <string name="tts_default_pitch_summary" msgid="1944885882882650009">"உருவாக்கப்படும் பேச்சின் டோன் பாதிக்கப்படும்"</string>
     <string name="tts_default_lang_title" msgid="8018087612299820556">"மொழி"</string>
     <string name="tts_lang_use_system" msgid="2679252467416513208">"முறைமையின் மொழியைப் பயன்படுத்து"</string>
     <string name="tts_lang_not_selected" msgid="7395787019276734765">"மொழி தேர்ந்தெடுக்கப்படவில்லை"</string>
@@ -279,7 +278,7 @@
     <string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"தனிப்படுத்தப்பட்ட செயல்முறையில் WebView ரெண்டரர்களை இயக்கு."</string>
     <string name="select_webview_provider_title" msgid="4628592979751918907">"WebView செயல்படுத்தல்"</string>
     <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"WebView செயல்படுத்தலை அமை"</string>
-    <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"தேர்வுசெய்த WebView செயல்படுத்தல் முடக்கப்பட்டுள்ளது, பயன்படுத்த வேண்டுமெனில் அதைக் கண்டிப்பாக இயக்க வேண்டும். இயக்க விரும்புகிறீர்களா?"</string>
+    <string name="select_webview_provider_toast_text" msgid="8168796505966635684">"தேர்வுசெய்த WebView செயல்படுத்தல் தவறானது. ஏனெனில் செயல்படுத்தல் விருப்பங்கள் பட்டியல் காலாவதியாகியுள்ளது. பட்டியலை இப்போது புதுப்பிக்க வேண்டும்."</string>
     <string name="convert_to_file_encryption" msgid="3060156730651061223">"கோப்பு முறைமையாக்கத்திற்கு மாற்று"</string>
     <string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"மாற்று…"</string>
     <string name="convert_to_file_encryption_done" msgid="7859766358000523953">"ஏற்கனவே கோப்பு முறைமையாக்கப்பட்டது"</string>
@@ -312,6 +311,8 @@
     <string name="battery_info_status_not_charging" msgid="2820070506621483576">"சார்ஜ் ஏறவில்லை"</string>
     <string name="battery_info_status_full" msgid="2824614753861462808">"முழுமை"</string>
     <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"நிர்வாகி கட்டுப்படுத்துகிறார்"</string>
+    <string name="enabled_by_admin" msgid="2386503803463071894">"நிர்வாகி இயக்கியுள்ளார்"</string>
+    <string name="disabled_by_admin" msgid="3669999613095206948">"நிர்வாகி முடக்கியுள்ளார்"</string>
     <string name="home" msgid="8263346537524314127">"முகப்பு"</string>
     <string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g> முன்"</string>
     <string name="remaining_length_format" msgid="7886337596669190587">"<xliff:g id="ID_1">%1$s</xliff:g> உள்ளது"</string>
diff --git a/packages/SettingsLib/res/values-te-rIN/strings.xml b/packages/SettingsLib/res/values-te-rIN/strings.xml
index e1822bc..a74fc82 100644
--- a/packages/SettingsLib/res/values-te-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-te-rIN/strings.xml
@@ -278,7 +278,7 @@
     <string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"ప్రత్యేకప్రాసెస్‌లో వెబ్ వీక్షణ రెండెరెర్‌లను అమలుచేస్తుంది."</string>
     <string name="select_webview_provider_title" msgid="4628592979751918907">"వెబ్ వీక్షణ అమలు"</string>
     <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"వెబ్ వీక్షణ అమలుని సెట్ చేయండి"</string>
-    <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"ఎంచుకున్న వెబ్ వీక్షణ అమలు నిలిపివేయబడింది, కానీ ఉపయోగించడానికి తప్పనిసరిగా ప్రారంభించాల్సి ఉంటుంది, మీరు దీన్ని ప్రారంభించాలనుకుంటున్నారా?"</string>
+    <string name="select_webview_provider_toast_text" msgid="8168796505966635684">"అమలు ఎంపికల జాబితా కాలం చెల్లినది అయినందున ఎంచుకున్న వెబ్ వీక్షణ అమలు చెల్లదు. జాబితా ఇప్పుడు నవీకరించబడుతుంది."</string>
     <string name="convert_to_file_encryption" msgid="3060156730651061223">"ఫైల్ గుప్తీకరణకు మార్చు"</string>
     <string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"మార్చండి…"</string>
     <string name="convert_to_file_encryption_done" msgid="7859766358000523953">"ఫైల్ ఇప్పటికే గుప్తీకరించబడింది"</string>
@@ -311,6 +311,8 @@
     <string name="battery_info_status_not_charging" msgid="2820070506621483576">"ఛార్జ్ కావడం లేదు"</string>
     <string name="battery_info_status_full" msgid="2824614753861462808">"నిండింది"</string>
     <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"నిర్వాహకుని ద్వారా నియంత్రించబడింది"</string>
+    <string name="enabled_by_admin" msgid="2386503803463071894">"నిర్వాహకులు ప్రారంభించారు"</string>
+    <string name="disabled_by_admin" msgid="3669999613095206948">"నిర్వాహకులు నిలిపివేసారు"</string>
     <string name="home" msgid="8263346537524314127">"హోమ్"</string>
     <string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g> క్రితం"</string>
     <string name="remaining_length_format" msgid="7886337596669190587">"<xliff:g id="ID_1">%1$s</xliff:g> మిగిలి ఉంది"</string>
diff --git a/packages/SettingsLib/res/values-th/strings.xml b/packages/SettingsLib/res/values-th/strings.xml
index 0a123ae..53caea5 100644
--- a/packages/SettingsLib/res/values-th/strings.xml
+++ b/packages/SettingsLib/res/values-th/strings.xml
@@ -102,8 +102,7 @@
     <string name="tts_default_rate_title" msgid="6030550998379310088">"ความเร็วของคำพูด"</string>
     <string name="tts_default_rate_summary" msgid="4061815292287182801">"ความเร็วในการพูดข้อความ"</string>
     <string name="tts_default_pitch_title" msgid="6135942113172488671">"ความสูง-ต่ำของเสียง"</string>
-    <!-- no translation found for tts_default_pitch_summary (1944885882882650009) -->
-    <skip />
+    <string name="tts_default_pitch_summary" msgid="1944885882882650009">"มีผลต่อโทนเสียงของข้อความสังเคราะห์"</string>
     <string name="tts_default_lang_title" msgid="8018087612299820556">"ภาษา"</string>
     <string name="tts_lang_use_system" msgid="2679252467416513208">"ใช้ภาษาของระบบ"</string>
     <string name="tts_lang_not_selected" msgid="7395787019276734765">"ไม่ได้เลือกภาษา"</string>
@@ -279,7 +278,7 @@
     <string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"เรียกใช้โหมดแสดงภาพ WebView ในการดำเนินการที่แยกออกมา"</string>
     <string name="select_webview_provider_title" msgid="4628592979751918907">"การใช้งาน WebView"</string>
     <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"ตั้งค่าการใช้งาน WebView"</string>
-    <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"การใช้งาน WebView ที่เลือกไว้ถูกปิดใช้อยู่ คุณต้องการเปิดใช้เพื่อที่จะใช้งานไหม"</string>
+    <string name="select_webview_provider_toast_text" msgid="8168796505966635684">"การใช้งาน WebView ที่เลือกไม่สามารถใช้ได้เนื่องจากรายการตัวเลือกการนำไปใช้ล้าสมัยแล้ว ควรอัปเดตรายการนี้ได้แล้ว"</string>
     <string name="convert_to_file_encryption" msgid="3060156730651061223">"แปลงเป็นการเข้ารหัสไฟล์"</string>
     <string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"แปลง…"</string>
     <string name="convert_to_file_encryption_done" msgid="7859766358000523953">"เข้ารหัสไฟล์แล้ว"</string>
@@ -312,6 +311,8 @@
     <string name="battery_info_status_not_charging" msgid="2820070506621483576">"ไม่ได้ชาร์จ"</string>
     <string name="battery_info_status_full" msgid="2824614753861462808">"เต็ม"</string>
     <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"ผู้ดูแลระบบเป็นผู้ควบคุม"</string>
+    <string name="enabled_by_admin" msgid="2386503803463071894">"เปิดใช้โดยผู้ดูแลระบบ"</string>
+    <string name="disabled_by_admin" msgid="3669999613095206948">"ปิดใช้โดยผู้ดูแลระบบ"</string>
     <string name="home" msgid="8263346537524314127">"หน้าแรก"</string>
     <string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g>ที่ผ่านมา"</string>
     <string name="remaining_length_format" msgid="7886337596669190587">"เหลือ <xliff:g id="ID_1">%1$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-tl/strings.xml b/packages/SettingsLib/res/values-tl/strings.xml
index 4787bdf..0c1f167 100644
--- a/packages/SettingsLib/res/values-tl/strings.xml
+++ b/packages/SettingsLib/res/values-tl/strings.xml
@@ -102,8 +102,7 @@
     <string name="tts_default_rate_title" msgid="6030550998379310088">"Rate ng pagsasalita"</string>
     <string name="tts_default_rate_summary" msgid="4061815292287182801">"Bilis ng pagsambit sa teksto"</string>
     <string name="tts_default_pitch_title" msgid="6135942113172488671">"Pitch"</string>
-    <!-- no translation found for tts_default_pitch_summary (1944885882882650009) -->
-    <skip />
+    <string name="tts_default_pitch_summary" msgid="1944885882882650009">"Nakakaapekto sa tono ng naka-synthesize na pananalita"</string>
     <string name="tts_default_lang_title" msgid="8018087612299820556">"Wika"</string>
     <string name="tts_lang_use_system" msgid="2679252467416513208">"Gamitin ang wika ng system"</string>
     <string name="tts_lang_not_selected" msgid="7395787019276734765">"Walang napiling wika"</string>
@@ -279,7 +278,7 @@
     <string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"Tagapag-render ng WebView, patakbuhin sa hiwalay na proseso."</string>
     <string name="select_webview_provider_title" msgid="4628592979751918907">"Pagpapatupad sa WebView"</string>
     <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Itakda ang pagpapatupad sa WebView"</string>
-    <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"Naka-disable ang napiling pagpapatupad sa WebView, at dapat itong i-enable upang magamit, gusto mo ba itong i-enable?"</string>
+    <string name="select_webview_provider_toast_text" msgid="8168796505966635684">"Di-wasto ang piniling pag-implement ng WebView dahil luma na ang mga pagpipian ng pag-implement. Dapat na na-update na ngayon ang listahan."</string>
     <string name="convert_to_file_encryption" msgid="3060156730651061223">"I-convert at gawing pag-encrypt ng file"</string>
     <string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"I-convert..."</string>
     <string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Na-encrypt na ang file"</string>
@@ -312,6 +311,8 @@
     <string name="battery_info_status_not_charging" msgid="2820070506621483576">"Hindi nagkakarga"</string>
     <string name="battery_info_status_full" msgid="2824614753861462808">"Puno"</string>
     <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Pinapamahalaan ng admin"</string>
+    <string name="enabled_by_admin" msgid="2386503803463071894">"Na-enable ng administrator"</string>
+    <string name="disabled_by_admin" msgid="3669999613095206948">"Na-disable ng administrator"</string>
     <string name="home" msgid="8263346537524314127">"Home"</string>
     <string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g> na ang nakalipas"</string>
     <string name="remaining_length_format" msgid="7886337596669190587">"<xliff:g id="ID_1">%1$s</xliff:g> na lang"</string>
diff --git a/packages/SettingsLib/res/values-tr/strings.xml b/packages/SettingsLib/res/values-tr/strings.xml
index 933b891..230da22 100644
--- a/packages/SettingsLib/res/values-tr/strings.xml
+++ b/packages/SettingsLib/res/values-tr/strings.xml
@@ -102,8 +102,7 @@
     <string name="tts_default_rate_title" msgid="6030550998379310088">"Konuşma hızı"</string>
     <string name="tts_default_rate_summary" msgid="4061815292287182801">"Metnin konuşulduğu hız"</string>
     <string name="tts_default_pitch_title" msgid="6135942113172488671">"Perde"</string>
-    <!-- no translation found for tts_default_pitch_summary (1944885882882650009) -->
-    <skip />
+    <string name="tts_default_pitch_summary" msgid="1944885882882650009">"Sentezlenmiş konuşma sesini etkiler"</string>
     <string name="tts_default_lang_title" msgid="8018087612299820556">"Dil"</string>
     <string name="tts_lang_use_system" msgid="2679252467416513208">"Sistemin dilini kullan"</string>
     <string name="tts_lang_not_selected" msgid="7395787019276734765">"Dil seçilmedi"</string>
@@ -279,7 +278,7 @@
     <string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"WebView oluşturucuları yalıtılmış bir işlemde çalıştırın."</string>
     <string name="select_webview_provider_title" msgid="4628592979751918907">"WebView kullanımı"</string>
     <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"WebView kullanımını ayarla"</string>
-    <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"Seçilen WebView uygulama şekli devre dışı. Bu uygulama şeklinin kullanılabilmesi için etkinleştirilmesi gerekir. Etkinleştirmek istiyor musunuz?"</string>
+    <string name="select_webview_provider_toast_text" msgid="8168796505966635684">"Seçilen WebView uygulaması, uygulama seçenekleri listesi eskidiği için geçersiz. Listenin şimdi güncellenmesi gerekiyor."</string>
     <string name="convert_to_file_encryption" msgid="3060156730651061223">"Dosya şifrelemeye dönüştür"</string>
     <string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Dönüştür…"</string>
     <string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Dosya şifreleme zaten uygulandı"</string>
@@ -312,6 +311,8 @@
     <string name="battery_info_status_not_charging" msgid="2820070506621483576">"Şarj etmiyor"</string>
     <string name="battery_info_status_full" msgid="2824614753861462808">"Dolu"</string>
     <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Yönetici tarafından denetleniyor"</string>
+    <string name="enabled_by_admin" msgid="2386503803463071894">"Yönetici tarafından etkinleştirildi"</string>
+    <string name="disabled_by_admin" msgid="3669999613095206948">"Yönetici tarafından devre dışı bırakıldı"</string>
     <string name="home" msgid="8263346537524314127">"Ana Ekran"</string>
     <string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g> önce"</string>
     <string name="remaining_length_format" msgid="7886337596669190587">"<xliff:g id="ID_1">%1$s</xliff:g> kaldı"</string>
diff --git a/packages/SettingsLib/res/values-uk/strings.xml b/packages/SettingsLib/res/values-uk/strings.xml
index e8ba6cb..01cedc6 100644
--- a/packages/SettingsLib/res/values-uk/strings.xml
+++ b/packages/SettingsLib/res/values-uk/strings.xml
@@ -102,8 +102,7 @@
     <string name="tts_default_rate_title" msgid="6030550998379310088">"Темп мовлення"</string>
     <string name="tts_default_rate_summary" msgid="4061815292287182801">"Швидкість відтворення тексту"</string>
     <string name="tts_default_pitch_title" msgid="6135942113172488671">"Вис. зв."</string>
-    <!-- no translation found for tts_default_pitch_summary (1944885882882650009) -->
-    <skip />
+    <string name="tts_default_pitch_summary" msgid="1944885882882650009">"Впливає на тон синтезованого мовлення"</string>
     <string name="tts_default_lang_title" msgid="8018087612299820556">"Мова"</string>
     <string name="tts_lang_use_system" msgid="2679252467416513208">"Використовувати мову системи"</string>
     <string name="tts_lang_not_selected" msgid="7395787019276734765">"Мову не вибрано"</string>
@@ -279,7 +278,7 @@
     <string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"Запустити засоби обробки відео WebView окремим процесом."</string>
     <string name="select_webview_provider_title" msgid="4628592979751918907">"Застосування WebView"</string>
     <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Налаштувати застосування WebView"</string>
-    <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"Вибране застосування WebView вимкнено. Увімкнути його?"</string>
+    <string name="select_webview_provider_toast_text" msgid="8168796505966635684">"Недійсне застосування WebView, оскільки список вибору застосувань застарів. Тепер список оновлено."</string>
     <string name="convert_to_file_encryption" msgid="3060156730651061223">"Конвертувати в зашифрований файл"</string>
     <string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Конвертація…"</string>
     <string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Уже конвертовано в зашифрований файл"</string>
@@ -312,6 +311,8 @@
     <string name="battery_info_status_not_charging" msgid="2820070506621483576">"Не заряджається"</string>
     <string name="battery_info_status_full" msgid="2824614753861462808">"Акумулятор заряджено"</string>
     <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Керується адміністратором"</string>
+    <string name="enabled_by_admin" msgid="2386503803463071894">"Увімкнено адміністратором"</string>
+    <string name="disabled_by_admin" msgid="3669999613095206948">"Вимкнено адміністратором"</string>
     <string name="home" msgid="8263346537524314127">"Головний екран"</string>
     <string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g> тому"</string>
     <string name="remaining_length_format" msgid="7886337596669190587">"Залишилося <xliff:g id="ID_1">%1$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-ur-rPK/strings.xml b/packages/SettingsLib/res/values-ur-rPK/strings.xml
index 9d4a269..878ff0c 100644
--- a/packages/SettingsLib/res/values-ur-rPK/strings.xml
+++ b/packages/SettingsLib/res/values-ur-rPK/strings.xml
@@ -102,8 +102,7 @@
     <string name="tts_default_rate_title" msgid="6030550998379310088">"اسپیچ کی شرح"</string>
     <string name="tts_default_rate_summary" msgid="4061815292287182801">"متن بولے جانے کی رفتار"</string>
     <string name="tts_default_pitch_title" msgid="6135942113172488671">"پچ"</string>
-    <!-- no translation found for tts_default_pitch_summary (1944885882882650009) -->
-    <skip />
+    <string name="tts_default_pitch_summary" msgid="1944885882882650009">"تصنعی اسپیچ کی ٹون کو متاثر کرتا ہے"</string>
     <string name="tts_default_lang_title" msgid="8018087612299820556">"زبان"</string>
     <string name="tts_lang_use_system" msgid="2679252467416513208">"سسٹم کی زبان استعمال کریں"</string>
     <string name="tts_lang_not_selected" msgid="7395787019276734765">"زبان منتخب نہیں کی گئی"</string>
@@ -279,7 +278,7 @@
     <string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"‏WebView رینڈررز کو ایک علیحدہ پراسیس میں چلائیں۔"</string>
     <string name="select_webview_provider_title" msgid="4628592979751918907">"‏WebView کا نفاذ"</string>
     <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"‏WebView کا نفاذ سیٹ کریں"</string>
-    <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"‏منتخب کردہ WebView کا نفاذ غیر فعال ہے اور استعمال کرنے کیلئے اسے فعال ہونا چاہئیے، کیا آپ اسے فعال کرنا چاہتے ہیں؟"</string>
+    <string name="select_webview_provider_toast_text" msgid="8168796505966635684">"‏WebView کا منتخب کردہ نفاذ غلط ہے کیونکہ نفاذ کے انتخابات کی فہرست باسی ہو گئی ہے۔ اب فہرست کو اپ ڈیٹ ہونا چاہئیے۔"</string>
     <string name="convert_to_file_encryption" msgid="3060156730651061223">"فائل مرموز کاری میں بدلیں"</string>
     <string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"بدلیں…"</string>
     <string name="convert_to_file_encryption_done" msgid="7859766358000523953">"فائل پہلے ہی مرموز شدہ ہے"</string>
@@ -312,6 +311,8 @@
     <string name="battery_info_status_not_charging" msgid="2820070506621483576">"چارج نہیں ہو رہا ہے"</string>
     <string name="battery_info_status_full" msgid="2824614753861462808">"مکمل"</string>
     <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"کنٹرول کردہ بذریعہ منتظم"</string>
+    <string name="enabled_by_admin" msgid="2386503803463071894">"منتظم نے فعال کر دیا"</string>
+    <string name="disabled_by_admin" msgid="3669999613095206948">"منتظم نے غیر فعال کر دیا"</string>
     <string name="home" msgid="8263346537524314127">"ہوم"</string>
     <string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g> قبل"</string>
     <string name="remaining_length_format" msgid="7886337596669190587">"<xliff:g id="ID_1">%1$s</xliff:g> باقی ہیں"</string>
diff --git a/packages/SettingsLib/res/values-uz-rUZ/strings.xml b/packages/SettingsLib/res/values-uz-rUZ/strings.xml
index 082f6d7..d81a041 100644
--- a/packages/SettingsLib/res/values-uz-rUZ/strings.xml
+++ b/packages/SettingsLib/res/values-uz-rUZ/strings.xml
@@ -102,8 +102,7 @@
     <string name="tts_default_rate_title" msgid="6030550998379310088">"Nutq tezligi"</string>
     <string name="tts_default_rate_summary" msgid="4061815292287182801">"Matnni o‘qish tezligi"</string>
     <string name="tts_default_pitch_title" msgid="6135942113172488671">"Chimdish"</string>
-    <!-- no translation found for tts_default_pitch_summary (1944885882882650009) -->
-    <skip />
+    <string name="tts_default_pitch_summary" msgid="1944885882882650009">"Sintezlangan nutq balandligiga ta’sir qiladi"</string>
     <string name="tts_default_lang_title" msgid="8018087612299820556">"Til"</string>
     <string name="tts_lang_use_system" msgid="2679252467416513208">"Tizim tili"</string>
     <string name="tts_lang_not_selected" msgid="7395787019276734765">"Til tanlanmagan"</string>
@@ -279,7 +278,7 @@
     <string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"WebView renderlovchilarini alohida jarayonda ishga tushirish."</string>
     <string name="select_webview_provider_title" msgid="4628592979751918907">"WebView ta’minotchisi"</string>
     <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"WebView ta’minotchisini sozlash"</string>
-    <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"Tanlangan WebView ta’minotchisi o‘chirilgan va foydalanish uchun yoqilishi zarur. Yoqilsinmi?"</string>
+    <string name="select_webview_provider_toast_text" msgid="8168796505966635684">"Tanlangan WebView xizmati qo‘llab-quvvatlanmaydi. Xizmatlar ro‘yxati eskirgan va hozir ular yangilanadi."</string>
     <string name="convert_to_file_encryption" msgid="3060156730651061223">"Faylli shifrga o‘girish"</string>
     <string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"O‘girish…"</string>
     <string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Fayl allaqachon shifrlangan"</string>
@@ -312,6 +311,8 @@
     <string name="battery_info_status_not_charging" msgid="2820070506621483576">"Quvvatlanmayapti"</string>
     <string name="battery_info_status_full" msgid="2824614753861462808">"To‘la"</string>
     <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Administrator tomonidan boshqariladi"</string>
+    <string name="enabled_by_admin" msgid="2386503803463071894">"Administrator tomonidan yoqilgan"</string>
+    <string name="disabled_by_admin" msgid="3669999613095206948">"Administrator tomonidan o‘chirilgan"</string>
     <string name="home" msgid="8263346537524314127">"Bosh ekran"</string>
     <string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g> oldin"</string>
     <string name="remaining_length_format" msgid="7886337596669190587">"<xliff:g id="ID_1">%1$s</xliff:g> qoldi"</string>
diff --git a/packages/SettingsLib/res/values-vi/strings.xml b/packages/SettingsLib/res/values-vi/strings.xml
index b3000a8..2b4bddd 100644
--- a/packages/SettingsLib/res/values-vi/strings.xml
+++ b/packages/SettingsLib/res/values-vi/strings.xml
@@ -102,8 +102,7 @@
     <string name="tts_default_rate_title" msgid="6030550998379310088">"Tốc độ nói"</string>
     <string name="tts_default_rate_summary" msgid="4061815292287182801">"Tốc độ đọc văn bản"</string>
     <string name="tts_default_pitch_title" msgid="6135942113172488671">"Độ cao"</string>
-    <!-- no translation found for tts_default_pitch_summary (1944885882882650009) -->
-    <skip />
+    <string name="tts_default_pitch_summary" msgid="1944885882882650009">"Ảnh hưởng đến âm điệu giọng nói được tổng hợp"</string>
     <string name="tts_default_lang_title" msgid="8018087612299820556">"Ngôn ngữ"</string>
     <string name="tts_lang_use_system" msgid="2679252467416513208">"Sử dụng ngôn ngữ hệ thống"</string>
     <string name="tts_lang_not_selected" msgid="7395787019276734765">"Không thể chọn ngôn ngữ"</string>
@@ -279,7 +278,7 @@
     <string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"Chạy kết xuất đồ họa WebView trong quy trình tách biệt."</string>
     <string name="select_webview_provider_title" msgid="4628592979751918907">"Triển khai WebView"</string>
     <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Đặt triển khai WebView"</string>
-    <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"Triển khai WebView đã chọn bị vô hiệu hóa và bạn phải bật để sử dụng tính năng này. Bạn có muốn bật tính năng này không?"</string>
+    <string name="select_webview_provider_toast_text" msgid="8168796505966635684">"Triển khai WebView đã chọn không hợp lệ vì danh sách lựa chọn triển khai đã cũ. Phải cập nhật danh sách ngay bây giờ."</string>
     <string name="convert_to_file_encryption" msgid="3060156730651061223">"Chuyển đổi sang mã hóa tệp"</string>
     <string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Chuyển đổi..."</string>
     <string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Đã mã hóa tệp"</string>
@@ -312,6 +311,8 @@
     <string name="battery_info_status_not_charging" msgid="2820070506621483576">"Hiện không sạc"</string>
     <string name="battery_info_status_full" msgid="2824614753861462808">"Đầy"</string>
     <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Do quản trị viên kiểm soát"</string>
+    <string name="enabled_by_admin" msgid="2386503803463071894">"Được bật bởi quản trị viên"</string>
+    <string name="disabled_by_admin" msgid="3669999613095206948">"Bị tắt bởi quản trị viên"</string>
     <string name="home" msgid="8263346537524314127">"Màn hình chính"</string>
     <string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g> trước"</string>
     <string name="remaining_length_format" msgid="7886337596669190587">"Còn <xliff:g id="ID_1">%1$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-zh-rCN/strings.xml b/packages/SettingsLib/res/values-zh-rCN/strings.xml
index 9444224..48f03b7 100644
--- a/packages/SettingsLib/res/values-zh-rCN/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rCN/strings.xml
@@ -102,8 +102,7 @@
     <string name="tts_default_rate_title" msgid="6030550998379310088">"语速"</string>
     <string name="tts_default_rate_summary" msgid="4061815292287182801">"文字转换成语音后的播放速度"</string>
     <string name="tts_default_pitch_title" msgid="6135942113172488671">"音高"</string>
-    <!-- no translation found for tts_default_pitch_summary (1944885882882650009) -->
-    <skip />
+    <string name="tts_default_pitch_summary" msgid="1944885882882650009">"会影响合成语音的音调"</string>
     <string name="tts_default_lang_title" msgid="8018087612299820556">"语言"</string>
     <string name="tts_lang_use_system" msgid="2679252467416513208">"使用系统语言"</string>
     <string name="tts_lang_not_selected" msgid="7395787019276734765">"未选择语言"</string>
@@ -279,7 +278,7 @@
     <string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"在独立进程中运行 WebView 渲染程序。"</string>
     <string name="select_webview_provider_title" msgid="4628592979751918907">"WebView 实现"</string>
     <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"设置 WebView 实现"</string>
-    <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"所选的 WebView 实现已停用,您必须先启用 WebView 实现才能加以使用。要启用该 WebView 实现吗?"</string>
+    <string name="select_webview_provider_toast_text" msgid="8168796505966635684">"所选的 WebView 实现无效,因为实现选项列表已过时。请立即更新列表。"</string>
     <string name="convert_to_file_encryption" msgid="3060156730651061223">"转换为文件加密"</string>
     <string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"转换…"</string>
     <string name="convert_to_file_encryption_done" msgid="7859766358000523953">"文件已加密"</string>
@@ -311,7 +310,9 @@
     <string name="battery_info_status_discharging" msgid="310932812698268588">"未在充电"</string>
     <string name="battery_info_status_not_charging" msgid="2820070506621483576">"未在充电"</string>
     <string name="battery_info_status_full" msgid="2824614753861462808">"电量充足"</string>
-    <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"已由管理员控制"</string>
+    <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"由管理员控制"</string>
+    <string name="enabled_by_admin" msgid="2386503803463071894">"已被管理员启用"</string>
+    <string name="disabled_by_admin" msgid="3669999613095206948">"已被管理员禁用"</string>
     <string name="home" msgid="8263346537524314127">"主屏幕"</string>
     <string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g>前"</string>
     <string name="remaining_length_format" msgid="7886337596669190587">"还剩 <xliff:g id="ID_1">%1$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-zh-rHK/strings.xml b/packages/SettingsLib/res/values-zh-rHK/strings.xml
index c474c0c..38656e5 100644
--- a/packages/SettingsLib/res/values-zh-rHK/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rHK/strings.xml
@@ -102,8 +102,7 @@
     <string name="tts_default_rate_title" msgid="6030550998379310088">"語音速率"</string>
     <string name="tts_default_rate_summary" msgid="4061815292287182801">"文字轉語音的播放速度"</string>
     <string name="tts_default_pitch_title" msgid="6135942113172488671">"音調"</string>
-    <!-- no translation found for tts_default_pitch_summary (1944885882882650009) -->
-    <skip />
+    <string name="tts_default_pitch_summary" msgid="1944885882882650009">"影響合成語音的音調"</string>
     <string name="tts_default_lang_title" msgid="8018087612299820556">"語言"</string>
     <string name="tts_lang_use_system" msgid="2679252467416513208">"使用系統語言"</string>
     <string name="tts_lang_not_selected" msgid="7395787019276734765">"未選取語言"</string>
@@ -279,7 +278,7 @@
     <string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"在獨立的處理程序中執行 WebView 轉譯器。"</string>
     <string name="select_webview_provider_title" msgid="4628592979751918907">"WebView 設置"</string>
     <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"設定 WebView 設置"</string>
-    <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"您選擇的 WebView 設定已停用,您必須先啟用此設定才能加以使用。要啟用此設定嗎?"</string>
+    <string name="select_webview_provider_toast_text" msgid="8168796505966635684">"WebView 的設定選項清單已過時,因此您所選的 WebView 設定無效。請立即更新這份清單。"</string>
     <string name="convert_to_file_encryption" msgid="3060156730651061223">"轉換為檔案加密"</string>
     <string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"轉換…"</string>
     <string name="convert_to_file_encryption_done" msgid="7859766358000523953">"已加密檔案"</string>
@@ -312,6 +311,8 @@
     <string name="battery_info_status_not_charging" msgid="2820070506621483576">"未開始充電"</string>
     <string name="battery_info_status_full" msgid="2824614753861462808">"電量已滿"</string>
     <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"已由管理員停用"</string>
+    <string name="enabled_by_admin" msgid="2386503803463071894">"已由管理員啟用"</string>
+    <string name="disabled_by_admin" msgid="3669999613095206948">"已由管理員停用"</string>
     <string name="home" msgid="8263346537524314127">"主畫面"</string>
     <string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g>前"</string>
     <string name="remaining_length_format" msgid="7886337596669190587">"尚餘 <xliff:g id="ID_1">%1$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-zh-rTW/strings.xml b/packages/SettingsLib/res/values-zh-rTW/strings.xml
index df2a54c..af83365 100644
--- a/packages/SettingsLib/res/values-zh-rTW/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rTW/strings.xml
@@ -102,8 +102,7 @@
     <string name="tts_default_rate_title" msgid="6030550998379310088">"語音速率"</string>
     <string name="tts_default_rate_summary" msgid="4061815292287182801">"文字轉語音的播放速度"</string>
     <string name="tts_default_pitch_title" msgid="6135942113172488671">"音調"</string>
-    <!-- no translation found for tts_default_pitch_summary (1944885882882650009) -->
-    <skip />
+    <string name="tts_default_pitch_summary" msgid="1944885882882650009">"會影響合成語音的音調"</string>
     <string name="tts_default_lang_title" msgid="8018087612299820556">"語言"</string>
     <string name="tts_lang_use_system" msgid="2679252467416513208">"使用系統設定"</string>
     <string name="tts_lang_not_selected" msgid="7395787019276734765">"未選取語言"</string>
@@ -279,7 +278,7 @@
     <string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"在獨立的處理程序中執行 WebView 轉譯器。"</string>
     <string name="select_webview_provider_title" msgid="4628592979751918907">"WebView 實作"</string>
     <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"設定 WebView 實作"</string>
-    <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"您所選的 WebView 實作已停用,您必須先啟用 WebView 實作才能加以使用。要啟用該 WebView 實作嗎?"</string>
+    <string name="select_webview_provider_toast_text" msgid="8168796505966635684">"您所選的 WebView 實作無效,這是因為相關的實作選項清單已過時。請立即更新這份清單。"</string>
     <string name="convert_to_file_encryption" msgid="3060156730651061223">"轉換成檔案加密"</string>
     <string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"轉換..."</string>
     <string name="convert_to_file_encryption_done" msgid="7859766358000523953">"已將檔案加密"</string>
@@ -312,6 +311,8 @@
     <string name="battery_info_status_not_charging" msgid="2820070506621483576">"非充電中"</string>
     <string name="battery_info_status_full" msgid="2824614753861462808">"電力充足"</string>
     <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"已由管理員停用"</string>
+    <string name="enabled_by_admin" msgid="2386503803463071894">"已由管理員啟用"</string>
+    <string name="disabled_by_admin" msgid="3669999613095206948">"已由管理員停用"</string>
     <string name="home" msgid="8263346537524314127">"主畫面"</string>
     <string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g>前"</string>
     <string name="remaining_length_format" msgid="7886337596669190587">"還剩 <xliff:g id="ID_1">%1$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-zu/strings.xml b/packages/SettingsLib/res/values-zu/strings.xml
index f234dc6..16841d3 100644
--- a/packages/SettingsLib/res/values-zu/strings.xml
+++ b/packages/SettingsLib/res/values-zu/strings.xml
@@ -102,8 +102,7 @@
     <string name="tts_default_rate_title" msgid="6030550998379310088">"Ukukala izwi"</string>
     <string name="tts_default_rate_summary" msgid="4061815292287182801">"Isivinini leso umbhalo okhulunywe ngaso"</string>
     <string name="tts_default_pitch_title" msgid="6135942113172488671">"Ukuphakama"</string>
-    <!-- no translation found for tts_default_pitch_summary (1944885882882650009) -->
-    <skip />
+    <string name="tts_default_pitch_summary" msgid="1944885882882650009">"Ithinta amathoni enkulumo akhiqiziwe"</string>
     <string name="tts_default_lang_title" msgid="8018087612299820556">"Ulimi"</string>
     <string name="tts_lang_use_system" msgid="2679252467416513208">"Sebenzisa ulimi lwesistimu"</string>
     <string name="tts_lang_not_selected" msgid="7395787019276734765">"Ulimi alukhethwanga"</string>
@@ -279,7 +278,7 @@
     <string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"Sebenzisa abasebenzeli be-WebView kwinqubo ekhethiwe."</string>
     <string name="select_webview_provider_title" msgid="4628592979751918907">"Ukufakwa ke-WebView"</string>
     <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Sesba ukufakwa kwe-WebView"</string>
-    <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"Ukusetshenziswa kwe-WebView okukhethiwe kukhutshaziwe, futhi kuzomele kunikwe amandla ukuze kusetshenziswe, ingabe ufisa ukukunika amandla?"</string>
+    <string name="select_webview_provider_toast_text" msgid="8168796505966635684">"Ukusetshenziswa okukhethiwe kwe-WebView akuvumelekile ngoba uhlu lokukhetha ukusetshenziswa lukhule lwaba ludala. Uhlu kumele manje libuyekezwe."</string>
     <string name="convert_to_file_encryption" msgid="3060156730651061223">"Phendulisela ekubethelweni kwefayela"</string>
     <string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Iyaphendulela..."</string>
     <string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Sekuvele kubethelwe ngefayela"</string>
@@ -312,6 +311,8 @@
     <string name="battery_info_status_not_charging" msgid="2820070506621483576">"Ayishaji"</string>
     <string name="battery_info_status_full" msgid="2824614753861462808">"Kugcwele"</string>
     <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Kulawulwa umqondisi"</string>
+    <string name="enabled_by_admin" msgid="2386503803463071894">"Kunikwe amandla umqondisi"</string>
+    <string name="disabled_by_admin" msgid="3669999613095206948">"Ikhutshazwe umlawuli"</string>
     <string name="home" msgid="8263346537524314127">"Ekhaya"</string>
     <string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g> edlule"</string>
     <string name="remaining_length_format" msgid="7886337596669190587">"<xliff:g id="ID_1">%1$s</xliff:g> osele"</string>
diff --git a/packages/SettingsLib/res/values/dimens.xml b/packages/SettingsLib/res/values/dimens.xml
index 9f78e87..c3b3cfc 100644
--- a/packages/SettingsLib/res/values/dimens.xml
+++ b/packages/SettingsLib/res/values/dimens.xml
@@ -33,8 +33,8 @@
     <dimen name="user_spinner_item_height">56dp</dimen>
 
     <!-- Lock icon for preferences locked by admin -->
-    <dimen name="restricted_lock_icon_size">16dp</dimen>
-    <dimen name="restricted_lock_icon_padding">4dp</dimen>
+    <dimen name="restricted_icon_size">16dp</dimen>
+    <dimen name="restricted_icon_padding">4dp</dimen>
 
     <dimen name="wifi_preference_badge_padding">8dip</dimen>
 
diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml
index 72fa939..1b49eed 100644
--- a/packages/SettingsLib/res/values/strings.xml
+++ b/packages/SettingsLib/res/values/strings.xml
@@ -677,7 +677,7 @@
     <!-- Services settings screen, setting option summary for the user to go to the screen to view running services  -->
     <string name="runningservices_settings_summary">View and control currently running services</string>
 
-    <!-- Developer settings: enable WebView multiprocess name [CHAR LIMIT=30] -->
+    <!-- Developer settings: enable WebView multiprocess name [CHAR LIMIT=50] -->
     <string name="enable_webview_multiprocess">Enable multiprocess WebView</string>
     <!-- Developer settings: enable WebView multiprocess summary [CHAR LIMIT=60] -->
     <string name="enable_webview_multiprocess_desc">Run WebView renderers in an isolated process.</string>
@@ -773,6 +773,11 @@
     <!-- Summary for settings preference disabled by administrator [CHAR LIMIT=50] -->
     <string name="disabled_by_admin_summary_text">Controlled by admin</string>
 
+    <!-- Summary for switch preference to denote it is switched on [CHAR LIMIT=50] -->
+    <string name="enabled_by_admin">Enabled by administrator</string>
+    <!-- Summary for switch preference to denote it is switched off [CHAR LIMIT=50] -->
+    <string name="disabled_by_admin">Disabled by administrator</string>
+
     <!-- Option in navigation drawer that leads to Settings main screen [CHAR LIMIT=30] -->
     <string name="home">Home</string>
 
diff --git a/packages/SettingsLib/src/com/android/settingslib/RestrictedDropDownPreference.java b/packages/SettingsLib/src/com/android/settingslib/RestrictedDropDownPreference.java
deleted file mode 100644
index c2f885d..0000000
--- a/packages/SettingsLib/src/com/android/settingslib/RestrictedDropDownPreference.java
+++ /dev/null
@@ -1,153 +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.settingslib;
-
-import android.content.Context;
-import android.graphics.drawable.Drawable;
-import android.support.v7.preference.DropDownPreference;
-import android.support.v7.preference.PreferenceViewHolder;
-import android.util.AttributeSet;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.AdapterView;
-import android.widget.AdapterView.OnItemSelectedListener;
-import android.widget.ArrayAdapter;
-import android.widget.Spinner;
-import android.widget.TextView;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
-
-public class RestrictedDropDownPreference extends DropDownPreference {
-    private Spinner mSpinner;
-    private final Drawable mRestrictedPadlock;
-    private final int mRestrictedPadlockPadding;
-    private List<RestrictedItem> mRestrictedItems = new ArrayList<>();
-
-    public RestrictedDropDownPreference(Context context) {
-        this(context, null);
-    }
-
-    public RestrictedDropDownPreference(Context context, AttributeSet attrs) {
-        super(context, attrs);
-
-        mRestrictedPadlock = RestrictedLockUtils.getRestrictedPadlock(context);
-        mRestrictedPadlockPadding = context.getResources().getDimensionPixelSize(
-                R.dimen.restricted_lock_icon_padding);
-    }
-
-    private final OnItemSelectedListener mItemSelectedListener = new OnItemSelectedListener() {
-        @Override
-        public void onItemSelected(AdapterView<?> parent, View v, int position, long id) {
-            if (position >= 0) {
-                String value = getEntryValues()[position].toString();
-                RestrictedItem item = getRestrictedItemForEntryValue(value);
-                if (item != null) {
-                    RestrictedLockUtils.sendShowAdminSupportDetailsIntent(getContext(),
-                            item.enforcedAdmin);
-                    mSpinner.setSelection(findIndexOfValue(getValue()));
-                } else if (!value.equals(getValue()) && callChangeListener(value)) {
-                    setValue(value);
-                }
-            }
-        }
-
-        @Override
-        public void onNothingSelected(AdapterView<?> parent) {
-            // noop
-        }
-    };
-
-    @Override
-    protected ArrayAdapter createAdapter() {
-        return new RestrictedArrayItemAdapter(getContext());
-    }
-
-    @Override
-    public void setValue(String value) {
-        if (getRestrictedItemForEntryValue(value) != null) {
-            return;
-        }
-        super.setValue(value);
-    }
-
-    @Override
-    public void onBindViewHolder(PreferenceViewHolder view) {
-        super.onBindViewHolder(view);
-        mSpinner = (Spinner) view.itemView.findViewById(R.id.spinner);
-        mSpinner.setOnItemSelectedListener(mItemSelectedListener);
-    }
-
-    private class RestrictedArrayItemAdapter extends ArrayAdapter<String> {
-        public RestrictedArrayItemAdapter(Context context) {
-            super(context, R.layout.spinner_dropdown_restricted_item);
-        }
-
-        @Override
-        public View getDropDownView(int position, View convertView, ViewGroup parent) {
-            TextView view = (TextView) super.getView(position, convertView, parent);
-            CharSequence entry = getItem(position);
-            boolean isEntryRestricted = isRestrictedForEntry(entry);
-            RestrictedLockUtils.setTextViewPadlock(getContext(), view, isEntryRestricted);
-            view.setEnabled(!isEntryRestricted);
-            return view;
-        }
-    }
-
-    private boolean isRestrictedForEntry(CharSequence entry) {
-        if (entry == null) {
-            return false;
-        }
-        for (RestrictedItem item : mRestrictedItems) {
-            if (entry.equals(item.entry)) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    private RestrictedItem getRestrictedItemForEntryValue(CharSequence entryValue) {
-        if (entryValue == null) {
-            return null;
-        }
-        for (RestrictedItem item : mRestrictedItems) {
-            if (entryValue.equals(item.entryValue)) {
-                return item;
-            }
-        }
-        return null;
-    }
-
-    public void addRestrictedItem(RestrictedItem item) {
-        mRestrictedItems.add(item);
-    }
-
-    public static class RestrictedItem {
-        public CharSequence entry;
-        public CharSequence entryValue;
-        public EnforcedAdmin enforcedAdmin;
-
-        public RestrictedItem(CharSequence entry, CharSequence entryValue,
-                EnforcedAdmin enforcedAdmin) {
-            this.entry = entry;
-            this.entryValue = entryValue;
-            this.enforcedAdmin = enforcedAdmin;
-        }
-    }
-}
\ No newline at end of file
diff --git a/packages/SettingsLib/src/com/android/settingslib/RestrictedLockImageSpan.java b/packages/SettingsLib/src/com/android/settingslib/RestrictedLockImageSpan.java
index e63130d..360a34c 100644
--- a/packages/SettingsLib/src/com/android/settingslib/RestrictedLockImageSpan.java
+++ b/packages/SettingsLib/src/com/android/settingslib/RestrictedLockImageSpan.java
@@ -36,7 +36,7 @@
 
         mContext = context;
         mExtraPadding = mContext.getResources().getDimensionPixelSize(
-                R.dimen.restricted_lock_icon_padding);
+                R.dimen.restricted_icon_padding);
         mRestrictedPadlock = RestrictedLockUtils.getRestrictedPadlock(mContext);
     }
 
@@ -53,7 +53,7 @@
 
         // Add extra padding before the padlock.
         float transX = x + mExtraPadding;
-        float transY = bottom - drawable.getBounds().bottom - paint.getFontMetricsInt().descent;
+        float transY = (bottom - drawable.getBounds().bottom) / 2.0f;
 
         canvas.translate(transX, transY);
         drawable.draw(canvas);
diff --git a/packages/SettingsLib/src/com/android/settingslib/RestrictedLockUtils.java b/packages/SettingsLib/src/com/android/settingslib/RestrictedLockUtils.java
index 6d29c5f..1f1a9b8 100644
--- a/packages/SettingsLib/src/com/android/settingslib/RestrictedLockUtils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/RestrictedLockUtils.java
@@ -49,9 +49,9 @@
      * @return drawables for displaying with settings that are locked by a device admin.
      */
     public static Drawable getRestrictedPadlock(Context context) {
-        Drawable restrictedPadlock = context.getDrawable(R.drawable.ic_settings_lock_outline);
+        Drawable restrictedPadlock = context.getDrawable(R.drawable.ic_info);
         final int iconSize = context.getResources().getDimensionPixelSize(
-                R.dimen.restricted_lock_icon_size);
+                R.dimen.restricted_icon_size);
         restrictedPadlock.setBounds(0, 0, iconSize, iconSize);
         return restrictedPadlock;
     }
@@ -651,8 +651,11 @@
             final int disabledColor = context.getColor(R.color.disabled_text_color);
             sb.setSpan(new ForegroundColorSpan(disabledColor), 0, sb.length(),
                     Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
-            final ImageSpan image = new RestrictedLockImageSpan(context);
-            sb.append(" ", image, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+            textView.setCompoundDrawables(null, null, getRestrictedPadlock(context), null);
+            textView.setCompoundDrawablePadding(context.getResources().getDimensionPixelSize(
+                    R.dimen.restricted_icon_padding));
+        } else {
+            textView.setCompoundDrawables(null, null, null, null);
         }
         textView.setText(sb);
     }
diff --git a/packages/SettingsLib/src/com/android/settingslib/RestrictedPreference.java b/packages/SettingsLib/src/com/android/settingslib/RestrictedPreference.java
index 810f6eb..e69497a 100644
--- a/packages/SettingsLib/src/com/android/settingslib/RestrictedPreference.java
+++ b/packages/SettingsLib/src/com/android/settingslib/RestrictedPreference.java
@@ -23,6 +23,7 @@
 import android.support.v7.preference.PreferenceManager;
 import android.support.v7.preference.PreferenceViewHolder;
 import android.util.AttributeSet;
+import android.view.View;
 
 import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
 
@@ -36,6 +37,7 @@
     public RestrictedPreference(Context context, AttributeSet attrs,
             int defStyleAttr, int defStyleRes) {
         super(context, attrs, defStyleAttr, defStyleRes);
+        setWidgetLayoutResource(R.layout.restricted_icon);
         mHelper = new RestrictedPreferenceHelper(context, this, attrs);
     }
 
@@ -56,6 +58,10 @@
     public void onBindViewHolder(PreferenceViewHolder holder) {
         super.onBindViewHolder(holder);
         mHelper.onBindViewHolder(holder);
+        final View restrictedIcon = holder.findViewById(R.id.restricted_icon);
+        if (restrictedIcon != null) {
+            restrictedIcon.setVisibility(isDisabledByAdmin() ? View.VISIBLE : View.GONE);
+        }
     }
 
     @Override
diff --git a/packages/SettingsLib/src/com/android/settingslib/RestrictedPreferenceHelper.java b/packages/SettingsLib/src/com/android/settingslib/RestrictedPreferenceHelper.java
index 227b1e8..47023c1 100644
--- a/packages/SettingsLib/src/com/android/settingslib/RestrictedPreferenceHelper.java
+++ b/packages/SettingsLib/src/com/android/settingslib/RestrictedPreferenceHelper.java
@@ -22,9 +22,6 @@
 import android.os.UserHandle;
 import android.support.v7.preference.Preference;
 import android.support.v7.preference.PreferenceViewHolder;
-import android.text.Spanned;
-import android.text.SpannableStringBuilder;
-import android.text.style.ImageSpan;
 import android.util.AttributeSet;
 import android.util.TypedValue;
 import android.view.View;
@@ -39,8 +36,6 @@
 public class RestrictedPreferenceHelper {
     private final Context mContext;
     private final Preference mPreference;
-    private final Drawable mRestrictedPadlock;
-    private final int mRestrictedPadlockPadding;
 
     private boolean mDisabledByAdmin;
     private EnforcedAdmin mEnforcedAdmin;
@@ -52,10 +47,6 @@
         mContext = context;
         mPreference = preference;
 
-        mRestrictedPadlock = RestrictedLockUtils.getRestrictedPadlock(mContext);
-        mRestrictedPadlockPadding = mContext.getResources().getDimensionPixelSize(
-                R.dimen.restricted_lock_icon_padding);
-
         if (attrs != null) {
             final TypedArray attributes = context.obtainStyledAttributes(attrs,
                     R.styleable.RestrictedPreference);
@@ -91,12 +82,8 @@
      * Modify PreferenceViewHolder to add padlock if restriction is disabled.
      */
     public void onBindViewHolder(PreferenceViewHolder holder) {
-        final TextView titleView = (TextView) holder.findViewById(android.R.id.title);
-        if (titleView != null) {
-            RestrictedLockUtils.setTextViewPadlock(mContext, titleView, mDisabledByAdmin);
-            if (mDisabledByAdmin) {
-                holder.itemView.setEnabled(true);
-            }
+        if (mDisabledByAdmin) {
+            holder.itemView.setEnabled(true);
         }
         if (mUseAdminDisabledSummary) {
             final TextView summaryView = (TextView) holder.findViewById(android.R.id.summary);
@@ -158,10 +145,10 @@
      */
     public boolean setDisabledByAdmin(EnforcedAdmin admin) {
         final boolean disabled = (admin != null ? true : false);
-        mEnforcedAdmin = (disabled ? admin : null);
+        mEnforcedAdmin = admin;
+        mPreference.setEnabled(!disabled);
         if (mDisabledByAdmin != disabled) {
             mDisabledByAdmin = disabled;
-            mPreference.setEnabled(!disabled);
             return true;
         }
         return false;
diff --git a/packages/SettingsLib/src/com/android/settingslib/RestrictedSwitchPreference.java b/packages/SettingsLib/src/com/android/settingslib/RestrictedSwitchPreference.java
index 6cae8aa..f381286 100644
--- a/packages/SettingsLib/src/com/android/settingslib/RestrictedSwitchPreference.java
+++ b/packages/SettingsLib/src/com/android/settingslib/RestrictedSwitchPreference.java
@@ -23,6 +23,8 @@
 import android.support.v7.preference.PreferenceViewHolder;
 import android.support.v14.preference.SwitchPreference;
 import android.util.AttributeSet;
+import android.view.View;
+import android.widget.TextView;
 
 import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
 
@@ -36,6 +38,7 @@
     public RestrictedSwitchPreference(Context context, AttributeSet attrs,
             int defStyleAttr, int defStyleRes) {
         super(context, attrs, defStyleAttr, defStyleRes);
+        setWidgetLayoutResource(R.layout.restricted_switch_widget);
         mHelper = new RestrictedPreferenceHelper(context, this, attrs);
     }
 
@@ -56,6 +59,20 @@
     public void onBindViewHolder(PreferenceViewHolder holder) {
         super.onBindViewHolder(holder);
         mHelper.onBindViewHolder(holder);
+        final View restrictedIcon = holder.findViewById(R.id.restricted_icon);
+        final View switchWidget = holder.findViewById(android.R.id.switch_widget);
+        if (restrictedIcon != null) {
+            restrictedIcon.setVisibility(isDisabledByAdmin() ? View.VISIBLE : View.GONE);
+        }
+        if (switchWidget != null) {
+            switchWidget.setVisibility(isDisabledByAdmin() ? View.GONE : View.VISIBLE);
+        }
+        final TextView summaryView = (TextView) holder.findViewById(android.R.id.summary);
+        if (summaryView != null && isDisabledByAdmin()) {
+            summaryView.setText(
+                    isChecked() ? R.string.enabled_by_admin : R.string.disabled_by_admin);
+            summaryView.setVisibility(View.VISIBLE);
+        }
     }
 
     @Override
diff --git a/packages/SettingsLib/src/com/android/settingslib/SuggestionParser.java b/packages/SettingsLib/src/com/android/settingslib/SuggestionParser.java
index 1859207..741b0ea 100644
--- a/packages/SettingsLib/src/com/android/settingslib/SuggestionParser.java
+++ b/packages/SettingsLib/src/com/android/settingslib/SuggestionParser.java
@@ -25,6 +25,12 @@
 import android.util.Log;
 import android.util.Pair;
 import android.util.Xml;
+import android.provider.Settings;
+import android.accounts.Account;
+import android.accounts.AccountManager;
+import android.content.ContentValues;
+import android.content.pm.PackageManager;
+import android.content.res.Resources;
 import android.view.InflateException;
 import com.android.settingslib.drawer.Tile;
 import com.android.settingslib.drawer.TileUtils;
@@ -42,6 +48,12 @@
     // If defined, only returns this suggestion if the feature is supported.
     public static final String META_DATA_REQUIRE_FEATURE = "com.android.settings.require_feature";
 
+    // If defined, only display this optional step if an account of that type exists.
+    private static final String META_DATA_REQUIRE_ACCOUNT = "com.android.settings.require_account";
+
+    // If defined and not true, do not should optional step.
+    private static final String META_DATA_IS_SUPPORTED = "com.android.settings.is_supported";
+
     /**
      * Allows suggestions to appear after a certain number of days, and to re-appear if dismissed.
      * For instance:
@@ -110,7 +122,10 @@
         TileUtils.getTilesForIntent(mContext, new UserHandle(UserHandle.myUserId()), intent,
                 addCache, null, suggestions, true, false);
         for (int i = countBefore; i < suggestions.size(); i++) {
-            if (!isAvailable(suggestions.get(i)) || isDismissed(suggestions.get(i))) {
+            if (!isAvailable(suggestions.get(i)) ||
+                    !isSupported(suggestions.get(i)) ||
+                    !satisfiesRequiredAccount(suggestions.get(i)) ||
+                    isDismissed(suggestions.get(i))) {
                 suggestions.remove(i--);
             }
         }
@@ -124,7 +139,10 @@
                     item = last;
                 }
             }
-            suggestions.add(item);
+            // If category is marked as done, do not add any item.
+            if (!isCategoryDone(category.category)) {
+                suggestions.add(item);
+            }
         }
     }
 
@@ -136,6 +154,41 @@
         return true;
     }
 
+    public boolean satisfiesRequiredAccount(Tile suggestion) {
+        String requiredAccountType = suggestion.metaData.getString(META_DATA_REQUIRE_ACCOUNT);
+        if (requiredAccountType == null) {
+            return true;
+        }
+        AccountManager accountManager = AccountManager.get(mContext);
+        Account[] accounts = accountManager.getAccountsByType(requiredAccountType);
+        return accounts.length > 0;
+    }
+
+    public boolean isSupported(Tile suggestion) {
+        int isSupportedResource = suggestion.metaData.getInt(META_DATA_IS_SUPPORTED);
+        try {
+            if (suggestion.intent == null) {
+                return false;
+            }
+            final Resources res = mContext.getPackageManager().getResourcesForActivity(
+                    suggestion.intent.getComponent());
+            return isSupportedResource != 0 ? res.getBoolean(isSupportedResource) : true;
+        } catch (PackageManager.NameNotFoundException e) {
+            Log.w(TAG, "Cannot find resources for " + suggestion.intent.getComponent());
+            return false;
+        }
+    }
+
+    public boolean isCategoryDone(String category) {
+        String name = Settings.Secure.COMPLETED_CATEGORY_PREFIX + category;
+        return Settings.Secure.getInt(mContext.getContentResolver(), name, 0) != 0;
+    }
+
+    public void markCategoryDone(String category) {
+        String name = Settings.Secure.COMPLETED_CATEGORY_PREFIX + category;
+        Settings.Secure.putInt(mContext.getContentResolver(), name, 1);
+    }
+
     private boolean isDismissed(Tile suggestion) {
         Object dismissObj = suggestion.metaData.get(META_DATA_DISMISS_CONTROL);
         if (dismissObj == null) {
diff --git a/packages/SettingsLib/src/com/android/settingslib/accessibility/AccessibilityUtils.java b/packages/SettingsLib/src/com/android/settingslib/accessibility/AccessibilityUtils.java
index 99bd4ad..fcff305 100644
--- a/packages/SettingsLib/src/com/android/settingslib/accessibility/AccessibilityUtils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/accessibility/AccessibilityUtils.java
@@ -22,6 +22,7 @@
 import android.content.pm.ResolveInfo;
 import android.content.res.Configuration;
 import android.content.res.Resources;
+import android.os.UserHandle;
 import android.provider.Settings;
 import android.text.TextUtils;
 import android.util.ArraySet;
@@ -40,12 +41,21 @@
             new TextUtils.SimpleStringSplitter(ENABLED_ACCESSIBILITY_SERVICES_SEPARATOR);
 
     /**
-     * @return the set of enabled accessibility services. If there are not services
-     * it returned the unmodifiable {@link Collections#emptySet()}.
+     * @return the set of enabled accessibility services. If there are no services,
+     * it returns the unmodifiable {@link Collections#emptySet()}.
      */
     public static Set<ComponentName> getEnabledServicesFromSettings(Context context) {
-        final String enabledServicesSetting = Settings.Secure.getString(
-                context.getContentResolver(), Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES);
+        return getEnabledServicesFromSettings(context, UserHandle.myUserId());
+    }
+
+    /**
+     * @return the set of enabled accessibility services for {@param userId}. If there are no
+     * services, it returns the unmodifiable {@link Collections#emptySet()}.
+     */
+    public static Set<ComponentName> getEnabledServicesFromSettings(Context context, int userId) {
+        final String enabledServicesSetting = Settings.Secure.getStringForUser(
+                context.getContentResolver(), Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES,
+                userId);
         if (enabledServicesSetting == null) {
             return Collections.emptySet();
         }
@@ -77,11 +87,22 @@
         return langContext.getText(resId);
     }
 
+    /**
+     * Changes an accessibility component's state.
+     */
     public static void setAccessibilityServiceState(Context context, ComponentName toggledService,
             boolean enabled) {
+        setAccessibilityServiceState(context, toggledService, enabled, UserHandle.myUserId());
+    }
+
+    /**
+     * Changes an accessibility component's state for {@param userId}.
+     */
+    public static void setAccessibilityServiceState(Context context, ComponentName toggledService,
+            boolean enabled, int userId) {
         // Parse the enabled services.
         Set<ComponentName> enabledServices = AccessibilityUtils.getEnabledServicesFromSettings(
-                context);
+                context, userId);
 
         if (enabledServices.isEmpty()) {
             enabledServices = new ArraySet<>(1);
@@ -121,13 +142,9 @@
         if (enabledServicesBuilderLength > 0) {
             enabledServicesBuilder.deleteCharAt(enabledServicesBuilderLength - 1);
         }
-        Settings.Secure.putString(context.getContentResolver(),
+        Settings.Secure.putStringForUser(context.getContentResolver(),
                 Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES,
-                enabledServicesBuilder.toString());
-
-        // Update accessibility enabled.
-        Settings.Secure.putInt(context.getContentResolver(),
-                Settings.Secure.ACCESSIBILITY_ENABLED, accessibilityEnabled ? 1 : 0);
+                enabledServicesBuilder.toString(), userId);
     }
 
     private static Set<ComponentName> getInstalledServices(Context context) {
diff --git a/packages/SettingsLib/src/com/android/settingslib/drawer/SettingsDrawerActivity.java b/packages/SettingsLib/src/com/android/settingslib/drawer/SettingsDrawerActivity.java
index a578055..7a1c741 100644
--- a/packages/SettingsLib/src/com/android/settingslib/drawer/SettingsDrawerActivity.java
+++ b/packages/SettingsLib/src/com/android/settingslib/drawer/SettingsDrawerActivity.java
@@ -69,16 +69,18 @@
 
         long startTime = System.currentTimeMillis();
 
-        getWindow().addFlags(LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
-        getWindow().addFlags(LayoutParams.FLAG_TRANSLUCENT_STATUS);
-        requestWindowFeature(Window.FEATURE_NO_TITLE);
+        TypedArray theme = getTheme().obtainStyledAttributes(android.R.styleable.Theme);
+        if (!theme.getBoolean(android.R.styleable.Theme_windowNoTitle, false)) {
+            getWindow().addFlags(LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
+            getWindow().addFlags(LayoutParams.FLAG_TRANSLUCENT_STATUS);
+            requestWindowFeature(Window.FEATURE_NO_TITLE);
+        }
         super.setContentView(R.layout.settings_with_drawer);
         mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
         if (mDrawerLayout == null) {
             return;
         }
         Toolbar toolbar = (Toolbar) findViewById(R.id.action_bar);
-        TypedArray theme = getTheme().obtainStyledAttributes(android.R.styleable.Theme);
         if (theme.getBoolean(android.R.styleable.Theme_windowNoTitle, false)) {
             toolbar.setVisibility(View.GONE);
             mDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED);
diff --git a/packages/SettingsLib/src/com/android/settingslib/drawer/TileUtils.java b/packages/SettingsLib/src/com/android/settingslib/drawer/TileUtils.java
index 2dfdfda..418b138 100644
--- a/packages/SettingsLib/src/com/android/settingslib/drawer/TileUtils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/drawer/TileUtils.java
@@ -41,7 +41,7 @@
 public class TileUtils {
 
     private static final boolean DEBUG = false;
-    private static final boolean DEBUG_TIMING = true;
+    private static final boolean DEBUG_TIMING = false;
 
     private static final String LOG_TAG = "TileUtils";
 
diff --git a/packages/SettingsLib/src/com/android/settingslib/graph/UsageGraph.java b/packages/SettingsLib/src/com/android/settingslib/graph/UsageGraph.java
index 530ec16..1fff0fb 100644
--- a/packages/SettingsLib/src/com/android/settingslib/graph/UsageGraph.java
+++ b/packages/SettingsLib/src/com/android/settingslib/graph/UsageGraph.java
@@ -43,6 +43,7 @@
     private final Paint mDottedPaint;
 
     private final Drawable mDivider;
+    private final Drawable mTintedDivider;
     private final int mDividerSize;
 
     private final Path mPath = new Path();
@@ -51,6 +52,7 @@
     private final SparseIntArray mPaths = new SparseIntArray();
     // Paths in local coordinates for drawing.
     private final SparseIntArray mLocalPaths = new SparseIntArray();
+    private final int mCornerRadius;
 
     private int mAccentColor;
     private boolean mShowProjection;
@@ -59,6 +61,10 @@
     private float mMaxX = 100;
     private float mMaxY = 100;
 
+    private float mMiddleDividerLoc = .5f;
+    private int mMiddleDividerTint = -1;
+    private int mTopDividerTint = -1;
+
     public UsageGraph(Context context, @Nullable AttributeSet attrs) {
         super(context, attrs);
         final Resources resources = context.getResources();
@@ -68,8 +74,8 @@
         mLinePaint.setStrokeCap(Cap.ROUND);
         mLinePaint.setStrokeJoin(Join.ROUND);
         mLinePaint.setAntiAlias(true);
-        mLinePaint.setPathEffect(new CornerPathEffect(resources.getDimensionPixelSize(
-                R.dimen.usage_graph_line_corner_radius)));
+        mCornerRadius = resources.getDimensionPixelSize(R.dimen.usage_graph_line_corner_radius);
+        mLinePaint.setPathEffect(new CornerPathEffect(mCornerRadius));
         mLinePaint.setStrokeWidth(resources.getDimensionPixelSize(R.dimen.usage_graph_line_width));
 
         mFillPaint = new Paint(mLinePaint);
@@ -86,6 +92,7 @@
         TypedValue v = new TypedValue();
         context.getTheme().resolveAttribute(com.android.internal.R.attr.listDivider, v, true);
         mDivider = context.getDrawable(v.resourceId);
+        mTintedDivider = context.getDrawable(v.resourceId);
         mDividerSize = resources.getDimensionPixelSize(R.dimen.usage_graph_divider_size);
     }
 
@@ -98,6 +105,15 @@
         mMaxY = maxY;
     }
 
+    void setDividerLoc(int height) {
+        mMiddleDividerLoc = 1 - height / mMaxY;
+    }
+
+    void setDividerColors(int middleColor, int topColor) {
+        mMiddleDividerTint = middleColor;
+        mTopDividerTint = topColor;
+    }
+
     public void addPath(SparseIntArray points) {
         for (int i = 0; i < points.size(); i++) {
             mPaths.put(points.keyAt(i), points.valueAt(i));
@@ -150,7 +166,7 @@
                 if (mLocalPaths.size() > 0) {
                     int lastX = mLocalPaths.keyAt(mLocalPaths.size() - 1);
                     int lastY = mLocalPaths.valueAt(mLocalPaths.size() - 1);
-                    if (lastY != PATH_DELIM && (lastX == lx || lastY == ly)) {
+                    if (lastY != PATH_DELIM && !hasDiff(lastX, lx) && !hasDiff(lastY, ly)) {
                         pendingYLoc = ly;
                         continue;
                     }
@@ -160,6 +176,10 @@
         }
     }
 
+    private boolean hasDiff(int x1, int x2) {
+        return Math.abs(x2 - x1) >= mCornerRadius;
+    }
+
     private int getX(float x) {
         return (int) (x / mMaxX * getWidth());
     }
@@ -180,9 +200,12 @@
     @Override
     protected void onDraw(Canvas canvas) {
         // Draw lines across the top, middle, and bottom.
-        drawDivider(0, canvas);
-        drawDivider((canvas.getHeight() - mDividerSize) / 2, canvas);
-        drawDivider(canvas.getHeight() - mDividerSize, canvas);
+        if (mMiddleDividerLoc != 0) {
+            drawDivider(0, canvas, mTopDividerTint);
+        }
+        drawDivider((int) ((canvas.getHeight() - mDividerSize) * mMiddleDividerLoc), canvas,
+                mMiddleDividerTint);
+        drawDivider(canvas.getHeight() - mDividerSize, canvas, -1);
 
         if (mLocalPaths.size() == 0) {
             return;
@@ -242,8 +265,13 @@
         canvas.drawPath(mPath, mFillPaint);
     }
 
-    private void drawDivider(int y, Canvas canvas) {
-        mDivider.setBounds(0, y, canvas.getWidth(), y + mDividerSize);
-        mDivider.draw(canvas);
+    private void drawDivider(int y, Canvas canvas, int tintColor) {
+        Drawable d = mDivider;
+        if (tintColor != -1) {
+            mTintedDivider.setTint(tintColor);
+            d = mTintedDivider;
+        }
+        d.setBounds(0, y, canvas.getWidth(), y + mDividerSize);
+        d.draw(canvas);
     }
 }
diff --git a/packages/SettingsLib/src/com/android/settingslib/graph/UsageView.java b/packages/SettingsLib/src/com/android/settingslib/graph/UsageView.java
index f95a97a..ee1821d 100644
--- a/packages/SettingsLib/src/com/android/settingslib/graph/UsageView.java
+++ b/packages/SettingsLib/src/com/android/settingslib/graph/UsageView.java
@@ -20,6 +20,7 @@
 import android.util.SparseIntArray;
 import android.view.Gravity;
 import android.view.LayoutInflater;
+import android.view.View;
 import android.widget.FrameLayout;
 import android.widget.LinearLayout;
 import android.widget.TextView;
@@ -98,6 +99,26 @@
         mUsageGraph.setAccentColor(color);
     }
 
+    public void setDividerLoc(int dividerLoc) {
+        mUsageGraph.setDividerLoc(dividerLoc);
+    }
+
+    public void setDividerColors(int middleColor, int topColor) {
+        mUsageGraph.setDividerColors(middleColor, topColor);
+    }
+
+    public void setSideLabelWeights(float before, float after) {
+        setWeight(R.id.space1, before);
+        setWeight(R.id.space2, after);
+    }
+
+    private void setWeight(int id, float weight) {
+        View v = findViewById(id);
+        LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) v.getLayoutParams();
+        params.weight = weight;
+        v.setLayoutParams(params);
+    }
+
     public void setSideLabels(CharSequence[] labels) {
         if (labels.length != mLabels.length) {
             throw new IllegalArgumentException("Invalid number of labels");
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
index 5b8ed28..380fcd4 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
@@ -110,6 +110,7 @@
     private final Context mContext;
 
     private String ssid;
+    private String bssid;
     private int security;
     private int networkId = WifiConfiguration.INVALID_NETWORK_ID;
 
@@ -335,6 +336,10 @@
         return ssid;
     }
 
+    public String getBssid() {
+        return bssid;
+    }
+
     public CharSequence getSsid() {
         SpannableString str = new SpannableString(ssid);
         str.setSpan(new TtsSpan.VerbatimBuilder(ssid).build(), 0, ssid.length(),
@@ -657,6 +662,7 @@
         else
             ssid = (config.SSID == null ? "" : removeDoubleQuotes(config.SSID));
 
+        bssid = config.BSSID;
         security = getSecurity(config);
         networkId = config.networkId;
         mConfig = config;
@@ -664,6 +670,7 @@
 
     private void initWithScanResult(ScanResult result) {
         ssid = result.SSID;
+        bssid = result.BSSID;
         security = getSecurity(result);
         if (security == SECURITY_PSK)
             pskType = getPskType(result);
diff --git a/packages/SettingsProvider/res/values-bs-rBA/defaults.xml b/packages/SettingsProvider/res/values-bs-rBA/defaults.xml
index 5650077..4a87a12 100644
--- a/packages/SettingsProvider/res/values-bs-rBA/defaults.xml
+++ b/packages/SettingsProvider/res/values-bs-rBA/defaults.xml
@@ -19,9 +19,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for def_device_name (6309317409634339402) -->
-    <skip />
-    <!-- no translation found for def_device_name_simple (9037785625140748221) -->
-    <skip />
+    <string name="def_device_name" msgid="6309317409634339402">"%1$s %2$s"</string>
+    <string name="def_device_name_simple" msgid="9037785625140748221">"%1$s"</string>
     <string name="def_nfc_payment_component" msgid="5861297439873026958"></string>
 </resources>
diff --git a/packages/SettingsProvider/res/values/defaults.xml b/packages/SettingsProvider/res/values/defaults.xml
index 51d8ca0..978ca94 100644
--- a/packages/SettingsProvider/res/values/defaults.xml
+++ b/packages/SettingsProvider/res/values/defaults.xml
@@ -155,6 +155,9 @@
     <!-- Default for Settings.Secure.LONG_PRESS_TIMEOUT_MILLIS -->
     <integer name="def_long_press_timeout_millis">500</integer>
 
+    <!-- Default for Settings.Secure.SHOW_IME_WITH_HARD_KEYBOARD -->
+    <bool name="def_show_ime_with_hard_keyboard">false</bool>
+
     <!-- Default for Settings.System.POINTER_SPEED -->
     <integer name="def_pointer_speed">0</integer>
 
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java
index d89abf42..b79ce80 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java
@@ -62,8 +62,9 @@
      */
     private static final ArraySet<String> sBroadcastOnRestore;
     static {
-        sBroadcastOnRestore = new ArraySet<String>(3);
+        sBroadcastOnRestore = new ArraySet<String>(4);
         sBroadcastOnRestore.add(Settings.Secure.ENABLED_NOTIFICATION_LISTENERS);
+        sBroadcastOnRestore.add(Settings.Secure.ENABLED_VR_LISTENERS);
         sBroadcastOnRestore.add(Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES);
         sBroadcastOnRestore.add(Settings.Secure.ENABLED_INPUT_METHODS);
     }
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
index 9842e28..987b5ea 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
@@ -1128,10 +1128,15 @@
 
     private PackageInfo getCallingPackageInfoOrThrow(int userId) {
         try {
-            return mPackageManager.getPackageInfo(getCallingPackage(), 0, userId);
+            PackageInfo packageInfo = mPackageManager.getPackageInfo(
+                    getCallingPackage(), 0, userId);
+            if (packageInfo != null) {
+                return packageInfo;
+            }
         } catch (RemoteException e) {
-            throw new IllegalStateException("Calling package doesn't exist");
+            /* ignore */
         }
+        throw new IllegalStateException("Calling package doesn't exist");
     }
 
     private int getGroupParentLocked(int userId) {
@@ -1666,16 +1671,16 @@
 
         private void migrateLegacySettingsForUserLocked(DatabaseHelper dbHelper,
                 SQLiteDatabase database, int userId) {
-            // Move over the global settings if owner.
-            if (userId == UserHandle.USER_SYSTEM) {
-                final int globalKey = makeKey(SETTINGS_TYPE_GLOBAL, userId);
-                ensureSettingsStateLocked(globalKey);
-                SettingsState globalSettings = mSettingsStates.get(globalKey);
-                migrateLegacySettingsLocked(globalSettings, database, TABLE_GLOBAL);
-                globalSettings.persistSyncLocked();
-            }
+            // Move over the system settings.
+            final int systemKey = makeKey(SETTINGS_TYPE_SYSTEM, userId);
+            ensureSettingsStateLocked(systemKey);
+            SettingsState systemSettings = mSettingsStates.get(systemKey);
+            migrateLegacySettingsLocked(systemSettings, database, TABLE_SYSTEM);
+            systemSettings.persistSyncLocked();
 
             // Move over the secure settings.
+            // Do this after System settings, since this is the first thing we check when deciding
+            // to skip over migration from db to xml for a secondary user.
             final int secureKey = makeKey(SETTINGS_TYPE_SECURE, userId);
             ensureSettingsStateLocked(secureKey);
             SettingsState secureSettings = mSettingsStates.get(secureKey);
@@ -1683,12 +1688,16 @@
             ensureSecureSettingAndroidIdSetLocked(secureSettings);
             secureSettings.persistSyncLocked();
 
-            // Move over the system settings.
-            final int systemKey = makeKey(SETTINGS_TYPE_SYSTEM, userId);
-            ensureSettingsStateLocked(systemKey);
-            SettingsState systemSettings = mSettingsStates.get(systemKey);
-            migrateLegacySettingsLocked(systemSettings, database, TABLE_SYSTEM);
-            systemSettings.persistSyncLocked();
+            // Move over the global settings if owner.
+            // Do this last, since this is the first thing we check when deciding
+            // to skip over migration from db to xml for owner user.
+            if (userId == UserHandle.USER_SYSTEM) {
+                final int globalKey = makeKey(SETTINGS_TYPE_GLOBAL, userId);
+                ensureSettingsStateLocked(globalKey);
+                SettingsState globalSettings = mSettingsStates.get(globalKey);
+                migrateLegacySettingsLocked(globalSettings, database, TABLE_GLOBAL);
+                globalSettings.persistSyncLocked();
+            }
 
             // Drop the database as now all is moved and persisted.
             if (DROP_DATABASE_ON_MIGRATION) {
@@ -1931,7 +1940,7 @@
         }
 
         private final class UpgradeController {
-            private static final int SETTINGS_VERSION = 124;
+            private static final int SETTINGS_VERSION = 125;
 
             private final int mUserId;
 
@@ -2111,6 +2120,22 @@
                     currentVersion = 124;
                 }
 
+                if (currentVersion == 124) {
+                    // Version 124: allow OEMs to set a default value for whether IME should be
+                    // shown when a physical keyboard is connected.
+                    final SettingsState secureSettings = getSecureSettingsLocked(userId);
+                    Setting currentSetting = secureSettings.getSettingLocked(
+                            Settings.Secure.SHOW_IME_WITH_HARD_KEYBOARD);
+                    if (currentSetting == null) {
+                        secureSettings.insertSettingLocked(
+                                Settings.Secure.SHOW_IME_WITH_HARD_KEYBOARD,
+                                getContext().getResources().getBoolean(
+                                        R.bool.def_show_ime_with_hard_keyboard) ? "1" : "0",
+                                SettingsState.SYSTEM_PACKAGE_NAME);
+                    }
+                    currentVersion = 125;
+                }
+
                 // vXXX: Add new settings above this point.
 
                 // Return the current version.
diff --git a/packages/Shell/res/layout/dialog_bugreport_info.xml b/packages/Shell/res/layout/dialog_bugreport_info.xml
index 5d1e9f9..b6b8d6b 100644
--- a/packages/Shell/res/layout/dialog_bugreport_info.xml
+++ b/packages/Shell/res/layout/dialog_bugreport_info.xml
@@ -16,28 +16,44 @@
 
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
     android:orientation="vertical"
+    android:paddingTop="15dp"
+    android:paddingStart="24dp"
+    android:paddingEnd="24dp"
     android:layout_width="wrap_content"
     android:layout_height="wrap_content">
+    <TextView
+        android:inputType="textNoSuggestions"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:text="@string/bugreport_info_name"/>
     <EditText
         android:id="@+id/name"
         android:maxLength="30"
         android:singleLine="true"
+        android:selectAllOnFocus="true"
         android:inputType="textNoSuggestions"
         android:layout_width="match_parent"
+        android:layout_height="wrap_content"/>
+    <TextView
+        android:layout_width="match_parent"
         android:layout_height="wrap_content"
-        android:hint="@string/bugreport_info_name"/>
+        android:text="@string/bugreport_info_title"/>
     <EditText
         android:id="@+id/title"
         android:maxLength="80"
         android:singleLine="true"
+        android:inputType="textAutoCorrect|textCapSentences"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"/>
+    <TextView
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
-        android:hint="@string/bugreport_info_title"/>
+        android:editable="false"
+        android:text="@string/bugreport_info_description"/>
     <EditText
         android:id="@+id/description"
         android:singleLine="false"
-        android:inputType="textMultiLine"
+        android:inputType="textMultiLine|textAutoCorrect|textCapSentences"
         android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:hint="@string/bugreport_info_description"/>
+        android:layout_height="wrap_content"/>
 </LinearLayout>
diff --git a/packages/Shell/res/values-af/strings.xml b/packages/Shell/res/values-af/strings.xml
index 9d399c1..8dbe3cd 100644
--- a/packages/Shell/res/values-af/strings.xml
+++ b/packages/Shell/res/values-af/strings.xml
@@ -19,10 +19,13 @@
     <string name="app_label" msgid="3701846017049540910">"Tuisskerm"</string>
     <string name="bugreport_in_progress_title" msgid="4311705936714972757">"Foutverslag <xliff:g id="ID">#%d</xliff:g> word tans geskep"</string>
     <string name="bugreport_finished_title" msgid="4429132808670114081">"Foutverslag <xliff:g id="ID">#%d</xliff:g> is vasgevang"</string>
+    <string name="bugreport_finished_pending_screenshot_title" msgid="5460883450679439591">"Foutverslag <xliff:g id="ID">#%d</xliff:g> vasgevang, maar skermkiekie hangende"</string>
     <string name="bugreport_updating_title" msgid="4423539949559634214">"Voeg tans besonderhede by die foutverslag"</string>
     <string name="bugreport_updating_wait" msgid="3322151947853929470">"Wag asseblief …"</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Swiep na links om jou foutverslag te deel"</string>
     <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"Tik om jou foutverslag te deel"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"Tik om jou foutverslag sonder \'n skermkiekie te deel, of wag totdat die skermkiekie gereed is"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"Tik om jou foutverslag sonder \'n skermkiekie te deel, of wag totdat die skermkiekie gereed is"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"Foutverslae bevat data van die stelsel se verskillende loglêers af, insluitend persoonlike en private inligting. Deel foutverslae net met programme en mense wat jy vertrou."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Wys hierdie boodskap volgende keer"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"Foutverslae"</string>
@@ -34,6 +37,7 @@
     <string name="bugreport_screenshot_failed" msgid="5853049140806834601">"Kon nie skermkiekie neem nie."</string>
     <string name="bugreport_info_dialog_title" msgid="1355948594292983332">"Foutverslag <xliff:g id="ID">#%d</xliff:g> se besonderhede"</string>
     <string name="bugreport_info_name" msgid="4414036021935139527">"Lêernaam"</string>
-    <string name="bugreport_info_title" msgid="5599558206004371052">"Titel"</string>
-    <string name="bugreport_info_description" msgid="4117088998733546784">"Gedetailleerde beskrywing"</string>
+    <string name="bugreport_info_title" msgid="2306030793918239804">"Fouttitel"</string>
+    <string name="bugreport_info_description" msgid="5072835127481627722">"Foutopsomming"</string>
+    <string name="save" msgid="4781509040564835759">"Stoor"</string>
 </resources>
diff --git a/packages/Shell/res/values-am/strings.xml b/packages/Shell/res/values-am/strings.xml
index 2545222..fae820c 100644
--- a/packages/Shell/res/values-am/strings.xml
+++ b/packages/Shell/res/values-am/strings.xml
@@ -19,10 +19,16 @@
     <string name="app_label" msgid="3701846017049540910">"ቀፎ"</string>
     <string name="bugreport_in_progress_title" msgid="4311705936714972757">"የሳንካ ሪፖርት <xliff:g id="ID">#%d</xliff:g> እየተመነጨ ነው"</string>
     <string name="bugreport_finished_title" msgid="4429132808670114081">"የሳንካ ሪፖርት <xliff:g id="ID">#%d</xliff:g> ተወስዷል"</string>
+    <!-- no translation found for bugreport_finished_pending_screenshot_title (5460883450679439591) -->
+    <skip />
     <string name="bugreport_updating_title" msgid="4423539949559634214">"ዝርዝሮችን ወደ የሳንካ ሪፖርቱ በማከል ላይ"</string>
     <string name="bugreport_updating_wait" msgid="3322151947853929470">"እባክዎ ይጠብቁ…"</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"የሳንካ ሪፖርትዎን ለማጋራት ወደ ግራ ያንሸራትቱ"</string>
     <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"የሳንካ ሪፖርትዎን ለማጋራት መታ ያድርጉ"</string>
+    <!-- no translation found for bugreport_finished_pending_screenshot_text (1474435374470177193) -->
+    <skip />
+    <!-- no translation found for bugreport_finished_pending_screenshot_text (1474435374470177193) -->
+    <skip />
     <string name="bugreport_confirm" msgid="5130698467795669780">"የሳንካ ሪፖርቶች የግል መረጃን ጨምሮ ከበርካታ የስርዓቱ ምዝግብ ማስታወሻዎች የመጣ ውሂብን ይዟል። የሳንካ ሪፖርቶች ለሚያምኗቸው መተግበሪያዎችን እና ሰዎችን ብቻ ያጋሩ።"</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"ይህን መልዕክት በሚቀጥለው ጊዜ አሳይ"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"የሳንካ ሪፖርቶች"</string>
@@ -34,6 +40,7 @@
     <string name="bugreport_screenshot_failed" msgid="5853049140806834601">"ቅጽበታዊ ገጽ እይታ ሊነሳ አይችልም"</string>
     <string name="bugreport_info_dialog_title" msgid="1355948594292983332">"የሳንካ ሪፖርት <xliff:g id="ID">#%d</xliff:g> ዝርዝሮች"</string>
     <string name="bugreport_info_name" msgid="4414036021935139527">"የፋይል ስም"</string>
-    <string name="bugreport_info_title" msgid="5599558206004371052">"ርዕስ"</string>
-    <string name="bugreport_info_description" msgid="4117088998733546784">"ዝርዝር መግለጫ"</string>
+    <string name="bugreport_info_title" msgid="2306030793918239804">"የሳንካ ርዕስ"</string>
+    <string name="bugreport_info_description" msgid="5072835127481627722">"የሳንካ ማጠቃለያ"</string>
+    <string name="save" msgid="4781509040564835759">"አስቀምጥ"</string>
 </resources>
diff --git a/packages/Shell/res/values-ar/strings.xml b/packages/Shell/res/values-ar/strings.xml
index 7593110..818c368 100644
--- a/packages/Shell/res/values-ar/strings.xml
+++ b/packages/Shell/res/values-ar/strings.xml
@@ -19,10 +19,13 @@
     <string name="app_label" msgid="3701846017049540910">"Shell"</string>
     <string name="bugreport_in_progress_title" msgid="4311705936714972757">"جارٍ إنشاء تقرير الخطأ <xliff:g id="ID">#%d</xliff:g>."</string>
     <string name="bugreport_finished_title" msgid="4429132808670114081">"تم تسجيل تقرير الخطأ <xliff:g id="ID">#%d</xliff:g>."</string>
+    <string name="bugreport_finished_pending_screenshot_title" msgid="5460883450679439591">"تم التقاط تقرير الأخطاء <xliff:g id="ID">#%d</xliff:g> ولكن في انتظار لقطة الشاشة"</string>
     <string name="bugreport_updating_title" msgid="4423539949559634214">"إضافة تفاصيل إلى تقرير الخطأ"</string>
     <string name="bugreport_updating_wait" msgid="3322151947853929470">"الرجاء الانتظار…"</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"مرر بسرعة لليمين لمشاركة تقرير الخطأ"</string>
     <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"انقر لمشاركة تقرير الخطأ."</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"انقر لمشاركة تقرير الأخطاء بدون لقطة شاشة أو انتظر حتى انتهاء لقطة الشاشة"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"انقر لمشاركة تقرير الأخطاء بدون لقطة شاشة أو انتظر حتى انتهاء لقطة الشاشة"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"تحتوي تقارير الأخطاء على بيانات من ملفات سجلات النظام المتنوعة، بما في ذلك معلومات شخصية وخاصة. لا تشارك تقارير الأخطاء إلا مع التطبيقات والأشخاص الموثوق بهم."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"إظهار هذه الرسالة في المرة القادمة"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"تقارير الأخطاء"</string>
@@ -34,6 +37,7 @@
     <string name="bugreport_screenshot_failed" msgid="5853049140806834601">"تعذر التقاط لقطة الشاشة."</string>
     <string name="bugreport_info_dialog_title" msgid="1355948594292983332">"تفاصيل تقرير الخطأ <xliff:g id="ID">#%d</xliff:g>"</string>
     <string name="bugreport_info_name" msgid="4414036021935139527">"اسم الملف"</string>
-    <string name="bugreport_info_title" msgid="5599558206004371052">"العنوان"</string>
-    <string name="bugreport_info_description" msgid="4117088998733546784">"وصف تفصيلي"</string>
+    <string name="bugreport_info_title" msgid="2306030793918239804">"عنوان الخطأ"</string>
+    <string name="bugreport_info_description" msgid="5072835127481627722">"ملخص الخطأ"</string>
+    <string name="save" msgid="4781509040564835759">"حفظ"</string>
 </resources>
diff --git a/packages/Shell/res/values-az-rAZ/strings.xml b/packages/Shell/res/values-az-rAZ/strings.xml
index 9130255..6172e7d 100644
--- a/packages/Shell/res/values-az-rAZ/strings.xml
+++ b/packages/Shell/res/values-az-rAZ/strings.xml
@@ -19,10 +19,16 @@
     <string name="app_label" msgid="3701846017049540910">"Shell"</string>
     <string name="bugreport_in_progress_title" msgid="4311705936714972757">"Baq hesabatı <xliff:g id="ID">#%d</xliff:g> yaradıldı"</string>
     <string name="bugreport_finished_title" msgid="4429132808670114081">"Baq hesabatı <xliff:g id="ID">#%d</xliff:g> alındı"</string>
+    <!-- no translation found for bugreport_finished_pending_screenshot_title (5460883450679439591) -->
+    <skip />
     <string name="bugreport_updating_title" msgid="4423539949559634214">"Detallar baq hesabatına əlavə olunur"</string>
     <string name="bugreport_updating_wait" msgid="3322151947853929470">"Lütfən, gözləyin..."</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Baq raportunu paylaşmaq üçün sola sürüşdürün"</string>
     <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"Baq hesabatınızı paylaşmaq üçün tıklayın"</string>
+    <!-- no translation found for bugreport_finished_pending_screenshot_text (1474435374470177193) -->
+    <skip />
+    <!-- no translation found for bugreport_finished_pending_screenshot_text (1474435374470177193) -->
+    <skip />
     <string name="bugreport_confirm" msgid="5130698467795669780">"Baq raportları sistemin müxtəlif jurnal fayllarından data içərir ki, buna şəxsi və konfidensial məlumatlar da aiddir. Yalnız inandığınız adamlarla baq raportlarını paylaşın."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Bu mesajı növbəti dəfə göstər"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"Baq hesabatları"</string>
@@ -34,6 +40,7 @@
     <string name="bugreport_screenshot_failed" msgid="5853049140806834601">"Displey görüntüsü əlçatan deyil."</string>
     <string name="bugreport_info_dialog_title" msgid="1355948594292983332">"Baq hesabatı <xliff:g id="ID">#%d</xliff:g> detalları"</string>
     <string name="bugreport_info_name" msgid="4414036021935139527">"Fayl adı"</string>
-    <string name="bugreport_info_title" msgid="5599558206004371052">"Başlıq"</string>
-    <string name="bugreport_info_description" msgid="4117088998733546784">"Ətraflı təsvir"</string>
+    <string name="bugreport_info_title" msgid="2306030793918239804">"Baq başlığı"</string>
+    <string name="bugreport_info_description" msgid="5072835127481627722">"Baq xülasə"</string>
+    <string name="save" msgid="4781509040564835759">"Yadda saxlayın"</string>
 </resources>
diff --git a/packages/Shell/res/values-b+sr+Latn/strings.xml b/packages/Shell/res/values-b+sr+Latn/strings.xml
index 597e545..bc5ce26 100644
--- a/packages/Shell/res/values-b+sr+Latn/strings.xml
+++ b/packages/Shell/res/values-b+sr+Latn/strings.xml
@@ -19,10 +19,13 @@
     <string name="app_label" msgid="3701846017049540910">"Shell"</string>
     <string name="bugreport_in_progress_title" msgid="4311705936714972757">"Izveštaj o grešci <xliff:g id="ID">#%d</xliff:g> se generiše"</string>
     <string name="bugreport_finished_title" msgid="4429132808670114081">"Izveštaj o grešci <xliff:g id="ID">#%d</xliff:g> je snimljen"</string>
+    <string name="bugreport_finished_pending_screenshot_title" msgid="5460883450679439591">"Izveštaj o grešci <xliff:g id="ID">#%d</xliff:g> snimljen; snimak ekrana se čeka"</string>
     <string name="bugreport_updating_title" msgid="4423539949559634214">"Dodaju se detalji u izveštaj o grešci"</string>
     <string name="bugreport_updating_wait" msgid="3322151947853929470">"Sačekajte..."</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Prevucite ulevo da biste delili izveštaj o greškama"</string>
     <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"Dodirnite da biste delili izveštaj o grešci"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"Dodirnite za deljenje izveštaja o grešci bez snimka ekrana ili sačekajte da se napravi snimak ekrana"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"Dodirnite za deljenje izveštaja o grešci bez snimka ekrana ili sačekajte da se napravi snimak ekrana"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"Izveštaji o greškama sadrže podatke iz različitih sistemskih datoteka evidencije, uključujući lične i privatne podatke. Delite izveštaje o greškama samo sa aplikacijama i ljudima u koje imate poverenja."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Prikaži ovu poruku sledeći put"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"Izveštaji o greškama"</string>
@@ -34,6 +37,7 @@
     <string name="bugreport_screenshot_failed" msgid="5853049140806834601">"Snimanje ekrana nije uspelo."</string>
     <string name="bugreport_info_dialog_title" msgid="1355948594292983332">"Detalji izveštaja o grešci <xliff:g id="ID">#%d</xliff:g>"</string>
     <string name="bugreport_info_name" msgid="4414036021935139527">"Naziv datoteke"</string>
-    <string name="bugreport_info_title" msgid="5599558206004371052">"Naslov"</string>
-    <string name="bugreport_info_description" msgid="4117088998733546784">"Detaljni opis"</string>
+    <string name="bugreport_info_title" msgid="2306030793918239804">"Naslov greške"</string>
+    <string name="bugreport_info_description" msgid="5072835127481627722">"Rezime greške"</string>
+    <string name="save" msgid="4781509040564835759">"Sačuvaj"</string>
 </resources>
diff --git a/packages/Shell/res/values-bg/strings.xml b/packages/Shell/res/values-bg/strings.xml
index 6ca7914..6a69f7d 100644
--- a/packages/Shell/res/values-bg/strings.xml
+++ b/packages/Shell/res/values-bg/strings.xml
@@ -19,10 +19,16 @@
     <string name="app_label" msgid="3701846017049540910">"Команден ред"</string>
     <string name="bugreport_in_progress_title" msgid="4311705936714972757">"Сигналът за програмна грешка „<xliff:g id="ID">#%d</xliff:g>“ се генерира"</string>
     <string name="bugreport_finished_title" msgid="4429132808670114081">"Сигналът за програмна грешка „<xliff:g id="ID">#%d</xliff:g>“ е заснет"</string>
+    <!-- no translation found for bugreport_finished_pending_screenshot_title (5460883450679439591) -->
+    <skip />
     <string name="bugreport_updating_title" msgid="4423539949559634214">"Подробностите се добавят към сигнала за пр. грешка"</string>
     <string name="bugreport_updating_wait" msgid="3322151947853929470">"Моля, изчакайте…"</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Прекарайте пръст наляво, за да споделите сигнала си за програмна грешка"</string>
     <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"Докоснете, за да споделите сигнала си за програмна грешка"</string>
+    <!-- no translation found for bugreport_finished_pending_screenshot_text (1474435374470177193) -->
+    <skip />
+    <!-- no translation found for bugreport_finished_pending_screenshot_text (1474435374470177193) -->
+    <skip />
     <string name="bugreport_confirm" msgid="5130698467795669780">"Отчетите за програмни грешки съдържат данни от различни регистрационни файлове на системата, включително лична и поверителна информация. Споделяйте ги само с приложения и хора, на които имате доверие."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Това съобщение да се показва следващия път"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"Отчети за прогр. грешки"</string>
@@ -34,6 +40,7 @@
     <string name="bugreport_screenshot_failed" msgid="5853049140806834601">"Екранната снимка не можа да бъде направена."</string>
     <string name="bugreport_info_dialog_title" msgid="1355948594292983332">"Подробности за сигнала за програмна грешка „<xliff:g id="ID">#%d</xliff:g>“"</string>
     <string name="bugreport_info_name" msgid="4414036021935139527">"Име на файла"</string>
-    <string name="bugreport_info_title" msgid="5599558206004371052">"Заглавие"</string>
-    <string name="bugreport_info_description" msgid="4117088998733546784">"Подробно описание"</string>
+    <string name="bugreport_info_title" msgid="2306030793918239804">"Заглавие на сигнала за програмна грешка"</string>
+    <string name="bugreport_info_description" msgid="5072835127481627722">"Обобщена информация за сигнала за програмна грешка"</string>
+    <string name="save" msgid="4781509040564835759">"Запазване"</string>
 </resources>
diff --git a/packages/Shell/res/values-bn-rBD/strings.xml b/packages/Shell/res/values-bn-rBD/strings.xml
index 5390315..c632b10 100644
--- a/packages/Shell/res/values-bn-rBD/strings.xml
+++ b/packages/Shell/res/values-bn-rBD/strings.xml
@@ -19,10 +19,13 @@
     <string name="app_label" msgid="3701846017049540910">"শেল"</string>
     <string name="bugreport_in_progress_title" msgid="4311705936714972757">"ত্রুটির প্রতিবেদন <xliff:g id="ID">#%d</xliff:g> তৈরি করা হচ্ছে"</string>
     <string name="bugreport_finished_title" msgid="4429132808670114081">"ত্রুটির প্রতিবেদন <xliff:g id="ID">#%d</xliff:g> ক্যাপচার করা হয়েছে"</string>
+    <string name="bugreport_finished_pending_screenshot_title" msgid="5460883450679439591">"ত্রুটির প্রতিবেদন <xliff:g id="ID">#%d</xliff:g> ক্যাপচার করা হয়েছে কিন্তু স্ক্রীনশট নেওয়ার কাজ সম্পন্ন হয়নি"</string>
     <string name="bugreport_updating_title" msgid="4423539949559634214">"ত্রুটির প্রতিবেদনে বিশদ বিবরণ যোগ করা হচ্ছে"</string>
     <string name="bugreport_updating_wait" msgid="3322151947853929470">"অনুগ্রহ করে অপেক্ষা করুন..."</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"আপনার বাগ রিপোর্ট শেয়ার করতে বামে সোয়াইপ করুন"</string>
     <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"আপনার ত্রুটির প্রতিবেদন শেয়ার করতে আলতো চাপ দিন"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"কোনো স্ক্রীনশট ছাড়াই ত্রুটির প্রতিবেদন শেয়ার করতে আলতো চাপ দিন বা সম্পন্ন করতে স্ক্রীনশটের জন্য অপেক্ষা করুন"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"কোনো স্ক্রীনশট ছাড়াই ত্রুটির প্রতিবেদন শেয়ার করতে আলতো চাপ দিন বা সম্পন্ন করতে স্ক্রীনশটের জন্য অপেক্ষা করুন"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"ত্রুটির প্রতিবেদনগুলিতে থাকা ডেটা, সিস্টেমের বিভিন্ন লগ ফাইলগুলি থেকে আসে, যাতে ব্যক্তিগত এবং গোপনীয় তথ্য অন্তর্ভুক্ত থাকে৷ আপনি বিশ্বাস করেন শুধুমাত্র এমন অ্যাপ্লিকেশান এবং ব্যক্তিদের সাথে ত্রুটির প্রতিবেদনগুলি ভাগ করুন৷"</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"এই বার্তাটি পরের বার দেখান"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"ত্রুটির প্রতিবেদনগুলি"</string>
@@ -34,6 +37,7 @@
     <string name="bugreport_screenshot_failed" msgid="5853049140806834601">"স্ক্রীনশট নেওয়া যায়নি৷"</string>
     <string name="bugreport_info_dialog_title" msgid="1355948594292983332">"ত্রুটির প্রতিবেদন <xliff:g id="ID">#%d</xliff:g> এর বিশদ বিবরণ"</string>
     <string name="bugreport_info_name" msgid="4414036021935139527">"ফাইলের নাম"</string>
-    <string name="bugreport_info_title" msgid="5599558206004371052">"শীর্ষক"</string>
-    <string name="bugreport_info_description" msgid="4117088998733546784">"বিস্তারিত বিবরণ"</string>
+    <string name="bugreport_info_title" msgid="2306030793918239804">"ত্রুটির শীর্ষক"</string>
+    <string name="bugreport_info_description" msgid="5072835127481627722">"ত্রুটির সারাংশ"</string>
+    <string name="save" msgid="4781509040564835759">"সংরক্ষণ করুন"</string>
 </resources>
diff --git a/packages/Shell/res/values-bs-rBA/strings.xml b/packages/Shell/res/values-bs-rBA/strings.xml
index 903c2ab..a38be0e 100644
--- a/packages/Shell/res/values-bs-rBA/strings.xml
+++ b/packages/Shell/res/values-bs-rBA/strings.xml
@@ -19,10 +19,16 @@
     <string name="app_label" msgid="3701846017049540910">"Ljuska"</string>
     <string name="bugreport_in_progress_title" msgid="4311705936714972757">"Izvještaj o grešci <xliff:g id="ID">#%d</xliff:g> se generira"</string>
     <string name="bugreport_finished_title" msgid="4429132808670114081">"Izvještaj o grešci <xliff:g id="ID">#%d</xliff:g> je snimljen"</string>
+    <!-- no translation found for bugreport_finished_pending_screenshot_title (5460883450679439591) -->
+    <skip />
     <string name="bugreport_updating_title" msgid="4423539949559634214">"Dodavanje detalja u izvještaj o greškama"</string>
     <string name="bugreport_updating_wait" msgid="3322151947853929470">"Pričekajte..."</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Prevucite lijevo da podijelite izvještaj o greškama"</string>
     <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"Dodirnite da biste podijelili izvještaj o grešci"</string>
+    <!-- no translation found for bugreport_finished_pending_screenshot_text (1474435374470177193) -->
+    <skip />
+    <!-- no translation found for bugreport_finished_pending_screenshot_text (1474435374470177193) -->
+    <skip />
     <string name="bugreport_confirm" msgid="5130698467795669780">"Izvještaji o greškama sadrže podatke iz raznih zapisnika sistema, uključujući lične i privatne informacije. Podijelite izvještaje o greškama samo sa aplikacijama i osobama kojima vjerujete."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Pokaži ovu poruku sljedeći put"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"Izvještaji o greškama"</string>
@@ -34,6 +40,7 @@
     <string name="bugreport_screenshot_failed" msgid="5853049140806834601">"Ekran nije moguće snimiti."</string>
     <string name="bugreport_info_dialog_title" msgid="1355948594292983332">"Detalji izvještaja o grešci <xliff:g id="ID">#%d</xliff:g>"</string>
     <string name="bugreport_info_name" msgid="4414036021935139527">"Naziv fajla"</string>
-    <string name="bugreport_info_title" msgid="5599558206004371052">"Naslov"</string>
-    <string name="bugreport_info_description" msgid="4117088998733546784">"Detaljan opis"</string>
+    <string name="bugreport_info_title" msgid="2306030793918239804">"Naslov greške"</string>
+    <string name="bugreport_info_description" msgid="5072835127481627722">"Sažetak greške"</string>
+    <string name="save" msgid="4781509040564835759">"Sačuvaj"</string>
 </resources>
diff --git a/packages/Shell/res/values-ca/strings.xml b/packages/Shell/res/values-ca/strings.xml
index 0836946..c246ec4 100644
--- a/packages/Shell/res/values-ca/strings.xml
+++ b/packages/Shell/res/values-ca/strings.xml
@@ -19,10 +19,16 @@
     <string name="app_label" msgid="3701846017049540910">"Protecció"</string>
     <string name="bugreport_in_progress_title" msgid="4311705936714972757">"S\'està generant l\'informe d\'errors <xliff:g id="ID">#%d</xliff:g>"</string>
     <string name="bugreport_finished_title" msgid="4429132808670114081">"S\'ha capturat l\'informe d\'errors <xliff:g id="ID">#%d</xliff:g>"</string>
+    <!-- no translation found for bugreport_finished_pending_screenshot_title (5460883450679439591) -->
+    <skip />
     <string name="bugreport_updating_title" msgid="4423539949559634214">"S\'estan afegint detalls a l\'informe d\'errors"</string>
     <string name="bugreport_updating_wait" msgid="3322151947853929470">"Espera…"</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Llisca cap a l\'esquerra per compartir l\'informe d\'errors."</string>
     <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"Toca per compartir l\'informe d\'errors"</string>
+    <!-- no translation found for bugreport_finished_pending_screenshot_text (1474435374470177193) -->
+    <skip />
+    <!-- no translation found for bugreport_finished_pending_screenshot_text (1474435374470177193) -->
+    <skip />
     <string name="bugreport_confirm" msgid="5130698467795669780">"Els informes d\'error contenen dades dels diferents fitxers de registre del sistema, inclosa informació privada i personal. Comparteix els informes d\'error només amb les aplicacions i amb les persones en qui confies."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Mostra aquest missatge la propera vegada"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"Informes d\'error"</string>
@@ -34,6 +40,7 @@
     <string name="bugreport_screenshot_failed" msgid="5853049140806834601">"No s\'ha pogut fer la captura de pantalla."</string>
     <string name="bugreport_info_dialog_title" msgid="1355948594292983332">"Detalls de l\'informe d\'errors <xliff:g id="ID">#%d</xliff:g>"</string>
     <string name="bugreport_info_name" msgid="4414036021935139527">"Nom del fitxer"</string>
-    <string name="bugreport_info_title" msgid="5599558206004371052">"Títol"</string>
-    <string name="bugreport_info_description" msgid="4117088998733546784">"Descripció detallada"</string>
+    <string name="bugreport_info_title" msgid="2306030793918239804">"Títol de l\'error"</string>
+    <string name="bugreport_info_description" msgid="5072835127481627722">"Resum d\'errors"</string>
+    <string name="save" msgid="4781509040564835759">"Desa"</string>
 </resources>
diff --git a/packages/Shell/res/values-cs/strings.xml b/packages/Shell/res/values-cs/strings.xml
index 215ec87..ebd9b53 100644
--- a/packages/Shell/res/values-cs/strings.xml
+++ b/packages/Shell/res/values-cs/strings.xml
@@ -19,10 +19,16 @@
     <string name="app_label" msgid="3701846017049540910">"Shell"</string>
     <string name="bugreport_in_progress_title" msgid="4311705936714972757">"Zpráva o chybě <xliff:g id="ID">#%d</xliff:g> se vytváří"</string>
     <string name="bugreport_finished_title" msgid="4429132808670114081">"Zpráva o chybě <xliff:g id="ID">#%d</xliff:g> byla vytvořena"</string>
+    <!-- no translation found for bugreport_finished_pending_screenshot_title (5460883450679439591) -->
+    <skip />
     <string name="bugreport_updating_title" msgid="4423539949559634214">"Přidávání podrobností do zprávy o chybě"</string>
     <string name="bugreport_updating_wait" msgid="3322151947853929470">"Čekejte prosím…"</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Chcete-li hlášení chyby sdílet, přejeďte doleva."</string>
     <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"Zprávu o chybě můžete sdílet klepnutím"</string>
+    <!-- no translation found for bugreport_finished_pending_screenshot_text (1474435374470177193) -->
+    <skip />
+    <!-- no translation found for bugreport_finished_pending_screenshot_text (1474435374470177193) -->
+    <skip />
     <string name="bugreport_confirm" msgid="5130698467795669780">"Chybová hlášení obsahují data z různých souborů protokolů systému včetně osobních a soukromých informací. Chybová hlášení sdílejte pouze s aplikacemi a uživateli, kterým důvěřujete."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Zobrazit tuto zprávu příště"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"Zprávy o chybách"</string>
@@ -34,6 +40,7 @@
     <string name="bugreport_screenshot_failed" msgid="5853049140806834601">"Snímek obrazovky se nepodařilo pořídit."</string>
     <string name="bugreport_info_dialog_title" msgid="1355948594292983332">"Podrobnosti zprávy o chybě <xliff:g id="ID">#%d</xliff:g>"</string>
     <string name="bugreport_info_name" msgid="4414036021935139527">"Název souboru"</string>
-    <string name="bugreport_info_title" msgid="5599558206004371052">"Název"</string>
-    <string name="bugreport_info_description" msgid="4117088998733546784">"Podrobný popis"</string>
+    <string name="bugreport_info_title" msgid="2306030793918239804">"Název chyby"</string>
+    <string name="bugreport_info_description" msgid="5072835127481627722">"Přehled chyby"</string>
+    <string name="save" msgid="4781509040564835759">"Uložit"</string>
 </resources>
diff --git a/packages/Shell/res/values-da/strings.xml b/packages/Shell/res/values-da/strings.xml
index e956d3a..0f7b784 100644
--- a/packages/Shell/res/values-da/strings.xml
+++ b/packages/Shell/res/values-da/strings.xml
@@ -19,10 +19,13 @@
     <string name="app_label" msgid="3701846017049540910">"Shell"</string>
     <string name="bugreport_in_progress_title" msgid="4311705936714972757">"Fejlrapporten <xliff:g id="ID">#%d</xliff:g> genereres"</string>
     <string name="bugreport_finished_title" msgid="4429132808670114081">"Fejrapporten <xliff:g id="ID">#%d</xliff:g> blev gemt"</string>
+    <string name="bugreport_finished_pending_screenshot_title" msgid="5460883450679439591">"Fejlrapport <xliff:g id="ID">#%d</xliff:g> blev gemt, men skærmbilledet afventer"</string>
     <string name="bugreport_updating_title" msgid="4423539949559634214">"Tilføjelse af oplysninger til fejlrapporten"</string>
     <string name="bugreport_updating_wait" msgid="3322151947853929470">"Vent et øjeblik…"</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Stryg til venstre for at dele din fejlrapport"</string>
     <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"Tryk for at dele din fejlrapport"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"Tryk for at dele din fejlrapport uden et skærmbillede, eller vent på, at skærmbilledet fuldføres"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"Tryk for at dele din fejlrapport uden et skærmbillede, eller vent på, at skærmbilledet fuldføres"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"Fejlrapporter indeholder data fra systemets forskellige logfiler, f.eks. personlige og private oplysninger. Del kun fejlrapporter med apps og personer, du har tillid til."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Vis denne underretning næste gang"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"Fejlrapporter"</string>
@@ -34,6 +37,7 @@
     <string name="bugreport_screenshot_failed" msgid="5853049140806834601">"Der kunne ikke tages et skærmbillede."</string>
     <string name="bugreport_info_dialog_title" msgid="1355948594292983332">"Oplysninger om fejlrapporten <xliff:g id="ID">#%d</xliff:g>"</string>
     <string name="bugreport_info_name" msgid="4414036021935139527">"Filnavn"</string>
-    <string name="bugreport_info_title" msgid="5599558206004371052">"Titel"</string>
-    <string name="bugreport_info_description" msgid="4117088998733546784">"Detaljeret beskrivelse"</string>
+    <string name="bugreport_info_title" msgid="2306030793918239804">"Fejlrapportens titel"</string>
+    <string name="bugreport_info_description" msgid="5072835127481627722">"Oversigt over fejl"</string>
+    <string name="save" msgid="4781509040564835759">"Gem"</string>
 </resources>
diff --git a/packages/Shell/res/values-de/strings.xml b/packages/Shell/res/values-de/strings.xml
index 07f8898..8f87fed 100644
--- a/packages/Shell/res/values-de/strings.xml
+++ b/packages/Shell/res/values-de/strings.xml
@@ -19,10 +19,13 @@
     <string name="app_label" msgid="3701846017049540910">"Shell"</string>
     <string name="bugreport_in_progress_title" msgid="4311705936714972757">"Fehlerbericht <xliff:g id="ID">#%d</xliff:g> wird generiert"</string>
     <string name="bugreport_finished_title" msgid="4429132808670114081">"Fehlerbericht <xliff:g id="ID">#%d</xliff:g> erfasst"</string>
+    <string name="bugreport_finished_pending_screenshot_title" msgid="5460883450679439591">"Fehlerbericht <xliff:g id="ID">#%d</xliff:g> erfasst, aber Screenshot ausstehend"</string>
     <string name="bugreport_updating_title" msgid="4423539949559634214">"Informationen werden zum Fehlerbericht hinzugefügt"</string>
     <string name="bugreport_updating_wait" msgid="3322151947853929470">"Bitte warten…"</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Wische nach links, um deinen Fehlerbericht zu teilen."</string>
     <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"Zum Teilen des Fehlerberichts tippen"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"Tippe, um den Fehlerbericht ohne Screenshot zu teilen, oder warte auf den Screenshot"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"Tippe, um den Fehlerbericht ohne Screenshot zu teilen, oder warte auf den Screenshot"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"Fehlerberichte enthalten Daten aus verschiedenen Protokolldateien des Systems, darunter auch personenbezogene und private Daten. Teile Fehlerberichte nur mit Apps und Personen, denen du vertraust."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Diese Nachricht nächstes Mal zeigen"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"Fehlerberichte"</string>
@@ -34,6 +37,7 @@
     <string name="bugreport_screenshot_failed" msgid="5853049140806834601">"Screenshot konnte nicht aufgenommen werden."</string>
     <string name="bugreport_info_dialog_title" msgid="1355948594292983332">"Details zum Fehlerbericht <xliff:g id="ID">#%d</xliff:g>"</string>
     <string name="bugreport_info_name" msgid="4414036021935139527">"Dateiname"</string>
-    <string name="bugreport_info_title" msgid="5599558206004371052">"Titel"</string>
-    <string name="bugreport_info_description" msgid="4117088998733546784">"Detaillierte Beschreibung"</string>
+    <string name="bugreport_info_title" msgid="2306030793918239804">"Titel des Programmfehlers"</string>
+    <string name="bugreport_info_description" msgid="5072835127481627722">"Zusammenfassung des Programmfehlers"</string>
+    <string name="save" msgid="4781509040564835759">"Speichern"</string>
 </resources>
diff --git a/packages/Shell/res/values-el/strings.xml b/packages/Shell/res/values-el/strings.xml
index 6746976..517d83a 100644
--- a/packages/Shell/res/values-el/strings.xml
+++ b/packages/Shell/res/values-el/strings.xml
@@ -19,10 +19,13 @@
     <string name="app_label" msgid="3701846017049540910">"Κέλυφος"</string>
     <string name="bugreport_in_progress_title" msgid="4311705936714972757">"Δημιουργείται η αναφορά σφάλματος <xliff:g id="ID">#%d</xliff:g>"</string>
     <string name="bugreport_finished_title" msgid="4429132808670114081">"Έγινε λήψη της αναφοράς σφάλματος <xliff:g id="ID">#%d</xliff:g>"</string>
+    <string name="bugreport_finished_pending_screenshot_title" msgid="5460883450679439591">"Η αναφ. σφάλματος <xliff:g id="ID">#%d</xliff:g> ελήφθη, αλλά το στιγμ. εκκρεμεί"</string>
     <string name="bugreport_updating_title" msgid="4423539949559634214">"Προσθήκη λεπτομερειών στην αναφορά σφάλματος"</string>
     <string name="bugreport_updating_wait" msgid="3322151947853929470">"Περιμένετε…"</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Σύρετε προς τα αριστερά για κοινή χρήση της αναφοράς σφαλμάτων"</string>
     <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"Πατήστε για κοινή χρήση της αναφοράς σφάλματος"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"Πατήστε για κοινοποίηση της αναφοράς σφάλματος χωρίς στιγμιότυπο οθόνης ή περιμένετε να ολοκληρωθεί"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"Πατήστε για κοινοποίηση της αναφοράς σφάλματος χωρίς στιγμιότυπο οθόνης ή περιμένετε να ολοκληρωθεί"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"Οι αναφορές σφαλμάτων περιέχουν δεδομένα από τα διάφορα αρχεία καταγραφής του συστήματος, συμπεριλαμβανομένων προσωπικών και ιδιωτικών πληροφοριών. Να μοιράζεστε αναφορές σφαλμάτων μόνο με εφαρμογές και άτομα που εμπιστεύεστε."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Εμφάνιση αυτού του μηνύματος την επόμενη φορά"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"Αναφορές σφαλμάτων"</string>
@@ -34,6 +37,7 @@
     <string name="bugreport_screenshot_failed" msgid="5853049140806834601">"Δεν ήταν δυνατή η λήψη του στιγμιότυπου οθόνης."</string>
     <string name="bugreport_info_dialog_title" msgid="1355948594292983332">"Λεπτομέρειες της αναφοράς σφάλματος <xliff:g id="ID">#%d</xliff:g>"</string>
     <string name="bugreport_info_name" msgid="4414036021935139527">"Όνομα αρχείου"</string>
-    <string name="bugreport_info_title" msgid="5599558206004371052">"Τίτλος"</string>
-    <string name="bugreport_info_description" msgid="4117088998733546784">"Αναλυτική περιγραφή"</string>
+    <string name="bugreport_info_title" msgid="2306030793918239804">"Τίτλος σφάλματος"</string>
+    <string name="bugreport_info_description" msgid="5072835127481627722">"Περίληψη σφάλματος"</string>
+    <string name="save" msgid="4781509040564835759">"Αποθήκευση"</string>
 </resources>
diff --git a/packages/Shell/res/values-en-rAU/strings.xml b/packages/Shell/res/values-en-rAU/strings.xml
index ac681e2..2349ec5 100644
--- a/packages/Shell/res/values-en-rAU/strings.xml
+++ b/packages/Shell/res/values-en-rAU/strings.xml
@@ -19,10 +19,13 @@
     <string name="app_label" msgid="3701846017049540910">"Shell"</string>
     <string name="bugreport_in_progress_title" msgid="4311705936714972757">"Bug report <xliff:g id="ID">#%d</xliff:g> is being generated"</string>
     <string name="bugreport_finished_title" msgid="4429132808670114081">"Bug report <xliff:g id="ID">#%d</xliff:g> captured"</string>
+    <string name="bugreport_finished_pending_screenshot_title" msgid="5460883450679439591">"Bug report <xliff:g id="ID">#%d</xliff:g> captured but screenshot pending"</string>
     <string name="bugreport_updating_title" msgid="4423539949559634214">"Adding details to the bug report"</string>
     <string name="bugreport_updating_wait" msgid="3322151947853929470">"Please wait…"</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Swipe left to share your bug report"</string>
     <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"Tap to share your bug report"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"Tap to share your bug report without a screenshot or wait for the screenshot to finish"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"Tap to share your bug report without a screenshot or wait for the screenshot to finish"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"Bug reports contain data from the system\'s various log files, including personal and private information. Only share bug reports with apps and people that you trust."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Show this message next time"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"Bug reports"</string>
@@ -34,6 +37,7 @@
     <string name="bugreport_screenshot_failed" msgid="5853049140806834601">"Screenshot could not be taken."</string>
     <string name="bugreport_info_dialog_title" msgid="1355948594292983332">"Bug report <xliff:g id="ID">#%d</xliff:g> details"</string>
     <string name="bugreport_info_name" msgid="4414036021935139527">"Filename"</string>
-    <string name="bugreport_info_title" msgid="5599558206004371052">"Title"</string>
-    <string name="bugreport_info_description" msgid="4117088998733546784">"Detailed description"</string>
+    <string name="bugreport_info_title" msgid="2306030793918239804">"Bug title"</string>
+    <string name="bugreport_info_description" msgid="5072835127481627722">"Bug summary"</string>
+    <string name="save" msgid="4781509040564835759">"Save"</string>
 </resources>
diff --git a/packages/Shell/res/values-en-rGB/strings.xml b/packages/Shell/res/values-en-rGB/strings.xml
index ac681e2..2349ec5 100644
--- a/packages/Shell/res/values-en-rGB/strings.xml
+++ b/packages/Shell/res/values-en-rGB/strings.xml
@@ -19,10 +19,13 @@
     <string name="app_label" msgid="3701846017049540910">"Shell"</string>
     <string name="bugreport_in_progress_title" msgid="4311705936714972757">"Bug report <xliff:g id="ID">#%d</xliff:g> is being generated"</string>
     <string name="bugreport_finished_title" msgid="4429132808670114081">"Bug report <xliff:g id="ID">#%d</xliff:g> captured"</string>
+    <string name="bugreport_finished_pending_screenshot_title" msgid="5460883450679439591">"Bug report <xliff:g id="ID">#%d</xliff:g> captured but screenshot pending"</string>
     <string name="bugreport_updating_title" msgid="4423539949559634214">"Adding details to the bug report"</string>
     <string name="bugreport_updating_wait" msgid="3322151947853929470">"Please wait…"</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Swipe left to share your bug report"</string>
     <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"Tap to share your bug report"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"Tap to share your bug report without a screenshot or wait for the screenshot to finish"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"Tap to share your bug report without a screenshot or wait for the screenshot to finish"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"Bug reports contain data from the system\'s various log files, including personal and private information. Only share bug reports with apps and people that you trust."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Show this message next time"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"Bug reports"</string>
@@ -34,6 +37,7 @@
     <string name="bugreport_screenshot_failed" msgid="5853049140806834601">"Screenshot could not be taken."</string>
     <string name="bugreport_info_dialog_title" msgid="1355948594292983332">"Bug report <xliff:g id="ID">#%d</xliff:g> details"</string>
     <string name="bugreport_info_name" msgid="4414036021935139527">"Filename"</string>
-    <string name="bugreport_info_title" msgid="5599558206004371052">"Title"</string>
-    <string name="bugreport_info_description" msgid="4117088998733546784">"Detailed description"</string>
+    <string name="bugreport_info_title" msgid="2306030793918239804">"Bug title"</string>
+    <string name="bugreport_info_description" msgid="5072835127481627722">"Bug summary"</string>
+    <string name="save" msgid="4781509040564835759">"Save"</string>
 </resources>
diff --git a/packages/Shell/res/values-en-rIN/strings.xml b/packages/Shell/res/values-en-rIN/strings.xml
index ac681e2..2349ec5 100644
--- a/packages/Shell/res/values-en-rIN/strings.xml
+++ b/packages/Shell/res/values-en-rIN/strings.xml
@@ -19,10 +19,13 @@
     <string name="app_label" msgid="3701846017049540910">"Shell"</string>
     <string name="bugreport_in_progress_title" msgid="4311705936714972757">"Bug report <xliff:g id="ID">#%d</xliff:g> is being generated"</string>
     <string name="bugreport_finished_title" msgid="4429132808670114081">"Bug report <xliff:g id="ID">#%d</xliff:g> captured"</string>
+    <string name="bugreport_finished_pending_screenshot_title" msgid="5460883450679439591">"Bug report <xliff:g id="ID">#%d</xliff:g> captured but screenshot pending"</string>
     <string name="bugreport_updating_title" msgid="4423539949559634214">"Adding details to the bug report"</string>
     <string name="bugreport_updating_wait" msgid="3322151947853929470">"Please wait…"</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Swipe left to share your bug report"</string>
     <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"Tap to share your bug report"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"Tap to share your bug report without a screenshot or wait for the screenshot to finish"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"Tap to share your bug report without a screenshot or wait for the screenshot to finish"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"Bug reports contain data from the system\'s various log files, including personal and private information. Only share bug reports with apps and people that you trust."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Show this message next time"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"Bug reports"</string>
@@ -34,6 +37,7 @@
     <string name="bugreport_screenshot_failed" msgid="5853049140806834601">"Screenshot could not be taken."</string>
     <string name="bugreport_info_dialog_title" msgid="1355948594292983332">"Bug report <xliff:g id="ID">#%d</xliff:g> details"</string>
     <string name="bugreport_info_name" msgid="4414036021935139527">"Filename"</string>
-    <string name="bugreport_info_title" msgid="5599558206004371052">"Title"</string>
-    <string name="bugreport_info_description" msgid="4117088998733546784">"Detailed description"</string>
+    <string name="bugreport_info_title" msgid="2306030793918239804">"Bug title"</string>
+    <string name="bugreport_info_description" msgid="5072835127481627722">"Bug summary"</string>
+    <string name="save" msgid="4781509040564835759">"Save"</string>
 </resources>
diff --git a/packages/Shell/res/values-es-rUS/strings.xml b/packages/Shell/res/values-es-rUS/strings.xml
index 96ca14c..3f7f4d6 100644
--- a/packages/Shell/res/values-es-rUS/strings.xml
+++ b/packages/Shell/res/values-es-rUS/strings.xml
@@ -19,10 +19,16 @@
     <string name="app_label" msgid="3701846017049540910">"Shell"</string>
     <string name="bugreport_in_progress_title" msgid="4311705936714972757">"Se está generando el informe de errores <xliff:g id="ID">#%d</xliff:g>"</string>
     <string name="bugreport_finished_title" msgid="4429132808670114081">"Se capturó el informe de errores <xliff:g id="ID">#%d</xliff:g>"</string>
+    <!-- no translation found for bugreport_finished_pending_screenshot_title (5460883450679439591) -->
+    <skip />
     <string name="bugreport_updating_title" msgid="4423539949559634214">"Agregando detalles al informe de errores"</string>
     <string name="bugreport_updating_wait" msgid="3322151947853929470">"Espera…"</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Desliza el dedo hacia la izquierda para compartir el informe de errores."</string>
     <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"Toca para compartir el informe de errores"</string>
+    <!-- no translation found for bugreport_finished_pending_screenshot_text (1474435374470177193) -->
+    <skip />
+    <!-- no translation found for bugreport_finished_pending_screenshot_text (1474435374470177193) -->
+    <skip />
     <string name="bugreport_confirm" msgid="5130698467795669780">"Los informes de errores contienen datos de los distintos archivos de registro del sistema, incluida la información personal y privada. Comparte los informes de errores únicamente con aplicaciones y personas en las que confíes."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Mostrar este mensaje la próxima vez"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"Informes de errores"</string>
@@ -34,6 +40,7 @@
     <string name="bugreport_screenshot_failed" msgid="5853049140806834601">"No se pudo tomar la captura de pantalla."</string>
     <string name="bugreport_info_dialog_title" msgid="1355948594292983332">"Detalles del informe de errores <xliff:g id="ID">#%d</xliff:g>"</string>
     <string name="bugreport_info_name" msgid="4414036021935139527">"Nombre del archivo"</string>
-    <string name="bugreport_info_title" msgid="5599558206004371052">"Título"</string>
-    <string name="bugreport_info_description" msgid="4117088998733546784">"Descripción completa"</string>
+    <string name="bugreport_info_title" msgid="2306030793918239804">"Título del error"</string>
+    <string name="bugreport_info_description" msgid="5072835127481627722">"Resumen del error"</string>
+    <string name="save" msgid="4781509040564835759">"Guardar"</string>
 </resources>
diff --git a/packages/Shell/res/values-es/strings.xml b/packages/Shell/res/values-es/strings.xml
index 00874c6..68abf83 100644
--- a/packages/Shell/res/values-es/strings.xml
+++ b/packages/Shell/res/values-es/strings.xml
@@ -19,10 +19,13 @@
     <string name="app_label" msgid="3701846017049540910">"Shell"</string>
     <string name="bugreport_in_progress_title" msgid="4311705936714972757">"Se está generando el informe de errores <xliff:g id="ID">#%d</xliff:g>"</string>
     <string name="bugreport_finished_title" msgid="4429132808670114081">"Informe de errores <xliff:g id="ID">#%d</xliff:g> capturado"</string>
+    <string name="bugreport_finished_pending_screenshot_title" msgid="5460883450679439591">"Informe de errores <xliff:g id="ID">#%d</xliff:g> capturado (captura pendiente)"</string>
     <string name="bugreport_updating_title" msgid="4423539949559634214">"Añadiendo detalles al informe de errores"</string>
     <string name="bugreport_updating_wait" msgid="3322151947853929470">"Espera…"</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Desliza el dedo hacia la izquierda para compartir el informe de error"</string>
     <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"Toca para compartir el informe de errores"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"Toca para compartir informe de errores sin captura de pantalla o espera a que se haga la captura."</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"Toca para compartir informe de errores sin captura de pantalla o espera a que se haga la captura."</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"Los informes de errores contienen datos de los distintos archivos de registro del sistema, incluida información personal y privada. Comparte los informes de errores únicamente con aplicaciones y usuarios en los que confíes."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Mostrar este mensaje la próxima vez"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"Informes de error"</string>
@@ -34,6 +37,7 @@
     <string name="bugreport_screenshot_failed" msgid="5853049140806834601">"No se puede realizar la captura de pantalla."</string>
     <string name="bugreport_info_dialog_title" msgid="1355948594292983332">"Detalles del informe de errores <xliff:g id="ID">#%d</xliff:g>"</string>
     <string name="bugreport_info_name" msgid="4414036021935139527">"Nombre de archivo"</string>
-    <string name="bugreport_info_title" msgid="5599558206004371052">"Título"</string>
-    <string name="bugreport_info_description" msgid="4117088998733546784">"Descripción completa"</string>
+    <string name="bugreport_info_title" msgid="2306030793918239804">"Nombre del informe de errores"</string>
+    <string name="bugreport_info_description" msgid="5072835127481627722">"Resumen del informe de errores"</string>
+    <string name="save" msgid="4781509040564835759">"Guardar"</string>
 </resources>
diff --git a/packages/Shell/res/values-et-rEE/strings.xml b/packages/Shell/res/values-et-rEE/strings.xml
index bc469bc..028e2bd 100644
--- a/packages/Shell/res/values-et-rEE/strings.xml
+++ b/packages/Shell/res/values-et-rEE/strings.xml
@@ -19,10 +19,13 @@
     <string name="app_label" msgid="3701846017049540910">"Kest"</string>
     <string name="bugreport_in_progress_title" msgid="4311705936714972757">"Luuakse veaaruannet <xliff:g id="ID">#%d</xliff:g>"</string>
     <string name="bugreport_finished_title" msgid="4429132808670114081">"Jäädvustati veaaruanne <xliff:g id="ID">#%d</xliff:g>"</string>
+    <string name="bugreport_finished_pending_screenshot_title" msgid="5460883450679439591">"Jäädvustati veaaruanne <xliff:g id="ID">#%d</xliff:g>, kuid ekraanipilt on ootel"</string>
     <string name="bugreport_updating_title" msgid="4423539949559634214">"Üksikasjade lisamine veaaruandesse"</string>
     <string name="bugreport_updating_wait" msgid="3322151947853929470">"Oodake …"</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Veaaruande jagamiseks pühkige vasakule"</string>
     <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"Veaaruande jagamiseks puudutage"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"Puudutage, et veaaruannet ilma ekraanipildita jagada, või oodake, kuni ekraanipilt tehtud saab."</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"Puudutage, et veaaruannet ilma ekraanipildita jagada, või oodake, kuni ekraanipilt tehtud saab."</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"Veaaruanded sisaldavad andmeid erinevatest süsteemi logifailidest, sh isiklikku ja privaatset teavet. Jagage veaaruandeid ainult usaldusväärsete rakenduste ja inimestega."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Kuva see sõnum järgmisel korral"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"Veaaruanded"</string>
@@ -34,6 +37,7 @@
     <string name="bugreport_screenshot_failed" msgid="5853049140806834601">"Ekraanipilti ei saanud teha."</string>
     <string name="bugreport_info_dialog_title" msgid="1355948594292983332">"Veaaruande <xliff:g id="ID">#%d</xliff:g> üksikasjad"</string>
     <string name="bugreport_info_name" msgid="4414036021935139527">"Faili nimi"</string>
-    <string name="bugreport_info_title" msgid="5599558206004371052">"Pealkiri"</string>
-    <string name="bugreport_info_description" msgid="4117088998733546784">"Üksikasjalik kirjeldus"</string>
+    <string name="bugreport_info_title" msgid="2306030793918239804">"Vea pealkiri"</string>
+    <string name="bugreport_info_description" msgid="5072835127481627722">"Vea kokkuvõte"</string>
+    <string name="save" msgid="4781509040564835759">"Salvesta"</string>
 </resources>
diff --git a/packages/Shell/res/values-eu-rES/strings.xml b/packages/Shell/res/values-eu-rES/strings.xml
index 614f17e..8f4d219 100644
--- a/packages/Shell/res/values-eu-rES/strings.xml
+++ b/packages/Shell/res/values-eu-rES/strings.xml
@@ -19,10 +19,16 @@
     <string name="app_label" msgid="3701846017049540910">"Shell-interfazea"</string>
     <string name="bugreport_in_progress_title" msgid="4311705936714972757">"Akatsen <xliff:g id="ID">#%d</xliff:g> txostena egiten ari gara"</string>
     <string name="bugreport_finished_title" msgid="4429132808670114081">"Akatsen <xliff:g id="ID">#%d</xliff:g> txostena egin da"</string>
+    <!-- no translation found for bugreport_finished_pending_screenshot_title (5460883450679439591) -->
+    <skip />
     <string name="bugreport_updating_title" msgid="4423539949559634214">"Akatsen txostenean xehetasunak gehitzen"</string>
     <string name="bugreport_updating_wait" msgid="3322151947853929470">"Itxaron, mesedez…"</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Programa-akatsen txostena partekatzeko, pasatu hatza ezkerrera"</string>
     <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"Sakatu akatsen txostena partekatzeko"</string>
+    <!-- no translation found for bugreport_finished_pending_screenshot_text (1474435374470177193) -->
+    <skip />
+    <!-- no translation found for bugreport_finished_pending_screenshot_text (1474435374470177193) -->
+    <skip />
     <string name="bugreport_confirm" msgid="5130698467795669780">"Akatsen txostenek sistemaren erregistro-fitxategietako datuak dauzkate, informazio pertsonala eta pribatua barne. Akatsen txostenak partekatzen badituzu, partekatu soilik aplikazio eta pertsona fidagarriekin."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Erakutsi mezu hau hurrengoan"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"Akatsen txostenak"</string>
@@ -34,6 +40,7 @@
     <string name="bugreport_screenshot_failed" msgid="5853049140806834601">"Ezin izan da atera pantaila-argazkia."</string>
     <string name="bugreport_info_dialog_title" msgid="1355948594292983332">"Akatsen <xliff:g id="ID">#%d</xliff:g> txostenaren xehetasunak"</string>
     <string name="bugreport_info_name" msgid="4414036021935139527">"Fitxategi-izena"</string>
-    <string name="bugreport_info_title" msgid="5599558206004371052">"Izena"</string>
-    <string name="bugreport_info_description" msgid="4117088998733546784">"Azalpen xehatua"</string>
+    <string name="bugreport_info_title" msgid="2306030793918239804">"Akatsaren izena"</string>
+    <string name="bugreport_info_description" msgid="5072835127481627722">"Akatsaren laburpena"</string>
+    <string name="save" msgid="4781509040564835759">"Gorde"</string>
 </resources>
diff --git a/packages/Shell/res/values-fa/strings.xml b/packages/Shell/res/values-fa/strings.xml
index ab00562..c0f4d2a 100644
--- a/packages/Shell/res/values-fa/strings.xml
+++ b/packages/Shell/res/values-fa/strings.xml
@@ -19,10 +19,16 @@
     <string name="app_label" msgid="3701846017049540910">"Shell"</string>
     <string name="bugreport_in_progress_title" msgid="4311705936714972757">"گزارش اشکال <xliff:g id="ID">#%d</xliff:g> در حال ایجاد شدن است"</string>
     <string name="bugreport_finished_title" msgid="4429132808670114081">"گزارش اشکال <xliff:g id="ID">#%d</xliff:g> ثبت شد"</string>
+    <!-- no translation found for bugreport_finished_pending_screenshot_title (5460883450679439591) -->
+    <skip />
     <string name="bugreport_updating_title" msgid="4423539949559634214">"اضافه کردن جزئیات به گزارش اشکال"</string>
     <string name="bugreport_updating_wait" msgid="3322151947853929470">"لطفاً منتظر بمانید..."</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"برای اشتراک‌گذاری گزارش اشکال، به تندی آن را به چپ بکشید"</string>
     <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"برای به اشتراک گذاشتن گزارش اشکال، ضربه بزنید"</string>
+    <!-- no translation found for bugreport_finished_pending_screenshot_text (1474435374470177193) -->
+    <skip />
+    <!-- no translation found for bugreport_finished_pending_screenshot_text (1474435374470177193) -->
+    <skip />
     <string name="bugreport_confirm" msgid="5130698467795669780">"گزارش‌های اشکال حاوی داده‌هایی از فایل‌های گزارش مختلف در سیستم هستند، شامل اطلاعات شخصی و خصوصی. گزارش‌های اشکال را فقط با افراد و برنامه‌های مورد اعتماد خود به اشتراک بگذارید."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"دفعه بعد این پیام نشان داده شود"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"گزارش اشکال"</string>
@@ -34,6 +40,7 @@
     <string name="bugreport_screenshot_failed" msgid="5853049140806834601">"نمی‌توان عکس صفحه‌نمایش گرفت."</string>
     <string name="bugreport_info_dialog_title" msgid="1355948594292983332">"جزئیات گزارش اشکال <xliff:g id="ID">#%d</xliff:g>"</string>
     <string name="bugreport_info_name" msgid="4414036021935139527">"نام فایل"</string>
-    <string name="bugreport_info_title" msgid="5599558206004371052">"عنوان"</string>
-    <string name="bugreport_info_description" msgid="4117088998733546784">"جزئیات دقیق"</string>
+    <string name="bugreport_info_title" msgid="2306030793918239804">"عنوان اشکال"</string>
+    <string name="bugreport_info_description" msgid="5072835127481627722">"خلاصه اشکال"</string>
+    <string name="save" msgid="4781509040564835759">"ذخیره کردن"</string>
 </resources>
diff --git a/packages/Shell/res/values-fi/strings.xml b/packages/Shell/res/values-fi/strings.xml
index be7aabd..64245aa 100644
--- a/packages/Shell/res/values-fi/strings.xml
+++ b/packages/Shell/res/values-fi/strings.xml
@@ -19,10 +19,16 @@
     <string name="app_label" msgid="3701846017049540910">"Komentotulkki"</string>
     <string name="bugreport_in_progress_title" msgid="4311705936714972757">"Luodaan virheraporttia <xliff:g id="ID">#%d</xliff:g>."</string>
     <string name="bugreport_finished_title" msgid="4429132808670114081">"Virheraportti <xliff:g id="ID">#%d</xliff:g> tallennettu"</string>
+    <!-- no translation found for bugreport_finished_pending_screenshot_title (5460883450679439591) -->
+    <skip />
     <string name="bugreport_updating_title" msgid="4423539949559634214">"Lisätään tietoja virheraporttiin"</string>
     <string name="bugreport_updating_wait" msgid="3322151947853929470">"Odota…"</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Jaa virheraportti pyyhkäisemällä vasemmalle"</string>
     <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"Jaa virheraportti napauttamalla."</string>
+    <!-- no translation found for bugreport_finished_pending_screenshot_text (1474435374470177193) -->
+    <skip />
+    <!-- no translation found for bugreport_finished_pending_screenshot_text (1474435374470177193) -->
+    <skip />
     <string name="bugreport_confirm" msgid="5130698467795669780">"Virheraportit sisältävät järjestelmän lokitietoja, ja niihin voi sisältyä henkilökohtaisia ja yksityisiä tietoja. Jaa virheraportteja vain luotettaville sovelluksille ja käyttäjille."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Näytä tämä viesti seuraavalla kerralla"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"Virheraportit"</string>
@@ -34,6 +40,7 @@
     <string name="bugreport_screenshot_failed" msgid="5853049140806834601">"Kuvakaappauksen tallentaminen epäonnistui."</string>
     <string name="bugreport_info_dialog_title" msgid="1355948594292983332">"Virheraportin <xliff:g id="ID">#%d</xliff:g> tiedot"</string>
     <string name="bugreport_info_name" msgid="4414036021935139527">"Tiedostonimi"</string>
-    <string name="bugreport_info_title" msgid="5599558206004371052">"Otsikko"</string>
-    <string name="bugreport_info_description" msgid="4117088998733546784">"Yksityiskohtainen kuvaus"</string>
+    <string name="bugreport_info_title" msgid="2306030793918239804">"Virheen nimi"</string>
+    <string name="bugreport_info_description" msgid="5072835127481627722">"Virheen yhteenveto"</string>
+    <string name="save" msgid="4781509040564835759">"Tallenna"</string>
 </resources>
diff --git a/packages/Shell/res/values-fr-rCA/strings.xml b/packages/Shell/res/values-fr-rCA/strings.xml
index 7d9f97d..9575273 100644
--- a/packages/Shell/res/values-fr-rCA/strings.xml
+++ b/packages/Shell/res/values-fr-rCA/strings.xml
@@ -19,10 +19,16 @@
     <string name="app_label" msgid="3701846017049540910">"Shell"</string>
     <string name="bugreport_in_progress_title" msgid="4311705936714972757">"Rapport de bogue <xliff:g id="ID">#%d</xliff:g> généré"</string>
     <string name="bugreport_finished_title" msgid="4429132808670114081">"Rapport de bogue <xliff:g id="ID">#%d</xliff:g> enregistré"</string>
+    <!-- no translation found for bugreport_finished_pending_screenshot_title (5460883450679439591) -->
+    <skip />
     <string name="bugreport_updating_title" msgid="4423539949559634214">"Ajout de détails au rapport de bogue"</string>
     <string name="bugreport_updating_wait" msgid="3322151947853929470">"Veuillez patienter…"</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Faites glisser le doigt vers la gauche pour partager votre rapport de bogue."</string>
     <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"Touchez ici pour partager votre rapport de bogue"</string>
+    <!-- no translation found for bugreport_finished_pending_screenshot_text (1474435374470177193) -->
+    <skip />
+    <!-- no translation found for bugreport_finished_pending_screenshot_text (1474435374470177193) -->
+    <skip />
     <string name="bugreport_confirm" msgid="5130698467795669780">"Les rapports de bogue contiennent des données des fichiers journaux du système, y compris des informations personnelles et privées. Ne partagez les rapports de bogue qu\'avec les applications et les personnes que vous estimez fiables."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Afficher ce message la prochaine fois"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"Rapports de bogues"</string>
@@ -34,6 +40,7 @@
     <string name="bugreport_screenshot_failed" msgid="5853049140806834601">"Une erreur s\'est produite lors de la saisie d\'écran."</string>
     <string name="bugreport_info_dialog_title" msgid="1355948594292983332">"Détails du rapport de bogue <xliff:g id="ID">#%d</xliff:g>"</string>
     <string name="bugreport_info_name" msgid="4414036021935139527">"Nom de fichier"</string>
-    <string name="bugreport_info_title" msgid="5599558206004371052">"Titre"</string>
-    <string name="bugreport_info_description" msgid="4117088998733546784">"Description détaillée"</string>
+    <string name="bugreport_info_title" msgid="2306030793918239804">"Titre du bogue"</string>
+    <string name="bugreport_info_description" msgid="5072835127481627722">"Sommaire des bogues"</string>
+    <string name="save" msgid="4781509040564835759">"Enregistrer"</string>
 </resources>
diff --git a/packages/Shell/res/values-fr/strings.xml b/packages/Shell/res/values-fr/strings.xml
index 74025d9..83d30e6 100644
--- a/packages/Shell/res/values-fr/strings.xml
+++ b/packages/Shell/res/values-fr/strings.xml
@@ -19,10 +19,16 @@
     <string name="app_label" msgid="3701846017049540910">"Shell"</string>
     <string name="bugreport_in_progress_title" msgid="4311705936714972757">"Le rapport de bug \"<xliff:g id="ID">#%d</xliff:g>\" est en cours de création"</string>
     <string name="bugreport_finished_title" msgid="4429132808670114081">"Le rapport de bug \"<xliff:g id="ID">#%d</xliff:g>\" a bien été enregistré"</string>
+    <!-- no translation found for bugreport_finished_pending_screenshot_title (5460883450679439591) -->
+    <skip />
     <string name="bugreport_updating_title" msgid="4423539949559634214">"Ajout d\'informations au rapport de bug"</string>
     <string name="bugreport_updating_wait" msgid="3322151947853929470">"Veuillez patienter…"</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Faites glisser le doigt vers la gauche pour partager votre rapport d\'erreur."</string>
     <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"Appuyer pour partager votre rapport de bug"</string>
+    <!-- no translation found for bugreport_finished_pending_screenshot_text (1474435374470177193) -->
+    <skip />
+    <!-- no translation found for bugreport_finished_pending_screenshot_text (1474435374470177193) -->
+    <skip />
     <string name="bugreport_confirm" msgid="5130698467795669780">"Les rapports de bug contiennent des données des fichiers journaux du système, y compris des informations personnelles et privées. Ne partagez les rapports de bug qu\'avec les applications et les personnes que vous estimez fiables."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Afficher ce message la prochaine fois"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"Rapports d\'erreur"</string>
@@ -34,6 +40,7 @@
     <string name="bugreport_screenshot_failed" msgid="5853049140806834601">"Impossible d\'effectuer une capture d\'écran."</string>
     <string name="bugreport_info_dialog_title" msgid="1355948594292983332">"Informations sur le rapport de bug \"<xliff:g id="ID">#%d</xliff:g>\""</string>
     <string name="bugreport_info_name" msgid="4414036021935139527">"Nom de fichier"</string>
-    <string name="bugreport_info_title" msgid="5599558206004371052">"Titre"</string>
-    <string name="bugreport_info_description" msgid="4117088998733546784">"Description détaillée"</string>
+    <string name="bugreport_info_title" msgid="2306030793918239804">"Titre du bug"</string>
+    <string name="bugreport_info_description" msgid="5072835127481627722">"Résumé du bug"</string>
+    <string name="save" msgid="4781509040564835759">"Enregistrer"</string>
 </resources>
diff --git a/packages/Shell/res/values-gl-rES/strings.xml b/packages/Shell/res/values-gl-rES/strings.xml
index d3be7c5..e462cee 100644
--- a/packages/Shell/res/values-gl-rES/strings.xml
+++ b/packages/Shell/res/values-gl-rES/strings.xml
@@ -19,10 +19,13 @@
     <string name="app_label" msgid="3701846017049540910">"Shell"</string>
     <string name="bugreport_in_progress_title" msgid="4311705936714972757">"Estase xerando o informe de erros <xliff:g id="ID">#%d</xliff:g>"</string>
     <string name="bugreport_finished_title" msgid="4429132808670114081">"Rexistrouse o informe de erros <xliff:g id="ID">#%d</xliff:g>"</string>
+    <string name="bugreport_finished_pending_screenshot_title" msgid="5460883450679439591">"Inf. erros rexistrado <xliff:g id="ID">#%d</xliff:g> e captura pantalla pendente"</string>
     <string name="bugreport_updating_title" msgid="4423539949559634214">"Engadindo detalles ao informe de erro"</string>
     <string name="bugreport_updating_wait" msgid="3322151947853929470">"Agarda..."</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Pasa o dedo á esquerda para compartir o teu informe de erros"</string>
     <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"Toca para compartir o teu informe de erros"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"Toca para compartir o informe de erros sen captura de pantalla ou agarda a que finalice a captura"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"Toca para compartir o informe de erros sen captura de pantalla ou agarda a que finalice a captura"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"Os informes de erros conteñen datos dos distintos ficheiros de rexistro do sistema, incluída información persoal e privada. Comparte os informes de erros unicamente con aplicacións e persoas de confianza."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Mostrar esta mensaxe a próxima vez"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"Informes de erros"</string>
@@ -34,6 +37,7 @@
     <string name="bugreport_screenshot_failed" msgid="5853049140806834601">"Non se puido realizar a captura de pantalla."</string>
     <string name="bugreport_info_dialog_title" msgid="1355948594292983332">"Detalles do informe de erros <xliff:g id="ID">#%d</xliff:g>"</string>
     <string name="bugreport_info_name" msgid="4414036021935139527">"Nome do ficheiro"</string>
-    <string name="bugreport_info_title" msgid="5599558206004371052">"Título"</string>
-    <string name="bugreport_info_description" msgid="4117088998733546784">"Descrición detallada"</string>
+    <string name="bugreport_info_title" msgid="2306030793918239804">"Título do informe de erros"</string>
+    <string name="bugreport_info_description" msgid="5072835127481627722">"Resumo do informe de erros"</string>
+    <string name="save" msgid="4781509040564835759">"Gardar"</string>
 </resources>
diff --git a/packages/Shell/res/values-gu-rIN/strings.xml b/packages/Shell/res/values-gu-rIN/strings.xml
index 45df7b3..f99167d 100644
--- a/packages/Shell/res/values-gu-rIN/strings.xml
+++ b/packages/Shell/res/values-gu-rIN/strings.xml
@@ -19,10 +19,13 @@
     <string name="app_label" msgid="3701846017049540910">"શેલ"</string>
     <string name="bugreport_in_progress_title" msgid="4311705936714972757">"બગ રિપોર્ટ <xliff:g id="ID">#%d</xliff:g> જનરેટ કરવામાં આવી રહી છે"</string>
     <string name="bugreport_finished_title" msgid="4429132808670114081">"બગ રિપોર્ટ <xliff:g id="ID">#%d</xliff:g> કૅપ્ચર કરી"</string>
+    <string name="bugreport_finished_pending_screenshot_title" msgid="5460883450679439591">"બગ રિપોર્ટ <xliff:g id="ID">#%d</xliff:g> કૅપ્ચર કરી પરંતુ સ્ક્રીનશૉટ બાકી છે"</string>
     <string name="bugreport_updating_title" msgid="4423539949559634214">"બગ રિપોર્ટમાં વિગતો ઉમેરવી"</string>
     <string name="bugreport_updating_wait" msgid="3322151947853929470">"કૃપા કરીને રાહ જુઓ…"</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"તમારી બગ રિપોર્ટ શેર કરવા માટે ડાબે સ્વાઇપ કરો"</string>
     <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"તમારી બગ રિપોર્ટ શેર કરવા ટૅપ કરો"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"સ્ક્રીનશૉટ વગર અથવા સ્ક્રીનશૉટ સમાપ્ત થવાની રાહ જોયા વગર તમારી બગ રિપોર્ટ શેર કરવા ટૅપ કરો"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"સ્ક્રીનશૉટ વગર અથવા સ્ક્રીનશૉટ સમાપ્ત થવાની રાહ જોયા વગર તમારી બગ રિપોર્ટ શેર કરવા ટૅપ કરો"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"બગ રિપોર્ટ્સ વ્યક્તિગત અને ખાનગી માહિતી સહિત, સિસ્ટમની વિભિન્ન લૉગ ફાઇલોનો ડેટા ધરાવે છે. બગ રિપોર્ટ્સ ફક્ત તમે વિશ્વાસ કરતા હો તે એપ્લિકેશનો અને લોકો સાથે જ શેર કરો."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"આગલી વખતે આ સંદેશ બતાવો"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"બગ રિપોર્ટ્સ"</string>
@@ -34,6 +37,7 @@
     <string name="bugreport_screenshot_failed" msgid="5853049140806834601">"સ્ક્રીનશોટ લઇ શકાયો નથી."</string>
     <string name="bugreport_info_dialog_title" msgid="1355948594292983332">"બગ રિપોર્ટ <xliff:g id="ID">#%d</xliff:g> ની વિગતો"</string>
     <string name="bugreport_info_name" msgid="4414036021935139527">"ફાઇલનું નામ"</string>
-    <string name="bugreport_info_title" msgid="5599558206004371052">"શીર્ષક"</string>
-    <string name="bugreport_info_description" msgid="4117088998733546784">"વિગતવાર વર્ણન"</string>
+    <string name="bugreport_info_title" msgid="2306030793918239804">"બગનું શીર્ષક"</string>
+    <string name="bugreport_info_description" msgid="5072835127481627722">"બગનો સારાંશ"</string>
+    <string name="save" msgid="4781509040564835759">"સાચવો"</string>
 </resources>
diff --git a/packages/Shell/res/values-hi/strings.xml b/packages/Shell/res/values-hi/strings.xml
index 8858bc3..aedec04 100644
--- a/packages/Shell/res/values-hi/strings.xml
+++ b/packages/Shell/res/values-hi/strings.xml
@@ -19,10 +19,13 @@
     <string name="app_label" msgid="3701846017049540910">"शेल"</string>
     <string name="bugreport_in_progress_title" msgid="4311705936714972757">"बग रिपोर्ट <xliff:g id="ID">#%d</xliff:g> जेनरेट की जा रही है"</string>
     <string name="bugreport_finished_title" msgid="4429132808670114081">"बग रिपोर्ट <xliff:g id="ID">#%d</xliff:g> कैप्चर की गई"</string>
+    <string name="bugreport_finished_pending_screenshot_title" msgid="5460883450679439591">"बग रिपोर्ट <xliff:g id="ID">#%d</xliff:g> कैप्चर की गई लेकिन स्क्रीनशॉट लंबित है"</string>
     <string name="bugreport_updating_title" msgid="4423539949559634214">"बग रिपोर्ट में विवरण जोड़े जा रहे हैं"</string>
     <string name="bugreport_updating_wait" msgid="3322151947853929470">"कृपया प्रतीक्षा करें…"</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"अपनी बग रिपोर्ट साझा करने के लिए बाएं स्वाइप करें"</string>
     <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"अपनी बग रिपोर्ट साझा करने के लिए टैप करें"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"अपनी बग रिपोर्ट को बिना स्क्रीनशॉट साझा करने हेतु टैप करें या स्क्रीनशॉट पूरा होने की प्रतीक्षा करें"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"अपनी बग रिपोर्ट को बिना स्क्रीनशॉट साझा करने हेतु टैप करें या स्क्रीनशॉट पूरा होने की प्रतीक्षा करें"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"बग रिपोर्ट में व्यक्तिगत और निजी जानकारी सहित, सिस्टम की विभिन्न लॉग फ़ाइलों का डेटा होता है. बग रिपोर्ट केवल विश्वसनीय ऐप्स  और व्यक्तियों से ही साझा करें."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"यह संदेश अगली बार दिखाएं"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"बग रिपोर्ट"</string>
@@ -34,6 +37,7 @@
     <string name="bugreport_screenshot_failed" msgid="5853049140806834601">"स्क्रीनशॉट नहीं लिया जा सका."</string>
     <string name="bugreport_info_dialog_title" msgid="1355948594292983332">"बग रिपोर्ट <xliff:g id="ID">#%d</xliff:g> के विवरण"</string>
     <string name="bugreport_info_name" msgid="4414036021935139527">"फ़ाइल नाम"</string>
-    <string name="bugreport_info_title" msgid="5599558206004371052">"शीर्षक"</string>
-    <string name="bugreport_info_description" msgid="4117088998733546784">"विस्तृत वर्णन"</string>
+    <string name="bugreport_info_title" msgid="2306030793918239804">"बग शीर्षक"</string>
+    <string name="bugreport_info_description" msgid="5072835127481627722">"बग सारांश"</string>
+    <string name="save" msgid="4781509040564835759">"सहेजें"</string>
 </resources>
diff --git a/packages/Shell/res/values-hr/strings.xml b/packages/Shell/res/values-hr/strings.xml
index cb03f9c..462eb2a1 100644
--- a/packages/Shell/res/values-hr/strings.xml
+++ b/packages/Shell/res/values-hr/strings.xml
@@ -19,10 +19,13 @@
     <string name="app_label" msgid="3701846017049540910">"Ljuska"</string>
     <string name="bugreport_in_progress_title" msgid="4311705936714972757">"Generira se izvješće o programskoj pogrešci <xliff:g id="ID">#%d</xliff:g>"</string>
     <string name="bugreport_finished_title" msgid="4429132808670114081">"Izvješće o programskoj pogrešci <xliff:g id="ID">#%d</xliff:g> snimljeno"</string>
+    <string name="bugreport_finished_pending_screenshot_title" msgid="5460883450679439591">"Izvješće o pogrešci <xliff:g id="ID">#%d</xliff:g> snimljeno, ali se čeka snimka"</string>
     <string name="bugreport_updating_title" msgid="4423539949559634214">"Dodavanje pojedinosti u izvješće o progr. pogrešci"</string>
     <string name="bugreport_updating_wait" msgid="3322151947853929470">"Pričekajte..."</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Prijeđite prstom ulijevo da biste poslali izvješće o programskim pogreškama"</string>
     <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"Dodirnite da biste podijelili izvješće o programskoj pogrešci"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"Dodirnite za dijeljenje izvješća o pogrešci bez snimke zaslona ili pričekajte da se izradi snimka"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"Dodirnite za dijeljenje izvješća o pogrešci bez snimke zaslona ili pričekajte da se izradi snimka"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"Prijave programskih pogrešaka sadržavaju podatke iz različitih datoteka zapisnika sustava, uključujući osobne i privatne informacije. Prijave programskih pogrešaka dijelite samo s aplikacijama i osobama koje smatrate pouzdanima."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Prikaži tu poruku sljedeći put"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"Izvj. o prog. pogreš."</string>
@@ -34,6 +37,7 @@
     <string name="bugreport_screenshot_failed" msgid="5853049140806834601">"Snimanje zaslona nije uspjelo."</string>
     <string name="bugreport_info_dialog_title" msgid="1355948594292983332">"Pojedinosti izvješća o programskoj pogrešci <xliff:g id="ID">#%d</xliff:g>"</string>
     <string name="bugreport_info_name" msgid="4414036021935139527">"Naziv datoteke"</string>
-    <string name="bugreport_info_title" msgid="5599558206004371052">"Naslov"</string>
-    <string name="bugreport_info_description" msgid="4117088998733546784">"Detaljan opis"</string>
+    <string name="bugreport_info_title" msgid="2306030793918239804">"Naslov izvješća o programskoj pogrešci"</string>
+    <string name="bugreport_info_description" msgid="5072835127481627722">"Sažetak izvješća o programskoj pogrešci"</string>
+    <string name="save" msgid="4781509040564835759">"Spremi"</string>
 </resources>
diff --git a/packages/Shell/res/values-hu/strings.xml b/packages/Shell/res/values-hu/strings.xml
index 390cd2f..1f7f1fa 100644
--- a/packages/Shell/res/values-hu/strings.xml
+++ b/packages/Shell/res/values-hu/strings.xml
@@ -19,10 +19,13 @@
     <string name="app_label" msgid="3701846017049540910">"Héj"</string>
     <string name="bugreport_in_progress_title" msgid="4311705936714972757">"Hibajelentés (<xliff:g id="ID">#%d</xliff:g>) létrehozása folyamatban"</string>
     <string name="bugreport_finished_title" msgid="4429132808670114081">"Hibajelentés (<xliff:g id="ID">#%d</xliff:g>) rögzítve"</string>
+    <string name="bugreport_finished_pending_screenshot_title" msgid="5460883450679439591">"Hibajelentés (<xliff:g id="ID">#%d</xliff:g>) rögzítve – képernyőkép függőben"</string>
     <string name="bugreport_updating_title" msgid="4423539949559634214">"Információk hozzáadása a hibajelentéshez"</string>
     <string name="bugreport_updating_wait" msgid="3322151947853929470">"Kérjük, várjon..."</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Húzza ujját balra a hibajelentés megosztásához"</string>
     <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"Koppintson a hibajelentés megosztásához"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"Koppintson ide, ha képernyőkép nélkül osztaná meg a hibajelentést, vagy várjon a képernyőképre."</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"Koppintson ide, ha képernyőkép nélkül osztaná meg a hibajelentést, vagy várjon a képernyőképre."</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"A programhiba-jelentések a rendszer különféle naplófájljaiból származó adatokat tartalmaznak, köztük személyes és magánjellegű információkat is. Csak olyan alkalmazásokkal és személyekkel osszon meg programhiba-jelentéseket, amelyekben vagy akikben megbízik."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Üzenet mutatása legközelebb"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"Hibajelentések"</string>
@@ -34,6 +37,7 @@
     <string name="bugreport_screenshot_failed" msgid="5853049140806834601">"Nem sikerült elkészíteni a képernyőképet."</string>
     <string name="bugreport_info_dialog_title" msgid="1355948594292983332">"Hibajelentés (<xliff:g id="ID">#%d</xliff:g>) részletei"</string>
     <string name="bugreport_info_name" msgid="4414036021935139527">"Fájlnév"</string>
-    <string name="bugreport_info_title" msgid="5599558206004371052">"Név"</string>
-    <string name="bugreport_info_description" msgid="4117088998733546784">"Részletes leírás"</string>
+    <string name="bugreport_info_title" msgid="2306030793918239804">"Hibajelentés címe"</string>
+    <string name="bugreport_info_description" msgid="5072835127481627722">"Hibajelentés összefoglalója"</string>
+    <string name="save" msgid="4781509040564835759">"Mentés"</string>
 </resources>
diff --git a/packages/Shell/res/values-hy-rAM/strings.xml b/packages/Shell/res/values-hy-rAM/strings.xml
index 68478ab..3cfe2f7 100644
--- a/packages/Shell/res/values-hy-rAM/strings.xml
+++ b/packages/Shell/res/values-hy-rAM/strings.xml
@@ -19,10 +19,16 @@
     <string name="app_label" msgid="3701846017049540910">"Խեցի"</string>
     <string name="bugreport_in_progress_title" msgid="4311705936714972757">"<xliff:g id="ID">#%d</xliff:g> վրիպակի զեկույցը ստեղծվում է"</string>
     <string name="bugreport_finished_title" msgid="4429132808670114081">"<xliff:g id="ID">#%d</xliff:g> վրիպակի զեկույցը գրանցվեց"</string>
+    <!-- no translation found for bugreport_finished_pending_screenshot_title (5460883450679439591) -->
+    <skip />
     <string name="bugreport_updating_title" msgid="4423539949559634214">"Տվյալների ավելացում վրիպակի զեկույցում"</string>
     <string name="bugreport_updating_wait" msgid="3322151947853929470">"Խնդրում ենք սպասել…"</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Սահեցրեք ձախ՝ սխալի հաշվետվությունը համօգտագործելու համար"</string>
     <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"Հպեք՝ վրիպակի զեկույցը տրամադրելու համար"</string>
+    <!-- no translation found for bugreport_finished_pending_screenshot_text (1474435374470177193) -->
+    <skip />
+    <!-- no translation found for bugreport_finished_pending_screenshot_text (1474435374470177193) -->
+    <skip />
     <string name="bugreport_confirm" msgid="5130698467795669780">"Վրիպակի զեկույցները պարունակում են տվյալներ համակարգի տարբեր մուտքի ֆայլերից, այդ թվում նաև անհատական ​​և գաղտնի տեղեկություններ: Վրիպակի զեկույցները կիսեք միայն այն հավելվածների և մարդկանց հետ, որոնց վստահում եք:"</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Այս հաղորդագրությունը ցույց տալ հաջորդ անգամ"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"Վրիպակների հաշվետվություններ"</string>
@@ -34,6 +40,7 @@
     <string name="bugreport_screenshot_failed" msgid="5853049140806834601">"Չհաջողվեց ստանալ էկրանի պատկերը:"</string>
     <string name="bugreport_info_dialog_title" msgid="1355948594292983332">"<xliff:g id="ID">#%d</xliff:g> վրիպակի զեկույցի մանրամասները"</string>
     <string name="bugreport_info_name" msgid="4414036021935139527">"Ֆայլի անունը"</string>
-    <string name="bugreport_info_title" msgid="5599558206004371052">"Անվանումը"</string>
-    <string name="bugreport_info_description" msgid="4117088998733546784">"Մանրամասն նկարագրություն"</string>
+    <string name="bugreport_info_title" msgid="2306030793918239804">"Վրիպակի զեկույցի վերնագիրը"</string>
+    <string name="bugreport_info_description" msgid="5072835127481627722">"Վրիպակի զեկույցի ամփոփագիրը"</string>
+    <string name="save" msgid="4781509040564835759">"Պահել"</string>
 </resources>
diff --git a/packages/Shell/res/values-in/strings.xml b/packages/Shell/res/values-in/strings.xml
index 4416fc7..4bca166 100644
--- a/packages/Shell/res/values-in/strings.xml
+++ b/packages/Shell/res/values-in/strings.xml
@@ -19,10 +19,13 @@
     <string name="app_label" msgid="3701846017049540910">"Kerangka"</string>
     <string name="bugreport_in_progress_title" msgid="4311705936714972757">"Laporan bug <xliff:g id="ID">#%d</xliff:g> sedang dibuat"</string>
     <string name="bugreport_finished_title" msgid="4429132808670114081">"Laporan bug <xliff:g id="ID">#%d</xliff:g> dijepret"</string>
+    <string name="bugreport_finished_pending_screenshot_title" msgid="5460883450679439591">"Laporan bug <xliff:g id="ID">#%d</xliff:g> dijepret, tetapi tangkapan layar belum selesai"</string>
     <string name="bugreport_updating_title" msgid="4423539949559634214">"Menambahkan detail ke laporan bug"</string>
     <string name="bugreport_updating_wait" msgid="3322151947853929470">"Harap tunggu..."</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Gesek ke kiri untuk membagikan laporan bug Anda"</string>
     <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"Ketuk untuk membagikan laporan bug"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"Ketuk untuk membagikan laporan bug tanpa tangkapan layar atau menunggu tangkapan layar selesai"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"Ketuk untuk membagikan laporan bug tanpa tangkapan layar atau menunggu tangkapan layar selesai"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"Laporan bug berisi data dari berbagai file log sistem, termasuk informasi pribadi dan rahasia. Hanya bagikan laporan bug dengan aplikasi dan orang yang Anda percaya."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Tampilkan pesan ini lain kali"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"Laporan bug"</string>
@@ -34,6 +37,7 @@
     <string name="bugreport_screenshot_failed" msgid="5853049140806834601">"Tangkapan layar tidak dapat diambil."</string>
     <string name="bugreport_info_dialog_title" msgid="1355948594292983332">"Detail laporan bug <xliff:g id="ID">#%d</xliff:g>"</string>
     <string name="bugreport_info_name" msgid="4414036021935139527">"Nama file"</string>
-    <string name="bugreport_info_title" msgid="5599558206004371052">"Judul"</string>
-    <string name="bugreport_info_description" msgid="4117088998733546784">"Deskripsi detail"</string>
+    <string name="bugreport_info_title" msgid="2306030793918239804">"Judul bug"</string>
+    <string name="bugreport_info_description" msgid="5072835127481627722">"Ringkasan bug"</string>
+    <string name="save" msgid="4781509040564835759">"Simpan"</string>
 </resources>
diff --git a/packages/Shell/res/values-is-rIS/strings.xml b/packages/Shell/res/values-is-rIS/strings.xml
index 0d43719..aedf3bc3 100644
--- a/packages/Shell/res/values-is-rIS/strings.xml
+++ b/packages/Shell/res/values-is-rIS/strings.xml
@@ -19,10 +19,13 @@
     <string name="app_label" msgid="3701846017049540910">"Skipanalína"</string>
     <string name="bugreport_in_progress_title" msgid="4311705936714972757">"Verið er að búa til villutilkynningu <xliff:g id="ID">#%d</xliff:g>"</string>
     <string name="bugreport_finished_title" msgid="4429132808670114081">"Villutilkynning <xliff:g id="ID">#%d</xliff:g> búin til"</string>
+    <string name="bugreport_finished_pending_screenshot_title" msgid="5460883450679439591">"Villuskýrsla <xliff:g id="ID">#%d</xliff:g> tilbúin en skjámynd í vinnslu"</string>
     <string name="bugreport_updating_title" msgid="4423539949559634214">"Bætir upplýsingum við villutilkynningu"</string>
     <string name="bugreport_updating_wait" msgid="3322151947853929470">"Augnablik..."</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Strjúktu til vinstri til að deila villuskýrslunni"</string>
     <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"Ýttu til að deila villutilkynningunni"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"Ýttu til að deila villutilkynningunni án skjámyndar eða hinkraðu þangað til skjámyndin er tilbúin"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"Ýttu til að deila villutilkynningunni án skjámyndar eða hinkraðu þangað til skjámyndin er tilbúin"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"Villutilkynningar innihalda gögn úr hinum ýmsu annálsskrám kerfisins, þ. á m. persónuleg gögn og trúnaðarupplýsingar. Deildu villutilkynningum eingöngu með forritum og fólki sem þú treystir."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Sýna þessi skilaboð næst"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"Villutilkynningar"</string>
@@ -34,6 +37,7 @@
     <string name="bugreport_screenshot_failed" msgid="5853049140806834601">"Ekki tókst að taka skjámynd."</string>
     <string name="bugreport_info_dialog_title" msgid="1355948594292983332">"Upplýsingar villutilkynningar <xliff:g id="ID">#%d</xliff:g>"</string>
     <string name="bugreport_info_name" msgid="4414036021935139527">"Skráarheiti"</string>
-    <string name="bugreport_info_title" msgid="5599558206004371052">"Titill"</string>
-    <string name="bugreport_info_description" msgid="4117088998733546784">"Ítarleg lýsing"</string>
+    <string name="bugreport_info_title" msgid="2306030793918239804">"Heiti villu"</string>
+    <string name="bugreport_info_description" msgid="5072835127481627722">"Villusamantekt"</string>
+    <string name="save" msgid="4781509040564835759">"Vista"</string>
 </resources>
diff --git a/packages/Shell/res/values-it/strings.xml b/packages/Shell/res/values-it/strings.xml
index fc9383a..d7d62e2 100644
--- a/packages/Shell/res/values-it/strings.xml
+++ b/packages/Shell/res/values-it/strings.xml
@@ -19,10 +19,13 @@
     <string name="app_label" msgid="3701846017049540910">"Shell"</string>
     <string name="bugreport_in_progress_title" msgid="4311705936714972757">"Generazione segnalazione di bug <xliff:g id="ID">#%d</xliff:g> in corso"</string>
     <string name="bugreport_finished_title" msgid="4429132808670114081">"Segnalazione di bug <xliff:g id="ID">#%d</xliff:g> acquisita"</string>
+    <string name="bugreport_finished_pending_screenshot_title" msgid="5460883450679439591">"Segnalazione di bug <xliff:g id="ID">#%d</xliff:g> acquisita, screenshot in attesa"</string>
     <string name="bugreport_updating_title" msgid="4423539949559634214">"Aggiunta di dettagli alla segnalazione di bug"</string>
     <string name="bugreport_updating_wait" msgid="3322151947853929470">"Attendi..."</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Scorri verso sinistra per condividere il rapporto sui bug"</string>
     <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"Tocca per condividere la segnalazione di bug"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"Tocca per condividere la segnalazione di bug senza screenshot o attendi che lo screenshot sia completo"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"Tocca per condividere la segnalazione di bug senza screenshot o attendi che lo screenshot sia completo"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"Le segnalazioni di bug contengono dati da vari file di log del sistema, incluse informazioni personali e private. Condividi le segnalazioni di bug solo con app e persone attendibili."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Mostra questo messaggio la prossima volta"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"Rapporti sui bug"</string>
@@ -34,6 +37,7 @@
     <string name="bugreport_screenshot_failed" msgid="5853049140806834601">"Impossibile acquisire lo screenshot."</string>
     <string name="bugreport_info_dialog_title" msgid="1355948594292983332">"Dettagli sulla segnalazione di bug <xliff:g id="ID">#%d</xliff:g>"</string>
     <string name="bugreport_info_name" msgid="4414036021935139527">"Nome file"</string>
-    <string name="bugreport_info_title" msgid="5599558206004371052">"Titolo"</string>
-    <string name="bugreport_info_description" msgid="4117088998733546784">"Descrizione dettagliata"</string>
+    <string name="bugreport_info_title" msgid="2306030793918239804">"Titolo bug"</string>
+    <string name="bugreport_info_description" msgid="5072835127481627722">"Riepilogo bug"</string>
+    <string name="save" msgid="4781509040564835759">"Salva"</string>
 </resources>
diff --git a/packages/Shell/res/values-iw/strings.xml b/packages/Shell/res/values-iw/strings.xml
index 335a2e8..6589c8b 100644
--- a/packages/Shell/res/values-iw/strings.xml
+++ b/packages/Shell/res/values-iw/strings.xml
@@ -19,10 +19,13 @@
     <string name="app_label" msgid="3701846017049540910">"מעטפת"</string>
     <string name="bugreport_in_progress_title" msgid="4311705936714972757">"יצירת הדוח על הבאג <xliff:g id="ID">#%d</xliff:g> מתבצעת"</string>
     <string name="bugreport_finished_title" msgid="4429132808670114081">"הדוח על הבאג <xliff:g id="ID">#%d</xliff:g> צולם"</string>
+    <string name="bugreport_finished_pending_screenshot_title" msgid="5460883450679439591">"הדוח על הבאג <xliff:g id="ID">#%d</xliff:g> נוצר, אך צילום המסך בהמתנה"</string>
     <string name="bugreport_updating_title" msgid="4423539949559634214">"מוסיף פרטים לדוח על הבאג"</string>
     <string name="bugreport_updating_wait" msgid="3322151947853929470">"המתן…"</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"החלק שמאלה כדי לשתף את דוח הבאגים"</string>
     <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"הקש כדי לשתף את הדוח על הבאג"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"הקש כדי לשתף את הדוח על הבאג ללא צילום מסך, או המתן להשלמת צילום המסך"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"הקש כדי לשתף את הדוח על הבאג ללא צילום מסך, או המתן להשלמת צילום המסך"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"דוחות על באגים כוללים נתונים מקובצי היומן השונים במערכת, כולל מידע אישי ופרטי. שתף דוחות באגים רק עם אפליקציות ואנשים שאתה סומך עליהם."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"הצג את ההודעה הזו בפעם הבאה"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"דוחות באגים"</string>
@@ -34,6 +37,7 @@
     <string name="bugreport_screenshot_failed" msgid="5853049140806834601">"לא ניתן היה לצלם מסך."</string>
     <string name="bugreport_info_dialog_title" msgid="1355948594292983332">"פרטי הדוח על הבאג <xliff:g id="ID">#%d</xliff:g>"</string>
     <string name="bugreport_info_name" msgid="4414036021935139527">"שם קובץ"</string>
-    <string name="bugreport_info_title" msgid="5599558206004371052">"כותרת"</string>
-    <string name="bugreport_info_description" msgid="4117088998733546784">"תיאור מפורט"</string>
+    <string name="bugreport_info_title" msgid="2306030793918239804">"כותרת הבאג"</string>
+    <string name="bugreport_info_description" msgid="5072835127481627722">"סיכום הבאג"</string>
+    <string name="save" msgid="4781509040564835759">"שמור"</string>
 </resources>
diff --git a/packages/Shell/res/values-ja/strings.xml b/packages/Shell/res/values-ja/strings.xml
index b98b05f..33ddec9 100644
--- a/packages/Shell/res/values-ja/strings.xml
+++ b/packages/Shell/res/values-ja/strings.xml
@@ -19,10 +19,16 @@
     <string name="app_label" msgid="3701846017049540910">"シェル"</string>
     <string name="bugreport_in_progress_title" msgid="4311705936714972757">"バグレポート <xliff:g id="ID">#%d</xliff:g> の生成中"</string>
     <string name="bugreport_finished_title" msgid="4429132808670114081">"バグレポート <xliff:g id="ID">#%d</xliff:g> の記録完了"</string>
+    <!-- no translation found for bugreport_finished_pending_screenshot_title (5460883450679439591) -->
+    <skip />
     <string name="bugreport_updating_title" msgid="4423539949559634214">"バグレポートに詳細情報を追加しています"</string>
     <string name="bugreport_updating_wait" msgid="3322151947853929470">"お待ちください…"</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"バグレポートを共有するには左にスワイプ"</string>
     <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"バグレポートを共有するにはタップします"</string>
+    <!-- no translation found for bugreport_finished_pending_screenshot_text (1474435374470177193) -->
+    <skip />
+    <!-- no translation found for bugreport_finished_pending_screenshot_text (1474435374470177193) -->
+    <skip />
     <string name="bugreport_confirm" msgid="5130698467795669780">"バグレポートには、個人の非公開情報など、システムのさまざまなログファイルのデータが含まれます。共有する場合は信頼するアプリとユーザーのみを選択してください。"</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"このメッセージを次回も表示する"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"バグレポート"</string>
@@ -34,6 +40,7 @@
     <string name="bugreport_screenshot_failed" msgid="5853049140806834601">"スクリーンショットを撮影できませんでした。"</string>
     <string name="bugreport_info_dialog_title" msgid="1355948594292983332">"バグレポート <xliff:g id="ID">#%d</xliff:g> の詳細"</string>
     <string name="bugreport_info_name" msgid="4414036021935139527">"ファイル名"</string>
-    <string name="bugreport_info_title" msgid="5599558206004371052">"タイトル"</string>
-    <string name="bugreport_info_description" msgid="4117088998733546784">"詳細説明"</string>
+    <string name="bugreport_info_title" msgid="2306030793918239804">"バグのタイトル"</string>
+    <string name="bugreport_info_description" msgid="5072835127481627722">"バグの概要"</string>
+    <string name="save" msgid="4781509040564835759">"保存"</string>
 </resources>
diff --git a/packages/Shell/res/values-ka-rGE/strings.xml b/packages/Shell/res/values-ka-rGE/strings.xml
index 24d83a4..61bdff7 100644
--- a/packages/Shell/res/values-ka-rGE/strings.xml
+++ b/packages/Shell/res/values-ka-rGE/strings.xml
@@ -19,10 +19,16 @@
     <string name="app_label" msgid="3701846017049540910">"გარეკანი"</string>
     <string name="bugreport_in_progress_title" msgid="4311705936714972757">"ხარვეზების შესახებ ანგარიში <xliff:g id="ID">#%d</xliff:g> გენერირდება"</string>
     <string name="bugreport_finished_title" msgid="4429132808670114081">"ხარვეზების შესახებ ანგარიში <xliff:g id="ID">#%d</xliff:g> აღბეჭდილია"</string>
+    <!-- no translation found for bugreport_finished_pending_screenshot_title (5460883450679439591) -->
+    <skip />
     <string name="bugreport_updating_title" msgid="4423539949559634214">"ხარვეზის შესახებ ანგარიშს დეტალები ემატება"</string>
     <string name="bugreport_updating_wait" msgid="3322151947853929470">"გთხოვთ, მოითმინოთ..."</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"გაასრიალეთ მარცხნივ თქვენი ხარვეზის შეტყობინების გასაზიარებლად"</string>
     <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"შეეხეთ ხარვეზების შესახებ ანგარიშის გასაზიარებლად"</string>
+    <!-- no translation found for bugreport_finished_pending_screenshot_text (1474435374470177193) -->
+    <skip />
+    <!-- no translation found for bugreport_finished_pending_screenshot_text (1474435374470177193) -->
+    <skip />
     <string name="bugreport_confirm" msgid="5130698467795669780">"ხარვეზის ანგარიშები მოიცავს მონაცემებს სხვადასხვა სისტემური ჟურნალის ფაილებიდან, მათ შორის პირად და კონფიდენციალურ ინფორმაციას."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"შემდგომში აჩვენე ეს შეტყობინება"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"შეცდომების ანგარიშები"</string>
@@ -34,6 +40,7 @@
     <string name="bugreport_screenshot_failed" msgid="5853049140806834601">"ეკრანის ანაბეჭდის გადაღება ვერ მოხერხდა."</string>
     <string name="bugreport_info_dialog_title" msgid="1355948594292983332">"ხარვეზების შესახებ ანგარიში <xliff:g id="ID">#%d</xliff:g>-ის დეტალები"</string>
     <string name="bugreport_info_name" msgid="4414036021935139527">"ფაილის სახელი"</string>
-    <string name="bugreport_info_title" msgid="5599558206004371052">"სათაური"</string>
-    <string name="bugreport_info_description" msgid="4117088998733546784">"დეტალური აღწერა"</string>
+    <string name="bugreport_info_title" msgid="2306030793918239804">"შეცდომის სათაური"</string>
+    <string name="bugreport_info_description" msgid="5072835127481627722">"შეცდომის რეზიუმე"</string>
+    <string name="save" msgid="4781509040564835759">"შენახვა"</string>
 </resources>
diff --git a/packages/Shell/res/values-kk-rKZ/strings.xml b/packages/Shell/res/values-kk-rKZ/strings.xml
index 5878b17..403615a 100644
--- a/packages/Shell/res/values-kk-rKZ/strings.xml
+++ b/packages/Shell/res/values-kk-rKZ/strings.xml
@@ -19,10 +19,16 @@
     <string name="app_label" msgid="3701846017049540910">"Қабыршық"</string>
     <string name="bugreport_in_progress_title" msgid="4311705936714972757">"<xliff:g id="ID">#%d</xliff:g> қате туралы есебі жасалуда"</string>
     <string name="bugreport_finished_title" msgid="4429132808670114081">"<xliff:g id="ID">#%d</xliff:g> қате туралы есебі жазып алынды"</string>
+    <!-- no translation found for bugreport_finished_pending_screenshot_title (5460883450679439591) -->
+    <skip />
     <string name="bugreport_updating_title" msgid="4423539949559634214">"Қате туралы есепке мәліметтер қосылуда"</string>
     <string name="bugreport_updating_wait" msgid="3322151947853929470">"Күте тұрыңыз…"</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Қате туралы есепті бөлісу үшін солға жанаңыз"</string>
     <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"Қате туралы есепті бөлісу үшін түртіңіз"</string>
+    <!-- no translation found for bugreport_finished_pending_screenshot_text (1474435374470177193) -->
+    <skip />
+    <!-- no translation found for bugreport_finished_pending_screenshot_text (1474435374470177193) -->
+    <skip />
     <string name="bugreport_confirm" msgid="5130698467795669780">"Вирус туралы баянатта жүйеде тіркелген әртүрлі файлдар туралы деректер болады, оған жеке және құпия ақпарат та кіреді. Вирус баянаттарын сенімді қолданбалар және сенімді адамдармен ғана бөлісіңіз."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Бұл хабарды келесі жолы көрсетіңіз"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"Қате туралы баяндамалар"</string>
@@ -34,6 +40,7 @@
     <string name="bugreport_screenshot_failed" msgid="5853049140806834601">"Скриншот түсіру мүмкін болмады."</string>
     <string name="bugreport_info_dialog_title" msgid="1355948594292983332">"<xliff:g id="ID">#%d</xliff:g> қате туралы есебі туралы мәліметтер"</string>
     <string name="bugreport_info_name" msgid="4414036021935139527">"Файл атауы"</string>
-    <string name="bugreport_info_title" msgid="5599558206004371052">"Атауы"</string>
-    <string name="bugreport_info_description" msgid="4117088998733546784">"Егжей-тегжейлі сипаттама"</string>
+    <string name="bugreport_info_title" msgid="2306030793918239804">"Қатенің атауы"</string>
+    <string name="bugreport_info_description" msgid="5072835127481627722">"Қате туралы жиынтық мәліметтер"</string>
+    <string name="save" msgid="4781509040564835759">"Сақтау"</string>
 </resources>
diff --git a/packages/Shell/res/values-km-rKH/strings.xml b/packages/Shell/res/values-km-rKH/strings.xml
index 9c95e98..05f5cc5 100644
--- a/packages/Shell/res/values-km-rKH/strings.xml
+++ b/packages/Shell/res/values-km-rKH/strings.xml
@@ -19,10 +19,16 @@
     <string name="app_label" msgid="3701846017049540910">"សែល"</string>
     <string name="bugreport_in_progress_title" msgid="4311705936714972757">"<xliff:g id="ID">#%d</xliff:g> របាយការណ៍កំហុសកំពុងត្រូវបានបង្កើត"</string>
     <string name="bugreport_finished_title" msgid="4429132808670114081">"<xliff:g id="ID">#%d</xliff:g> របាយការណ៍កំហុសត្រូវបានថត"</string>
+    <!-- no translation found for bugreport_finished_pending_screenshot_title (5460883450679439591) -->
+    <skip />
     <string name="bugreport_updating_title" msgid="4423539949559634214">"កំពុងបន្ថែមព័ត៌មានលម្អិតទៅរបាយការណ៍កំហុស"</string>
     <string name="bugreport_updating_wait" msgid="3322151947853929470">"សូម​រង់ចាំ…"</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"អូស​ទៅ​ឆ្វេង​​ ដើម្បី​ចែក​រំលែក​របាយការណ៍​កំហុស​របស់​អ្នក"</string>
     <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"ប៉ះដើម្បីចែករំលែករបាយការណ៍កំហុសរបស់អ្នក"</string>
+    <!-- no translation found for bugreport_finished_pending_screenshot_text (1474435374470177193) -->
+    <skip />
+    <!-- no translation found for bugreport_finished_pending_screenshot_text (1474435374470177193) -->
+    <skip />
     <string name="bugreport_confirm" msgid="5130698467795669780">"របាយការណ៍​កំហុស​រួមមាន​ឯកសារ​កំណត់​ហេតុ​ផ្សេងៗ​របស់​ប្រព័ន្ធ រួមមាន​ព័ត៌មាន​ផ្ទាល់ខ្លួន និង​ឯកជន។ ចែករំលែក​របាយការណ៍​កំហុស​ជា​មួយ​កម្មវិធី និង​មនុស្ស​ដែល​អ្នក​ទុក​ចិត្ត។"</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"បង្ហាញ​សារ​នេះ​ពេល​ក្រោយ"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"រាយការណ៍ពីកំហុស"</string>
@@ -34,6 +40,7 @@
     <string name="bugreport_screenshot_failed" msgid="5853049140806834601">"មិនអាចថតរូបថតអេក្រង់បានទេ"</string>
     <string name="bugreport_info_dialog_title" msgid="1355948594292983332">"ព័ត៌មានលម្អិតពី <xliff:g id="ID">#%d</xliff:g> របាយការណ៍កំហុស"</string>
     <string name="bugreport_info_name" msgid="4414036021935139527">"ឈ្មោះ​ឯកសារ"</string>
-    <string name="bugreport_info_title" msgid="5599558206004371052">"ចំណងជើង"</string>
-    <string name="bugreport_info_description" msgid="4117088998733546784">"ការពិពណ៌នាលម្អិត"</string>
+    <string name="bugreport_info_title" msgid="2306030793918239804">"ចំណងជើងកំហុស"</string>
+    <string name="bugreport_info_description" msgid="5072835127481627722">"សង្ខេបកំហុស"</string>
+    <string name="save" msgid="4781509040564835759">"រក្សាទុក"</string>
 </resources>
diff --git a/packages/Shell/res/values-kn-rIN/strings.xml b/packages/Shell/res/values-kn-rIN/strings.xml
index ce6f3c0..1331f7e 100644
--- a/packages/Shell/res/values-kn-rIN/strings.xml
+++ b/packages/Shell/res/values-kn-rIN/strings.xml
@@ -19,10 +19,13 @@
     <string name="app_label" msgid="3701846017049540910">"ಶೆಲ್"</string>
     <string name="bugreport_in_progress_title" msgid="4311705936714972757">"ದೋಷ ವರದಿಯ <xliff:g id="ID">#%d</xliff:g> ಅನ್ನು ರಚಿಸಲಾಗುತ್ತಿದೆ"</string>
     <string name="bugreport_finished_title" msgid="4429132808670114081">"ದೋಷ ವರದಿಯ <xliff:g id="ID">#%d</xliff:g> ಅನ್ನು ಕ್ಯಾಪ್ಚರ್ ಮಾಡಿಕೊಳ್ಳಲಾಗಿದೆ"</string>
+    <string name="bugreport_finished_pending_screenshot_title" msgid="5460883450679439591">"ದೋಷ ವರದಿಯ <xliff:g id="ID">#%d</xliff:g> ಅನ್ನು ಕ್ಯಾಪ್ಚರ್ ಮಾಡಿಕೊಳ್ಳಲಾಗಿದೆ ಆದರೆ ಸ್ಕ್ರೀನ್‌ಶಾಟ್‌ ಬಾಕಿ ಉಳಿದಿದೆ"</string>
     <string name="bugreport_updating_title" msgid="4423539949559634214">"ಬಗ್ ವರದಿಗೆ ವಿವರಗಳನ್ನು ಸೇರಿಸಲಾಗುತ್ತಿದೆ"</string>
     <string name="bugreport_updating_wait" msgid="3322151947853929470">"ದಯವಿಟ್ಟು ನಿರೀಕ್ಷಿಸಿ..."</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"ನಿಮ್ಮ ದೋಷ ವರದಿಯನ್ನು ಹಂಚಿಕೊಳ್ಳಲು ಎಡಕ್ಕೆ ಸ್ವೈಪ್‌ ಮಾಡಿ"</string>
     <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"ನಿಮ್ಮ ಬಗ್ ವರದಿಯನ್ನು ಹಂಚಿಕೊಳ್ಳಲು ಟ್ಯಾಪ್ ಮಾಡಿ"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"ಸ್ಕ್ರೀನ್‌ಶಾಟ್‌ ಇಲ್ಲದೇ ನಿಮ್ಮ ಬಗ್ ವರದಿಯನ್ನು ಹಂಚಿಕೊಳ್ಳಲು ಟ್ಯಾಪ್ ಮಾಡಿ ಅಥವಾ ಸ್ಕ್ರೀನ್‌ಶಾಟ್‌ ಪೂರ್ತಿಯಾಗುವವರೆಗೂ ನಿರೀಕ್ಷಿಸಿ"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"ಸ್ಕ್ರೀನ್‌ಶಾಟ್‌ ಇಲ್ಲದೇ ನಿಮ್ಮ ಬಗ್ ವರದಿಯನ್ನು ಹಂಚಿಕೊಳ್ಳಲು ಟ್ಯಾಪ್ ಮಾಡಿ ಅಥವಾ ಸ್ಕ್ರೀನ್‌ಶಾಟ್‌ ಪೂರ್ತಿಯಾಗುವವರೆಗೂ ನಿರೀಕ್ಷಿಸಿ"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"ವೈಯಕ್ತಿಕ ಮತ್ತು ಖಾಸಗಿ ಮಾಹಿತಿಯು ಸೇರಿದಂತೆ, ಸಿಸ್ಟಂನ ಹಲವಾರು ಲಾಗ್ ಫೈಲ್‌ಗಳಿಂದ ಡೇಟಾವನ್ನು ದೋಷದ ವರದಿಗಳು ಒಳಗೊಂಡಿವೆ. ನೀವು ನಂಬುವಂತಹ ಅಪ್ಲಿಕೇಶನ್‌ಗಳು ಮತ್ತು ಜನರೊಂದಿಗೆ ಮಾತ್ರ ದೋಷದ ವರದಿಗಳನ್ನು ಹಂಚಿಕೊಳ್ಳಿ."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"ಈ ಸಂದೇಶವನ್ನು ಮುಂದಿನ ಬಾರಿ ತೋರಿಸಿ"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"ದೋಷ ವರದಿಗಳು"</string>
@@ -34,6 +37,7 @@
     <string name="bugreport_screenshot_failed" msgid="5853049140806834601">"ಸ್ಕ್ರೀನ್‌ಶಾಟ್‌ ತೆಗೆದುಕೊಳ್ಳಲು ಸಾಧ್ಯವಾಗುವುದಿಲ್ಲ."</string>
     <string name="bugreport_info_dialog_title" msgid="1355948594292983332">"ದೋಷ ವರದಿಯ <xliff:g id="ID">#%d</xliff:g> ವಿವರಗಳು"</string>
     <string name="bugreport_info_name" msgid="4414036021935139527">"ಫೈಲ್‌ಹೆಸರು"</string>
-    <string name="bugreport_info_title" msgid="5599558206004371052">"ಶೀರ್ಷಿಕೆ"</string>
-    <string name="bugreport_info_description" msgid="4117088998733546784">"ವಿವರವಾದ ವಿವರಣೆ"</string>
+    <string name="bugreport_info_title" msgid="2306030793918239804">"ಬಗ್ ಶೀರ್ಷಿಕೆ"</string>
+    <string name="bugreport_info_description" msgid="5072835127481627722">"ಬಗ್ ಸಾರಾಂಶ"</string>
+    <string name="save" msgid="4781509040564835759">"ಉಳಿಸು"</string>
 </resources>
diff --git a/packages/Shell/res/values-ko/strings.xml b/packages/Shell/res/values-ko/strings.xml
index 70df8e2..8087304 100644
--- a/packages/Shell/res/values-ko/strings.xml
+++ b/packages/Shell/res/values-ko/strings.xml
@@ -19,10 +19,16 @@
     <string name="app_label" msgid="3701846017049540910">"셸"</string>
     <string name="bugreport_in_progress_title" msgid="4311705936714972757">"버그 신고 <xliff:g id="ID">#%d</xliff:g> 생성 중"</string>
     <string name="bugreport_finished_title" msgid="4429132808670114081">"버그 신고 <xliff:g id="ID">#%d</xliff:g> 캡처됨"</string>
+    <!-- no translation found for bugreport_finished_pending_screenshot_title (5460883450679439591) -->
+    <skip />
     <string name="bugreport_updating_title" msgid="4423539949559634214">"세부정보를 버그 보고서에 추가"</string>
     <string name="bugreport_updating_wait" msgid="3322151947853929470">"잠시 기다려 주세요..."</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"왼쪽으로 스와이프하여 버그 신고서를 공유하세요."</string>
     <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"버그 신고를 공유하려면 탭하세요."</string>
+    <!-- no translation found for bugreport_finished_pending_screenshot_text (1474435374470177193) -->
+    <skip />
+    <!-- no translation found for bugreport_finished_pending_screenshot_text (1474435374470177193) -->
+    <skip />
     <string name="bugreport_confirm" msgid="5130698467795669780">"버그 신고서는 시스템의 다양한 로그 파일 데이터(예: 개인 및 비공개 정보)를 포함합니다. 신뢰할 수 있는 앱과 사용자에게만 버그 신고서를 공유하세요."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"다음에 이 메시지 표시"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"버그 신고"</string>
@@ -34,6 +40,7 @@
     <string name="bugreport_screenshot_failed" msgid="5853049140806834601">"스크린샷을 찍을 수 없습니다."</string>
     <string name="bugreport_info_dialog_title" msgid="1355948594292983332">"버그 신고 <xliff:g id="ID">#%d</xliff:g> 세부정보"</string>
     <string name="bugreport_info_name" msgid="4414036021935139527">"파일 이름"</string>
-    <string name="bugreport_info_title" msgid="5599558206004371052">"제목"</string>
-    <string name="bugreport_info_description" msgid="4117088998733546784">"자세한 설명"</string>
+    <string name="bugreport_info_title" msgid="2306030793918239804">"버그 제목"</string>
+    <string name="bugreport_info_description" msgid="5072835127481627722">"버그 요약"</string>
+    <string name="save" msgid="4781509040564835759">"저장"</string>
 </resources>
diff --git a/packages/Shell/res/values-ky-rKG/strings.xml b/packages/Shell/res/values-ky-rKG/strings.xml
index 49d8d8d..cc5b2e5 100644
--- a/packages/Shell/res/values-ky-rKG/strings.xml
+++ b/packages/Shell/res/values-ky-rKG/strings.xml
@@ -19,10 +19,16 @@
     <string name="app_label" msgid="3701846017049540910">"Командалык кабык"</string>
     <string name="bugreport_in_progress_title" msgid="4311705936714972757">"Мүчүлүштүк тууралуу билдирүү <xliff:g id="ID">#%d</xliff:g> түзүлүүдө"</string>
     <string name="bugreport_finished_title" msgid="4429132808670114081">"Мүчүлүштүк тууралуу билдирүү <xliff:g id="ID">#%d</xliff:g> жаздырылды"</string>
+    <!-- no translation found for bugreport_finished_pending_screenshot_title (5460883450679439591) -->
+    <skip />
     <string name="bugreport_updating_title" msgid="4423539949559634214">"Мүчүлүштүк жөнүндө кабардын чоо-жайы кошулууда"</string>
     <string name="bugreport_updating_wait" msgid="3322151947853929470">"Күтө туруңуз…"</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Ката жөнүндө кабар менен бөлүшүү үчүн солго серпип коюңуз"</string>
     <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"Мүчүлүштүк тууралуу билдирүүңүздү бөлүшүү үчүн таптап коюңуз"</string>
+    <!-- no translation found for bugreport_finished_pending_screenshot_text (1474435374470177193) -->
+    <skip />
+    <!-- no translation found for bugreport_finished_pending_screenshot_text (1474435374470177193) -->
+    <skip />
     <string name="bugreport_confirm" msgid="5130698467795669780">"Ката тууралуу билдирүүлөр системанын ар кандай лог файлдарынын берилиштерин камтыйт, аларга өздүк жана купуя маалыматтар дагы кирет. Ката тууралуу билдирүүлөрдү сиз ишенген колдонмолор жана адамдар менен гана бөлүшүңүз."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Бул билдирүү кийин көрсөтүлсүн"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"Мүчүлүштүктөрдү кабарлоолор"</string>
@@ -34,6 +40,7 @@
     <string name="bugreport_screenshot_failed" msgid="5853049140806834601">"Скриншот тартылбай койду."</string>
     <string name="bugreport_info_dialog_title" msgid="1355948594292983332">"Мүчүлүштүк тууралуу билдирүүнүн <xliff:g id="ID">#%d</xliff:g> чоо-жайы"</string>
     <string name="bugreport_info_name" msgid="4414036021935139527">"Файлдын аталышы"</string>
-    <string name="bugreport_info_title" msgid="5599558206004371052">"Аталышы"</string>
-    <string name="bugreport_info_description" msgid="4117088998733546784">"Кененирээк маалымат"</string>
+    <string name="bugreport_info_title" msgid="2306030793918239804">"Мүчүлүштүктүн аталышы"</string>
+    <string name="bugreport_info_description" msgid="5072835127481627722">"Мүчүлүштүк корутундусу"</string>
+    <string name="save" msgid="4781509040564835759">"Сактоо"</string>
 </resources>
diff --git a/packages/Shell/res/values-lo-rLA/strings.xml b/packages/Shell/res/values-lo-rLA/strings.xml
index 61b06c8..7685d44 100644
--- a/packages/Shell/res/values-lo-rLA/strings.xml
+++ b/packages/Shell/res/values-lo-rLA/strings.xml
@@ -19,10 +19,16 @@
     <string name="app_label" msgid="3701846017049540910">"Shell"</string>
     <string name="bugreport_in_progress_title" msgid="4311705936714972757">"ກຳລັງສ້າງລາຍງານຂໍ້ຜິດພາດ <xliff:g id="ID">#%d</xliff:g>"</string>
     <string name="bugreport_finished_title" msgid="4429132808670114081">"ບັນທຶກລາຍງານຂໍ້ຜິດພາດ <xliff:g id="ID">#%d</xliff:g> ແລ້ວ"</string>
+    <!-- no translation found for bugreport_finished_pending_screenshot_title (5460883450679439591) -->
+    <skip />
     <string name="bugreport_updating_title" msgid="4423539949559634214">"ກຳລັງເພີ່ມລາຍລະອຽດໃສ່ລາຍງານຂໍ້ຜິດພາດ"</string>
     <string name="bugreport_updating_wait" msgid="3322151947853929470">"ກະລຸນາລໍຖ້າ..."</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"​ປັດ​ໄປ​ຊ້າຍ​ເພື່ອ​ສົ່ງ​ລາຍ​ງານ​ຂໍ້​ຜິດ​ພາດ​ຂອງ​ທ່ານ"</string>
     <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"ແຕະເພື່ອແບ່ງປັນລາຍງານຂໍ້ຜິດພາດຂອງທ່ານ"</string>
+    <!-- no translation found for bugreport_finished_pending_screenshot_text (1474435374470177193) -->
+    <skip />
+    <!-- no translation found for bugreport_finished_pending_screenshot_text (1474435374470177193) -->
+    <skip />
     <string name="bugreport_confirm" msgid="5130698467795669780">"ການລາຍງານຂໍ້ຜິດພາດປະກອບມີ ຂໍ້ມູນຈາກໄຟລ໌ບັນທຶກຂອງລະບົບຫຼາຍໄຟລ໌, ຮວມທັງຂໍ້ມູນສ່ວນໂຕນຳ. ທ່ານຕ້ອງແບ່ງປັນລາຍງານຂໍ້ຜິດພາດໃຫ້ແອັບຯ ແລະຄົນທີ່ທ່ານເຊື່ອຖືໄດ້ເທົ່ານັ້ນ."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"ສະແດງຂໍ້ຄວາມນີ້ອີກໃນເທື່ອຕໍ່ໄປ"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"ລາຍ​ງານ​ບັນ​ຫາ"</string>
@@ -34,6 +40,7 @@
     <string name="bugreport_screenshot_failed" msgid="5853049140806834601">"ບໍ່ສາມາດຖ່າຍພາບໜ້າຈໍໄດ້."</string>
     <string name="bugreport_info_dialog_title" msgid="1355948594292983332">"ລາຍລະອຽດຂອງລາຍງານຂໍ້ຜິດພາດ <xliff:g id="ID">#%d</xliff:g>"</string>
     <string name="bugreport_info_name" msgid="4414036021935139527">"ຊື່ໄຟລ໌"</string>
-    <string name="bugreport_info_title" msgid="5599558206004371052">"ຊື່"</string>
-    <string name="bugreport_info_description" msgid="4117088998733546784">"ຄຳອະທິບາຍແບບລະອຽດ"</string>
+    <string name="bugreport_info_title" msgid="2306030793918239804">"ຊື່ຂໍ້ຜິດພາດ"</string>
+    <string name="bugreport_info_description" msgid="5072835127481627722">"ສະຫຼຸບຂໍ້ຜິດພາດ"</string>
+    <string name="save" msgid="4781509040564835759">"ບັນທຶກ"</string>
 </resources>
diff --git a/packages/Shell/res/values-lt/strings.xml b/packages/Shell/res/values-lt/strings.xml
index 3418213..202401a 100644
--- a/packages/Shell/res/values-lt/strings.xml
+++ b/packages/Shell/res/values-lt/strings.xml
@@ -19,10 +19,16 @@
     <string name="app_label" msgid="3701846017049540910">"Apvalkalas"</string>
     <string name="bugreport_in_progress_title" msgid="4311705936714972757">"Pranešimas apie riktą (<xliff:g id="ID">#%d</xliff:g>) generuojamas"</string>
     <string name="bugreport_finished_title" msgid="4429132808670114081">"Pranešimas apie riktą (<xliff:g id="ID">#%d</xliff:g>) užfiksuotas"</string>
+    <!-- no translation found for bugreport_finished_pending_screenshot_title (5460883450679439591) -->
+    <skip />
     <string name="bugreport_updating_title" msgid="4423539949559634214">"Pridedama informacijos prie pranešimo apie riktą"</string>
     <string name="bugreport_updating_wait" msgid="3322151947853929470">"Palaukite…"</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Perbraukite kairėn, kad bendrintumėte rikto ataskaitą"</string>
     <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"Palieskite, kad bendrintumėte pranešimą apie riktą"</string>
+    <!-- no translation found for bugreport_finished_pending_screenshot_text (1474435374470177193) -->
+    <skip />
+    <!-- no translation found for bugreport_finished_pending_screenshot_text (1474435374470177193) -->
+    <skip />
     <string name="bugreport_confirm" msgid="5130698467795669780">"Riktų ataskaitose pateikiami duomenys iš įvairių sistemos žurnalo failų, įskaitant asmeninę ir privačią informaciją. Riktų ataskaitas bendrinkite tik su patikimomis programomis ir žmonėmis."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Rodyti šį pranešimą kitą kartą"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"Riktų ataskaitos"</string>
@@ -34,6 +40,7 @@
     <string name="bugreport_screenshot_failed" msgid="5853049140806834601">"Nepavyko padaryti ekrano kopijos."</string>
     <string name="bugreport_info_dialog_title" msgid="1355948594292983332">"Išsami informacija apie pranešimą apie riktą (<xliff:g id="ID">#%d</xliff:g>)"</string>
     <string name="bugreport_info_name" msgid="4414036021935139527">"Failo pavadinimas"</string>
-    <string name="bugreport_info_title" msgid="5599558206004371052">"Pavadinimas"</string>
-    <string name="bugreport_info_description" msgid="4117088998733546784">"Išsamus aprašas"</string>
+    <string name="bugreport_info_title" msgid="2306030793918239804">"Rikto pavadinimas"</string>
+    <string name="bugreport_info_description" msgid="5072835127481627722">"Rikto suvestinė"</string>
+    <string name="save" msgid="4781509040564835759">"Išsaugoti"</string>
 </resources>
diff --git a/packages/Shell/res/values-lv/strings.xml b/packages/Shell/res/values-lv/strings.xml
index 6108716..93de35d 100644
--- a/packages/Shell/res/values-lv/strings.xml
+++ b/packages/Shell/res/values-lv/strings.xml
@@ -19,10 +19,16 @@
     <string name="app_label" msgid="3701846017049540910">"Aizsargs"</string>
     <string name="bugreport_in_progress_title" msgid="4311705936714972757">"Kļūdas pārskats <xliff:g id="ID">#%d</xliff:g> tiek ģenerēts"</string>
     <string name="bugreport_finished_title" msgid="4429132808670114081">"Kļūdas pārskats <xliff:g id="ID">#%d</xliff:g> reģistrēts"</string>
+    <!-- no translation found for bugreport_finished_pending_screenshot_title (5460883450679439591) -->
+    <skip />
     <string name="bugreport_updating_title" msgid="4423539949559634214">"Informācijas pievienošana kļūdas pārskatam"</string>
     <string name="bugreport_updating_wait" msgid="3322151947853929470">"Lūdzu, uzgaidiet..."</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Velciet pa kreisi, lai kopīgotu savu kļūdu ziņojumu."</string>
     <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"Pieskarieties, lai kopīgotu kļūdas pārskatu."</string>
+    <!-- no translation found for bugreport_finished_pending_screenshot_text (1474435374470177193) -->
+    <skip />
+    <!-- no translation found for bugreport_finished_pending_screenshot_text (1474435374470177193) -->
+    <skip />
     <string name="bugreport_confirm" msgid="5130698467795669780">"Kļūdu pārskatā ir iekļauti dati no dažādiem sistēmas žurnālfailiem, tostarp personas dati un privāta informācija. Kļūdu pārskatus ieteicams kopīgot tikai ar uzticamām lietotnēm un lietotājiem."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Rādīt šo ziņojumu nākamajā reizē"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"Kļūdu ziņojumi"</string>
@@ -34,6 +40,7 @@
     <string name="bugreport_screenshot_failed" msgid="5853049140806834601">"Nevarēja veikt ekrānuzņēmumu."</string>
     <string name="bugreport_info_dialog_title" msgid="1355948594292983332">"Kļūdas pārskats <xliff:g id="ID">#%d</xliff:g>: detalizēta informācija"</string>
     <string name="bugreport_info_name" msgid="4414036021935139527">"Faila nosaukums"</string>
-    <string name="bugreport_info_title" msgid="5599558206004371052">"Nosaukums"</string>
-    <string name="bugreport_info_description" msgid="4117088998733546784">"Detalizēts apraksts"</string>
+    <string name="bugreport_info_title" msgid="2306030793918239804">"Kļūdas nosaukums"</string>
+    <string name="bugreport_info_description" msgid="5072835127481627722">"Kļūdas kopsavilkums"</string>
+    <string name="save" msgid="4781509040564835759">"Saglabāt"</string>
 </resources>
diff --git a/packages/Shell/res/values-mk-rMK/strings.xml b/packages/Shell/res/values-mk-rMK/strings.xml
index 500196d..f274f6d 100644
--- a/packages/Shell/res/values-mk-rMK/strings.xml
+++ b/packages/Shell/res/values-mk-rMK/strings.xml
@@ -19,10 +19,16 @@
     <string name="app_label" msgid="3701846017049540910">"Обвивка"</string>
     <string name="bugreport_in_progress_title" msgid="4311705936714972757">"Се генерира извештајот за грешки <xliff:g id="ID">#%d</xliff:g>"</string>
     <string name="bugreport_finished_title" msgid="4429132808670114081">"Извештајот за грешки <xliff:g id="ID">#%d</xliff:g> е снимен"</string>
+    <!-- no translation found for bugreport_finished_pending_screenshot_title (5460883450679439591) -->
+    <skip />
     <string name="bugreport_updating_title" msgid="4423539949559634214">"Се додаваат детали на извештајот за грешка"</string>
     <string name="bugreport_updating_wait" msgid="3322151947853929470">"Почекајте..."</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Повлечете налево за да споделите пријава за грешка"</string>
     <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"Допрете за да го споделите извештајот за грешки"</string>
+    <!-- no translation found for bugreport_finished_pending_screenshot_text (1474435374470177193) -->
+    <skip />
+    <!-- no translation found for bugreport_finished_pending_screenshot_text (1474435374470177193) -->
+    <skip />
     <string name="bugreport_confirm" msgid="5130698467795669780">"Извештаите за грешка содржат податоци од разни датотеки за евиденција на системот, вклучувајќи лични и приватни информации. Извештаите за грешка споделувајте ги само со апликации и луѓе на коишто им верувате."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Прикажи ја поракава следниот пат"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"Извештаи за грешки"</string>
@@ -34,6 +40,7 @@
     <string name="bugreport_screenshot_failed" msgid="5853049140806834601">"Не може да се направи слика од екранот."</string>
     <string name="bugreport_info_dialog_title" msgid="1355948594292983332">"Детали за извештајот за грешки <xliff:g id="ID">#%d</xliff:g>"</string>
     <string name="bugreport_info_name" msgid="4414036021935139527">"Име на датотека"</string>
-    <string name="bugreport_info_title" msgid="5599558206004371052">"Наслов"</string>
-    <string name="bugreport_info_description" msgid="4117088998733546784">"Детален опис"</string>
+    <string name="bugreport_info_title" msgid="2306030793918239804">"Наслов на грешката"</string>
+    <string name="bugreport_info_description" msgid="5072835127481627722">"Преглед на грешката"</string>
+    <string name="save" msgid="4781509040564835759">"Зачувај"</string>
 </resources>
diff --git a/packages/Shell/res/values-ml-rIN/strings.xml b/packages/Shell/res/values-ml-rIN/strings.xml
index 696aab2..d5d2e4e 100644
--- a/packages/Shell/res/values-ml-rIN/strings.xml
+++ b/packages/Shell/res/values-ml-rIN/strings.xml
@@ -19,10 +19,16 @@
     <string name="app_label" msgid="3701846017049540910">"ഷെൽ"</string>
     <string name="bugreport_in_progress_title" msgid="4311705936714972757">"ബഗ് റിപ്പോർട്ട് <xliff:g id="ID">#%d</xliff:g> സൃഷ്ടിക്കുന്നു"</string>
     <string name="bugreport_finished_title" msgid="4429132808670114081">"ബഗ് റിപ്പോർട്ട് <xliff:g id="ID">#%d</xliff:g> ക്യാപ്ചർ ചെയ്തു"</string>
+    <!-- no translation found for bugreport_finished_pending_screenshot_title (5460883450679439591) -->
+    <skip />
     <string name="bugreport_updating_title" msgid="4423539949559634214">"ബഗ് റിപ്പോർട്ടിലേക്ക് വിശദാംശങ്ങൾ ചേർക്കുന്നു"</string>
     <string name="bugreport_updating_wait" msgid="3322151947853929470">"കാത്തിരിക്കുക..."</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"നിങ്ങളുടെ ബഗ് റിപ്പോർട്ട് പങ്കിടുന്നതിന് ഇടത്തേയ്‌ക്ക് സ്വൈപ്പുചെയ്യുക"</string>
     <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"നിങ്ങളുടെ ബഗ് റിപ്പോർട്ട് പങ്കിടാൻ ടാപ്പുചെയ്യുക"</string>
+    <!-- no translation found for bugreport_finished_pending_screenshot_text (1474435374470177193) -->
+    <skip />
+    <!-- no translation found for bugreport_finished_pending_screenshot_text (1474435374470177193) -->
+    <skip />
     <string name="bugreport_confirm" msgid="5130698467795669780">"വ്യക്തിഗതവും സ്വകാര്യവുമായ വിവരങ്ങൾ ഉൾപ്പെടെ, സിസ്റ്റത്തിന്റെ നിരവധി ലോഗ് ഫയലുകളിൽ നിന്നുള്ള ഡാറ്റ, ബഗ് റിപ്പോർട്ടുകളിൽ അടങ്ങിയിരിക്കുന്നു. നിങ്ങൾ വിശ്വസിക്കുന്ന അപ്ലിക്കേഷനുകൾക്കും ആളുകൾക്കും മാത്രം ബഗ് റിപ്പോർട്ടുകൾ പങ്കിടുക."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"ഈ സന്ദേശം അടുത്ത തവണ ദൃശ്യമാക്കുക"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"ബഗ് റിപ്പോർട്ടുകൾ"</string>
@@ -34,6 +40,7 @@
     <string name="bugreport_screenshot_failed" msgid="5853049140806834601">"സ്ക്രീൻഷോട്ട് എടുക്കാൻ കഴിഞ്ഞില്ല."</string>
     <string name="bugreport_info_dialog_title" msgid="1355948594292983332">"ബഗ് റിപ്പോർട്ട് <xliff:g id="ID">#%d</xliff:g> വിശദാംശങ്ങൾ"</string>
     <string name="bugreport_info_name" msgid="4414036021935139527">"ഫയല്‍നാമം"</string>
-    <string name="bugreport_info_title" msgid="5599558206004371052">"പേര്"</string>
-    <string name="bugreport_info_description" msgid="4117088998733546784">"വിശദമായ വിവരണം"</string>
+    <string name="bugreport_info_title" msgid="2306030793918239804">"ബഗിന്റെ പേര്"</string>
+    <string name="bugreport_info_description" msgid="5072835127481627722">"ബഗ് സംഗ്രഹം"</string>
+    <string name="save" msgid="4781509040564835759">"സംരക്ഷിക്കുക"</string>
 </resources>
diff --git a/packages/Shell/res/values-mn-rMN/strings.xml b/packages/Shell/res/values-mn-rMN/strings.xml
index 62d83cb..cce2107 100644
--- a/packages/Shell/res/values-mn-rMN/strings.xml
+++ b/packages/Shell/res/values-mn-rMN/strings.xml
@@ -19,10 +19,16 @@
     <string name="app_label" msgid="3701846017049540910">"Шел"</string>
     <string name="bugreport_in_progress_title" msgid="4311705936714972757">"Програмд гарсан алдааны мэдээллийн <xliff:g id="ID">#%d</xliff:g> үүсгэгдэж байна"</string>
     <string name="bugreport_finished_title" msgid="4429132808670114081">"Програмд гарсан алдааны мэдээллийн <xliff:g id="ID">#%d</xliff:g>-г бүртгэгдлээ"</string>
+    <!-- no translation found for bugreport_finished_pending_screenshot_title (5460883450679439591) -->
+    <skip />
     <string name="bugreport_updating_title" msgid="4423539949559634214">"Алдааны тайланд дэлгэрэнгүй мэдээлэл нэмж байна"</string>
     <string name="bugreport_updating_wait" msgid="3322151947853929470">"Түр хүлээнэ үү..."</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Өөрийн согог репортыг хуваалцахын тулд зүүн шудрана уу"</string>
     <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"Програмд гарсан алдааны мэдээллээ хуваалцах бол дарна уу"</string>
+    <!-- no translation found for bugreport_finished_pending_screenshot_text (1474435374470177193) -->
+    <skip />
+    <!-- no translation found for bugreport_finished_pending_screenshot_text (1474435374470177193) -->
+    <skip />
     <string name="bugreport_confirm" msgid="5130698467795669780">"Алдааны репорт нь хувийн болон нууц мэдээлэл зэргийг агуулсан системийн төрөл бүрийн лог файлын датаг агуулна. Алдааны репортыг зөвхөн итгэлтэй апп болон хүмүүст хуваалцана уу."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Энэ мессежийг дараагийн удаа харуулах"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"Гэмтлийн тухай тайлан"</string>
@@ -34,6 +40,7 @@
     <string name="bugreport_screenshot_failed" msgid="5853049140806834601">"Дэлгэцийн зураг авах боломжгүй."</string>
     <string name="bugreport_info_dialog_title" msgid="1355948594292983332">"Програмд гарсан алдааны мэдээллийн <xliff:g id="ID">#%d</xliff:g>-ны дэлгэрэнгүй"</string>
     <string name="bugreport_info_name" msgid="4414036021935139527">"Файлын нэр"</string>
-    <string name="bugreport_info_title" msgid="5599558206004371052">"Гарчиг"</string>
-    <string name="bugreport_info_description" msgid="4117088998733546784">"Дэлгэрэнгүй тайлбар"</string>
+    <string name="bugreport_info_title" msgid="2306030793918239804">"Алдааны нэр"</string>
+    <string name="bugreport_info_description" msgid="5072835127481627722">"Алдааны хураангуй"</string>
+    <string name="save" msgid="4781509040564835759">"Хадгалах"</string>
 </resources>
diff --git a/packages/Shell/res/values-mr-rIN/strings.xml b/packages/Shell/res/values-mr-rIN/strings.xml
index e6b2b04..8eb5686 100644
--- a/packages/Shell/res/values-mr-rIN/strings.xml
+++ b/packages/Shell/res/values-mr-rIN/strings.xml
@@ -19,10 +19,13 @@
     <string name="app_label" msgid="3701846017049540910">"शेल"</string>
     <string name="bugreport_in_progress_title" msgid="4311705936714972757">"दोष अहवाल <xliff:g id="ID">#%d</xliff:g> तयार केला जात आहे"</string>
     <string name="bugreport_finished_title" msgid="4429132808670114081">"दोष अहवाल <xliff:g id="ID">#%d</xliff:g> कॅप्चर केला"</string>
+    <string name="bugreport_finished_pending_screenshot_title" msgid="5460883450679439591">"दोष अहवाल <xliff:g id="ID">#%d</xliff:g> कॅप्चर केला परंतु स्क्रीनशॉट प्रलंबित आहे"</string>
     <string name="bugreport_updating_title" msgid="4423539949559634214">"दोष अहवालामध्‍ये तपशील जोडत आहे"</string>
     <string name="bugreport_updating_wait" msgid="3322151947853929470">"कृपया प्रतीक्षा करा..."</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"आपला दोष अहवाल सामायिक करण्यासाठी डावीकडे स्वाइप करा"</string>
     <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"आपला दोष अहवाल सामायिक करण्यासाठी टॅप करा"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"स्क्रीनशॉट शिवाय आपला दोष अहवाल सामायिक करण्यासाठी टॅप करा किंवा समाप्त करण्यासाठी स्क्रीनशॉटची प्रतीक्षा करा"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"स्क्रीनशॉट शिवाय आपला दोष अहवाल सामायिक करण्यासाठी टॅप करा किंवा समाप्त करण्यासाठी स्क्रीनशॉटची प्रतीक्षा करा"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"दोष अहवालांमध्‍ये वैयक्तिक आणि खाजगी माहितीसह, सिस्‍टमच्‍या अनेक लॉग फायलींमधील डेटा असतो. केवळ आपला विश्वास असलेल्‍या अ‍ॅप्‍स आणि लोकांसह दोष अहवाल सामायिक करा."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"पुढील वेळी हा संदेश दर्शवा"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"दोष अहवाल"</string>
@@ -34,6 +37,7 @@
     <string name="bugreport_screenshot_failed" msgid="5853049140806834601">"स्क्रीनशॉट घेणे शक्य झाले नाही."</string>
     <string name="bugreport_info_dialog_title" msgid="1355948594292983332">"दोष अहवाल <xliff:g id="ID">#%d</xliff:g> तपशील"</string>
     <string name="bugreport_info_name" msgid="4414036021935139527">"फाईलनाव"</string>
-    <string name="bugreport_info_title" msgid="5599558206004371052">"शीर्षक"</string>
-    <string name="bugreport_info_description" msgid="4117088998733546784">"तपशीलवार वर्णन"</string>
+    <string name="bugreport_info_title" msgid="2306030793918239804">"दोष शीर्षक"</string>
+    <string name="bugreport_info_description" msgid="5072835127481627722">"दोष सारांश"</string>
+    <string name="save" msgid="4781509040564835759">"जतन करा"</string>
 </resources>
diff --git a/packages/Shell/res/values-ms-rMY/strings.xml b/packages/Shell/res/values-ms-rMY/strings.xml
index 1d04253..b23a382 100644
--- a/packages/Shell/res/values-ms-rMY/strings.xml
+++ b/packages/Shell/res/values-ms-rMY/strings.xml
@@ -19,10 +19,16 @@
     <string name="app_label" msgid="3701846017049540910">"Shell"</string>
     <string name="bugreport_in_progress_title" msgid="4311705936714972757">"Laporan pepijat <xliff:g id="ID">#%d</xliff:g> sedang dijana"</string>
     <string name="bugreport_finished_title" msgid="4429132808670114081">"Laporan pepijat <xliff:g id="ID">#%d</xliff:g> telah ditangkap"</string>
+    <!-- no translation found for bugreport_finished_pending_screenshot_title (5460883450679439591) -->
+    <skip />
     <string name="bugreport_updating_title" msgid="4423539949559634214">"Menambahkan butiran pada laporan pepijat"</string>
     <string name="bugreport_updating_wait" msgid="3322151947853929470">"Sila tunggu…"</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Leret ke kiri untuk berkongsi laporan pepijat anda"</string>
     <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"Ketik untuk berkongsi laporan pepijat anda"</string>
+    <!-- no translation found for bugreport_finished_pending_screenshot_text (1474435374470177193) -->
+    <skip />
+    <!-- no translation found for bugreport_finished_pending_screenshot_text (1474435374470177193) -->
+    <skip />
     <string name="bugreport_confirm" msgid="5130698467795669780">"Laporan pepijat mengandungi data dari pelbagai fail log sistem, termasuk maklumat peribadi dan sulit. Kongsikan laporan pepijat hanya dengan apl dan orang yang anda percayai."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Tunjukkan mesej ini pada masa akan datang"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"Laporan pepijat"</string>
@@ -34,6 +40,7 @@
     <string name="bugreport_screenshot_failed" msgid="5853049140806834601">"Tangkapan skrin tidak dapat diambil."</string>
     <string name="bugreport_info_dialog_title" msgid="1355948594292983332">"Butiran laporan pepijat <xliff:g id="ID">#%d</xliff:g>"</string>
     <string name="bugreport_info_name" msgid="4414036021935139527">"Nama fail"</string>
-    <string name="bugreport_info_title" msgid="5599558206004371052">"Tajuk"</string>
-    <string name="bugreport_info_description" msgid="4117088998733546784">"Perihalan terperinci"</string>
+    <string name="bugreport_info_title" msgid="2306030793918239804">"Tajuk pepijat"</string>
+    <string name="bugreport_info_description" msgid="5072835127481627722">"Ringkasan pepijat"</string>
+    <string name="save" msgid="4781509040564835759">"Simpan"</string>
 </resources>
diff --git a/packages/Shell/res/values-my-rMM/strings.xml b/packages/Shell/res/values-my-rMM/strings.xml
index f63c8c5..cecd20f 100644
--- a/packages/Shell/res/values-my-rMM/strings.xml
+++ b/packages/Shell/res/values-my-rMM/strings.xml
@@ -19,10 +19,13 @@
     <string name="app_label" msgid="3701846017049540910">"အခွံ"</string>
     <string name="bugreport_in_progress_title" msgid="4311705936714972757">"ချွတ်ယွင်းမှုအစီရင်ခံချက် <xliff:g id="ID">#%d</xliff:g> ကိုထုတ်နေပါသည်"</string>
     <string name="bugreport_finished_title" msgid="4429132808670114081">"ချွတ်ယွင်းမှုအစီရင်ခံချက် <xliff:g id="ID">#%d</xliff:g> ကိုရယူထားပြီးပါပြီ"</string>
+    <string name="bugreport_finished_pending_screenshot_title" msgid="5460883450679439591">"ချွတ်ယွင်းချက် အစီရင်ခံစာ <xliff:g id="ID">#%d</xliff:g> ဖမ်းယူထားသည် သို့သော် မျက်နှာပြင်ဓာတ်ပုံမှတ်တမ်းတင်ခြင်း စောင့်ဆိုင်းနေသည်"</string>
     <string name="bugreport_updating_title" msgid="4423539949559634214">"ချွတ်ယွင်းချက်အစီရင်ခံချက်သို့ အသေးစိတ်များပေါင်းထည့်ရန်"</string>
     <string name="bugreport_updating_wait" msgid="3322151947853929470">"ခေတ္တစောင့်ပါ..."</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"သင်၏ ဘာဂ် အစီရင်ခံစာကို မျှပေးရန် ဘယ်ဘက်သို့ ပွတ်ဆွဲရန်"</string>
     <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"သင့်ချွတ်ယွင်းမှုအစီရင်ခံချက်ကို မျှဝေရန် တို့ပါ"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"ချွတ်ယွင်းချက်အစီရင်ခံချက်ကို မျက်နှာပြင်ဓတ်ပုံမှတ်တမ်း မပါဘဲမျှဝေရန် တို့ပါ သို့မဟုတ် မျက်နှာပြင်ဓာတ်ပုံမှတ်တမ်းတင်ခြင်း ပြီးဆုံးသည်အထိ စောင့်ပါ"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"ချွတ်ယွင်းချက်အစီရင်ခံချက်ကို မျက်နှာပြင်ဓတ်ပုံမှတ်တမ်း မပါဘဲမျှဝေရန် တို့ပါ သို့မဟုတ် မျက်နှာပြင်ဓာတ်ပုံမှတ်တမ်းတင်ခြင်း ပြီးဆုံးသည်အထိ စောင့်ပါ"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"အမှားအယွင်း မှတ်တမ်းမှာ ပါရှိသော အချက်အလက်များမှာ ကိုယ်ရေးကိုယ်တာ နဲ့ လုံခြုံရေး အချက်အလက်များပါဝင်သော စနစ်မှ ပြုလုပ်မှု မှတ်တမ်းများ ဖြစ်ပါသည်၊ အမှားအယွင်း မှတ်တမ်းများကို ယုံကြည်ရသော အပလီကေးရှင်းများနဲ့ လူများကိုသာ ပေးဝေပြသမှု လုပ်ပါရန်။"</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"ဤစာတန်းကို နောက်တစ်ခါတွင် ပြရန်"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"ချို့ယွင်းမှု အစီရင်ခံစာများ"</string>
@@ -34,6 +37,7 @@
     <string name="bugreport_screenshot_failed" msgid="5853049140806834601">"မျက်နှာပြင် လျှပ်တစ်ပြက်ပုံ မရိုက်နိုင်ပါ"</string>
     <string name="bugreport_info_dialog_title" msgid="1355948594292983332">"ချွတ်ယွင်းမှုအစီရင်ခံချက် <xliff:g id="ID">#%d</xliff:g> အသေးစိတ်များ"</string>
     <string name="bugreport_info_name" msgid="4414036021935139527">"ဖိုင်အမည်"</string>
-    <string name="bugreport_info_title" msgid="5599558206004371052">"ခေါင်းစဉ်"</string>
-    <string name="bugreport_info_description" msgid="4117088998733546784">"အသေးစိတ် ဖော်ပြချက်"</string>
+    <string name="bugreport_info_title" msgid="2306030793918239804">"ချွတ်ယွင်းချက် ခေါင်းစဉ်"</string>
+    <string name="bugreport_info_description" msgid="5072835127481627722">"ချွတ်ယွင်းချက် အကျဉ်းချုပ်"</string>
+    <string name="save" msgid="4781509040564835759">"သိမ်းဆည်းပါ"</string>
 </resources>
diff --git a/packages/Shell/res/values-nb/strings.xml b/packages/Shell/res/values-nb/strings.xml
index 328e8ae..0605e0e 100644
--- a/packages/Shell/res/values-nb/strings.xml
+++ b/packages/Shell/res/values-nb/strings.xml
@@ -19,10 +19,13 @@
     <string name="app_label" msgid="3701846017049540910">"Kommandoliste"</string>
     <string name="bugreport_in_progress_title" msgid="4311705936714972757">"Feilrapporten <xliff:g id="ID">#%d</xliff:g> blir generert"</string>
     <string name="bugreport_finished_title" msgid="4429132808670114081">"Feilrapporten <xliff:g id="ID">#%d</xliff:g> er fullført"</string>
+    <string name="bugreport_finished_pending_screenshot_title" msgid="5460883450679439591">"Feilrapporten <xliff:g id="ID">#%d</xliff:g> er hentet. Venter på skjermdumpen"</string>
     <string name="bugreport_updating_title" msgid="4423539949559634214">"Legger til detaljer i feilrapporten"</string>
     <string name="bugreport_updating_wait" msgid="3322151947853929470">"Vent litt"</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Sveip til venstre for å dele feilrapporten din"</string>
     <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"Trykk for å dele feilrapporten"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"Trykk for å dele feilrapporten uten noen skjermdump, eller vent til skjermdumpen er klar"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"Trykk for å dele feilrapporten uten noen skjermdump, eller vent til skjermdumpen er klar"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"Feilrapporter inkluderer data fra systemets forskjellige loggfiler. Dette omfatter personlig og privat informasjon. Du bør bare dele feilrapporter med apper og folk du stoler på."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Vis denne meldingen neste gang"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"Feilrapporter"</string>
@@ -34,6 +37,7 @@
     <string name="bugreport_screenshot_failed" msgid="5853049140806834601">"Skjermdumpen kunne ikke tas."</string>
     <string name="bugreport_info_dialog_title" msgid="1355948594292983332">"Detaljer om feilrapporten <xliff:g id="ID">#%d</xliff:g>"</string>
     <string name="bugreport_info_name" msgid="4414036021935139527">"Filnavn"</string>
-    <string name="bugreport_info_title" msgid="5599558206004371052">"Tittel"</string>
-    <string name="bugreport_info_description" msgid="4117088998733546784">"Detaljert beskrivelse"</string>
+    <string name="bugreport_info_title" msgid="2306030793918239804">"Navn på feil"</string>
+    <string name="bugreport_info_description" msgid="5072835127481627722">"Oppsummering av feil"</string>
+    <string name="save" msgid="4781509040564835759">"Lagre"</string>
 </resources>
diff --git a/packages/Shell/res/values-ne-rNP/strings.xml b/packages/Shell/res/values-ne-rNP/strings.xml
index 62bfead..9fb1bcb 100644
--- a/packages/Shell/res/values-ne-rNP/strings.xml
+++ b/packages/Shell/res/values-ne-rNP/strings.xml
@@ -19,10 +19,13 @@
     <string name="app_label" msgid="3701846017049540910">"सेल"</string>
     <string name="bugreport_in_progress_title" msgid="4311705936714972757">"बग रिपोर्ट <xliff:g id="ID">#%d</xliff:g>लाई निकालिदैछ"</string>
     <string name="bugreport_finished_title" msgid="4429132808670114081">"बग रिपोर्ट <xliff:g id="ID">#%d</xliff:g>लाई कैद गरियो"</string>
+    <string name="bugreport_finished_pending_screenshot_title" msgid="5460883450679439591">"बग रिपोर्ट <xliff:g id="ID">#%d</xliff:g> लाई क्याप्चर गरियो तर स्क्रिनसट बाँकी रहेको छ"</string>
     <string name="bugreport_updating_title" msgid="4423539949559634214">"बग रिपोर्टमा विवरणहरू थप्दै"</string>
     <string name="bugreport_updating_wait" msgid="3322151947853929470">"कृपया प्रतीक्षा गर्नुहोला..."</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"तपाईँको बग रिपोर्ट साझेदारी गर्न बायाँ स्वाइप गर्नुहोस्"</string>
     <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"तपाईंको बग रिपोर्टलाई साझेदारी गर्न ट्याप गर्नुहोस्"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"तपाईँको बग रिपोर्टलाई स्क्रिनसट बिना साझेदारी गर्नका लागि ट्याप गर्नुहोस् वा स्क्रिनसट लिने प्रक्रिया पूरा हुने प्रतीक्षा गर्नुहोस्"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"तपाईँको बग रिपोर्टलाई स्क्रिनसट बिना साझेदारी गर्नका लागि ट्याप गर्नुहोस् वा स्क्रिनसट लिने प्रक्रिया पूरा हुने प्रतीक्षा गर्नुहोस्"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"बग रिपोर्टहरूमा प्रणालीका विभिन्न लग फाइलहरूबाट व्यक्तिगत तथा नीजि सूचनासहितको डेटा रहन्छ।  बग रिपोर्टहरू अनुप्रयोगहरू र तपाईँले विश्वास गरेका व्यक्तिहरूसँग मात्र साझेदारी गर्नुहोस्।"</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"यो सन्देश अर्को पटक देखाउनुहोस्"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"बग रिपोर्टहरू"</string>
@@ -34,6 +37,7 @@
     <string name="bugreport_screenshot_failed" msgid="5853049140806834601">"स्क्रिनशट लिन सकिएन।"</string>
     <string name="bugreport_info_dialog_title" msgid="1355948594292983332">"बग रिपोर्ट <xliff:g id="ID">#%d</xliff:g>का विवरणहरू"</string>
     <string name="bugreport_info_name" msgid="4414036021935139527">"फाइलको नाम"</string>
-    <string name="bugreport_info_title" msgid="5599558206004371052">"शीर्षक"</string>
-    <string name="bugreport_info_description" msgid="4117088998733546784">"विस्तृत विवरण"</string>
+    <string name="bugreport_info_title" msgid="2306030793918239804">"बगको शीर्षक"</string>
+    <string name="bugreport_info_description" msgid="5072835127481627722">"बगको सारांश"</string>
+    <string name="save" msgid="4781509040564835759">"सुरक्षित गर्नुहोस्"</string>
 </resources>
diff --git a/packages/Shell/res/values-nl/strings.xml b/packages/Shell/res/values-nl/strings.xml
index 2f4b215..3022691 100644
--- a/packages/Shell/res/values-nl/strings.xml
+++ b/packages/Shell/res/values-nl/strings.xml
@@ -19,10 +19,13 @@
     <string name="app_label" msgid="3701846017049540910">"Shell"</string>
     <string name="bugreport_in_progress_title" msgid="4311705936714972757">"Bugrapport <xliff:g id="ID">#%d</xliff:g> wordt gegenereerd"</string>
     <string name="bugreport_finished_title" msgid="4429132808670114081">"Bugrapport <xliff:g id="ID">#%d</xliff:g> is vastgelegd"</string>
+    <string name="bugreport_finished_pending_screenshot_title" msgid="5460883450679439591">"Bugrapport <xliff:g id="ID">#%d</xliff:g> vastgelegd, screenshot in behandeling"</string>
     <string name="bugreport_updating_title" msgid="4423539949559634214">"Details toevoegen aan het bugrapport"</string>
     <string name="bugreport_updating_wait" msgid="3322151947853929470">"Even geduld…"</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Veeg naar links om je bugmelding te delen"</string>
     <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"Tik om je bugrapport te delen"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"Tik om je bugrapport te delen zonder screenshot of wacht tot het screenshot is voltooid"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"Tik om je bugrapport te delen zonder screenshot of wacht tot het screenshot is voltooid"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"Foutenrapporten bevatten gegevens uit de verschillende logbestanden van het systeem, waaronder persoonlijke en privégegevens. Deel foutenrapporten alleen met apps en mensen die u vertrouwt."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Dit bericht de volgende keer weergeven"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"Foutenrapporten"</string>
@@ -34,6 +37,7 @@
     <string name="bugreport_screenshot_failed" msgid="5853049140806834601">"Screenshot kan niet worden gemaakt."</string>
     <string name="bugreport_info_dialog_title" msgid="1355948594292983332">"Details van bugrapport <xliff:g id="ID">#%d</xliff:g>"</string>
     <string name="bugreport_info_name" msgid="4414036021935139527">"Bestandsnaam"</string>
-    <string name="bugreport_info_title" msgid="5599558206004371052">"Titel"</string>
-    <string name="bugreport_info_description" msgid="4117088998733546784">"Gedetailleerde beschrijving"</string>
+    <string name="bugreport_info_title" msgid="2306030793918239804">"Titel van bug"</string>
+    <string name="bugreport_info_description" msgid="5072835127481627722">"Overzicht van bug"</string>
+    <string name="save" msgid="4781509040564835759">"Opslaan"</string>
 </resources>
diff --git a/packages/Shell/res/values-pa-rIN/strings.xml b/packages/Shell/res/values-pa-rIN/strings.xml
index dc2277f..d44daf7 100644
--- a/packages/Shell/res/values-pa-rIN/strings.xml
+++ b/packages/Shell/res/values-pa-rIN/strings.xml
@@ -19,10 +19,13 @@
     <string name="app_label" msgid="3701846017049540910">"ਸ਼ੈਲ"</string>
     <string name="bugreport_in_progress_title" msgid="4311705936714972757">"ਬੱਗ ਰਿਪੋਰਟ <xliff:g id="ID">#%d</xliff:g> ਸਿਰਜੀ ਜਾ ਰਹੀ ਹੈ"</string>
     <string name="bugreport_finished_title" msgid="4429132808670114081">"ਬੱਗ ਰਿਪੋਰਟ <xliff:g id="ID">#%d</xliff:g> ਕੈਪਚਰ ਕੀਤੀ ਗਈ"</string>
+    <string name="bugreport_finished_pending_screenshot_title" msgid="5460883450679439591">"ਬੱਗ ਰਿਪੋਰਟ <xliff:g id="ID">#%d</xliff:g> ਕੈਪਚਰ ਕੀਤੀ ਗਈ ਪਰ ਸਕ੍ਰੀਨਸ਼ਾਟ ਅਧੂਰਾ ਹੈ"</string>
     <string name="bugreport_updating_title" msgid="4423539949559634214">"ਬੱਗ ਰਿਪੋਰਟ ਵਿੱਚ ਵੇਰਵਿਆਂ ਨੂੰ ਸ਼ਾਮਲ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ"</string>
     <string name="bugreport_updating_wait" msgid="3322151947853929470">"ਕਿਰਪਾ ਕਰਕੇ ਉਡੀਕ ਕਰੋ..."</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"ਤੁਹਾਡੀ ਬਗ ਰਿਪੋਰਟ ਸ਼ੇਅਰ ਕਰਨ ਲਈ ਖੱਬੇ ਪਾਸੇ ਸਵਾਈਪ ਕਰੋ"</string>
     <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"ਆਪਣੀ ਬੱਗ ਰਿਪੋਰਟ ਸਾਂਝੀ ਕਰਨ ਲਈ ਟੈਪ ਕਰੋ"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"ਸਕ੍ਰੀਨਸ਼ਾਟ ਦੇ ਬਿਨਾਂ ਆਪਣੀ ਬੱਗ ਰਿਪੋਰਟ ਨੂੰ ਸਾਂਝੀ ਕਰਨ ਲਈ ਟੈਪ ਕਰੋ ਜਾਂ ਸਕ੍ਰੀਨਸ਼ਾਟ ਦੇ ਪੂਰੇ ਹੋਣ ਦੀ ਉਡੀਕ ਕਰੋ"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"ਸਕ੍ਰੀਨਸ਼ਾਟ ਦੇ ਬਿਨਾਂ ਆਪਣੀ ਬੱਗ ਰਿਪੋਰਟ ਨੂੰ ਸਾਂਝੀ ਕਰਨ ਲਈ ਟੈਪ ਕਰੋ ਜਾਂ ਸਕ੍ਰੀਨਸ਼ਾਟ ਦੇ ਪੂਰੇ ਹੋਣ ਦੀ ਉਡੀਕ ਕਰੋ"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"ਬਗ ਰਿਪੋਰਟਾਂ ਵਿੱਚ ਸਿਸਟਮ ਦੀਆਂ ਭਿੰਨ ਲੌਗ ਫਾਈਲਾਂ ਦਾ ਡਾਟਾ ਹੁੰਦਾ ਹੈ, ਨਿੱਜੀ ਅਤੇ ਪ੍ਰਾਈਵੇਟ ਜਾਣਕਾਰੀ ਸਮੇਤ। ਕੇਵਲ ਉਹਨਾਂ ਐਪਸ ਅਤੇ ਲੋਕਾਂ ਨਾਲ ਬਗ ਰਿਪੋਰਟਾਂ ਸ਼ੇਅਰ ਕਰੋ, ਜਿਹਨਾਂ ਤੇ ਤੁਸੀਂ ਭਰੋਸਾ ਕਰਦੇ ਹੋ।"</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"ਅਗਲੀ ਵਾਰ ਇਹ ਸੁਨੇਹਾ ਦਿਖਾਓ"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"ਬਗ ਰਿਪੋਰਟਾਂ"</string>
@@ -34,6 +37,7 @@
     <string name="bugreport_screenshot_failed" msgid="5853049140806834601">"ਸਕ੍ਰੀਨਸ਼ਾਟ ਨਹੀਂ ਲਿਆ ਜਾ ਸਕਿਆ।"</string>
     <string name="bugreport_info_dialog_title" msgid="1355948594292983332">"ਬੱਗ ਰਿਪੋਰਟ <xliff:g id="ID">#%d</xliff:g> ਵੇਰਵੇ"</string>
     <string name="bugreport_info_name" msgid="4414036021935139527">"ਫ਼ਾਈਲ ਨਾਮ"</string>
-    <string name="bugreport_info_title" msgid="5599558206004371052">"ਸਿਰਲੇਖ"</string>
-    <string name="bugreport_info_description" msgid="4117088998733546784">"ਵਿਸਥਾਰ ਸਹਿਤ ਵਰਣਨ"</string>
+    <string name="bugreport_info_title" msgid="2306030793918239804">"ਬੱਗ ਸਿਰਲੇਖ"</string>
+    <string name="bugreport_info_description" msgid="5072835127481627722">"ਬੱਗ ਸਾਰਾਂਸ਼"</string>
+    <string name="save" msgid="4781509040564835759">"ਰੱਖਿਅਤ ਕਰੋ"</string>
 </resources>
diff --git a/packages/Shell/res/values-pl/strings.xml b/packages/Shell/res/values-pl/strings.xml
index c585568..b4977a4 100644
--- a/packages/Shell/res/values-pl/strings.xml
+++ b/packages/Shell/res/values-pl/strings.xml
@@ -19,10 +19,13 @@
     <string name="app_label" msgid="3701846017049540910">"Powłoka"</string>
     <string name="bugreport_in_progress_title" msgid="4311705936714972757">"Generuję raport o błędzie <xliff:g id="ID">#%d</xliff:g>"</string>
     <string name="bugreport_finished_title" msgid="4429132808670114081">"Raport o błędzie <xliff:g id="ID">#%d</xliff:g> został zapisany"</string>
+    <string name="bugreport_finished_pending_screenshot_title" msgid="5460883450679439591">"Raport <xliff:g id="ID">#%d</xliff:g> zapisany. Zrzut nie jest jeszcze gotowy"</string>
     <string name="bugreport_updating_title" msgid="4423539949559634214">"Dodaję szczegóły do raportu o błędzie"</string>
     <string name="bugreport_updating_wait" msgid="3322151947853929470">"Czekaj..."</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Przesuń palcem w lewo, by udostępnić swoje zgłoszenie błędu"</string>
     <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"Kliknij, by udostępnić raport o błędzie"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"Kliknij, by udostępnić raport o błędzie bez zrzutu ekranu, lub poczekaj, aż zostanie on wygenerowany"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"Kliknij, by udostępnić raport o błędzie bez zrzutu ekranu, lub poczekaj, aż zostanie on wygenerowany"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"Raporty o błędach zawierają dane z różnych plików dzienników systemu, w tym dane osobowe i prywatne. Udostępniaj je tylko aplikacjom i osobom, którym ufasz."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Pokaż ten komunikat następnym razem"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"Raporty o błędach"</string>
@@ -34,6 +37,7 @@
     <string name="bugreport_screenshot_failed" msgid="5853049140806834601">"Nie udało się zrobić zrzutu ekranu."</string>
     <string name="bugreport_info_dialog_title" msgid="1355948594292983332">"Szczegóły raportu o błędzie <xliff:g id="ID">#%d</xliff:g>"</string>
     <string name="bugreport_info_name" msgid="4414036021935139527">"Nazwa pliku"</string>
-    <string name="bugreport_info_title" msgid="5599558206004371052">"Tytuł"</string>
-    <string name="bugreport_info_description" msgid="4117088998733546784">"Szczegółowy opis"</string>
+    <string name="bugreport_info_title" msgid="2306030793918239804">"Tytuł raportu o błędzie"</string>
+    <string name="bugreport_info_description" msgid="5072835127481627722">"Podsumowanie raportu o błędzie"</string>
+    <string name="save" msgid="4781509040564835759">"Zapisz"</string>
 </resources>
diff --git a/packages/Shell/res/values-pt-rBR/strings.xml b/packages/Shell/res/values-pt-rBR/strings.xml
index fc6e21c..438c031 100644
--- a/packages/Shell/res/values-pt-rBR/strings.xml
+++ b/packages/Shell/res/values-pt-rBR/strings.xml
@@ -19,10 +19,16 @@
     <string name="app_label" msgid="3701846017049540910">"Shell"</string>
     <string name="bugreport_in_progress_title" msgid="4311705936714972757">"O relatório do bug <xliff:g id="ID">#%d</xliff:g> está sendo gerado"</string>
     <string name="bugreport_finished_title" msgid="4429132808670114081">"Relatório do bug <xliff:g id="ID">#%d</xliff:g> capturado"</string>
+    <!-- no translation found for bugreport_finished_pending_screenshot_title (5460883450679439591) -->
+    <skip />
     <string name="bugreport_updating_title" msgid="4423539949559634214">"Adicionando detalhes ao relatório do bug"</string>
     <string name="bugreport_updating_wait" msgid="3322151947853929470">"Aguarde…"</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Deslize para a esquerda para compartilhar seu relatório de bugs"</string>
     <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"Toque para compartilhar seu relatório do bug"</string>
+    <!-- no translation found for bugreport_finished_pending_screenshot_text (1474435374470177193) -->
+    <skip />
+    <!-- no translation found for bugreport_finished_pending_screenshot_text (1474435374470177193) -->
+    <skip />
     <string name="bugreport_confirm" msgid="5130698467795669780">"Os relatórios de bugs contêm dados de diversos arquivos de registro do sistema, inclusive informações pessoais e particulares. Compartilhe relatórios de bugs somente com apps e pessoas nos quais você confia."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Mostrar esta mensagem da próxima vez"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"Relatórios de bugs"</string>
@@ -34,6 +40,7 @@
     <string name="bugreport_screenshot_failed" msgid="5853049140806834601">"Não foi possível fazer a captura de tela."</string>
     <string name="bugreport_info_dialog_title" msgid="1355948594292983332">"Detalhes do relatório de bugs <xliff:g id="ID">#%d</xliff:g>"</string>
     <string name="bugreport_info_name" msgid="4414036021935139527">"Nome do arquivo"</string>
-    <string name="bugreport_info_title" msgid="5599558206004371052">"Título"</string>
-    <string name="bugreport_info_description" msgid="4117088998733546784">"Descrição detalhada"</string>
+    <string name="bugreport_info_title" msgid="2306030793918239804">"Título do bug"</string>
+    <string name="bugreport_info_description" msgid="5072835127481627722">"Resumo do bug"</string>
+    <string name="save" msgid="4781509040564835759">"Salvar"</string>
 </resources>
diff --git a/packages/Shell/res/values-pt-rPT/strings.xml b/packages/Shell/res/values-pt-rPT/strings.xml
index 252edb1..7daed8b 100644
--- a/packages/Shell/res/values-pt-rPT/strings.xml
+++ b/packages/Shell/res/values-pt-rPT/strings.xml
@@ -19,10 +19,13 @@
     <string name="app_label" msgid="3701846017049540910">"Shell"</string>
     <string name="bugreport_in_progress_title" msgid="4311705936714972757">"O relatório de erro <xliff:g id="ID">#%d</xliff:g> está a ser criado"</string>
     <string name="bugreport_finished_title" msgid="4429132808670114081">"Relatório de erro <xliff:g id="ID">#%d</xliff:g> criado"</string>
+    <string name="bugreport_finished_pending_screenshot_title" msgid="5460883450679439591">"Rel. de erro <xliff:g id="ID">#%d</xliff:g> capturado, captura de ecrã pendente"</string>
     <string name="bugreport_updating_title" msgid="4423539949559634214">"A adicionar detalhes ao relatório de erro"</string>
     <string name="bugreport_updating_wait" msgid="3322151947853929470">"Aguarde..."</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Deslizar rapidamente para a esquerda para partilhar o seu relatório de erros"</string>
     <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"Toque para partilhar o relatório de erro"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"Toque para partilhar o relatório de erro sem uma captura de ecrã ou aguarde a conclusão da mesma"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"Toque para partilhar o relatório de erro sem uma captura de ecrã ou aguarde a conclusão da mesma"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"Os relatórios de erros incluem dados de vários ficheiros de registo do sistema, nomeadamente informações pessoais e privadas. Partilhe relatórios de erros apenas com aplicações e pessoas fidedignas."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Mostrar esta mensagem da próxima vez"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"Relatórios de erros"</string>
@@ -34,6 +37,7 @@
     <string name="bugreport_screenshot_failed" msgid="5853049140806834601">"Não foi possível tirar a captura de ecrã."</string>
     <string name="bugreport_info_dialog_title" msgid="1355948594292983332">"Detalhes do relatório de erro <xliff:g id="ID">#%d</xliff:g>"</string>
     <string name="bugreport_info_name" msgid="4414036021935139527">"Nome do ficheiro"</string>
-    <string name="bugreport_info_title" msgid="5599558206004371052">"Título"</string>
-    <string name="bugreport_info_description" msgid="4117088998733546784">"Descrição detalhada"</string>
+    <string name="bugreport_info_title" msgid="2306030793918239804">"Título do erro"</string>
+    <string name="bugreport_info_description" msgid="5072835127481627722">"Resumo de erros"</string>
+    <string name="save" msgid="4781509040564835759">"Guardar"</string>
 </resources>
diff --git a/packages/Shell/res/values-pt/strings.xml b/packages/Shell/res/values-pt/strings.xml
index fc6e21c..438c031 100644
--- a/packages/Shell/res/values-pt/strings.xml
+++ b/packages/Shell/res/values-pt/strings.xml
@@ -19,10 +19,16 @@
     <string name="app_label" msgid="3701846017049540910">"Shell"</string>
     <string name="bugreport_in_progress_title" msgid="4311705936714972757">"O relatório do bug <xliff:g id="ID">#%d</xliff:g> está sendo gerado"</string>
     <string name="bugreport_finished_title" msgid="4429132808670114081">"Relatório do bug <xliff:g id="ID">#%d</xliff:g> capturado"</string>
+    <!-- no translation found for bugreport_finished_pending_screenshot_title (5460883450679439591) -->
+    <skip />
     <string name="bugreport_updating_title" msgid="4423539949559634214">"Adicionando detalhes ao relatório do bug"</string>
     <string name="bugreport_updating_wait" msgid="3322151947853929470">"Aguarde…"</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Deslize para a esquerda para compartilhar seu relatório de bugs"</string>
     <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"Toque para compartilhar seu relatório do bug"</string>
+    <!-- no translation found for bugreport_finished_pending_screenshot_text (1474435374470177193) -->
+    <skip />
+    <!-- no translation found for bugreport_finished_pending_screenshot_text (1474435374470177193) -->
+    <skip />
     <string name="bugreport_confirm" msgid="5130698467795669780">"Os relatórios de bugs contêm dados de diversos arquivos de registro do sistema, inclusive informações pessoais e particulares. Compartilhe relatórios de bugs somente com apps e pessoas nos quais você confia."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Mostrar esta mensagem da próxima vez"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"Relatórios de bugs"</string>
@@ -34,6 +40,7 @@
     <string name="bugreport_screenshot_failed" msgid="5853049140806834601">"Não foi possível fazer a captura de tela."</string>
     <string name="bugreport_info_dialog_title" msgid="1355948594292983332">"Detalhes do relatório de bugs <xliff:g id="ID">#%d</xliff:g>"</string>
     <string name="bugreport_info_name" msgid="4414036021935139527">"Nome do arquivo"</string>
-    <string name="bugreport_info_title" msgid="5599558206004371052">"Título"</string>
-    <string name="bugreport_info_description" msgid="4117088998733546784">"Descrição detalhada"</string>
+    <string name="bugreport_info_title" msgid="2306030793918239804">"Título do bug"</string>
+    <string name="bugreport_info_description" msgid="5072835127481627722">"Resumo do bug"</string>
+    <string name="save" msgid="4781509040564835759">"Salvar"</string>
 </resources>
diff --git a/packages/Shell/res/values-ro/strings.xml b/packages/Shell/res/values-ro/strings.xml
index d720417..43366f8 100644
--- a/packages/Shell/res/values-ro/strings.xml
+++ b/packages/Shell/res/values-ro/strings.xml
@@ -19,10 +19,16 @@
     <string name="app_label" msgid="3701846017049540910">"Shell"</string>
     <string name="bugreport_in_progress_title" msgid="4311705936714972757">"Raportul de eroare <xliff:g id="ID">#%d</xliff:g> se generează"</string>
     <string name="bugreport_finished_title" msgid="4429132808670114081">"Raportul de eroare <xliff:g id="ID">#%d</xliff:g> a fost creat"</string>
+    <!-- no translation found for bugreport_finished_pending_screenshot_title (5460883450679439591) -->
+    <skip />
     <string name="bugreport_updating_title" msgid="4423539949559634214">"Se adaugă detaliile la raportul de eroare"</string>
     <string name="bugreport_updating_wait" msgid="3322151947853929470">"Așteptați…"</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Glisați la stânga pentru a trimite raportul de erori"</string>
     <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"Atingeți pentru a trimite raportul de eroare"</string>
+    <!-- no translation found for bugreport_finished_pending_screenshot_text (1474435374470177193) -->
+    <skip />
+    <!-- no translation found for bugreport_finished_pending_screenshot_text (1474435374470177193) -->
+    <skip />
     <string name="bugreport_confirm" msgid="5130698467795669780">"Rapoartele despre erori conțin date din diferite fișiere de jurnal ale sistemului, inclusiv informații private și personale. Permiteți accesul la rapoartele despre erori numai aplicațiilor și persoanelor în care aveți încredere."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Afișați acest mesaj data viitoare"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"Rapoarte de erori"</string>
@@ -34,6 +40,7 @@
     <string name="bugreport_screenshot_failed" msgid="5853049140806834601">"Captura de ecran nu a putut fi făcută."</string>
     <string name="bugreport_info_dialog_title" msgid="1355948594292983332">"Detaliile raportului de eroare <xliff:g id="ID">#%d</xliff:g>"</string>
     <string name="bugreport_info_name" msgid="4414036021935139527">"Numele fișierului"</string>
-    <string name="bugreport_info_title" msgid="5599558206004371052">"Titlu"</string>
-    <string name="bugreport_info_description" msgid="4117088998733546784">"Descriere detaliată"</string>
+    <string name="bugreport_info_title" msgid="2306030793918239804">"Titlul erorii"</string>
+    <string name="bugreport_info_description" msgid="5072835127481627722">"Rezumat privind eroarea"</string>
+    <string name="save" msgid="4781509040564835759">"Salvați"</string>
 </resources>
diff --git a/packages/Shell/res/values-ru/strings.xml b/packages/Shell/res/values-ru/strings.xml
index ed5ecaf..e22ad2e 100644
--- a/packages/Shell/res/values-ru/strings.xml
+++ b/packages/Shell/res/values-ru/strings.xml
@@ -19,10 +19,16 @@
     <string name="app_label" msgid="3701846017049540910">"Оболочка"</string>
     <string name="bugreport_in_progress_title" msgid="4311705936714972757">"Создание отчета об ошибке <xliff:g id="ID">#%d</xliff:g>…"</string>
     <string name="bugreport_finished_title" msgid="4429132808670114081">"Отчет об ошибке <xliff:g id="ID">#%d</xliff:g> сохранен"</string>
+    <!-- no translation found for bugreport_finished_pending_screenshot_title (5460883450679439591) -->
+    <skip />
     <string name="bugreport_updating_title" msgid="4423539949559634214">"Добавление данных в отчет об ошибке"</string>
     <string name="bugreport_updating_wait" msgid="3322151947853929470">"Подождите…"</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Проведите влево, чтобы отправить отчет"</string>
     <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"Нажмите, чтобы отправить отчет об ошибке."</string>
+    <!-- no translation found for bugreport_finished_pending_screenshot_text (1474435374470177193) -->
+    <skip />
+    <!-- no translation found for bugreport_finished_pending_screenshot_text (1474435374470177193) -->
+    <skip />
     <string name="bugreport_confirm" msgid="5130698467795669780">"Отчеты об ошибках содержат данные различных системных журналов и могут включать личную информацию. Рекомендуем открывать к ним доступ только лицам и приложениям, заслуживающим доверие."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Показать это сообщение в следующий раз"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"Отчеты об ошибках"</string>
@@ -34,6 +40,7 @@
     <string name="bugreport_screenshot_failed" msgid="5853049140806834601">"Не удалось сделать скриншот"</string>
     <string name="bugreport_info_dialog_title" msgid="1355948594292983332">"Данные отчета об ошибке <xliff:g id="ID">#%d</xliff:g>"</string>
     <string name="bugreport_info_name" msgid="4414036021935139527">"Название файла"</string>
-    <string name="bugreport_info_title" msgid="5599558206004371052">"Название"</string>
-    <string name="bugreport_info_description" msgid="4117088998733546784">"Подробное описание"</string>
+    <string name="bugreport_info_title" msgid="2306030793918239804">"Название ошибки"</string>
+    <string name="bugreport_info_description" msgid="5072835127481627722">"Описание ошибки"</string>
+    <string name="save" msgid="4781509040564835759">"Сохранить"</string>
 </resources>
diff --git a/packages/Shell/res/values-si-rLK/strings.xml b/packages/Shell/res/values-si-rLK/strings.xml
index cd8fba3..1ea7586 100644
--- a/packages/Shell/res/values-si-rLK/strings.xml
+++ b/packages/Shell/res/values-si-rLK/strings.xml
@@ -19,10 +19,13 @@
     <string name="app_label" msgid="3701846017049540910">"ෂෙල්"</string>
     <string name="bugreport_in_progress_title" msgid="4311705936714972757">"දෝෂ වාර්තා <xliff:g id="ID">#%d</xliff:g> ජනනය කරමින් පවතී"</string>
     <string name="bugreport_finished_title" msgid="4429132808670114081">"දෝෂ වාර්තා <xliff:g id="ID">#%d</xliff:g> ග්‍රහණය කර ගන්නා ලදී"</string>
+    <string name="bugreport_finished_pending_screenshot_title" msgid="5460883450679439591">"දෝෂ වාර්තාව <xliff:g id="ID">#%d</xliff:g> ග්‍රහණය කළ නමුත් තිර රුව පොරොත්තුව ඇත"</string>
     <string name="bugreport_updating_title" msgid="4423539949559634214">"දෝෂ වාර්තාව වෙත විස්තර එක් කිරීම"</string>
     <string name="bugreport_updating_wait" msgid="3322151947853929470">"කරුණාකර රැඳී සිටින්න..."</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"ඔබගේ දෝෂ වාර්තාව බෙදාගැනීමට වමට ස්වයිප් කරන්න"</string>
     <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"ඔබගේ දෝෂ වාර්තාව බෙදා ගැනීමට තට්ටු කරන්න"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"තිර රුවක් රහිතව ඔබගේ දෝෂ වාර්තාව බෙදා ගැනීමට තට්ටු කරන්න නැතහොත් තිර රුව ගැනීම අවසන් වන තෙක් රැඳෙන්න"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"තිර රුවක් රහිතව ඔබගේ දෝෂ වාර්තාව බෙදා ගැනීමට තට්ටු කරන්න නැතහොත් තිර රුව ගැනීම අවසන් වන තෙක් රැඳෙන්න"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"පුද්ගලික සහ පෞද්ගලික තොරතුරු ඇතුළත්ව පද්ධතියේ විවිධ ලොග් ගොනු වල දත්ත දෝෂ වාර්තාවේ අඩංගු වේ. ඔබට විශ්වාසවන්ත යෙදුම් සහ පුද්ගලයින් සමඟ පමණක් දෝෂ වාර්තා බෙදා ගන්න."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"ඊළඟ වෙලාවේ මෙම පණිවිඩය පෙන්වන්න"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"දෝෂ වාර්තා"</string>
@@ -34,6 +37,7 @@
     <string name="bugreport_screenshot_failed" msgid="5853049140806834601">"තිර රුවක් ගත නොහැකි විය."</string>
     <string name="bugreport_info_dialog_title" msgid="1355948594292983332">"දෝෂ වාර්තා <xliff:g id="ID">#%d</xliff:g> විස්තර"</string>
     <string name="bugreport_info_name" msgid="4414036021935139527">"ගොනුවේ නම"</string>
-    <string name="bugreport_info_title" msgid="5599558206004371052">"මාතෘකාව"</string>
-    <string name="bugreport_info_description" msgid="4117088998733546784">"සවිස්තර විස්තරය"</string>
+    <string name="bugreport_info_title" msgid="2306030793918239804">"දෝෂ මාතෘකාව"</string>
+    <string name="bugreport_info_description" msgid="5072835127481627722">"දෝෂ සාරාංශය"</string>
+    <string name="save" msgid="4781509040564835759">"සුරකින්න"</string>
 </resources>
diff --git a/packages/Shell/res/values-sk/strings.xml b/packages/Shell/res/values-sk/strings.xml
index 23e67f5..fa17326 100644
--- a/packages/Shell/res/values-sk/strings.xml
+++ b/packages/Shell/res/values-sk/strings.xml
@@ -19,10 +19,13 @@
     <string name="app_label" msgid="3701846017049540910">"Prostredie"</string>
     <string name="bugreport_in_progress_title" msgid="4311705936714972757">"Generuje sa hlásenie chyby <xliff:g id="ID">#%d</xliff:g>"</string>
     <string name="bugreport_finished_title" msgid="4429132808670114081">"Hlásenie chyby <xliff:g id="ID">#%d</xliff:g> bolo zaznamenané"</string>
+    <string name="bugreport_finished_pending_screenshot_title" msgid="5460883450679439591">"Hlásenie chyby <xliff:g id="ID">#%d</xliff:g> bolo zaznamenané, ale čaká sa na snímku obrazovky"</string>
     <string name="bugreport_updating_title" msgid="4423539949559634214">"Pridanie podrobností o hlásení chyby"</string>
     <string name="bugreport_updating_wait" msgid="3322151947853929470">"Čakajte prosím…"</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Ak chcete hlásenie o chybe zdieľať, prejdite prstom doľava."</string>
     <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"Hlásenie chyby môžete zdieľať klepnutím"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"Klepnutím zdieľajte hlásenie chyby bez snímky obrazovky alebo počkajte na dokončenie snímky obrazovky"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"Klepnutím zdieľajte hlásenie chyby bez snímky obrazovky alebo počkajte na dokončenie snímky obrazovky"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"Správy o chybách obsahujú údaje z rôznych súborov denníkov systému vrátane osobných a súkromných informácií. Zdieľajte ich iba s dôveryhodnými aplikáciami a ľuďmi."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Zobraziť túto správu nabudúce"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"Hlásenia chýb"</string>
@@ -34,6 +37,7 @@
     <string name="bugreport_screenshot_failed" msgid="5853049140806834601">"Snímku obrazovky sa nepodarilo zaznamenať."</string>
     <string name="bugreport_info_dialog_title" msgid="1355948594292983332">"Podrobnosti hlásenia chyby <xliff:g id="ID">#%d</xliff:g>"</string>
     <string name="bugreport_info_name" msgid="4414036021935139527">"Názov súboru"</string>
-    <string name="bugreport_info_title" msgid="5599558206004371052">"Názov"</string>
-    <string name="bugreport_info_description" msgid="4117088998733546784">"Podrobný popis"</string>
+    <string name="bugreport_info_title" msgid="2306030793918239804">"Názov chyby"</string>
+    <string name="bugreport_info_description" msgid="5072835127481627722">"Súhrn chyby"</string>
+    <string name="save" msgid="4781509040564835759">"Uložiť"</string>
 </resources>
diff --git a/packages/Shell/res/values-sl/strings.xml b/packages/Shell/res/values-sl/strings.xml
index 519f3f2..9419760 100644
--- a/packages/Shell/res/values-sl/strings.xml
+++ b/packages/Shell/res/values-sl/strings.xml
@@ -19,10 +19,16 @@
     <string name="app_label" msgid="3701846017049540910">"Lupina"</string>
     <string name="bugreport_in_progress_title" msgid="4311705936714972757">"Poročilo o napaki <xliff:g id="ID">#%d</xliff:g> je v izdelavi"</string>
     <string name="bugreport_finished_title" msgid="4429132808670114081">"Poročilo o napaki <xliff:g id="ID">#%d</xliff:g> zajeto"</string>
+    <!-- no translation found for bugreport_finished_pending_screenshot_title (5460883450679439591) -->
+    <skip />
     <string name="bugreport_updating_title" msgid="4423539949559634214">"Dodajanje podrobnosti v poročilo o napakah"</string>
     <string name="bugreport_updating_wait" msgid="3322151947853929470">"Počakajte ..."</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Povlecite v levo, če želite poslati sporočilo o napaki"</string>
     <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"Dotaknite se, če želite poročilo o napaki dati v skupno rabo"</string>
+    <!-- no translation found for bugreport_finished_pending_screenshot_text (1474435374470177193) -->
+    <skip />
+    <!-- no translation found for bugreport_finished_pending_screenshot_text (1474435374470177193) -->
+    <skip />
     <string name="bugreport_confirm" msgid="5130698467795669780">"Poročila o napakah vsebujejo podatke iz različnih dnevniških datotek sistema, vključno z osebnimi in zasebnimi podatki. Poročila o napakah delite samo z aplikacijami in ljudmi, ki jim zaupate."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Pokaži to sporočilo naslednjič"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"Poročila o napakah"</string>
@@ -34,6 +40,7 @@
     <string name="bugreport_screenshot_failed" msgid="5853049140806834601">"Posnetka zaslon ni bilo mogoče ustvariti."</string>
     <string name="bugreport_info_dialog_title" msgid="1355948594292983332">"Podrobnosti poročila o napaki <xliff:g id="ID">#%d</xliff:g>"</string>
     <string name="bugreport_info_name" msgid="4414036021935139527">"Ime datoteke"</string>
-    <string name="bugreport_info_title" msgid="5599558206004371052">"Naslov"</string>
-    <string name="bugreport_info_description" msgid="4117088998733546784">"Podroben opis"</string>
+    <string name="bugreport_info_title" msgid="2306030793918239804">"Naslov poročila o napakah"</string>
+    <string name="bugreport_info_description" msgid="5072835127481627722">"Povzetek poročila o napakah"</string>
+    <string name="save" msgid="4781509040564835759">"Shrani"</string>
 </resources>
diff --git a/packages/Shell/res/values-sq-rAL/strings.xml b/packages/Shell/res/values-sq-rAL/strings.xml
index 5e3c706..206ffda 100644
--- a/packages/Shell/res/values-sq-rAL/strings.xml
+++ b/packages/Shell/res/values-sq-rAL/strings.xml
@@ -19,10 +19,16 @@
     <string name="app_label" msgid="3701846017049540910">"Guaska"</string>
     <string name="bugreport_in_progress_title" msgid="4311705936714972757">"Raporti i defekteve në kod <xliff:g id="ID">#%d</xliff:g> po krijohet"</string>
     <string name="bugreport_finished_title" msgid="4429132808670114081">"Raporti i defekteve në kod <xliff:g id="ID">#%d</xliff:g> u regjistrua"</string>
+    <!-- no translation found for bugreport_finished_pending_screenshot_title (5460883450679439591) -->
+    <skip />
     <string name="bugreport_updating_title" msgid="4423539949559634214">"Po shtohen detajet te raporti i defekteve në kod"</string>
     <string name="bugreport_updating_wait" msgid="3322151947853929470">"Qëndro në pritje..."</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Rrëshqit majtas për të ndarë raportin e defektit në kod"</string>
     <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"Trokit për të ndarë raportin e defekteve në kod"</string>
+    <!-- no translation found for bugreport_finished_pending_screenshot_text (1474435374470177193) -->
+    <skip />
+    <!-- no translation found for bugreport_finished_pending_screenshot_text (1474435374470177193) -->
+    <skip />
     <string name="bugreport_confirm" msgid="5130698467795669780">"Raportet e gabimeve përmbajnë të dhëna nga skedarë të ndryshëm ditarësh sistemi, përfshi informacione personale dhe private. Shpërndaji publikisht raportet e gabimeve vetëm me aplikacionet dhe personat që iu beson."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Tregoje këtë mesazh herën tjetër"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"Raportet e gabimeve"</string>
@@ -34,6 +40,7 @@
     <string name="bugreport_screenshot_failed" msgid="5853049140806834601">"Pamja e ekranit nuk mund të realizohej."</string>
     <string name="bugreport_info_dialog_title" msgid="1355948594292983332">"Detajet e raportit të defekteve në kod <xliff:g id="ID">#%d</xliff:g>"</string>
     <string name="bugreport_info_name" msgid="4414036021935139527">"Emri i skedarit"</string>
-    <string name="bugreport_info_title" msgid="5599558206004371052">"Titulli"</string>
-    <string name="bugreport_info_description" msgid="4117088998733546784">"Përshkrimi i detajuar"</string>
+    <string name="bugreport_info_title" msgid="2306030793918239804">"Titulli i defektit në kod"</string>
+    <string name="bugreport_info_description" msgid="5072835127481627722">"Përmbledhja e defekteve në kod"</string>
+    <string name="save" msgid="4781509040564835759">"Ruaj"</string>
 </resources>
diff --git a/packages/Shell/res/values-sr/strings.xml b/packages/Shell/res/values-sr/strings.xml
index 55119b6..3bea4f3 100644
--- a/packages/Shell/res/values-sr/strings.xml
+++ b/packages/Shell/res/values-sr/strings.xml
@@ -19,10 +19,13 @@
     <string name="app_label" msgid="3701846017049540910">"Shell"</string>
     <string name="bugreport_in_progress_title" msgid="4311705936714972757">"Извештај о грешци <xliff:g id="ID">#%d</xliff:g> се генерише"</string>
     <string name="bugreport_finished_title" msgid="4429132808670114081">"Извештај о грешци <xliff:g id="ID">#%d</xliff:g> је снимљен"</string>
+    <string name="bugreport_finished_pending_screenshot_title" msgid="5460883450679439591">"Извештај о грешци <xliff:g id="ID">#%d</xliff:g> снимљен; снимак екрана се чека"</string>
     <string name="bugreport_updating_title" msgid="4423539949559634214">"Додају се детаљи у извештај о грешци"</string>
     <string name="bugreport_updating_wait" msgid="3322151947853929470">"Сачекајте..."</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Превуците улево да бисте делили извештај о грешкама"</string>
     <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"Додирните да бисте делили извештај о грешци"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"Додирните за дељење извештаја о грешци без снимка екрана или сачекајте да се направи снимак екрана"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"Додирните за дељење извештаја о грешци без снимка екрана или сачекајте да се направи снимак екрана"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"Извештаји о грешкама садрже податке из различитих системских датотека евиденције, укључујући личне и приватне податке. Делите извештаје о грешкама само са апликацијама и људима у које имате поверења."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Прикажи ову поруку следећи пут"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"Извештаји о грешкама"</string>
@@ -34,6 +37,7 @@
     <string name="bugreport_screenshot_failed" msgid="5853049140806834601">"Снимање екрана није успело."</string>
     <string name="bugreport_info_dialog_title" msgid="1355948594292983332">"Детаљи извештаја о грешци <xliff:g id="ID">#%d</xliff:g>"</string>
     <string name="bugreport_info_name" msgid="4414036021935139527">"Назив датотеке"</string>
-    <string name="bugreport_info_title" msgid="5599558206004371052">"Наслов"</string>
-    <string name="bugreport_info_description" msgid="4117088998733546784">"Детаљни опис"</string>
+    <string name="bugreport_info_title" msgid="2306030793918239804">"Наслов грешке"</string>
+    <string name="bugreport_info_description" msgid="5072835127481627722">"Резиме грешке"</string>
+    <string name="save" msgid="4781509040564835759">"Сачувај"</string>
 </resources>
diff --git a/packages/Shell/res/values-sv/strings.xml b/packages/Shell/res/values-sv/strings.xml
index 085f57e..a8cb64d 100644
--- a/packages/Shell/res/values-sv/strings.xml
+++ b/packages/Shell/res/values-sv/strings.xml
@@ -19,10 +19,13 @@
     <string name="app_label" msgid="3701846017049540910">"Skal"</string>
     <string name="bugreport_in_progress_title" msgid="4311705936714972757">"Felrapporten <xliff:g id="ID">#%d</xliff:g> genereras"</string>
     <string name="bugreport_finished_title" msgid="4429132808670114081">"Felrapporten <xliff:g id="ID">#%d</xliff:g> har skapats"</string>
+    <string name="bugreport_finished_pending_screenshot_title" msgid="5460883450679439591">"Felrapporten <xliff:g id="ID">#%d</xliff:g> har skapats, väntar på skärmdumpen"</string>
     <string name="bugreport_updating_title" msgid="4423539949559634214">"Lägger till information i felrapporten"</string>
     <string name="bugreport_updating_wait" msgid="3322151947853929470">"Vänta …"</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Svep åt vänster om du vill dela felrapporten"</string>
     <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"Tryck om du vill dela felrapporten"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"Tryck om du vill dela felrapporten utan en skärmdump eller vänta tills skärmdumpen är klar"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"Tryck om du vill dela felrapporten utan en skärmdump eller vänta tills skärmdumpen är klar"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"Felrapporter innehåller data från systemets olika loggfiler, inklusive personliga och privata uppgifter. Dela bara felrapporter med personer du litar på."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Visa det här meddelandet nästa gång"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"Felrapporter"</string>
@@ -34,6 +37,7 @@
     <string name="bugreport_screenshot_failed" msgid="5853049140806834601">"Det gick inte att ta skrämdump."</string>
     <string name="bugreport_info_dialog_title" msgid="1355948594292983332">"Information för felrapporten <xliff:g id="ID">#%d</xliff:g>"</string>
     <string name="bugreport_info_name" msgid="4414036021935139527">"Filnamn"</string>
-    <string name="bugreport_info_title" msgid="5599558206004371052">"Namn"</string>
-    <string name="bugreport_info_description" msgid="4117088998733546784">"Detaljerad beskrivning"</string>
+    <string name="bugreport_info_title" msgid="2306030793918239804">"Felets titel"</string>
+    <string name="bugreport_info_description" msgid="5072835127481627722">"Sammanfattning av felet"</string>
+    <string name="save" msgid="4781509040564835759">"Spara"</string>
 </resources>
diff --git a/packages/Shell/res/values-sw/strings.xml b/packages/Shell/res/values-sw/strings.xml
index c5a8ef1..945bb60 100644
--- a/packages/Shell/res/values-sw/strings.xml
+++ b/packages/Shell/res/values-sw/strings.xml
@@ -19,10 +19,13 @@
     <string name="app_label" msgid="3701846017049540910">"Ganda"</string>
     <string name="bugreport_in_progress_title" msgid="4311705936714972757">"Ripoti ya hitilafu ya <xliff:g id="ID">#%d</xliff:g> inatayarishwa"</string>
     <string name="bugreport_finished_title" msgid="4429132808670114081">"Ripoti ya hitilafu ya <xliff:g id="ID">#%d</xliff:g> imerekodiwa"</string>
+    <string name="bugreport_finished_pending_screenshot_title" msgid="5460883450679439591">"Ripoti ya hitilafu ya <xliff:g id="ID">#%d</xliff:g> imerekodiwa lakini picha ya skrini bado haijakamilishwa"</string>
     <string name="bugreport_updating_title" msgid="4423539949559634214">"Inaongeza maelezo kwenye ripoti ya hitilafu"</string>
     <string name="bugreport_updating_wait" msgid="3322151947853929470">"Tafadhali subiri…"</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Telezesha kidole kushoto ili ushiriki ripoti yako ya hitilafu"</string>
     <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"Gonga ili ushiriki ripoti yako ya hitilafu"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"Gonga ili ushiriki ripoti yako ya hitilafu bila picha ya skrini au usubiri picha ya skrini itayarishwe"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"Gonga ili ushiriki ripoti yako ya hitilafu bila picha ya skrini au usubiri picha ya skrini itayarishwe"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"Ripoti ya hitilafu ina data kutoka kwenye faili za kumbukumbu mbalimbali za mfumo, pamoja na maelezo ya kibinafsi na faragha. Shiriki ripoti ya hitilafu na programu na watu unaowaamini pekee."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Onyesha ujumbe huu wakati mwingine"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"Ripoti za hitilafu"</string>
@@ -34,6 +37,7 @@
     <string name="bugreport_screenshot_failed" msgid="5853049140806834601">"Haikupiga picha ya skrini."</string>
     <string name="bugreport_info_dialog_title" msgid="1355948594292983332">"Maelezo ya ripoti ya hitilafu ya <xliff:g id="ID">#%d</xliff:g>"</string>
     <string name="bugreport_info_name" msgid="4414036021935139527">"Jina la faili"</string>
-    <string name="bugreport_info_title" msgid="5599558206004371052">"Kichwa"</string>
-    <string name="bugreport_info_description" msgid="4117088998733546784">"Maelezo ya kina"</string>
+    <string name="bugreport_info_title" msgid="2306030793918239804">"Jina la hitilafu"</string>
+    <string name="bugreport_info_description" msgid="5072835127481627722">"Muhtasari wa hitilafu"</string>
+    <string name="save" msgid="4781509040564835759">"Hifadhi"</string>
 </resources>
diff --git a/packages/Shell/res/values-ta-rIN/strings.xml b/packages/Shell/res/values-ta-rIN/strings.xml
index 7ef89e2..a501764 100644
--- a/packages/Shell/res/values-ta-rIN/strings.xml
+++ b/packages/Shell/res/values-ta-rIN/strings.xml
@@ -19,10 +19,13 @@
     <string name="app_label" msgid="3701846017049540910">"ஷெல்"</string>
     <string name="bugreport_in_progress_title" msgid="4311705936714972757">"பிழை அறிக்கை <xliff:g id="ID">#%d</xliff:g> உருவாக்கப்படுகிறது"</string>
     <string name="bugreport_finished_title" msgid="4429132808670114081">"பிழை அறிக்கை <xliff:g id="ID">#%d</xliff:g> எடுக்கப்பட்டது"</string>
+    <string name="bugreport_finished_pending_screenshot_title" msgid="5460883450679439591">"பிழை அறிக்கை <xliff:g id="ID">#%d</xliff:g> எடுக்கப்பட்டது ஆனால் ஸ்கிரீன்ஷாட் நிலுவையிலுள்ளது"</string>
     <string name="bugreport_updating_title" msgid="4423539949559634214">"பிழை அறிக்கையில் விவரங்களைச் சேர்க்கிறது"</string>
     <string name="bugreport_updating_wait" msgid="3322151947853929470">"காத்திருக்கவும்…"</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"பிழை அறிக்கையைப் பகிர இடது புறமாகத் தேய்க்கவும்"</string>
     <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"பிழை அறிக்கையைப் பகிர, தட்டவும்"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"ஸ்கிரீன்ஷாட் இல்லாமல் பிழை அறிக்கையைப் பகிர, தட்டவும் அல்லது ஸ்கிரீன்ஷாட் முடியும்வரை காத்திருக்கவும்"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"ஸ்கிரீன்ஷாட் இல்லாமல் பிழை அறிக்கையைப் பகிர, தட்டவும் அல்லது ஸ்கிரீன்ஷாட் முடியும்வரை காத்திருக்கவும்"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"பிழை அறிக்கைகளில், சொந்த வாழ்க்கை மற்றும் தனிப்பட்ட தகவல் உள்பட கணினியின் பல்வேறு பதிவுகளில் உள்ள தரவு இருக்கும். நீங்கள் நம்பும் பயன்பாடுகள் மற்றும் நபர்களுடன் மட்டும் பிழை அறிக்கைகளைப் பகிரவும்."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"இந்தச் செய்தியை அடுத்த முறைக் காட்டு"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"பிழை அறிக்கைகள்"</string>
@@ -34,6 +37,7 @@
     <string name="bugreport_screenshot_failed" msgid="5853049140806834601">"ஸ்கிரீன் ஷாட்டை எடுக்க முடியவில்லை."</string>
     <string name="bugreport_info_dialog_title" msgid="1355948594292983332">"பிழை அறிக்கை <xliff:g id="ID">#%d</xliff:g> இன் விவரங்கள்"</string>
     <string name="bugreport_info_name" msgid="4414036021935139527">"கோப்புப்பெயர்"</string>
-    <string name="bugreport_info_title" msgid="5599558206004371052">"தலைப்பு"</string>
-    <string name="bugreport_info_description" msgid="4117088998733546784">"விரிவான விளக்கம்"</string>
+    <string name="bugreport_info_title" msgid="2306030793918239804">"பிழை தலைப்பு"</string>
+    <string name="bugreport_info_description" msgid="5072835127481627722">"பிழை குறித்த சுருக்க விவரம்"</string>
+    <string name="save" msgid="4781509040564835759">"சேமி"</string>
 </resources>
diff --git a/packages/Shell/res/values-te-rIN/strings.xml b/packages/Shell/res/values-te-rIN/strings.xml
index 6ba816b..f406869 100644
--- a/packages/Shell/res/values-te-rIN/strings.xml
+++ b/packages/Shell/res/values-te-rIN/strings.xml
@@ -19,10 +19,13 @@
     <string name="app_label" msgid="3701846017049540910">"షెల్"</string>
     <string name="bugreport_in_progress_title" msgid="4311705936714972757">"బగ్ నివేదిక <xliff:g id="ID">#%d</xliff:g> ఉత్పాదించబడుతోంది"</string>
     <string name="bugreport_finished_title" msgid="4429132808670114081">"బగ్ నివేదిక <xliff:g id="ID">#%d</xliff:g> సంగ్రహించబడింది"</string>
+    <string name="bugreport_finished_pending_screenshot_title" msgid="5460883450679439591">"బగ్ నివే. <xliff:g id="ID">#%d</xliff:g> క్యాప్చ., కానీ స్క్రీన్‌షాట్ పెం. ఉంది"</string>
     <string name="bugreport_updating_title" msgid="4423539949559634214">"బగ్ నివేదికకు వివరాలను జోడిస్తోంది"</string>
     <string name="bugreport_updating_wait" msgid="3322151947853929470">"దయచేసి వేచి ఉండండి..."</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"మీ బగ్ నివేదికను భాగస్వామ్యం చేయడానికి ఎడమవైపుకు స్వైప్ చేయండి"</string>
     <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"మీ బగ్ నివేదికను భాగస్వామ్యం చేయడానికి నొక్కండి"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"స్క్రీన్‌షాట్ లేకుండా మీ బగ్ నివే. భాగ. చేయడానికి నొక్కండి లేదా స్క్రీన్‌షాట్ ముగిసేదాకా వేచి ఉండండి"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"స్క్రీన్‌షాట్ లేకుండా మీ బగ్ నివే. భాగ. చేయడానికి నొక్కండి లేదా స్క్రీన్‌షాట్ ముగిసేదాకా వేచి ఉండండి"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"బగ్ నివేదికలు వ్యక్తిగతమైన మరియు రహస్యమైన సమాచారంతో సహా సిస్టమ్ యొక్క విభిన్న లాగ్ ఫైల్‌ల్లోని డేటాను కలిగి ఉంటాయి. కనుక బగ్ నివేదికలను మీరు విశ్వసించే అనువర్తనాలు మరియు వ్యక్తులతో మాత్రమే భాగస్వామ్యం చేయండి."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"తదుపరిసారి ఈ సందేశాన్ని చూపు"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"బగ్ నివేదికలు"</string>
@@ -34,6 +37,7 @@
     <string name="bugreport_screenshot_failed" msgid="5853049140806834601">"స్క్రీన్‌షాట్‌ను తీయడం సాధ్యపడలేదు."</string>
     <string name="bugreport_info_dialog_title" msgid="1355948594292983332">"బగ్ నివేదిక <xliff:g id="ID">#%d</xliff:g> వివరాలు"</string>
     <string name="bugreport_info_name" msgid="4414036021935139527">"ఫైల్ పేరు"</string>
-    <string name="bugreport_info_title" msgid="5599558206004371052">"శీర్షిక"</string>
-    <string name="bugreport_info_description" msgid="4117088998733546784">"సమగ్ర వివరణ"</string>
+    <string name="bugreport_info_title" msgid="2306030793918239804">"బగ్ శీర్షిక"</string>
+    <string name="bugreport_info_description" msgid="5072835127481627722">"బగ్ సారాంశం"</string>
+    <string name="save" msgid="4781509040564835759">"సేవ్ చేయి"</string>
 </resources>
diff --git a/packages/Shell/res/values-th/strings.xml b/packages/Shell/res/values-th/strings.xml
index d68ca26..ff9a647 100644
--- a/packages/Shell/res/values-th/strings.xml
+++ b/packages/Shell/res/values-th/strings.xml
@@ -19,10 +19,16 @@
     <string name="app_label" msgid="3701846017049540910">"Shell"</string>
     <string name="bugreport_in_progress_title" msgid="4311705936714972757">"กำลังสร้างรายงานข้อบกพร่อง <xliff:g id="ID">#%d</xliff:g>"</string>
     <string name="bugreport_finished_title" msgid="4429132808670114081">"บันทึกรายงานข้อบกพร่อง <xliff:g id="ID">#%d</xliff:g> แล้ว"</string>
+    <!-- no translation found for bugreport_finished_pending_screenshot_title (5460883450679439591) -->
+    <skip />
     <string name="bugreport_updating_title" msgid="4423539949559634214">"กำลังเพิ่มรายละเอียดในรายงานข้อบกพร่อง"</string>
     <string name="bugreport_updating_wait" msgid="3322151947853929470">"โปรดรอสักครู่…"</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"กวาดไปทางซ้ายเพื่อแชร์รายงานข้อบกพร่อง"</string>
     <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"แตะเพื่อแชร์รายงานข้อบกพร่องของคุณ"</string>
+    <!-- no translation found for bugreport_finished_pending_screenshot_text (1474435374470177193) -->
+    <skip />
+    <!-- no translation found for bugreport_finished_pending_screenshot_text (1474435374470177193) -->
+    <skip />
     <string name="bugreport_confirm" msgid="5130698467795669780">"รายงานข้อบกพร่องมีข้อมูลจากไฟล์บันทึกต่างๆ ของระบบ รวมถึงข้อมูลส่วนตัว แชร์รายงานข้อบกพร่องกับแอปและบุคคลที่คุณไว้ใจเท่านั้น"</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"แสดงข้อความนี้ในครั้งต่อไป"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"รายงานข้อบกพร่อง"</string>
@@ -34,6 +40,7 @@
     <string name="bugreport_screenshot_failed" msgid="5853049140806834601">"ไม่สามารถจับภาพหน้าจอได้"</string>
     <string name="bugreport_info_dialog_title" msgid="1355948594292983332">"รายละเอียดรายงานข้อบกพร่อง <xliff:g id="ID">#%d</xliff:g>"</string>
     <string name="bugreport_info_name" msgid="4414036021935139527">"ชื่อไฟล์"</string>
-    <string name="bugreport_info_title" msgid="5599558206004371052">"ชื่อ"</string>
-    <string name="bugreport_info_description" msgid="4117088998733546784">"คำอธิบายโดยละเอียด"</string>
+    <string name="bugreport_info_title" msgid="2306030793918239804">"ชื่อข้อบกพร่อง"</string>
+    <string name="bugreport_info_description" msgid="5072835127481627722">"สรุปข้อบกพร่อง"</string>
+    <string name="save" msgid="4781509040564835759">"บันทึก"</string>
 </resources>
diff --git a/packages/Shell/res/values-tl/strings.xml b/packages/Shell/res/values-tl/strings.xml
index 432eb90..9e152d3 100644
--- a/packages/Shell/res/values-tl/strings.xml
+++ b/packages/Shell/res/values-tl/strings.xml
@@ -19,10 +19,16 @@
     <string name="app_label" msgid="3701846017049540910">"Shell"</string>
     <string name="bugreport_in_progress_title" msgid="4311705936714972757">"Binubuo na ang ulat ng bug na <xliff:g id="ID">#%d</xliff:g>"</string>
     <string name="bugreport_finished_title" msgid="4429132808670114081">"Na-capture ang ulat ng bug na <xliff:g id="ID">#%d</xliff:g>"</string>
+    <!-- no translation found for bugreport_finished_pending_screenshot_title (5460883450679439591) -->
+    <skip />
     <string name="bugreport_updating_title" msgid="4423539949559634214">"Pagdaragdag ng mga detalye sa ulat ng bug"</string>
     <string name="bugreport_updating_wait" msgid="3322151947853929470">"Mangyaring maghintay..."</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Mag-swipe pakaliwa upang ibahagi ang iyong ulat ng bug"</string>
     <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"Mag-tap upang ibahagi ang iyong ulat ng bug"</string>
+    <!-- no translation found for bugreport_finished_pending_screenshot_text (1474435374470177193) -->
+    <skip />
+    <!-- no translation found for bugreport_finished_pending_screenshot_text (1474435374470177193) -->
+    <skip />
     <string name="bugreport_confirm" msgid="5130698467795669780">"Naglalaman ang mga ulat ng bug ng data mula sa iba\'t ibang file ng log ng system, kabilang ang personal at pribadong impormasyon. Magbahagi lang ng mga ulat ng bug sa apps at mga tao na pinagkakatiwalaan mo."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Ipakita ang mensaheng ito sa susunod"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"Mga ulat sa bug"</string>
@@ -34,6 +40,7 @@
     <string name="bugreport_screenshot_failed" msgid="5853049140806834601">"Hindi makunan ng screenshot."</string>
     <string name="bugreport_info_dialog_title" msgid="1355948594292983332">"Mga detalye ng ulat ng bug na <xliff:g id="ID">#%d</xliff:g>"</string>
     <string name="bugreport_info_name" msgid="4414036021935139527">"Filename"</string>
-    <string name="bugreport_info_title" msgid="5599558206004371052">"Pamagat"</string>
-    <string name="bugreport_info_description" msgid="4117088998733546784">"Detalyadong paglalarawan"</string>
+    <string name="bugreport_info_title" msgid="2306030793918239804">"Pamagat ng bug"</string>
+    <string name="bugreport_info_description" msgid="5072835127481627722">"Buod ng bug"</string>
+    <string name="save" msgid="4781509040564835759">"I-save"</string>
 </resources>
diff --git a/packages/Shell/res/values-tr/strings.xml b/packages/Shell/res/values-tr/strings.xml
index dae377f..4c765da 100644
--- a/packages/Shell/res/values-tr/strings.xml
+++ b/packages/Shell/res/values-tr/strings.xml
@@ -19,10 +19,16 @@
     <string name="app_label" msgid="3701846017049540910">"Kabuk"</string>
     <string name="bugreport_in_progress_title" msgid="4311705936714972757">"Hata raporu (<xliff:g id="ID">#%d</xliff:g>) oluşturuluyor"</string>
     <string name="bugreport_finished_title" msgid="4429132808670114081">"Hata raporu (<xliff:g id="ID">#%d</xliff:g>) yakalandı"</string>
+    <!-- no translation found for bugreport_finished_pending_screenshot_title (5460883450679439591) -->
+    <skip />
     <string name="bugreport_updating_title" msgid="4423539949559634214">"Hata raporuna ayrıntılar ekleniyor"</string>
     <string name="bugreport_updating_wait" msgid="3322151947853929470">"Lütfen bekleyin…"</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Hata raporunuzu paylaşmak için hızlıca sola kaydırın"</string>
     <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"Hata raporunuzu paylaşmak için hafifçe dokunun"</string>
+    <!-- no translation found for bugreport_finished_pending_screenshot_text (1474435374470177193) -->
+    <skip />
+    <!-- no translation found for bugreport_finished_pending_screenshot_text (1474435374470177193) -->
+    <skip />
     <string name="bugreport_confirm" msgid="5130698467795669780">"Hata raporları, kişisel ve özel bilgiler dahil olmak üzere sistemin çeşitli günlük dosyalarından veriler içerir. Hata raporlarını sadece güvendiğiniz uygulamalar ve kişilerle paylaşın."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Bir dahaki sefere bu iletiyi göster"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"Hata raporları"</string>
@@ -34,6 +40,7 @@
     <string name="bugreport_screenshot_failed" msgid="5853049140806834601">"Ekran görüntüsü alınamadı."</string>
     <string name="bugreport_info_dialog_title" msgid="1355948594292983332">"Hata raporu (<xliff:g id="ID">#%d</xliff:g>) ayrıntıları"</string>
     <string name="bugreport_info_name" msgid="4414036021935139527">"Dosya adı"</string>
-    <string name="bugreport_info_title" msgid="5599558206004371052">"Başlık"</string>
-    <string name="bugreport_info_description" msgid="4117088998733546784">"Ayrıntılı açıklama"</string>
+    <string name="bugreport_info_title" msgid="2306030793918239804">"Hata başlığı"</string>
+    <string name="bugreport_info_description" msgid="5072835127481627722">"Hata özeti"</string>
+    <string name="save" msgid="4781509040564835759">"Kaydet"</string>
 </resources>
diff --git a/packages/Shell/res/values-uk/strings.xml b/packages/Shell/res/values-uk/strings.xml
index 02eeb2f..c35c61c 100644
--- a/packages/Shell/res/values-uk/strings.xml
+++ b/packages/Shell/res/values-uk/strings.xml
@@ -19,10 +19,13 @@
     <string name="app_label" msgid="3701846017049540910">"Оболонка"</string>
     <string name="bugreport_in_progress_title" msgid="4311705936714972757">"Генерується повідомлення про помилку <xliff:g id="ID">#%d</xliff:g>"</string>
     <string name="bugreport_finished_title" msgid="4429132808670114081">"Повідомлення про помилку <xliff:g id="ID">#%d</xliff:g> створено"</string>
+    <string name="bugreport_finished_pending_screenshot_title" msgid="5460883450679439591">"Повідомлення <xliff:g id="ID">#%d</xliff:g> створено. Очікується знімок екрана"</string>
     <string name="bugreport_updating_title" msgid="4423539949559634214">"Додаються деталі до повідомлення про помилку"</string>
     <string name="bugreport_updating_wait" msgid="3322151947853929470">"Зачекайте…"</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Проведіть пальцем ліворуч, щоб надіслати звіт про помилки"</string>
     <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"Торкніться, щоб надіслати повідомлення про помилку"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"Торкніться, щоб надіслати повідомлення про помилку без знімка екрана або зачекайте на знімок"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"Торкніться, щоб надіслати повідомлення про помилку без знімка екрана або зачекайте на знімок"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"Звіти про помилки містять дані з різних файлів журналу системи, зокрема особисті та конфіденційні. Надсилайте звіт про помилки лише тим, кому довіряєте."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Показати це повідомлення наступного разу"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"Звіти про помилки"</string>
@@ -34,6 +37,7 @@
     <string name="bugreport_screenshot_failed" msgid="5853049140806834601">"Не вдалося зробити знімок екрана."</string>
     <string name="bugreport_info_dialog_title" msgid="1355948594292983332">"Деталі повідомлення про помилку <xliff:g id="ID">#%d</xliff:g>"</string>
     <string name="bugreport_info_name" msgid="4414036021935139527">"Назва файлу"</string>
-    <string name="bugreport_info_title" msgid="5599558206004371052">"Назва"</string>
-    <string name="bugreport_info_description" msgid="4117088998733546784">"Детальний опис"</string>
+    <string name="bugreport_info_title" msgid="2306030793918239804">"Назва помилки"</string>
+    <string name="bugreport_info_description" msgid="5072835127481627722">"Опис помилки"</string>
+    <string name="save" msgid="4781509040564835759">"Зберегти"</string>
 </resources>
diff --git a/packages/Shell/res/values-ur-rPK/strings.xml b/packages/Shell/res/values-ur-rPK/strings.xml
index 23cada6..edc7433 100644
--- a/packages/Shell/res/values-ur-rPK/strings.xml
+++ b/packages/Shell/res/values-ur-rPK/strings.xml
@@ -19,10 +19,16 @@
     <string name="app_label" msgid="3701846017049540910">"شیل"</string>
     <string name="bugreport_in_progress_title" msgid="4311705936714972757">"بگ رپورٹ <xliff:g id="ID">#%d</xliff:g> تخلیق ہو رہی ہے"</string>
     <string name="bugreport_finished_title" msgid="4429132808670114081">"بگ رپورٹ <xliff:g id="ID">#%d</xliff:g> کیپچر ہو گئی"</string>
+    <!-- no translation found for bugreport_finished_pending_screenshot_title (5460883450679439591) -->
+    <skip />
     <string name="bugreport_updating_title" msgid="4423539949559634214">"بگ رپورٹ میں تفصیلات شامل کی جا رہی ہیں"</string>
     <string name="bugreport_updating_wait" msgid="3322151947853929470">"براہ کرم انتظار کریں…"</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"اپنی بگ رپورٹ کا اشتراک کرنے کیلئے بائیں سوائپ کریں"</string>
     <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"اپنی بگ رپورٹ کا اشتراک کرنے کیلئے تھپتھپائیں"</string>
+    <!-- no translation found for bugreport_finished_pending_screenshot_text (1474435374470177193) -->
+    <skip />
+    <!-- no translation found for bugreport_finished_pending_screenshot_text (1474435374470177193) -->
+    <skip />
     <string name="bugreport_confirm" msgid="5130698467795669780">"بَگ رپورٹس میں سسٹم کی مختلف لاگ فائلوں سے ڈیٹا شامل ہوتا ہے، بشمول ذاتی اور نجی معلومات۔ بَگ رپورٹس کا اشتراک صرف اپنے بھروسے مند ایپس اور لوگوں کے ساتھ کریں۔"</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"یہ پیغام اگلی بار دکھائیں"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"بگ رپورٹس"</string>
@@ -34,6 +40,7 @@
     <string name="bugreport_screenshot_failed" msgid="5853049140806834601">"سکرین شاٹ نہیں لیا جا سکا۔"</string>
     <string name="bugreport_info_dialog_title" msgid="1355948594292983332">"بگ رپورٹ <xliff:g id="ID">#%d</xliff:g> کی تفصیلات"</string>
     <string name="bugreport_info_name" msgid="4414036021935139527">"فائل کا نام"</string>
-    <string name="bugreport_info_title" msgid="5599558206004371052">"عنوان"</string>
-    <string name="bugreport_info_description" msgid="4117088998733546784">"تفصیلی وضاحت"</string>
+    <string name="bugreport_info_title" msgid="2306030793918239804">"بَگ کا عنوان"</string>
+    <string name="bugreport_info_description" msgid="5072835127481627722">"بَگ کا خلاصہ"</string>
+    <string name="save" msgid="4781509040564835759">"محفوظ کریں"</string>
 </resources>
diff --git a/packages/Shell/res/values-uz-rUZ/strings.xml b/packages/Shell/res/values-uz-rUZ/strings.xml
index 39703a2..90d7718 100644
--- a/packages/Shell/res/values-uz-rUZ/strings.xml
+++ b/packages/Shell/res/values-uz-rUZ/strings.xml
@@ -19,10 +19,16 @@
     <string name="app_label" msgid="3701846017049540910">"Terminal"</string>
     <string name="bugreport_in_progress_title" msgid="4311705936714972757">"Xatoliklar hisoboti (<xliff:g id="ID">#%d</xliff:g>) tayyorlanmoqda"</string>
     <string name="bugreport_finished_title" msgid="4429132808670114081">"Xatoliklar hisoboti (<xliff:g id="ID">#%d</xliff:g>) yozib olindi"</string>
+    <!-- no translation found for bugreport_finished_pending_screenshot_title (5460883450679439591) -->
+    <skip />
     <string name="bugreport_updating_title" msgid="4423539949559634214">"Xatoliklar hisobotiga tafsilotlar qo‘shilmoqda"</string>
     <string name="bugreport_updating_wait" msgid="3322151947853929470">"Iltimos, kuting…"</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Xatolik hisobotini yuborish uchun barmog‘ingiz bilan chapga suring"</string>
     <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"Xatoliklar hisobotini ulashish uchun bosing"</string>
+    <!-- no translation found for bugreport_finished_pending_screenshot_text (1474435374470177193) -->
+    <skip />
+    <!-- no translation found for bugreport_finished_pending_screenshot_text (1474435374470177193) -->
+    <skip />
     <string name="bugreport_confirm" msgid="5130698467795669780">"Xatolik hisobotlari tizimdagi har xil jurnal fayllardagi ma’lumotlarni, shuningdek, shaxsiy hamda maxfiy ma’lumotlarni o‘z ichiga oladi. Xatolik hisobotlarini faqat ishonchli dasturlar va odamlar bilan bo‘lishing."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Ushbu xabar keyingi safar ko‘rsatilsin"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"Xatoliklar hisoboti"</string>
@@ -34,6 +40,7 @@
     <string name="bugreport_screenshot_failed" msgid="5853049140806834601">"Skrinshot olib bo‘lmadi."</string>
     <string name="bugreport_info_dialog_title" msgid="1355948594292983332">"Xatoliklar hisoboti (<xliff:g id="ID">#%d</xliff:g>) tafsilotlari"</string>
     <string name="bugreport_info_name" msgid="4414036021935139527">"Fayl nomi"</string>
-    <string name="bugreport_info_title" msgid="5599558206004371052">"Nomi"</string>
-    <string name="bugreport_info_description" msgid="4117088998733546784">"Batafsil ta’rif"</string>
+    <string name="bugreport_info_title" msgid="2306030793918239804">"Xatolik nomi"</string>
+    <string name="bugreport_info_description" msgid="5072835127481627722">"Xatolik ta’rifi"</string>
+    <string name="save" msgid="4781509040564835759">"Saqlash"</string>
 </resources>
diff --git a/packages/Shell/res/values-vi/strings.xml b/packages/Shell/res/values-vi/strings.xml
index 16ffaff..cb8c5b9 100644
--- a/packages/Shell/res/values-vi/strings.xml
+++ b/packages/Shell/res/values-vi/strings.xml
@@ -19,10 +19,16 @@
     <string name="app_label" msgid="3701846017049540910">"Shell"</string>
     <string name="bugreport_in_progress_title" msgid="4311705936714972757">"Báo cáo lỗi <xliff:g id="ID">#%d</xliff:g> đang được tạo"</string>
     <string name="bugreport_finished_title" msgid="4429132808670114081">"Đã chụp báo cáo lỗi <xliff:g id="ID">#%d</xliff:g>"</string>
+    <!-- no translation found for bugreport_finished_pending_screenshot_title (5460883450679439591) -->
+    <skip />
     <string name="bugreport_updating_title" msgid="4423539949559634214">"Đang thêm thông tin chi tiết vào báo cáo lỗi"</string>
     <string name="bugreport_updating_wait" msgid="3322151947853929470">"Vui lòng đợi…"</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Vuốt sang trái để chia sẻ báo cáo lỗi của bạn"</string>
     <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"Nhấn để chia sẻ báo cáo lỗi của bạn"</string>
+    <!-- no translation found for bugreport_finished_pending_screenshot_text (1474435374470177193) -->
+    <skip />
+    <!-- no translation found for bugreport_finished_pending_screenshot_text (1474435374470177193) -->
+    <skip />
     <string name="bugreport_confirm" msgid="5130698467795669780">"Các báo cáo lỗi chứa dữ liệu từ nhiều tệp nhật ký khác nhau của hệ thống, bao gồm cả thông tin cá nhân và riêng tư. Chỉ chia sẻ báo cáo lỗi với các ứng dụng và những người mà bạn tin tưởng."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Hiển thị thông báo này vào lần tới"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"Báo cáo lỗi"</string>
@@ -34,6 +40,7 @@
     <string name="bugreport_screenshot_failed" msgid="5853049140806834601">"Không thể chụp ảnh màn hình."</string>
     <string name="bugreport_info_dialog_title" msgid="1355948594292983332">"Chi tiết báo cáo lỗi <xliff:g id="ID">#%d</xliff:g>"</string>
     <string name="bugreport_info_name" msgid="4414036021935139527">"Tên tệp"</string>
-    <string name="bugreport_info_title" msgid="5599558206004371052">"Tiêu đề"</string>
-    <string name="bugreport_info_description" msgid="4117088998733546784">"Mô tả chi tiết"</string>
+    <string name="bugreport_info_title" msgid="2306030793918239804">"Tiêu đề lỗi"</string>
+    <string name="bugreport_info_description" msgid="5072835127481627722">"Tóm tắt lỗi"</string>
+    <string name="save" msgid="4781509040564835759">"Lưu"</string>
 </resources>
diff --git a/packages/Shell/res/values-zh-rCN/strings.xml b/packages/Shell/res/values-zh-rCN/strings.xml
index 382478e..6e13d75 100644
--- a/packages/Shell/res/values-zh-rCN/strings.xml
+++ b/packages/Shell/res/values-zh-rCN/strings.xml
@@ -19,10 +19,16 @@
     <string name="app_label" msgid="3701846017049540910">"Shell"</string>
     <string name="bugreport_in_progress_title" msgid="4311705936714972757">"正在生成错误报告 <xliff:g id="ID">#%d</xliff:g>"</string>
     <string name="bugreport_finished_title" msgid="4429132808670114081">"已捕获错误报告 <xliff:g id="ID">#%d</xliff:g>"</string>
+    <!-- no translation found for bugreport_finished_pending_screenshot_title (5460883450679439591) -->
+    <skip />
     <string name="bugreport_updating_title" msgid="4423539949559634214">"正在向错误报告添加详细信息"</string>
     <string name="bugreport_updating_wait" msgid="3322151947853929470">"请稍候…"</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"向左滑动即可分享错误报告"</string>
     <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"点按即可分享您的错误报告"</string>
+    <!-- no translation found for bugreport_finished_pending_screenshot_text (1474435374470177193) -->
+    <skip />
+    <!-- no translation found for bugreport_finished_pending_screenshot_text (1474435374470177193) -->
+    <skip />
     <string name="bugreport_confirm" msgid="5130698467795669780">"错误报告包含的数据来自于系统的各个日志文件,其中包含个人信息和隐私信息。请务必只与您信任的应用和用户分享错误报告。"</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"下次再显示这条讯息"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"错误报告"</string>
@@ -34,6 +40,7 @@
     <string name="bugreport_screenshot_failed" msgid="5853049140806834601">"无法截图。"</string>
     <string name="bugreport_info_dialog_title" msgid="1355948594292983332">"错误报告 <xliff:g id="ID">#%d</xliff:g> 详情"</string>
     <string name="bugreport_info_name" msgid="4414036021935139527">"文件名"</string>
-    <string name="bugreport_info_title" msgid="5599558206004371052">"标题"</string>
-    <string name="bugreport_info_description" msgid="4117088998733546784">"详细说明"</string>
+    <string name="bugreport_info_title" msgid="2306030793918239804">"错误标题"</string>
+    <string name="bugreport_info_description" msgid="5072835127481627722">"错误摘要"</string>
+    <string name="save" msgid="4781509040564835759">"保存"</string>
 </resources>
diff --git a/packages/Shell/res/values-zh-rHK/strings.xml b/packages/Shell/res/values-zh-rHK/strings.xml
index 04b5e48..7ade56b 100644
--- a/packages/Shell/res/values-zh-rHK/strings.xml
+++ b/packages/Shell/res/values-zh-rHK/strings.xml
@@ -19,10 +19,16 @@
     <string name="app_label" msgid="3701846017049540910">"命令介面"</string>
     <string name="bugreport_in_progress_title" msgid="4311705936714972757">"正在產生錯誤報告 <xliff:g id="ID">#%d</xliff:g>"</string>
     <string name="bugreport_finished_title" msgid="4429132808670114081">"已擷取錯誤報告 <xliff:g id="ID">#%d</xliff:g>"</string>
+    <!-- no translation found for bugreport_finished_pending_screenshot_title (5460883450679439591) -->
+    <skip />
     <string name="bugreport_updating_title" msgid="4423539949559634214">"正在新增錯誤報告詳細資訊"</string>
     <string name="bugreport_updating_wait" msgid="3322151947853929470">"請稍候…"</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"向左滑動即可分享錯誤報告"</string>
     <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"輕按即可分享錯誤報告"</string>
+    <!-- no translation found for bugreport_finished_pending_screenshot_text (1474435374470177193) -->
+    <skip />
+    <!-- no translation found for bugreport_finished_pending_screenshot_text (1474435374470177193) -->
+    <skip />
     <string name="bugreport_confirm" msgid="5130698467795669780">"錯誤報告中有來自系統各個記錄檔案的資料,包括個人和私人資料。請只與您信任的應用程式和使用者分享錯誤報告。"</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"下次再顯示這則訊息"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"錯誤報告"</string>
@@ -34,6 +40,7 @@
     <string name="bugreport_screenshot_failed" msgid="5853049140806834601">"無法擷取螢幕畫面。"</string>
     <string name="bugreport_info_dialog_title" msgid="1355948594292983332">"錯誤報告 <xliff:g id="ID">#%d</xliff:g> 的詳情"</string>
     <string name="bugreport_info_name" msgid="4414036021935139527">"檔案名稱"</string>
-    <string name="bugreport_info_title" msgid="5599558206004371052">"標題"</string>
-    <string name="bugreport_info_description" msgid="4117088998733546784">"詳細說明"</string>
+    <string name="bugreport_info_title" msgid="2306030793918239804">"錯誤標題"</string>
+    <string name="bugreport_info_description" msgid="5072835127481627722">"錯誤摘要"</string>
+    <string name="save" msgid="4781509040564835759">"儲存"</string>
 </resources>
diff --git a/packages/Shell/res/values-zh-rTW/strings.xml b/packages/Shell/res/values-zh-rTW/strings.xml
index 7a1ab77..8695d5f 100644
--- a/packages/Shell/res/values-zh-rTW/strings.xml
+++ b/packages/Shell/res/values-zh-rTW/strings.xml
@@ -19,10 +19,16 @@
     <string name="app_label" msgid="3701846017049540910">"殼層"</string>
     <string name="bugreport_in_progress_title" msgid="4311705936714972757">"正在產生錯誤報告 <xliff:g id="ID">#%d</xliff:g>"</string>
     <string name="bugreport_finished_title" msgid="4429132808670114081">"已擷取錯誤報告 <xliff:g id="ID">#%d</xliff:g>"</string>
+    <!-- no translation found for bugreport_finished_pending_screenshot_title (5460883450679439591) -->
+    <skip />
     <string name="bugreport_updating_title" msgid="4423539949559634214">"正在新增錯誤報告詳細資訊"</string>
     <string name="bugreport_updating_wait" msgid="3322151947853929470">"請稍候…"</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"向左滑動即可分享錯誤報告"</string>
     <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"輕按即可分享錯誤報告"</string>
+    <!-- no translation found for bugreport_finished_pending_screenshot_text (1474435374470177193) -->
+    <skip />
+    <!-- no translation found for bugreport_finished_pending_screenshot_text (1474435374470177193) -->
+    <skip />
     <string name="bugreport_confirm" msgid="5130698467795669780">"錯誤報告的資料來自系統各個紀錄檔,包括個人和私密資訊。請務必只與您信任的應用程式和使用者分享錯誤報告。"</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"下次仍顯示這則訊息"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"錯誤報告"</string>
@@ -34,6 +40,7 @@
     <string name="bugreport_screenshot_failed" msgid="5853049140806834601">"無法拍攝螢幕擷取畫面。"</string>
     <string name="bugreport_info_dialog_title" msgid="1355948594292983332">"錯誤報告 <xliff:g id="ID">#%d</xliff:g> 的詳細資料"</string>
     <string name="bugreport_info_name" msgid="4414036021935139527">"檔案名稱"</string>
-    <string name="bugreport_info_title" msgid="5599558206004371052">"標題"</string>
-    <string name="bugreport_info_description" msgid="4117088998733546784">"詳細說明"</string>
+    <string name="bugreport_info_title" msgid="2306030793918239804">"錯誤標題"</string>
+    <string name="bugreport_info_description" msgid="5072835127481627722">"錯誤摘要"</string>
+    <string name="save" msgid="4781509040564835759">"儲存"</string>
 </resources>
diff --git a/packages/Shell/res/values-zu/strings.xml b/packages/Shell/res/values-zu/strings.xml
index 29b7dd83..561ac0a 100644
--- a/packages/Shell/res/values-zu/strings.xml
+++ b/packages/Shell/res/values-zu/strings.xml
@@ -19,10 +19,13 @@
     <string name="app_label" msgid="3701846017049540910">"I-Shell"</string>
     <string name="bugreport_in_progress_title" msgid="4311705936714972757">"Umbiko wesiphazamisi ongu-<xliff:g id="ID">#%d</xliff:g> uyacutshungulwa"</string>
     <string name="bugreport_finished_title" msgid="4429132808670114081">"Umbiko wesiphazamisi ongu-<xliff:g id="ID">#%d</xliff:g> uthwetshuliwe"</string>
+    <string name="bugreport_finished_pending_screenshot_title" msgid="5460883450679439591">"Umbiko wesiphazamisi esingu-<xliff:g id="ID">#%d</xliff:g> uthwetshuliwe kodwa isithombe-skrini silindile"</string>
     <string name="bugreport_updating_title" msgid="4423539949559634214">"Ingeza imininingwane kumbiko wesiphazamisi"</string>
     <string name="bugreport_updating_wait" msgid="3322151947853929470">"Sicela ulinde..."</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Swayiphela kwesokunxele ukuze wabelane umbiko wesiphazamiso sakho"</string>
     <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"Thepha ukuze wabelane ngombiko wakho wesiphazamisi"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"Thepha ukuze wabelane ngombiko wesiphazamisi ngaphandle kwesithombe-skrini noma ulinde isithombe-skrini ukuthi siqede"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"Thepha ukuze wabelane ngombiko wesiphazamisi ngaphandle kwesithombe-skrini noma ulinde isithombe-skrini ukuthi siqede"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"Imibiko yeziphazamisi iqukethe idatha yamafayela wokungena ahlukile wesistimu, afaka ulwazi lomuntu siqu noma lobumfihlo. Yabelana kuphela ngemibiko yeziphazamisi nezinhlelo zokusebenza nabantu obathembayo."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Bonisa lo mlayezo ngesikhathi esilandelayo"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"Imibiko yeziphazamiso"</string>
@@ -34,6 +37,7 @@
     <string name="bugreport_screenshot_failed" msgid="5853049140806834601">"Isithombe-skrini asikwazanga ukuthathwa."</string>
     <string name="bugreport_info_dialog_title" msgid="1355948594292983332">"Imininingwane yombiko wesiphazamisi ongu-<xliff:g id="ID">#%d</xliff:g>"</string>
     <string name="bugreport_info_name" msgid="4414036021935139527">"Igama lefayela"</string>
-    <string name="bugreport_info_title" msgid="5599558206004371052">"Isihloko"</string>
-    <string name="bugreport_info_description" msgid="4117088998733546784">"Incazelo enemininingwane"</string>
+    <string name="bugreport_info_title" msgid="2306030793918239804">"Isihloko sesiphazamisi"</string>
+    <string name="bugreport_info_description" msgid="5072835127481627722">"Isifinyezo sesiphazamisi"</string>
+    <string name="save" msgid="4781509040564835759">"Londoloza"</string>
 </resources>
diff --git a/packages/Shell/res/values/strings.xml b/packages/Shell/res/values/strings.xml
index c26b549..5d90189 100644
--- a/packages/Shell/res/values/strings.xml
+++ b/packages/Shell/res/values/strings.xml
@@ -20,6 +20,8 @@
     <string name="bugreport_in_progress_title">Bug report <xliff:g id="id">#%d</xliff:g> is being generated</string>
     <!-- Title of notification indicating a bugreport has been successfully captured. [CHAR LIMIT=50] -->
     <string name="bugreport_finished_title">Bug report <xliff:g id="id">#%d</xliff:g> captured</string>
+    <!-- Title of notification indicating a bugreport has been successfully captured, but screenshot is not finished yet. [CHAR LIMIT=50] -->
+    <string name="bugreport_finished_pending_screenshot_title">Bug report <xliff:g id="id">#%d</xliff:g> captured but screenshot pending</string>
     <!-- Title of notification indicating a bugreport is being updated before it can be shared. [CHAR LIMIT=50] -->
     <string name="bugreport_updating_title">Adding details to the bug report</string>
     <!-- Content notification indicating a bugreport is being updated before it can be shared, asking the user to wait [CHAR LIMIT=50] -->
@@ -29,7 +31,10 @@
     <string name="bugreport_finished_text" product="watch">Swipe left to share your bug report</string>
     <!-- Text of notification indicating that tapping will share the captured bugreport. [CHAR LIMIT=100] -->
     <string name="bugreport_finished_text" product="default">Tap to share your bug report</string>
-
+    <!-- Text of notification indicating that swipe left will share the captured bugreport, but giving user the option to wait for the screenshot. [CHAR LIMIT=100] -->
+    <string name="bugreport_finished_pending_screenshot_text" product="watch">Tap to share your bug report without a screenshot or wait for the screenshot to finish</string>
+    <!-- Text of notification indicating that tapping will share the captured bugreport, but giving user the option to wait for the screenshot. [CHAR LIMIT=100] -->
+    <string name="bugreport_finished_pending_screenshot_text" product="default">Tap to share your bug report without a screenshot or wait for the screenshot to finish</string>
 
     <!-- Body of dialog informing user about contents of a bugreport. [CHAR LIMIT=NONE] -->
     <string name="bugreport_confirm">Bug reports contain data from the system\'s various log files, including personal and private information.  Only share bug reports with apps and people you trust.</string>
@@ -59,13 +64,16 @@
     <!--  Title of the dialog asking for user-defined bug report details like name, title, and description. -->
     <string name="bugreport_info_dialog_title">Bug report <xliff:g id="id">#%d</xliff:g> details</string>
 
-    <!-- Text of the hint asking for the bug report name, which when set will define a suffix in the
+    <!-- Text of the label identifying the bug report name, which when set will define a suffix in the
          bug report file names. [CHAR LIMIT=30] -->
     <string name="bugreport_info_name">Filename</string>
-    <!-- Text of hint asking for the bug report title, which when set will define the
+    <!-- Text of the label identifying the bug report title, which when set will define the
          Subject of the email message. [CHAR LIMIT=60] -->
-    <string name="bugreport_info_title">Title</string>
-    <!-- Text of hint asking for the bug report description, which when set will describe
+    <string name="bugreport_info_title">Bug title</string>
+    <!-- Text of the label identifying the bug report description, which when set will describe
          what the bug report is about. [CHAR LIMIT=NONE] -->
-    <string name="bugreport_info_description">Detailed description</string>
+    <string name="bugreport_info_description">Bug summary</string>
+
+    <!-- Label of button that save bugreport details.  -->
+    <string name="save">Save</string>
 </resources>
diff --git a/packages/Shell/src/com/android/shell/BugreportProgressService.java b/packages/Shell/src/com/android/shell/BugreportProgressService.java
index 587fd6c..d212d53 100644
--- a/packages/Shell/src/com/android/shell/BugreportProgressService.java
+++ b/packages/Shell/src/com/android/shell/BugreportProgressService.java
@@ -56,7 +56,6 @@
 import android.app.Service;
 import android.content.ClipData;
 import android.content.Context;
-import android.content.ContextWrapper;
 import android.content.DialogInterface;
 import android.content.Intent;
 import android.content.res.Configuration;
@@ -121,8 +120,6 @@
     static final String INTENT_BUGREPORT_FINISHED = "android.intent.action.BUGREPORT_FINISHED";
     static final String INTENT_REMOTE_BUGREPORT_FINISHED =
             "android.intent.action.REMOTE_BUGREPORT_FINISHED";
-    static final String INTENT_REMOTE_BUGREPORT_DISPATCH =
-            "android.intent.action.REMOTE_BUGREPORT_DISPATCH";
 
     // Internal intents used on notification actions.
     static final String INTENT_BUGREPORT_CANCEL = "android.intent.action.BUGREPORT_CANCEL";
@@ -208,7 +205,7 @@
         mMainHandler = new ServiceHandler("BugreportProgressServiceMainThread");
         mScreenshotHandler = new ScreenshotHandler("BugreportProgressServiceScreenshotThread");
 
-        mScreenshotsDir = new File(new ContextWrapper(mContext).getFilesDir(), SCREENSHOT_DIR);
+        mScreenshotsDir = new File(getFilesDir(), SCREENSHOT_DIR);
         if (!mScreenshotsDir.exists()) {
             Log.i(TAG, "Creating directory " + mScreenshotsDir + " to store temporary screenshots");
             if (!mScreenshotsDir.mkdir()) {
@@ -436,10 +433,12 @@
         final Intent infoIntent = new Intent(mContext, BugreportProgressService.class);
         infoIntent.setAction(INTENT_BUGREPORT_INFO_LAUNCH);
         infoIntent.putExtra(EXTRA_ID, info.id);
+        final PendingIntent infoPendingIntent =
+                PendingIntent.getService(mContext, info.id, infoIntent,
+                PendingIntent.FLAG_UPDATE_CURRENT);
         final Action infoAction = new Action.Builder(null,
                 mContext.getString(R.string.bugreport_info_action),
-                PendingIntent.getService(mContext, info.id, infoIntent,
-                        PendingIntent.FLAG_UPDATE_CURRENT)).build();
+                infoPendingIntent).build();
         final Intent screenshotIntent = new Intent(mContext, BugreportProgressService.class);
         screenshotIntent.setAction(INTENT_BUGREPORT_SCREENSHOT);
         screenshotIntent.putExtra(EXTRA_ID, info.id);
@@ -466,6 +465,7 @@
                 .setLocalOnly(true)
                 .setColor(mContext.getColor(
                         com.android.internal.R.color.system_notification_accent_color))
+                .setContentIntent(infoPendingIntent)
                 .addAction(infoAction)
                 .addAction(screenshotAction)
                 .addAction(cancelAction)
@@ -504,9 +504,9 @@
             Log.d(TAG, "Removing ID " + id);
             mProcesses.remove(id);
         }
-        stopSelfWhenDone();
         Log.v(TAG, "stopProgress(" + id + "): cancel notification");
         NotificationManager.from(mContext).cancel(TAG, id);
+        stopSelfWhenDone();
     }
 
     /**
@@ -598,7 +598,8 @@
             // Most likely am killed Shell before user tapped the notification. Since system might
             // be too busy anwyays, it's better to ignore the notification and switch back to the
             // non-interactive mode (where the bugerport will be shared upon completion).
-            Log.d(TAG, "launchBugreportInfoDialog(" + id + "): cancel notification");
+            Log.w(TAG, "launchBugreportInfoDialog(): canceling notification because id " + id
+                    + " was not found");
             // TODO: add test case to make sure notification is canceled.
             NotificationManager.from(mContext).cancel(TAG, id);
             return;
@@ -624,7 +625,8 @@
             // Most likely am killed Shell before user tapped the notification. Since system might
             // be too busy anwyays, it's better to ignore the notification and switch back to the
             // non-interactive mode (where the bugerport will be shared upon completion).
-            Log.d(TAG, "takeScreenshot(" + id + ", " + delayed + "): cancel notification");
+            Log.w(TAG, "takeScreenshot(): canceling notification because id " + id
+                    + " was not found");
             // TODO: add test case to make sure notification is canceled.
             NotificationManager.from(mContext).cancel(TAG, id);
             return;
@@ -712,7 +714,7 @@
             if (info.finished) {
                 Log.d(TAG, "Screenshot finished after bugreport; updating share notification");
                 info.renameScreenshots(mScreenshotsDir);
-                sendBugreportNotification(mContext, info);
+                sendBugreportNotification(mContext, info, mTakingScreenshot);
             }
             msg = mContext.getString(R.string.bugreport_screenshot_taken);
         } else {
@@ -801,10 +803,10 @@
         boolean isPlainText = info.bugreportFile.getName().toLowerCase().endsWith(".txt");
         if (!isPlainText) {
             // Already zipped, send it right away.
-            sendBugreportNotification(context, info);
+            sendBugreportNotification(context, info, mTakingScreenshot);
         } else {
             // Asynchronously zip the file first, then send it.
-            sendZippedBugreportNotification(context, info);
+            sendZippedBugreportNotification(context, info, mTakingScreenshot);
         }
     }
 
@@ -874,6 +876,8 @@
             info = sharedInfo;
             Log.d(TAG, "shareBugreport(): no info for ID " + id + " on managed processes ("
                     + mProcesses + "), using info from intent instead (" + info + ")");
+        } else {
+            Log.v(TAG, "shareBugReport(): id " + id + " info = " + info);
         }
 
         addDetailsToZipFile(mContext, info);
@@ -899,7 +903,8 @@
     /**
      * Sends a notification indicating the bugreport has finished so use can share it.
      */
-    private static void sendBugreportNotification(Context context, BugreportInfo info) {
+    private static void sendBugreportNotification(Context context, BugreportInfo info,
+            boolean takingScreenshot) {
 
         // Since adding the details can take a while, do it before notifying user.
         addDetailsToZipFile(context, info);
@@ -910,12 +915,20 @@
         shareIntent.putExtra(EXTRA_ID, info.id);
         shareIntent.putExtra(EXTRA_INFO, info);
 
-        final String title = context.getString(R.string.bugreport_finished_title, info.id);
+        final String title, content;
+        if (takingScreenshot) {
+            title = context.getString(R.string.bugreport_finished_pending_screenshot_title,
+                    info.id);
+            content = context.getString(R.string.bugreport_finished_pending_screenshot_text);
+        } else {
+            title = context.getString(R.string.bugreport_finished_title, info.id);
+            content = context.getString(R.string.bugreport_finished_text);
+        }
         final Notification.Builder builder = new Notification.Builder(context)
                 .setSmallIcon(com.android.internal.R.drawable.stat_sys_adb)
                 .setContentTitle(title)
                 .setTicker(title)
-                .setContentText(context.getString(R.string.bugreport_finished_text))
+                .setContentText(content)
                 .setContentIntent(PendingIntent.getService(context, info.id, shareIntent,
                         PendingIntent.FLAG_UPDATE_CURRENT))
                 .setDeleteIntent(newCancelIntent(context, info))
@@ -954,12 +967,12 @@
      * Sends a zipped bugreport notification.
      */
     private static void sendZippedBugreportNotification(final Context context,
-            final BugreportInfo info) {
+            final BugreportInfo info, final boolean takingScreenshot) {
         new AsyncTask<Void, Void, Void>() {
             @Override
             protected Void doInBackground(Void... params) {
                 zipBugreport(info);
-                sendBugreportNotification(context, info);
+                sendBugreportNotification(context, info, takingScreenshot);
                 return null;
             }
         }.execute();
@@ -1177,14 +1190,13 @@
      * Takes a screenshot and save it to the given location.
      */
     private static boolean takeScreenshot(Context context, String screenshotFile) {
-        ((Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE))
-                .vibrate(150);
         final ProcessBuilder screencap = new ProcessBuilder()
                 .command("/system/bin/screencap", "-p", screenshotFile);
         Log.d(TAG, "Taking screenshot using " + screencap.command());
         try {
             final int exitValue = screencap.start().waitFor();
             if (exitValue == 0) {
+                ((Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE)).vibrate(150);
                 return true;
             }
             Log.e(TAG, "screencap (" + screencap.command() + ") failed: " + exitValue);
@@ -1265,6 +1277,9 @@
                         if (hasFocus) {
                             return;
                         }
+                        // Select-all is useful just initially, since the date-based filename is
+                        // full of hyphens.
+                        mInfoName.setSelectAllOnFocus(false);
                         sanitizeName();
                     }
                 });
@@ -1273,7 +1288,7 @@
                         .setView(view)
                         .setTitle(dialogTitle)
                         .setCancelable(false)
-                        .setPositiveButton(context.getString(com.android.internal.R.string.ok),
+                        .setPositiveButton(context.getString(R.string.save),
                                 null)
                         .setNegativeButton(context.getString(com.android.internal.R.string.cancel),
                                 new DialogInterface.OnClickListener()
@@ -1526,6 +1541,7 @@
                 final File newFile;
                 if (!newName.equals(oldName)) {
                     final File renamedFile = new File(screenshotDir, newName);
+                    Log.d(TAG, "Renaming screenshot file " + oldFile + " to " + renamedFile);
                     newFile = oldFile.renameTo(renamedFile) ? renamedFile : oldFile;
                 } else {
                     Log.w(TAG, "Name didn't change: " + oldName); // Shouldn't happen.
diff --git a/packages/Shell/src/com/android/shell/BugreportStorageProvider.java b/packages/Shell/src/com/android/shell/BugreportStorageProvider.java
index 814aa8c..49759c5 100644
--- a/packages/Shell/src/com/android/shell/BugreportStorageProvider.java
+++ b/packages/Shell/src/com/android/shell/BugreportStorageProvider.java
@@ -56,7 +56,7 @@
         final MatrixCursor result = new MatrixCursor(resolveRootProjection(projection));
         final RowBuilder row = result.newRow();
         row.add(Root.COLUMN_ROOT_ID, DOC_ID_ROOT);
-        row.add(Root.COLUMN_FLAGS, Root.FLAG_LOCAL_ONLY | Root.FLAG_ADVANCED);
+        row.add(Root.COLUMN_FLAGS, Root.FLAG_LOCAL_ONLY);
         row.add(Root.COLUMN_ICON, android.R.mipmap.sym_def_app_icon);
         row.add(Root.COLUMN_TITLE, getContext().getString(R.string.bugreport_storage_title));
         row.add(Root.COLUMN_DOCUMENT_ID, DOC_ID_ROOT);
diff --git a/packages/Shell/src/com/android/shell/RemoteBugreportReceiver.java b/packages/Shell/src/com/android/shell/RemoteBugreportReceiver.java
index be54b43..634c3b4 100644
--- a/packages/Shell/src/com/android/shell/RemoteBugreportReceiver.java
+++ b/packages/Shell/src/com/android/shell/RemoteBugreportReceiver.java
@@ -18,13 +18,13 @@
 
 import static com.android.shell.BugreportProgressService.EXTRA_BUGREPORT;
 import static com.android.shell.BugreportProgressService.INTENT_REMOTE_BUGREPORT_FINISHED;
-import static com.android.shell.BugreportProgressService.INTENT_REMOTE_BUGREPORT_DISPATCH;
 import static com.android.shell.BugreportProgressService.getFileExtra;
 import static com.android.shell.BugreportProgressService.getUri;
 import static com.android.shell.BugreportReceiver.cleanupOldFiles;
 
 import java.io.File;
 
+import android.app.admin.DevicePolicyManager;
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
@@ -41,8 +41,6 @@
 public class RemoteBugreportReceiver extends BroadcastReceiver {
 
     private static final String BUGREPORT_MIMETYPE = "application/vnd.android.bugreport";
-    private static final String EXTRA_REMOTE_BUGREPORT_HASH =
-            "android.intent.extra.REMOTE_BUGREPORT_HASH";
 
     /** Always keep just the last remote bugreport's files around. */
     private static final int REMOTE_BUGREPORT_FILES_AMOUNT = 3;
@@ -57,11 +55,12 @@
 
         final File bugreportFile = getFileExtra(intent, EXTRA_BUGREPORT);
         final Uri bugreportUri = getUri(context, bugreportFile);
-        final String bugreportHash = intent.getStringExtra(EXTRA_REMOTE_BUGREPORT_HASH);
+        final String bugreportHash = intent.getStringExtra(
+                DevicePolicyManager.EXTRA_REMOTE_BUGREPORT_HASH);
 
-        final Intent newIntent = new Intent(INTENT_REMOTE_BUGREPORT_DISPATCH);
+        final Intent newIntent = new Intent(DevicePolicyManager.ACTION_REMOTE_BUGREPORT_DISPATCH);
         newIntent.setDataAndType(bugreportUri, BUGREPORT_MIMETYPE);
-        newIntent.putExtra(EXTRA_REMOTE_BUGREPORT_HASH, bugreportHash);
+        newIntent.putExtra(DevicePolicyManager.EXTRA_REMOTE_BUGREPORT_HASH, bugreportHash);
         context.sendBroadcastAsUser(newIntent, UserHandle.SYSTEM,
                 android.Manifest.permission.DUMP);
     }
diff --git a/packages/Shell/tests/src/com/android/shell/BugreportReceiverTest.java b/packages/Shell/tests/src/com/android/shell/BugreportReceiverTest.java
index 3cef3bb..47e3b3b 100644
--- a/packages/Shell/tests/src/com/android/shell/BugreportReceiverTest.java
+++ b/packages/Shell/tests/src/com/android/shell/BugreportReceiverTest.java
@@ -130,6 +130,9 @@
     private static final boolean RENAMED_SCREENSHOTS = true;
     private static final boolean DIDNT_RENAME_SCREENSHOTS = false;
 
+    private static final boolean PENDING_SCREENSHOT = true;
+    private static final boolean NOT_PENDING_SCREENSHOT = false;
+
     private String mDescription;
 
     private String mPlainTextPath;
@@ -198,6 +201,25 @@
         assertServiceNotRunning();
     }
 
+    public void testProgress_cancel() throws Exception {
+        resetProperties();
+        sendBugreportStarted(1000);
+        waitForScreenshotButtonEnabled(true);
+
+        final NumberFormat nf = NumberFormat.getPercentInstance();
+        nf.setMinimumFractionDigits(2);
+        nf.setMaximumFractionDigits(2);
+
+        assertProgressNotification(NAME, nf.format(0));
+
+        openProgressNotification(ID);
+        UiObject cancelButton = mUiBot.getVisibleObject(mContext.getString(
+                com.android.internal.R.string.cancel).toUpperCase());
+        mUiBot.click(cancelButton, "cancel_button");
+
+        waitForService(false);
+    }
+
     public void testProgress_takeExtraScreenshot() throws Exception {
         takeExtraScreenshotTest(false);
     }
@@ -339,12 +361,20 @@
         assertServiceNotRunning();
     }
 
-    public void testProgress_changeJustDetails() throws Exception {
+    public void testProgress_changeJustDetailsTouchingDetails() throws Exception {
+        changeJustDetailsTest(true);
+    }
+
+    public void testProgress_changeJustDetailsTouchingNotification() throws Exception {
+        changeJustDetailsTest(false);
+    }
+
+    private void changeJustDetailsTest(boolean touchDetails) throws Exception {
         resetProperties();
         sendBugreportStarted(1000);
         waitForScreenshotButtonEnabled(true);
 
-        DetailsUi detailsUi = new DetailsUi(mUiBot, ID);
+        DetailsUi detailsUi = new DetailsUi(mUiBot, ID, touchDetails);
 
         detailsUi.nameField.setText("");
         detailsUi.titleField.setText("");
@@ -373,8 +403,8 @@
 
         DetailsUi detailsUi = new DetailsUi(mUiBot, ID);
         detailsUi.assertName(NAME);
-        detailsUi.assertTitle(mContext.getString(R.string.bugreport_info_title));
-        detailsUi.assertDescription(mContext.getString(R.string.bugreport_info_description));
+        detailsUi.assertTitle("");
+        detailsUi.assertDescription("");
         detailsUi.nameField.setText(NEW_NAME);
         detailsUi.titleField.setText(TITLE);
         detailsUi.descField.setText(DESCRIPTION);
@@ -382,14 +412,13 @@
 
         sendBugreportStarted(ID2, PID2, NAME2, 1000);
 
-        Bundle extras = sendBugreportFinishedAndGetSharedIntent(ID, mZipPath, mScreenshotPath);
-        assertActionSendMultiple(extras, BUGREPORT_CONTENT, SCREENSHOT_CONTENT, ID, PID, TITLE,
-                NEW_NAME, TITLE, DESCRIPTION, 1, RENAMED_SCREENSHOTS);
+        sendBugreportFinished(ID, mZipPath, mScreenshotPath);
+        Bundle extras = acceptBugreportAndGetSharedIntent(ID, PENDING_SCREENSHOT);
 
         detailsUi = new DetailsUi(mUiBot, ID2);
         detailsUi.assertName(NAME2);
-        detailsUi.assertTitle(mContext.getString(R.string.bugreport_info_title));
-        detailsUi.assertDescription(mContext.getString(R.string.bugreport_info_description));
+        detailsUi.assertTitle("");
+        detailsUi.assertDescription("");
         detailsUi.nameField.setText(NEW_NAME2);
         detailsUi.titleField.setText(TITLE2);
         detailsUi.descField.setText(DESCRIPTION2);
@@ -527,10 +556,10 @@
         mUiBot.getObject(percent);
     }
 
-    private void openProgressNotification(int id) {
+    private UiObject openProgressNotification(int id) {
         String title = mContext.getString(R.string.bugreport_in_progress_title, id);
         Log.v(TAG, "Looking for progress notification title: '" + title + "'");
-        mUiBot.getNotification(title);
+        return mUiBot.getNotification(title);
     }
 
     void resetProperties() {
@@ -575,7 +604,7 @@
     private Bundle sendBugreportFinishedAndGetSharedIntent(int id, String bugreportPath,
             String screenshotPath) {
         sendBugreportFinished(id, bugreportPath, screenshotPath);
-        return acceptBugreportAndGetSharedIntent(id);
+        return acceptBugreportAndGetSharedIntent(id, NOT_PENDING_SCREENSHOT);
     }
 
     /**
@@ -584,7 +613,11 @@
      * @return extras sent in the shared intent.
      */
     private Bundle acceptBugreportAndGetSharedIntent(int id) {
-        acceptBugreport(id);
+        return acceptBugreportAndGetSharedIntent(id, NOT_PENDING_SCREENSHOT);
+    }
+
+    private Bundle acceptBugreportAndGetSharedIntent(int id, boolean pendingScreenshot) {
+        acceptBugreport(id, pendingScreenshot);
         mUiBot.chooseActivity(UI_NAME);
         return mListener.getExtras();
     }
@@ -600,7 +633,13 @@
      * Accepts the notification to share the finished bugreport.
      */
     private void acceptBugreport(int id) {
-        mUiBot.clickOnNotification(mContext.getString(R.string.bugreport_finished_title, id));
+        acceptBugreport(id, NOT_PENDING_SCREENSHOT);
+    }
+
+    private void acceptBugreport(int id, boolean pendingScreenshot) {
+        final int res = pendingScreenshot ? R.string.bugreport_finished_pending_screenshot_title
+                : R.string.bugreport_finished_title;
+        mUiBot.clickOnNotification(mContext.getString(res, id));
     }
 
     /**
@@ -899,11 +938,23 @@
          * Gets the UI objects by opening the progress notification and clicking DETAILS.
          */
         DetailsUi(UiBot uiBot, int id) throws UiObjectNotFoundException {
-            openProgressNotification(id);
+            this(uiBot, id, true);
+        }
+
+        /**
+         * Gets the UI objects by opening the progress notification and clicking on DETAILS or in
+         * the notification itself.
+         */
+        DetailsUi(UiBot uiBot, int id, boolean clickDetails) throws UiObjectNotFoundException {
+            UiObject notification = openProgressNotification(id);
             detailsButton = mUiBot.getVisibleObject(mContext.getString(
                     R.string.bugreport_info_action).toUpperCase());
 
-            mUiBot.click(detailsButton, "details_button");
+            if (clickDetails) {
+                mUiBot.click(detailsButton, "details_button");
+            } else {
+                mUiBot.click(notification, "notification");
+            }
             // TODO: unhardcode resource ids
             UiObject dialogTitle = mUiBot.getVisibleObjectById("android:id/alertTitle");
             assertEquals("Wrong title", mContext.getString(R.string.bugreport_info_dialog_title,
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index c590ec7a..334035c 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -82,6 +82,7 @@
     <uses-permission android:name="android.permission.GET_TOP_ACTIVITY_INFO" />
     <uses-permission android:name="android.permission.MANAGE_ACTIVITY_STACKS" />
     <uses-permission android:name="android.permission.START_TASKS_FROM_RECENTS" />
+    <uses-permission android:name="android.permission.GET_INTENT_SENDER_INTENT" />
 
     <!-- WindowManager -->
     <uses-permission android:name="android.permission.INTERNAL_SYSTEM_WINDOW" />
@@ -186,6 +187,15 @@
             android:process=":screenshot"
             android:exported="false" />
 
+        <!-- Called from PhoneWindowManager -->
+        <receiver android:name=".screenshot.ScreenshotServiceErrorReceiver"
+            android:process=":screenshot"
+            android:exported="false">
+            <intent-filter>
+                <action android:name="com.android.systemui.screenshot.SHOW_ERROR" />
+            </intent-filter>
+        </receiver>
+
         <service android:name=".LoadAverageService"
                 android:exported="true" />
 
@@ -244,7 +254,7 @@
                   android:stateNotNeeded="true"
                   android:resumeWhilePausing="true"
                   android:screenOrientation="behind"
-                  android:theme="@style/RecentsTheme.Wallpaper">
+                  android:theme="@style/RecentsTvTheme.Wallpaper">
             <intent-filter>
                 <action android:name="com.android.systemui.recents.TOGGLE_RECENTS" />
             </intent-filter>
diff --git a/packages/SystemUI/res/color/notification_guts_buttons.xml b/packages/SystemUI/res/color/notification_guts_buttons.xml
new file mode 100644
index 0000000..f7a4ee9
--- /dev/null
+++ b/packages/SystemUI/res/color/notification_guts_buttons.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:state_checked="true"
+          android:color="@*android:color/material_deep_teal_500" />
+    <item android:color="@android:color/black"
+          android:alpha=".87" />
+</selector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/ic_info.xml b/packages/SystemUI/res/drawable/ic_info.xml
deleted file mode 100644
index 65e7bf5..0000000
--- a/packages/SystemUI/res/drawable/ic_info.xml
+++ /dev/null
@@ -1,24 +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.
--->
-<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="M12.000000,2.000000C6.500000,2.000000 2.000000,6.500000 2.000000,12.000000s4.500000,10.000000 10.000000,10.000000c5.500000,0.000000 10.000000,-4.500000 10.000000,-10.000000S17.500000,2.000000 12.000000,2.000000zM13.000000,17.000000l-2.000000,0.000000l0.000000,-6.000000l2.000000,0.000000L13.000000,17.000000zM13.000000,9.000000l-2.000000,0.000000L11.000000,7.000000l2.000000,0.000000L13.000000,9.000000z"
-        android:fillColor="#FFFFFF"/>
-</vector>
diff --git a/packages/SystemUI/res/drawable/qs_btn_borderless_rect.xml b/packages/SystemUI/res/drawable/qs_btn_borderless_rect.xml
new file mode 100644
index 0000000..03bfd1a
--- /dev/null
+++ b/packages/SystemUI/res/drawable/qs_btn_borderless_rect.xml
@@ -0,0 +1,32 @@
+<!--
+     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.
+-->
+<inset
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:insetTop="4dp"
+    android:insetBottom="4dp">
+    <ripple
+        android:color="?android:attr/colorControlHighlight" >
+
+        <item android:id="@android:id/mask">
+            <shape>
+                <corners android:radius="@dimen/borderless_button_radius" />
+
+                <solid android:color="@android:color/white" />
+            </shape>
+        </item>
+
+    </ripple>
+</inset>
diff --git a/packages/SystemUI/res/drawable/qs_customizer_background.xml b/packages/SystemUI/res/drawable/qs_customizer_background.xml
index 6bb27cc..d90f820 100644
--- a/packages/SystemUI/res/drawable/qs_customizer_background.xml
+++ b/packages/SystemUI/res/drawable/qs_customizer_background.xml
@@ -15,5 +15,5 @@
 -->
 <transition xmlns:android="http://schemas.android.com/apk/res/android">
     <item android:drawable="@color/qs_detail_transition" />
-    <item android:drawable="?android:attr/windowBackground" />
+    <item android:drawable="@color/system_primary_color" />
 </transition>
diff --git a/packages/SystemUI/res/drawable/qs_background_secondary.xml b/packages/SystemUI/res/drawable/recents_tv_background_gradient.xml
similarity index 75%
rename from packages/SystemUI/res/drawable/qs_background_secondary.xml
rename to packages/SystemUI/res/drawable/recents_tv_background_gradient.xml
index 31c0162..e98d43f 100644
--- a/packages/SystemUI/res/drawable/qs_background_secondary.xml
+++ b/packages/SystemUI/res/drawable/recents_tv_background_gradient.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2014 The Android Open Source Project
+<!-- Copyright (C) 2016 The Android Open Source Project
 
      Licensed under the Apache License, Version 2.0 (the "License");
      you may not use this file except in compliance with the License.
@@ -13,9 +13,10 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-<shape xmlns:android="http://schemas.android.com/apk/res/android">
-    <solid android:color="@color/system_secondary_color" />
-    <corners
-        android:topLeftRadius="0dp"
-        android:topRightRadius="0dp" />
-</shape>
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+       android:shape="rectangle">
+    <gradient
+            android:startColor="#99000000"
+            android:endColor="#E6000000"
+            android:angle="90"/>
+</shape>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/qs_background_secondary.xml b/packages/SystemUI/res/drawable/tv_pip_overlay_background.xml
similarity index 72%
copy from packages/SystemUI/res/drawable/qs_background_secondary.xml
copy to packages/SystemUI/res/drawable/tv_pip_overlay_background.xml
index 31c0162..e247dec 100644
--- a/packages/SystemUI/res/drawable/qs_background_secondary.xml
+++ b/packages/SystemUI/res/drawable/tv_pip_overlay_background.xml
@@ -1,5 +1,5 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2014 The Android Open Source Project
+<!--
+     Copyright (C) 2016 The Android Open Source Project
 
      Licensed under the Apache License, Version 2.0 (the "License");
      you may not use this file except in compliance with the License.
@@ -13,9 +13,11 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-<shape xmlns:android="http://schemas.android.com/apk/res/android">
-    <solid android:color="@color/system_secondary_color" />
-    <corners
-        android:topLeftRadius="0dp"
-        android:topRightRadius="0dp" />
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+    android:shape="rectangle">
+
+    <gradient
+        android:startColor="#B2000000"
+        android:endColor="#00000000"
+        android:angle="90"/>
 </shape>
diff --git a/packages/SystemUI/res/drawable/tv_pip_play_button.xml b/packages/SystemUI/res/drawable/tv_pip_play_button.xml
new file mode 100644
index 0000000..fecdc09
--- /dev/null
+++ b/packages/SystemUI/res/drawable/tv_pip_play_button.xml
@@ -0,0 +1,26 @@
+<?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.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:constantSize="true">
+    <item android:state_focused="true">
+        <layer-list>
+            <item android:drawable="@drawable/tv_pip_button_focused" />
+            <item android:drawable="@drawable/ic_play_arrow_white_24dp" />
+        </layer-list>
+    </item>
+    <item android:drawable="@drawable/ic_play_arrow_white_24dp" />
+</selector>
diff --git a/packages/SystemUI/res/layout/battery_detail.xml b/packages/SystemUI/res/layout/battery_detail.xml
index 99121a9..af3e379 100644
--- a/packages/SystemUI/res/layout/battery_detail.xml
+++ b/packages/SystemUI/res/layout/battery_detail.xml
@@ -33,7 +33,7 @@
     <com.android.settingslib.graph.UsageView
         android:id="@+id/battery_usage"
         android:layout_width="match_parent"
-        android:layout_height="wrap_content"
+        android:layout_height="141dp"
         android:layout_marginStart="16dp"
         android:layout_marginEnd="24dp"
         systemui:sideLabels="@array/battery_labels"
diff --git a/packages/SystemUI/res/layout/global_screenshot.xml b/packages/SystemUI/res/layout/global_screenshot.xml
index 8b337ea..c1fe1a8 100644
--- a/packages/SystemUI/res/layout/global_screenshot.xml
+++ b/packages/SystemUI/res/layout/global_screenshot.xml
@@ -33,4 +33,10 @@
         android:layout_height="match_parent"
         android:src="@android:color/white"
         android:visibility="gone" />
+    <com.android.systemui.screenshot.ScreenshotSelectorView
+        android:id="@+id/global_screenshot_selector"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:visibility="gone"
+        android:pointerShape="crosshair"/>
 </FrameLayout>
diff --git a/packages/SystemUI/res/layout/notification_guts.xml b/packages/SystemUI/res/layout/notification_guts.xml
index 4d0eb96..1ab6bf9 100644
--- a/packages/SystemUI/res/layout/notification_guts.xml
+++ b/packages/SystemUI/res/layout/notification_guts.xml
@@ -26,7 +26,7 @@
         android:orientation="vertical"
         android:paddingStart="@*android:dimen/notification_content_margin_start"
         android:paddingEnd="8dp"
-        android:background="@color/notification_guts_bg_color" >
+        android:background="@color/notification_guts_bg_color">
 
     <!-- header -->
     <LinearLayout
@@ -39,7 +39,7 @@
             android:layout_gravity="center_vertical|start">
 
         <ImageView
-                android:id="@android:id/icon"
+                android:id="@+id/app_icon"
                 android:layout_width="18dp"
                 android:layout_height="18dp"
                 android:layout_marginEnd="6dp"
@@ -58,8 +58,41 @@
                 android:layout_gravity="bottom|start"
                 android:visibility="gone" />
     </LinearLayout>
+    <!-- Importance radio buttons -->
+    <RadioGroup
+            android:id="@+id/importance_buttons"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:paddingTop="4dp"
+            android:paddingBottom="16dip"
+            android:paddingEnd="8dp" >
+        <RadioButton
+                android:id="@+id/silent_importance"
+                android:layout_width="wrap_content"
+                android:layout_height="48dp"
+                android:paddingStart="32dp"
+                android:text="@string/show_silently"
+                style="@style/TextAppearance.NotificationGuts.Radio"
+                android:buttonTint="@color/notification_guts_buttons" />
+        <RadioButton
+                android:id="@+id/block_importance"
+                android:layout_width="wrap_content"
+                android:layout_height="48dp"
+                android:paddingStart="32dp"
+                android:text="@string/block"
+                style="@style/TextAppearance.NotificationGuts.Radio"
+                android:buttonTint="@color/notification_guts_buttons" />
+        <RadioButton
+                android:id="@+id/reset_importance"
+                android:layout_width="wrap_content"
+                android:layout_height="48dp"
+                android:paddingStart="32dp"
+                style="@style/TextAppearance.NotificationGuts.Radio"
+                android:buttonTint="@color/notification_guts_buttons" />
+    </RadioGroup>
     <!-- Importance slider -->
     <LinearLayout
+            android:id="@+id/importance_slider"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
             android:gravity="center_vertical"
@@ -67,7 +100,8 @@
             android:clickable="false"
             android:focusable="false"
             android:paddingBottom="8dip"
-            android:paddingEnd="8dp" >
+            android:paddingEnd="8dp"
+            android:visibility="gone">
         <TextView
                 android:id="@+id/title"
                 android:layout_width="match_parent"
diff --git a/packages/SystemUI/res/layout/notification_settings_icon_row.xml b/packages/SystemUI/res/layout/notification_settings_icon_row.xml
index 52d07fc..f47083a 100644
--- a/packages/SystemUI/res/layout/notification_settings_icon_row.xml
+++ b/packages/SystemUI/res/layout/notification_settings_icon_row.xml
@@ -19,6 +19,7 @@
     xmlns:systemui="http://schemas.android.com/apk/res-auto"
     android:layout_width="wrap_content"
     android:layout_height="wrap_content"
+    android:visibility="invisible"
     >
 
     <com.android.systemui.statusbar.AlphaOptimizedImageView
@@ -31,7 +32,6 @@
         android:paddingBottom="@dimen/notification_gear_padding"
         android:src="@drawable/ic_settings"
         android:tint="@color/notification_gear_color"
-        android:visibility="invisible"
         android:alpha="0"
         android:background="?android:attr/selectableItemBackgroundBorderless"
         />
diff --git a/packages/SystemUI/res/layout/qs_customize_panel.xml b/packages/SystemUI/res/layout/qs_customize_panel.xml
index 458ce2d..7af247e 100644
--- a/packages/SystemUI/res/layout/qs_customize_panel.xml
+++ b/packages/SystemUI/res/layout/qs_customize_panel.xml
@@ -14,32 +14,14 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
+
+<!-- Height is 0 because it will be managed by the QSContainer manually -->
 <com.android.systemui.qs.customize.QSCustomizer
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
-    android:layout_height="match_parent"
+    android:layout_height="0dp"
     android:orientation="vertical"
     android:background="@drawable/qs_customizer_background"
     android:gravity="center_horizontal">
 
-    <Toolbar
-        android:id="@*android:id/action_bar"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:layout_marginTop="28dp"
-        android:navigationContentDescription="@*android:string/action_bar_up_description"
-        style="?android:attr/toolbarStyle" />
-
-    <android.support.v7.widget.RecyclerView
-        android:id="@android:id/list"
-        android:layout_width="@dimen/notification_panel_width"
-        android:layout_height="0dp"
-        android:layout_weight="1" />
-
-    <View
-        android:layout_width="match_parent"
-        android:layout_height="@dimen/navigation_bar_size"
-        android:layout_gravity="bottom"
-        android:background="#ff000000" />
-
 </com.android.systemui.qs.customize.QSCustomizer>
diff --git a/packages/SystemUI/res/layout/qs_customize_panel_content.xml b/packages/SystemUI/res/layout/qs_customize_panel_content.xml
new file mode 100644
index 0000000..75f8fa4
--- /dev/null
+++ b/packages/SystemUI/res/layout/qs_customize_panel_content.xml
@@ -0,0 +1,41 @@
+<?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.
+-->
+
+<merge xmlns:android="http://schemas.android.com/apk/res/android">
+
+    <Toolbar
+        android:id="@*android:id/action_bar"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_marginTop="28dp"
+        android:navigationContentDescription="@*android:string/action_bar_up_description"
+        style="?android:attr/toolbarStyle" />
+
+    <android.support.v7.widget.RecyclerView
+        android:id="@android:id/list"
+        android:layout_width="@dimen/notification_panel_width"
+        android:layout_height="0dp"
+        android:layout_weight="1"
+        android:scrollIndicators="top"
+        android:scrollbars="vertical" />
+
+    <View
+        android:layout_width="match_parent"
+        android:layout_height="@dimen/navigation_bar_size"
+        android:layout_gravity="bottom"
+        android:background="#ff000000" />
+</merge>
diff --git a/packages/SystemUI/res/layout/qs_panel.xml b/packages/SystemUI/res/layout/qs_panel.xml
index 994d3c9..ef15195 100644
--- a/packages/SystemUI/res/layout/qs_panel.xml
+++ b/packages/SystemUI/res/layout/qs_panel.xml
@@ -34,4 +34,7 @@
 
     <include android:id="@+id/qs_detail" layout="@layout/qs_detail" />
 
+    <include android:id="@+id/qs_customize" layout="@layout/qs_customize_panel"
+        android:visibility="gone" />
+
 </com.android.systemui.qs.QSContainer>
diff --git a/packages/SystemUI/res/layout/qs_tile_label.xml b/packages/SystemUI/res/layout/qs_tile_label.xml
index 603ebbf..b0dca9a 100644
--- a/packages/SystemUI/res/layout/qs_tile_label.xml
+++ b/packages/SystemUI/res/layout/qs_tile_label.xml
@@ -20,22 +20,22 @@
         android:layout_height="wrap_content"
         android:orientation="horizontal">
      <TextView android:id="@+id/tile_label"
-             android:layout_width="wrap_content"
-             android:layout_height="wrap_content"
-             android:textColor="@color/qs_tile_text"
-             android:gravity="center_horizontal"
-             android:minLines="2"
-             android:padding="0dp"
-             android:fontFamily="sans-serif-condensed"
-             android:textStyle="normal"
-             android:textSize="@dimen/qs_tile_text_size"
-             android:clickable="false" />
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:textColor="@color/qs_tile_text"
+            android:gravity="center_horizontal"
+            android:minLines="2"
+            android:padding="0dp"
+            android:fontFamily="sans-serif-condensed"
+            android:textStyle="normal"
+            android:textSize="@dimen/qs_tile_text_size"
+            android:clickable="false" />
      <ImageView android:id="@+id/restricted_padlock"
-             android:layout_width="@dimen/qs_tile_text_size"
-             android:layout_height="@dimen/qs_tile_text_size"
-             android:src="@drawable/ic_settings_lock_outline"
-             android:layout_marginLeft="@dimen/restricted_padlock_pading"
-             android:baselineAlignBottom="true"
-             android:scaleType="centerInside"
-             android:visibility="gone" />
+            android:layout_width="@dimen/qs_tile_text_size"
+            android:layout_height="match_parent"
+            android:paddingBottom="@dimen/qs_tile_text_size"
+            android:src="@drawable/ic_info"
+            android:layout_marginLeft="@dimen/restricted_padlock_pading"
+            android:scaleType="centerInside"
+            android:visibility="gone" />
 </LinearLayout>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/qs_user_detail_item.xml b/packages/SystemUI/res/layout/qs_user_detail_item.xml
index a22c360..661d74a 100644
--- a/packages/SystemUI/res/layout/qs_user_detail_item.xml
+++ b/packages/SystemUI/res/layout/qs_user_detail_item.xml
@@ -53,10 +53,10 @@
         <ImageView
                 android:id="@+id/restricted_padlock"
                 android:layout_width="@dimen/qs_detail_item_secondary_text_size"
-                android:layout_height="@dimen/qs_detail_item_secondary_text_size"
-                android:src="@drawable/ic_settings_lock_outline"
+                android:layout_height="match_parent"
+                android:gravity="center_vertical"
+                android:src="@drawable/ic_info"
                 android:layout_marginLeft="@dimen/restricted_padlock_pading"
-                android:baselineAlignBottom="true"
                 android:scaleType="centerInside"
                 android:visibility="gone" />
     </LinearLayout>
diff --git a/packages/SystemUI/res/layout/recents_on_tv.xml b/packages/SystemUI/res/layout/recents_on_tv.xml
index 94b099e..3a7c1d1 100644
--- a/packages/SystemUI/res/layout/recents_on_tv.xml
+++ b/packages/SystemUI/res/layout/recents_on_tv.xml
@@ -18,9 +18,10 @@
     android:id="@+id/recents_view"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
+    android:background="@drawable/recents_tv_background_gradient"
     android:clipChildren="false"
-    android:clipToPadding="false" >
-
+    android:clipToPadding="false"
+    android:layoutDirection="rtl">
     <com.android.systemui.recents.tv.views.TaskStackHorizontalGridView
         android:id="@+id/task_list"
         android:layout_width="wrap_content"
diff --git a/packages/SystemUI/res/layout/recents_task_card_view.xml b/packages/SystemUI/res/layout/recents_tv_task_card_view.xml
similarity index 65%
rename from packages/SystemUI/res/layout/recents_task_card_view.xml
rename to packages/SystemUI/res/layout/recents_tv_task_card_view.xml
index fa1daad..c5b1a7a 100644
--- a/packages/SystemUI/res/layout/recents_task_card_view.xml
+++ b/packages/SystemUI/res/layout/recents_tv_task_card_view.xml
@@ -20,28 +20,28 @@
     android:focusable="true"
     android:focusableInTouchMode="true"
     android:layout_gravity="center"
-    android:layout_centerInParent="true">
+    android:layout_centerInParent="true"
+    android:layoutDirection="ltr">
 
-    <RelativeLayout
+    <LinearLayout
             android:layout_width="@dimen/recents_tv_card_width"
             android:layout_height="wrap_content"
             android:layout_centerInParent="true"
-            android:layout_gravity="center">
-        <ImageView
-                android:id="@+id/card_view_thumbnail"
-                android:layout_width="match_parent"
-                android:layout_height="@dimen/recents_tv_card_height"
-                android:scaleType="centerCrop"
-                android:gravity="center"
-                android:layout_alignParentTop="true"
-                android:layout_centerHorizontal="true"/>
-
-        <RelativeLayout
+            android:layout_gravity="center"
+            android:orientation="vertical" >
+        <LinearLayout
                 android:id="@+id/card_info_field"
                 android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:layout_below="@id/card_view_thumbnail"
-                android:background="@color/recents_tv_card_background_color" >
+                android:layout_height="wrap_content">
+            <ImageView
+                    android:id="@+id/card_extra_badge"
+                    android:layout_width="@dimen/recents_tv_card_extra_badge_size"
+                    android:layout_height="@dimen/recents_tv_card_extra_badge_size"
+                    android:layout_marginBottom="@dimen/recents_tv_icon_padding_bottom"
+                    android:layout_marginEnd="@dimen/recents_tv_icon_padding_end"
+                    android:scaleType="fitCenter"
+                    android:layout_centerVertical="true"
+                    android:layout_alignParentRight="true" />
             <TextView
                     android:id="@+id/card_title_text"
                     android:layout_width="match_parent"
@@ -49,29 +49,21 @@
                     android:layout_alignParentTop="false"
                     android:includeFontPadding="true"
                     android:minLines="1"
-                    android:maxLines="2"
+                    android:maxLines="1"
                     android:textColor="@color/recents_tv_card_title_text_color"
-                    android:ellipsize="end" />
-            <TextView
-                    android:id="@+id/card_content_text"
-                    android:layout_width="match_parent"
-                    android:layout_height="wrap_content"
-                    android:layout_alignParentStart="true"
-                    android:layout_below="@id/card_title_text"
-                    android:includeFontPadding="true"
-                    android:minLines="1"
-                    android:maxLines="2"
-                    android:textColor="@color/recents_tv_card_content_text_color"
-                    android:ellipsize="end" />
-            <ImageView
-                    android:id="@+id/card_extra_badge"
-                    android:layout_width="@dimen/recents_tv_card_extra_badge_size"
-                    android:layout_height="@dimen/recents_tv_card_extra_badge_size"
-                    android:scaleType="fitCenter"
-                    android:background="@android:color/transparent"
-                    android:contentDescription="@null"
-                    android:layout_centerVertical="true"
-                    android:layout_alignParentRight="true"/>
-        </RelativeLayout>
-    </RelativeLayout>
+                    android:fontFamily="@string/font_roboto_regular"
+                    android:textSize="@dimen/recents_tv_title_text_size"
+                    android:layout_marginBottom="@dimen/recents_tv_text_padding_bottom"
+                    android:ellipsize="end"/>
+        </LinearLayout>
+        <ImageView
+                android:id="@+id/card_view_thumbnail"
+                android:layout_width="match_parent"
+                android:layout_height="@dimen/recents_tv_card_height"
+                android:scaleType="centerCrop"
+                android:gravity="center"
+                android:layout_alignParentTop="true"
+                android:layout_centerHorizontal="true"
+                android:layout_below="@id/card_title_text" />
+    </LinearLayout>
 </com.android.systemui.recents.tv.views.TaskCardView>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/remote_input.xml b/packages/SystemUI/res/layout/remote_input.xml
index 818df3b..75195c4 100644
--- a/packages/SystemUI/res/layout/remote_input.xml
+++ b/packages/SystemUI/res/layout/remote_input.xml
@@ -43,7 +43,7 @@
             android:singleLine="true"
             android:ellipsize="start"
             android:inputType="textShortMessage|textAutoCorrect|textCapSentences"
-            android:imeOptions="actionSend" />
+            android:imeOptions="actionSend|flagNoExtractUi" />
 
     <FrameLayout
             android:layout_width="wrap_content"
diff --git a/packages/SystemUI/res/layout/status_bar_expanded.xml b/packages/SystemUI/res/layout/status_bar_expanded.xml
index 289b1d9..ccefb5f 100644
--- a/packages/SystemUI/res/layout/status_bar_expanded.xml
+++ b/packages/SystemUI/res/layout/status_bar_expanded.xml
@@ -39,11 +39,14 @@
         android:clipToPadding="false"
         android:clipChildren="false">
 
-        <include
-            layout="@layout/qs_panel"
+        <com.android.systemui.DensityContainer
+            android:id="@+id/qs_density_container"
+            android:layout="@layout/qs_panel"
             android:layout_width="@dimen/notification_panel_width"
-            android:layout_height="wrap_content"
-            android:layout_gravity="@integer/notification_panel_layout_gravity" />
+            android:layout_height="match_parent"
+            android:layout_gravity="@integer/notification_panel_layout_gravity"
+            android:clipToPadding="false"
+            android:clipChildren="false" />
 
         <com.android.systemui.statusbar.stack.NotificationStackScrollLayout
             android:id="@+id/notification_stack_scroller"
diff --git a/packages/SystemUI/res/layout/tv_pip_menu.xml b/packages/SystemUI/res/layout/tv_pip_menu.xml
index 0b98d0e..1fec49e 100644
--- a/packages/SystemUI/res/layout/tv_pip_menu.xml
+++ b/packages/SystemUI/res/layout/tv_pip_menu.xml
@@ -34,7 +34,7 @@
         android:gravity="center"
         android:clipChildren="false">
 
-        <ImageView android:id="@+id/full"
+        <ImageView android:id="@+id/full_button"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:focusable="true"
@@ -53,17 +53,16 @@
             android:clipChildren="false" />
     </LinearLayout>
 
-    <LinearLayout
+    <LinearLayout android:id="@+id/play_pause"
         android:layout_width="34dp"
         android:layout_height="wrap_content"
         android:layout_marginStart="3dp"
         android:layout_marginEnd="3dp"
         android:orientation="vertical"
         android:gravity="center"
-        android:visibility="gone"
         android:clipChildren="false">
 
-        <ImageView android:id="@+id/play_pause"
+        <ImageView android:id="@+id/play_pause_button"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:focusable="true"
@@ -90,7 +89,7 @@
         android:gravity="center"
         android:clipChildren="false">
 
-        <ImageView android:id="@+id/close"
+        <ImageView android:id="@+id/close_button"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:focusable="true"
diff --git a/packages/SystemUI/res/layout/tv_pip_overlay.xml b/packages/SystemUI/res/layout/tv_pip_overlay.xml
index ebd362c..40c6fa1 100644
--- a/packages/SystemUI/res/layout/tv_pip_overlay.xml
+++ b/packages/SystemUI/res/layout/tv_pip_overlay.xml
@@ -24,12 +24,13 @@
     <TextView
         android:id="@+id/guide_overlay"
         android:layout_width="match_parent"
-        android:layout_height="wrap_content"
+        android:layout_height="32dp"
         android:layout_alignParentBottom="true"
-        android:padding="3dp"
-        android:textSize="13sp"
-        android:textColor="#111111"
-        android:background="#99EEEEEE"
+        android:textSize="14sp"
+        android:textColor="#EEEEEE"
+        android:fontFamily="sans-serif"
+        android:background="@drawable/tv_pip_overlay_background"
+        android:gravity="center"
         android:text="@string/pip_hold_home" />
     <LinearLayout
         android:id="@+id/guide_buttons"
diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml
index 5b8ebf4..70247ee 100644
--- a/packages/SystemUI/res/values-af/strings.xml
+++ b/packages/SystemUI/res/values-af/strings.xml
@@ -73,7 +73,8 @@
     <string name="screenshot_saved_title" msgid="6461865960961414961">"Skermkiekie geneem."</string>
     <string name="screenshot_saved_text" msgid="1152839647677558815">"Raak om jou skermkiekie te sien."</string>
     <string name="screenshot_failed_title" msgid="705781116746922771">"Kon nie skermkiekie neem nie."</string>
-    <string name="screenshot_failed_text" msgid="1260203058661337274">"Kan nie skermkiekie neem nie oor beperkte bergingspasie of die program of organisasie verbied dit."</string>
+    <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Kan weens beperkte bergingspasie nie skermkiekie stoor nie."</string>
+    <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Die program of jou organisasie laat nie toe dat skermkiekies geneem word nie."</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"USB-lêeroordrag-opsies"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Heg as \'n mediaspeler (MTP)"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"Heg as \'n kamera (PTP)"</string>
@@ -206,6 +207,7 @@
     <string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"Meer tyd."</string>
     <string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"Minder tyd."</string>
     <string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"Flitslig af."</string>
+    <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"Flitslig is nie beskikbaar nie."</string>
     <string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"Flitslig aan."</string>
     <string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"Flitslig afgeskakel."</string>
     <string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"Flitslig aangeskakel."</string>
@@ -218,6 +220,10 @@
     <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"Werkmodus is aan."</string>
     <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"Werkmodus is afgeskakel."</string>
     <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"Werkmodus is aangeskakel."</string>
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_off (650231949881093289) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_on (4218725402373934151) -->
+    <skip />
     <string name="accessibility_brightness" msgid="8003681285547803095">"Skermhelderheid"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"2G-3G-data is laat wag"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"4G-data is laat wag"</string>
@@ -304,6 +310,8 @@
     <string name="recents_launch_disabled_message" msgid="1624523193008871793">"<xliff:g id="APP">%s</xliff:g> is in veiligmodus gedeaktiveer."</string>
     <string name="recents_history_button_label" msgid="5153358867807604821">"Geskiedenis"</string>
     <string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"Vee uit"</string>
+    <string name="recents_drag_non_dockable_task_message" msgid="2935843902795166158">"Hierdie program steun nie veelvuldige vensters nie"</string>
+    <string name="recents_launch_non_dockable_task_label" msgid="7862379814938391888">"Program steun nie veelvuldige vensters nie"</string>
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Verdeel horisontaal"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Verdeel vertikaal"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Verdeel gepasmaak"</string>
@@ -451,18 +459,23 @@
     <string name="enable_bluetooth_title" msgid="5027037706500635269">"Skakel Bluetooth aan?"</string>
     <string name="enable_bluetooth_message" msgid="9106595990708985385">"Jy moet Bluetooth aanskakel om jou sleutelbord aan jou tablet te koppel."</string>
     <string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"Skakel aan"</string>
-    <string name="apply_to_topic" msgid="3641403489318659666">"Pas toe op <xliff:g id="TOPIC_NAME">%1$s</xliff:g>-kennisgewings"</string>
-    <string name="apply_to_app" msgid="363016783939815960">"Pas toe op alle kennisgewings van hierdie program af"</string>
+    <string name="show_silently" msgid="6841966539811264192">"Wys kennisgewings sonder klank"</string>
+    <string name="block" msgid="2734508760962682611">"Blokkeer alle kennisgewings"</string>
+    <string name="do_not_silence" msgid="6878060322594892441">"Moenie stilmaak nie"</string>
+    <string name="do_not_silence_block" msgid="4070647971382232311">"Moenie stilmaak of blokkeer nie"</string>
+    <string name="tuner_full_importance_settings" msgid="8103289238676424226">"Wys volledige belangrikheidinstellings"</string>
     <string name="blocked_importance" msgid="5198578988978234161">"Geblokkeer"</string>
+    <string name="min_importance" msgid="1901894910809414782">"Onbelangrik"</string>
     <string name="low_importance" msgid="4109929986107147930">"Min belang"</string>
     <string name="default_importance" msgid="8192107689995742653">"Normale belang"</string>
     <string name="high_importance" msgid="1527066195614050263">"Groot belang"</string>
     <string name="max_importance" msgid="5089005872719563894">"Dringende belang"</string>
     <string name="notification_importance_blocked" msgid="2397192642657872872">"Moet nooit hierdie kennisgewings wys nie"</string>
-    <string name="notification_importance_low" msgid="4383563267370859725">"Wys onderaan die kennisgewinglys sonder \'n geluid"</string>
-    <string name="notification_importance_default" msgid="4926529615920610817">"Wys hierdie kennisgewings sonder geluide"</string>
-    <string name="notification_importance_high" msgid="3222680136612408223">"Wys boaan die kennisgewinglys en maak \'n geluid"</string>
-    <string name="notification_importance_max" msgid="5236987171904756134">"Verskyn vlugtig op die skerm en maak \'n geluid"</string>
+    <string name="notification_importance_min" msgid="1938190340516905748">"Wys sonder klank aan die onderkant van die kennisgewinglys"</string>
+    <string name="notification_importance_low" msgid="3657252049508213048">"Wys hierdie kennisgewings sonder klank"</string>
+    <string name="notification_importance_default" msgid="4466466472622442175">"Laat hierdie kennisgewing toe om geluide te maak"</string>
+    <string name="notification_importance_high" msgid="2135428926525093825">"Verskyn vlugtig op die skerm en laat klank toe"</string>
+    <string name="notification_importance_max" msgid="5806278962376556491">"Wys boaan die kennisgewingslys, verskyn vlugtig op die skerm en laat klank toe"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"Meer instellings"</string>
     <string name="notification_done" msgid="5279426047273930175">"Klaar"</string>
     <string name="color_and_appearance" msgid="1254323855964993144">"Kleur en voorkoms"</string>
@@ -476,7 +489,7 @@
     <string name="use_dark_theme" msgid="2900938704964299312">"Gebruik donkertema vir Android-bedryfstelsel"</string>
     <string name="adjust_tint" msgid="3398569573231409878">"Verstel tint"</string>
     <string name="adjust_brightness" msgid="980039329808178246">"Verstel helderheid"</string>
-    <string name="night_mode_disclaimer" msgid="3297928749219711334">"Die donkertema word toegepas op kernareas van Android-bedryfstelsel wat gewoonlik in \'n ligtema gewys word, soos instellings en kennisgewings."</string>
+    <string name="night_mode_disclaimer" msgid="598914896926759578">"Die donkertema word toegepas op kernareas van Android-bedryfstelsel wat gewoonlik in \'n ligtema gewys word, soos instellings."</string>
     <string name="color_apply" msgid="9212602012641034283">"Pas toe"</string>
     <string name="color_revert_title" msgid="4746666545480534663">"Bevestig instellings"</string>
     <string name="color_revert_message" msgid="9116001069397996691">"Sommige kleurinstellings kan hierdie toestel onbruikbaar maak. Klik OK om hierdie kleurinstellings te bevestig; andersins sal hierdie instellings ná 10 sekondes teruggestel word."</string>
@@ -535,4 +548,10 @@
     <item msgid="2139628951880142927">"Wys persentasie wanneer gelaai word (verstek)"</item>
     <item msgid="3327323682209964956">"Moenie hierdie ikoon wys nie"</item>
   </string-array>
+    <string name="other" msgid="4060683095962566764">"Ander"</string>
+    <string name="accessibility_divider" msgid="5903423481953635044">"Skermverdeler"</string>
+    <string name="accessibility_action_divider_move_down" msgid="704893304141890042">"Skuif af"</string>
+    <string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"Skuif op"</string>
+    <string name="accessibility_action_divider_move_left" msgid="9218189832115847253">"Skuif links"</string>
+    <string name="accessibility_action_divider_move_right" msgid="4671522715182567972">"Skuif regs"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-af/strings_tv.xml b/packages/SystemUI/res/values-af/strings_tv.xml
new file mode 100644
index 0000000..adc1306
--- /dev/null
+++ b/packages/SystemUI/res/values-af/strings_tv.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.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="pip_close" msgid="3480680679023423574">"Maak PIP toe"</string>
+    <string name="pip_fullscreen" msgid="8604643018538487816">"Volskerm"</string>
+    <string name="pip_play" msgid="674145557658227044">"Speel"</string>
+    <string name="pip_pause" msgid="8412075640017218862">"Laat wag"</string>
+    <string name="pip_hold_home" msgid="340086535668778109">"Hou "<b>"TUIS"</b>" om PIP te beheer"</string>
+    <string name="pip_onboarding_description" msgid="2627737116380318292">"Druk en hou die TUIS-\nknoppie om PIP te beheer"</string>
+    <string name="pip_onboarding_button" msgid="3957426748484904611">"Het dit"</string>
+</resources>
diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml
index f33d270..226d7f5 100644
--- a/packages/SystemUI/res/values-am/strings.xml
+++ b/packages/SystemUI/res/values-am/strings.xml
@@ -73,7 +73,8 @@
     <string name="screenshot_saved_title" msgid="6461865960961414961">"ቅጽበታዊ ገጽ እይታ ተቀርጿል"</string>
     <string name="screenshot_saved_text" msgid="1152839647677558815">"የእርስዎን ቅጽበታዊ ገጽ እይታ ለማየት ይንኩ"</string>
     <string name="screenshot_failed_title" msgid="705781116746922771">"ቅጽበታዊ ገጽ እይታ መቅረጽ አልተቻለም::"</string>
-    <string name="screenshot_failed_text" msgid="1260203058661337274">"በተገደበ የማከማቻ ቦታ ምክንያት ወይም በመተግበሪያው ወይም በድርጅትዎ ስለማይፈቀድ የማያ ገጽ ቅጽበታዊ እይታዎችን ማንሳት አይቻልም።"</string>
+    <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"ባለው የተገደበ የማከማቻ ቦታ ምክንያት ቅጽበታዊ ገጽ ዕይታን ማስቀመጥ አይችልም።"</string>
+    <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"ቅጽበታዊ ገጽ እይታዎችን ማንሳት በመተግበሪያው ወይም በእርስዎ ድርጅት አይፈቀድም።"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"የUSB ፋይል ሰደዳ አማራጮች"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"እንደ ማህደረ አጫዋች (MTP) ሰካ"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"እንደ ካሜራ (PTP) ሰካ"</string>
@@ -206,6 +207,7 @@
     <string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"ተጨማሪ ጊዜ።"</string>
     <string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"ያነሰ ጊዜ።"</string>
     <string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"የባትሪ ብርሃን ጠፍቷል።"</string>
+    <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"የባትሪ ብርሃን አይገኝም።"</string>
     <string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"የባትሪ ብርሃን በርቷል።"</string>
     <string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"የባትሪ ብርሃን ጠፍቷል።"</string>
     <string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"የባትሪ ብርሃን በርቷል።"</string>
@@ -218,6 +220,10 @@
     <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"የሥራ ሁነታ በርቷል።"</string>
     <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"የሥራ ሁነታ ጠፍቷል።"</string>
     <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"የሥራ ሁነታ በርቷል።"</string>
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_off (650231949881093289) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_on (4218725402373934151) -->
+    <skip />
     <string name="accessibility_brightness" msgid="8003681285547803095">"ብሩህነት ያሳዩ"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"2ጂ-3ጂ ውሂብ ላፍታ ቆሟል"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"4ጂ ውሂብ ላፍታ ቆሟል"</string>
@@ -304,6 +310,8 @@
     <string name="recents_launch_disabled_message" msgid="1624523193008871793">"<xliff:g id="APP">%s</xliff:g> በጥንቃቄ ሁነታ ውስጥ ታግዷል።"</string>
     <string name="recents_history_button_label" msgid="5153358867807604821">"ታሪክ"</string>
     <string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"ጥረግ"</string>
+    <string name="recents_drag_non_dockable_task_message" msgid="2935843902795166158">"ይህ መተግበሪያ ብዝሃ-መስኮትን አይደግፍም"</string>
+    <string name="recents_launch_non_dockable_task_label" msgid="7862379814938391888">"መተግበሪያው ብዝሃ-መስኮትን አይደግፍም"</string>
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"አግድም ክፈል"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"ቁልቁል ክፈል"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"በብጁ ክፈል"</string>
@@ -451,18 +459,23 @@
     <string name="enable_bluetooth_title" msgid="5027037706500635269">"ብሉቱዝ ይብራ?"</string>
     <string name="enable_bluetooth_message" msgid="9106595990708985385">"የቁልፍ ሰሌዳዎን ከእርስዎ ጡባዊ ጋር ለማገናኘት በመጀመሪያ ብሉቱዝን ማብራት አለብዎት።"</string>
     <string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"አብራ"</string>
-    <string name="apply_to_topic" msgid="3641403489318659666">"በ<xliff:g id="TOPIC_NAME">%1$s</xliff:g> ማሳወቂያዎች ላይ ተግብር"</string>
-    <string name="apply_to_app" msgid="363016783939815960">"ከዚህ መተግበሪያ በሚመጡ ሁሉም ማሳወቂያዎች ላይ ተግብር"</string>
+    <string name="show_silently" msgid="6841966539811264192">"ማሳወቂያዎችን በጸጥታ አሳይ"</string>
+    <string name="block" msgid="2734508760962682611">"ሁሉንም ማሳወቂያዎች አግድ"</string>
+    <string name="do_not_silence" msgid="6878060322594892441">"ድምፅ አትዝጋ"</string>
+    <string name="do_not_silence_block" msgid="4070647971382232311">"ድምፅ አትዝጋ ወይም አታግድ"</string>
+    <string name="tuner_full_importance_settings" msgid="8103289238676424226">"ሙሉ የአስፈላጊነት ቅንብሮችን አሳይ"</string>
     <string name="blocked_importance" msgid="5198578988978234161">"የታገዱ"</string>
+    <string name="min_importance" msgid="1901894910809414782">"አነስተኛ አስፈላጊነት"</string>
     <string name="low_importance" msgid="4109929986107147930">"ዝቅተኛ አስፈላጊነት"</string>
     <string name="default_importance" msgid="8192107689995742653">"መደበኛ አስፈላጊነት"</string>
     <string name="high_importance" msgid="1527066195614050263">"ከፍተኛ አስፈላጊነት"</string>
     <string name="max_importance" msgid="5089005872719563894">"አስቸኳይ አስፈላጊነት"</string>
     <string name="notification_importance_blocked" msgid="2397192642657872872">"እነዚህን ማሳወቂያዎች በጭራሽ አታሳይ"</string>
-    <string name="notification_importance_low" msgid="4383563267370859725">"በማሳወቂያ ዝርዝሩ ታችኛውን ክፍል ላይ በጸጥታ አሳይ"</string>
-    <string name="notification_importance_default" msgid="4926529615920610817">"እነዚህን ማሳወቂያዎች በጸጥታ አሳይ"</string>
-    <string name="notification_importance_high" msgid="3222680136612408223">"በማሳወቂያዎች ዝርዝር ላይኛው ክፍል ላይ አሳይና ድምፅ አሰማ"</string>
-    <string name="notification_importance_max" msgid="5236987171904756134">"ወደ ገጸ ማያው ይመልከቱና ድምፅ ይቅረጹ"</string>
+    <string name="notification_importance_min" msgid="1938190340516905748">"በማሳወቂያ ዝርዝሩ ታችኛውን ክፍል ላይ በጸጥታ አሳይ"</string>
+    <string name="notification_importance_low" msgid="3657252049508213048">"እነዚህን ማሳወቂያዎች በጸጥታ አሳይ"</string>
+    <string name="notification_importance_default" msgid="4466466472622442175">"እነዚህ ማሳወቂያዎች ድምፆችን እንዲፈጥሩ ፍቀድ"</string>
+    <string name="notification_importance_high" msgid="2135428926525093825">"ወደ ማያ ገጹ አስገባና ድምፅ ፍቀድ"</string>
+    <string name="notification_importance_max" msgid="5806278962376556491">"በማሳወቂያዎች ዝርዝር አናት ላይ አሳይ፣ ወደ ማያ ገጹ አሳይና ድምፅ ፍቀድ"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"ተጨማሪ ቅንብሮች"</string>
     <string name="notification_done" msgid="5279426047273930175">"ተከናውኗል"</string>
     <string name="color_and_appearance" msgid="1254323855964993144">"ቀለም እና መልክ"</string>
@@ -476,7 +489,7 @@
     <string name="use_dark_theme" msgid="2900938704964299312">"ለAndroid ስርዓተ ክወና ጨለማ ገጽታን ተጠቀም"</string>
     <string name="adjust_tint" msgid="3398569573231409878">"ቅልም አስተካክል"</string>
     <string name="adjust_brightness" msgid="980039329808178246">"ብሩህነት አስተካክል"</string>
-    <string name="night_mode_disclaimer" msgid="3297928749219711334">"ጨለማ ገጽታው እንደ ቅንብሮች እና ማሳወቂያዎች ያሉ በመደበኛነት በብርሃን ገጽታ በሚታዩ የAndroid ስርዓተ ክወና ዋና ክፍሎች ላይ ይተገበራል።"</string>
+    <string name="night_mode_disclaimer" msgid="598914896926759578">"ጨለማ ገጽታው እንደ ቅንብሮች ያሉ በመደበኛነት በብርሃን ገጽታ በሚታዩ የAndroid ስርዓተ ክወና ዋና ክፍሎች ላይ ይተገበራል።"</string>
     <string name="color_apply" msgid="9212602012641034283">"ተግብር"</string>
     <string name="color_revert_title" msgid="4746666545480534663">"ቅንብሮችን ያረጋግጡ"</string>
     <string name="color_revert_message" msgid="9116001069397996691">"አንዳንድ የቀለም ቅንብሮች ይህን መሣሪያ የማይጠቅም ሊያደርጉት ይችላሉ። እነዚህን የቀለም ቅንብሮች ለማረጋገጥ እሺ የሚለውን ጠቅ ያድርጉ፣ አለበለዚያ እነዚህ ቅንብሮች ከ10 ሰከንዶች በኋላ ዳግም ይጀምራሉ።"</string>
@@ -535,4 +548,10 @@
     <item msgid="2139628951880142927">"የባትሪ ኃይል በሚሞላበት ጊዜ መቶኛ አሳይ (ነባሪ)"</item>
     <item msgid="3327323682209964956">"ይህን አዶ አታሳይ"</item>
   </string-array>
+    <string name="other" msgid="4060683095962566764">"ሌላ"</string>
+    <string name="accessibility_divider" msgid="5903423481953635044">"የተከፈለ የማያ ገጽ ከፋይ"</string>
+    <string name="accessibility_action_divider_move_down" msgid="704893304141890042">"ወደ ታች ሂድ"</string>
+    <string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"ወደ ላይ ሂድ"</string>
+    <string name="accessibility_action_divider_move_left" msgid="9218189832115847253">"ወደ ግራ ሂድ"</string>
+    <string name="accessibility_action_divider_move_right" msgid="4671522715182567972">"ወደ ቀኝ ሂድ"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-am/strings_tv.xml b/packages/SystemUI/res/values-am/strings_tv.xml
new file mode 100644
index 0000000..a6b9660
--- /dev/null
+++ b/packages/SystemUI/res/values-am/strings_tv.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2016, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <!-- no translation found for pip_close (3480680679023423574) -->
+    <skip />
+    <string name="pip_fullscreen" msgid="8604643018538487816">"ሙሉ ማያ ገጽ"</string>
+    <string name="pip_play" msgid="674145557658227044">"አጫውት"</string>
+    <string name="pip_pause" msgid="8412075640017218862">"ለአፍታ አቁም"</string>
+    <!-- no translation found for pip_hold_home (340086535668778109) -->
+    <skip />
+    <!-- no translation found for pip_onboarding_description (2627737116380318292) -->
+    <skip />
+    <!-- no translation found for pip_onboarding_button (3957426748484904611) -->
+    <skip />
+</resources>
diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml
index 91a2bca..5dc3b01 100644
--- a/packages/SystemUI/res/values-ar/strings.xml
+++ b/packages/SystemUI/res/values-ar/strings.xml
@@ -77,7 +77,8 @@
     <string name="screenshot_saved_title" msgid="6461865960961414961">"تم التقاط لقطة الشاشة."</string>
     <string name="screenshot_saved_text" msgid="1152839647677558815">"المس لعرض لقطة الشاشة."</string>
     <string name="screenshot_failed_title" msgid="705781116746922771">"تعذر التقاط لقطة الشاشة."</string>
-    <string name="screenshot_failed_text" msgid="1260203058661337274">"يتعذر التقاط لقطة شاشة نظرًا لأن مساحة التخزين المتاحة محدودة، أو نظرًا لعدم سماح التطبيق أو المؤسسة بذلك."</string>
+    <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"يتعذر حفظ لقطة الشاشة نظرًا لأن مساحة التخزين المتاحة محدودة."</string>
+    <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"غير مسموح بالتقاط لقطات شاشة نظرًا لإذن يتعلق بالتطبيق أو بالمؤسسة."</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"‏خيارات نقل الملفات عبر USB"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"‏تحميل كمشغل وسائط (MTP)"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"‏تحميل ككاميرا (PTP)"</string>
@@ -210,6 +211,7 @@
     <string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"وقت أكثر."</string>
     <string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"وقت أقل."</string>
     <string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"إيقاف الفلاش."</string>
+    <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"تطبيق المصباح اليدوي غير متاح."</string>
     <string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"تشغيل الفلاش."</string>
     <string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"تم إيقاف الفلاش."</string>
     <string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"تم تشغيل الفلاش."</string>
@@ -222,6 +224,10 @@
     <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"وضع العمل قيد التشغيل."</string>
     <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"تم تعطيل وضع العمل."</string>
     <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"تم تشغيل وضع العمل."</string>
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_off (650231949881093289) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_on (4218725402373934151) -->
+    <skip />
     <string name="accessibility_brightness" msgid="8003681285547803095">"سطوع الشاشة"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"بيانات شبكات الجيل الثاني والثالث متوقفة مؤقتًا"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"تم إيقاف بيانات شبكة الجيل الرابع مؤقتًا"</string>
@@ -308,6 +314,8 @@
     <string name="recents_launch_disabled_message" msgid="1624523193008871793">"تم تعطيل <xliff:g id="APP">%s</xliff:g> في الوضع الآمن."</string>
     <string name="recents_history_button_label" msgid="5153358867807604821">"السجلّ"</string>
     <string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"محو"</string>
+    <string name="recents_drag_non_dockable_task_message" msgid="2935843902795166158">"لا يتيح هذا التطبيق النوافذ المتعددة."</string>
+    <string name="recents_launch_non_dockable_task_label" msgid="7862379814938391888">"لا يتيح التطبيق النوافذ المتعددة."</string>
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"تقسيم أفقي"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"تقسيم رأسي"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"تقسيم مخصص"</string>
@@ -455,18 +463,23 @@
     <string name="enable_bluetooth_title" msgid="5027037706500635269">"تشغيل البلوتوث؟"</string>
     <string name="enable_bluetooth_message" msgid="9106595990708985385">"لتوصيل لوحة المفاتيح بالجهاز اللوحي، يلزمك تشغيل بلوتوث أولاً."</string>
     <string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"تشغيل"</string>
-    <string name="apply_to_topic" msgid="3641403489318659666">"التطبيق على إشعارات <xliff:g id="TOPIC_NAME">%1$s</xliff:g>"</string>
-    <string name="apply_to_app" msgid="363016783939815960">"التطبيق في جميع الإشعارات من هذا التطبيق"</string>
+    <string name="show_silently" msgid="6841966539811264192">"عرض الإشعارات بدون تنبيه صوتي"</string>
+    <string name="block" msgid="2734508760962682611">"حظر كل الإشعارات"</string>
+    <string name="do_not_silence" msgid="6878060322594892441">"عدم كتم التنبيه الصوتي"</string>
+    <string name="do_not_silence_block" msgid="4070647971382232311">"عدم كتم التنبيه الصوتي أو حظر الإشعار"</string>
+    <string name="tuner_full_importance_settings" msgid="8103289238676424226">"عرض الإعدادات الكاملة لمدى الأهمية"</string>
     <string name="blocked_importance" msgid="5198578988978234161">"تم الحظر"</string>
+    <string name="min_importance" msgid="1901894910809414782">"الأقل أهمية"</string>
     <string name="low_importance" msgid="4109929986107147930">"أهمية منخفضة"</string>
     <string name="default_importance" msgid="8192107689995742653">"أهمية عادية"</string>
     <string name="high_importance" msgid="1527066195614050263">"أهمية عالية"</string>
     <string name="max_importance" msgid="5089005872719563894">"أهمية ملحَّة"</string>
     <string name="notification_importance_blocked" msgid="2397192642657872872">"عدم عرض هذه الإشعارات"</string>
-    <string name="notification_importance_low" msgid="4383563267370859725">"العرض أسفل قائمة الإشعارات بدون تنبيه صوتي"</string>
-    <string name="notification_importance_default" msgid="4926529615920610817">"عرض هذه الإشعارات بدون تنبيه صوتي"</string>
-    <string name="notification_importance_high" msgid="3222680136612408223">"العرض أعلى قائمة الإشعارات مع تنبيه صوتي"</string>
-    <string name="notification_importance_max" msgid="5236987171904756134">"الظهور سريعًا على الشاشة مع تنبيه صوتي"</string>
+    <string name="notification_importance_min" msgid="1938190340516905748">"عرض الإشعار بأسفل قائمة الإشعارات بدون تنبيه صوتي"</string>
+    <string name="notification_importance_low" msgid="3657252049508213048">"عرض هذه الإشعارات بدون تنبيه صوتي"</string>
+    <string name="notification_importance_default" msgid="4466466472622442175">"السماح لهذه الإشعارات بإصدار تنبيهات صوتية"</string>
+    <string name="notification_importance_high" msgid="2135428926525093825">"يتم عرض الإشعار بسرعة على الشاشة مع السماح بإصدار تنبيه صوتي"</string>
+    <string name="notification_importance_max" msgid="5806278962376556491">"عرض هذا الإشعار بأعلى قائمة الإشعارات وعرضه بسرعة على الشاشة مع السماح بإصدار تنبيه صوتي"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"المزيد من الإعدادات"</string>
     <string name="notification_done" msgid="5279426047273930175">"تم"</string>
     <string name="color_and_appearance" msgid="1254323855964993144">"اللون والمظهر"</string>
@@ -480,7 +493,7 @@
     <string name="use_dark_theme" msgid="2900938704964299312">"‏استخدام مظهر معتم لنظام التشغيل Android"</string>
     <string name="adjust_tint" msgid="3398569573231409878">"ضبط التلوين الخفيف"</string>
     <string name="adjust_brightness" msgid="980039329808178246">"ضبط السطوع"</string>
-    <string name="night_mode_disclaimer" msgid="3297928749219711334">"‏يتم تطبيق المظهر المعتم على المناطق الأساسية في نظام التشغيل Android والتي يتم عرضها عادة في مظهر مضيء، مثل الإعدادات والإشعارات."</string>
+    <string name="night_mode_disclaimer" msgid="598914896926759578">"‏يتم تطبيق المظهر المعتم على المناطق الأساسية في نظام التشغيل Android والتي يتم عرضها عادة في مظهر مضيء، مثل الإعدادات."</string>
     <string name="color_apply" msgid="9212602012641034283">"تطبيق"</string>
     <string name="color_revert_title" msgid="4746666545480534663">"تأكيد الإعدادات"</string>
     <string name="color_revert_message" msgid="9116001069397996691">"يمكن أن تتسبب بعض إعدادات الألوان في تعطيل إمكانية استخدام الجهاز. يمكنك النقر على \"موافق\" لتأكيد إعدادات الألوان هذه، وإلا فستتم إعادة تعيين هذه الإعدادات بعد 10 ثوانٍ."</string>
@@ -539,4 +552,10 @@
     <item msgid="2139628951880142927">"عرض النسبة المئوية عند الشحن (افتراضي)"</item>
     <item msgid="3327323682209964956">"عدم عرض هذا الرمز"</item>
   </string-array>
+    <string name="other" msgid="4060683095962566764">"غير ذلك"</string>
+    <string name="accessibility_divider" msgid="5903423481953635044">"أداة تقسيم الشاشة"</string>
+    <string name="accessibility_action_divider_move_down" msgid="704893304141890042">"نقل لأسفل"</string>
+    <string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"نقل لأعلى"</string>
+    <string name="accessibility_action_divider_move_left" msgid="9218189832115847253">"نقل لليسار"</string>
+    <string name="accessibility_action_divider_move_right" msgid="4671522715182567972">"نقل لليمين"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ar/strings_tv.xml b/packages/SystemUI/res/values-ar/strings_tv.xml
new file mode 100644
index 0000000..99c413cf
--- /dev/null
+++ b/packages/SystemUI/res/values-ar/strings_tv.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.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="pip_close" msgid="3480680679023423574">"‏إغلاق PIP"</string>
+    <string name="pip_fullscreen" msgid="8604643018538487816">"ملء الشاشة"</string>
+    <string name="pip_play" msgid="674145557658227044">"تشغيل"</string>
+    <string name="pip_pause" msgid="8412075640017218862">"إيقاف مؤقت"</string>
+    <string name="pip_hold_home" msgid="340086535668778109">"‏اضغط "<b>"الرئيسية"</b>" للتحكم في PIP"</string>
+    <string name="pip_onboarding_description" msgid="2627737116380318292">"‏اضغط مع الاستمرار على زر الرئيسية\nللتحكم في PIP"</string>
+    <string name="pip_onboarding_button" msgid="3957426748484904611">"حسنًا"</string>
+</resources>
diff --git a/packages/SystemUI/res/values-az-rAZ/strings.xml b/packages/SystemUI/res/values-az-rAZ/strings.xml
index 45aba36..21bdc45 100644
--- a/packages/SystemUI/res/values-az-rAZ/strings.xml
+++ b/packages/SystemUI/res/values-az-rAZ/strings.xml
@@ -73,7 +73,8 @@
     <string name="screenshot_saved_title" msgid="6461865960961414961">"Skrinşot çəkildi."</string>
     <string name="screenshot_saved_text" msgid="1152839647677558815">"Skrinşotunuza baxmaq üçün toxunun"</string>
     <string name="screenshot_failed_title" msgid="705781116746922771">"Skrinşot götürülə bilinmədi."</string>
-    <string name="screenshot_failed_text" msgid="1260203058661337274">"Yaddaş ehtiyatının az olması səbəbindən skrinşot çəkmək olmur və ya bunu etmək ya tətbiq, ya da şirkət tərəfindən qadağan olunub."</string>
+    <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Yaddaş ehtiyatının az olması səbəbindən skrinşotu yadda saxlamaq olmur."</string>
+    <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Tətbiq və ya təşkilatınız tərəfindən skrinşot çəkməyə icazə verilmir."</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"USB fayl transferi seçimləri"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Media pleyer (MTP) kimi montaj edin"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"Kamera kimi birləşdir (PTP)"</string>
@@ -206,6 +207,7 @@
     <string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"Daha çox vaxt."</string>
     <string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"Daha az vaxt."</string>
     <string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"Fənər deaktiv."</string>
+    <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"Fənər əlçatan deyil."</string>
     <string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"Fənər aktiv."</string>
     <string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"Fənər deaktivdir."</string>
     <string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"Fənər aktivdir."</string>
@@ -218,6 +220,10 @@
     <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"İş rejimi aktivdir."</string>
     <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"İş rejimi sönülüdür."</string>
     <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"İş rejimi yanılıdır."</string>
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_off (650231949881093289) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_on (4218725402373934151) -->
+    <skip />
     <string name="accessibility_brightness" msgid="8003681285547803095">"Display brightness"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"2G-3G məlumatlarına fasilə verildi"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"4G məlumatlarına fasilə verildi"</string>
@@ -304,6 +310,8 @@
     <string name="recents_launch_disabled_message" msgid="1624523193008871793">"<xliff:g id="APP">%s</xliff:g> güvənli rejimdə deaktiv edildi."</string>
     <string name="recents_history_button_label" msgid="5153358867807604821">"Tarixçə"</string>
     <string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"Təmizləyin"</string>
+    <string name="recents_drag_non_dockable_task_message" msgid="2935843902795166158">"Bu tətbiq çoxsaylı pəncərəni dəstəkləmir"</string>
+    <string name="recents_launch_non_dockable_task_label" msgid="7862379814938391888">"Bu tətbiq çoxsaylı pəncərəni dəstəkləyir"</string>
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Üfüqi Böl"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Şaquli Böl"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Fərdi Böl"</string>
@@ -451,18 +459,23 @@
     <string name="enable_bluetooth_title" msgid="5027037706500635269">"Bluetooth aktivləşsin?"</string>
     <string name="enable_bluetooth_message" msgid="9106595990708985385">"Tabletinizlə klaviaturaya bağlanmaq üçün ilk olaraq Bluetooth\'u aktivləşdirməlisiniz."</string>
     <string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"Aktivləşdirin"</string>
-    <string name="apply_to_topic" msgid="3641403489318659666">"<xliff:g id="TOPIC_NAME">%1$s</xliff:g> bildirişlərinə müraciət edin"</string>
-    <string name="apply_to_app" msgid="363016783939815960">"Bu tətbiqdən olan bütün bildirişlərə müraciət edin"</string>
+    <string name="show_silently" msgid="6841966539811264192">"Bildirişləri səssiz göstərin"</string>
+    <string name="block" msgid="2734508760962682611">"Bütün bildirişləri blok edin"</string>
+    <string name="do_not_silence" msgid="6878060322594892441">"Səssiz etməyin"</string>
+    <string name="do_not_silence_block" msgid="4070647971382232311">"Səssiz və ya blok etməyin"</string>
+    <string name="tuner_full_importance_settings" msgid="8103289238676424226">"Tam əhəmiyyətlilik ayarlarını göstərin"</string>
     <string name="blocked_importance" msgid="5198578988978234161">"Bloklanmış"</string>
+    <string name="min_importance" msgid="1901894910809414782">"Minimum əhəmiyyətli"</string>
     <string name="low_importance" msgid="4109929986107147930">"Az əhəmiyyətli"</string>
     <string name="default_importance" msgid="8192107689995742653">"Normal əhəmiyyətli"</string>
     <string name="high_importance" msgid="1527066195614050263">"Çox əhəmiyyətli"</string>
     <string name="max_importance" msgid="5089005872719563894">"Təcili əhəmiyyətli"</string>
     <string name="notification_importance_blocked" msgid="2397192642657872872">"Bu bildirişləri heç vaxt göstərməyin"</string>
-    <string name="notification_importance_low" msgid="4383563267370859725">"Bildirişlər siyahısının aşağısında səssiz göstərin"</string>
-    <string name="notification_importance_default" msgid="4926529615920610817">"Bu bildişləri səssiz göstərin"</string>
-    <string name="notification_importance_high" msgid="3222680136612408223">"Bildirişlər siyahısında yuxarıda göstərin və səsli edin"</string>
-    <string name="notification_importance_max" msgid="5236987171904756134">"Ekranda nəzər salın və səsli edin"</string>
+    <string name="notification_importance_min" msgid="1938190340516905748">"Bildirişlər siyahısının aşağısında səssiz göstərin"</string>
+    <string name="notification_importance_low" msgid="3657252049508213048">"Bu bildişləri səssiz göstərin"</string>
+    <string name="notification_importance_default" msgid="4466466472622442175">"Bu bildirişi səsli edin"</string>
+    <string name="notification_importance_high" msgid="2135428926525093825">"Ekranda nəzər salın və səsə icazə verin"</string>
+    <string name="notification_importance_max" msgid="5806278962376556491">"Bildirişlər siyahısında yuxarıda göstərin, ekrana nəzər salın və səsə icazə verin"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"Daha çox ayar"</string>
     <string name="notification_done" msgid="5279426047273930175">"Hazırdır"</string>
     <string name="color_and_appearance" msgid="1254323855964993144">"Rəng və görünüş"</string>
@@ -476,7 +489,7 @@
     <string name="use_dark_theme" msgid="2900938704964299312">"Android OS üçün tünd tema istifadə edin"</string>
     <string name="adjust_tint" msgid="3398569573231409878">"Çaları nizamlayın"</string>
     <string name="adjust_brightness" msgid="980039329808178246">"Parlaqlığı nizamlayın"</string>
-    <string name="night_mode_disclaimer" msgid="3297928749219711334">"Tünd tema Android OS sisteminin adətən işıqlı tema göstərilən Ayarlar və bildirişlər kimi əsas sahələri üçün tətbiq edilir."</string>
+    <string name="night_mode_disclaimer" msgid="598914896926759578">"Tünd tema Android OS sisteminin adətən işıqlı tema göstərilən Ayarlar kimi əsas sahələri üçün tətbiq edilir."</string>
     <string name="color_apply" msgid="9212602012641034283">"Tətbiq edin"</string>
     <string name="color_revert_title" msgid="4746666545480534663">"Ayarları təsdiq edin"</string>
     <string name="color_revert_message" msgid="9116001069397996691">"Bəzi renk ayarları bu cihazı yararsız edə bilər. Bu rənk ayarlarını təsdiq etmək üçün OK basın, əks halda bu ayarlar 10 saniyə sonra sıfırlanacaq."</string>
@@ -535,4 +548,10 @@
     <item msgid="2139628951880142927">"Enerji dolan zaman faizi göstərin (defolt)"</item>
     <item msgid="3327323682209964956">"Bu piktoqramı göstərməyin"</item>
   </string-array>
+    <string name="other" msgid="4060683095962566764">"Digər"</string>
+    <string name="accessibility_divider" msgid="5903423481953635044">"Bölünmüş ekran ayırıcısı"</string>
+    <string name="accessibility_action_divider_move_down" msgid="704893304141890042">"Aşağıya keçin"</string>
+    <string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"Yuxarıya keçin"</string>
+    <string name="accessibility_action_divider_move_left" msgid="9218189832115847253">"Sola köçürün"</string>
+    <string name="accessibility_action_divider_move_right" msgid="4671522715182567972">"Sağa köçürün"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-az-rAZ/strings_tv.xml b/packages/SystemUI/res/values-az-rAZ/strings_tv.xml
new file mode 100644
index 0000000..e4e35ab2
--- /dev/null
+++ b/packages/SystemUI/res/values-az-rAZ/strings_tv.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2016, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <!-- no translation found for pip_close (3480680679023423574) -->
+    <skip />
+    <string name="pip_fullscreen" msgid="8604643018538487816">"Tam ekran"</string>
+    <string name="pip_play" msgid="674145557658227044">"Göstərin"</string>
+    <string name="pip_pause" msgid="8412075640017218862">"Fasilə verin"</string>
+    <!-- no translation found for pip_hold_home (340086535668778109) -->
+    <skip />
+    <!-- no translation found for pip_onboarding_description (2627737116380318292) -->
+    <skip />
+    <!-- no translation found for pip_onboarding_button (3957426748484904611) -->
+    <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 5494892..969b378 100644
--- a/packages/SystemUI/res/values-b+sr+Latn/strings.xml
+++ b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
@@ -74,7 +74,8 @@
     <string name="screenshot_saved_title" msgid="6461865960961414961">"Snimak ekrana je napravljen."</string>
     <string name="screenshot_saved_text" msgid="1152839647677558815">"Dodirnite da biste videli snimak ekrana."</string>
     <string name="screenshot_failed_title" msgid="705781116746922771">"Nije moguće napraviti snimak ekrana."</string>
-    <string name="screenshot_failed_text" msgid="1260203058661337274">"Nije moguće snimiti ekran zbog nedovoljne memorije ili to ne dozvoljava aplikacija ili organizacija."</string>
+    <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Čuvanje snimka ekrana nije uspelo zbog ograničenog memorijskog prostora."</string>
+    <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Aplikacija ili organizacija ne dozvoljavaju pravljenje snimaka ekrana."</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"Opcije USB prenosa datoteka"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Priključi kao medija plejer (MTP)"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"Priključi kao kameru (PTP)"</string>
@@ -207,6 +208,7 @@
     <string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"Više vremena."</string>
     <string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"Manje vremena."</string>
     <string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"Baterijska lampa je isključena."</string>
+    <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"Lampa nije dostupna."</string>
     <string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"Baterijska lampa je uključena."</string>
     <string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"Baterijska lampa je isključena."</string>
     <string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"Baterijska lampa je uključena."</string>
@@ -219,6 +221,10 @@
     <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"Režim rada je uključen."</string>
     <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"Režim rada je isključen."</string>
     <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"Režim rada je uključen."</string>
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_off (650231949881093289) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_on (4218725402373934151) -->
+    <skip />
     <string name="accessibility_brightness" msgid="8003681285547803095">"Osvetljenost ekrana"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"2G–3G podaci su pauzirani"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"4G podaci su pauzirani"</string>
@@ -305,6 +311,8 @@
     <string name="recents_launch_disabled_message" msgid="1624523193008871793">"Aplikacija <xliff:g id="APP">%s</xliff:g> je onemogućena u bezbednom režimu."</string>
     <string name="recents_history_button_label" msgid="5153358867807604821">"Istorija"</string>
     <string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"Obriši"</string>
+    <string name="recents_drag_non_dockable_task_message" msgid="2935843902795166158">"Ova aplikacija ne podržava režim sa više prozora"</string>
+    <string name="recents_launch_non_dockable_task_label" msgid="7862379814938391888">"Aplikacija ne podržava režim sa više prozora"</string>
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Podeli horizontalno"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Podeli vertikalno"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Prilagođeno deljenje"</string>
@@ -452,18 +460,23 @@
     <string name="enable_bluetooth_title" msgid="5027037706500635269">"Želite li da uključite Bluetooth?"</string>
     <string name="enable_bluetooth_message" msgid="9106595990708985385">"Da biste povezali tastaturu sa tabletom, prvo morate da uključite Bluetooth."</string>
     <string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"Uključi"</string>
-    <string name="apply_to_topic" msgid="3641403489318659666">"Primeni na obaveštenja o temi <xliff:g id="TOPIC_NAME">%1$s</xliff:g>"</string>
-    <string name="apply_to_app" msgid="363016783939815960">"Primeni na sva obaveštenja iz ove aplikacije"</string>
+    <string name="show_silently" msgid="6841966539811264192">"Prikazuj obaveštenja bez zvuka"</string>
+    <string name="block" msgid="2734508760962682611">"Blokiraj sva obaveštenja"</string>
+    <string name="do_not_silence" msgid="6878060322594892441">"Ne isključuj zvuk"</string>
+    <string name="do_not_silence_block" msgid="4070647971382232311">"Ne isključuju zvuk niti blokiraj"</string>
+    <string name="tuner_full_importance_settings" msgid="8103289238676424226">"Prikaži kompletna podešavanja važnosti"</string>
     <string name="blocked_importance" msgid="5198578988978234161">"Blokirana"</string>
+    <string name="min_importance" msgid="1901894910809414782">"Veoma mala važnost"</string>
     <string name="low_importance" msgid="4109929986107147930">"Mala važnost"</string>
     <string name="default_importance" msgid="8192107689995742653">"Uobičajena važnost"</string>
     <string name="high_importance" msgid="1527066195614050263">"Velika važnost"</string>
     <string name="max_importance" msgid="5089005872719563894">"Važnost: hitno"</string>
     <string name="notification_importance_blocked" msgid="2397192642657872872">"Ova obaveštenja se nikada ne prikazuju"</string>
-    <string name="notification_importance_low" msgid="4383563267370859725">"Prikazuju se u dnu liste obaveštenja bez zvuka"</string>
-    <string name="notification_importance_default" msgid="4926529615920610817">"Ova obaveštenja se prikazuju bez zvuka"</string>
-    <string name="notification_importance_high" msgid="3222680136612408223">"Prikazuju se u vrhu liste obaveštenja i emituje se zvuk"</string>
-    <string name="notification_importance_max" msgid="5236987171904756134">"Nakratko se prikazuju na ekranu i emituje se zvuk"</string>
+    <string name="notification_importance_min" msgid="1938190340516905748">"Prikazuju se u dnu liste obaveštenja bez zvuka"</string>
+    <string name="notification_importance_low" msgid="3657252049508213048">"Ova obaveštenja se prikazuju bez zvuka"</string>
+    <string name="notification_importance_default" msgid="4466466472622442175">"Dozvolite da ova obaveštenja emituju zvuk"</string>
+    <string name="notification_importance_high" msgid="2135428926525093825">"Nakratko se prikazuju na ekranu i emituju zvuk"</string>
+    <string name="notification_importance_max" msgid="5806278962376556491">"Prikazuju se u vrhu liste obaveštenja, nakratko se prikazuju na ekranu i emituju zvuk"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"Još podešavanja"</string>
     <string name="notification_done" msgid="5279426047273930175">"Gotovo"</string>
     <string name="color_and_appearance" msgid="1254323855964993144">"Boja i izgled"</string>
@@ -477,7 +490,7 @@
     <string name="use_dark_theme" msgid="2900938704964299312">"Koristi tamnu temu za Android OS"</string>
     <string name="adjust_tint" msgid="3398569573231409878">"Prilagodi senku"</string>
     <string name="adjust_brightness" msgid="980039329808178246">"Prilagodi osvetljenost"</string>
-    <string name="night_mode_disclaimer" msgid="3297928749219711334">"Tamna tema se primenjuje na ključne oblasti Android OS-a koje se obično prikazuju u svetloj temi, kao što su podešavanja i obaveštenja."</string>
+    <string name="night_mode_disclaimer" msgid="598914896926759578">"Tamna tema se primenjuje na ključne delove Android OS-a koji se obično prikazuju u svetloj temi, poput Podešavanja."</string>
     <string name="color_apply" msgid="9212602012641034283">"Primeni"</string>
     <string name="color_revert_title" msgid="4746666545480534663">"Potvrdite podešavanja"</string>
     <string name="color_revert_message" msgid="9116001069397996691">"Neka podešavanja boja mogu da učine uređaj neupotrebljivim. Kliknite na Potvrdi da biste potvrdili ova podešavanja boja, pošto će se u suprotnom ova podešavanja resetovati nakon 10 sekundi."</string>
@@ -536,4 +549,10 @@
     <item msgid="2139628951880142927">"Prikaži procenat tokom punjenja (podrazumevano)"</item>
     <item msgid="3327323682209964956">"Ne prikazuj ovu ikonu"</item>
   </string-array>
+    <string name="other" msgid="4060683095962566764">"Drugo"</string>
+    <string name="accessibility_divider" msgid="5903423481953635044">"Razdelnik podeljenog ekrana"</string>
+    <string name="accessibility_action_divider_move_down" msgid="704893304141890042">"Pomeri nadole"</string>
+    <string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"Pomeri nagore"</string>
+    <string name="accessibility_action_divider_move_left" msgid="9218189832115847253">"Pomeri ulevo"</string>
+    <string name="accessibility_action_divider_move_right" msgid="4671522715182567972">"Pomeri udesno"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-b+sr+Latn/strings_tv.xml b/packages/SystemUI/res/values-b+sr+Latn/strings_tv.xml
new file mode 100644
index 0000000..39a858c
--- /dev/null
+++ b/packages/SystemUI/res/values-b+sr+Latn/strings_tv.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.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="pip_close" msgid="3480680679023423574">"Zatvori PIP"</string>
+    <string name="pip_fullscreen" msgid="8604643018538487816">"Ceo ekran"</string>
+    <string name="pip_play" msgid="674145557658227044">"Pusti"</string>
+    <string name="pip_pause" msgid="8412075640017218862">"Pauziraj"</string>
+    <string name="pip_hold_home" msgid="340086535668778109"><b>"POČETNI EKRAN"</b>" kont. PIP"</string>
+    <string name="pip_onboarding_description" msgid="2627737116380318292">"Pritisnite i zadržite dugme POČETNI EKRAN\n da biste kontrolisali PIP"</string>
+    <string name="pip_onboarding_button" msgid="3957426748484904611">"Važi"</string>
+</resources>
diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml
index 31a9e13..9ff5f95 100644
--- a/packages/SystemUI/res/values-bg/strings.xml
+++ b/packages/SystemUI/res/values-bg/strings.xml
@@ -73,7 +73,8 @@
     <string name="screenshot_saved_title" msgid="6461865960961414961">"Екранната снимка е заснета."</string>
     <string name="screenshot_saved_text" msgid="1152839647677558815">"Докоснете, за да видите екранната си снимка."</string>
     <string name="screenshot_failed_title" msgid="705781116746922771">"Екранната снимка не можа да бъде заснета."</string>
-    <string name="screenshot_failed_text" msgid="1260203058661337274">"Не може да се направи екр. снимка поради недостиг на място или забрана от прилож. или организацията ви."</string>
+    <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Екранната снимка не може да се запази поради ограничено място в хранилището."</string>
+    <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Правенето на екранни снимки не е разрешено от приложението или организацията ви."</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"Опции за пренос на файлове чрез USB"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Свързване като медиен плейър (MTP)"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"Свързване като камера (PTP)"</string>
@@ -206,6 +207,7 @@
     <string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"Повече време."</string>
     <string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"По-малко време."</string>
     <string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"Фенерчето е изключено."</string>
+    <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"Няма достъп до фенерчето."</string>
     <string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"Фенерчето е включено."</string>
     <string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"Фенерчето е изключено."</string>
     <string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"Фенерчето е включено."</string>
@@ -218,6 +220,10 @@
     <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"Работният режим е включен."</string>
     <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"Работният режим е изключен."</string>
     <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"Работният режим е включен."</string>
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_off (650231949881093289) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_on (4218725402373934151) -->
+    <skip />
     <string name="accessibility_brightness" msgid="8003681285547803095">"Яркост на екрана"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"Данните от 2G – 3G са поставени на пауза"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"Данните от 4G са поставени на пауза"</string>
@@ -304,6 +310,8 @@
     <string name="recents_launch_disabled_message" msgid="1624523193008871793">"Приложението <xliff:g id="APP">%s</xliff:g> е деактивирано в безопасния режим."</string>
     <string name="recents_history_button_label" msgid="5153358867807604821">"История"</string>
     <string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"Изчистване"</string>
+    <string name="recents_drag_non_dockable_task_message" msgid="2935843902795166158">"Това приложение не поддържа няколко прозореца"</string>
+    <string name="recents_launch_non_dockable_task_label" msgid="7862379814938391888">"Приложението не поддържа няколко прозореца"</string>
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Хоризонтално разделяне"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Вертикално разделяне"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Персонализирано разделяне"</string>
@@ -451,18 +459,23 @@
     <string name="enable_bluetooth_title" msgid="5027037706500635269">"Да се включи ли Bluetooth?"</string>
     <string name="enable_bluetooth_message" msgid="9106595990708985385">"За да свържете клавиатурата с таблета си, първо трябва да включите Bluetooth."</string>
     <string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"Включване"</string>
-    <string name="apply_to_topic" msgid="3641403489318659666">"Прилагане за известията на тема „<xliff:g id="TOPIC_NAME">%1$s</xliff:g>“"</string>
-    <string name="apply_to_app" msgid="363016783939815960">"Прилагане за всички известия от това приложение"</string>
+    <string name="show_silently" msgid="6841966539811264192">"Показване на известията без звуков сигнал"</string>
+    <string name="block" msgid="2734508760962682611">"Блокиране на всички известия"</string>
+    <string name="do_not_silence" msgid="6878060322594892441">"Без заглушаване на звуковите сигнали"</string>
+    <string name="do_not_silence_block" msgid="4070647971382232311">"Без заглушаване на звуковите сигнали или блокиране"</string>
+    <string name="tuner_full_importance_settings" msgid="8103289238676424226">"Показване на пълните настройки за важността"</string>
     <string name="blocked_importance" msgid="5198578988978234161">"Блокирано"</string>
+    <string name="min_importance" msgid="1901894910809414782">"Минимална важност"</string>
     <string name="low_importance" msgid="4109929986107147930">"Малка важност"</string>
     <string name="default_importance" msgid="8192107689995742653">"Нормална важност"</string>
     <string name="high_importance" msgid="1527066195614050263">"Голяма важност"</string>
     <string name="max_importance" msgid="5089005872719563894">"Неотложна важност"</string>
     <string name="notification_importance_blocked" msgid="2397192642657872872">"Тези известия не се показват"</string>
-    <string name="notification_importance_low" msgid="4383563267370859725">"Беззвучно показване най-долу в списъка с известия"</string>
-    <string name="notification_importance_default" msgid="4926529615920610817">"Тези известия се показват без звук"</string>
-    <string name="notification_importance_high" msgid="3222680136612408223">"Показване най-горе в списъка с известия и издаване на звуков сигнал"</string>
-    <string name="notification_importance_max" msgid="5236987171904756134">"Показване на екрана и издаване на звуков сигнал"</string>
+    <string name="notification_importance_min" msgid="1938190340516905748">"Показване без звуков сигнал най-долу в списъка с известия"</string>
+    <string name="notification_importance_low" msgid="3657252049508213048">"Показване на тези известия без звуков сигнал"</string>
+    <string name="notification_importance_default" msgid="4466466472622442175">"Разрешаване при тези известия да се издава звуков сигнал"</string>
+    <string name="notification_importance_high" msgid="2135428926525093825">"Показване на екрана и разрешаване на звуков сигнал"</string>
+    <string name="notification_importance_max" msgid="5806278962376556491">"Показване най-горе в списъка с известия, както и на екрана и разрешаване на звуков сигнал"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"Още настройки"</string>
     <string name="notification_done" msgid="5279426047273930175">"Готово"</string>
     <string name="color_and_appearance" msgid="1254323855964993144">"Цвят и облик"</string>
@@ -476,7 +489,7 @@
     <string name="use_dark_theme" msgid="2900938704964299312">"Ползв. на тъмната тема за опер. с-ма Android"</string>
     <string name="adjust_tint" msgid="3398569573231409878">"Коригиране на нюансирането"</string>
     <string name="adjust_brightness" msgid="980039329808178246">"Коригиране на яркостта"</string>
-    <string name="night_mode_disclaimer" msgid="3297928749219711334">"Тъмната темата ще се прилага за основните области на операционната система Android, които обикновено се показват в светлата тема, като например настройките и известията."</string>
+    <string name="night_mode_disclaimer" msgid="598914896926759578">"Тъмната тема се прилага към основните области на операционната система Android, които обикновено се показват със светла тема, като например настройките."</string>
     <string name="color_apply" msgid="9212602012641034283">"Прилагане"</string>
     <string name="color_revert_title" msgid="4746666545480534663">"Потвърждаване на настройките"</string>
     <string name="color_revert_message" msgid="9116001069397996691">"Някои настройки за цветовете могат да направят това устройство неизползваемо. За да ги потвърдите, кликнете върху „OK“. В противен случай те ще бъдат нулирани след 10 секунди."</string>
@@ -535,4 +548,10 @@
     <item msgid="2139628951880142927">"Процентът да се показва при зареждане (по подразбиране)"</item>
     <item msgid="3327323682209964956">"Тази икона да не се показва"</item>
   </string-array>
+    <string name="other" msgid="4060683095962566764">"Друго"</string>
+    <string name="accessibility_divider" msgid="5903423481953635044">"Разделител в режима за разделен екран"</string>
+    <string name="accessibility_action_divider_move_down" msgid="704893304141890042">"Преместване надолу"</string>
+    <string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"Преместване нагоре"</string>
+    <string name="accessibility_action_divider_move_left" msgid="9218189832115847253">"Преместване наляво"</string>
+    <string name="accessibility_action_divider_move_right" msgid="4671522715182567972">"Преместване надясно"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-bg/strings_tv.xml b/packages/SystemUI/res/values-bg/strings_tv.xml
new file mode 100644
index 0000000..c5fc5b1
--- /dev/null
+++ b/packages/SystemUI/res/values-bg/strings_tv.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2016, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <!-- no translation found for pip_close (3480680679023423574) -->
+    <skip />
+    <string name="pip_fullscreen" msgid="8604643018538487816">"Цял екран"</string>
+    <string name="pip_play" msgid="674145557658227044">"Пускане"</string>
+    <string name="pip_pause" msgid="8412075640017218862">"Пауза"</string>
+    <!-- no translation found for pip_hold_home (340086535668778109) -->
+    <skip />
+    <!-- no translation found for pip_onboarding_description (2627737116380318292) -->
+    <skip />
+    <!-- no translation found for pip_onboarding_button (3957426748484904611) -->
+    <skip />
+</resources>
diff --git a/packages/SystemUI/res/values-bn-rBD/strings.xml b/packages/SystemUI/res/values-bn-rBD/strings.xml
index a54bf34..66537da 100644
--- a/packages/SystemUI/res/values-bn-rBD/strings.xml
+++ b/packages/SystemUI/res/values-bn-rBD/strings.xml
@@ -73,7 +73,8 @@
     <string name="screenshot_saved_title" msgid="6461865960961414961">"স্ক্রীনশট নেওয়া হযেছে৷"</string>
     <string name="screenshot_saved_text" msgid="1152839647677558815">"আপনার স্ক্রীনশট দেখতে স্পর্শ করুন৷"</string>
     <string name="screenshot_failed_title" msgid="705781116746922771">"স্ক্রীনশট নেওয়া যায়নি৷"</string>
-    <string name="screenshot_failed_text" msgid="1260203058661337274">"সঞ্চয়স্থান সীমিত হওয়ার ফলে স্ক্রীনশট নেওয়া যাবে না, অথবা এটি অ্যাপ্লিকেশানটি অথবা আপনার প্রতিষ্ঠানের দ্বারা অনুমোদিত নয়৷"</string>
+    <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"সঞ্চয়স্থান সীমিত থাকায় স্ক্রীনশটটি সংরক্ষণ করা যাবে না৷"</string>
+    <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"অ্যাপ্লিকেশান বা আপনার প্রতিষ্ঠান স্ক্রীনশটগুলি নেওয়া অনুমতি দেয়নি৷"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"USB ফাইল স্থানান্তরের বিকল্পগুলি"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"একটি মিডিয়া প্লেয়ার হিসাবে মাউন্ট করুন (MTP)"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"একটি ক্যামেরা হিসাবে মাউন্ট করুন (PTP)"</string>
@@ -206,6 +207,7 @@
     <string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"বেশি সময়।"</string>
     <string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"কম সময়।"</string>
     <string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"ফ্ল্যাশলাইট বন্ধ আছে।"</string>
+    <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"ফ্ল্যাশলাইট অনুপলব্ধ৷"</string>
     <string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"ফ্ল্যাশলাইট চালু আছে।"</string>
     <string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"ফ্ল্যাশলাইট বন্ধ হয়েছে।"</string>
     <string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"ফ্ল্যাশলাইট চালু হয়েছে।"</string>
@@ -218,6 +220,10 @@
     <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"কাজের মোড চালু আছে"</string>
     <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"কাজের মোড বন্ধ আছে।"</string>
     <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"কাজের মোড চালু আছে"</string>
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_off (650231949881093289) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_on (4218725402373934151) -->
+    <skip />
     <string name="accessibility_brightness" msgid="8003681285547803095">"প্রদর্শনের উজ্জ্বলতা"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"2G-3G ডেটা বিরতি দেওয়া হয়েছে"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"4G ডেটা বিরতি দেওয়া হয়েছে"</string>
@@ -304,6 +310,8 @@
     <string name="recents_launch_disabled_message" msgid="1624523193008871793">"নিরাপদ মোডে <xliff:g id="APP">%s</xliff:g> অক্ষম করা হয়েছে৷"</string>
     <string name="recents_history_button_label" msgid="5153358867807604821">"ইতিহাস"</string>
     <string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"সাফ করুন"</string>
+    <string name="recents_drag_non_dockable_task_message" msgid="2935843902795166158">"এই অ্যাপ্লিকেশানটি মাল্টি-উইন্ডো সমর্থন করে না"</string>
+    <string name="recents_launch_non_dockable_task_label" msgid="7862379814938391888">"অ্যাপ্লিকেশানগুলি মাল্টি-উইন্ডো সমর্থন করে না"</string>
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"অনুভূমিক স্প্লিট"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"উল্লম্ব স্প্লিট"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"কাস্টম স্প্লিট করুন"</string>
@@ -451,18 +459,23 @@
     <string name="enable_bluetooth_title" msgid="5027037706500635269">"Bluetooth চালু করবেন?"</string>
     <string name="enable_bluetooth_message" msgid="9106595990708985385">"আপনার ট্যাবলেটের সাথে আপনার কীবোর্ড সংযুক্ত করতে, আপনাকে প্রথমে Bluetooth চালু করতে হবে।"</string>
     <string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"চালু করুন"</string>
-    <string name="apply_to_topic" msgid="3641403489318659666">"<xliff:g id="TOPIC_NAME">%1$s</xliff:g> বিজ্ঞপ্তিগুলিতে প্রয়োগ করুন"</string>
-    <string name="apply_to_app" msgid="363016783939815960">"এই অ্যাপ্লিকেশনের থেকে সব বিজ্ঞপ্তিতে প্রয়োগ করুন"</string>
+    <string name="show_silently" msgid="6841966539811264192">"নীরবভাবে বিজ্ঞপ্তিগুলি দেখায়"</string>
+    <string name="block" msgid="2734508760962682611">"সমস্ত বিজ্ঞপ্তি অবরুদ্ধ করুন"</string>
+    <string name="do_not_silence" msgid="6878060322594892441">"নীরব করবেন না"</string>
+    <string name="do_not_silence_block" msgid="4070647971382232311">"নীরব বা অবরুদ্ধ করবেন না"</string>
+    <string name="tuner_full_importance_settings" msgid="8103289238676424226">"সম্পূর্ণ গুরুত্বপূর্ণ সেটিংস দেখায়"</string>
     <string name="blocked_importance" msgid="5198578988978234161">"অবরুদ্ধ"</string>
+    <string name="min_importance" msgid="1901894910809414782">"ন্যূনতম গুরুত্ব"</string>
     <string name="low_importance" msgid="4109929986107147930">"কম গুরুত্ব"</string>
     <string name="default_importance" msgid="8192107689995742653">"সাধারণ গুরুত্ব"</string>
     <string name="high_importance" msgid="1527066195614050263">"বেশি গুরুত্ব"</string>
     <string name="max_importance" msgid="5089005872719563894">"জরুরি গুরুত্ব"</string>
     <string name="notification_importance_blocked" msgid="2397192642657872872">"এই বিজ্ঞপ্তিগুলি কখনোই দেখানো হবে না"</string>
-    <string name="notification_importance_low" msgid="4383563267370859725">"বিজ্ঞপ্তি তালিকার নীচের অংশে নিঃশব্দে দেখানো হয়"</string>
-    <string name="notification_importance_default" msgid="4926529615920610817">"নিঃশব্দে এই বিজ্ঞপ্তিগুলি দেখানো হয়"</string>
-    <string name="notification_importance_high" msgid="3222680136612408223">"বিজ্ঞপ্তি তালিকার শীর্ষে দেখানো হয় এবং শব্দ করে"</string>
-    <string name="notification_importance_max" msgid="5236987171904756134">"স্ক্রীনের উপরে দেখানো হয় এবং শব্দ করে"</string>
+    <string name="notification_importance_min" msgid="1938190340516905748">"বিজ্ঞপ্তি তালিকার নীচের অংশে নিঃশব্দে দেখানো হয়"</string>
+    <string name="notification_importance_low" msgid="3657252049508213048">"নিঃশব্দে এই বিজ্ঞপ্তিগুলি দেখানো হয়"</string>
+    <string name="notification_importance_default" msgid="4466466472622442175">"এই বিজ্ঞপ্তিগুলিকে শব্দ করার মঞ্জুরি দেয়"</string>
+    <string name="notification_importance_high" msgid="2135428926525093825">"স্ক্রীনের উপরে প্রদর্শিত এবং শব্দ করার মঞ্জুরি দেয়"</string>
+    <string name="notification_importance_max" msgid="5806278962376556491">"বিজ্ঞপ্তি তালিকার শীর্ষে দেখানো হয় এবং স্ক্রীনের উপরে প্রদর্শিত এবং শব্দ করার মঞ্জুরি দেয়"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"আরো সেটিংস"</string>
     <string name="notification_done" msgid="5279426047273930175">"সম্পন্ন"</string>
     <string name="color_and_appearance" msgid="1254323855964993144">"রঙ এবং চেহারা"</string>
@@ -476,7 +489,7 @@
     <string name="use_dark_theme" msgid="2900938704964299312">"Android OS এর জন্য গাঢ় থিম ব্যবহার করুন"</string>
     <string name="adjust_tint" msgid="3398569573231409878">"টিন্ট সমন্বয় করুন"</string>
     <string name="adjust_brightness" msgid="980039329808178246">"উজ্জ্বলতা সমন্বয় করুন"</string>
-    <string name="night_mode_disclaimer" msgid="3297928749219711334">"Android OS এর মূল অংশগুলিতে গাঢ় থিম প্রয়োগ করা হয়েছে যেটা সাধারণত একটি হালকা থিমে প্রদর্শিত হয়, যেমন সেটিংস এবং বিজ্ঞপ্তিগুলি৷"</string>
+    <string name="night_mode_disclaimer" msgid="598914896926759578">"Android OS এর মূল অংশগুলিতে গাঢ় থিম প্রয়োগ করা হয়েছে যেটা সাধারণত একটি হালকা থিমে প্রদর্শিত হয়, যেমন সেটিংস৷"</string>
     <string name="color_apply" msgid="9212602012641034283">"প্রয়োগ করুন"</string>
     <string name="color_revert_title" msgid="4746666545480534663">"সেটিংস নিশ্চিত করুন"</string>
     <string name="color_revert_message" msgid="9116001069397996691">"কিছু রঙের সেটিংস এই ডিভাইসকে ব্যবহারের অযোগ্য করে দিতে পারে৷ এই রঙের সেটিংস নিশ্চিত করতে ওকে এ ক্লিক করুন, অন্যথায় ১০ সেকেন্ড পরে এই সেটিংস পুনরায় সেট হবে৷"</string>
@@ -535,4 +548,10 @@
     <item msgid="2139628951880142927">"চার্জ করার সময় শতাংশ দেখান (ডিফল্ট)"</item>
     <item msgid="3327323682209964956">"এই আইকনটি দেখাবেন না"</item>
   </string-array>
+    <string name="other" msgid="4060683095962566764">"অন্যান্য"</string>
+    <string name="accessibility_divider" msgid="5903423481953635044">"বিভক্ত-স্ক্রীন বিভাজক"</string>
+    <string name="accessibility_action_divider_move_down" msgid="704893304141890042">"নীচে সরান"</string>
+    <string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"উপরে সরান"</string>
+    <string name="accessibility_action_divider_move_left" msgid="9218189832115847253">"বাঁয়ে সরান"</string>
+    <string name="accessibility_action_divider_move_right" msgid="4671522715182567972">"ডানে সরান"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-bn-rBD/strings_tv.xml b/packages/SystemUI/res/values-bn-rBD/strings_tv.xml
new file mode 100644
index 0000000..7a95815
--- /dev/null
+++ b/packages/SystemUI/res/values-bn-rBD/strings_tv.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.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="pip_close" msgid="3480680679023423574">"PIP বন্ধ করুন"</string>
+    <string name="pip_fullscreen" msgid="8604643018538487816">"পূর্ণ স্ক্রীন"</string>
+    <string name="pip_play" msgid="674145557658227044">"চালান"</string>
+    <string name="pip_pause" msgid="8412075640017218862">"বিরাম দিন"</string>
+    <string name="pip_hold_home" msgid="340086535668778109">"PIP নিয়ন্ত্রণ করতে "<b>"হোম"</b>" কী ধরে রাখুন"</string>
+    <string name="pip_onboarding_description" msgid="2627737116380318292">"PIP নিয়ন্ত্রণ করতে হোম\nবোতামটি টিপে ধরে রাখুন"</string>
+    <string name="pip_onboarding_button" msgid="3957426748484904611">"বুঝেছি"</string>
+</resources>
diff --git a/packages/SystemUI/res/values-bs-rBA/strings.xml b/packages/SystemUI/res/values-bs-rBA/strings.xml
index 25e350d..91d9dea 100644
--- a/packages/SystemUI/res/values-bs-rBA/strings.xml
+++ b/packages/SystemUI/res/values-bs-rBA/strings.xml
@@ -74,7 +74,8 @@
     <string name="screenshot_saved_title" msgid="6461865960961414961">"Ekran snimljen."</string>
     <string name="screenshot_saved_text" msgid="1152839647677558815">"Dodirnite za prikaz snimka ekrana."</string>
     <string name="screenshot_failed_title" msgid="705781116746922771">"Došlo je do greške prilikom snimanja ekrana."</string>
-    <string name="screenshot_failed_text" msgid="1260203058661337274">"Ekran se ne može snimiti zbog manjka prostora, ili to ne dopuštaju aplikacija ili vaša organizacija."</string>
+    <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Snimak ekrana se ne može sačuvati zbog manjka prostora za pohranu."</string>
+    <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Aplikacija ili vaša organizacija ne dopuštaju pravljenje snimaka ekrana."</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"Opcije USB prijenosa fajlova"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Reproduciranje medijskih sadržaja (MTP)"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"Priključiti kao kameru (PTP)"</string>
@@ -207,6 +208,7 @@
     <string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"Više vremena."</string>
     <string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"Manje vremena."</string>
     <string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"Svjetiljka isključena."</string>
+    <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"Svjetiljka nije dostupna."</string>
     <string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"Svjetiljka uključena."</string>
     <string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"Svjetiljka je isključena."</string>
     <string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"Svjetiljka je uključena."</string>
@@ -219,6 +221,10 @@
     <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"Poslovni režim uključen."</string>
     <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"Poslovni režim je isključen."</string>
     <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"Poslovni režim je uključen."</string>
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_off (650231949881093289) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_on (4218725402373934151) -->
+    <skip />
     <string name="accessibility_brightness" msgid="8003681285547803095">"Osvjetljenje ekrana"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"2G–3G prijenos podataka je pauzirano"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"4G prijenos podataka je pauzirano"</string>
@@ -305,6 +311,8 @@
     <string name="recents_launch_disabled_message" msgid="1624523193008871793">"<xliff:g id="APP">%s</xliff:g> je onemogućena u sigurnom načinu rada."</string>
     <string name="recents_history_button_label" msgid="5153358867807604821">"Historija"</string>
     <string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"Obriši"</string>
+    <string name="recents_drag_non_dockable_task_message" msgid="2935843902795166158">"Ova aplikacija ne podržava rad sa više prozora"</string>
+    <string name="recents_launch_non_dockable_task_label" msgid="7862379814938391888">"Aplikacija ne podržava rad sa više prozora"</string>
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Podjela po horizontali"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Podjela po vertikali"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Prilagođena podjela"</string>
@@ -452,18 +460,23 @@
     <string name="enable_bluetooth_title" msgid="5027037706500635269">"Želiti li uključiti Bluetooth?"</string>
     <string name="enable_bluetooth_message" msgid="9106595990708985385">"Da povežete tastaturu sa tabletom, prvo morate uključiti Bluetooth."</string>
     <string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"Uključi"</string>
-    <string name="apply_to_topic" msgid="3641403489318659666">"Primijeni na obavještenja koja se odnose na temu <xliff:g id="TOPIC_NAME">%1$s</xliff:g>"</string>
-    <string name="apply_to_app" msgid="363016783939815960">"Primijeni na sva obavještenja ove aplikacije"</string>
+    <string name="show_silently" msgid="6841966539811264192">"Nečujno prikaži obavijesti"</string>
+    <string name="block" msgid="2734508760962682611">"Blokiraj sva obavještenja"</string>
+    <string name="do_not_silence" msgid="6878060322594892441">"Nemoj utišati"</string>
+    <string name="do_not_silence_block" msgid="4070647971382232311">"Nemoj utišati ili blokirati"</string>
+    <string name="tuner_full_importance_settings" msgid="8103289238676424226">"Prikaži kompletne postavke za određivanje značaja"</string>
     <string name="blocked_importance" msgid="5198578988978234161">"Blokirano"</string>
+    <string name="min_importance" msgid="1901894910809414782">"Minimalni značaj"</string>
     <string name="low_importance" msgid="4109929986107147930">"Mali značaj"</string>
     <string name="default_importance" msgid="8192107689995742653">"Normalan značaj"</string>
     <string name="high_importance" msgid="1527066195614050263">"Visok značaj"</string>
     <string name="max_importance" msgid="5089005872719563894">"Hitan značaj"</string>
     <string name="notification_importance_blocked" msgid="2397192642657872872">"Nikada ne prikazuj ova obavještenja"</string>
-    <string name="notification_importance_low" msgid="4383563267370859725">"Nečujno pokaži na dnu spiska obavještenja"</string>
-    <string name="notification_importance_default" msgid="4926529615920610817">"Nečujno prikaži ova obavještenja"</string>
-    <string name="notification_importance_high" msgid="3222680136612408223">"Pokaži na vrhu spiska obavještanja uz zvuk"</string>
-    <string name="notification_importance_max" msgid="5236987171904756134">"Kratki prikaz na ekranu uz zvuk"</string>
+    <string name="notification_importance_min" msgid="1938190340516905748">"Nečujno prikaži na dnu spiska obavještenja"</string>
+    <string name="notification_importance_low" msgid="3657252049508213048">"Nečujno prikaži ova obavještenja"</string>
+    <string name="notification_importance_default" msgid="4466466472622442175">"Dozvolite zvuk na ovim obavještenjima"</string>
+    <string name="notification_importance_high" msgid="2135428926525093825">"Kratko prikaži na ekranu i dozvoli zvuk"</string>
+    <string name="notification_importance_max" msgid="5806278962376556491">"Prikaži na vrhu liste obavještenja, kratko prikaži na ekranu i dozvoli zvuk"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"Više postavki"</string>
     <string name="notification_done" msgid="5279426047273930175">"Gotovo"</string>
     <string name="color_and_appearance" msgid="1254323855964993144">"Boja i izgled"</string>
@@ -477,7 +490,7 @@
     <string name="use_dark_theme" msgid="2900938704964299312">"Koristiti tamne teme za OS Android"</string>
     <string name="adjust_tint" msgid="3398569573231409878">"Prilagođavanje nijanse"</string>
     <string name="adjust_brightness" msgid="980039329808178246">"Podešavanje osvijetljenosti"</string>
-    <string name="night_mode_disclaimer" msgid="3297928749219711334">"Tamna tema se primjenjuje na ključna područja OS Android koja se obično prikazuju uz svijetlu temu, kao što su Postavke i Obavještenja."</string>
+    <string name="night_mode_disclaimer" msgid="598914896926759578">"Tamna tema se primjenjuje na ključna područja OS Android koja se obično prikazuju u svijetloj temi, kao što je meni Postavke."</string>
     <string name="color_apply" msgid="9212602012641034283">"Prihvati"</string>
     <string name="color_revert_title" msgid="4746666545480534663">"Potvrdi postavke"</string>
     <string name="color_revert_message" msgid="9116001069397996691">"S nekim postavkama boja ovaj uređaj može biti neupotrebljiv. Kliknite U redu da biste potvrdili ove postavke boja ili sačekajte 10 sekundi da se postavke vrate na početnu vrijednost."</string>
@@ -536,4 +549,10 @@
     <item msgid="2139628951880142927">"Pokaži postotak u toku punjenja (zadano)"</item>
     <item msgid="3327323682209964956">"Ne prikazuj ovu ikonu"</item>
   </string-array>
+    <string name="other" msgid="4060683095962566764">"Ostalo"</string>
+    <string name="accessibility_divider" msgid="5903423481953635044">"Razdjelnik ekrana"</string>
+    <string name="accessibility_action_divider_move_down" msgid="704893304141890042">"Pomjeri dolje"</string>
+    <string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"Pomjeri gore"</string>
+    <string name="accessibility_action_divider_move_left" msgid="9218189832115847253">"Pomjeri lijevo"</string>
+    <string name="accessibility_action_divider_move_right" msgid="4671522715182567972">"Pomjeri desno"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml
index f5124a1..a758798 100644
--- a/packages/SystemUI/res/values-ca/strings.xml
+++ b/packages/SystemUI/res/values-ca/strings.xml
@@ -73,7 +73,8 @@
     <string name="screenshot_saved_title" msgid="6461865960961414961">"S\'ha fet una captura de pantalla."</string>
     <string name="screenshot_saved_text" msgid="1152839647677558815">"Toca per veure la captura de pantalla."</string>
     <string name="screenshot_failed_title" msgid="705781116746922771">"No s\'ha pogut fer una captura de pantalla."</string>
-    <string name="screenshot_failed_text" msgid="1260203058661337274">"No es pot fer la captura perquè no hi ha prou espai, o l\'organització o l\'aplicació no ho permet."</string>
+    <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"La captura de pantalla no es pot desar perquè no hi ha prou espai d\'emmagatzematge."</string>
+    <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"L\'aplicació o l\'organització no permeten fer captures de pantalla."</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"Opcions transf. fitxers USB"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Munta com a reproductor multimèdia (MTP)"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"Munta com a càmera (PTP)"</string>
@@ -206,6 +207,7 @@
     <string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"Més temps"</string>
     <string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"Menys temps"</string>
     <string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"Llanterna desactivada"</string>
+    <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"La llanterna no està disponible."</string>
     <string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"Llanterna activada"</string>
     <string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"Llanterna desactivada."</string>
     <string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"Llanterna activada."</string>
@@ -218,6 +220,10 @@
     <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"El mode de feina està activat."</string>
     <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"S\'ha desactivat el mode de feina."</string>
     <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"S\'ha activat el mode de feina."</string>
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_off (650231949881093289) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_on (4218725402373934151) -->
+    <skip />
     <string name="accessibility_brightness" msgid="8003681285547803095">"Brillantor de la pantalla"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"Les dades 2G-3G estan aturades"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"Les dades 4G estan aturades"</string>
@@ -304,6 +310,8 @@
     <string name="recents_launch_disabled_message" msgid="1624523193008871793">"En mode segur, l\'aplicació <xliff:g id="APP">%s</xliff:g> està desactivada."</string>
     <string name="recents_history_button_label" msgid="5153358867807604821">"Historial"</string>
     <string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"Esborra"</string>
+    <string name="recents_drag_non_dockable_task_message" msgid="2935843902795166158">"Aquesta aplicació no admet el mode multifinestra"</string>
+    <string name="recents_launch_non_dockable_task_label" msgid="7862379814938391888">"L\'aplicació no admet el mode multifinestra"</string>
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Divisió horitzontal"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Divisió vertical"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Divisió personalitzada"</string>
@@ -451,18 +459,23 @@
     <string name="enable_bluetooth_title" msgid="5027037706500635269">"Vols activar el Bluetooth?"</string>
     <string name="enable_bluetooth_message" msgid="9106595990708985385">"Per connectar el teclat amb la tauleta, primer has d\'activar el Bluetooth."</string>
     <string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"Activa"</string>
-    <string name="apply_to_topic" msgid="3641403489318659666">"Aplica a les notificacions sobre <xliff:g id="TOPIC_NAME">%1$s</xliff:g>"</string>
-    <string name="apply_to_app" msgid="363016783939815960">"Aplica a totes les notificacions d\'aquesta aplicació"</string>
+    <string name="show_silently" msgid="6841966539811264192">"Mostra les notificacions de manera silenciosa"</string>
+    <string name="block" msgid="2734508760962682611">"Bloqueja totes les notificacions"</string>
+    <string name="do_not_silence" msgid="6878060322594892441">"No silenciïs"</string>
+    <string name="do_not_silence_block" msgid="4070647971382232311">"No silenciïs ni bloquegis"</string>
+    <string name="tuner_full_importance_settings" msgid="8103289238676424226">"Mostra la configuració completa per a la importància"</string>
     <string name="blocked_importance" msgid="5198578988978234161">"Bloquejades"</string>
+    <string name="min_importance" msgid="1901894910809414782">"Importància mínima"</string>
     <string name="low_importance" msgid="4109929986107147930">"Importància baixa"</string>
     <string name="default_importance" msgid="8192107689995742653">"Importància normal"</string>
     <string name="high_importance" msgid="1527066195614050263">"Importància alta"</string>
     <string name="max_importance" msgid="5089005872719563894">"Importància urgent"</string>
     <string name="notification_importance_blocked" msgid="2397192642657872872">"No mostris mai aquestes notificacions"</string>
-    <string name="notification_importance_low" msgid="4383563267370859725">"Mostra de manera silenciosa a la part inferior de la llista de notificacions"</string>
-    <string name="notification_importance_default" msgid="4926529615920610817">"Mostra aquestes notificacions de manera silenciosa"</string>
-    <string name="notification_importance_high" msgid="3222680136612408223">"Mostra a la part superior de la llista de notificacions i emet un so"</string>
-    <string name="notification_importance_max" msgid="5236987171904756134">"Mostra a la pantalla i emet un so"</string>
+    <string name="notification_importance_min" msgid="1938190340516905748">"Les notificacions es mostren de manera silenciosa al capdavall de la llista"</string>
+    <string name="notification_importance_low" msgid="3657252049508213048">"Mostra aquestes notificacions de manera silenciosa"</string>
+    <string name="notification_importance_default" msgid="4466466472622442175">"Permet que aquestes notificacions emetin sons"</string>
+    <string name="notification_importance_high" msgid="2135428926525093825">"Les notificacions apareixen a la pantalla i poden emetre sons"</string>
+    <string name="notification_importance_max" msgid="5806278962376556491">"Les notificacions es mostren al capdamunt de la llista, apareixen a la pantalla i poden emetre sons"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"Més opcions"</string>
     <string name="notification_done" msgid="5279426047273930175">"Fet"</string>
     <string name="color_and_appearance" msgid="1254323855964993144">"Color i aparença"</string>
@@ -476,7 +489,7 @@
     <string name="use_dark_theme" msgid="2900938704964299312">"Fes servir un tema fosc per a Android OS"</string>
     <string name="adjust_tint" msgid="3398569573231409878">"Ajusta el color"</string>
     <string name="adjust_brightness" msgid="980039329808178246">"Ajusta la brillantor"</string>
-    <string name="night_mode_disclaimer" msgid="3297928749219711334">"El mode nocturn s\'aplica a les àrees clau d\'Android OS que normalment es mostren amb un tema clar, com ara la configuració i les notificacions."</string>
+    <string name="night_mode_disclaimer" msgid="598914896926759578">"El tema fosc s\'aplica a les àrees clau d\'Android OS que normalment es mostren amb un tema clar, com ara Configuració."</string>
     <string name="color_apply" msgid="9212602012641034283">"Aplica"</string>
     <string name="color_revert_title" msgid="4746666545480534663">"Confirma la configuració"</string>
     <string name="color_revert_message" msgid="9116001069397996691">"Algunes opcions de configuració de color poden deixar el dispositiu inservible. Fes clic a D\'acord per confirmar la configuració de color; en cas contrari, la configuració es restablirà al cap de 10 segons."</string>
@@ -535,4 +548,10 @@
     <item msgid="2139628951880142927">"Mostra el percentatge quan es carregui (opció predeterminada)"</item>
     <item msgid="3327323682209964956">"No mostris aquesta icona"</item>
   </string-array>
+    <string name="other" msgid="4060683095962566764">"Altres"</string>
+    <string name="accessibility_divider" msgid="5903423481953635044">"Divisor de pantalles"</string>
+    <string name="accessibility_action_divider_move_down" msgid="704893304141890042">"Mou avall"</string>
+    <string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"Mou amunt"</string>
+    <string name="accessibility_action_divider_move_left" msgid="9218189832115847253">"Mou a l\'esquerra"</string>
+    <string name="accessibility_action_divider_move_right" msgid="4671522715182567972">"Mou a la dreta"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ca/strings_tv.xml b/packages/SystemUI/res/values-ca/strings_tv.xml
new file mode 100644
index 0000000..c5779ae
--- /dev/null
+++ b/packages/SystemUI/res/values-ca/strings_tv.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2016, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <!-- no translation found for pip_close (3480680679023423574) -->
+    <skip />
+    <string name="pip_fullscreen" msgid="8604643018538487816">"Pantalla completa"</string>
+    <string name="pip_play" msgid="674145557658227044">"Reprodueix"</string>
+    <string name="pip_pause" msgid="8412075640017218862">"Posa en pausa"</string>
+    <!-- no translation found for pip_hold_home (340086535668778109) -->
+    <skip />
+    <!-- no translation found for pip_onboarding_description (2627737116380318292) -->
+    <skip />
+    <!-- no translation found for pip_onboarding_button (3957426748484904611) -->
+    <skip />
+</resources>
diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml
index 6d5f717..86353a6 100644
--- a/packages/SystemUI/res/values-cs/strings.xml
+++ b/packages/SystemUI/res/values-cs/strings.xml
@@ -75,7 +75,8 @@
     <string name="screenshot_saved_title" msgid="6461865960961414961">"Snímek obrazovky Snímek obrazovky pořízen."</string>
     <string name="screenshot_saved_text" msgid="1152839647677558815">"Snímek obrazovky zobrazíte dotykem."</string>
     <string name="screenshot_failed_title" msgid="705781116746922771">"Snímek obrazovky se nepodařilo zachytit."</string>
-    <string name="screenshot_failed_text" msgid="1260203058661337274">"Snímek obrazovky nelze pořídit kvůli nedostatku místa, nebo to aplikace či vaše organizace zakazuje."</string>
+    <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Snímek obrazovky nelze pořídit kvůli nedostatku místa v úložišti."</string>
+    <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Aplikace nebo organizace zakazuje pořizování snímků obrazovky."</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"Možnosti přenosu souborů pomocí rozhraní USB"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Připojit jako přehrávač médií (MTP)"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"Připojit jako fotoaparát (PTP)"</string>
@@ -208,6 +209,7 @@
     <string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"Delší doba"</string>
     <string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"Kratší doba"</string>
     <string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"Svítilna je vypnutá."</string>
+    <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"Svítilna není k dispozici."</string>
     <string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"Svítilna je zapnutá."</string>
     <string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"Svítilna je vypnutá."</string>
     <string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"Svítilna je zapnutá."</string>
@@ -220,6 +222,10 @@
     <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"Pracovní režim zapnutý"</string>
     <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"Pracovní režim je vypnutý."</string>
     <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"Pracovní režim je zapnutý."</string>
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_off (650231949881093289) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_on (4218725402373934151) -->
+    <skip />
     <string name="accessibility_brightness" msgid="8003681285547803095">"Jas displeje"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"Data 2G a 3G jsou pozastavena"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"Data 4G jsou pozastavena"</string>
@@ -306,6 +312,8 @@
     <string name="recents_launch_disabled_message" msgid="1624523193008871793">"Aplikace <xliff:g id="APP">%s</xliff:g> je v nouzovém režimu zakázána."</string>
     <string name="recents_history_button_label" msgid="5153358867807604821">"Historie"</string>
     <string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"Vymazat"</string>
+    <string name="recents_drag_non_dockable_task_message" msgid="2935843902795166158">"Tato aplikace režim v několika oknech nepodporuje"</string>
+    <string name="recents_launch_non_dockable_task_label" msgid="7862379814938391888">"Aplikace režim v několika oknech nepodporuje"</string>
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Vodorovné rozdělení"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Vertikální rozdělení"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Vlastní rozdělení"</string>
@@ -453,18 +461,23 @@
     <string name="enable_bluetooth_title" msgid="5027037706500635269">"Zapnout Bluetooth?"</string>
     <string name="enable_bluetooth_message" msgid="9106595990708985385">"Chcete-li klávesnici připojit k tabletu, nejdříve musíte zapnout Bluetooth."</string>
     <string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"Zapnout"</string>
-    <string name="apply_to_topic" msgid="3641403489318659666">"Použít u oznámení z aplikace <xliff:g id="TOPIC_NAME">%1$s</xliff:g>"</string>
-    <string name="apply_to_app" msgid="363016783939815960">"Použít u všech oznámení z této aplikace"</string>
+    <string name="show_silently" msgid="6841966539811264192">"Zobrazovat oznámení tiše"</string>
+    <string name="block" msgid="2734508760962682611">"Blokovat všechna oznámení"</string>
+    <string name="do_not_silence" msgid="6878060322594892441">"Bez ztlumení"</string>
+    <string name="do_not_silence_block" msgid="4070647971382232311">"Bez ztlumení a blokování"</string>
+    <string name="tuner_full_importance_settings" msgid="8103289238676424226">"Zobrazit všechna nastavení důležitosti"</string>
     <string name="blocked_importance" msgid="5198578988978234161">"Blokováno"</string>
+    <string name="min_importance" msgid="1901894910809414782">"Minimální důležitost"</string>
     <string name="low_importance" msgid="4109929986107147930">"Nízká důležitost"</string>
     <string name="default_importance" msgid="8192107689995742653">"Normální důležitost"</string>
     <string name="high_importance" msgid="1527066195614050263">"Vysoká důležitost"</string>
     <string name="max_importance" msgid="5089005872719563894">"Urgentní důležitost"</string>
     <string name="notification_importance_blocked" msgid="2397192642657872872">"Tato oznámení nikdy nezobrazovat"</string>
-    <string name="notification_importance_low" msgid="4383563267370859725">"Tato oznámení zobrazovat na konci seznamu bez zvukového upozornění"</string>
-    <string name="notification_importance_default" msgid="4926529615920610817">"Tato oznámení zobrazovat bez zvukového upozornění"</string>
-    <string name="notification_importance_high" msgid="3222680136612408223">"Tato oznámení zobrazovat na začátku seznamu a upozornit na ně zvukem"</string>
-    <string name="notification_importance_max" msgid="5236987171904756134">"Tato oznámení zobrazovat přímo na obrazovce a upozornit na ně zvukem"</string>
+    <string name="notification_importance_min" msgid="1938190340516905748">"Tato oznámení zobrazovat na konci seznamu bez zvukového upozornění"</string>
+    <string name="notification_importance_low" msgid="3657252049508213048">"Tato oznámení zobrazovat bez zvukového upozornění"</string>
+    <string name="notification_importance_default" msgid="4466466472622442175">"Povolit těmto oznámením vydávat zvuky"</string>
+    <string name="notification_importance_high" msgid="2135428926525093825">"Tato oznámení zobrazovat přímo na obrazovce a upozornit na ně zvukem"</string>
+    <string name="notification_importance_max" msgid="5806278962376556491">"Tato oznámení zobrazovat na začátku seznamu, zobrazit přímo na obrazovce a upozornit na ně zvukem"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"Další nastavení"</string>
     <string name="notification_done" msgid="5279426047273930175">"Hotovo"</string>
     <string name="color_and_appearance" msgid="1254323855964993144">"Barva a vzhled"</string>
@@ -478,7 +491,7 @@
     <string name="use_dark_theme" msgid="2900938704964299312">"Použít v systému Android tmavý motiv"</string>
     <string name="adjust_tint" msgid="3398569573231409878">"Upravit tónování"</string>
     <string name="adjust_brightness" msgid="980039329808178246">"Upravit jas"</string>
-    <string name="night_mode_disclaimer" msgid="3297928749219711334">"V hlavních oblastech systému Android, které jsou běžně zobrazovány ve světlém motivu (například Nastavení nebo oznámení), se použije tmavý motiv."</string>
+    <string name="night_mode_disclaimer" msgid="598914896926759578">"V hlavních oblastech systému Android, které jsou běžně zobrazovány ve světlém motivu (například Nastavení), se použije tmavý motiv."</string>
     <string name="color_apply" msgid="9212602012641034283">"Použít"</string>
     <string name="color_revert_title" msgid="4746666545480534663">"Ověření nastavení"</string>
     <string name="color_revert_message" msgid="9116001069397996691">"Některá nastavení barev mohou způsobit, že zařízení nebude použitelné. Kliknutím na OK toto nastavení barev potvrdíte, v opačném případě se nastavení po 10 sekundách resetuje."</string>
@@ -537,4 +550,10 @@
     <item msgid="2139628951880142927">"Zobrazovat procento při nabíjení (výchozí nastavení)"</item>
     <item msgid="3327323682209964956">"Tuto ikonu nezobrazovat"</item>
   </string-array>
+    <string name="other" msgid="4060683095962566764">"Jiné"</string>
+    <string name="accessibility_divider" msgid="5903423481953635044">"Čára rozdělující obrazovku"</string>
+    <string name="accessibility_action_divider_move_down" msgid="704893304141890042">"Přesunout dolů"</string>
+    <string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"Přesunout nahoru"</string>
+    <string name="accessibility_action_divider_move_left" msgid="9218189832115847253">"Přesunout vlevo"</string>
+    <string name="accessibility_action_divider_move_right" msgid="4671522715182567972">"Přesunout vpravo"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-cs/strings_tv.xml b/packages/SystemUI/res/values-cs/strings_tv.xml
new file mode 100644
index 0000000..89640cd
--- /dev/null
+++ b/packages/SystemUI/res/values-cs/strings_tv.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2016, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <!-- no translation found for pip_close (3480680679023423574) -->
+    <skip />
+    <string name="pip_fullscreen" msgid="8604643018538487816">"Celá obrazovka"</string>
+    <string name="pip_play" msgid="674145557658227044">"Přehrát"</string>
+    <string name="pip_pause" msgid="8412075640017218862">"Pozastavit"</string>
+    <!-- no translation found for pip_hold_home (340086535668778109) -->
+    <skip />
+    <!-- no translation found for pip_onboarding_description (2627737116380318292) -->
+    <skip />
+    <!-- no translation found for pip_onboarding_button (3957426748484904611) -->
+    <skip />
+</resources>
diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml
index 04893c7..55fefc2 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -73,7 +73,8 @@
     <string name="screenshot_saved_title" msgid="6461865960961414961">"Skærmbilledet er gemt."</string>
     <string name="screenshot_saved_text" msgid="1152839647677558815">"Tryk for at se dit skærmbillede."</string>
     <string name="screenshot_failed_title" msgid="705781116746922771">"Skærmbilledet kunne ikke tages."</string>
-    <string name="screenshot_failed_text" msgid="1260203058661337274">"Skærmbilledet kan ikke tages pga. begrænset lagerplads, eller det tillades ikke af appen eller din organisation."</string>
+    <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Skærmbilledet kan ikke gemmes pga. begrænset lagerplads."</string>
+    <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Appen eller din organisation tillader ikke, at du tager skærmbilleder."</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"Muligheder for USB-filoverførsel"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Isæt som en medieafspiller (MTP)"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"Isæt som et kamera (PTP)"</string>
@@ -206,6 +207,7 @@
     <string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"Mere tid."</string>
     <string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"Mindre tid."</string>
     <string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"Lommelygten er slået fra."</string>
+    <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"Lommelygten er ikke tilgængelig."</string>
     <string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"Lommelygten er slået til."</string>
     <string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"Lommelygten er slået fra."</string>
     <string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"Lommelygten er slået til."</string>
@@ -218,6 +220,10 @@
     <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"Arbejdstilstand er slået til."</string>
     <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"Arbejdstilstand er slået fra."</string>
     <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"Arbejdstilstand er slået til."</string>
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_off (650231949881093289) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_on (4218725402373934151) -->
+    <skip />
     <string name="accessibility_brightness" msgid="8003681285547803095">"Skærmens lysstyrke"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"2G-3G-data er sat på pause"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"4G-data er sat på pause"</string>
@@ -304,6 +310,8 @@
     <string name="recents_launch_disabled_message" msgid="1624523193008871793">"<xliff:g id="APP">%s</xliff:g> er deaktiveret i sikker tilstand."</string>
     <string name="recents_history_button_label" msgid="5153358867807604821">"Historik"</string>
     <string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"Ryd"</string>
+    <string name="recents_drag_non_dockable_task_message" msgid="2935843902795166158">"Denne app understøtter ikke flere vinduer"</string>
+    <string name="recents_launch_non_dockable_task_label" msgid="7862379814938391888">"Appen understøtter ikke flere vinduer"</string>
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Opdel vandret"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Opdel lodret"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Opdel brugerdefineret"</string>
@@ -451,18 +459,23 @@
     <string name="enable_bluetooth_title" msgid="5027037706500635269">"Vil du slå Bluetooth til?"</string>
     <string name="enable_bluetooth_message" msgid="9106595990708985385">"Bluetooth skal være slået til, før du kan knytte dit tastatur til din tablet."</string>
     <string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"Slå til"</string>
-    <string name="apply_to_topic" msgid="3641403489318659666">"Anvend for underretninger vedrørende <xliff:g id="TOPIC_NAME">%1$s</xliff:g>"</string>
-    <string name="apply_to_app" msgid="363016783939815960">"Anvend for alle underretninger fra denne app"</string>
+    <string name="show_silently" msgid="6841966539811264192">"Vis underretninger lydløst"</string>
+    <string name="block" msgid="2734508760962682611">"Bloker alle underretninger"</string>
+    <string name="do_not_silence" msgid="6878060322594892441">"Skal ikke sættes på lydløs"</string>
+    <string name="do_not_silence_block" msgid="4070647971382232311">"Skal ikke sættes på lydløs eller blokeres"</string>
+    <string name="tuner_full_importance_settings" msgid="8103289238676424226">"Vis alle indstillinger for vigtighed"</string>
     <string name="blocked_importance" msgid="5198578988978234161">"Blokeret"</string>
+    <string name="min_importance" msgid="1901894910809414782">"Min vigtighed"</string>
     <string name="low_importance" msgid="4109929986107147930">"Lille vigtighed"</string>
     <string name="default_importance" msgid="8192107689995742653">"Normal vigtighed"</string>
     <string name="high_importance" msgid="1527066195614050263">"Stor vigtighed"</string>
     <string name="max_importance" msgid="5089005872719563894">"Presserende vigtighed"</string>
     <string name="notification_importance_blocked" msgid="2397192642657872872">"Vis aldrig disse underretninger"</string>
-    <string name="notification_importance_low" msgid="4383563267370859725">"Vis lydløst nederst på listen over underretninger"</string>
-    <string name="notification_importance_default" msgid="4926529615920610817">"Vis disse underretninger lydløst"</string>
-    <string name="notification_importance_high" msgid="3222680136612408223">"Vis øverst på listen over underretninger, og giv lyd"</string>
-    <string name="notification_importance_max" msgid="5236987171904756134">"Vis på skærmen, og giv lyd"</string>
+    <string name="notification_importance_min" msgid="1938190340516905748">"Vis lydløst nederst på listen over underretninger"</string>
+    <string name="notification_importance_low" msgid="3657252049508213048">"Vis disse underretninger lydløst"</string>
+    <string name="notification_importance_default" msgid="4466466472622442175">"Giv disse underretninger tilladelse til at give lyd"</string>
+    <string name="notification_importance_high" msgid="2135428926525093825">"Vis på skærmen, og tillad lyd"</string>
+    <string name="notification_importance_max" msgid="5806278962376556491">"Vis øverst på listen over underretninger, vis på skærmen, og tillad lyd"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"Flere indstillinger"</string>
     <string name="notification_done" msgid="5279426047273930175">"Færdig"</string>
     <string name="color_and_appearance" msgid="1254323855964993144">"Farve og udseende"</string>
@@ -476,7 +489,7 @@
     <string name="use_dark_theme" msgid="2900938704964299312">"Brug mørkt tema til Android OS"</string>
     <string name="adjust_tint" msgid="3398569573231409878">"Juster farvetonen"</string>
     <string name="adjust_brightness" msgid="980039329808178246">"Juster lysstyrken"</string>
-    <string name="night_mode_disclaimer" msgid="3297928749219711334">"Det mørke tema anvendes på centrale områder i Android OS, der normalt vises med lyst tema, f.eks. Indstilinger og underretninger."</string>
+    <string name="night_mode_disclaimer" msgid="598914896926759578">"Det mørke tema anvendes på centrale områder i Android OS, der normalt vises med lyst tema, f.eks. Indstillinger."</string>
     <string name="color_apply" msgid="9212602012641034283">"Anvend"</string>
     <string name="color_revert_title" msgid="4746666545480534663">"Bekræft indstillingerne"</string>
     <string name="color_revert_message" msgid="9116001069397996691">"Nogle farveindstillinger kan medføre, at du ikke kan bruge enheden. Klik på OK for at bekræfte disse farveindstillinger. Ellers nulstilles disse indstillinger efter ti sekunder."</string>
@@ -535,4 +548,10 @@
     <item msgid="2139628951880142927">"Vis procent ved opladning (standard)"</item>
     <item msgid="3327323682209964956">"Vis ikke dette ikon"</item>
   </string-array>
+    <string name="other" msgid="4060683095962566764">"Andet"</string>
+    <string name="accessibility_divider" msgid="5903423481953635044">"Adskiller til delt skærm"</string>
+    <string name="accessibility_action_divider_move_down" msgid="704893304141890042">"Flyt ned"</string>
+    <string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"Flyt op"</string>
+    <string name="accessibility_action_divider_move_left" msgid="9218189832115847253">"Flyt til venstre"</string>
+    <string name="accessibility_action_divider_move_right" msgid="4671522715182567972">"Flyt til højre"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-da/strings_tv.xml b/packages/SystemUI/res/values-da/strings_tv.xml
new file mode 100644
index 0000000..10a1ecd
--- /dev/null
+++ b/packages/SystemUI/res/values-da/strings_tv.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.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="pip_close" msgid="3480680679023423574">"Luk PIP"</string>
+    <string name="pip_fullscreen" msgid="8604643018538487816">"Fuld skærm"</string>
+    <string name="pip_play" msgid="674145557658227044">"Afspil"</string>
+    <string name="pip_pause" msgid="8412075640017218862">"Pause"</string>
+    <string name="pip_hold_home" msgid="340086535668778109">"Hold "<b>"HOME"</b>" nede for at styre PIP"</string>
+    <string name="pip_onboarding_description" msgid="2627737116380318292">"Tryk på knappen HOME,\nog hold den nede for at styre PIP"</string>
+    <string name="pip_onboarding_button" msgid="3957426748484904611">"OK"</string>
+</resources>
diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml
index c1619bf..cb8e0fd 100644
--- a/packages/SystemUI/res/values-de/strings.xml
+++ b/packages/SystemUI/res/values-de/strings.xml
@@ -73,7 +73,8 @@
     <string name="screenshot_saved_title" msgid="6461865960961414961">"Screenshot aufgenommen"</string>
     <string name="screenshot_saved_text" msgid="1152839647677558815">"Zum Ansehen berühren"</string>
     <string name="screenshot_failed_title" msgid="705781116746922771">"Screenshot konnte nicht aufgenommen werden."</string>
-    <string name="screenshot_failed_text" msgid="1260203058661337274">"Screenshot nicht möglich. Entweder zu wenig Speicher oder die App/dein Unternehmen lässt dies nicht zu."</string>
+    <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Speichern des Screenshots aufgrund von zu wenig Speicher nicht möglich."</string>
+    <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Die App oder Ihr Unternehmen lässt das Erstellen von Screenshots nicht zu."</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"USB-Dateiübertragungsoptionen"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Als Medienplayer (MTP) bereitstellen"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"Als Kamera (PTP) bereitstellen"</string>
@@ -206,6 +207,7 @@
     <string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"Mehr Zeit"</string>
     <string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"Weniger Zeit"</string>
     <string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"Taschenlampe deaktiviert"</string>
+    <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"Taschenlampe nicht verfügbar."</string>
     <string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"Taschenlampe aktiviert"</string>
     <string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"Die Taschenlampe ist deaktiviert."</string>
     <string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"Die Taschenlampe ist aktiviert."</string>
@@ -218,6 +220,10 @@
     <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"Arbeitsmodus an."</string>
     <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"Arbeitsmodus deaktiviert."</string>
     <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"Arbeitsmodus aktiviert."</string>
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_off (650231949881093289) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_on (4218725402373934151) -->
+    <skip />
     <string name="accessibility_brightness" msgid="8003681285547803095">"Helligkeit des Displays"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"2G-/3G-Daten pausiert"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"4G-Daten pausiert"</string>
@@ -304,6 +310,8 @@
     <string name="recents_launch_disabled_message" msgid="1624523193008871793">"<xliff:g id="APP">%s</xliff:g> ist im abgesicherten Modus deaktiviert."</string>
     <string name="recents_history_button_label" msgid="5153358867807604821">"Verlauf"</string>
     <string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"Löschen"</string>
+    <string name="recents_drag_non_dockable_task_message" msgid="2935843902795166158">"Diese App unterstützt den Mehrfenstermodus nicht"</string>
+    <string name="recents_launch_non_dockable_task_label" msgid="7862379814938391888">"App unterstützt Mehrfenstermodus nicht"</string>
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Geteilte Schaltfläche – horizontal"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Geteilte Schaltfläche – vertikal"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Geteilte Schaltfläche – benutzerdefiniert"</string>
@@ -451,18 +459,23 @@
     <string name="enable_bluetooth_title" msgid="5027037706500635269">"Bluetooth aktivieren?"</string>
     <string name="enable_bluetooth_message" msgid="9106595990708985385">"Zum Verbinden von Tastatur und Tablet muss Bluetooth aktiviert sein."</string>
     <string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"Aktivieren"</string>
-    <string name="apply_to_topic" msgid="3641403489318659666">"Für Benachrichtigungen über <xliff:g id="TOPIC_NAME">%1$s</xliff:g> anwenden"</string>
-    <string name="apply_to_app" msgid="363016783939815960">"Auf alle Benachrichtigungen dieser App anwenden"</string>
+    <string name="show_silently" msgid="6841966539811264192">"Benachrichtigungen ohne Ton anzeigen"</string>
+    <string name="block" msgid="2734508760962682611">"Alle Benachrichtigungen blockieren"</string>
+    <string name="do_not_silence" msgid="6878060322594892441">"Nicht stummschalten"</string>
+    <string name="do_not_silence_block" msgid="4070647971382232311">"Nicht stummschalten oder blockieren"</string>
+    <string name="tuner_full_importance_settings" msgid="8103289238676424226">"Vollständige Wichtigkeitseinstellungen anzeigen"</string>
     <string name="blocked_importance" msgid="5198578988978234161">"Blockiert"</string>
+    <string name="min_importance" msgid="1901894910809414782">"Minimum-Wichtigkeit"</string>
     <string name="low_importance" msgid="4109929986107147930">"Geringe Wichtigkeit"</string>
     <string name="default_importance" msgid="8192107689995742653">"Reguläre Wichtigkeit"</string>
     <string name="high_importance" msgid="1527066195614050263">"Hohe Wichtigkeit"</string>
     <string name="max_importance" msgid="5089005872719563894">"Sehr hohe Wichtigkeit"</string>
     <string name="notification_importance_blocked" msgid="2397192642657872872">"Diese Benachrichtigungen niemals anzeigen"</string>
-    <string name="notification_importance_low" msgid="4383563267370859725">"Ohne Ton am Ende der Benachrichtigungsliste anzeigen"</string>
-    <string name="notification_importance_default" msgid="4926529615920610817">"Diese Benachrichtigungen ohne Ton anzeigen"</string>
-    <string name="notification_importance_high" msgid="3222680136612408223">"Mit Ton ganz oben in der Benachrichtigungsliste anzeigen"</string>
-    <string name="notification_importance_max" msgid="5236987171904756134">"Mit Ton auf dem Display einblenden"</string>
+    <string name="notification_importance_min" msgid="1938190340516905748">"Ohne Ton am Ende der Benachrichtigungsliste anzeigen"</string>
+    <string name="notification_importance_low" msgid="3657252049508213048">"Diese Benachrichtigungen ohne Ton anzeigen"</string>
+    <string name="notification_importance_default" msgid="4466466472622442175">"Für diese Benachrichtigungen Ton zulassen"</string>
+    <string name="notification_importance_high" msgid="2135428926525093825">"Auf dem Display einblenden und Ton zulassen"</string>
+    <string name="notification_importance_max" msgid="5806278962376556491">"Ganz oben in der Benachrichtigungsliste anzeigen, auf dem Display einblenden und Ton zulassen"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"Weitere Einstellungen"</string>
     <string name="notification_done" msgid="5279426047273930175">"Fertig"</string>
     <string name="color_and_appearance" msgid="1254323855964993144">"Farbe und Darstellung"</string>
@@ -476,7 +489,7 @@
     <string name="use_dark_theme" msgid="2900938704964299312">"Dunkles Design unter Android OS verwenden"</string>
     <string name="adjust_tint" msgid="3398569573231409878">"Farbton anpassen"</string>
     <string name="adjust_brightness" msgid="980039329808178246">"Helligkeit anpassen"</string>
-    <string name="night_mode_disclaimer" msgid="3297928749219711334">"Das dunkle Design wird unter Android OS in allen Hauptbereichen übernommen, die normalerweise hell dargestellt werden, wie beispielsweise Einstellungen und Benachrichtigungen."</string>
+    <string name="night_mode_disclaimer" msgid="598914896926759578">"Das dunkle Design wird unter Android OS in allen Hauptbereichen übernommen, die normalerweise hell dargestellt werden, wie beispielsweise Einstellungen."</string>
     <string name="color_apply" msgid="9212602012641034283">"Übernehmen"</string>
     <string name="color_revert_title" msgid="4746666545480534663">"Einstellungen bestätigen"</string>
     <string name="color_revert_message" msgid="9116001069397996691">"Einige Farbeinstellungen können dazu führen, dass das Gerät nicht mehr genutzt werden kann. Klicke auf \"OK\", um diese Farbeinstellungen zu bestätigen. Anderenfalls werden diese Einstellungen in 10 Sekunden zurückgesetzt."</string>
@@ -535,4 +548,10 @@
     <item msgid="2139628951880142927">"Prozentwert beim Laden anzeigen (Standardeinstellung)"</item>
     <item msgid="3327323682209964956">"Dieses Symbol nicht anzeigen"</item>
   </string-array>
+    <string name="other" msgid="4060683095962566764">"Sonstiges"</string>
+    <string name="accessibility_divider" msgid="5903423481953635044">"Bildschirmteiler"</string>
+    <string name="accessibility_action_divider_move_down" msgid="704893304141890042">"Nach unten verschieben"</string>
+    <string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"Nach oben verschieben"</string>
+    <string name="accessibility_action_divider_move_left" msgid="9218189832115847253">"Nach links verschieben"</string>
+    <string name="accessibility_action_divider_move_right" msgid="4671522715182567972">"Nach rechts verschieben"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-de/strings_tv.xml b/packages/SystemUI/res/values-de/strings_tv.xml
new file mode 100644
index 0000000..aa1a9b2
--- /dev/null
+++ b/packages/SystemUI/res/values-de/strings_tv.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.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="pip_close" msgid="3480680679023423574">"PIP schließen"</string>
+    <string name="pip_fullscreen" msgid="8604643018538487816">"Vollbild"</string>
+    <string name="pip_play" msgid="674145557658227044">"Wiedergeben"</string>
+    <string name="pip_pause" msgid="8412075640017218862">"Pausieren"</string>
+    <string name="pip_hold_home" msgid="340086535668778109"><b>"STARTBILDSCHIRMTASTE"</b>" drücken, um PIP zu steuern"</string>
+    <string name="pip_onboarding_description" msgid="2627737116380318292">"STARTBILDSCHIRMTASTE\n gedrückt halten, um PIP zu steuern"</string>
+    <string name="pip_onboarding_button" msgid="3957426748484904611">"OK"</string>
+</resources>
diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml
index f6ed4bc..b1df615 100644
--- a/packages/SystemUI/res/values-el/strings.xml
+++ b/packages/SystemUI/res/values-el/strings.xml
@@ -73,7 +73,8 @@
     <string name="screenshot_saved_title" msgid="6461865960961414961">"Λήφθηκε το στιγμιότυπο οθόνης ."</string>
     <string name="screenshot_saved_text" msgid="1152839647677558815">"Αγγίξτε για να δείτε το στιγμιότυπο οθόνης σας"</string>
     <string name="screenshot_failed_title" msgid="705781116746922771">"Αδύνατη η αποθήκευση του στιγμιότυπου οθόνης."</string>
-    <string name="screenshot_failed_text" msgid="1260203058661337274">"Αδύνατη λήψη στιγμ. οθόνης λόγω περιορισμένου αποθ.χώρου ή αποκλεισμού από εφαρμογή ή οργανισμό."</string>
+    <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Δεν είναι δυνατή η αποθήκευση του στιγμιότυπου οθόνης λόγω περιορισμένου χώρου αποθήκευσης."</string>
+    <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Η λήψη στιγμιοτύπων οθόνης δεν επιτρέπεται από την εφαρμογή ή από τον οργανισμό σας."</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"Επιλογές μεταφοράς αρχείων μέσω USB"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Προσάρτηση ως μονάδας αναπαραγωγής μέσων (MTP)"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"Προσάρτηση ως κάμερας (PTP)"</string>
@@ -206,6 +207,7 @@
     <string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"Περισσότερη ώρα."</string>
     <string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"Λιγότερη ώρα."</string>
     <string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"Ανενεργός φακός."</string>
+    <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"Ο φακός δεν είναι διαθέσιμος."</string>
     <string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"Ενεργός φακός."</string>
     <string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"Ο φακός απενεργοποιήθηκε."</string>
     <string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"Ο φακός ενεργοποιήθηκε."</string>
@@ -218,6 +220,10 @@
     <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"Η λειτουργία εργασίας είναι ενεργή."</string>
     <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"Η λειτουργία εργασίας απενεργοποιήθηκε."</string>
     <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"Η λειτουργία εργασίας ενεργοποιήθηκε."</string>
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_off (650231949881093289) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_on (4218725402373934151) -->
+    <skip />
     <string name="accessibility_brightness" msgid="8003681285547803095">"Φωτεινότητα οθόνης"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"Τα δεδομένα 2G-3G τέθηκαν σε παύση"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"Τα δεδομένα 4G τέθηκαν σε παύση"</string>
@@ -304,6 +310,8 @@
     <string name="recents_launch_disabled_message" msgid="1624523193008871793">"Η εφαρμογή <xliff:g id="APP">%s</xliff:g> έχει απενεργοποιηθεί στην ασφαλή λειτουργία."</string>
     <string name="recents_history_button_label" msgid="5153358867807604821">"Ιστορικό"</string>
     <string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"Εκκαθάριση"</string>
+    <string name="recents_drag_non_dockable_task_message" msgid="2935843902795166158">"Η εφαρμογή αυτή δεν υποστηρίζει τη λειτουργία πολλαπλών παραθύρων"</string>
+    <string name="recents_launch_non_dockable_task_label" msgid="7862379814938391888">"Η εφαρμογή δεν υποστηρίζει τη λειτουργία πολλαπλών παραθύρων"</string>
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Οριζόντιος διαχωρισμός"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Κάθετος διαχωρισμός"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Προσαρμοσμένος διαχωρισμός"</string>
@@ -451,18 +459,23 @@
     <string name="enable_bluetooth_title" msgid="5027037706500635269">"Ενεργοποίηση Bluetooth;"</string>
     <string name="enable_bluetooth_message" msgid="9106595990708985385">"Για να συνδέσετε το πληκτρολόγιο με το tablet σας, θα πρέπει πρώτα να ενεργοποιήσετε το Bluetooth."</string>
     <string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"Ενεργοποίηση"</string>
-    <string name="apply_to_topic" msgid="3641403489318659666">"Να εφαρμοστεί στις ειδοποιήσεις <xliff:g id="TOPIC_NAME">%1$s</xliff:g>"</string>
-    <string name="apply_to_app" msgid="363016783939815960">"Να εφαρμοστεί σε όλες τις ειδοποιήσεις από αυτήν την εφαρμογή"</string>
+    <string name="show_silently" msgid="6841966539811264192">"Εμφάνιση ειδοποιήσεων χωρίς ήχο"</string>
+    <string name="block" msgid="2734508760962682611">"Αποκλεισμός όλων των ειδοποιήσεων"</string>
+    <string name="do_not_silence" msgid="6878060322594892441">"Χωρίς σίγαση"</string>
+    <string name="do_not_silence_block" msgid="4070647971382232311">"Χωρίς σίγαση ή αποκλεισμό"</string>
+    <string name="tuner_full_importance_settings" msgid="8103289238676424226">"Εμφάνιση όλων των ρυθμίσεων βαρύτητας"</string>
     <string name="blocked_importance" msgid="5198578988978234161">"Αποκλεισμένες"</string>
+    <string name="min_importance" msgid="1901894910809414782">"Ελάχιστη βαρύτητα"</string>
     <string name="low_importance" msgid="4109929986107147930">"Μικρής βαρύτητας"</string>
     <string name="default_importance" msgid="8192107689995742653">"Κανονικής βαρύτητας"</string>
     <string name="high_importance" msgid="1527066195614050263">"Μεγάλης βαρύτητας"</string>
     <string name="max_importance" msgid="5089005872719563894">"Επείγουσες"</string>
     <string name="notification_importance_blocked" msgid="2397192642657872872">"Να μην εμφανίζονται ποτέ αυτές οι ειδοποιήσεις"</string>
-    <string name="notification_importance_low" msgid="4383563267370859725">"Να εμφανίζονται στο κάτω τμήμα της λίστας ειδοποιήσεων χωρίς τίτλο"</string>
-    <string name="notification_importance_default" msgid="4926529615920610817">"Να εμφανίζονται αυτές οι ειδοποιήσεις χωρίς ήχο"</string>
-    <string name="notification_importance_high" msgid="3222680136612408223">"Να εμφανίζονται στην κορυφή της λίστας ειδοποιήσεων με ήχο"</string>
-    <string name="notification_importance_max" msgid="5236987171904756134">"Να προβάλλονται στην οθόνη και να συνοδεύονται από κάποιον ήχο"</string>
+    <string name="notification_importance_min" msgid="1938190340516905748">"Να εμφανίζονται στο κάτω μέρος της λίστας ειδοποιήσεων χωρίς ήχο"</string>
+    <string name="notification_importance_low" msgid="3657252049508213048">"Να εμφανίζονται αυτές οι ειδοποιήσεις χωρίς ήχο"</string>
+    <string name="notification_importance_default" msgid="4466466472622442175">"Να επιτρέπονται οι ήχοι από αυτές τις ειδοποιήσεις"</string>
+    <string name="notification_importance_high" msgid="2135428926525093825">"Να προβάλλονται στην οθόνη και να επιτρέπεται ο ήχος"</string>
+    <string name="notification_importance_max" msgid="5806278962376556491">"Να εμφανίζονται στην κορυφή της λίστας ειδοποιήσεων, να προβάλλονται στην οθόνη και να επιτρέπεται ο ήχος"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"Περισσότερες ρυθμίσεις"</string>
     <string name="notification_done" msgid="5279426047273930175">"Τέλος"</string>
     <string name="color_and_appearance" msgid="1254323855964993144">"Χρώμα και εμφάνιση"</string>
@@ -476,7 +489,7 @@
     <string name="use_dark_theme" msgid="2900938704964299312">"Χρήση σκοτεινού θέματος για Android OS"</string>
     <string name="adjust_tint" msgid="3398569573231409878">"Ρύθμιση απόχρωσης"</string>
     <string name="adjust_brightness" msgid="980039329808178246">"Ρύθμιση φωτεινότητας"</string>
-    <string name="night_mode_disclaimer" msgid="3297928749219711334">"Το σκούρο θέμα εφαρμόζεται σε βασικές περιοχές του λειτουργικού συστήματος Android οι οποίες συνήθως εμφανίζονται με φωτεινό θέμα, όπως οι Ρυθμίσεις και οι ειδοποιήσεις."</string>
+    <string name="night_mode_disclaimer" msgid="598914896926759578">"Το σκούρο θέμα εφαρμόζεται σε βασικές περιοχές του λειτουργικού συστήματος Android οι οποίες συνήθως εμφανίζονται με φωτεινό θέμα, όπως οι Ρυθμίσεις."</string>
     <string name="color_apply" msgid="9212602012641034283">"Εφαρμογή"</string>
     <string name="color_revert_title" msgid="4746666545480534663">"Επιβεβαίωση ρυθμίσεων"</string>
     <string name="color_revert_message" msgid="9116001069397996691">"Ορισμένες ρυθμίσεις χρωμάτων μπορεί να μην επιτρέπουν τη χρήση αυτής της συσκευής. Κάντε κλικ στην επιλογή OK για να επιβεβαιώσετε αυτές τις ρυθμίσεις χρωμάτων, διαφορετικά θα γίνει επαναφορά αυτών των ρυθμίσεων μετά από 10 δευτερόλεπτα."</string>
@@ -535,4 +548,10 @@
     <item msgid="2139628951880142927">"Να εμφανίζεται ποσοστό κατά τη φόρτιση (προεπιλογή)"</item>
     <item msgid="3327323682209964956">"Να μην εμφανίζεται αυτό το εικονίδιο"</item>
   </string-array>
+    <string name="other" msgid="4060683095962566764">"Άλλο"</string>
+    <string name="accessibility_divider" msgid="5903423481953635044">"Διαχωριστικό οθόνης"</string>
+    <string name="accessibility_action_divider_move_down" msgid="704893304141890042">"Μετακίνηση προς τα κάτω"</string>
+    <string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"Μετακίνηση προς τα επάνω"</string>
+    <string name="accessibility_action_divider_move_left" msgid="9218189832115847253">"Μετακίνηση αριστερά"</string>
+    <string name="accessibility_action_divider_move_right" msgid="4671522715182567972">"Μετακίνηση δεξιά"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-el/strings_tv.xml b/packages/SystemUI/res/values-el/strings_tv.xml
new file mode 100644
index 0000000..c96f852
--- /dev/null
+++ b/packages/SystemUI/res/values-el/strings_tv.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.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="pip_close" msgid="3480680679023423574">"Κλείσιμο PIP"</string>
+    <string name="pip_fullscreen" msgid="8604643018538487816">"Πλήρης οθόνη"</string>
+    <string name="pip_play" msgid="674145557658227044">"Αναπαραγωγή"</string>
+    <string name="pip_pause" msgid="8412075640017218862">"Παύση"</string>
+    <string name="pip_hold_home" msgid="340086535668778109">"Κρατήστε το πλήκτρο "<b>"HOME"</b>" πατημένο για έλεγχο του PIP"</string>
+    <string name="pip_onboarding_description" msgid="2627737116380318292">"Πατήστε παρατεταμένα το κουμπί HOME\nγια έλεγχο του PIP"</string>
+    <string name="pip_onboarding_button" msgid="3957426748484904611">"Κατάλαβα"</string>
+</resources>
diff --git a/packages/SystemUI/res/values-en-rAU/strings.xml b/packages/SystemUI/res/values-en-rAU/strings.xml
index bdc4bdb..72c71a8 100644
--- a/packages/SystemUI/res/values-en-rAU/strings.xml
+++ b/packages/SystemUI/res/values-en-rAU/strings.xml
@@ -73,7 +73,8 @@
     <string name="screenshot_saved_title" msgid="6461865960961414961">"Screenshot captured."</string>
     <string name="screenshot_saved_text" msgid="1152839647677558815">"Touch to view your screenshot."</string>
     <string name="screenshot_failed_title" msgid="705781116746922771">"Couldn\'t capture screenshot."</string>
-    <string name="screenshot_failed_text" msgid="1260203058661337274">"Can\'t take screenshot due to limited storage space, or it isn\'t allowed by the app or your organisation."</string>
+    <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Can\'t save screenshot due to limited storage space."</string>
+    <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Taking screenshots is not allowed by the app or your organisation."</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"USB file transfer options"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Mount as a media player (MTP)"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"Mount as a camera (PTP)"</string>
@@ -206,6 +207,7 @@
     <string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"More time."</string>
     <string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"Less time."</string>
     <string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"Torch off."</string>
+    <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"Torch unavailable."</string>
     <string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"Torch on."</string>
     <string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"Torch turned off."</string>
     <string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"Torch turned on."</string>
@@ -218,6 +220,10 @@
     <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"Work mode on."</string>
     <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"Work mode turned off."</string>
     <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"Work mode turned on."</string>
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_off (650231949881093289) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_on (4218725402373934151) -->
+    <skip />
     <string name="accessibility_brightness" msgid="8003681285547803095">"Display brightness"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"2G-3G data is paused"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"4G data is paused"</string>
@@ -304,6 +310,8 @@
     <string name="recents_launch_disabled_message" msgid="1624523193008871793">"<xliff:g id="APP">%s</xliff:g> is disabled in safe-mode."</string>
     <string name="recents_history_button_label" msgid="5153358867807604821">"History"</string>
     <string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"Clear"</string>
+    <string name="recents_drag_non_dockable_task_message" msgid="2935843902795166158">"This app does not support multi-window"</string>
+    <string name="recents_launch_non_dockable_task_label" msgid="7862379814938391888">"App does not support multi-window"</string>
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Split Horizontal"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Split Vertical"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Split Customised"</string>
@@ -451,18 +459,23 @@
     <string name="enable_bluetooth_title" msgid="5027037706500635269">"Turn on Bluetooth?"</string>
     <string name="enable_bluetooth_message" msgid="9106595990708985385">"To connect your keyboard with your tablet, you first have to turn on Bluetooth."</string>
     <string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"Turn on"</string>
-    <string name="apply_to_topic" msgid="3641403489318659666">"Apply to <xliff:g id="TOPIC_NAME">%1$s</xliff:g> notifications"</string>
-    <string name="apply_to_app" msgid="363016783939815960">"Apply to all notifications from this app"</string>
+    <string name="show_silently" msgid="6841966539811264192">"Show notifications silently"</string>
+    <string name="block" msgid="2734508760962682611">"Block all notifications"</string>
+    <string name="do_not_silence" msgid="6878060322594892441">"Don\'t silence"</string>
+    <string name="do_not_silence_block" msgid="4070647971382232311">"Don\'t silence or block"</string>
+    <string name="tuner_full_importance_settings" msgid="8103289238676424226">"Show full importance settings"</string>
     <string name="blocked_importance" msgid="5198578988978234161">"Blocked"</string>
+    <string name="min_importance" msgid="1901894910809414782">"Min importance"</string>
     <string name="low_importance" msgid="4109929986107147930">"Low importance"</string>
     <string name="default_importance" msgid="8192107689995742653">"Normal importance"</string>
     <string name="high_importance" msgid="1527066195614050263">"High importance"</string>
     <string name="max_importance" msgid="5089005872719563894">"Urgent importance"</string>
     <string name="notification_importance_blocked" msgid="2397192642657872872">"Never show these notifications"</string>
-    <string name="notification_importance_low" msgid="4383563267370859725">"Silently show at the bottom of the notification list"</string>
-    <string name="notification_importance_default" msgid="4926529615920610817">"Silently show these notifications"</string>
-    <string name="notification_importance_high" msgid="3222680136612408223">"Show at the top of the notifications list and make sound"</string>
-    <string name="notification_importance_max" msgid="5236987171904756134">"Peek onto the screen and make sound"</string>
+    <string name="notification_importance_min" msgid="1938190340516905748">"Silently show at the bottom of the notification list"</string>
+    <string name="notification_importance_low" msgid="3657252049508213048">"Silently show these notifications"</string>
+    <string name="notification_importance_default" msgid="4466466472622442175">"Allow these notifications to make sounds"</string>
+    <string name="notification_importance_high" msgid="2135428926525093825">"Peek on to the screen and allow sound"</string>
+    <string name="notification_importance_max" msgid="5806278962376556491">"Show at the top of the notifications list, peek on to the screen and allow sound"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"More settings"</string>
     <string name="notification_done" msgid="5279426047273930175">"Finished"</string>
     <string name="color_and_appearance" msgid="1254323855964993144">"Colour and appearance"</string>
@@ -476,7 +489,7 @@
     <string name="use_dark_theme" msgid="2900938704964299312">"Use dark theme for Android OS"</string>
     <string name="adjust_tint" msgid="3398569573231409878">"Adjust tint"</string>
     <string name="adjust_brightness" msgid="980039329808178246">"Adjust brightness"</string>
-    <string name="night_mode_disclaimer" msgid="3297928749219711334">"The dark theme is applied to core areas of Android OS that are normally displayed in a light theme, such as Settings and notifications."</string>
+    <string name="night_mode_disclaimer" msgid="598914896926759578">"The dark theme is applied to core areas of Android OS that are normally displayed in a light theme, such as Settings."</string>
     <string name="color_apply" msgid="9212602012641034283">"Apply"</string>
     <string name="color_revert_title" msgid="4746666545480534663">"Confirm Settings"</string>
     <string name="color_revert_message" msgid="9116001069397996691">"Some colour settings can make this device unusable. Click OK to confirm these colour settings, otherwise these settings will reset after 10 seconds."</string>
@@ -535,4 +548,10 @@
     <item msgid="2139628951880142927">"Show percentage when charging (default)"</item>
     <item msgid="3327323682209964956">"Don\'t show this icon"</item>
   </string-array>
+    <string name="other" msgid="4060683095962566764">"Other"</string>
+    <string name="accessibility_divider" msgid="5903423481953635044">"Split screen divider"</string>
+    <string name="accessibility_action_divider_move_down" msgid="704893304141890042">"Move down"</string>
+    <string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"Move up"</string>
+    <string name="accessibility_action_divider_move_left" msgid="9218189832115847253">"Move to the left"</string>
+    <string name="accessibility_action_divider_move_right" msgid="4671522715182567972">"Move to the right"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-en-rAU/strings_tv.xml b/packages/SystemUI/res/values-en-rAU/strings_tv.xml
new file mode 100644
index 0000000..6f33655
--- /dev/null
+++ b/packages/SystemUI/res/values-en-rAU/strings_tv.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.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="pip_close" msgid="3480680679023423574">"Close PIP"</string>
+    <string name="pip_fullscreen" msgid="8604643018538487816">"Full screen"</string>
+    <string name="pip_play" msgid="674145557658227044">"Play"</string>
+    <string name="pip_pause" msgid="8412075640017218862">"Pause"</string>
+    <string name="pip_hold_home" msgid="340086535668778109">"Hold "<b>"HOME"</b>" to control PIP"</string>
+    <string name="pip_onboarding_description" msgid="2627737116380318292">"Press and hold the HOME\nbutton to control PIP"</string>
+    <string name="pip_onboarding_button" msgid="3957426748484904611">"Understood"</string>
+</resources>
diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml
index bdc4bdb..72c71a8 100644
--- a/packages/SystemUI/res/values-en-rGB/strings.xml
+++ b/packages/SystemUI/res/values-en-rGB/strings.xml
@@ -73,7 +73,8 @@
     <string name="screenshot_saved_title" msgid="6461865960961414961">"Screenshot captured."</string>
     <string name="screenshot_saved_text" msgid="1152839647677558815">"Touch to view your screenshot."</string>
     <string name="screenshot_failed_title" msgid="705781116746922771">"Couldn\'t capture screenshot."</string>
-    <string name="screenshot_failed_text" msgid="1260203058661337274">"Can\'t take screenshot due to limited storage space, or it isn\'t allowed by the app or your organisation."</string>
+    <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Can\'t save screenshot due to limited storage space."</string>
+    <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Taking screenshots is not allowed by the app or your organisation."</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"USB file transfer options"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Mount as a media player (MTP)"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"Mount as a camera (PTP)"</string>
@@ -206,6 +207,7 @@
     <string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"More time."</string>
     <string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"Less time."</string>
     <string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"Torch off."</string>
+    <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"Torch unavailable."</string>
     <string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"Torch on."</string>
     <string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"Torch turned off."</string>
     <string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"Torch turned on."</string>
@@ -218,6 +220,10 @@
     <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"Work mode on."</string>
     <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"Work mode turned off."</string>
     <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"Work mode turned on."</string>
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_off (650231949881093289) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_on (4218725402373934151) -->
+    <skip />
     <string name="accessibility_brightness" msgid="8003681285547803095">"Display brightness"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"2G-3G data is paused"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"4G data is paused"</string>
@@ -304,6 +310,8 @@
     <string name="recents_launch_disabled_message" msgid="1624523193008871793">"<xliff:g id="APP">%s</xliff:g> is disabled in safe-mode."</string>
     <string name="recents_history_button_label" msgid="5153358867807604821">"History"</string>
     <string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"Clear"</string>
+    <string name="recents_drag_non_dockable_task_message" msgid="2935843902795166158">"This app does not support multi-window"</string>
+    <string name="recents_launch_non_dockable_task_label" msgid="7862379814938391888">"App does not support multi-window"</string>
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Split Horizontal"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Split Vertical"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Split Customised"</string>
@@ -451,18 +459,23 @@
     <string name="enable_bluetooth_title" msgid="5027037706500635269">"Turn on Bluetooth?"</string>
     <string name="enable_bluetooth_message" msgid="9106595990708985385">"To connect your keyboard with your tablet, you first have to turn on Bluetooth."</string>
     <string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"Turn on"</string>
-    <string name="apply_to_topic" msgid="3641403489318659666">"Apply to <xliff:g id="TOPIC_NAME">%1$s</xliff:g> notifications"</string>
-    <string name="apply_to_app" msgid="363016783939815960">"Apply to all notifications from this app"</string>
+    <string name="show_silently" msgid="6841966539811264192">"Show notifications silently"</string>
+    <string name="block" msgid="2734508760962682611">"Block all notifications"</string>
+    <string name="do_not_silence" msgid="6878060322594892441">"Don\'t silence"</string>
+    <string name="do_not_silence_block" msgid="4070647971382232311">"Don\'t silence or block"</string>
+    <string name="tuner_full_importance_settings" msgid="8103289238676424226">"Show full importance settings"</string>
     <string name="blocked_importance" msgid="5198578988978234161">"Blocked"</string>
+    <string name="min_importance" msgid="1901894910809414782">"Min importance"</string>
     <string name="low_importance" msgid="4109929986107147930">"Low importance"</string>
     <string name="default_importance" msgid="8192107689995742653">"Normal importance"</string>
     <string name="high_importance" msgid="1527066195614050263">"High importance"</string>
     <string name="max_importance" msgid="5089005872719563894">"Urgent importance"</string>
     <string name="notification_importance_blocked" msgid="2397192642657872872">"Never show these notifications"</string>
-    <string name="notification_importance_low" msgid="4383563267370859725">"Silently show at the bottom of the notification list"</string>
-    <string name="notification_importance_default" msgid="4926529615920610817">"Silently show these notifications"</string>
-    <string name="notification_importance_high" msgid="3222680136612408223">"Show at the top of the notifications list and make sound"</string>
-    <string name="notification_importance_max" msgid="5236987171904756134">"Peek onto the screen and make sound"</string>
+    <string name="notification_importance_min" msgid="1938190340516905748">"Silently show at the bottom of the notification list"</string>
+    <string name="notification_importance_low" msgid="3657252049508213048">"Silently show these notifications"</string>
+    <string name="notification_importance_default" msgid="4466466472622442175">"Allow these notifications to make sounds"</string>
+    <string name="notification_importance_high" msgid="2135428926525093825">"Peek on to the screen and allow sound"</string>
+    <string name="notification_importance_max" msgid="5806278962376556491">"Show at the top of the notifications list, peek on to the screen and allow sound"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"More settings"</string>
     <string name="notification_done" msgid="5279426047273930175">"Finished"</string>
     <string name="color_and_appearance" msgid="1254323855964993144">"Colour and appearance"</string>
@@ -476,7 +489,7 @@
     <string name="use_dark_theme" msgid="2900938704964299312">"Use dark theme for Android OS"</string>
     <string name="adjust_tint" msgid="3398569573231409878">"Adjust tint"</string>
     <string name="adjust_brightness" msgid="980039329808178246">"Adjust brightness"</string>
-    <string name="night_mode_disclaimer" msgid="3297928749219711334">"The dark theme is applied to core areas of Android OS that are normally displayed in a light theme, such as Settings and notifications."</string>
+    <string name="night_mode_disclaimer" msgid="598914896926759578">"The dark theme is applied to core areas of Android OS that are normally displayed in a light theme, such as Settings."</string>
     <string name="color_apply" msgid="9212602012641034283">"Apply"</string>
     <string name="color_revert_title" msgid="4746666545480534663">"Confirm Settings"</string>
     <string name="color_revert_message" msgid="9116001069397996691">"Some colour settings can make this device unusable. Click OK to confirm these colour settings, otherwise these settings will reset after 10 seconds."</string>
@@ -535,4 +548,10 @@
     <item msgid="2139628951880142927">"Show percentage when charging (default)"</item>
     <item msgid="3327323682209964956">"Don\'t show this icon"</item>
   </string-array>
+    <string name="other" msgid="4060683095962566764">"Other"</string>
+    <string name="accessibility_divider" msgid="5903423481953635044">"Split screen divider"</string>
+    <string name="accessibility_action_divider_move_down" msgid="704893304141890042">"Move down"</string>
+    <string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"Move up"</string>
+    <string name="accessibility_action_divider_move_left" msgid="9218189832115847253">"Move to the left"</string>
+    <string name="accessibility_action_divider_move_right" msgid="4671522715182567972">"Move to the right"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-en-rGB/strings_tv.xml b/packages/SystemUI/res/values-en-rGB/strings_tv.xml
new file mode 100644
index 0000000..6f33655
--- /dev/null
+++ b/packages/SystemUI/res/values-en-rGB/strings_tv.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.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="pip_close" msgid="3480680679023423574">"Close PIP"</string>
+    <string name="pip_fullscreen" msgid="8604643018538487816">"Full screen"</string>
+    <string name="pip_play" msgid="674145557658227044">"Play"</string>
+    <string name="pip_pause" msgid="8412075640017218862">"Pause"</string>
+    <string name="pip_hold_home" msgid="340086535668778109">"Hold "<b>"HOME"</b>" to control PIP"</string>
+    <string name="pip_onboarding_description" msgid="2627737116380318292">"Press and hold the HOME\nbutton to control PIP"</string>
+    <string name="pip_onboarding_button" msgid="3957426748484904611">"Understood"</string>
+</resources>
diff --git a/packages/SystemUI/res/values-en-rIN/strings.xml b/packages/SystemUI/res/values-en-rIN/strings.xml
index bdc4bdb..72c71a8 100644
--- a/packages/SystemUI/res/values-en-rIN/strings.xml
+++ b/packages/SystemUI/res/values-en-rIN/strings.xml
@@ -73,7 +73,8 @@
     <string name="screenshot_saved_title" msgid="6461865960961414961">"Screenshot captured."</string>
     <string name="screenshot_saved_text" msgid="1152839647677558815">"Touch to view your screenshot."</string>
     <string name="screenshot_failed_title" msgid="705781116746922771">"Couldn\'t capture screenshot."</string>
-    <string name="screenshot_failed_text" msgid="1260203058661337274">"Can\'t take screenshot due to limited storage space, or it isn\'t allowed by the app or your organisation."</string>
+    <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Can\'t save screenshot due to limited storage space."</string>
+    <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Taking screenshots is not allowed by the app or your organisation."</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"USB file transfer options"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Mount as a media player (MTP)"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"Mount as a camera (PTP)"</string>
@@ -206,6 +207,7 @@
     <string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"More time."</string>
     <string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"Less time."</string>
     <string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"Torch off."</string>
+    <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"Torch unavailable."</string>
     <string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"Torch on."</string>
     <string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"Torch turned off."</string>
     <string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"Torch turned on."</string>
@@ -218,6 +220,10 @@
     <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"Work mode on."</string>
     <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"Work mode turned off."</string>
     <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"Work mode turned on."</string>
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_off (650231949881093289) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_on (4218725402373934151) -->
+    <skip />
     <string name="accessibility_brightness" msgid="8003681285547803095">"Display brightness"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"2G-3G data is paused"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"4G data is paused"</string>
@@ -304,6 +310,8 @@
     <string name="recents_launch_disabled_message" msgid="1624523193008871793">"<xliff:g id="APP">%s</xliff:g> is disabled in safe-mode."</string>
     <string name="recents_history_button_label" msgid="5153358867807604821">"History"</string>
     <string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"Clear"</string>
+    <string name="recents_drag_non_dockable_task_message" msgid="2935843902795166158">"This app does not support multi-window"</string>
+    <string name="recents_launch_non_dockable_task_label" msgid="7862379814938391888">"App does not support multi-window"</string>
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Split Horizontal"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Split Vertical"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Split Customised"</string>
@@ -451,18 +459,23 @@
     <string name="enable_bluetooth_title" msgid="5027037706500635269">"Turn on Bluetooth?"</string>
     <string name="enable_bluetooth_message" msgid="9106595990708985385">"To connect your keyboard with your tablet, you first have to turn on Bluetooth."</string>
     <string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"Turn on"</string>
-    <string name="apply_to_topic" msgid="3641403489318659666">"Apply to <xliff:g id="TOPIC_NAME">%1$s</xliff:g> notifications"</string>
-    <string name="apply_to_app" msgid="363016783939815960">"Apply to all notifications from this app"</string>
+    <string name="show_silently" msgid="6841966539811264192">"Show notifications silently"</string>
+    <string name="block" msgid="2734508760962682611">"Block all notifications"</string>
+    <string name="do_not_silence" msgid="6878060322594892441">"Don\'t silence"</string>
+    <string name="do_not_silence_block" msgid="4070647971382232311">"Don\'t silence or block"</string>
+    <string name="tuner_full_importance_settings" msgid="8103289238676424226">"Show full importance settings"</string>
     <string name="blocked_importance" msgid="5198578988978234161">"Blocked"</string>
+    <string name="min_importance" msgid="1901894910809414782">"Min importance"</string>
     <string name="low_importance" msgid="4109929986107147930">"Low importance"</string>
     <string name="default_importance" msgid="8192107689995742653">"Normal importance"</string>
     <string name="high_importance" msgid="1527066195614050263">"High importance"</string>
     <string name="max_importance" msgid="5089005872719563894">"Urgent importance"</string>
     <string name="notification_importance_blocked" msgid="2397192642657872872">"Never show these notifications"</string>
-    <string name="notification_importance_low" msgid="4383563267370859725">"Silently show at the bottom of the notification list"</string>
-    <string name="notification_importance_default" msgid="4926529615920610817">"Silently show these notifications"</string>
-    <string name="notification_importance_high" msgid="3222680136612408223">"Show at the top of the notifications list and make sound"</string>
-    <string name="notification_importance_max" msgid="5236987171904756134">"Peek onto the screen and make sound"</string>
+    <string name="notification_importance_min" msgid="1938190340516905748">"Silently show at the bottom of the notification list"</string>
+    <string name="notification_importance_low" msgid="3657252049508213048">"Silently show these notifications"</string>
+    <string name="notification_importance_default" msgid="4466466472622442175">"Allow these notifications to make sounds"</string>
+    <string name="notification_importance_high" msgid="2135428926525093825">"Peek on to the screen and allow sound"</string>
+    <string name="notification_importance_max" msgid="5806278962376556491">"Show at the top of the notifications list, peek on to the screen and allow sound"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"More settings"</string>
     <string name="notification_done" msgid="5279426047273930175">"Finished"</string>
     <string name="color_and_appearance" msgid="1254323855964993144">"Colour and appearance"</string>
@@ -476,7 +489,7 @@
     <string name="use_dark_theme" msgid="2900938704964299312">"Use dark theme for Android OS"</string>
     <string name="adjust_tint" msgid="3398569573231409878">"Adjust tint"</string>
     <string name="adjust_brightness" msgid="980039329808178246">"Adjust brightness"</string>
-    <string name="night_mode_disclaimer" msgid="3297928749219711334">"The dark theme is applied to core areas of Android OS that are normally displayed in a light theme, such as Settings and notifications."</string>
+    <string name="night_mode_disclaimer" msgid="598914896926759578">"The dark theme is applied to core areas of Android OS that are normally displayed in a light theme, such as Settings."</string>
     <string name="color_apply" msgid="9212602012641034283">"Apply"</string>
     <string name="color_revert_title" msgid="4746666545480534663">"Confirm Settings"</string>
     <string name="color_revert_message" msgid="9116001069397996691">"Some colour settings can make this device unusable. Click OK to confirm these colour settings, otherwise these settings will reset after 10 seconds."</string>
@@ -535,4 +548,10 @@
     <item msgid="2139628951880142927">"Show percentage when charging (default)"</item>
     <item msgid="3327323682209964956">"Don\'t show this icon"</item>
   </string-array>
+    <string name="other" msgid="4060683095962566764">"Other"</string>
+    <string name="accessibility_divider" msgid="5903423481953635044">"Split screen divider"</string>
+    <string name="accessibility_action_divider_move_down" msgid="704893304141890042">"Move down"</string>
+    <string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"Move up"</string>
+    <string name="accessibility_action_divider_move_left" msgid="9218189832115847253">"Move to the left"</string>
+    <string name="accessibility_action_divider_move_right" msgid="4671522715182567972">"Move to the right"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-en-rIN/strings_tv.xml b/packages/SystemUI/res/values-en-rIN/strings_tv.xml
new file mode 100644
index 0000000..6f33655
--- /dev/null
+++ b/packages/SystemUI/res/values-en-rIN/strings_tv.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.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="pip_close" msgid="3480680679023423574">"Close PIP"</string>
+    <string name="pip_fullscreen" msgid="8604643018538487816">"Full screen"</string>
+    <string name="pip_play" msgid="674145557658227044">"Play"</string>
+    <string name="pip_pause" msgid="8412075640017218862">"Pause"</string>
+    <string name="pip_hold_home" msgid="340086535668778109">"Hold "<b>"HOME"</b>" to control PIP"</string>
+    <string name="pip_onboarding_description" msgid="2627737116380318292">"Press and hold the HOME\nbutton to control PIP"</string>
+    <string name="pip_onboarding_button" msgid="3957426748484904611">"Understood"</string>
+</resources>
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index 53386ed..34e5a7e 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -73,7 +73,8 @@
     <string name="screenshot_saved_title" msgid="6461865960961414961">"Se guardó la captura de pantalla."</string>
     <string name="screenshot_saved_text" msgid="1152839647677558815">"Toca para ver tu captura de pantalla."</string>
     <string name="screenshot_failed_title" msgid="705781116746922771">"No se pudo guardar la captura de pantalla."</string>
-    <string name="screenshot_failed_text" msgid="1260203058661337274">"Error de captura por almacenamiento limitado o porque la aplicación u organización no lo permiten."</string>
+    <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"No se puede guardar la captura de pantalla debido al almacenamiento limitado."</string>
+    <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"La app o tu organización no permiten las capturas de pantalla."</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"Opciones de transferencia de archivos por USB"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Activar como reproductor de medios (MTP)"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"Activar como cámara (PTP)"</string>
@@ -206,6 +207,7 @@
     <string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"Más tiempo"</string>
     <string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"Menos tiempo"</string>
     <string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"Linterna desactivada"</string>
+    <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"La linterna no está disponible."</string>
     <string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"Linterna activada"</string>
     <string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"Linterna desactivada"</string>
     <string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"Linterna activada"</string>
@@ -218,6 +220,10 @@
     <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"Modo de trabajo activado"</string>
     <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"Se desactivó el modo de trabajo."</string>
     <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"Se activó el modo de trabajo."</string>
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_off (650231949881093289) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_on (4218725402373934151) -->
+    <skip />
     <string name="accessibility_brightness" msgid="8003681285547803095">"Brillo de pantalla"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"Datos 2G-3G pausados"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"Datos 4G pausados"</string>
@@ -304,6 +310,8 @@
     <string name="recents_launch_disabled_message" msgid="1624523193008871793">"<xliff:g id="APP">%s</xliff:g> está inhabilitada en modo seguro."</string>
     <string name="recents_history_button_label" msgid="5153358867807604821">"Historial"</string>
     <string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"Borrar"</string>
+    <string name="recents_drag_non_dockable_task_message" msgid="2935843902795166158">"Esta app no es compatible con el modo multiventana"</string>
+    <string name="recents_launch_non_dockable_task_label" msgid="7862379814938391888">"La app no es compatible con el modo multiventana"</string>
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"División horizontal"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"División vertical"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"División personalizada"</string>
@@ -451,18 +459,23 @@
     <string name="enable_bluetooth_title" msgid="5027037706500635269">"¿Activar Bluetooth?"</string>
     <string name="enable_bluetooth_message" msgid="9106595990708985385">"Para conectar el teclado con la tablet, primero debes activar Bluetooth."</string>
     <string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"Activar"</string>
-    <string name="apply_to_topic" msgid="3641403489318659666">"Aplicar a las notificaciones de <xliff:g id="TOPIC_NAME">%1$s</xliff:g>"</string>
-    <string name="apply_to_app" msgid="363016783939815960">"Aplicar a todas las notificaciones de esta app"</string>
+    <string name="show_silently" msgid="6841966539811264192">"Mostrar notificaciones de manera silenciosa"</string>
+    <string name="block" msgid="2734508760962682611">"Bloquear todas las notificaciones"</string>
+    <string name="do_not_silence" msgid="6878060322594892441">"No silenciar"</string>
+    <string name="do_not_silence_block" msgid="4070647971382232311">"No silenciar ni bloquear"</string>
+    <string name="tuner_full_importance_settings" msgid="8103289238676424226">"Mostrar configuración de importancia"</string>
     <string name="blocked_importance" msgid="5198578988978234161">"Bloqueada"</string>
+    <string name="min_importance" msgid="1901894910809414782">"Importancia mínima"</string>
     <string name="low_importance" msgid="4109929986107147930">"Poca importancia"</string>
     <string name="default_importance" msgid="8192107689995742653">"Importancia normal"</string>
     <string name="high_importance" msgid="1527066195614050263">"Importancia alta"</string>
     <string name="max_importance" msgid="5089005872719563894">"Urgente"</string>
     <string name="notification_importance_blocked" msgid="2397192642657872872">"No mostrar nunca estas notificaciones"</string>
-    <string name="notification_importance_low" msgid="4383563267370859725">"Mostrar en la parte inferior de la lista de notificaciones sin emitir sonido"</string>
-    <string name="notification_importance_default" msgid="4926529615920610817">"Mostrar estas notificaciones de manera silenciosa"</string>
-    <string name="notification_importance_high" msgid="3222680136612408223">"Mostrar en la parte superior de la lista de notificaciones y emitir sonido"</string>
-    <string name="notification_importance_max" msgid="5236987171904756134">"Mostrar en la pantalla y emitir sonido"</string>
+    <string name="notification_importance_min" msgid="1938190340516905748">"Mostrar en la parte inferior de la lista de notificaciones sin emitir sonido"</string>
+    <string name="notification_importance_low" msgid="3657252049508213048">"Mostrar estas notificaciones de manera silenciosa"</string>
+    <string name="notification_importance_default" msgid="4466466472622442175">"Permitir que estas notificaciones emitan sonidos"</string>
+    <string name="notification_importance_high" msgid="2135428926525093825">"Ver en la pantalla y permitir sonidos"</string>
+    <string name="notification_importance_max" msgid="5806278962376556491">"Mostrar en la parte superior de la lista de notificaciones, ver en la pantalla y permitir sonidos"</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="color_and_appearance" msgid="1254323855964993144">"Color y apariencia"</string>
@@ -476,7 +489,7 @@
     <string name="use_dark_theme" msgid="2900938704964299312">"Usar tema oscuro para el SO Android"</string>
     <string name="adjust_tint" msgid="3398569573231409878">"Ajustar tinte"</string>
     <string name="adjust_brightness" msgid="980039329808178246">"Ajustar brillo"</string>
-    <string name="night_mode_disclaimer" msgid="3297928749219711334">"El tema oscuro se aplica en las áreas principales del sistema operativo Android que suelen mostrarse con un tema claro, como la Configuración y las notificaciones."</string>
+    <string name="night_mode_disclaimer" msgid="598914896926759578">"El tema oscuro se aplica en las áreas principales del SO Android que suelen mostrarse con un tema claro, como Configuración."</string>
     <string name="color_apply" msgid="9212602012641034283">"Aplicar"</string>
     <string name="color_revert_title" msgid="4746666545480534663">"Confirmar la configuración"</string>
     <string name="color_revert_message" msgid="9116001069397996691">"Algunas opciones de configuración de color pueden provocar que el dispositivo quede inutilizable. Haz clic en Aceptar para confirmar estos parámetros de color. De lo contrario, la configuración se restablecerá en diez segundos."</string>
@@ -535,4 +548,10 @@
     <item msgid="2139628951880142927">"Mostrar el porcentaje durante la carga (predeterminado)"</item>
     <item msgid="3327323682209964956">"No mostrar este ícono"</item>
   </string-array>
+    <string name="other" msgid="4060683095962566764">"Otros"</string>
+    <string name="accessibility_divider" msgid="5903423481953635044">"Divisor de pantalla dividida"</string>
+    <string name="accessibility_action_divider_move_down" msgid="704893304141890042">"Mover hacia abajo"</string>
+    <string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"Mover hacia arriba"</string>
+    <string name="accessibility_action_divider_move_left" msgid="9218189832115847253">"Mover a la izquierda"</string>
+    <string name="accessibility_action_divider_move_right" msgid="4671522715182567972">"Mover a la derecha"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-es-rUS/strings_tv.xml b/packages/SystemUI/res/values-es-rUS/strings_tv.xml
new file mode 100644
index 0000000..16d9f36
--- /dev/null
+++ b/packages/SystemUI/res/values-es-rUS/strings_tv.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2016, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <!-- no translation found for pip_close (3480680679023423574) -->
+    <skip />
+    <string name="pip_fullscreen" msgid="8604643018538487816">"Pantalla completa"</string>
+    <string name="pip_play" msgid="674145557658227044">"Reproducir"</string>
+    <string name="pip_pause" msgid="8412075640017218862">"Pausar"</string>
+    <!-- no translation found for pip_hold_home (340086535668778109) -->
+    <skip />
+    <!-- no translation found for pip_onboarding_description (2627737116380318292) -->
+    <skip />
+    <!-- no translation found for pip_onboarding_button (3957426748484904611) -->
+    <skip />
+</resources>
diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml
index 37689ce..2698ffc 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -73,7 +73,8 @@
     <string name="screenshot_saved_title" msgid="6461865960961414961">"Captura guardada"</string>
     <string name="screenshot_saved_text" msgid="1152839647677558815">"Toca para ver la captura de pantalla"</string>
     <string name="screenshot_failed_title" msgid="705781116746922771">"No se ha podido guardar la captura de pantalla."</string>
-    <string name="screenshot_failed_text" msgid="1260203058661337274">"Error al hacer captura por límite almacenamiento o porque aplicación u organización no lo permiten."</string>
+    <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"No se puede guardar la captura de pantalla porque no hay espacio de almacenamiento suficiente."</string>
+    <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"La aplicación o tu organización no permiten que se realicen capturas de pantalla."</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"Opciones de transferencia de archivos por USB"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Activar como reproductor de medios (MTP)"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"Activar como cámara (PTP)"</string>
@@ -206,6 +207,7 @@
     <string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"Más tiempo."</string>
     <string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"Menos tiempo."</string>
     <string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"Linterna desactivada."</string>
+    <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"La linterna no está disponible."</string>
     <string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"Linterna activada."</string>
     <string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"Linterna desactivada."</string>
     <string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"Linterna activada."</string>
@@ -218,6 +220,10 @@
     <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"Modo de trabajo activado."</string>
     <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"Modo de trabajo desactivado."</string>
     <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"Modo de trabajo activado."</string>
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_off (650231949881093289) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_on (4218725402373934151) -->
+    <skip />
     <string name="accessibility_brightness" msgid="8003681285547803095">"Brillo de la pantalla"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"Datos 2G-3G pausados"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"Datos 4G pausados"</string>
@@ -301,10 +307,11 @@
     <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"fijación de pantalla"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"buscar"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"No se ha podido iniciar <xliff:g id="APP">%s</xliff:g>."</string>
-    <!-- no translation found for recents_launch_disabled_message (1624523193008871793) -->
-    <skip />
+    <string name="recents_launch_disabled_message" msgid="1624523193008871793">"La aplicación <xliff:g id="APP">%s</xliff:g> se ha inhabilitado en modo seguro."</string>
     <string name="recents_history_button_label" msgid="5153358867807604821">"Historial"</string>
     <string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"Borrar"</string>
+    <string name="recents_drag_non_dockable_task_message" msgid="2935843902795166158">"Esta aplicación no admite el modo multiventana."</string>
+    <string name="recents_launch_non_dockable_task_label" msgid="7862379814938391888">"La aplicación no admite el modo multiventana"</string>
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"División horizontal"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"División vertical"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"División personalizada"</string>
@@ -452,18 +459,23 @@
     <string name="enable_bluetooth_title" msgid="5027037706500635269">"¿Activar Bluetooth?"</string>
     <string name="enable_bluetooth_message" msgid="9106595990708985385">"Para poder conectar tu teclado a tu tablet, debes activar el Bluetooth."</string>
     <string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"Activar"</string>
-    <string name="apply_to_topic" msgid="3641403489318659666">"Aplicar a las notificaciones de <xliff:g id="TOPIC_NAME">%1$s</xliff:g>"</string>
-    <string name="apply_to_app" msgid="363016783939815960">"Aplicar a todas las notificaciones de esta aplicación"</string>
+    <string name="show_silently" msgid="6841966539811264192">"Mostrar notificaciones de forma silenciosa"</string>
+    <string name="block" msgid="2734508760962682611">"Bloquear todas las notificaciones"</string>
+    <string name="do_not_silence" msgid="6878060322594892441">"No silenciar"</string>
+    <string name="do_not_silence_block" msgid="4070647971382232311">"No silenciar ni bloquear"</string>
+    <string name="tuner_full_importance_settings" msgid="8103289238676424226">"Mostrar ajustes de importancia por completo"</string>
     <string name="blocked_importance" msgid="5198578988978234161">"Bloqueado"</string>
+    <string name="min_importance" msgid="1901894910809414782">"Importancia mínima"</string>
     <string name="low_importance" msgid="4109929986107147930">"Poco importante"</string>
     <string name="default_importance" msgid="8192107689995742653">"Importancia normal"</string>
     <string name="high_importance" msgid="1527066195614050263">"Muy importante"</string>
     <string name="max_importance" msgid="5089005872719563894">"Urgente"</string>
     <string name="notification_importance_blocked" msgid="2397192642657872872">"No mostrar estas notificaciones"</string>
-    <string name="notification_importance_low" msgid="4383563267370859725">"Mostrar en la parte inferior de la lista de notificaciones de forma silenciosa"</string>
-    <string name="notification_importance_default" msgid="4926529615920610817">"Mostrar estas notificaciones de forma silenciosa"</string>
-    <string name="notification_importance_high" msgid="3222680136612408223">"Mostrar en la parte superior de la lista de notificaciones y emitir sonido"</string>
-    <string name="notification_importance_max" msgid="5236987171904756134">"Mostrar en la pantalla y emitir sonido"</string>
+    <string name="notification_importance_min" msgid="1938190340516905748">"Mostrar en la parte inferior de la lista de notificaciones de forma silenciosa"</string>
+    <string name="notification_importance_low" msgid="3657252049508213048">"Mostrar estas notificaciones de forma silenciosa"</string>
+    <string name="notification_importance_default" msgid="4466466472622442175">"Permitir que estas notificaciones reproduzcan sonidos"</string>
+    <string name="notification_importance_high" msgid="2135428926525093825">"Mostrar en la pantalla y permitir sonido"</string>
+    <string name="notification_importance_max" msgid="5806278962376556491">"Mostrar en la parte superior de la lista de notificaciones, mostrar en la pantalla y permitir sonido"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"Más ajustes"</string>
     <string name="notification_done" msgid="5279426047273930175">"Listo"</string>
     <string name="color_and_appearance" msgid="1254323855964993144">"Color y aspecto"</string>
@@ -477,7 +489,7 @@
     <string name="use_dark_theme" msgid="2900938704964299312">"Tema oscuro para sistema operativo Android"</string>
     <string name="adjust_tint" msgid="3398569573231409878">"Ajustar tono"</string>
     <string name="adjust_brightness" msgid="980039329808178246">"Ajustar brillo"</string>
-    <string name="night_mode_disclaimer" msgid="3297928749219711334">"El tema oscuro se aplica a las áreas principales del sistema operativo Android que normalmente se muestran con un tema claro, como la aplicación Ajustes y las notificaciones."</string>
+    <string name="night_mode_disclaimer" msgid="598914896926759578">"El tema oscuro se aplica a las áreas principales del sistema operativo Android que normalmente se muestran con un tema claro, como la aplicación Ajustes."</string>
     <string name="color_apply" msgid="9212602012641034283">"Aplicar"</string>
     <string name="color_revert_title" msgid="4746666545480534663">"Confirmar configuración"</string>
     <string name="color_revert_message" msgid="9116001069397996691">"Algunas opciones de configuración de color pueden hacer que el dispositivo no se pueda utilizar. Haz clic en Aceptar para confirmar esta configuración. Si no lo haces, se restablecerá esta configuración cuando transcurran 10 segundos."</string>
@@ -536,4 +548,10 @@
     <item msgid="2139628951880142927">"Mostrar porcentaje durante la carga (predeterminado)"</item>
     <item msgid="3327323682209964956">"No mostrar este icono"</item>
   </string-array>
+    <string name="other" msgid="4060683095962566764">"Otros"</string>
+    <string name="accessibility_divider" msgid="5903423481953635044">"Dividir la pantalla"</string>
+    <string name="accessibility_action_divider_move_down" msgid="704893304141890042">"Bajar"</string>
+    <string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"Subir"</string>
+    <string name="accessibility_action_divider_move_left" msgid="9218189832115847253">"Mover a la izquierda"</string>
+    <string name="accessibility_action_divider_move_right" msgid="4671522715182567972">"Mover a la derecha"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-es/strings_tv.xml b/packages/SystemUI/res/values-es/strings_tv.xml
new file mode 100644
index 0000000..fcc839e
--- /dev/null
+++ b/packages/SystemUI/res/values-es/strings_tv.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.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="pip_close" msgid="3480680679023423574">"Cerrar PIP"</string>
+    <string name="pip_fullscreen" msgid="8604643018538487816">"Pantalla completa"</string>
+    <string name="pip_play" msgid="674145557658227044">"Reproducir"</string>
+    <string name="pip_pause" msgid="8412075640017218862">"Pausar"</string>
+    <string name="pip_hold_home" msgid="340086535668778109"><b>"INICIO"</b>" pulsado: control PIP"</string>
+    <string name="pip_onboarding_description" msgid="2627737116380318292">"INICIO pulsado:\ncontrol PIP"</string>
+    <string name="pip_onboarding_button" msgid="3957426748484904611">"Entendido"</string>
+</resources>
diff --git a/packages/SystemUI/res/values-et-rEE/strings.xml b/packages/SystemUI/res/values-et-rEE/strings.xml
index 6ca0fcf..42d449a 100644
--- a/packages/SystemUI/res/values-et-rEE/strings.xml
+++ b/packages/SystemUI/res/values-et-rEE/strings.xml
@@ -73,7 +73,8 @@
     <string name="screenshot_saved_title" msgid="6461865960961414961">"Ekraanipilt on jäädvustatud."</string>
     <string name="screenshot_saved_text" msgid="1152839647677558815">"Puudutage kuvatõmmise vaatamiseks."</string>
     <string name="screenshot_failed_title" msgid="705781116746922771">"Kuvatõmmist ei saanud jäädvustada."</string>
-    <string name="screenshot_failed_text" msgid="1260203058661337274">"Ekraanipilti ei saa jäädvustada piiratud talletusruumi tõttu või ei luba seda rakendus/organisatsioon."</string>
+    <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Piiratud salvestusruumi tõttu ei saa ekraanipilti salvestada."</string>
+    <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Rakendus või teie organisatsioon ei luba ekraanipilte jäädvustada."</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"USB-failiedastuse valikud"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Paigalda meediumimängijana (MTP)"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"Paigalda kaamerana (PTP)"</string>
@@ -206,6 +207,7 @@
     <string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"Pikem aeg."</string>
     <string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"Lühem aeg."</string>
     <string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"Taskulamp on väljas."</string>
+    <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"Taskulamp pole saadaval."</string>
     <string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"Taskulamp on sees."</string>
     <string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"Taskulamp on välja lülitatud."</string>
     <string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"Taskulamp on sisse lülitatud."</string>
@@ -218,6 +220,10 @@
     <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"Töörežiim on sees."</string>
     <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"Töörežiim on välja lülitatud."</string>
     <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"Töörežiim on sisse lülitatud."</string>
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_off (650231949881093289) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_on (4218725402373934151) -->
+    <skip />
     <string name="accessibility_brightness" msgid="8003681285547803095">"Ekraani heledus"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"2G–3G andmekasutus on peatatud"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"4G andmekasutus on peatatud"</string>
@@ -304,6 +310,8 @@
     <string name="recents_launch_disabled_message" msgid="1624523193008871793">"Rakendus <xliff:g id="APP">%s</xliff:g> on turvarežiimis keelatud."</string>
     <string name="recents_history_button_label" msgid="5153358867807604821">"Ajalugu"</string>
     <string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"Kustuta"</string>
+    <string name="recents_drag_non_dockable_task_message" msgid="2935843902795166158">"See rakendus ei toeta mitut akent"</string>
+    <string name="recents_launch_non_dockable_task_label" msgid="7862379814938391888">"Rakendus ei toeta mitut akent"</string>
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Horisontaalne poolitamine"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Vertikaalne poolitamine"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Kohandatud poolitamine"</string>
@@ -451,18 +459,23 @@
     <string name="enable_bluetooth_title" msgid="5027037706500635269">"Kas lülitada Bluetooth sisse?"</string>
     <string name="enable_bluetooth_message" msgid="9106595990708985385">"Klaviatuuri ühendamiseks tahvelarvutiga peate esmalt Bluetoothi sisse lülitama."</string>
     <string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"Lülita sisse"</string>
-    <string name="apply_to_topic" msgid="3641403489318659666">"Rakenda teema <xliff:g id="TOPIC_NAME">%1$s</xliff:g> märguannete puhul"</string>
-    <string name="apply_to_app" msgid="363016783939815960">"Rakenda selle rakenduse kõigi märguannete puhul"</string>
+    <string name="show_silently" msgid="6841966539811264192">"Kuva märguanded vaikselt"</string>
+    <string name="block" msgid="2734508760962682611">"Blokeeri kõik märguanded"</string>
+    <string name="do_not_silence" msgid="6878060322594892441">"Ära vaigista"</string>
+    <string name="do_not_silence_block" msgid="4070647971382232311">"Ära vaigista ega blokeeri"</string>
+    <string name="tuner_full_importance_settings" msgid="8103289238676424226">"Kuva täieliku tähtsuse seaded"</string>
     <string name="blocked_importance" msgid="5198578988978234161">"Blokeeritud"</string>
+    <string name="min_importance" msgid="1901894910809414782">"Minimaalne tähtsus"</string>
     <string name="low_importance" msgid="4109929986107147930">"Madal tähtsuse tase"</string>
     <string name="default_importance" msgid="8192107689995742653">"Tavaline tähtsuse tase"</string>
     <string name="high_importance" msgid="1527066195614050263">"Kõrge tähtsuse tase"</string>
     <string name="max_importance" msgid="5089005872719563894">"Kiireloomuline tähtsuse tase"</string>
     <string name="notification_importance_blocked" msgid="2397192642657872872">"Ära kunagi näita neid märguandeid"</string>
-    <string name="notification_importance_low" msgid="4383563267370859725">"Kuva märguannete loendi allosas vaikselt"</string>
-    <string name="notification_importance_default" msgid="4926529615920610817">"Kuva need märguanded vaikselt"</string>
-    <string name="notification_importance_high" msgid="3222680136612408223">"Kuva märguannete loendi ülaosas koos heliga"</string>
-    <string name="notification_importance_max" msgid="5236987171904756134">"Kuva ekraani servas koos heliga"</string>
+    <string name="notification_importance_min" msgid="1938190340516905748">"Kuva märguannete loendi allosas vaikselt"</string>
+    <string name="notification_importance_low" msgid="3657252049508213048">"Kuva need märguanded vaikselt"</string>
+    <string name="notification_importance_default" msgid="4466466472622442175">"Luba nende märguannete puhul heli"</string>
+    <string name="notification_importance_high" msgid="2135428926525093825">"Kuva ekraani servas ja luba heli"</string>
+    <string name="notification_importance_max" msgid="5806278962376556491">"Kuva märguannete loendi ülaservas, kuva ekraani servas ja luba heli"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"Rohkem seadeid"</string>
     <string name="notification_done" msgid="5279426047273930175">"Valmis"</string>
     <string name="color_and_appearance" msgid="1254323855964993144">"Värv ja ilme"</string>
@@ -476,7 +489,7 @@
     <string name="use_dark_theme" msgid="2900938704964299312">"Kasuta Android OS-is tumedat teemat"</string>
     <string name="adjust_tint" msgid="3398569573231409878">"Reguleeri tooni"</string>
     <string name="adjust_brightness" msgid="980039329808178246">"Reguleeri heledust"</string>
-    <string name="night_mode_disclaimer" msgid="3297928749219711334">"Tume teema rakendatakse Android OS-i põhialadele, mis kuvatakse tavaliselt heleda teemaga (nt seaded ja märguanded)."</string>
+    <string name="night_mode_disclaimer" msgid="598914896926759578">"Tume teema rakendatakse Android OS-i põhialadele, mis kuvatakse tavaliselt heleda teemaga (nt seaded)."</string>
     <string name="color_apply" msgid="9212602012641034283">"Rakenda"</string>
     <string name="color_revert_title" msgid="4746666545480534663">"Seadete kinnitamine"</string>
     <string name="color_revert_message" msgid="9116001069397996691">"Mõni värviseade ei saa seadet võib-olla kasutada. Nende värviseadete kinnitamiseks klõpsake OK, muidu lähtestatakse need seaded 10 sekundi pärast."</string>
@@ -535,4 +548,10 @@
     <item msgid="2139628951880142927">"Kuva protsent laadimisel (vaikimisi)"</item>
     <item msgid="3327323682209964956">"Ära kuva seda ikooni"</item>
   </string-array>
+    <string name="other" msgid="4060683095962566764">"Muu"</string>
+    <string name="accessibility_divider" msgid="5903423481953635044">"Ekraanijagaja"</string>
+    <string name="accessibility_action_divider_move_down" msgid="704893304141890042">"Liigu alla"</string>
+    <string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"Liigu üles"</string>
+    <string name="accessibility_action_divider_move_left" msgid="9218189832115847253">"Liigu vasakule"</string>
+    <string name="accessibility_action_divider_move_right" msgid="4671522715182567972">"Liigu paremale"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-et-rEE/strings_tv.xml b/packages/SystemUI/res/values-et-rEE/strings_tv.xml
new file mode 100644
index 0000000..ae6cb30
--- /dev/null
+++ b/packages/SystemUI/res/values-et-rEE/strings_tv.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.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="pip_close" msgid="3480680679023423574">"Sule PIP"</string>
+    <string name="pip_fullscreen" msgid="8604643018538487816">"Täisekraan"</string>
+    <string name="pip_play" msgid="674145557658227044">"Esita"</string>
+    <string name="pip_pause" msgid="8412075640017218862">"Peata"</string>
+    <string name="pip_hold_home" msgid="340086535668778109">"PIP juht. hoidke all nuppu "<b>"AVAEKRAAN"</b></string>
+    <string name="pip_onboarding_description" msgid="2627737116380318292">"PIP juhtim. vajutage\npikalt nuppu AVAEKRAAN"</string>
+    <string name="pip_onboarding_button" msgid="3957426748484904611">"Selge"</string>
+</resources>
diff --git a/packages/SystemUI/res/values-eu-rES/strings.xml b/packages/SystemUI/res/values-eu-rES/strings.xml
index 88ce866..67f13cc 100644
--- a/packages/SystemUI/res/values-eu-rES/strings.xml
+++ b/packages/SystemUI/res/values-eu-rES/strings.xml
@@ -73,7 +73,8 @@
     <string name="screenshot_saved_title" msgid="6461865960961414961">"Pantaila-argazkia atera da."</string>
     <string name="screenshot_saved_text" msgid="1152839647677558815">"Pantaila-argazkia ikusteko, ukitu ezazu."</string>
     <string name="screenshot_failed_title" msgid="705781116746922771">"Ezin izan da pantaila-argazkia atera."</string>
-    <string name="screenshot_failed_text" msgid="1260203058661337274">"Ezin da atera pantaila-argazkia tokirik geratzen ez delako edo horrelakorik onartzen ez delako."</string>
+    <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Ezin da atera pantaila-argazkia ez delako tokirik geratzen."</string>
+    <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Aplikazioak edo erakundeak ez du onartzen pantaila-argazkiak ateratzea."</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"USB fitxategiak transferitzeko aukerak"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Muntatu multimedia-erreproduzigailu gisa (MTP)"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"Muntatu kamera gisa (PTP)"</string>
@@ -206,6 +207,7 @@
     <string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"Denbora gehiago."</string>
     <string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"Denbora gutxiago."</string>
     <string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"Flasha desaktibatuta dago."</string>
+    <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"Linterna ez dago erabilgarri."</string>
     <string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"Flasha aktibatuta dago."</string>
     <string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"Flasha desaktibatu egin da."</string>
     <string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"Flasha aktibatu egin da."</string>
@@ -218,6 +220,10 @@
     <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"Aktibatuta dago lan modua."</string>
     <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"Desaktibatuta dago lan modua."</string>
     <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"Aktibatuta dago lan modua."</string>
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_off (650231949881093289) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_on (4218725402373934151) -->
+    <skip />
     <string name="accessibility_brightness" msgid="8003681285547803095">"Bistaratu distira"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"2G-3G datuen erabilera eten da"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"4G datuen erabilera eten da"</string>
@@ -304,9 +310,11 @@
     <string name="recents_launch_disabled_message" msgid="1624523193008871793">"<xliff:g id="APP">%s</xliff:g> desgaituta dago modu seguruan."</string>
     <string name="recents_history_button_label" msgid="5153358867807604821">"Historia"</string>
     <string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"Garbitu"</string>
-    <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Banaketa horizontala"</string>
-    <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Banaketa bertikala"</string>
-    <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Banaketa pertsonalizatua"</string>
+    <string name="recents_drag_non_dockable_task_message" msgid="2935843902795166158">"Aplikazioak ez du onartzen leiho bat baino gehiago erabiltzea"</string>
+    <string name="recents_launch_non_dockable_task_label" msgid="7862379814938391888">"Aplikazioak ez du onartzen leiho bat baino gehiago erabiltzea"</string>
+    <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Zatitze horizontala"</string>
+    <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Zatitze bertikala"</string>
+    <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Zatitze pertsonalizatua"</string>
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Kargatuta"</string>
     <string name="expanded_header_battery_charging" msgid="205623198487189724">"Kargatzen"</string>
     <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> falta zaizkio guztiz kargatzeko"</string>
@@ -451,18 +459,23 @@
     <string name="enable_bluetooth_title" msgid="5027037706500635269">"Bluetooth eginbidea aktibatu nahi duzu?"</string>
     <string name="enable_bluetooth_message" msgid="9106595990708985385">"Teklatua tabletara konektatzeko, Bluetooth eginbidea aktibatu behar duzu."</string>
     <string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"Aktibatu"</string>
-    <string name="apply_to_topic" msgid="3641403489318659666">"Aplikatu \"<xliff:g id="TOPIC_NAME">%1$s</xliff:g>\" gaiari buruzko jakinarazpenei"</string>
-    <string name="apply_to_app" msgid="363016783939815960">"Aplikatu aplikazio honetako jakinarazpen guztiei"</string>
+    <string name="show_silently" msgid="6841966539811264192">"Erakutsi jakinarazpenak soinurik egin gabe"</string>
+    <string name="block" msgid="2734508760962682611">"Blokeatu jakinarazpen guztiak"</string>
+    <string name="do_not_silence" msgid="6878060322594892441">"Ez isilarazi"</string>
+    <string name="do_not_silence_block" msgid="4070647971382232311">"Ez isilarazi edo blokeatu"</string>
+    <string name="tuner_full_importance_settings" msgid="8103289238676424226">"Erakutsi garrantzi handiko jakinarazpenen ezarpenak"</string>
     <string name="blocked_importance" msgid="5198578988978234161">"Blokeatuta"</string>
+    <string name="min_importance" msgid="1901894910809414782">"Gutxieneko garrantzia"</string>
     <string name="low_importance" msgid="4109929986107147930">"Garrantzi txikia"</string>
     <string name="default_importance" msgid="8192107689995742653">"Garrantzi normala"</string>
     <string name="high_importance" msgid="1527066195614050263">"Garrantzi handia"</string>
     <string name="max_importance" msgid="5089005872719563894">"Premiazkoa"</string>
     <string name="notification_importance_blocked" msgid="2397192642657872872">"Ez erakutsi jakinarazpen hauek inoiz"</string>
-    <string name="notification_importance_low" msgid="4383563267370859725">"Erakutsi jakinarazpen hauek zerrendaren behealdean, baina soinurik egin gabe"</string>
-    <string name="notification_importance_default" msgid="4926529615920610817">"Erakutsi jakinarazpen hauek, baina soinurik egin gabe"</string>
-    <string name="notification_importance_high" msgid="3222680136612408223">"Erakutsi jakinarazpen hauek zerrendaren goialdean eta egin soinua"</string>
-    <string name="notification_importance_max" msgid="5236987171904756134">"Agerrarazi jakinarazpen hauek pantailan eta egin soinua"</string>
+    <string name="notification_importance_min" msgid="1938190340516905748">"Erakutsi jakinarazpen hauek zerrendaren behealdean, baina soinurik egin gabe"</string>
+    <string name="notification_importance_low" msgid="3657252049508213048">"Erakutsi jakinarazpen hauek, baina soinurik egin gabe"</string>
+    <string name="notification_importance_default" msgid="4466466472622442175">"Egin soinua jakinarazpen hauek jasotzean"</string>
+    <string name="notification_importance_high" msgid="2135428926525093825">"Agerrarazi jakinarazpen hauek pantailan eta egin soinua"</string>
+    <string name="notification_importance_max" msgid="5806278962376556491">"Erakutsi jakinarazpen hauek zerrendaren goialdean, agerrarazi pantailan eta egin soinua"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"Ezarpen gehiago"</string>
     <string name="notification_done" msgid="5279426047273930175">"Eginda"</string>
     <string name="color_and_appearance" msgid="1254323855964993144">"Kolorea eta itxura"</string>
@@ -476,7 +489,7 @@
     <string name="use_dark_theme" msgid="2900938704964299312">"Erabili gai iluna Android sistema eragilean"</string>
     <string name="adjust_tint" msgid="3398569573231409878">"Doitu kolorea"</string>
     <string name="adjust_brightness" msgid="980039329808178246">"Doitu distira"</string>
-    <string name="night_mode_disclaimer" msgid="3297928749219711334">"Gai iluna Android sistema eragileko eremu nagusietan aplikatzen da. Normalean gai argian bistaratzen dira eremu horiek, adibidez, Ezarpenak atala eta jakinarazpenak."</string>
+    <string name="night_mode_disclaimer" msgid="598914896926759578">"Gai iluna Android sistema eragileko eremu nagusietan aplikatzen da. Normalean gai argian bistaratzen dira eremu horiek, adibidez, Ezarpenak atalean."</string>
     <string name="color_apply" msgid="9212602012641034283">"Aplikatu"</string>
     <string name="color_revert_title" msgid="4746666545480534663">"Berretsi ezarpenak"</string>
     <string name="color_revert_message" msgid="9116001069397996691">"Baliteke gailua kolore-ezarpen batzuekin ezin erabili izatea. Kolore-ezarpenak berresteko, sakatu Ados. Bestela, hamar segundoren buruan berrezarriko dira ezarpenak."</string>
@@ -535,4 +548,10 @@
     <item msgid="2139628951880142927">"Erakutsi ehunekoa kargatu bitartean (balio lehenetsia)"</item>
     <item msgid="3327323682209964956">"Ez erakutsi ikonoa"</item>
   </string-array>
+    <string name="other" msgid="4060683095962566764">"Beste bat"</string>
+    <string name="accessibility_divider" msgid="5903423481953635044">"Pantaila-zatitzailea"</string>
+    <string name="accessibility_action_divider_move_down" msgid="704893304141890042">"Eraman behera"</string>
+    <string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"Eraman gora"</string>
+    <string name="accessibility_action_divider_move_left" msgid="9218189832115847253">"Eraman ezkerrera"</string>
+    <string name="accessibility_action_divider_move_right" msgid="4671522715182567972">"Eraman eskuinera"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-eu-rES/strings_tv.xml b/packages/SystemUI/res/values-eu-rES/strings_tv.xml
new file mode 100644
index 0000000..e6bbd32
--- /dev/null
+++ b/packages/SystemUI/res/values-eu-rES/strings_tv.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2016, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <!-- no translation found for pip_close (3480680679023423574) -->
+    <skip />
+    <string name="pip_fullscreen" msgid="8604643018538487816">"Pantaila osoa"</string>
+    <string name="pip_play" msgid="674145557658227044">"Erreproduzitu"</string>
+    <string name="pip_pause" msgid="8412075640017218862">"Pausatu"</string>
+    <!-- no translation found for pip_hold_home (340086535668778109) -->
+    <skip />
+    <!-- no translation found for pip_onboarding_description (2627737116380318292) -->
+    <skip />
+    <!-- no translation found for pip_onboarding_button (3957426748484904611) -->
+    <skip />
+</resources>
diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml
index 7e552ca..13c9132 100644
--- a/packages/SystemUI/res/values-fa/strings.xml
+++ b/packages/SystemUI/res/values-fa/strings.xml
@@ -73,7 +73,8 @@
     <string name="screenshot_saved_title" msgid="6461865960961414961">"عکس صفحه‌نمایش گرفته شد."</string>
     <string name="screenshot_saved_text" msgid="1152839647677558815">"برای مشاهده عکس صفحه‌نمایشتان، لمس کنید."</string>
     <string name="screenshot_failed_title" msgid="705781116746922771">"عکس صفحه‌نمایش گرفته نشد."</string>
-    <string name="screenshot_failed_text" msgid="1260203058661337274">"به دلیل فضای ذخیره‌سازی کم یا عدم اجازه برنامه یا سازمانتان، نمی‌توان از صفحه عکس گرفت."</string>
+    <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"به دلیل محدود بودن فضای ذخیره‌سازی نمی‌توانید عکس صفحه‌نمایش را ذخیره کنید."</string>
+    <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"این برنامه یا سازمان شما اجازه نمی‌دهند عکس صفحه‌نمایش بگیرید."</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"‏گزینه‌های انتقال فایل USB"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"‏نصب به‌عنوان دستگاه پخش رسانه (MTP)"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"‏تصب به‌عنوان دوربین (PTP)"</string>
@@ -206,6 +207,7 @@
     <string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"زمان بیشتر."</string>
     <string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"زمان کمتر."</string>
     <string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"چراغ قوه خاموش است."</string>
+    <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"چراغ قوه در دسترس نیست."</string>
     <string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"چراغ قوه روشن است."</string>
     <string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"چراغ قوه خاموش شد."</string>
     <string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"چراغ قوه روشن شد."</string>
@@ -218,6 +220,10 @@
     <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"حالت کار روشن."</string>
     <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"حالت کار خاموش شد."</string>
     <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"حالت کار روشن شد."</string>
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_off (650231949881093289) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_on (4218725402373934151) -->
+    <skip />
     <string name="accessibility_brightness" msgid="8003681285547803095">"روشنایی نمایشگر"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"‏داده 2G-3G موقتاً متوقف شده است"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"‏داده 4G موقتاً متوقف شده است"</string>
@@ -304,6 +310,8 @@
     <string name="recents_launch_disabled_message" msgid="1624523193008871793">"<xliff:g id="APP">%s</xliff:g> در حالت ایمن غیرفعال است."</string>
     <string name="recents_history_button_label" msgid="5153358867807604821">"سابقه"</string>
     <string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"پاک کردن"</string>
+    <string name="recents_drag_non_dockable_task_message" msgid="2935843902795166158">"این برنامه از چندپنجره پشتیبانی نمی‌کند"</string>
+    <string name="recents_launch_non_dockable_task_label" msgid="7862379814938391888">"برنامه از چندپنجره پشتیبانی نمی‌کند"</string>
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"تقسیم افقی"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"تقسیم عمودی"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"سفارشی کردن تقسیم"</string>
@@ -451,18 +459,23 @@
     <string name="enable_bluetooth_title" msgid="5027037706500635269">"بلوتوث روشن شود؟"</string>
     <string name="enable_bluetooth_message" msgid="9106595990708985385">"برای مرتبط کردن صفحه‌کلید با رایانه لوحی، ابتدا باید بلوتوث را روشن کنید."</string>
     <string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"روشن کردن"</string>
-    <string name="apply_to_topic" msgid="3641403489318659666">"اعمال بر روی اعلان‌های <xliff:g id="TOPIC_NAME">%1$s</xliff:g>"</string>
-    <string name="apply_to_app" msgid="363016783939815960">"اعمال بر روی تمام اعلان‌های این برنامه"</string>
+    <string name="show_silently" msgid="6841966539811264192">"نمایش بی‌صدای اعلان‌ها"</string>
+    <string name="block" msgid="2734508760962682611">"مسدود کردن همه اعلان‌ها"</string>
+    <string name="do_not_silence" msgid="6878060322594892441">"ساکت نشود"</string>
+    <string name="do_not_silence_block" msgid="4070647971382232311">"ساکت یا مسدود نشود"</string>
+    <string name="tuner_full_importance_settings" msgid="8103289238676424226">"نمایش تنظیمات کامل اهمیت"</string>
     <string name="blocked_importance" msgid="5198578988978234161">"مسدود شده"</string>
+    <string name="min_importance" msgid="1901894910809414782">"کمترین اهمیت"</string>
     <string name="low_importance" msgid="4109929986107147930">"اهمیت کم"</string>
     <string name="default_importance" msgid="8192107689995742653">"اهمیت معمولی"</string>
     <string name="high_importance" msgid="1527066195614050263">"اهمیت زیاد"</string>
     <string name="max_importance" msgid="5089005872719563894">"اهمیت فوری"</string>
     <string name="notification_importance_blocked" msgid="2397192642657872872">"هرگز این اعلان‌ها نشان داده نشوند"</string>
-    <string name="notification_importance_low" msgid="4383563267370859725">"بدون صدا در پایین فهرست اعلان نشان داده شود"</string>
-    <string name="notification_importance_default" msgid="4926529615920610817">"این اعلان‌ها بی‌صدا نشان داده شوند"</string>
-    <string name="notification_importance_high" msgid="3222680136612408223">"در بالای فهرست اعلان‌ها و به همراه صدا نشان داده شود"</string>
-    <string name="notification_importance_max" msgid="5236987171904756134">"در جلوی صفحه به همراه صدا نشان داده شود"</string>
+    <string name="notification_importance_min" msgid="1938190340516905748">"بدون صدا در پایین فهرست اعلان نشان داده شود"</string>
+    <string name="notification_importance_low" msgid="3657252049508213048">"این اعلان‌ها بی‌صدا نشان داده شوند"</string>
+    <string name="notification_importance_default" msgid="4466466472622442175">"به این اعلان‌ها اجازه داده شود صدادار باشند"</string>
+    <string name="notification_importance_high" msgid="2135428926525093825">"در صفحه نشان داده شوند و صدادار باشند"</string>
+    <string name="notification_importance_max" msgid="5806278962376556491">"در بالای فهرست اعلان نشان داده شوند، در صفحه نشان داده شوند و صدادار باشند"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"تنظیمات بیشتر"</string>
     <string name="notification_done" msgid="5279426047273930175">"تمام"</string>
     <string name="color_and_appearance" msgid="1254323855964993144">"رنگ و ظاهر"</string>
@@ -476,7 +489,7 @@
     <string name="use_dark_theme" msgid="2900938704964299312">"‏استفاده از زمینه تیره برای سیستم‌عامل Android"</string>
     <string name="adjust_tint" msgid="3398569573231409878">"تنظیم سایه‌رنگ"</string>
     <string name="adjust_brightness" msgid="980039329808178246">"تنظیم روشنایی"</string>
-    <string name="night_mode_disclaimer" msgid="3297928749219711334">"‏زمینه تیره بر قسمت‌های هسته‌ای سیستم‌عامل Android که به‌طور معمول با زمینه روشن نشان داده می‌شوند (مثل تنظیمات و اعلان‌ها) اعمال می‌شود."</string>
+    <string name="night_mode_disclaimer" msgid="598914896926759578">"‏زمینه تیره بر قسمت‌های اصلی سیستم‌عامل Android که به‌طور معمول با زمینه روشن نشان داده می‌شوند (مثل «تنظیمات») اعمال می‌شود."</string>
     <string name="color_apply" msgid="9212602012641034283">"اعمال‌ کردن"</string>
     <string name="color_revert_title" msgid="4746666545480534663">"تأیید تنظیمات"</string>
     <string name="color_revert_message" msgid="9116001069397996691">"بعضی از تنظیمات رنگ می‌توانند این دستگاه را غیرقابل استفاده کنند. برای تأیید این تنظیمات رنگ روی «تأیید» کلیک کنید، در غیر این صورت این تغییرات بعد از ۱۰ ثانیه بازنشانی می‌شوند."</string>
@@ -535,4 +548,10 @@
     <item msgid="2139628951880142927">"هنگام شارژ شدن درصد نشان داده شود (پیش‌فرض)"</item>
     <item msgid="3327323682209964956">"این نماد نشان داده نشود"</item>
   </string-array>
+    <string name="other" msgid="4060683095962566764">"موارد دیگر"</string>
+    <string name="accessibility_divider" msgid="5903423481953635044">"تقسیم‌کننده صفحه"</string>
+    <string name="accessibility_action_divider_move_down" msgid="704893304141890042">"انتقال به پایین"</string>
+    <string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"انتقال به بالا"</string>
+    <string name="accessibility_action_divider_move_left" msgid="9218189832115847253">"انتقال به چپ"</string>
+    <string name="accessibility_action_divider_move_right" msgid="4671522715182567972">"انتقال به راست"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-fa/strings_tv.xml b/packages/SystemUI/res/values-fa/strings_tv.xml
new file mode 100644
index 0000000..6a62f12
--- /dev/null
+++ b/packages/SystemUI/res/values-fa/strings_tv.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2016, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <!-- no translation found for pip_close (3480680679023423574) -->
+    <skip />
+    <string name="pip_fullscreen" msgid="8604643018538487816">"تمام صفحه"</string>
+    <string name="pip_play" msgid="674145557658227044">"پخش"</string>
+    <string name="pip_pause" msgid="8412075640017218862">"مکث"</string>
+    <!-- no translation found for pip_hold_home (340086535668778109) -->
+    <skip />
+    <!-- no translation found for pip_onboarding_description (2627737116380318292) -->
+    <skip />
+    <!-- no translation found for pip_onboarding_button (3957426748484904611) -->
+    <skip />
+</resources>
diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml
index 1a8d603..e5ddaad 100644
--- a/packages/SystemUI/res/values-fi/strings.xml
+++ b/packages/SystemUI/res/values-fi/strings.xml
@@ -73,7 +73,8 @@
     <string name="screenshot_saved_title" msgid="6461865960961414961">"Kuvakaappaus tallennettu"</string>
     <string name="screenshot_saved_text" msgid="1152839647677558815">"Katso kuvakaappaus koskettamalla."</string>
     <string name="screenshot_failed_title" msgid="705781116746922771">"Kuvakaappausta ei voitu tallentaa"</string>
-    <string name="screenshot_failed_text" msgid="1260203058661337274">"Kuvakaappaus ei onnistu, koska tila ei riitä tai koska sovellus tai organisaatiosi ei salli sitä."</string>
+    <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Kuvakaappauksen tallentaminen epäonnistui, sillä tallennustilaa ei ole riittävästi."</string>
+    <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Sovellus tai organisaatiosi ei salli kuvakaappauksien tallentamista."</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"USB-tiedostonsiirtoasetukset"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Käytä mediasoittimena (MTP)"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"Käytä kamerana (PTP)"</string>
@@ -206,6 +207,7 @@
     <string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"Lisää aikaa."</string>
     <string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"Vähennä aikaa."</string>
     <string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"Taskulamppu on pois päältä."</string>
+    <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"Taskulamppu ei ole käytettävissä."</string>
     <string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"Taskulamppu on päällä."</string>
     <string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"Taskulamppu poistettiin käytöstä."</string>
     <string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"Taskulamppu otettiin käyttöön."</string>
@@ -218,6 +220,10 @@
     <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"Työtila on käytössä."</string>
     <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"Työtila poistettiin käytöstä."</string>
     <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"Työtila otettiin käyttöön."</string>
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_off (650231949881093289) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_on (4218725402373934151) -->
+    <skip />
     <string name="accessibility_brightness" msgid="8003681285547803095">"Näytön kirkkaus"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"2G–3G-tiedonsiirto keskeytettiin"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"4G-tiedonsiirto keskeytettiin"</string>
@@ -304,6 +310,8 @@
     <string name="recents_launch_disabled_message" msgid="1624523193008871793">"<xliff:g id="APP">%s</xliff:g> on poistettu käytöstä vikasietotilassa."</string>
     <string name="recents_history_button_label" msgid="5153358867807604821">"Historia"</string>
     <string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"Tyhjennä"</string>
+    <string name="recents_drag_non_dockable_task_message" msgid="2935843902795166158">"Tämä sovellus ei tue usean ikkunan tilaa."</string>
+    <string name="recents_launch_non_dockable_task_label" msgid="7862379814938391888">"Sovellus ei tue usean ikkunan tilaa."</string>
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Vaakasuuntainen jako"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Pystysuuntainen jako"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Muokattu jako"</string>
@@ -451,18 +459,23 @@
     <string name="enable_bluetooth_title" msgid="5027037706500635269">"Otetaanko Bluetooth käyttöön?"</string>
     <string name="enable_bluetooth_message" msgid="9106595990708985385">"Jotta voit yhdistää näppäimistön tablettiisi, sinun on ensin otettava Bluetooth käyttöön."</string>
     <string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"Ota käyttöön"</string>
-    <string name="apply_to_topic" msgid="3641403489318659666">"Sovella aiheen <xliff:g id="TOPIC_NAME">%1$s</xliff:g> ilmoituksiin"</string>
-    <string name="apply_to_app" msgid="363016783939815960">"Sovella kaikkiin tämän sovelluksen ilmoituksiin"</string>
+    <string name="show_silently" msgid="6841966539811264192">"Näytä ilmoitukset hiljennettyinä"</string>
+    <string name="block" msgid="2734508760962682611">"Estä kaikki ilmoitukset"</string>
+    <string name="do_not_silence" msgid="6878060322594892441">"Älä hiljennä"</string>
+    <string name="do_not_silence_block" msgid="4070647971382232311">"Älä hiljennä tai estä"</string>
+    <string name="tuner_full_importance_settings" msgid="8103289238676424226">"Näytä kaikki tärkeysasetukset"</string>
     <string name="blocked_importance" msgid="5198578988978234161">"Estetyt"</string>
+    <string name="min_importance" msgid="1901894910809414782">"Pienin tärkeys"</string>
     <string name="low_importance" msgid="4109929986107147930">"Ei kovin tärkeä"</string>
     <string name="default_importance" msgid="8192107689995742653">"Tärkeä"</string>
     <string name="high_importance" msgid="1527066195614050263">"Hyvin tärkeä"</string>
     <string name="max_importance" msgid="5089005872719563894">"Kiireellinen"</string>
     <string name="notification_importance_blocked" msgid="2397192642657872872">"Älä koskaan näytä näitä ilmoituksia"</string>
-    <string name="notification_importance_low" msgid="4383563267370859725">"Näytä huomaamattomasti ilmoitusluettelon alaosassa"</string>
-    <string name="notification_importance_default" msgid="4926529615920610817">"Näytä nämä ilmoitukset huomaamattomasti"</string>
-    <string name="notification_importance_high" msgid="3222680136612408223">"Näytä ilmoitukset luettelon kärjessä ja toista merkkiääni"</string>
-    <string name="notification_importance_max" msgid="5236987171904756134">"Näytä ilmoitus näytöllä ja toista äänimerkki"</string>
+    <string name="notification_importance_min" msgid="1938190340516905748">"Hiljennä ilmoitukset ja näytä ne ilmoitusluettelon alaosassa."</string>
+    <string name="notification_importance_low" msgid="3657252049508213048">"Näytä nämä ilmoitukset hiljennettyinä."</string>
+    <string name="notification_importance_default" msgid="4466466472622442175">"Salli näiden ilmoitusten äänet."</string>
+    <string name="notification_importance_high" msgid="2135428926525093825">"Näytä ilmoitukset näytöllä ja salli niiden äänet."</string>
+    <string name="notification_importance_max" msgid="5806278962376556491">"Näytä ilmoitukset näytöllä ja ilmoitusluettelon yläosassa ja salli niiden äänet."</string>
     <string name="notification_more_settings" msgid="816306283396553571">"Lisäasetukset"</string>
     <string name="notification_done" msgid="5279426047273930175">"Valmis"</string>
     <string name="color_and_appearance" msgid="1254323855964993144">"Väri ja ulkoasu"</string>
@@ -476,7 +489,7 @@
     <string name="use_dark_theme" msgid="2900938704964299312">"Käytä tummaa teemaa käyttöjärjestelmässä"</string>
     <string name="adjust_tint" msgid="3398569573231409878">"Säädä sävytystä"</string>
     <string name="adjust_brightness" msgid="980039329808178246">"Säädä kirkkautta"</string>
-    <string name="night_mode_disclaimer" msgid="3297928749219711334">"Tummaa teemaa käytetään Android-käyttöjärjestelmän ydinosissa, kuten Asetuksissa ja ilmoituksissa, joissa käytetään tavallisesti vaaleaa teemaa."</string>
+    <string name="night_mode_disclaimer" msgid="598914896926759578">"Tumma teema tulee käyttöön Android-käyttöjärjestelmän ydinosissa, kuten Asetuksissa, joissa käytetään tavallisesti vaaleaa teemaa."</string>
     <string name="color_apply" msgid="9212602012641034283">"Käytä"</string>
     <string name="color_revert_title" msgid="4746666545480534663">"Vahvista asetukset"</string>
     <string name="color_revert_message" msgid="9116001069397996691">"Jotkin väriasetukset voivat häiritä laitteen käyttöä. Vahvista uudet väriasetukset valitsemalla OK. Muussa tapauksessa aiemmat asetukset palautetaan 10 sekunnin kuluttua."</string>
@@ -535,4 +548,10 @@
     <item msgid="2139628951880142927">"Näytä prosenttiluku latauksen aikana (oletus)"</item>
     <item msgid="3327323682209964956">"Älä näytä tätä kuvaketta"</item>
   </string-array>
+    <string name="other" msgid="4060683095962566764">"Muu"</string>
+    <string name="accessibility_divider" msgid="5903423481953635044">"Näytön jakaja"</string>
+    <string name="accessibility_action_divider_move_down" msgid="704893304141890042">"Siirrä alaspäin"</string>
+    <string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"Siirrä ylöspäin"</string>
+    <string name="accessibility_action_divider_move_left" msgid="9218189832115847253">"Siirrä vasemmalle"</string>
+    <string name="accessibility_action_divider_move_right" msgid="4671522715182567972">"Siirrä oikealle"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-fi/strings_tv.xml b/packages/SystemUI/res/values-fi/strings_tv.xml
new file mode 100644
index 0000000..c19894f
--- /dev/null
+++ b/packages/SystemUI/res/values-fi/strings_tv.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2016, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <!-- no translation found for pip_close (3480680679023423574) -->
+    <skip />
+    <string name="pip_fullscreen" msgid="8604643018538487816">"Koko näyttö"</string>
+    <string name="pip_play" msgid="674145557658227044">"Toista"</string>
+    <string name="pip_pause" msgid="8412075640017218862">"Keskeytä"</string>
+    <!-- no translation found for pip_hold_home (340086535668778109) -->
+    <skip />
+    <!-- no translation found for pip_onboarding_description (2627737116380318292) -->
+    <skip />
+    <!-- no translation found for pip_onboarding_button (3957426748484904611) -->
+    <skip />
+</resources>
diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml
index 5a907a4..8ad463b 100644
--- a/packages/SystemUI/res/values-fr-rCA/strings.xml
+++ b/packages/SystemUI/res/values-fr-rCA/strings.xml
@@ -73,7 +73,8 @@
     <string name="screenshot_saved_title" msgid="6461865960961414961">"Capture d\'écran réussie"</string>
     <string name="screenshot_saved_text" msgid="1152839647677558815">"Appuyez pour afficher votre capture d\'écran."</string>
     <string name="screenshot_failed_title" msgid="705781116746922771">"Impossible de réaliser une capture d\'écran"</string>
-    <string name="screenshot_failed_text" msgid="1260203058661337274">"Imposs. prendre saisie d\'écran : espace stock. limité, ou l\'appli ou votre organisation l\'interdit."</string>
+    <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Impossible d\'enregistrer la saisie d\'écran, car l\'espace de stockage est limité."</string>
+    <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"L\'application ou votre organisation n\'autorise pas les saisies d\'écran."</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"Options transfert fichiers USB"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Installer comme un lecteur multimédia (MTP)"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"Installer comme un appareil photo (PTP)"</string>
@@ -206,6 +207,7 @@
     <string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"Plus longtemps"</string>
     <string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"Moins longtemps."</string>
     <string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"Lampe de poche désactivée."</string>
+    <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"Lampe de poche indisponible."</string>
     <string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"Lampe de poche activée."</string>
     <string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"Lampe de poche désactivée."</string>
     <string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"Lampe de poche activée."</string>
@@ -218,6 +220,10 @@
     <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"Mode Travail activé."</string>
     <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"Le mode Travail est désactivé."</string>
     <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"Le mode Travail est activé."</string>
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_off (650231949881093289) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_on (4218725402373934151) -->
+    <skip />
     <string name="accessibility_brightness" msgid="8003681285547803095">"Luminosité de l\'écran"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"Données 2G/3G désactivées"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"Données 4G désactivées"</string>
@@ -304,6 +310,8 @@
     <string name="recents_launch_disabled_message" msgid="1624523193008871793">"<xliff:g id="APP">%s</xliff:g> est désactivée en mode sécurisé."</string>
     <string name="recents_history_button_label" msgid="5153358867807604821">"Historique"</string>
     <string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"Effacer"</string>
+    <string name="recents_drag_non_dockable_task_message" msgid="2935843902795166158">"Cette application ne prend pas en charge le mode multifenêtre"</string>
+    <string name="recents_launch_non_dockable_task_label" msgid="7862379814938391888">"L\'application ne prend pas en charge le mode multifenêtre"</string>
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Séparation horizontale"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Séparation verticale"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Séparation personnalisée"</string>
@@ -451,18 +459,23 @@
     <string name="enable_bluetooth_title" msgid="5027037706500635269">"Activer Bluetooth?"</string>
     <string name="enable_bluetooth_message" msgid="9106595990708985385">"Pour connecter votre clavier à votre tablette, vous devez d\'abord activer la connectivité Bluetooth."</string>
     <string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"Activer"</string>
-    <string name="apply_to_topic" msgid="3641403489318659666">"Appliquer à <xliff:g id="TOPIC_NAME">%1$s</xliff:g> notifications"</string>
-    <string name="apply_to_app" msgid="363016783939815960">"Appliquer à toutes les notifications de cette application"</string>
+    <string name="show_silently" msgid="6841966539811264192">"Afficher les notifications en mode silencieux"</string>
+    <string name="block" msgid="2734508760962682611">"Bloquer toutes les notifications"</string>
+    <string name="do_not_silence" msgid="6878060322594892441">"Ne pas activer le mode silencieux"</string>
+    <string name="do_not_silence_block" msgid="4070647971382232311">"Ne pas activer le mode silencieux ni bloquer"</string>
+    <string name="tuner_full_importance_settings" msgid="8103289238676424226">"Afficher les paramètres d\'importance complets"</string>
     <string name="blocked_importance" msgid="5198578988978234161">"Bloquée"</string>
+    <string name="min_importance" msgid="1901894910809414782">"Importance minimale"</string>
     <string name="low_importance" msgid="4109929986107147930">"Importance faible"</string>
     <string name="default_importance" msgid="8192107689995742653">"Importance normale"</string>
     <string name="high_importance" msgid="1527066195614050263">"Importance élevée"</string>
     <string name="max_importance" msgid="5089005872719563894">"Importance urgente"</string>
     <string name="notification_importance_blocked" msgid="2397192642657872872">"Ne jamais afficher ces notifications"</string>
-    <string name="notification_importance_low" msgid="4383563267370859725">"Afficher en mode silencieux au bas de la liste de notifications"</string>
-    <string name="notification_importance_default" msgid="4926529615920610817">"Afficher ces notifications en mode silencieux"</string>
-    <string name="notification_importance_high" msgid="3222680136612408223">"Afficher en haut de la liste des notifications et émettre un son"</string>
-    <string name="notification_importance_max" msgid="5236987171904756134">"Afficher sur l\'écran et émettre un son"</string>
+    <string name="notification_importance_min" msgid="1938190340516905748">"Afficher en mode silencieux au bas de la liste de notifications"</string>
+    <string name="notification_importance_low" msgid="3657252049508213048">"Afficher ces notifications en mode silencieux"</string>
+    <string name="notification_importance_default" msgid="4466466472622442175">"Autoriser ces notifications à émettre des sons"</string>
+    <string name="notification_importance_high" msgid="2135428926525093825">"Afficher sur l\'écran et émettre un son"</string>
+    <string name="notification_importance_max" msgid="5806278962376556491">"Afficher en haut de la liste des notifications, afficher sur l\'écran et émettre un son"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"Plus de paramètres"</string>
     <string name="notification_done" msgid="5279426047273930175">"Terminé"</string>
     <string name="color_and_appearance" msgid="1254323855964993144">"Couleur et apparence"</string>
@@ -476,7 +489,7 @@
     <string name="use_dark_theme" msgid="2900938704964299312">"Utiliser thème foncé pour Android"</string>
     <string name="adjust_tint" msgid="3398569573231409878">"Ajuster la coloration"</string>
     <string name="adjust_brightness" msgid="980039329808178246">"Régler la luminosité"</string>
-    <string name="night_mode_disclaimer" msgid="3297928749219711334">"Le thème foncé est appliqué à des zones essentielles de la plateforme Android qui sont habituellement affichées dans un thème clair, comme les paramètres et les notifications."</string>
+    <string name="night_mode_disclaimer" msgid="598914896926759578">"Le thème foncé est appliqué à des zones essentielles de la plateforme Android qui sont habituellement affichées dans un thème clair, comme les paramètres."</string>
     <string name="color_apply" msgid="9212602012641034283">"Appliquer"</string>
     <string name="color_revert_title" msgid="4746666545480534663">"Confirmer les paramètres"</string>
     <string name="color_revert_message" msgid="9116001069397996691">"Certains paramètres de couleurs peuvent rendre cet appareil inutilisable. Cliquez sur « OK » pour valider ces paramètres, sinon ils seront réinitialisés après 10 secondes."</string>
@@ -535,4 +548,10 @@
     <item msgid="2139628951880142927">"Montrer le pourcentage durant la charge (par défaut)"</item>
     <item msgid="3327323682209964956">"Ne pas afficher cette icône"</item>
   </string-array>
+    <string name="other" msgid="4060683095962566764">"Autre"</string>
+    <string name="accessibility_divider" msgid="5903423481953635044">"Séparateur d\'écran partagé"</string>
+    <string name="accessibility_action_divider_move_down" msgid="704893304141890042">"Déplacer vers le bas"</string>
+    <string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"Déplacer vers le haut"</string>
+    <string name="accessibility_action_divider_move_left" msgid="9218189832115847253">"Déplacer vers la gauche"</string>
+    <string name="accessibility_action_divider_move_right" msgid="4671522715182567972">"Déplacer vers la droite"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-fr-rCA/strings_tv.xml b/packages/SystemUI/res/values-fr-rCA/strings_tv.xml
new file mode 100644
index 0000000..9165632
--- /dev/null
+++ b/packages/SystemUI/res/values-fr-rCA/strings_tv.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2016, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <!-- no translation found for pip_close (3480680679023423574) -->
+    <skip />
+    <string name="pip_fullscreen" msgid="8604643018538487816">"Plein écran"</string>
+    <string name="pip_play" msgid="674145557658227044">"Lecture"</string>
+    <string name="pip_pause" msgid="8412075640017218862">"Interrompre"</string>
+    <!-- no translation found for pip_hold_home (340086535668778109) -->
+    <skip />
+    <!-- no translation found for pip_onboarding_description (2627737116380318292) -->
+    <skip />
+    <!-- no translation found for pip_onboarding_button (3957426748484904611) -->
+    <skip />
+</resources>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index 0da6f14..b520a88 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -73,7 +73,8 @@
     <string name="screenshot_saved_title" msgid="6461865960961414961">"Capture d\'écran réussie"</string>
     <string name="screenshot_saved_text" msgid="1152839647677558815">"Appuyez pour afficher votre capture d\'écran."</string>
     <string name="screenshot_failed_title" msgid="705781116746922771">"Impossible de réaliser une capture d\'écran"</string>
-    <string name="screenshot_failed_text" msgid="1260203058661337274">"Capture d\'écran imposs., car espace stockage limité, ou appli ou entreprise ne vous y autorise pas."</string>
+    <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Impossible d\'enregistrer la capture d\'écran, car l\'espace de stockage est limité."</string>
+    <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Les captures d\'écran ne sont pas autorisées par l\'application ou par votre organisation."</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"Options transfert fichiers USB"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Installer en tant que lecteur multimédia (MTP)"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"Installer en tant qu\'appareil photo (PTP)"</string>
@@ -206,6 +207,7 @@
     <string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"Plus longtemps"</string>
     <string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"Moins longtemps"</string>
     <string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"Lampe de poche désactivée."</string>
+    <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"Lampe de poche indisponible."</string>
     <string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"Lampe de poche activée."</string>
     <string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"Lampe de poche désactivée."</string>
     <string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"Lampe de poche activée."</string>
@@ -218,6 +220,10 @@
     <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"Mode Travail activé"</string>
     <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"Le mode Travail est désactivé."</string>
     <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"Le mode Travail est activé."</string>
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_off (650231949881093289) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_on (4218725402373934151) -->
+    <skip />
     <string name="accessibility_brightness" msgid="8003681285547803095">"Luminosité de l\'affichage"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"Données 2G-3G désactivées"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"Données 4G désactivées"</string>
@@ -304,6 +310,8 @@
     <string name="recents_launch_disabled_message" msgid="1624523193008871793">"L\'application <xliff:g id="APP">%s</xliff:g> est désactivée en mode sécurisé."</string>
     <string name="recents_history_button_label" msgid="5153358867807604821">"Historique"</string>
     <string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"Effacer"</string>
+    <string name="recents_drag_non_dockable_task_message" msgid="2935843902795166158">"Application incompatible avec le mode multifenêtre."</string>
+    <string name="recents_launch_non_dockable_task_label" msgid="7862379814938391888">"Application incompatible avec le mode multifenêtre"</string>
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Séparation horizontale"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Séparation verticale"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Séparation personnalisée"</string>
@@ -451,18 +459,23 @@
     <string name="enable_bluetooth_title" msgid="5027037706500635269">"Activer le Bluetooth ?"</string>
     <string name="enable_bluetooth_message" msgid="9106595990708985385">"Pour connecter un clavier à votre tablette, vous devez avoir activé le Bluetooth."</string>
     <string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"Activer"</string>
-    <string name="apply_to_topic" msgid="3641403489318659666">"Appliquer aux notifications relatives au sujet \"<xliff:g id="TOPIC_NAME">%1$s</xliff:g>\""</string>
-    <string name="apply_to_app" msgid="363016783939815960">"Appliquer à toutes les notifications de cette application"</string>
+    <string name="show_silently" msgid="6841966539811264192">"Afficher les notifications en mode silencieux"</string>
+    <string name="block" msgid="2734508760962682611">"Bloquer toutes les notifications"</string>
+    <string name="do_not_silence" msgid="6878060322594892441">"Ne pas activer le mode silencieux"</string>
+    <string name="do_not_silence_block" msgid="4070647971382232311">"Ne pas activer le mode silencieux ni bloquer"</string>
+    <string name="tuner_full_importance_settings" msgid="8103289238676424226">"Afficher les paramètres d\'importance complets"</string>
     <string name="blocked_importance" msgid="5198578988978234161">"Bloquées"</string>
+    <string name="min_importance" msgid="1901894910809414782">"Importance minimale"</string>
     <string name="low_importance" msgid="4109929986107147930">"Importance faible"</string>
     <string name="default_importance" msgid="8192107689995742653">"Importance normale"</string>
     <string name="high_importance" msgid="1527066195614050263">"Importance élevée"</string>
     <string name="max_importance" msgid="5089005872719563894">"Urgent"</string>
     <string name="notification_importance_blocked" msgid="2397192642657872872">"Ne jamais afficher ces notifications"</string>
-    <string name="notification_importance_low" msgid="4383563267370859725">"Afficher au bas de la liste des notifications en mode silencieux"</string>
-    <string name="notification_importance_default" msgid="4926529615920610817">"Afficher ces notifications en mode silencieux"</string>
-    <string name="notification_importance_high" msgid="3222680136612408223">"Afficher en haut de la liste des notifications et émettre un son"</string>
-    <string name="notification_importance_max" msgid="5236987171904756134">"Afficher sur l\'écran et émettre un son"</string>
+    <string name="notification_importance_min" msgid="1938190340516905748">"Afficher au bas de la liste des notifications en mode silencieux"</string>
+    <string name="notification_importance_low" msgid="3657252049508213048">"Afficher ces notifications en mode silencieux"</string>
+    <string name="notification_importance_default" msgid="4466466472622442175">"Autoriser ces notifications à émettre des sons"</string>
+    <string name="notification_importance_high" msgid="2135428926525093825">"Afficher sur l\'écran et émettre un son"</string>
+    <string name="notification_importance_max" msgid="5806278962376556491">"Afficher en haut de la liste des notifications, afficher sur l\'écran et émettre un son"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"Plus de paramètres"</string>
     <string name="notification_done" msgid="5279426047273930175">"Terminé"</string>
     <string name="color_and_appearance" msgid="1254323855964993144">"Couleur et apparence"</string>
@@ -476,7 +489,7 @@
     <string name="use_dark_theme" msgid="2900938704964299312">"Utiliser thème foncé pour plate-forme Android"</string>
     <string name="adjust_tint" msgid="3398569573231409878">"Ajuster la coloration"</string>
     <string name="adjust_brightness" msgid="980039329808178246">"Régler la luminosité"</string>
-    <string name="night_mode_disclaimer" msgid="3297928749219711334">"Le thème foncé est appliqué à des zones essentielles de la plate-forme Android qui sont habituellement affichées dans un thème clair, telles que les paramètres et les notifications."</string>
+    <string name="night_mode_disclaimer" msgid="598914896926759578">"Le thème foncé est appliqué à des zones essentielles de la plate-forme Android qui sont habituellement affichées dans un thème clair, telles que les paramètres."</string>
     <string name="color_apply" msgid="9212602012641034283">"Appliquer"</string>
     <string name="color_revert_title" msgid="4746666545480534663">"Vérifier les paramètres"</string>
     <string name="color_revert_message" msgid="9116001069397996691">"Certains paramètres de couleurs peuvent rendre cet appareil inutilisable. Cliquez sur \"OK\" pour valider ces paramètres, sans quoi ils seront réinitialisés après 10 secondes."</string>
@@ -535,4 +548,10 @@
     <item msgid="2139628951880142927">"Afficher le pourcentage lorsque l\'appareil est en charge (option par défaut)"</item>
     <item msgid="3327323682209964956">"Ne plus afficher cette icône"</item>
   </string-array>
+    <string name="other" msgid="4060683095962566764">"Autre"</string>
+    <string name="accessibility_divider" msgid="5903423481953635044">"Séparateur d\'écran partagé"</string>
+    <string name="accessibility_action_divider_move_down" msgid="704893304141890042">"Déplacer vers le bas"</string>
+    <string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"Déplacer vers le haut"</string>
+    <string name="accessibility_action_divider_move_left" msgid="9218189832115847253">"Déplacer vers la gauche"</string>
+    <string name="accessibility_action_divider_move_right" msgid="4671522715182567972">"Déplacer vers la droite"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-fr/strings_tv.xml b/packages/SystemUI/res/values-fr/strings_tv.xml
new file mode 100644
index 0000000..bc4bd22
--- /dev/null
+++ b/packages/SystemUI/res/values-fr/strings_tv.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2016, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <!-- no translation found for pip_close (3480680679023423574) -->
+    <skip />
+    <string name="pip_fullscreen" msgid="8604643018538487816">"Plein écran"</string>
+    <string name="pip_play" msgid="674145557658227044">"Lire"</string>
+    <string name="pip_pause" msgid="8412075640017218862">"Suspendre"</string>
+    <!-- no translation found for pip_hold_home (340086535668778109) -->
+    <skip />
+    <!-- no translation found for pip_onboarding_description (2627737116380318292) -->
+    <skip />
+    <!-- no translation found for pip_onboarding_button (3957426748484904611) -->
+    <skip />
+</resources>
diff --git a/packages/SystemUI/res/values-gl-rES/strings.xml b/packages/SystemUI/res/values-gl-rES/strings.xml
index 1ff6b263..1dc47d5 100644
--- a/packages/SystemUI/res/values-gl-rES/strings.xml
+++ b/packages/SystemUI/res/values-gl-rES/strings.xml
@@ -73,7 +73,8 @@
     <string name="screenshot_saved_title" msgid="6461865960961414961">"Captura de pantalla gardada."</string>
     <string name="screenshot_saved_text" msgid="1152839647677558815">"Toca para ver a captura de pantalla."</string>
     <string name="screenshot_failed_title" msgid="705781116746922771">"Non se puido facer a captura de pantalla."</string>
-    <string name="screenshot_failed_text" msgid="1260203058661337274">"Non se pode realizar a captura de pantalla porque o espazo de almacenamento está limitado ou porque non o admite a aplicación ou a túa empresa."</string>
+    <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Non se pode gardar a captura de pantalla porque o espazo de almacenamento é limitado."</string>
+    <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"A aplicación ou a túa organización non permite realizar capturas de pantalla."</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"Opcións de transferencia USB"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Inserir como reprodutor multimedia (MTP)"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"Inserir como cámara (PTP)"</string>
@@ -206,6 +207,7 @@
     <string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"Máis tempo."</string>
     <string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"Menos tempo."</string>
     <string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"Lanterna desactivada."</string>
+    <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"A lanterna non está dispoñible."</string>
     <string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"Lanterna activada."</string>
     <string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"Desactivouse a lanterna."</string>
     <string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"Activouse a lanterna."</string>
@@ -218,6 +220,10 @@
     <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"Modo de traballo activado."</string>
     <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"Desactivouse o modo de traballo."</string>
     <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"Activouse o modo de traballo."</string>
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_off (650231949881093289) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_on (4218725402373934151) -->
+    <skip />
     <string name="accessibility_brightness" msgid="8003681285547803095">"Brillo de pantalla"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"Os datos 2G-3G están en pausa"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"Os datos 4G están en pausa"</string>
@@ -304,6 +310,8 @@
     <string name="recents_launch_disabled_message" msgid="1624523193008871793">"A aplicación <xliff:g id="APP">%s</xliff:g> está desactivada no modo seguro"</string>
     <string name="recents_history_button_label" msgid="5153358867807604821">"Historial"</string>
     <string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"Borrar"</string>
+    <string name="recents_drag_non_dockable_task_message" msgid="2935843902795166158">"Esta aplicación non é compatible con varias ventás"</string>
+    <string name="recents_launch_non_dockable_task_label" msgid="7862379814938391888">"A aplicación non é compatible con varias ventás"</string>
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Dividir en horizontal"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Dividir en vertical"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Dividir de xeito personalizado"</string>
@@ -451,18 +459,23 @@
     <string name="enable_bluetooth_title" msgid="5027037706500635269">"Queres activar o Bluetooth?"</string>
     <string name="enable_bluetooth_message" msgid="9106595990708985385">"Para conectar o teu teclado co tablet, primeiro tes que activar o Bluetooth."</string>
     <string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"Activar"</string>
-    <string name="apply_to_topic" msgid="3641403489318659666">"Aplicar ás notificacións de <xliff:g id="TOPIC_NAME">%1$s</xliff:g>"</string>
-    <string name="apply_to_app" msgid="363016783939815960">"Aplicar a todas as notificacións procedentes desta aplicación"</string>
+    <string name="show_silently" msgid="6841966539811264192">"Mostrar notificacións de forma silenciosa"</string>
+    <string name="block" msgid="2734508760962682611">"Bloquear todas as notificacións"</string>
+    <string name="do_not_silence" msgid="6878060322594892441">"Non silenciar"</string>
+    <string name="do_not_silence_block" msgid="4070647971382232311">"Non silenciar nin bloquear"</string>
+    <string name="tuner_full_importance_settings" msgid="8103289238676424226">"Mostrar a configuración completa da importancia"</string>
     <string name="blocked_importance" msgid="5198578988978234161">"Bloqueada"</string>
+    <string name="min_importance" msgid="1901894910809414782">"Importancia mínima"</string>
     <string name="low_importance" msgid="4109929986107147930">"Importancia baixa"</string>
     <string name="default_importance" msgid="8192107689995742653">"Importancia normal"</string>
     <string name="high_importance" msgid="1527066195614050263">"Importancia alta"</string>
     <string name="max_importance" msgid="5089005872719563894">"Importancia urxente"</string>
     <string name="notification_importance_blocked" msgid="2397192642657872872">"Non mostrar nunca estas notificacións"</string>
-    <string name="notification_importance_low" msgid="4383563267370859725">"Mostrar de forma silenciosa na parte inferior da lista de notificacións"</string>
-    <string name="notification_importance_default" msgid="4926529615920610817">"Mostrar estas notificacións de forma silenciosa"</string>
-    <string name="notification_importance_high" msgid="3222680136612408223">"Mostrar na parte superior da lista de notificacións e emitir son"</string>
-    <string name="notification_importance_max" msgid="5236987171904756134">"Mostrar na pantalla e emitir son"</string>
+    <string name="notification_importance_min" msgid="1938190340516905748">"Mostrar de forma silenciosa na parte inferior da lista de notificacións"</string>
+    <string name="notification_importance_low" msgid="3657252049508213048">"Mostrar estas notificacións de forma silenciosa"</string>
+    <string name="notification_importance_default" msgid="4466466472622442175">"Permitir que esta notificación emita son"</string>
+    <string name="notification_importance_high" msgid="2135428926525093825">"Mostrar na pantalla e permitir que emita son"</string>
+    <string name="notification_importance_max" msgid="5806278962376556491">"Mostrar na parte superior da lista de notificacións, amosar na pantalla e permitir que emita son"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"Máis opcións"</string>
     <string name="notification_done" msgid="5279426047273930175">"Feito"</string>
     <string name="color_and_appearance" msgid="1254323855964993144">"Cor e aspecto"</string>
@@ -473,10 +486,10 @@
     <string name="turn_on_automatically" msgid="4167565356762016083">"Activar automaticamente"</string>
     <string name="turn_on_auto_summary" msgid="2190994512406701520">"Cambia ao modo nocturno segundo proceda para a localización e a hora do día"</string>
     <string name="when_night_mode_on" msgid="2969436026899172821">"Cando o modo nocturno está activado"</string>
-    <string name="use_dark_theme" msgid="2900938704964299312">"Usar tema escuro para Android SO"</string>
-    <string name="adjust_tint" msgid="3398569573231409878">"Axustar matiz"</string>
+    <string name="use_dark_theme" msgid="2900938704964299312">"Usar tema escuro para SO Android"</string>
+    <string name="adjust_tint" msgid="3398569573231409878">"Axustar ton"</string>
     <string name="adjust_brightness" msgid="980039329808178246">"Axustar brillo"</string>
-    <string name="night_mode_disclaimer" msgid="3297928749219711334">"O tema escuro aplícase ás áreas principais de Android SO que se mostran normalmente nun tema claro, como a configuración e as notificacións."</string>
+    <string name="night_mode_disclaimer" msgid="598914896926759578">"O tema escuro aplícase ás áreas principais do SO Android que se mostran normalmente nun tema claro, como a configuración."</string>
     <string name="color_apply" msgid="9212602012641034283">"Aplicar"</string>
     <string name="color_revert_title" msgid="4746666545480534663">"Confirmar configuración"</string>
     <string name="color_revert_message" msgid="9116001069397996691">"Algunhas opcións de configuración de cor poden facer que este dispositivo sexa inutilizable. Fai clic en Aceptar para confirmar esta configuración de cor; en caso contrario, a configuración restablecerase tras 10 segundos."</string>
@@ -535,4 +548,10 @@
     <item msgid="2139628951880142927">"Mostrar porcentaxe durante a carga (predeterminado)"</item>
     <item msgid="3327323682209964956">"Non mostrar esta icona"</item>
   </string-array>
+    <string name="other" msgid="4060683095962566764">"Outros"</string>
+    <string name="accessibility_divider" msgid="5903423481953635044">"Divisor de pantalla dividida"</string>
+    <string name="accessibility_action_divider_move_down" msgid="704893304141890042">"Baixar"</string>
+    <string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"Subir"</string>
+    <string name="accessibility_action_divider_move_left" msgid="9218189832115847253">"Mover á esquerda"</string>
+    <string name="accessibility_action_divider_move_right" msgid="4671522715182567972">"Mover á dereita"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-gl-rES/strings_tv.xml b/packages/SystemUI/res/values-gl-rES/strings_tv.xml
new file mode 100644
index 0000000..6aab613
--- /dev/null
+++ b/packages/SystemUI/res/values-gl-rES/strings_tv.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.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="pip_close" msgid="3480680679023423574">"Pechar PIP"</string>
+    <string name="pip_fullscreen" msgid="8604643018538487816">"Pantalla completa"</string>
+    <string name="pip_play" msgid="674145557658227044">"Reproducir"</string>
+    <string name="pip_pause" msgid="8412075640017218862">"Pausar"</string>
+    <string name="pip_hold_home" msgid="340086535668778109">"Premido "<b>"INICIO"</b>" para PIP"</string>
+    <string name="pip_onboarding_description" msgid="2627737116380318292">"Premido INICIO\npara PIP"</string>
+    <string name="pip_onboarding_button" msgid="3957426748484904611">"De acordo"</string>
+</resources>
diff --git a/packages/SystemUI/res/values-gu-rIN/strings.xml b/packages/SystemUI/res/values-gu-rIN/strings.xml
index 3891d7b..57a95cd 100644
--- a/packages/SystemUI/res/values-gu-rIN/strings.xml
+++ b/packages/SystemUI/res/values-gu-rIN/strings.xml
@@ -73,7 +73,8 @@
     <string name="screenshot_saved_title" msgid="6461865960961414961">"સ્ક્રીનશોટ કેપ્ચર કર્યો."</string>
     <string name="screenshot_saved_text" msgid="1152839647677558815">"તમારો સ્ક્રીનશોટ જોવા માટે ટચ કરો."</string>
     <string name="screenshot_failed_title" msgid="705781116746922771">"સ્ક્રીનશોટ કેપ્ચર કરી શકાયો નથી."</string>
-    <string name="screenshot_failed_text" msgid="1260203058661337274">"મર્યાદિત સંગ્રહ સ્થાનને કારણે સ્ક્રીનશોટ લઈ શકાતો નથી અથવા એપ્લિકેશન અથવા તમારા સંગઠન દ્વારા તેની મંજૂરી નથી."</string>
+    <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"મર્યાદિત સંગ્રહ સ્થાનને કારણે સ્ક્રીનશોટ સાચવી શકાતો નથી."</string>
+    <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"ઍપ્લિકેશન કે તમારી સંસ્થા દ્વારા સ્ક્રીનશોટ્સ લેવાની મંજૂરી નથી."</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"USB ફાઇલ ટ્રાન્સફર વિકલ્પો"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"મીડિયા પ્લેયર તરીકે માઉન્ટ કરો (MTP)"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"કૅમેરા તરીકે માઉન્ટ કરો (PTP)"</string>
@@ -206,6 +207,7 @@
     <string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"વધુ સમય."</string>
     <string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"ઓછો સમય."</string>
     <string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"ફ્લેશલાઇટ બંધ."</string>
+    <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"ફ્લેશલાઇટ અનુપલબ્ધ."</string>
     <string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"ફ્લેશલાઇટ ચાલુ."</string>
     <string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"ફ્લેશલાઇટ બંધ કરી."</string>
     <string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"ફ્લેશલાઇટ ચાલુ કરી."</string>
@@ -218,6 +220,10 @@
     <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"કાર્ય મોડ ચાલુ."</string>
     <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"કાર્ય મોડ બંધ કર્યો."</string>
     <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"કાર્ય મોડ ચાલુ કર્યો."</string>
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_off (650231949881093289) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_on (4218725402373934151) -->
+    <skip />
     <string name="accessibility_brightness" msgid="8003681285547803095">"પ્રદર્શન તેજ"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"2G-3G ડેટા થોભાવ્યો છે"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"4G ડેટા થોભાવ્યો છે"</string>
@@ -304,6 +310,8 @@
     <string name="recents_launch_disabled_message" msgid="1624523193008871793">"સુરક્ષિત મોડમાં <xliff:g id="APP">%s</xliff:g> અક્ષમ કરેલ છે."</string>
     <string name="recents_history_button_label" msgid="5153358867807604821">"ઇતિહાસ"</string>
     <string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"સાફ કરો"</string>
+    <string name="recents_drag_non_dockable_task_message" msgid="2935843902795166158">"આ ઍપ્લિકેશન મલ્ટિ-વિંડોનું સમર્થન કરતી નથી"</string>
+    <string name="recents_launch_non_dockable_task_label" msgid="7862379814938391888">"ઍપ્લિકેશન મલ્ટિ-વિંડોનું સમર્થન કરતી નથી"</string>
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"આડું વિભક્ત કરો"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"ઊભું વિભક્ત કરો"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"કસ્ટમ વિભક્ત કરો"</string>
@@ -451,18 +459,23 @@
     <string name="enable_bluetooth_title" msgid="5027037706500635269">"Bluetooth ચાલુ કરવુ છે?"</string>
     <string name="enable_bluetooth_message" msgid="9106595990708985385">"તમારા ટેબ્લેટ સાથે કીબોર્ડ કનેક્ટ કરવા માટે, તમારે પહેલાં Bluetooth ચાલુ કરવાની જરૂર પડશે."</string>
     <string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"ચાલુ કરો"</string>
-    <string name="apply_to_topic" msgid="3641403489318659666">"<xliff:g id="TOPIC_NAME">%1$s</xliff:g> સૂચનાઓ પર લાગુ કરો"</string>
-    <string name="apply_to_app" msgid="363016783939815960">"આ ઍપ્લિકેશનની તમામ સૂચનાઓ પર લાગુ કરો"</string>
+    <string name="show_silently" msgid="6841966539811264192">"સૂચનાઓ ચુપચાપ બતાવો"</string>
+    <string name="block" msgid="2734508760962682611">"તમામ સૂચનાઓને અવરોધિત કરો"</string>
+    <string name="do_not_silence" msgid="6878060322594892441">"ચુપ કરશો નહીં"</string>
+    <string name="do_not_silence_block" msgid="4070647971382232311">"ચુપ કે અવરોધિત કરશો નહીં"</string>
+    <string name="tuner_full_importance_settings" msgid="8103289238676424226">"પૂર્ણ મહત્વ સેટિંગ્સ બતાવો"</string>
     <string name="blocked_importance" msgid="5198578988978234161">"અવરોધિત"</string>
+    <string name="min_importance" msgid="1901894910809414782">"ન્યૂનતમ મહત્વ"</string>
     <string name="low_importance" msgid="4109929986107147930">"નિમ્ન મહત્વની"</string>
     <string name="default_importance" msgid="8192107689995742653">"સામાન્ય મહત્વની"</string>
     <string name="high_importance" msgid="1527066195614050263">"ઉચ્ચ મહત્વની"</string>
     <string name="max_importance" msgid="5089005872719563894">"તાત્કાલિક મહત્વની"</string>
     <string name="notification_importance_blocked" msgid="2397192642657872872">"આ સૂચનાઓ ક્યારેય બતાવશો નહીં"</string>
-    <string name="notification_importance_low" msgid="4383563267370859725">"સૂચનાની સૂચિની નીચે ચુપચાપ બતાવો"</string>
-    <string name="notification_importance_default" msgid="4926529615920610817">"આ સૂચનાઓ ચુપચાપ બતાવો"</string>
-    <string name="notification_importance_high" msgid="3222680136612408223">"સૂચનાઓની સૂચિની ટોચ પર બતાવો અને અવાજ કરો"</string>
-    <string name="notification_importance_max" msgid="5236987171904756134">"સ્ક્રીન પર ત્વરિત દ્રષ્ટિ કરો અને અવાજ કરો"</string>
+    <string name="notification_importance_min" msgid="1938190340516905748">"સૂચનાની સૂચિની નીચે ચુપચાપ બતાવો"</string>
+    <string name="notification_importance_low" msgid="3657252049508213048">"આ સૂચનાઓ ચુપચાપ બતાવો"</string>
+    <string name="notification_importance_default" msgid="4466466472622442175">"આ સૂચનાને અવાજ કરવાની મંજૂરી આપો"</string>
+    <string name="notification_importance_high" msgid="2135428926525093825">"સ્ક્રીન પર ત્વરિત દ્રષ્ટિ કરો અને અવાજને મંજૂરી આપો"</string>
+    <string name="notification_importance_max" msgid="5806278962376556491">"સૂચનાઓની સૂચિની ટોચ પર બતાવો, સ્ક્રીન પર ત્વરિત દ્રષ્ટિ કરો અને અવાજને મંજૂરી આપો"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"વધુ સેટિંગ્સ"</string>
     <string name="notification_done" msgid="5279426047273930175">"થઈ ગયું"</string>
     <string name="color_and_appearance" msgid="1254323855964993144">"રંગ અને દેખાવ"</string>
@@ -476,7 +489,7 @@
     <string name="use_dark_theme" msgid="2900938704964299312">"Android OS માટે ઘાટી થીમનો ઉપયોગ કરો"</string>
     <string name="adjust_tint" msgid="3398569573231409878">"ટિંટ સમાયોજિત કરો"</string>
     <string name="adjust_brightness" msgid="980039329808178246">"તેજ સમાયોજિત કરો"</string>
-    <string name="night_mode_disclaimer" msgid="3297928749219711334">"ઘાટી થીમને Android OS ના મુખ્ય ક્ષેત્રો પર લાગુ કરે છે જે સામાન્ય રીતે સેટિંગ્સ અને સૂચનાઓ જેવી લાઇટ થીમમાં પ્રદર્શિત કરવામાં આવે છે."</string>
+    <string name="night_mode_disclaimer" msgid="598914896926759578">"ઘાટી થીમને Android OS ના મુખ્ય ક્ષેત્રો પર લાગુ કરે છે જે સામાન્ય રીતે સેટિંગ્સ જેવી લાઇટ થીમમાં પ્રદર્શિત કરવામાં આવે છે."</string>
     <string name="color_apply" msgid="9212602012641034283">"લાગુ કરો"</string>
     <string name="color_revert_title" msgid="4746666545480534663">"સેટિંગ્સની પુષ્ટિ કરો"</string>
     <string name="color_revert_message" msgid="9116001069397996691">"કેટલીક રંગ સેટિંગ્સ આ ઉપકરણને બિનઉપયોગી બનાવી શકે છે. આ રંગ સેટિંગ્સની પુષ્ટિ કરવા માટે ઑકે ક્લિક કરો, અન્યથા 10 સેકંડ પછી આ સેટિંગ્સ ફરીથી સેટ થશે."</string>
@@ -535,4 +548,10 @@
     <item msgid="2139628951880142927">"ચાર્જ થાય ત્યારે ટકાવારી બતાવો (ડિફોલ્ટ)"</item>
     <item msgid="3327323682209964956">"આ આઇકન બતાવશો નહીં"</item>
   </string-array>
+    <string name="other" msgid="4060683095962566764">"અન્ય"</string>
+    <string name="accessibility_divider" msgid="5903423481953635044">"સ્પ્લિટ-સ્ક્રીન વિભાજક"</string>
+    <string name="accessibility_action_divider_move_down" msgid="704893304141890042">"નીચે ખસેડો"</string>
+    <string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"ઉપર ખસેડો"</string>
+    <string name="accessibility_action_divider_move_left" msgid="9218189832115847253">"ડાબે ખસેડો"</string>
+    <string name="accessibility_action_divider_move_right" msgid="4671522715182567972">"જમણે ખસેડો"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-gu-rIN/strings_tv.xml b/packages/SystemUI/res/values-gu-rIN/strings_tv.xml
new file mode 100644
index 0000000..56f0298
--- /dev/null
+++ b/packages/SystemUI/res/values-gu-rIN/strings_tv.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.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="pip_close" msgid="3480680679023423574">"PIP બંધ કરો"</string>
+    <string name="pip_fullscreen" msgid="8604643018538487816">"પૂર્ણ સ્ક્રીન"</string>
+    <string name="pip_play" msgid="674145557658227044">"ચલાવો"</string>
+    <string name="pip_pause" msgid="8412075640017218862">"થોભાવો"</string>
+    <string name="pip_hold_home" msgid="340086535668778109">"PIP નિયંત્રિત કરવા માટે "<b>"હોમ"</b>" પકડી રાખો"</string>
+    <string name="pip_onboarding_description" msgid="2627737116380318292">"PIP નિયંત્રિત કરવા માટે હોમ\n બટન દબાવો અને પકડી રાખો"</string>
+    <string name="pip_onboarding_button" msgid="3957426748484904611">"સમજાઈ ગયું"</string>
+</resources>
diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml
index 68c7d70..0c3cb48 100644
--- a/packages/SystemUI/res/values-hi/strings.xml
+++ b/packages/SystemUI/res/values-hi/strings.xml
@@ -73,7 +73,8 @@
     <string name="screenshot_saved_title" msgid="6461865960961414961">"स्‍क्रीनशॉट कैप्‍चर किया गया."</string>
     <string name="screenshot_saved_text" msgid="1152839647677558815">"अपना स्‍क्रीनशॉट देखने के लिए स्‍पर्श करें."</string>
     <string name="screenshot_failed_title" msgid="705781116746922771">"स्क्रीनशॉट को कैप्चर नहीं किया जा सका."</string>
-    <string name="screenshot_failed_text" msgid="1260203058661337274">"सीमित मेमोरी स्थान के कारण स्क्रीनशॉट नहीं ले सकते, या ऐप्स या आपके संगठन द्वारा ऐसा अनुमत नहीं है."</string>
+    <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"सीमित मेमोरी स्थान के कारण स्क्रीनशॉट सहेजा नहीं जा सकता."</string>
+    <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"आपके ऐप्लिकेशन या आपके संगठन द्वारा स्क्रीनशॉट लेने की अनुमति नहीं है."</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"USB फ़ाइल स्थानांतरण विकल्प"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"मीडिया प्लेयर के रूप में माउंट करें (MTP)"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"कैमरे के रूप में माउंट करें (PTP)"</string>
@@ -206,6 +207,7 @@
     <string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"अधिक समय."</string>
     <string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"कम समय."</string>
     <string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"फ़्लैशलाइट बंद है."</string>
+    <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"फ़्लैशलाइट उपलब्ध नहीं है."</string>
     <string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"फ़्लैशलाइट चालू है."</string>
     <string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"फ़्लैशलाइट को बंद किया गया."</string>
     <string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"फ़्लैशलाइट को चालू किया गया."</string>
@@ -218,6 +220,10 @@
     <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"कार्य मोड चालू है."</string>
     <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"कार्य मोड बंद कर दिया गया."</string>
     <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"कार्य मोड चालू किया गया."</string>
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_off (650231949881093289) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_on (4218725402373934151) -->
+    <skip />
     <string name="accessibility_brightness" msgid="8003681285547803095">"स्क्रीन की स्क्रीन की रोशनी"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"2G-3G डेटा रोक दिया गया है"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"4G डेटा रोक दिया गया है"</string>
@@ -304,6 +310,8 @@
     <string name="recents_launch_disabled_message" msgid="1624523193008871793">"<xliff:g id="APP">%s</xliff:g> को सुरक्षित-मोड में अक्षम किया गया."</string>
     <string name="recents_history_button_label" msgid="5153358867807604821">"इतिहास"</string>
     <string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"साफ़ करें"</string>
+    <string name="recents_drag_non_dockable_task_message" msgid="2935843902795166158">"यह ऐप्लिकेशन एकाधिक विंडो का समर्थन नहीं करता है"</string>
+    <string name="recents_launch_non_dockable_task_label" msgid="7862379814938391888">"ऐप्लिकेशन एकाधिक विंडो का समर्थन नहीं करता है"</string>
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"क्षैतिज रूप से विभाजित करें"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"लम्बवत रूप से विभाजित करें"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"कस्‍टम रूप से विभाजित करें"</string>
@@ -451,18 +459,23 @@
     <string name="enable_bluetooth_title" msgid="5027037706500635269">"ब्लूटूथ चालू करें?"</string>
     <string name="enable_bluetooth_message" msgid="9106595990708985385">"अपने कीबोर्ड को अपने टैबलेट से कनेक्ट करने के लिए, आपको पहले ब्लूटूथ चालू करना होगा."</string>
     <string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"चालू करें"</string>
-    <string name="apply_to_topic" msgid="3641403489318659666">"<xliff:g id="TOPIC_NAME">%1$s</xliff:g> नोटिफिकेशन पर लागू करें"</string>
-    <string name="apply_to_app" msgid="363016783939815960">"इस ऐप के सभी नोटिफिकेशन पर लागू करें"</string>
+    <string name="show_silently" msgid="6841966539811264192">"नोटिफिकेशन मौन रूप से दिखाएं"</string>
+    <string name="block" msgid="2734508760962682611">"सभी नोटिफिकेशन अवरुद्ध करें"</string>
+    <string name="do_not_silence" msgid="6878060322594892441">"मौन ना करें"</string>
+    <string name="do_not_silence_block" msgid="4070647971382232311">"मौन या अवरुद्ध ना करें"</string>
+    <string name="tuner_full_importance_settings" msgid="8103289238676424226">"पूर्ण महत्व वाली सेटिंग दिखाएं"</string>
     <string name="blocked_importance" msgid="5198578988978234161">"अवरोधित"</string>
+    <string name="min_importance" msgid="1901894910809414782">"न्यूनतम महत्व"</string>
     <string name="low_importance" msgid="4109929986107147930">"निम्न महत्व"</string>
     <string name="default_importance" msgid="8192107689995742653">"सामान्य महत्व"</string>
     <string name="high_importance" msgid="1527066195614050263">"उच्च महत्व"</string>
     <string name="max_importance" msgid="5089005872719563894">"तत्काल महत्व"</string>
     <string name="notification_importance_blocked" msgid="2397192642657872872">"ये नोटिफिकेशन कभी ना दिखाएं"</string>
-    <string name="notification_importance_low" msgid="4383563267370859725">"नोटिफिकेशन सूची में सबसे नीचे मौन रूप से दिखाएं"</string>
-    <string name="notification_importance_default" msgid="4926529615920610817">"ये नोटिफिकेशन मौन रूप से दिखाएं"</string>
-    <string name="notification_importance_high" msgid="3222680136612408223">"नोटिफिकेशन सूची में सबसे ऊपर दिखाएं और ध्वनि चलाएं"</string>
-    <string name="notification_importance_max" msgid="5236987171904756134">"स्‍क्रीन पर एक झलक दिखाएं और ध्‍वनि चलाएं"</string>
+    <string name="notification_importance_min" msgid="1938190340516905748">"नोटिफिकेशन सूची में सबसे नीचे मौन रूप से दिखाएं"</string>
+    <string name="notification_importance_low" msgid="3657252049508213048">"ये नोटिफिकेशन मौन रूप से दिखाएं"</string>
+    <string name="notification_importance_default" msgid="4466466472622442175">"इन नोटिफिकेशन को ध्वनि करने दें"</string>
+    <string name="notification_importance_high" msgid="2135428926525093825">"स्क्रीन पर झलक दिखाएं और ध्वनि करें"</string>
+    <string name="notification_importance_max" msgid="5806278962376556491">"नोटिफिकेशन सूची के शीर्ष पर दिखाएं, स्क्रीन पर झलक दिखाएं और ध्वनि करें"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"और सेटिंग"</string>
     <string name="notification_done" msgid="5279426047273930175">"हो गया"</string>
     <string name="color_and_appearance" msgid="1254323855964993144">"रंग और दिखावट"</string>
@@ -476,7 +489,7 @@
     <string name="use_dark_theme" msgid="2900938704964299312">"Android OS के लिए गहरी थीम का उपयोग करें"</string>
     <string name="adjust_tint" msgid="3398569573231409878">"टिंट समायोजित करें"</string>
     <string name="adjust_brightness" msgid="980039329808178246">"स्क्रीन की रोशनी समायोजित करें"</string>
-    <string name="night_mode_disclaimer" msgid="3297928749219711334">"गहरी थीम को Android OS के मुख्य क्षेत्रों पर लागू किया जाता है जिन्हें सामान्यतः सेटिंग और नोटिफिकेशन जैसी हल्की थीम में प्रदर्शित किया जाता है."</string>
+    <string name="night_mode_disclaimer" msgid="598914896926759578">"गहरी थीम को Android OS के मुख्य क्षेत्रों पर लागू किया जाता है जिन्हें सामान्यतः सेटिंग जैसी हल्की थीम में प्रदर्शित किया जाता है."</string>
     <string name="color_apply" msgid="9212602012641034283">"लागू करें"</string>
     <string name="color_revert_title" msgid="4746666545480534663">"से‍ेटिंग की पुष्टि करें"</string>
     <string name="color_revert_message" msgid="9116001069397996691">"कुछ रंग सेटिंग इस डिवाइस को अनुपयोगी बना सकती हैं. इन रंग सेटिंग की पुष्टि करने के लिए ठीक क्लिक करें, अन्यथा 10 सेकंड के बाद ये सेटिंग रीसेट हो जाएंगी."</string>
@@ -535,4 +548,10 @@
     <item msgid="2139628951880142927">"चार्ज होते समय प्रतिशत दिखाएं (डिफ़ॉल्ट)"</item>
     <item msgid="3327323682209964956">"यह आइकन ना दिखाएं"</item>
   </string-array>
+    <string name="other" msgid="4060683095962566764">"अन्य"</string>
+    <string name="accessibility_divider" msgid="5903423481953635044">"विभाजित स्क्रीन विभाजक"</string>
+    <string name="accessibility_action_divider_move_down" msgid="704893304141890042">"नीचे ले जाएं"</string>
+    <string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"ऊपर ले जाएं"</string>
+    <string name="accessibility_action_divider_move_left" msgid="9218189832115847253">"बाएं ले जाएं"</string>
+    <string name="accessibility_action_divider_move_right" msgid="4671522715182567972">"दाएं ले जाएं"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-hi/strings_tv.xml b/packages/SystemUI/res/values-hi/strings_tv.xml
new file mode 100644
index 0000000..c4bb26b
--- /dev/null
+++ b/packages/SystemUI/res/values-hi/strings_tv.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.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="pip_close" msgid="3480680679023423574">"PIP बंद करें"</string>
+    <string name="pip_fullscreen" msgid="8604643018538487816">"पूर्ण स्‍क्रीन"</string>
+    <string name="pip_play" msgid="674145557658227044">"चलाएं"</string>
+    <string name="pip_pause" msgid="8412075640017218862">"रोकें"</string>
+    <string name="pip_hold_home" msgid="340086535668778109">"PIP नियंत्रण हेतु "<b>"HOME"</b>" होल्ड करें"</string>
+    <string name="pip_onboarding_description" msgid="2627737116380318292">"PIP नियंत्रण हेतु HOME\nबटन दबाए रखें"</string>
+    <string name="pip_onboarding_button" msgid="3957426748484904611">"समझ लिया"</string>
+</resources>
diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml
index e5fb6d3..81f10a2 100644
--- a/packages/SystemUI/res/values-hr/strings.xml
+++ b/packages/SystemUI/res/values-hr/strings.xml
@@ -74,7 +74,8 @@
     <string name="screenshot_saved_title" msgid="6461865960961414961">"Zaslon je snimljen."</string>
     <string name="screenshot_saved_text" msgid="1152839647677558815">"Dodirnite za prikaz snimke zaslona."</string>
     <string name="screenshot_failed_title" msgid="705781116746922771">"Nije bilo moguće snimiti zaslon."</string>
-    <string name="screenshot_failed_text" msgid="1260203058661337274">"Zaslon nije snimljen zbog ograničene pohrane ili zato što to ne dopušta aplikacija ili vaša organizacija."</string>
+    <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Zaslon nije snimljen zbog ograničenog prostora za pohranu."</string>
+    <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Snimanje zaslona ne dopušta aplikacija ili vaša organizacija."</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"Opcije USB prijenosa datoteka"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Učitaj kao media player (MTP)"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"Učitaj kao fotoaparat (PTP)"</string>
@@ -207,6 +208,7 @@
     <string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"Više vremena."</string>
     <string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"Manje vremena."</string>
     <string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"Svjetiljka isključena."</string>
+    <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"Svjetiljka nije dostupna."</string>
     <string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"Svjetiljka uključena."</string>
     <string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"Svjetiljka isključena."</string>
     <string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"Svjetiljka uključena."</string>
@@ -219,6 +221,10 @@
     <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"Način rada uključen."</string>
     <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"Način rada isključen."</string>
     <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"Način rada uključen."</string>
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_off (650231949881093289) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_on (4218725402373934151) -->
+    <skip />
     <string name="accessibility_brightness" msgid="8003681285547803095">"Svjetlina zaslona"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"2G – 3G podaci pauzirani"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"4G podaci pauzirani"</string>
@@ -302,10 +308,11 @@
     <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"prikvačivanje zaslona"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"pretraži"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"Aplikacija <xliff:g id="APP">%s</xliff:g> nije pokrenuta."</string>
-    <!-- no translation found for recents_launch_disabled_message (1624523193008871793) -->
-    <skip />
+    <string name="recents_launch_disabled_message" msgid="1624523193008871793">"Aplikacija <xliff:g id="APP">%s</xliff:g> onemogućena je u sigurnom načinu."</string>
     <string name="recents_history_button_label" msgid="5153358867807604821">"Povijest"</string>
     <string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"Izbriši"</string>
+    <string name="recents_drag_non_dockable_task_message" msgid="2935843902795166158">"Ta aplikacija ne podržava više prozora"</string>
+    <string name="recents_launch_non_dockable_task_label" msgid="7862379814938391888">"Aplikacija ne podržava više prozora"</string>
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Podijeli vodoravno"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Podijeli okomito"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Podijeli prilagođeno"</string>
@@ -453,18 +460,23 @@
     <string name="enable_bluetooth_title" msgid="5027037706500635269">"Želite li uključiti Bluetooth?"</string>
     <string name="enable_bluetooth_message" msgid="9106595990708985385">"Da biste povezali tipkovnicu s tabletom, morate uključiti Bluetooth."</string>
     <string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"Uključi"</string>
-    <string name="apply_to_topic" msgid="3641403489318659666">"Primijeni na obavijesti za temu <xliff:g id="TOPIC_NAME">%1$s</xliff:g>"</string>
-    <string name="apply_to_app" msgid="363016783939815960">"Primijeni na sve obavijesti ove aplikacije"</string>
+    <string name="show_silently" msgid="6841966539811264192">"Prikaži obavijesti tiho"</string>
+    <string name="block" msgid="2734508760962682611">"Blokiraj sve obavijesti"</string>
+    <string name="do_not_silence" msgid="6878060322594892441">"Ne utišavaj"</string>
+    <string name="do_not_silence_block" msgid="4070647971382232311">"Ne utišavaj i ne blokiraj"</string>
+    <string name="tuner_full_importance_settings" msgid="8103289238676424226">"Prikaži potpune postavke važnosti"</string>
     <string name="blocked_importance" msgid="5198578988978234161">"Blokirano"</string>
+    <string name="min_importance" msgid="1901894910809414782">"Najmanja važnost"</string>
     <string name="low_importance" msgid="4109929986107147930">"Mala važnost"</string>
     <string name="default_importance" msgid="8192107689995742653">"Uobičajena važnost"</string>
     <string name="high_importance" msgid="1527066195614050263">"Velika važnost"</string>
     <string name="max_importance" msgid="5089005872719563894">"Hitno"</string>
     <string name="notification_importance_blocked" msgid="2397192642657872872">"Nikad ne prikazuj te obavijesti"</string>
-    <string name="notification_importance_low" msgid="4383563267370859725">"Prikaži tiho pri dnu popisa obavijesti"</string>
-    <string name="notification_importance_default" msgid="4926529615920610817">"Prikaži te obavijesti tiho"</string>
-    <string name="notification_importance_high" msgid="3222680136612408223">"Prikaži na vrhu popisa obavijesti i emitiraj zvučni signal"</string>
-    <string name="notification_importance_max" msgid="5236987171904756134">"Prikaži na zaslonu i emitiraj zvučni signal"</string>
+    <string name="notification_importance_min" msgid="1938190340516905748">"Prikaži tiho pri dnu popisa obavijesti"</string>
+    <string name="notification_importance_low" msgid="3657252049508213048">"Prikaži te obavijesti tiho"</string>
+    <string name="notification_importance_default" msgid="4466466472622442175">"Dopusti obavijestima da emitiraju zvučne signale"</string>
+    <string name="notification_importance_high" msgid="2135428926525093825">"Prikaži na zaslonu i dopusti zvuk"</string>
+    <string name="notification_importance_max" msgid="5806278962376556491">"Prikaži pri vrhu popisa obavijesti, prikaži na zaslonu i dopusti zvuk"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"Više postavki"</string>
     <string name="notification_done" msgid="5279426047273930175">"Gotovo"</string>
     <string name="color_and_appearance" msgid="1254323855964993144">"Boja i izgled"</string>
@@ -478,7 +490,7 @@
     <string name="use_dark_theme" msgid="2900938704964299312">"Koristi tamnu temu za OS Android"</string>
     <string name="adjust_tint" msgid="3398569573231409878">"Prilagodi nijansu"</string>
     <string name="adjust_brightness" msgid="980039329808178246">"Prilagodi svjetlinu"</string>
-    <string name="night_mode_disclaimer" msgid="3297928749219711334">"Tamna se tema primjenjuje na glavna područja OS-a Android koja se inače prikazuju u svijetloj temi, primjerice postavke i obavijesti."</string>
+    <string name="night_mode_disclaimer" msgid="598914896926759578">"Tamna se tema primjenjuje na glavna područja OS-a Android, kao što su, primjerice, postavke, koja se inače prikazuju u svijetloj temi."</string>
     <string name="color_apply" msgid="9212602012641034283">"Primijeni"</string>
     <string name="color_revert_title" msgid="4746666545480534663">"Potvrdite postavke"</string>
     <string name="color_revert_message" msgid="9116001069397996691">"Neke postavke boja mogu učiniti uređaj neupotrebljivim. Kliknite U redu da biste potvrdili postavke boja jer će se u suprotnom poništiti za 10 sekundi."</string>
@@ -537,4 +549,10 @@
     <item msgid="2139628951880142927">"Prikazuj postotak tijekom punjenja (zadano)"</item>
     <item msgid="3327323682209964956">"Ne prikazuj tu ikonu"</item>
   </string-array>
+    <string name="other" msgid="4060683095962566764">"Ostalo"</string>
+    <string name="accessibility_divider" msgid="5903423481953635044">"Razdjelnik podijeljenog zaslona"</string>
+    <string name="accessibility_action_divider_move_down" msgid="704893304141890042">"Pomakni prema dolje"</string>
+    <string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"Pomakni prema gore"</string>
+    <string name="accessibility_action_divider_move_left" msgid="9218189832115847253">"Pomakni ulijevo"</string>
+    <string name="accessibility_action_divider_move_right" msgid="4671522715182567972">"Pomakni udesno"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-hr/strings_tv.xml b/packages/SystemUI/res/values-hr/strings_tv.xml
new file mode 100644
index 0000000..2a72055
--- /dev/null
+++ b/packages/SystemUI/res/values-hr/strings_tv.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.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="pip_close" msgid="3480680679023423574">"Zatvori PIP"</string>
+    <string name="pip_fullscreen" msgid="8604643018538487816">"Cijeli zaslon"</string>
+    <string name="pip_play" msgid="674145557658227044">"Reproduciraj"</string>
+    <string name="pip_pause" msgid="8412075640017218862">"Pauziraj"</string>
+    <string name="pip_hold_home" msgid="340086535668778109">"Držite "<b>"POČETNI"</b>" za PIP"</string>
+    <string name="pip_onboarding_description" msgid="2627737116380318292">"Pritisnite i držite POČETNI\nza upravljanje PIP-om"</string>
+    <string name="pip_onboarding_button" msgid="3957426748484904611">"Shvaćam"</string>
+</resources>
diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml
index 440c3f2..ccf582b 100644
--- a/packages/SystemUI/res/values-hu/strings.xml
+++ b/packages/SystemUI/res/values-hu/strings.xml
@@ -73,7 +73,8 @@
     <string name="screenshot_saved_title" msgid="6461865960961414961">"Képernyőkép rögzítve."</string>
     <string name="screenshot_saved_text" msgid="1152839647677558815">"Megérintésével megtekintheti a képernyőképet."</string>
     <string name="screenshot_failed_title" msgid="705781116746922771">"Nem sikerült rögzíteni a képernyőképet."</string>
-    <string name="screenshot_failed_text" msgid="1260203058661337274">"Nem készíthet képernyőképet, mert kevés a tárhely, vagy az alkalmazás/szervezet nem engedélyezi azt."</string>
+    <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Nem menthet képernyőképet, mert kevés a tárhely."</string>
+    <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Az alkalmazás vagy szervezete nem engedélyezi képernyőképek készítését."</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"USB-fájlátvitel beállításai"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Csatlakoztatás médialejátszóként (MTP)"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"Csatlakoztatás kameraként (PTP)"</string>
@@ -206,6 +207,7 @@
     <string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"Több idő."</string>
     <string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"Kevesebb idő."</string>
     <string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"Vaku kikapcsolva."</string>
+    <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"A zseblámpa nem áll rendelkezésre"</string>
     <string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"Vaku bekapcsolva."</string>
     <string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"Vaku kikapcsolva."</string>
     <string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"Vaku bekapcsolva."</string>
@@ -218,6 +220,10 @@
     <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"Munka mód be."</string>
     <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"Munka mód kikapcsolva."</string>
     <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"Munka mód bekapcsolva."</string>
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_off (650231949881093289) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_on (4218725402373934151) -->
+    <skip />
     <string name="accessibility_brightness" msgid="8003681285547803095">"A kijelző fényereje"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"A 2G és 3G adatforgalom szünetel."</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"A 4G adatforgalom szünetel"</string>
@@ -304,6 +310,8 @@
     <string name="recents_launch_disabled_message" msgid="1624523193008871793">"A(z) <xliff:g id="APP">%s</xliff:g> csökkentett módban ki van kapcsolva."</string>
     <string name="recents_history_button_label" msgid="5153358867807604821">"Előzmények"</string>
     <string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"Törlés"</string>
+    <string name="recents_drag_non_dockable_task_message" msgid="2935843902795166158">"Ez az alkalmazás nem támogatja a többablakos nézetet"</string>
+    <string name="recents_launch_non_dockable_task_label" msgid="7862379814938391888">"Az alkalmazás nem támogatja a többablakos nézetet"</string>
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Osztott vízszintes"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Osztott függőleges"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Osztott egyéni"</string>
@@ -451,18 +459,23 @@
     <string name="enable_bluetooth_title" msgid="5027037706500635269">"Engedélyezi a Bluetooth-kapcsolatot?"</string>
     <string name="enable_bluetooth_message" msgid="9106595990708985385">"Ha a billentyűzetet csatlakoztatni szeretné táblagépéhez, először engedélyeznie kell a Bluetooth-kapcsolatot."</string>
     <string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"Bekapcsolás"</string>
-    <string name="apply_to_topic" msgid="3641403489318659666">"A következő értesítések esetén: <xliff:g id="TOPIC_NAME">%1$s</xliff:g>"</string>
-    <string name="apply_to_app" msgid="363016783939815960">"Az alkalmazás minden értesítése esetén"</string>
+    <string name="show_silently" msgid="6841966539811264192">"Értesítések megjelenítése hangjelzés nélkül"</string>
+    <string name="block" msgid="2734508760962682611">"Minden értesítés letiltása"</string>
+    <string name="do_not_silence" msgid="6878060322594892441">"Nincs némítás"</string>
+    <string name="do_not_silence_block" msgid="4070647971382232311">"Nincs némítás vagy letiltás"</string>
+    <string name="tuner_full_importance_settings" msgid="8103289238676424226">"A teljes fontossági beállítások megjelenítése"</string>
     <string name="blocked_importance" msgid="5198578988978234161">"Letiltva"</string>
+    <string name="min_importance" msgid="1901894910809414782">"Minimális fontosságú"</string>
     <string name="low_importance" msgid="4109929986107147930">"Kevésbé fontos"</string>
     <string name="default_importance" msgid="8192107689995742653">"Normál"</string>
     <string name="high_importance" msgid="1527066195614050263">"Fontos"</string>
     <string name="max_importance" msgid="5089005872719563894">"Sürgős"</string>
     <string name="notification_importance_blocked" msgid="2397192642657872872">"Soha nem jelennek meg ezek az értesítések"</string>
-    <string name="notification_importance_low" msgid="4383563267370859725">"Hangjelzés nélkül jelennek meg az értesítési lista alján"</string>
-    <string name="notification_importance_default" msgid="4926529615920610817">"Hang nélkül jelennek meg ezek az értesítések"</string>
-    <string name="notification_importance_high" msgid="3222680136612408223">"Az értesítési lista tetején jelennek meg hangjelzéssel"</string>
-    <string name="notification_importance_max" msgid="5236987171904756134">"Az értesítések felugranak a képernyőn hangjelzéssel"</string>
+    <string name="notification_importance_min" msgid="1938190340516905748">"Hangjelzés nélkül jelennek meg az értesítési lista alján"</string>
+    <string name="notification_importance_low" msgid="3657252049508213048">"Ezek az értesítések hangjelzés nélkül jelennek meg"</string>
+    <string name="notification_importance_default" msgid="4466466472622442175">"Hangjelzés engedélyezése ezeknél az értesítéseknél"</string>
+    <string name="notification_importance_high" msgid="2135428926525093825">"Az értesítések felugranak a képernyőn hangjelzéssel"</string>
+    <string name="notification_importance_max" msgid="5806278962376556491">"Az értesítési lista tetején jelennek meg, illetve felugranak a képernyőn hangjelzéssel"</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="color_and_appearance" msgid="1254323855964993144">"Szín és megjelenés"</string>
@@ -476,7 +489,7 @@
     <string name="use_dark_theme" msgid="2900938704964299312">"Sötét téma használata az Android operációs rendszernél"</string>
     <string name="adjust_tint" msgid="3398569573231409878">"Színárnyalat módosítása"</string>
     <string name="adjust_brightness" msgid="980039329808178246">"Fényerő módosítása"</string>
-    <string name="night_mode_disclaimer" msgid="3297928749219711334">"Sötét téma látható az Android operációs rendszer olyan alapterületeinél, amelyek normál állapotban világosan jelennek meg (például a Beállítások és az értesítések)."</string>
+    <string name="night_mode_disclaimer" msgid="598914896926759578">"Sötét téma látható az Android operációs rendszer olyan alapterületeinél, amelyek normál állapotban világosan jelennek meg (például a Beállítások)."</string>
     <string name="color_apply" msgid="9212602012641034283">"Alkalmaz"</string>
     <string name="color_revert_title" msgid="4746666545480534663">"Beállítások megerősítése"</string>
     <string name="color_revert_message" msgid="9116001069397996691">"Bizonyos színbeállítások használhatatlanná tehetik ezt az eszközt. A színbeállítás megerősítéséhez kattintson az OK lehetőségre, máskülönben a rendszer 10 másodpercen belül visszaáll a korábbira."</string>
@@ -535,4 +548,10 @@
     <item msgid="2139628951880142927">"Százalékos érték töltés közben látható (alapértelmezett)"</item>
     <item msgid="3327323682209964956">"Ne jelenjen meg ez az ikon"</item>
   </string-array>
+    <string name="other" msgid="4060683095962566764">"Egyéb"</string>
+    <string name="accessibility_divider" msgid="5903423481953635044">"Elválasztó az osztott nézetben"</string>
+    <string name="accessibility_action_divider_move_down" msgid="704893304141890042">"Mozgatás lefelé"</string>
+    <string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"Mozgatás felfelé"</string>
+    <string name="accessibility_action_divider_move_left" msgid="9218189832115847253">"Mozgatás balra"</string>
+    <string name="accessibility_action_divider_move_right" msgid="4671522715182567972">"Mozgatás jobbra"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-hu/strings_tv.xml b/packages/SystemUI/res/values-hu/strings_tv.xml
new file mode 100644
index 0000000..ff4d37c
--- /dev/null
+++ b/packages/SystemUI/res/values-hu/strings_tv.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.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="pip_close" msgid="3480680679023423574">"PIP bezárása"</string>
+    <string name="pip_fullscreen" msgid="8604643018538487816">"Teljes képernyő"</string>
+    <string name="pip_play" msgid="674145557658227044">"Lejátszás"</string>
+    <string name="pip_pause" msgid="8412075640017218862">"Szüneteltetés"</string>
+    <string name="pip_hold_home" msgid="340086535668778109">"PIP vezérlése a "<b>"HOME"</b>"-mal"</string>
+    <string name="pip_onboarding_description" msgid="2627737116380318292">"A PIP vezérléséhez\ntartsa nyomva a HOME-ot"</string>
+    <string name="pip_onboarding_button" msgid="3957426748484904611">"Rendben"</string>
+</resources>
diff --git a/packages/SystemUI/res/values-hy-rAM/strings.xml b/packages/SystemUI/res/values-hy-rAM/strings.xml
index ef7c8e3..e60ce28 100644
--- a/packages/SystemUI/res/values-hy-rAM/strings.xml
+++ b/packages/SystemUI/res/values-hy-rAM/strings.xml
@@ -73,7 +73,8 @@
     <string name="screenshot_saved_title" msgid="6461865960961414961">"Էկրանի հանույթը լուսանկարվել է:"</string>
     <string name="screenshot_saved_text" msgid="1152839647677558815">"Հպեք ձեր էկրանի հանույթը տեսնելու համար:"</string>
     <string name="screenshot_failed_title" msgid="705781116746922771">"Չհաջողվեց լուսանկարել էկրանի հանույթը:"</string>
-    <string name="screenshot_failed_text" msgid="1260203058661337274">"Չենք կարող պատճենել էկրանը՝ տարածքի սահմանափակման կամ ձեր կազմակերպության կողմից արգելքի պատճառով:"</string>
+    <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Չհաջողվեց պահել էկրանի պատկերը սահմանափակ հիշողության պատճառով:"</string>
+    <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Այս հավելվածը կամ ձեր կազմակերպությունը չի թույլատրում Էկրանի պատկերի ստացումը:"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"USB ֆայլերի փոխանցման ընտրանքներ"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Միացնել որպես մեդիա նվագարկիչ (MTP)"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"Միացնել որպես ֆոտոխցիկ (PTP)"</string>
@@ -206,6 +207,7 @@
     <string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"Ավելացնել ժամանակը:"</string>
     <string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"Պակասեցնել ժամանակը:"</string>
     <string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"Լապտերն անջատված է:"</string>
+    <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"Լապտերն անհասանելի է:"</string>
     <string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"Լապտերը միացված է:"</string>
     <string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"Լապտերն անջատվեց:"</string>
     <string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"Լապտերը միացավ:"</string>
@@ -218,6 +220,10 @@
     <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"Աշխատանքային ռեժիմը միացված է:"</string>
     <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"Աշխատանքային ռեժիմն անջատվեց:"</string>
     <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"Աշխատանքային ռեժիմը միացվեց:"</string>
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_off (650231949881093289) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_on (4218725402373934151) -->
+    <skip />
     <string name="accessibility_brightness" msgid="8003681285547803095">"Ցուցադրել պայծառությունը"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"2Գ-3Գ տվյալների օգտագործումը դադարեցված է"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"4Գ տվյալների օգտագործումը դադարեցված է"</string>
@@ -304,6 +310,8 @@
     <string name="recents_launch_disabled_message" msgid="1624523193008871793">"<xliff:g id="APP">%s</xliff:g> հավելվածը անվտանգ ռեժիմում անջատված է:"</string>
     <string name="recents_history_button_label" msgid="5153358867807604821">"Պատմություն"</string>
     <string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"Մաքրել"</string>
+    <string name="recents_drag_non_dockable_task_message" msgid="2935843902795166158">"Այս հավելվածը չի աջակցում բազմապատուհան ռեժիմը"</string>
+    <string name="recents_launch_non_dockable_task_label" msgid="7862379814938391888">"Հավելվածը չի աջակցում բազմապատուհան ռեժիմը"</string>
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Հորիզոնական տրոհում"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Ուղղահայաց տրոհում"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Հատուկ տրոհում"</string>
@@ -451,18 +459,23 @@
     <string name="enable_bluetooth_title" msgid="5027037706500635269">"Միացնե՞լ Bluetooth-ը:"</string>
     <string name="enable_bluetooth_message" msgid="9106595990708985385">"Ստեղնաշարը ձեր պլանշետին միացնելու համար նախ անհրաժեշտ է միացնել Bluetooth-ը:"</string>
     <string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"Միացնել"</string>
-    <string name="apply_to_topic" msgid="3641403489318659666">"Կիրառել <xliff:g id="TOPIC_NAME">%1$s</xliff:g>-ի ծանուցումների նկատմամբ"</string>
-    <string name="apply_to_app" msgid="363016783939815960">"Կիրառել այս հավելվածի բոլոր ծանուցումների նկատմամբ"</string>
+    <string name="show_silently" msgid="6841966539811264192">"Ցույց տալ ծանուցումներն առանց ձայնային ազդանշանի"</string>
+    <string name="block" msgid="2734508760962682611">"Արգելափակել բոլոր ծանուցումները"</string>
+    <string name="do_not_silence" msgid="6878060322594892441">"Ձայնը չանջատել"</string>
+    <string name="do_not_silence_block" msgid="4070647971382232311">"Ձայնը չանջատել և չարգելափակել"</string>
+    <string name="tuner_full_importance_settings" msgid="8103289238676424226">"Ցույց տալ կարևորության բոլոր կարգավորումները"</string>
     <string name="blocked_importance" msgid="5198578988978234161">"Արգելափակված"</string>
+    <string name="min_importance" msgid="1901894910809414782">"Նվազագույն կարևորություն"</string>
     <string name="low_importance" msgid="4109929986107147930">"Ցածր կարևորություն"</string>
     <string name="default_importance" msgid="8192107689995742653">"Սովորական կարևորություն"</string>
     <string name="high_importance" msgid="1527066195614050263">"Բարձր կարևորություն"</string>
     <string name="max_importance" msgid="5089005872719563894">"Հրատապ կարևորություն"</string>
     <string name="notification_importance_blocked" msgid="2397192642657872872">"Երբեք չցուցադրել այս ծանուցումները"</string>
-    <string name="notification_importance_low" msgid="4383563267370859725">"Ցուցադրել ծանուցումների ցանկի ներքևում առանց ձայնային ազդանշանի"</string>
-    <string name="notification_importance_default" msgid="4926529615920610817">"Ցուցադրել այս ծանուցումներն առանց ձայնային ազդանշանի"</string>
-    <string name="notification_importance_high" msgid="3222680136612408223">"Ցուցադրել ծանուցումների ցանկի վերևում և հնչեցնել ձայնային ազդանշան"</string>
-    <string name="notification_importance_max" msgid="5236987171904756134">"Ցուցադրել էկրանին և հնչեցնել ձայնային ազդանշան"</string>
+    <string name="notification_importance_min" msgid="1938190340516905748">"Ցուցադրել ծանուցումների ցանկի ներքևում առանց ձայնային ազդանշանի"</string>
+    <string name="notification_importance_low" msgid="3657252049508213048">"Ցուցադրել այս ծանուցումներն առանց ձայնային ազդանշանի"</string>
+    <string name="notification_importance_default" msgid="4466466472622442175">"Թույլ տալ այս ծանուցումներին ձայնային ազդանշան հնչեցնել"</string>
+    <string name="notification_importance_high" msgid="2135428926525093825">"Թռուցիկ ցուցադրել էկրանին և թույլատրել ձայնային ազդանշանը"</string>
+    <string name="notification_importance_max" msgid="5806278962376556491">"Ցույց տալ ծանուցումների ցանկի վերևում, թռուցիկ ցուցադրել էկրանին և թույլատրել ձայնային ազդանշանը"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"Այլ կարգավորումներ"</string>
     <string name="notification_done" msgid="5279426047273930175">"Պատրաստ է"</string>
     <string name="color_and_appearance" msgid="1254323855964993144">"Գույնը և արտաքին տեսքը"</string>
@@ -476,7 +489,7 @@
     <string name="use_dark_theme" msgid="2900938704964299312">"Օգտագործել մուգ թեման Android OS-ի համար"</string>
     <string name="adjust_tint" msgid="3398569573231409878">"Կարգավորել երանգը"</string>
     <string name="adjust_brightness" msgid="980039329808178246">"Կարգավորել պայծառությունը"</string>
-    <string name="night_mode_disclaimer" msgid="3297928749219711334">"Մուգ թեման կիրառվում է Android OS-ի հիմնական հատվածների նկատմամբ, որոնք սովորաբար ցուցադրվում են բաց թենայում (օրինակ՝ Կարգավորումներ և ծանուցումներ):"</string>
+    <string name="night_mode_disclaimer" msgid="598914896926759578">"Մուգ թեման կիրառվում է Android OS-ի հիմնական հատվածների նկատմամբ, որոնք սովորաբար ցուցադրվում են բաց թեմայում (օրինակ՝ Կարգավորումներ):"</string>
     <string name="color_apply" msgid="9212602012641034283">"Կիրառել"</string>
     <string name="color_revert_title" msgid="4746666545480534663">"Հաստատել կարգավորումները"</string>
     <string name="color_revert_message" msgid="9116001069397996691">"Գունային որոշ կարգավորումները կարող են այս սարքը օգտագործման համար ոչ պիտանի դարձնել: Սեղմեք Լավ կոճակը՝ գունային այս կարգավորումները հաստատելու համար: Հակառակ դեպքում այս կարգավորումները կվերակայվեն 10 վայրկյան հետո:"</string>
@@ -535,4 +548,10 @@
     <item msgid="2139628951880142927">"Ցույց տալ տոկոսը լիցքավորելու ժամանակ (կանխադրված է)"</item>
     <item msgid="3327323682209964956">"Ցույց չտալ այս պատկերակը"</item>
   </string-array>
+    <string name="other" msgid="4060683095962566764">"Այլ"</string>
+    <string name="accessibility_divider" msgid="5903423481953635044">"Տրոհված էկրանի բաժանիչ"</string>
+    <string name="accessibility_action_divider_move_down" msgid="704893304141890042">"Տեղափոխել ներքև"</string>
+    <string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"Տեղափոխել վերև"</string>
+    <string name="accessibility_action_divider_move_left" msgid="9218189832115847253">"Տեղափոխել ձախ"</string>
+    <string name="accessibility_action_divider_move_right" msgid="4671522715182567972">"Տեղափոխել աջ"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-hy-rAM/strings_tv.xml b/packages/SystemUI/res/values-hy-rAM/strings_tv.xml
new file mode 100644
index 0000000..2eed586
--- /dev/null
+++ b/packages/SystemUI/res/values-hy-rAM/strings_tv.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2016, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <!-- no translation found for pip_close (3480680679023423574) -->
+    <skip />
+    <string name="pip_fullscreen" msgid="8604643018538487816">"Լիէկրան"</string>
+    <string name="pip_play" msgid="674145557658227044">"Նվագարկել"</string>
+    <string name="pip_pause" msgid="8412075640017218862">"Դադարեցնել"</string>
+    <!-- no translation found for pip_hold_home (340086535668778109) -->
+    <skip />
+    <!-- no translation found for pip_onboarding_description (2627737116380318292) -->
+    <skip />
+    <!-- no translation found for pip_onboarding_button (3957426748484904611) -->
+    <skip />
+</resources>
diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml
index c91d6fc..9eb1331 100644
--- a/packages/SystemUI/res/values-in/strings.xml
+++ b/packages/SystemUI/res/values-in/strings.xml
@@ -73,7 +73,8 @@
     <string name="screenshot_saved_title" msgid="6461865960961414961">"Tangkapan layar diambil."</string>
     <string name="screenshot_saved_text" msgid="1152839647677558815">"Sentuh untuk melihat tangkapan layar Anda."</string>
     <string name="screenshot_failed_title" msgid="705781116746922771">"Tidak dapat mengambil tangkapan layar."</string>
-    <string name="screenshot_failed_text" msgid="1260203058661337274">"Tak bisa mengambil tangkapan layar karena ruang penyimpanan terbatas/tak diizinkan aplikasi/organisasi Anda."</string>
+    <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Tidak dapat menyimpan tangkapan layar karena ruang penyimpanan terbatas."</string>
+    <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Mengambil tangkapan layar tidak diizinkan oleh aplikasi atau organisasi."</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"Opsi transfer file USB"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Pasang sebagai pemutar media (MTP)"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"Pasang sebagai kamera (PTP)"</string>
@@ -206,6 +207,7 @@
     <string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"Lebih lama."</string>
     <string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"Lebih cepat."</string>
     <string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"Senter nonaktif."</string>
+    <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"Senter tidak tersedia."</string>
     <string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"Senter aktif."</string>
     <string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"Senter dinonaktifkan."</string>
     <string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"Senter diaktifkan."</string>
@@ -218,6 +220,10 @@
     <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"Mode kerja aktif."</string>
     <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"Mode kerja dinonaktifkan."</string>
     <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"Mode kerja diaktifkan."</string>
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_off (650231949881093289) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_on (4218725402373934151) -->
+    <skip />
     <string name="accessibility_brightness" msgid="8003681285547803095">"Kecerahan tampilan"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"Data 2G-3G dijeda"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"Data 4G dijeda"</string>
@@ -304,6 +310,8 @@
     <string name="recents_launch_disabled_message" msgid="1624523193008871793">"<xliff:g id="APP">%s</xliff:g> dinonaktifkan dalam mode aman."</string>
     <string name="recents_history_button_label" msgid="5153358867807604821">"Riwayat"</string>
     <string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"Hapus"</string>
+    <string name="recents_drag_non_dockable_task_message" msgid="2935843902795166158">"Aplikasi ini tidak mendukung multijendela"</string>
+    <string name="recents_launch_non_dockable_task_label" msgid="7862379814938391888">"Aplikasi tidak mendukung multijendela"</string>
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Pisahkan Horizontal"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Pisahkan Vertikal"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Pisahkan Khusus"</string>
@@ -451,18 +459,23 @@
     <string name="enable_bluetooth_title" msgid="5027037706500635269">"Aktifkan Bluetooth?"</string>
     <string name="enable_bluetooth_message" msgid="9106595990708985385">"Untuk menghubungkan keyboard dengan tablet, terlebih dahulu aktifkan Bluetooth."</string>
     <string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"Aktifkan"</string>
-    <string name="apply_to_topic" msgid="3641403489318659666">"Terapkan ke notifikasi <xliff:g id="TOPIC_NAME">%1$s</xliff:g>"</string>
-    <string name="apply_to_app" msgid="363016783939815960">"Terapkan untuk semua notifikasi dari aplikasi ini"</string>
+    <string name="show_silently" msgid="6841966539811264192">"Tampilkan notifikasi tanpa suara"</string>
+    <string name="block" msgid="2734508760962682611">"Blokir semua notifikasi"</string>
+    <string name="do_not_silence" msgid="6878060322594892441">"Jangan bisukan"</string>
+    <string name="do_not_silence_block" msgid="4070647971382232311">"Jangan bisukan atau blokir"</string>
+    <string name="tuner_full_importance_settings" msgid="8103289238676424226">"Tampilkan setelan lengkap nilai penting"</string>
     <string name="blocked_importance" msgid="5198578988978234161">"Diblokir"</string>
+    <string name="min_importance" msgid="1901894910809414782">"Nilai penting min"</string>
     <string name="low_importance" msgid="4109929986107147930">"Tingkat kepentingan: rendah"</string>
     <string name="default_importance" msgid="8192107689995742653">"Tingkat kepentingan: normal"</string>
     <string name="high_importance" msgid="1527066195614050263">"Tingkat kepentingan: tinggi"</string>
     <string name="max_importance" msgid="5089005872719563894">"Tingkat kepentingan: darurat"</string>
     <string name="notification_importance_blocked" msgid="2397192642657872872">"Jangan pernah tunjukkan notifikasi ini"</string>
-    <string name="notification_importance_low" msgid="4383563267370859725">"Tunjukkan di bawah daftar notifikasi tanpa suara"</string>
-    <string name="notification_importance_default" msgid="4926529615920610817">"Tunjukkan notifikasi ini tanpa suara"</string>
-    <string name="notification_importance_high" msgid="3222680136612408223">"Tunjukkan di bagian atas daftar notifikasi dan bunyikan suara"</string>
-    <string name="notification_importance_max" msgid="5236987171904756134">"Muncul di layar dan bunyikan suara"</string>
+    <string name="notification_importance_min" msgid="1938190340516905748">"Tampilkan di bagian bawah daftar notifikasi tanpa suara"</string>
+    <string name="notification_importance_low" msgid="3657252049508213048">"Tampilkan notifikasi ini tanpa suara"</string>
+    <string name="notification_importance_default" msgid="4466466472622442175">"Izinkan notifikasi ini bersuara"</string>
+    <string name="notification_importance_high" msgid="2135428926525093825">"Muncul di layar dan izinkan suara"</string>
+    <string name="notification_importance_max" msgid="5806278962376556491">"Tampilkan di bagian atas daftar notifikasi, muncul di layar, dan izinkan suara"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"Setelan lainnya"</string>
     <string name="notification_done" msgid="5279426047273930175">"Selesai"</string>
     <string name="color_and_appearance" msgid="1254323855964993144">"Warna dan tampilan"</string>
@@ -476,7 +489,7 @@
     <string name="use_dark_theme" msgid="2900938704964299312">"Gunakan tema gelap untuk OS Android"</string>
     <string name="adjust_tint" msgid="3398569573231409878">"Sesuaikan rona"</string>
     <string name="adjust_brightness" msgid="980039329808178246">"Sesuaikan kecerahan"</string>
-    <string name="night_mode_disclaimer" msgid="3297928749219711334">"Tema gelap diterapkan ke area inti OS Android yang biasanya ditampilkan di tema terang, seperti Setelan dan notifikasi."</string>
+    <string name="night_mode_disclaimer" msgid="598914896926759578">"Tema gelap diterapkan ke area inti OS Android yang biasanya ditampilkan di tema terang, seperti Setelan."</string>
     <string name="color_apply" msgid="9212602012641034283">"Terapkan"</string>
     <string name="color_revert_title" msgid="4746666545480534663">"Konfirmasi setelan"</string>
     <string name="color_revert_message" msgid="9116001069397996691">"Beberapa setelan warna dapat membuat perangkat ini tidak dapat digunakan. Klik OKE untuk mengonfirmasi setelan warna ini. Jika tidak, setelan ini akan disetel ulang setelah 10 detik."</string>
@@ -535,4 +548,10 @@
     <item msgid="2139628951880142927">"Tampilkan persentase saat mengisi daya (default)"</item>
     <item msgid="3327323682209964956">"Jangan tampilkan ikon ini"</item>
   </string-array>
+    <string name="other" msgid="4060683095962566764">"Lainnya"</string>
+    <string name="accessibility_divider" msgid="5903423481953635044">"Pembagi layar terpisah"</string>
+    <string name="accessibility_action_divider_move_down" msgid="704893304141890042">"Turunkan"</string>
+    <string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"Naikkan"</string>
+    <string name="accessibility_action_divider_move_left" msgid="9218189832115847253">"Pindahkan ke kiri"</string>
+    <string name="accessibility_action_divider_move_right" msgid="4671522715182567972">"Pindahkan ke kanan"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-in/strings_tv.xml b/packages/SystemUI/res/values-in/strings_tv.xml
new file mode 100644
index 0000000..f631513
--- /dev/null
+++ b/packages/SystemUI/res/values-in/strings_tv.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.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="pip_close" msgid="3480680679023423574">"Tutup PIP"</string>
+    <string name="pip_fullscreen" msgid="8604643018538487816">"Layar penuh"</string>
+    <string name="pip_play" msgid="674145557658227044">"Putar"</string>
+    <string name="pip_pause" msgid="8412075640017218862">"Jeda"</string>
+    <string name="pip_hold_home" msgid="340086535668778109">"Tahan "<b>"LAYAR UTAMA"</b>" untuk mengontrol PIP"</string>
+    <string name="pip_onboarding_description" msgid="2627737116380318292">"Tekan dan tahan tombol LAYAR UTAMA\nuntuk mengontrol PIP"</string>
+    <string name="pip_onboarding_button" msgid="3957426748484904611">"Mengerti"</string>
+</resources>
diff --git a/packages/SystemUI/res/values-is-rIS/strings.xml b/packages/SystemUI/res/values-is-rIS/strings.xml
index 608ec51..1932595 100644
--- a/packages/SystemUI/res/values-is-rIS/strings.xml
+++ b/packages/SystemUI/res/values-is-rIS/strings.xml
@@ -73,7 +73,8 @@
     <string name="screenshot_saved_title" msgid="6461865960961414961">"Skjámynd var tekin."</string>
     <string name="screenshot_saved_text" msgid="1152839647677558815">"Snertu til að skoða skjámyndina."</string>
     <string name="screenshot_failed_title" msgid="705781116746922771">"Ekki tókst að taka skjámynd."</string>
-    <string name="screenshot_failed_text" msgid="1260203058661337274">"Ekki hægt að taka skjámynd vegna takmarkaðs pláss eða forritið eða notendaskipanin leyfir það ekki."</string>
+    <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Ekki tókst að vista skjámynd vegna takmarkaðs geymslupláss."</string>
+    <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Forritið eða fyrirtækið þitt leyfir ekki að teknar séu skjámyndir."</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"Valkostir USB-skráaflutnings"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Tengja sem efnisspilara (MTP)"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"Tengja sem myndavél (PTP)"</string>
@@ -206,6 +207,7 @@
     <string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"Meiri tími."</string>
     <string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"Minni tími."</string>
     <string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"Slökkt á vasaljósi."</string>
+    <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"Vasaljós ekki tiltækt"</string>
     <string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"Kveikt á vasaljósi."</string>
     <string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"Slökkt á vasaljósi."</string>
     <string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"Kveikt á vasaljósi."</string>
@@ -218,6 +220,10 @@
     <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"Kveikt á vinnustillingu."</string>
     <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"Slökkt á vinnustillingu."</string>
     <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"Kveikt á vinnustillingu."</string>
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_off (650231949881093289) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_on (4218725402373934151) -->
+    <skip />
     <string name="accessibility_brightness" msgid="8003681285547803095">"Birtustig skjás"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"Slökkt er á 2G- og 3G-gögnum"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"Slökkt er á 4G-gögnum"</string>
@@ -304,6 +310,8 @@
     <string name="recents_launch_disabled_message" msgid="1624523193008871793">"Slökkt er á <xliff:g id="APP">%s</xliff:g> í öruggri stillingu."</string>
     <string name="recents_history_button_label" msgid="5153358867807604821">"Ferill"</string>
     <string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"Hreinsa"</string>
+    <string name="recents_drag_non_dockable_task_message" msgid="2935843902795166158">"Þetta forrit styður ekki marga glugga"</string>
+    <string name="recents_launch_non_dockable_task_label" msgid="7862379814938391888">"Forritið styður ekki marga glugga"</string>
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Lárétt skipting"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Lóðrétt skipting"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Sérsniðin skipting"</string>
@@ -451,18 +459,23 @@
     <string name="enable_bluetooth_title" msgid="5027037706500635269">"Kveikja á Bluetooth?"</string>
     <string name="enable_bluetooth_message" msgid="9106595990708985385">"Til að geta tengt lyklaborðið við spjaldtölvuna þarftu fyrst að kveikja á Bluetooth."</string>
     <string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"Kveikja"</string>
-    <string name="apply_to_topic" msgid="3641403489318659666">"Láta gilda um tilkynningar varðandi <xliff:g id="TOPIC_NAME">%1$s</xliff:g>"</string>
-    <string name="apply_to_app" msgid="363016783939815960">"Láta gilda um allar tilkynningar frá þessu forriti"</string>
+    <string name="show_silently" msgid="6841966539811264192">"Sýna tilkynningar án hljóðs"</string>
+    <string name="block" msgid="2734508760962682611">"Loka á allar tilkynningar"</string>
+    <string name="do_not_silence" msgid="6878060322594892441">"Ekki þagga"</string>
+    <string name="do_not_silence_block" msgid="4070647971382232311">"Hvorki þagga né útiloka"</string>
+    <string name="tuner_full_importance_settings" msgid="8103289238676424226">"Sýna stillingar fyrir mikilvægi"</string>
     <string name="blocked_importance" msgid="5198578988978234161">"Útilokuð"</string>
+    <string name="min_importance" msgid="1901894910809414782">"Lítill forgangur"</string>
     <string name="low_importance" msgid="4109929986107147930">"Ekki svo mikilvægt"</string>
     <string name="default_importance" msgid="8192107689995742653">"Venjulegt mikilvægi"</string>
     <string name="high_importance" msgid="1527066195614050263">"Mjög mikilvægt"</string>
     <string name="max_importance" msgid="5089005872719563894">"Afar áríðandi"</string>
     <string name="notification_importance_blocked" msgid="2397192642657872872">"Aldrei sýna þessar tilkynningar"</string>
-    <string name="notification_importance_low" msgid="4383563267370859725">"Sýna neðst á tilkynningalistanum án hljóðs"</string>
-    <string name="notification_importance_default" msgid="4926529615920610817">"Sýna þessar tilkynningar án hljóðs"</string>
-    <string name="notification_importance_high" msgid="3222680136612408223">"Sýna efst á tilkynningalistanum og spila hljóð"</string>
-    <string name="notification_importance_max" msgid="5236987171904756134">"Birta á skjánum og spila hljóð"</string>
+    <string name="notification_importance_min" msgid="1938190340516905748">"Sýna neðst á tilkynningalistanum án hljóðs"</string>
+    <string name="notification_importance_low" msgid="3657252049508213048">"Sýna þessar tilkynningar án hljóðs"</string>
+    <string name="notification_importance_default" msgid="4466466472622442175">"Leyfa þessum tilkynningum að spila hljóð"</string>
+    <string name="notification_importance_high" msgid="2135428926525093825">"Birta á skjánum og leyfa hljóð"</string>
+    <string name="notification_importance_max" msgid="5806278962376556491">"Sýna efst á tilkynningalistanum, birta á skjánum og leyfa hljóð"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"Fleiri stillingar"</string>
     <string name="notification_done" msgid="5279426047273930175">"Lokið"</string>
     <string name="color_and_appearance" msgid="1254323855964993144">"Litur og útlit"</string>
@@ -476,7 +489,7 @@
     <string name="use_dark_theme" msgid="2900938704964299312">"Nota dökkt þema fyrir Android OS"</string>
     <string name="adjust_tint" msgid="3398569573231409878">"Stilla litblæ"</string>
     <string name="adjust_brightness" msgid="980039329808178246">"Stilla birtustig"</string>
-    <string name="night_mode_disclaimer" msgid="3297928749219711334">"Dökka þemað er notað á þeim aðalsvæðum Android OS sem venjulega eru ljós, s.s. stillingum og tilkynningum."</string>
+    <string name="night_mode_disclaimer" msgid="598914896926759578">"Dökka þemað er notað á þeim aðalsvæðum Android OS sem venjulega eru ljós, s.s. í stillingum."</string>
     <string name="color_apply" msgid="9212602012641034283">"Nota"</string>
     <string name="color_revert_title" msgid="4746666545480534663">"Staðfesta stillingar"</string>
     <string name="color_revert_message" msgid="9116001069397996691">"Sumar litastillingar kunna að bitna á notagildi tækisins. Veldu „Í lagi“ til að staðfesta þessar litastillingar, að öðrum kosti verða litirnir endurstilltir eftir tíu sekúndur."</string>
@@ -535,4 +548,10 @@
     <item msgid="2139628951880142927">"Sýna hlutfall meðan á hleðslu stendur (sjálfgefið)"</item>
     <item msgid="3327323682209964956">"Ekki sýna þetta tákn"</item>
   </string-array>
+    <string name="other" msgid="4060683095962566764">"Annað"</string>
+    <string name="accessibility_divider" msgid="5903423481953635044">"Skjáskipting"</string>
+    <string name="accessibility_action_divider_move_down" msgid="704893304141890042">"Færa niður"</string>
+    <string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"Færa upp"</string>
+    <string name="accessibility_action_divider_move_left" msgid="9218189832115847253">"Færa til vinstri"</string>
+    <string name="accessibility_action_divider_move_right" msgid="4671522715182567972">"Færa til hægri"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-is-rIS/strings_tv.xml b/packages/SystemUI/res/values-is-rIS/strings_tv.xml
new file mode 100644
index 0000000..b44aaf0
--- /dev/null
+++ b/packages/SystemUI/res/values-is-rIS/strings_tv.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.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="pip_close" msgid="3480680679023423574">"Loka mynd í mynd"</string>
+    <string name="pip_fullscreen" msgid="8604643018538487816">"Allur skjárinn"</string>
+    <string name="pip_play" msgid="674145557658227044">"Spila"</string>
+    <string name="pip_pause" msgid="8412075640017218862">"Hlé"</string>
+    <string name="pip_hold_home" msgid="340086535668778109">"Haltu "<b>"HOME"</b>"-hnappinum inni til að stjórna innfelldri mynd"</string>
+    <string name="pip_onboarding_description" msgid="2627737116380318292">"Haltu HOME\n-hnappinum inni til að stjórna innfelldri mynd"</string>
+    <string name="pip_onboarding_button" msgid="3957426748484904611">"Ég skil"</string>
+</resources>
diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml
index ee6c3ee..34faece 100644
--- a/packages/SystemUI/res/values-it/strings.xml
+++ b/packages/SystemUI/res/values-it/strings.xml
@@ -73,7 +73,8 @@
     <string name="screenshot_saved_title" msgid="6461865960961414961">"Screenshot acquisito."</string>
     <string name="screenshot_saved_text" msgid="1152839647677558815">"Tocca per visualizzare il tuo screenshot."</string>
     <string name="screenshot_failed_title" msgid="705781116746922771">"Impossibile acquisire lo screenshot."</string>
-    <string name="screenshot_failed_text" msgid="1260203058661337274">"Imposs. acquisire screenshot per spazio archiviazione limitato o perché vietato da organizzazione o app."</string>
+    <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Impossibile salvare lo screenshot a causa dello spazio di archiviazione limitato."</string>
+    <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"L\'acquisizione di screenshot non è consentita dall\'app o dall\'organizzazione."</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"Opzioni trasferimento file USB"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Monta come lettore multimediale (MTP)"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"Monta come videocamera (PTP)"</string>
@@ -206,6 +207,7 @@
     <string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"Più tempo."</string>
     <string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"Meno tempo."</string>
     <string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"Torcia spenta."</string>
+    <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"Torcia non disponibile."</string>
     <string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"Torcia accesa."</string>
     <string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"Torcia disattivata."</string>
     <string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"Torcia attivata."</string>
@@ -218,6 +220,10 @@
     <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"Modalità Lavoro attiva."</string>
     <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"Modalità Lavoro disattivata."</string>
     <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"Modalità Lavoro attivata."</string>
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_off (650231949881093289) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_on (4218725402373934151) -->
+    <skip />
     <string name="accessibility_brightness" msgid="8003681285547803095">"Luminosità dello schermo"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"Dati 2G-3G sospesi"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"Dati 4G sospesi"</string>
@@ -304,6 +310,8 @@
     <string name="recents_launch_disabled_message" msgid="1624523193008871793">"L\'app <xliff:g id="APP">%s</xliff:g> è stata disattivata in modalità provvisoria."</string>
     <string name="recents_history_button_label" msgid="5153358867807604821">"Cronologia"</string>
     <string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"Cancella"</string>
+    <string name="recents_drag_non_dockable_task_message" msgid="2935843902795166158">"Questa app non supporta la modalità multi-finestra"</string>
+    <string name="recents_launch_non_dockable_task_label" msgid="7862379814938391888">"L\'app non supporta la modalità multi-finestra"</string>
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Divisione in orizzontale"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Divisione in verticale"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Divisione personalizzata"</string>
@@ -451,18 +459,23 @@
     <string name="enable_bluetooth_title" msgid="5027037706500635269">"Attivare il Bluetooth?"</string>
     <string name="enable_bluetooth_message" msgid="9106595990708985385">"Per connettere la tastiera al tablet, devi prima attivare il Bluetooth."</string>
     <string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"Attiva"</string>
-    <string name="apply_to_topic" msgid="3641403489318659666">"Applica a notifiche <xliff:g id="TOPIC_NAME">%1$s</xliff:g>"</string>
-    <string name="apply_to_app" msgid="363016783939815960">"Applica a tutte le notifiche di quest\'app"</string>
+    <string name="show_silently" msgid="6841966539811264192">"Mostra le notifiche silenziosamente"</string>
+    <string name="block" msgid="2734508760962682611">"Blocca tutte le notifiche"</string>
+    <string name="do_not_silence" msgid="6878060322594892441">"Non silenziare"</string>
+    <string name="do_not_silence_block" msgid="4070647971382232311">"Non silenziare e non bloccare"</string>
+    <string name="tuner_full_importance_settings" msgid="8103289238676424226">"Mostra impostazioni di importanza complete"</string>
     <string name="blocked_importance" msgid="5198578988978234161">"Bloccata"</string>
+    <string name="min_importance" msgid="1901894910809414782">"Importanza minima"</string>
     <string name="low_importance" msgid="4109929986107147930">"Importanza scarsa"</string>
     <string name="default_importance" msgid="8192107689995742653">"Importanza normale"</string>
     <string name="high_importance" msgid="1527066195614050263">"Importanza elevata"</string>
     <string name="max_importance" msgid="5089005872719563894">"Importanza urgente"</string>
     <string name="notification_importance_blocked" msgid="2397192642657872872">"Non mostrare mai queste notifiche"</string>
-    <string name="notification_importance_low" msgid="4383563267370859725">"Mostra silenziosamente nella parte inferiore dell\'elenco delle notifiche"</string>
-    <string name="notification_importance_default" msgid="4926529615920610817">"Mostra silenziosamente queste notifiche"</string>
-    <string name="notification_importance_high" msgid="3222680136612408223">"Mostra nella parte superiore dell\'elenco delle notifiche e riproduci suono"</string>
-    <string name="notification_importance_max" msgid="5236987171904756134">"Apri sullo schermo e riproduci suono"</string>
+    <string name="notification_importance_min" msgid="1938190340516905748">"Mostra silenziosamente in fondo all\'elenco delle notifiche"</string>
+    <string name="notification_importance_low" msgid="3657252049508213048">"Mostra queste notifiche silenziosamente"</string>
+    <string name="notification_importance_default" msgid="4466466472622442175">"Attiva l\'audio per queste notifiche"</string>
+    <string name="notification_importance_high" msgid="2135428926525093825">"Visualizza sullo schermo e attiva l\'audio"</string>
+    <string name="notification_importance_max" msgid="5806278962376556491">"Mostra in cima all\'elenco delle notifiche, visualizza sullo schermo e attiva l\'audio"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"Altre impostazioni"</string>
     <string name="notification_done" msgid="5279426047273930175">"Fine"</string>
     <string name="color_and_appearance" msgid="1254323855964993144">"Colore e aspetto"</string>
@@ -476,7 +489,7 @@
     <string name="use_dark_theme" msgid="2900938704964299312">"Utilizza tema scuro per sistema Android"</string>
     <string name="adjust_tint" msgid="3398569573231409878">"Regola tinta"</string>
     <string name="adjust_brightness" msgid="980039329808178246">"Regola luminosità"</string>
-    <string name="night_mode_disclaimer" msgid="3297928749219711334">"Il tema scuro viene applicato agli elementi fondamentali del sistema operativo Android che vengono generalmente visualizzati con un tema chiaro, ad esempio impostazioni e notifiche."</string>
+    <string name="night_mode_disclaimer" msgid="598914896926759578">"Il tema scuro viene applicato agli elementi fondamentali del sistema operativo Android che vengono generalmente visualizzati con un tema chiaro, ad esempio le impostazioni."</string>
     <string name="color_apply" msgid="9212602012641034283">"Applica"</string>
     <string name="color_revert_title" msgid="4746666545480534663">"Conferma le impostazioni"</string>
     <string name="color_revert_message" msgid="9116001069397996691">"Alcune impostazioni relative ai colori potrebbero rendere inutilizzabile il dispositivo. Fai clic su OK per confermare queste impostazioni; in caso contrario, le impostazioni verranno reimpostate dopo 10 secondi."</string>
@@ -535,4 +548,10 @@
     <item msgid="2139628951880142927">"Mostra la percentuale quando in carica (opzione predefinita)"</item>
     <item msgid="3327323682209964956">"Non mostrare questa icona"</item>
   </string-array>
+    <string name="other" msgid="4060683095962566764">"Altro"</string>
+    <string name="accessibility_divider" msgid="5903423481953635044">"Strumento per schermo diviso"</string>
+    <string name="accessibility_action_divider_move_down" msgid="704893304141890042">"Sposta giù"</string>
+    <string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"Sposta su"</string>
+    <string name="accessibility_action_divider_move_left" msgid="9218189832115847253">"Sposta a sinistra"</string>
+    <string name="accessibility_action_divider_move_right" msgid="4671522715182567972">"Sposta a destra"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-it/strings_tv.xml b/packages/SystemUI/res/values-it/strings_tv.xml
new file mode 100644
index 0000000..08f2b67
--- /dev/null
+++ b/packages/SystemUI/res/values-it/strings_tv.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.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="pip_close" msgid="3480680679023423574">"Chiudi visualizzazione PIP"</string>
+    <string name="pip_fullscreen" msgid="8604643018538487816">"Schermo intero"</string>
+    <string name="pip_play" msgid="674145557658227044">"Riproduci"</string>
+    <string name="pip_pause" msgid="8412075640017218862">"Pausa"</string>
+    <string name="pip_hold_home" msgid="340086535668778109">"Tieni premuto "<b>"HOME"</b>" per controllare la visualizzazione PIP"</string>
+    <string name="pip_onboarding_description" msgid="2627737116380318292">"Premi e tieni premuto HOME\nper controllare la visualizzazione PIP"</string>
+    <string name="pip_onboarding_button" msgid="3957426748484904611">"OK"</string>
+</resources>
diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml
index 8af9575..9beed4f 100644
--- a/packages/SystemUI/res/values-iw/strings.xml
+++ b/packages/SystemUI/res/values-iw/strings.xml
@@ -75,7 +75,8 @@
     <string name="screenshot_saved_title" msgid="6461865960961414961">"צילום המסך בוצע."</string>
     <string name="screenshot_saved_text" msgid="1152839647677558815">"גע כדי להציג את צילום המסך שלך"</string>
     <string name="screenshot_failed_title" msgid="705781116746922771">"לא ניתן לבצע צילום מסך."</string>
-    <string name="screenshot_failed_text" msgid="1260203058661337274">"לא ניתן לצלם את המסך מפני שנפח האחסון מוגבל או מפני שהאפליקציה או הארגון שלך אינם מתירים זאת."</string>
+    <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"לא ניתן לשמור צילום מסך עקב שטח אחסון מוגבל."</string>
+    <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"האפליקציה, או הארגון שלך, אינם מתירים לבצע צילומי מסך."</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"‏אפשרויות העברת קבצים ב-USB"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"‏טען כנגן מדיה (MTP)"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"‏טען כמצלמה (PTP)"</string>
@@ -208,6 +209,7 @@
     <string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"יותר זמן."</string>
     <string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"פחות זמן."</string>
     <string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"הפנס כבוי."</string>
+    <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"פנס אינו זמין."</string>
     <string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"הפנס מופעל."</string>
     <string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"הפנס נכבה."</string>
     <string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"הפנס הופעל."</string>
@@ -220,6 +222,10 @@
     <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"מצב עבודה מופעל."</string>
     <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"מצב עבודה הושבת."</string>
     <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"מצב עבודה הופעל."</string>
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_off (650231949881093289) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_on (4218725402373934151) -->
+    <skip />
     <string name="accessibility_brightness" msgid="8003681285547803095">"בהירות תצוגה"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"‏השימוש בנתוני 2G-3G מושהה"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"‏השימוש בנתוני 4G מושהה"</string>
@@ -306,6 +312,8 @@
     <string name="recents_launch_disabled_message" msgid="1624523193008871793">"<xliff:g id="APP">%s</xliff:g> מושבת במצב בטוח."</string>
     <string name="recents_history_button_label" msgid="5153358867807604821">"היסטוריה"</string>
     <string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"נקה"</string>
+    <string name="recents_drag_non_dockable_task_message" msgid="2935843902795166158">"אפליקציה זו אינה תומכת בריבוי חלונות"</string>
+    <string name="recents_launch_non_dockable_task_label" msgid="7862379814938391888">"האפליקציה אינה תומכת בריבוי חלונות"</string>
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"פיצול אופקי"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"פיצול אנכי"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"פיצול מותאם אישית"</string>
@@ -453,18 +461,23 @@
     <string name="enable_bluetooth_title" msgid="5027037706500635269">"‏האם להפעיל את ה-Bluetooth?"</string>
     <string name="enable_bluetooth_message" msgid="9106595990708985385">"‏כדי לחבר את המקלדת לטאבלט, תחילה עליך להפעיל את ה-Bluetooth."</string>
     <string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"הפעל"</string>
-    <string name="apply_to_topic" msgid="3641403489318659666">"החל על הודעות של <xliff:g id="TOPIC_NAME">%1$s</xliff:g>"</string>
-    <string name="apply_to_app" msgid="363016783939815960">"החל על כל ההודעות מאפליקציה זו"</string>
+    <string name="show_silently" msgid="6841966539811264192">"הצג הודעות בלי להשמיע צליל"</string>
+    <string name="block" msgid="2734508760962682611">"חסום את כל ההודעות"</string>
+    <string name="do_not_silence" msgid="6878060322594892441">"לא להשתיק"</string>
+    <string name="do_not_silence_block" msgid="4070647971382232311">"לא להשתיק או לחסום"</string>
+    <string name="tuner_full_importance_settings" msgid="8103289238676424226">"הצג את הגדרות החשיבות במלואן"</string>
     <string name="blocked_importance" msgid="5198578988978234161">"חסום"</string>
+    <string name="min_importance" msgid="1901894910809414782">"חשיבות מינימלית"</string>
     <string name="low_importance" msgid="4109929986107147930">"חשיבות נמוכה"</string>
     <string name="default_importance" msgid="8192107689995742653">"חשיבות רגילה"</string>
     <string name="high_importance" msgid="1527066195614050263">"חשיבות גבוהה"</string>
     <string name="max_importance" msgid="5089005872719563894">"חשיבות דחופה"</string>
     <string name="notification_importance_blocked" msgid="2397192642657872872">"לעולם אל תציג את ההודעות האלה"</string>
-    <string name="notification_importance_low" msgid="4383563267370859725">"הצג בחלק התחתון של רשימת ההודעות בלי להשמיע צליל"</string>
-    <string name="notification_importance_default" msgid="4926529615920610817">"הצג את ההודעות האלה בלי להשמיע צליל"</string>
-    <string name="notification_importance_high" msgid="3222680136612408223">"הצג בחלק העליון של רשימת ההודעות והשמע צליל"</string>
-    <string name="notification_importance_max" msgid="5236987171904756134">"הצג לרגע על המסך והשמע צליל"</string>
+    <string name="notification_importance_min" msgid="1938190340516905748">"הצג בסוף רשימת ההודעות בלי להשמיע צליל"</string>
+    <string name="notification_importance_low" msgid="3657252049508213048">"הצג את ההודעות האלה בלי להשמיע צליל"</string>
+    <string name="notification_importance_default" msgid="4466466472622442175">"אשר להודעות אלה להשמיע צליל"</string>
+    <string name="notification_importance_high" msgid="2135428926525093825">"הצג לרגע על גבי המסך ואשר השמעת צליל"</string>
+    <string name="notification_importance_max" msgid="5806278962376556491">"הצג בראש רשימת ההודעות, הצג לרגע על גבי המסך ואשר השמעת צליל"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"הגדרות נוספות"</string>
     <string name="notification_done" msgid="5279426047273930175">"סיום"</string>
     <string name="color_and_appearance" msgid="1254323855964993144">"צבע ומראה"</string>
@@ -478,7 +491,7 @@
     <string name="use_dark_theme" msgid="2900938704964299312">"‏השתמש בעיצוב כהה למערכת ההפעלה של Android."</string>
     <string name="adjust_tint" msgid="3398569573231409878">"התאמת גוון"</string>
     <string name="adjust_brightness" msgid="980039329808178246">"התאמת בהירות"</string>
-    <string name="night_mode_disclaimer" msgid="3297928749219711334">"‏העיצוב הכהה מוחל על התחומים העיקריים במערכת ההפעלה של Android שמוצגים בדרך כלל בעיצוב בהיר, כמו \'הגדרות\' ו\'הודעות\'."</string>
+    <string name="night_mode_disclaimer" msgid="598914896926759578">"‏העיצוב הכהה מוחל על התחומים העיקריים במערכת ההפעלה Android שמוצגים בדרך כלל בעיצוב בהיר, כמו \'הגדרות\'."</string>
     <string name="color_apply" msgid="9212602012641034283">"החל"</string>
     <string name="color_revert_title" msgid="4746666545480534663">"אישור הגדרות"</string>
     <string name="color_revert_message" msgid="9116001069397996691">"הגדרות צבע מסוימות עלולות להפוך את המכשיר הזה לבלתי שמיש. לחץ על אישור כדי לאשר את הגדרות הצבע האלה, אחרת הגדרות אלה יתאפסו לאחר 10 שניות."</string>
@@ -537,4 +550,10 @@
     <item msgid="2139628951880142927">"הצג באחוזים בזמן טעינה (ברירת מחדל)"</item>
     <item msgid="3327323682209964956">"אל תציג את הסמל הזה"</item>
   </string-array>
+    <string name="other" msgid="4060683095962566764">"אחר"</string>
+    <string name="accessibility_divider" msgid="5903423481953635044">"מחלק מסך מפוצל"</string>
+    <string name="accessibility_action_divider_move_down" msgid="704893304141890042">"הזז למטה"</string>
+    <string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"הזז למעלה"</string>
+    <string name="accessibility_action_divider_move_left" msgid="9218189832115847253">"הזז שמאלה"</string>
+    <string name="accessibility_action_divider_move_right" msgid="4671522715182567972">"הזז ימינה"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-iw/strings_tv.xml b/packages/SystemUI/res/values-iw/strings_tv.xml
new file mode 100644
index 0000000..74297e4
--- /dev/null
+++ b/packages/SystemUI/res/values-iw/strings_tv.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.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="pip_close" msgid="3480680679023423574">"‏סגור PIP"</string>
+    <string name="pip_fullscreen" msgid="8604643018538487816">"מסך מלא"</string>
+    <string name="pip_play" msgid="674145557658227044">"הפעל"</string>
+    <string name="pip_pause" msgid="8412075640017218862">"השהה"</string>
+    <string name="pip_hold_home" msgid="340086535668778109">"‏לחץ לחיצה ארוכה על "<b>"דף הבית"</b>" כדי לשלוט ב-PIP"</string>
+    <string name="pip_onboarding_description" msgid="2627737116380318292">"‏לחץ לחיצה ארוכה על לחצן דף הבית\nכדי לשלוט ב-PIP"</string>
+    <string name="pip_onboarding_button" msgid="3957426748484904611">"הבנתי"</string>
+</resources>
diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml
index 76fdb73..b4b24ec 100644
--- a/packages/SystemUI/res/values-ja/strings.xml
+++ b/packages/SystemUI/res/values-ja/strings.xml
@@ -73,7 +73,8 @@
     <string name="screenshot_saved_title" msgid="6461865960961414961">"スクリーンショットを取得しました。"</string>
     <string name="screenshot_saved_text" msgid="1152839647677558815">"タップしてスクリーンショットを表示します。"</string>
     <string name="screenshot_failed_title" msgid="705781116746922771">"スクリーンショットをキャプチャできませんでした。"</string>
-    <string name="screenshot_failed_text" msgid="1260203058661337274">"空き容量が足りないか、アプリまたは組織によって許可されていないため、スクリーンショットは撮れません。"</string>
+    <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"空き容量が足りないため、スクリーンショットを保存できません。"</string>
+    <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"アプリまたは組織によって許可されていないため、スクリーンショットは撮れません。"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"USBファイル転送オプション"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"メディアプレーヤー(MTP)としてマウント"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"カメラ(PTP)としてマウント"</string>
@@ -206,6 +207,7 @@
     <string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"長くします。"</string>
     <string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"短くします。"</string>
     <string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"ライトがOFFです。"</string>
+    <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"ライトを使用できません。"</string>
     <string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"ライトがONです。"</string>
     <string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"ライトをOFFにしました。"</string>
     <string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"ライトをONにしました。"</string>
@@ -218,6 +220,10 @@
     <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"Work モードがオンです。"</string>
     <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"Work モードをオフにしました。"</string>
     <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"Work モードをオンにしました。"</string>
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_off (650231949881093289) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_on (4218725402373934151) -->
+    <skip />
     <string name="accessibility_brightness" msgid="8003681285547803095">"ディスプレイの明るさ"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"2G~3Gデータは一時停止中です"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"4Gデータは一時停止中です"</string>
@@ -304,6 +310,8 @@
     <string name="recents_launch_disabled_message" msgid="1624523193008871793">"「<xliff:g id="APP">%s</xliff:g>」はセーフモードでは無効になります。"</string>
     <string name="recents_history_button_label" msgid="5153358867807604821">"履歴"</string>
     <string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"消去"</string>
+    <string name="recents_drag_non_dockable_task_message" msgid="2935843902795166158">"このアプリはマルチウィンドウに対応していません"</string>
+    <string name="recents_launch_non_dockable_task_label" msgid="7862379814938391888">"アプリはマルチウィンドウに対応していません"</string>
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"横に分割"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"縦に分割"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"分割(カスタム)"</string>
@@ -451,18 +459,23 @@
     <string name="enable_bluetooth_title" msgid="5027037706500635269">"BluetoothをONにしますか?"</string>
     <string name="enable_bluetooth_message" msgid="9106595990708985385">"タブレットでキーボードに接続するには、最初にBluetoothをONにする必要があります。"</string>
     <string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"ONにする"</string>
-    <string name="apply_to_topic" msgid="3641403489318659666">"「<xliff:g id="TOPIC_NAME">%1$s</xliff:g>」の通知に適用"</string>
-    <string name="apply_to_app" msgid="363016783939815960">"このアプリからのすべての通知に適用"</string>
+    <string name="show_silently" msgid="6841966539811264192">"通知をマナーモードで表示する"</string>
+    <string name="block" msgid="2734508760962682611">"通知をすべてブロックする"</string>
+    <string name="do_not_silence" msgid="6878060322594892441">"音声で知らせる"</string>
+    <string name="do_not_silence_block" msgid="4070647971382232311">"音声で知らせる / ブロックしない"</string>
+    <string name="tuner_full_importance_settings" msgid="8103289238676424226">"重要度の設定をすべて表示"</string>
     <string name="blocked_importance" msgid="5198578988978234161">"ブロック中"</string>
+    <string name="min_importance" msgid="1901894910809414782">"重要度: 最低"</string>
     <string name="low_importance" msgid="4109929986107147930">"重要度: 低"</string>
     <string name="default_importance" msgid="8192107689995742653">"重要度: 中"</string>
     <string name="high_importance" msgid="1527066195614050263">"重要度: 高"</string>
     <string name="max_importance" msgid="5089005872719563894">"重要度: 緊急"</string>
     <string name="notification_importance_blocked" msgid="2397192642657872872">"今後はこの通知を表示しない"</string>
-    <string name="notification_importance_low" msgid="4383563267370859725">"通知リストの末尾にマナーモードで表示する"</string>
-    <string name="notification_importance_default" msgid="4926529615920610817">"この通知をマナーモードで表示する"</string>
-    <string name="notification_importance_high" msgid="3222680136612408223">"通知リストの先頭に表示し、音声でも知らせる"</string>
-    <string name="notification_importance_max" msgid="5236987171904756134">"画面に数秒間表示し、音声でも知らせる"</string>
+    <string name="notification_importance_min" msgid="1938190340516905748">"通知リストの末尾にマナーモードで表示する"</string>
+    <string name="notification_importance_low" msgid="3657252049508213048">"この通知をマナーモードで表示する"</string>
+    <string name="notification_importance_default" msgid="4466466472622442175">"通知を音声で知らせる"</string>
+    <string name="notification_importance_high" msgid="2135428926525093825">"画面に数秒間表示し、音声でも知らせる"</string>
+    <string name="notification_importance_max" msgid="5806278962376556491">"通知リストの先頭に表示し、画面に数秒間表示し、音声でも知らせる"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"詳細設定"</string>
     <string name="notification_done" msgid="5279426047273930175">"完了"</string>
     <string name="color_and_appearance" msgid="1254323855964993144">"色と表示"</string>
@@ -476,7 +489,7 @@
     <string name="use_dark_theme" msgid="2900938704964299312">"Android OS でダークテーマを使用"</string>
     <string name="adjust_tint" msgid="3398569573231409878">"ティントを調整"</string>
     <string name="adjust_brightness" msgid="980039329808178246">"明るさを調整"</string>
-    <string name="night_mode_disclaimer" msgid="3297928749219711334">"通常ライトテーマで表示される Android OS の主要領域(設定や通知など)にダークテーマが適用されます。"</string>
+    <string name="night_mode_disclaimer" msgid="598914896926759578">"通常ライトテーマで表示される Android OS の主要領域(設定など)にダークテーマが適用されます。"</string>
     <string name="color_apply" msgid="9212602012641034283">"適用"</string>
     <string name="color_revert_title" msgid="4746666545480534663">"設定の確認"</string>
     <string name="color_revert_message" msgid="9116001069397996691">"一部の色設定を適用すると、この端末を使用できなくなることがあります。この色設定を確認するには、[OK] をクリックしてください。確認しない場合、10 秒後に設定はリセットされます。"</string>
@@ -497,12 +510,9 @@
     <string name="headset" msgid="4534219457597457353">"ヘッドセット"</string>
     <string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"ヘッドホンを接続しました"</string>
     <string name="accessibility_status_bar_headset" msgid="8666419213072449202">"ヘッドセットを接続しました"</string>
-    <!-- no translation found for data_saver (5037565123367048522) -->
-    <skip />
-    <!-- no translation found for accessibility_data_saver_on (8454111686783887148) -->
-    <skip />
-    <!-- no translation found for accessibility_data_saver_off (8841582529453005337) -->
-    <skip />
+    <string name="data_saver" msgid="5037565123367048522">"データセーバー"</string>
+    <string name="accessibility_data_saver_on" msgid="8454111686783887148">"データセーバー ON"</string>
+    <string name="accessibility_data_saver_off" msgid="8841582529453005337">"データセーバー OFF"</string>
     <string name="switch_bar_on" msgid="1142437840752794229">"ON"</string>
     <string name="switch_bar_off" msgid="8803270596930432874">"OFF"</string>
     <string name="nav_bar" msgid="1993221402773877607">"ナビゲーション バー"</string>
@@ -538,4 +548,10 @@
     <item msgid="2139628951880142927">"変更時に割合を表示(デフォルト)"</item>
     <item msgid="3327323682209964956">"このアイコンを表示しない"</item>
   </string-array>
+    <string name="other" msgid="4060683095962566764">"その他"</string>
+    <string name="accessibility_divider" msgid="5903423481953635044">"分割画面の分割線"</string>
+    <string name="accessibility_action_divider_move_down" msgid="704893304141890042">"下に移動"</string>
+    <string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"上に移動"</string>
+    <string name="accessibility_action_divider_move_left" msgid="9218189832115847253">"左に移動"</string>
+    <string name="accessibility_action_divider_move_right" msgid="4671522715182567972">"右に移動"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ja/strings_tv.xml b/packages/SystemUI/res/values-ja/strings_tv.xml
new file mode 100644
index 0000000..8c56866
--- /dev/null
+++ b/packages/SystemUI/res/values-ja/strings_tv.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2016, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <!-- no translation found for pip_close (3480680679023423574) -->
+    <skip />
+    <string name="pip_fullscreen" msgid="8604643018538487816">"全画面表示"</string>
+    <string name="pip_play" msgid="674145557658227044">"再生"</string>
+    <string name="pip_pause" msgid="8412075640017218862">"一時停止"</string>
+    <!-- no translation found for pip_hold_home (340086535668778109) -->
+    <skip />
+    <!-- no translation found for pip_onboarding_description (2627737116380318292) -->
+    <skip />
+    <!-- no translation found for pip_onboarding_button (3957426748484904611) -->
+    <skip />
+</resources>
diff --git a/packages/SystemUI/res/values-ka-rGE/strings.xml b/packages/SystemUI/res/values-ka-rGE/strings.xml
index 6963770..4c461de 100644
--- a/packages/SystemUI/res/values-ka-rGE/strings.xml
+++ b/packages/SystemUI/res/values-ka-rGE/strings.xml
@@ -73,7 +73,8 @@
     <string name="screenshot_saved_title" msgid="6461865960961414961">"სკრინშოტი გადაღებულია."</string>
     <string name="screenshot_saved_text" msgid="1152839647677558815">"შეეხეთ ეკრანის სურათის სანახავად."</string>
     <string name="screenshot_failed_title" msgid="705781116746922771">"ვერ მოხერხდა ეკრანის ანაბეჭდის გადაღება."</string>
-    <string name="screenshot_failed_text" msgid="1260203058661337274">"ეკრანის ანაბეჭდი ვერ შეიქმნა შეზღუდული სივრცის გამო, ან შეზღუდულია თქვენი ორგანიზაციის აპის მიერ."</string>
+    <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"ეკრანის ანაბეჭდის შენახვა ვერ მოხერხდა შეზღუდული მეხსიერების გამო."</string>
+    <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"ეკრანის ანაბეჭდების შექმნა არ არის ნებადართული აპის ან თქვენი ორგანიზაციის მიერ."</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"USB ფაილის ტრანსფერის პარამეტრები"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"მედია-საკრავად (MTP) ჩართვა"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"მიუერთეთ როგორც კამერა (PTP)"</string>
@@ -206,6 +207,7 @@
     <string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"მეტი დრო."</string>
     <string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"ნაკლები დრო."</string>
     <string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"ფანარი გამორთულია."</string>
+    <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"ფანარი მიუწვდომელია."</string>
     <string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"ფანარი ჩართულია."</string>
     <string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"ფანარი გამოირთო."</string>
     <string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"ფანარი ჩაირთო."</string>
@@ -218,6 +220,10 @@
     <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"სამსახურის რეჟიმი ჩართულია."</string>
     <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"სამსახურის რეჟიმი გამორთულია."</string>
     <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"სამსახურის რეჟიმი ჩართულია."</string>
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_off (650231949881093289) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_on (4218725402373934151) -->
+    <skip />
     <string name="accessibility_brightness" msgid="8003681285547803095">"ეკრანის სიკაშკაშე"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"2G-3G მონაცემები შეჩერებულია"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"4G მონაცემები შეჩერებულია"</string>
@@ -304,6 +310,8 @@
     <string name="recents_launch_disabled_message" msgid="1624523193008871793">"<xliff:g id="APP">%s</xliff:g> გათიშულია უსაფრთხო რეჟიმში."</string>
     <string name="recents_history_button_label" msgid="5153358867807604821">"ისტორია"</string>
     <string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"გასუფთავება"</string>
+    <string name="recents_drag_non_dockable_task_message" msgid="2935843902795166158">"მრავალი ფანჯრის რეჟიმი არ არის მხარდაჭერილი ამ აპის მიერ"</string>
+    <string name="recents_launch_non_dockable_task_label" msgid="7862379814938391888">"მრავალი ფანჯრის რეჟიმი არ არის მხარდაჭერილი აპის მიერ"</string>
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"ჰორიზონტალური გაყოფა"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"ვერტიკალური გაყოფა"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"ინდივიდუალური გაყობა"</string>
@@ -451,18 +459,23 @@
     <string name="enable_bluetooth_title" msgid="5027037706500635269">"გსურთ Bluetooth-ის ჩართვა?"</string>
     <string name="enable_bluetooth_message" msgid="9106595990708985385">"კლავიატურის ტაბლეტთან დასაკავშირებლად, ჯერ უნდა ჩართოთ Bluetooth."</string>
     <string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"ჩართვა"</string>
-    <string name="apply_to_topic" msgid="3641403489318659666">"„<xliff:g id="TOPIC_NAME">%1$s</xliff:g>“ ტიპის შეტყობინებებისთვის მისადაგება"</string>
-    <string name="apply_to_app" msgid="363016783939815960">"ამ აპის ყველა შეტყობინებისთვის მისადაგება"</string>
+    <string name="show_silently" msgid="6841966539811264192">"შეტყობინებების უხმოდ ჩვენება"</string>
+    <string name="block" msgid="2734508760962682611">"ყველა შეტყობინების დაბლოკვა"</string>
+    <string name="do_not_silence" msgid="6878060322594892441">"არ გაჩუმდეს"</string>
+    <string name="do_not_silence_block" msgid="4070647971382232311">"არ გაჩუმდეს ან დაიბლოკოს"</string>
+    <string name="tuner_full_importance_settings" msgid="8103289238676424226">"მნიშვნელობის დონის სრული პარამეტრების ჩვენება"</string>
     <string name="blocked_importance" msgid="5198578988978234161">"დაბლოკილი"</string>
+    <string name="min_importance" msgid="1901894910809414782">"მინიმალური"</string>
     <string name="low_importance" msgid="4109929986107147930">"დაბალი პრიორიტეტი"</string>
     <string name="default_importance" msgid="8192107689995742653">"ჩვეულებრივი პრიორიტეტი"</string>
     <string name="high_importance" msgid="1527066195614050263">"მაღალი პრიორიტეტი"</string>
     <string name="max_importance" msgid="5089005872719563894">"გადაუდებელი"</string>
     <string name="notification_importance_blocked" msgid="2397192642657872872">"ამ შეტყობინებების ჩვენების შეწყვეტა"</string>
-    <string name="notification_importance_low" msgid="4383563267370859725">"ამ შეტყობინებების სიის ბოლოში, უხმოდ ჩვენება"</string>
-    <string name="notification_importance_default" msgid="4926529615920610817">"ამ შეტყობინებების უხმოდ ჩვენება"</string>
-    <string name="notification_importance_high" msgid="3222680136612408223">"ამ შეტყობინებების სიის თავში, ხმოვან სიგნალთან ერთად ჩვენება"</string>
-    <string name="notification_importance_max" msgid="5236987171904756134">"ამ შეტყობინებების პირდაპირ ეკრანზე, ხმოვან სიგნალთან ერთად ჩვენება"</string>
+    <string name="notification_importance_min" msgid="1938190340516905748">"შეტყობინებების სიის ბოლოში, უხმოდ ჩვენება"</string>
+    <string name="notification_importance_low" msgid="3657252049508213048">"ამ შეტყობინებების უხმოდ ჩვენება"</string>
+    <string name="notification_importance_default" msgid="4466466472622442175">"ამ შეტყობინებებისთვის ხმის გამოცემის დაშვება"</string>
+    <string name="notification_importance_high" msgid="2135428926525093825">"შეტყობინებების პირდაპირ ეკრანზე ჩვენება და ხმის დაშვება"</string>
+    <string name="notification_importance_max" msgid="5806278962376556491">"შეტყობინებების სიის თავში ჩვენება, პირდაპირ ეკრანზე გამოჩენა და ხმის დაშვება"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"დამატებითი პარამეტრები"</string>
     <string name="notification_done" msgid="5279426047273930175">"მზადაა"</string>
     <string name="color_and_appearance" msgid="1254323855964993144">"ფერი და იერსახე"</string>
@@ -476,7 +489,7 @@
     <string name="use_dark_theme" msgid="2900938704964299312">"Android OS-ისთვის მუქი თემის გამოყენება"</string>
     <string name="adjust_tint" msgid="3398569573231409878">"ელფერის გასწორება"</string>
     <string name="adjust_brightness" msgid="980039329808178246">"სიკაშკაშის გასწორება"</string>
-    <string name="night_mode_disclaimer" msgid="3297928749219711334">"მუქი თემა მიესადაგება Android OS-ის ძირითად არეებს, რომლებიც, ჩვეულებრივ, ღია თემის მეშვეობით არის ნაჩვენები. მაგალითად, პარამეტრებს და შეტყობინებებს."</string>
+    <string name="night_mode_disclaimer" msgid="598914896926759578">"მუქი თემა მიესადაგება Android OS-ის ძირითად არეებს, რომლებიც, ჩვეულებრივ, ღია თემის მეშვეობით არის ნაჩვენები. მაგალითად, პარამეტრებს."</string>
     <string name="color_apply" msgid="9212602012641034283">"გამოყენება"</string>
     <string name="color_revert_title" msgid="4746666545480534663">"პარამეტრების დადასტურება"</string>
     <string name="color_revert_message" msgid="9116001069397996691">"ფერთა ზოგიერთ პარამეტრს ამ მოწყობილობასთან მუშაობის გართულება შეუძლია. ფერთა ამჟამინდელი პარამეტრების დასადასტურებლად, დააწკაპუნეთ „კარგი“-ზე. წინააღმდეგ შემთხვევაში, პარამეტრები 10 წამის შემდეგ ჩამოიყრება."</string>
@@ -535,4 +548,10 @@
     <item msgid="2139628951880142927">"პროცენტულობის დატენვისას ჩვენება (ნაგულისხმევი)"</item>
     <item msgid="3327323682209964956">"აღარ მაჩვენო ეს ხატულა"</item>
   </string-array>
+    <string name="other" msgid="4060683095962566764">"სხვა"</string>
+    <string name="accessibility_divider" msgid="5903423481953635044">"გაყოფილი ეკრანის რეჟიმის გამყოფი"</string>
+    <string name="accessibility_action_divider_move_down" msgid="704893304141890042">"ქვემოთ გადატანა"</string>
+    <string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"ზემოთ გადატანა"</string>
+    <string name="accessibility_action_divider_move_left" msgid="9218189832115847253">"მარცხნივ გადატანა"</string>
+    <string name="accessibility_action_divider_move_right" msgid="4671522715182567972">"მარჯვნივ გადატანა"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ka-rGE/strings_tv.xml b/packages/SystemUI/res/values-ka-rGE/strings_tv.xml
new file mode 100644
index 0000000..9c5b0d6
--- /dev/null
+++ b/packages/SystemUI/res/values-ka-rGE/strings_tv.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2016, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <!-- no translation found for pip_close (3480680679023423574) -->
+    <skip />
+    <string name="pip_fullscreen" msgid="8604643018538487816">"სრულ ეკრანზე"</string>
+    <string name="pip_play" msgid="674145557658227044">"დაკვრა"</string>
+    <string name="pip_pause" msgid="8412075640017218862">"პაუზა"</string>
+    <!-- no translation found for pip_hold_home (340086535668778109) -->
+    <skip />
+    <!-- no translation found for pip_onboarding_description (2627737116380318292) -->
+    <skip />
+    <!-- no translation found for pip_onboarding_button (3957426748484904611) -->
+    <skip />
+</resources>
diff --git a/packages/SystemUI/res/values-kk-rKZ/strings.xml b/packages/SystemUI/res/values-kk-rKZ/strings.xml
index 60ab9f8..f1c09d8 100644
--- a/packages/SystemUI/res/values-kk-rKZ/strings.xml
+++ b/packages/SystemUI/res/values-kk-rKZ/strings.xml
@@ -73,7 +73,8 @@
     <string name="screenshot_saved_title" msgid="6461865960961414961">"Скриншот сақталды."</string>
     <string name="screenshot_saved_text" msgid="1152839647677558815">"Скриншотты көру үшін түрту."</string>
     <string name="screenshot_failed_title" msgid="705781116746922771">"Скриншот жасалмады."</string>
-    <string name="screenshot_failed_text" msgid="1260203058661337274">"Шектеулі жад кеңістігіне байланысты скриншот түсіру мүмкін емес немесе бұған қолданба немесе ұйым рұқсат етпейді."</string>
+    <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Жадтағы шектеулі бос орынға байланысты скриншотты сақтау мүмкін емес."</string>
+    <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Қолданба немесе ұйым скриншоттар түсіруге рұқсат етпейді."</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"USB файлын жіберу опциялары"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Медиа ойнатқыш (MTP) ретінде қосыңыз"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"Камера ретінде (PTP) қосыңыз"</string>
@@ -206,6 +207,7 @@
     <string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"Көбірек уақыт."</string>
     <string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"Азырақ уақыт."</string>
     <string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"Қол шам өшірулі."</string>
+    <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"Жарқыл қол жетімді емес."</string>
     <string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"Қол шам қосулы."</string>
     <string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"Қол шам өшірілді."</string>
     <string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"Қол шам қосылды."</string>
@@ -218,6 +220,10 @@
     <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"Жұмыс режимі қосулы."</string>
     <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"Жұмыс режимі өшірілді."</string>
     <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"Жұмыс режимі қосылды."</string>
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_off (650231949881093289) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_on (4218725402373934151) -->
+    <skip />
     <string name="accessibility_brightness" msgid="8003681285547803095">"Дисплей жарықтығы"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"2G-3G деректері кідіртілді"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"4G деректері кідіртілді"</string>
@@ -301,10 +307,11 @@
     <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"экранды бекіту"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"іздеу"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g> іске қосу мүмкін болмады."</string>
-    <!-- no translation found for recents_launch_disabled_message (1624523193008871793) -->
-    <skip />
+    <string name="recents_launch_disabled_message" msgid="1624523193008871793">"<xliff:g id="APP">%s</xliff:g> қауіпсіз режимде өшіріледі."</string>
     <string name="recents_history_button_label" msgid="5153358867807604821">"Тарих"</string>
     <string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"Тазалау"</string>
+    <string name="recents_drag_non_dockable_task_message" msgid="2935843902795166158">"Бұл қолданба көп терезені қолдамайды"</string>
+    <string name="recents_launch_non_dockable_task_label" msgid="7862379814938391888">"Қолданба көп терезені қолдамайды"</string>
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Бөлінген көлденең"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Бөлінген тік"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Бөлінген теңшелетін"</string>
@@ -452,18 +459,23 @@
     <string name="enable_bluetooth_title" msgid="5027037706500635269">"Bluetooth функциясын қосу керек пе?"</string>
     <string name="enable_bluetooth_message" msgid="9106595990708985385">"Пернетақтаны планшетке қосу үшін алдымен Bluetooth функциясын қосу керек."</string>
     <string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"Қосу"</string>
-    <string name="apply_to_topic" msgid="3641403489318659666">"<xliff:g id="TOPIC_NAME">%1$s</xliff:g> хабарландыруға қолдану"</string>
-    <string name="apply_to_app" msgid="363016783939815960">"Осы қолданбаның барлық хабарландыруларына қолдану"</string>
+    <string name="show_silently" msgid="6841966539811264192">"Хабарландыруларды үнсіз көрсету"</string>
+    <string name="block" msgid="2734508760962682611">"Барлық хабарландыруларды бұғаттау"</string>
+    <string name="do_not_silence" msgid="6878060322594892441">"Үнін өшірмеу"</string>
+    <string name="do_not_silence_block" msgid="4070647971382232311">"Үнін өшірмеу немесе бұғаттамау"</string>
+    <string name="tuner_full_importance_settings" msgid="8103289238676424226">"Толық маңыздылық параметрлерін көрсету"</string>
     <string name="blocked_importance" msgid="5198578988978234161">"Бөгелген"</string>
+    <string name="min_importance" msgid="1901894910809414782">"Ең аз маңыздылық"</string>
     <string name="low_importance" msgid="4109929986107147930">"Төмен маңыздылық"</string>
     <string name="default_importance" msgid="8192107689995742653">"Қалыпты маңыздылық"</string>
     <string name="high_importance" msgid="1527066195614050263">"Жоғары маңыздылық"</string>
     <string name="max_importance" msgid="5089005872719563894">"Шұғыл маңыздылық"</string>
     <string name="notification_importance_blocked" msgid="2397192642657872872">"Осы хабарландыруларды ешқашан көрсетпеу"</string>
-    <string name="notification_importance_low" msgid="4383563267370859725">"Хабарландырулар тізімнің төменгі жағында үнсіз көрсету"</string>
-    <string name="notification_importance_default" msgid="4926529615920610817">"Осы хабарландыруларды үнсіз көрсету"</string>
-    <string name="notification_importance_high" msgid="3222680136612408223">"Хабарландыруларды тізімінің жоғарғы жағында көрсету және дыбыс шығару"</string>
-    <string name="notification_importance_max" msgid="5236987171904756134">"Экранға бекіту және дыбыс шығару"</string>
+    <string name="notification_importance_min" msgid="1938190340516905748">"Хабарландырулар тізімнің төменгі жағында үнсіз көрсету"</string>
+    <string name="notification_importance_low" msgid="3657252049508213048">"Осы хабарландыруларды үнсіз көрсету"</string>
+    <string name="notification_importance_default" msgid="4466466472622442175">"Осы хабарландыруға дыбыстар шығаруға рұқсат ету"</string>
+    <string name="notification_importance_high" msgid="2135428926525093825">"Экранда көрсету және дыбыс шығаруға рұқсат ету"</string>
+    <string name="notification_importance_max" msgid="5806278962376556491">"Хабарландырулар тізімінің жоғарғы жағында көрсету, экранда көрсету және дыбысқа рұқсат ету"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"Қосымша параметрлер"</string>
     <string name="notification_done" msgid="5279426047273930175">"Дайын"</string>
     <string name="color_and_appearance" msgid="1254323855964993144">"Түс және сыртқы түрі"</string>
@@ -477,7 +489,7 @@
     <string name="use_dark_theme" msgid="2900938704964299312">"Android ОЖ үшін күңгірт тақырыпты пайдалану"</string>
     <string name="adjust_tint" msgid="3398569573231409878">"Реңкті реттеу"</string>
     <string name="adjust_brightness" msgid="980039329808178246">"Жарықтықты реттеу"</string>
-    <string name="night_mode_disclaimer" msgid="3297928749219711334">"Күңгірт тақырып Android операциялық жүйесінің әдетте ашық тақырыпта көрсетілетін негізгі аумақтарына қолданылады, мысалы, \"Параметрлер\" тармағына және хабарландыруларға."</string>
+    <string name="night_mode_disclaimer" msgid="598914896926759578">"Күңгірт тақырып Android операциялық жүйесінің әдетте \"Параметрлер\" сияқты ашық тақырыпта көрсетілетін негізгі аумақтарына қолданылады."</string>
     <string name="color_apply" msgid="9212602012641034283">"Қолдану"</string>
     <string name="color_revert_title" msgid="4746666545480534663">"Параметрлерді растау"</string>
     <string name="color_revert_message" msgid="9116001069397996691">"Кейбір түс параметрлері бұл құрылғыны пайдалану мүмкін емес етуі мүмкін. Бұл түс параметрлерін растау үшін OK түймесін басыңыз, әйтпесе параметрлер 10 секундтан кейін ысырылады."</string>
@@ -536,4 +548,10 @@
     <item msgid="2139628951880142927">"Зарядтау кезінде пайызды көрсету (әдепкі)"</item>
     <item msgid="3327323682209964956">"Бұл белгішені көрсетпеу"</item>
   </string-array>
+    <string name="other" msgid="4060683095962566764">"Басқа"</string>
+    <string name="accessibility_divider" msgid="5903423481953635044">"Бөлінген экран бөлгіші"</string>
+    <string name="accessibility_action_divider_move_down" msgid="704893304141890042">"Төмен қарай жылжыту"</string>
+    <string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"Жоғары қарай жылжыту"</string>
+    <string name="accessibility_action_divider_move_left" msgid="9218189832115847253">"Солға жылжыту"</string>
+    <string name="accessibility_action_divider_move_right" msgid="4671522715182567972">"Оңға жылжыту"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-kk-rKZ/strings_tv.xml b/packages/SystemUI/res/values-kk-rKZ/strings_tv.xml
new file mode 100644
index 0000000..3fc3403
--- /dev/null
+++ b/packages/SystemUI/res/values-kk-rKZ/strings_tv.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2016, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <!-- no translation found for pip_close (3480680679023423574) -->
+    <skip />
+    <string name="pip_fullscreen" msgid="8604643018538487816">"Толық экран"</string>
+    <string name="pip_play" msgid="674145557658227044">"Ойнату"</string>
+    <string name="pip_pause" msgid="8412075640017218862">"Кідірту"</string>
+    <!-- no translation found for pip_hold_home (340086535668778109) -->
+    <skip />
+    <!-- no translation found for pip_onboarding_description (2627737116380318292) -->
+    <skip />
+    <!-- no translation found for pip_onboarding_button (3957426748484904611) -->
+    <skip />
+</resources>
diff --git a/packages/SystemUI/res/values-km-rKH/strings.xml b/packages/SystemUI/res/values-km-rKH/strings.xml
index 32cdbcc..845a48e 100644
--- a/packages/SystemUI/res/values-km-rKH/strings.xml
+++ b/packages/SystemUI/res/values-km-rKH/strings.xml
@@ -73,7 +73,8 @@
     <string name="screenshot_saved_title" msgid="6461865960961414961">"បាន​ចាប់​យក​រូបថត​អេក្រង់។​"</string>
     <string name="screenshot_saved_text" msgid="1152839647677558815">"ប៉ះ ​ដើម្បី​មើល​រូបថត​អេក្រង់​របស់​អ្នក​។"</string>
     <string name="screenshot_failed_title" msgid="705781116746922771">"មិន​អាច​ចាប់​យក​រូប​ថត​អេក្រង់​។"</string>
-    <string name="screenshot_failed_text" msgid="1260203058661337274">"មិនអាចថតអេក្រង់ដោយសារតែទំហំផ្ទុកមានដែនកំណត់ ឬវាមិនត្រូវបានអនុញ្ញាត​ដោយកម្មវិធី ឬ​ស្ថាប័ន​របស់​អ្នក។"</string>
+    <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"មិនអាចរក្សាទុករូបថតអេក្រង់បានទេដោយសារទំហំផ្ទុកមានកម្រិត។"</string>
+    <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"ការថតរូបអេក្រង់មិនត្រូវបានអនុញ្ញាតដោយកម្មវិធីនេះ ឬស្ថាប័នរបស់អ្នក។"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"ជម្រើស​ផ្ទេរ​ឯកសារ​តាម​យូអេសប៊ី"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"ភ្ជាប់​ជា​កម្មវិធី​ចាក់​មេឌៀ (MTP)"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"ភ្ជាប់​ជា​ម៉ាស៊ីន​ថត (PTP)"</string>
@@ -206,6 +207,7 @@
     <string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"ច្រើនជាង"</string>
     <string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"តិច​ជាង"</string>
     <string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"បិទ​ពិល។"</string>
+    <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"ពិលមិនអាចប្រើបានទេ"</string>
     <string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"បើក​ពិល។"</string>
     <string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"បាន​បិទ​ពិល។"</string>
     <string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"បាន​បើក​ពិល។"</string>
@@ -218,6 +220,10 @@
     <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"បើករបៀបការងារ"</string>
     <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"បានបិទរបៀបការងារ"</string>
     <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"បានបើករបៀបការងារ"</string>
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_off (650231949881093289) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_on (4218725402373934151) -->
+    <skip />
     <string name="accessibility_brightness" msgid="8003681285547803095">"ពន្លឺ​ការ​បង្ហាញ"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"ទិន្នន័យ 2G-3G ត្រូវបានផ្អាក"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"ទិន្នន័យ 4G ត្រូវបានផ្អាក"</string>
@@ -304,6 +310,8 @@
     <string name="recents_launch_disabled_message" msgid="1624523193008871793">"<xliff:g id="APP">%s</xliff:g> ត្រូវបានបិទដំណើរការក្នុងរបៀបសុវត្ថិភាព"</string>
     <string name="recents_history_button_label" msgid="5153358867807604821">"ប្រវត្តិ"</string>
     <string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"សម្អាត"</string>
+    <string name="recents_drag_non_dockable_task_message" msgid="2935843902795166158">"កម្មវិធីនេះមិនគាំទ្រផ្ទាំងវិដូច្រើនទេ"</string>
+    <string name="recents_launch_non_dockable_task_label" msgid="7862379814938391888">"កម្មវិធីមិនគាំទ្រផ្ទាំងវិដូច្រើនទេ"</string>
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"បំបែកផ្តេក"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"បំបែកបញ្ឈរ"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"បំបែកផ្ទាល់ខ្លួន"</string>
@@ -451,18 +459,23 @@
     <string name="enable_bluetooth_title" msgid="5027037706500635269">"បើកប៊្លូធូសឬ?"</string>
     <string name="enable_bluetooth_message" msgid="9106595990708985385">"ដើម្បីភ្ជាប់ក្តារចុចរបស់អ្នកជាមួយនឹងថេប្លេតរបស់អ្នក អ្នកត្រូវតែបើកប៊្លូធូសជាមុនសិន។"</string>
     <string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"បើក"</string>
-    <string name="apply_to_topic" msgid="3641403489318659666">"អនុវត្តចំពោះការជូនដំណឹង <xliff:g id="TOPIC_NAME">%1$s</xliff:g>"</string>
-    <string name="apply_to_app" msgid="363016783939815960">"អនុវត្តចំពោះការជូនដំណឹងទាំងអស់ពីកម្មវិធីនេះ"</string>
+    <string name="show_silently" msgid="6841966539811264192">"បង្ហាញការជូនដំណឹងស្ងាត់ៗ"</string>
+    <string name="block" msgid="2734508760962682611">"រារាំងការជូនដំណឹងទាំងអស់"</string>
+    <string name="do_not_silence" msgid="6878060322594892441">"កុំបិទសំឡេង"</string>
+    <string name="do_not_silence_block" msgid="4070647971382232311">"កុំបិទសំឡេង ឬរារាំង"</string>
+    <string name="tuner_full_importance_settings" msgid="8103289238676424226">"បង្ហាញការកំណត់កម្រិតភាពសំខាន់ពេញលេញ"</string>
     <string name="blocked_importance" msgid="5198578988978234161">"បានរារាំង"</string>
+    <string name="min_importance" msgid="1901894910809414782">"កម្រិតសំខាន់អប្បបរមា"</string>
     <string name="low_importance" msgid="4109929986107147930">"មិនសូវសំខាន់"</string>
     <string name="default_importance" msgid="8192107689995742653">"សំខាន់មធ្យម"</string>
     <string name="high_importance" msgid="1527066195614050263">"សំខាន់ខ្លាំង"</string>
     <string name="max_importance" msgid="5089005872719563894">"សំខាន់ជាបន្ទាន់"</string>
     <string name="notification_importance_blocked" msgid="2397192642657872872">"កុំបង្ហាញការជូនដំណឹងទាំងនេះ"</string>
-    <string name="notification_importance_low" msgid="4383563267370859725">"បង្ហាញស្ងាត់ៗនៅផ្នែកខាងក្រោមបញ្ជីនៃការជូនដំណឹង"</string>
-    <string name="notification_importance_default" msgid="4926529615920610817">"បង្ហាញការជូនដំណឹងទាំងនេះស្ងាត់ៗ"</string>
-    <string name="notification_importance_high" msgid="3222680136612408223">"បង្ហាញនៅផ្នែកខាងលើបញ្ជីនៃការជូនដំណឹង និងបន្លឺសំឡេង"</string>
-    <string name="notification_importance_max" msgid="5236987171904756134">"លោតបង្ហាញនៅលើអេក្រង់ និងបន្លឺសំឡេង"</string>
+    <string name="notification_importance_min" msgid="1938190340516905748">"បង្ហាញស្ងាត់ៗនៅផ្នែកខាងក្រោមបញ្ជីនៃការជូនដំណឹង"</string>
+    <string name="notification_importance_low" msgid="3657252049508213048">"បង្ហាញការជូនដំណឹងទាំងនេះស្ងាត់ៗ"</string>
+    <string name="notification_importance_default" msgid="4466466472622442175">"អនុញ្ញាតឲ្យការជូនដំណឹងទាំងនេះបន្លឺសំឡេង"</string>
+    <string name="notification_importance_high" msgid="2135428926525093825">"លោតបង្ហាញនៅលើអេក្រង់ និងអនុញ្ញាតឲ្យបន្លឺសំឡេង"</string>
+    <string name="notification_importance_max" msgid="5806278962376556491">"បង្ហាញនៅផ្នែកខាងលើបញ្ជីនៃការជូនដំណឹង លោតបង្ហាញនៅលើអេក្រង់ និងអនុញ្ញាតឲ្យបន្លឺសំឡេង"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"ការកំណត់ច្រើនទៀត"</string>
     <string name="notification_done" msgid="5279426047273930175">"រួចរាល់"</string>
     <string name="color_and_appearance" msgid="1254323855964993144">"ពណ៌ និងរូបរាង"</string>
@@ -476,7 +489,7 @@
     <string name="use_dark_theme" msgid="2900938704964299312">"ប្រើធីមងងឹតសម្រាប់ប្រព័ន្ធប្រតិបត្តិការ Android"</string>
     <string name="adjust_tint" msgid="3398569573231409878">"កែសម្រួលពណ៌ព្រឿងៗ"</string>
     <string name="adjust_brightness" msgid="980039329808178246">"កែសម្រួលពន្លឺ"</string>
-    <string name="night_mode_disclaimer" msgid="3297928749219711334">"ធីមងងឹតត្រូវបានប្រើសម្រាប់ចំណុចស្នូលនៃប្រព័ន្ធប្រតិបត្តិការ Android ដែលជាទូទៅត្រូវបានបង្ហាញជាធីមដែលភ្លឺ ដូចជាការកំណត់ និងការជូនដំណឹង។"</string>
+    <string name="night_mode_disclaimer" msgid="598914896926759578">"ធីមងងឹតត្រូវបានប្រើសម្រាប់ចំណុចស្នូលនៃប្រព័ន្ធប្រតិបត្តិការ Android ដែលជាទូទៅត្រូវបានបង្ហាញជាធីមភ្លឺ ដូចជាការកំណត់ជាដើម។"</string>
     <string name="color_apply" msgid="9212602012641034283">"អនុវត្ត"</string>
     <string name="color_revert_title" msgid="4746666545480534663">"បញ្ជាក់ការកំណត់"</string>
     <string name="color_revert_message" msgid="9116001069397996691">"ការកំណត់ពណ៌មួយចំនួនអាចធ្វើឲ្យឧបករណ៍នេះមិនអាចប្រើបាន។ សូមចុច យល់ព្រម ដើម្បីបញ្ជាក់ការកំណត់ពណ៌ទាំងនេះ បើមិនដូច្នេះទេការកំណត់ទាំងនេះនឹងកំណត់ឡើងវិញក្នុងរយៈពេល 10 វិនាទីបន្ទាប់។"</string>
@@ -535,4 +548,10 @@
     <item msgid="2139628951880142927">"បង្ហាញភាគរយនៅពេលសាកថ្ម (លំនាំដើម)"</item>
     <item msgid="3327323682209964956">"កុំបង្ហាញរូបតំណាងនេះ"</item>
   </string-array>
+    <string name="other" msgid="4060683095962566764">"ផ្សេងៗ"</string>
+    <string name="accessibility_divider" msgid="5903423481953635044">"កម្មវិធីចែកអេក្រង់បំបែក"</string>
+    <string name="accessibility_action_divider_move_down" msgid="704893304141890042">"ផ្លាស់ទីចុះក្រោម"</string>
+    <string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"ផ្លាស់ទីឡើងលើ"</string>
+    <string name="accessibility_action_divider_move_left" msgid="9218189832115847253">"ផ្លាស់ទីទៅឆ្វេង"</string>
+    <string name="accessibility_action_divider_move_right" msgid="4671522715182567972">"ផ្លាស់ទីទៅស្តាំ"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-km-rKH/strings_tv.xml b/packages/SystemUI/res/values-km-rKH/strings_tv.xml
new file mode 100644
index 0000000..4b42132
--- /dev/null
+++ b/packages/SystemUI/res/values-km-rKH/strings_tv.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2016, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <!-- no translation found for pip_close (3480680679023423574) -->
+    <skip />
+    <string name="pip_fullscreen" msgid="8604643018538487816">"ពេញអេក្រង់"</string>
+    <string name="pip_play" msgid="674145557658227044">"ចាក់"</string>
+    <string name="pip_pause" msgid="8412075640017218862">"ផ្អាក"</string>
+    <!-- no translation found for pip_hold_home (340086535668778109) -->
+    <skip />
+    <!-- no translation found for pip_onboarding_description (2627737116380318292) -->
+    <skip />
+    <!-- no translation found for pip_onboarding_button (3957426748484904611) -->
+    <skip />
+</resources>
diff --git a/packages/SystemUI/res/values-kn-rIN/strings.xml b/packages/SystemUI/res/values-kn-rIN/strings.xml
index f97c842..bf604e7 100644
--- a/packages/SystemUI/res/values-kn-rIN/strings.xml
+++ b/packages/SystemUI/res/values-kn-rIN/strings.xml
@@ -73,7 +73,8 @@
     <string name="screenshot_saved_title" msgid="6461865960961414961">"ಸ್ಕ್ರೀನ್‌ಶಾಟ್ ಸೆರೆಹಿಡಿಯಲಾಗಿದೆ."</string>
     <string name="screenshot_saved_text" msgid="1152839647677558815">"ನಿಮ್ಮ ಸ್ಕ್ರೀನ್‌ಶಾಟ್ ವೀಕ್ಷಿಸಲು ಸ್ಪರ್ಶಿಸಿ."</string>
     <string name="screenshot_failed_title" msgid="705781116746922771">"ಸ್ಕ್ರೀನ್‌ಶಾಟ್ ಸೆರೆಹಿಡಿಯಲು ಸಾಧ್ಯವಾಗುತ್ತಿಲ್ಲ."</string>
-    <string name="screenshot_failed_text" msgid="1260203058661337274">"ಪರಿಮಿತ ಸಂಗ್ರಹಣೆ ಸ್ಥಳ, ಅಥವಾ ಅಪ್ಲಿಕೇಶನ್ ಅಥವಾ ನಿಮ್ಮ ಸಂಸ್ಥೆಯಿಂದ ಅನುಮತಿಯಿಲ್ಲದಿರುವ ಕಾರಣ ಸ್ಕ್ರೀನ್‌ಶಾಟ್ ತೆಗೆಯಲು ಸಾಧ್ಯವಿಲ್ಲ."</string>
+    <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"ಪರಿಮಿತ ಸಂಗ್ರಹಣೆ ಸ್ಥಳದ ಕಾರಣದಿಂದಾಗಿ ಸ್ಕ್ರೀನ್‌ಶಾಟ್ ಉಳಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ."</string>
+    <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"ಸ್ಕ್ರೀನ್‌ಶಾಟ್‌ಗಳನ್ನು ತೆಗೆದುಕೊಳ್ಳುವುದನ್ನು ಅಪ್ಲಿಕೇಶನ್ ಅಥವಾ ನಿಮ್ಮ ಸಂಸ್ಥೆ ಅನುಮತಿಸುವುದಿಲ್ಲ."</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"USB ಫೈಲ್ ವರ್ಗಾವಣೆ ಆಯ್ಕೆಗಳು"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"ಮೀಡಿಯಾ ಪ್ಲೇಯರ್ ರೂಪದಲ್ಲಿ ಅಳವಡಿಸಿ (MTP)"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"ಕ್ಯಾಮರಾ ರೂಪದಲ್ಲಿ ಅಳವಡಿಸಿ (PTP)"</string>
@@ -206,6 +207,7 @@
     <string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"ಹೆಚ್ಚು ಸಮಯ."</string>
     <string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"ಕಡಿಮೆ ಸಮಯ."</string>
     <string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"ಫ್ಲ್ಯಾಶ್‌ಲೈಟ್ ಆಫ್ ಆಗಿದೆ."</string>
+    <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"ಫ್ಲ್ಯಾಶ್‌ಲೈಟ್ ಲಭ್ಯವಿಲ್ಲ."</string>
     <string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"ಫ್ಲ್ಯಾಶ್‌ಲೈಟ್ ಆನ್ ಆಗಿದೆ."</string>
     <string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"ಫ್ಲ್ಯಾಶ್‌ಲೈಟ್ ಆಫ್ ಮಾಡಲಾಗಿದೆ."</string>
     <string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"ಫ್ಲ್ಯಾಶ್‌ಲೈಟ್ ಆನ್ ಮಾಡಲಾಗಿದೆ."</string>
@@ -218,6 +220,10 @@
     <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"ಕೆಲಸದ ಮೋಡ್ ಆನ್ ಆಗಿದೆ."</string>
     <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"ಕೆಲಸದ ಮೋಡ್ ಆಫ್ ಮಾಡಲಾಗಿದೆ."</string>
     <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"ಕೆಲಸದ ಮೋಡ್ ಆನ್ ಮಾಡಲಾಗಿದೆ."</string>
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_off (650231949881093289) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_on (4218725402373934151) -->
+    <skip />
     <string name="accessibility_brightness" msgid="8003681285547803095">"ಹೊಳಪನ್ನು ಪ್ರದರ್ಶಿಸಿ"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"2G-3G ಡೇಟಾವನ್ನು ವಿರಾಮಗೊಳಿಸಲಾಗಿದೆ"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"4G ಡೇಟಾ ವಿರಾಮಗೊಳಿಸಲಾಗಿದೆ"</string>
@@ -304,6 +310,8 @@
     <string name="recents_launch_disabled_message" msgid="1624523193008871793">"<xliff:g id="APP">%s</xliff:g> ಅನ್ನು ಸುರಕ್ಷಿತ ಮೋಡ್‌ನಲ್ಲಿ ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಲಾಗಿದೆ."</string>
     <string name="recents_history_button_label" msgid="5153358867807604821">"ಇತಿಹಾಸ"</string>
     <string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"ತೆರವುಗೊಳಿಸು"</string>
+    <string name="recents_drag_non_dockable_task_message" msgid="2935843902795166158">"ಈ ಅಪ್ಲಿಕೇಶನ್ ಬಹು-ವಿಂಡೊಗಳನ್ನು ಬೆಂಬಲಿಸುವುದಿಲ್ಲ"</string>
+    <string name="recents_launch_non_dockable_task_label" msgid="7862379814938391888">"ಅಪ್ಲಿಕೇಶನ್ ಬಹು-ವಿಂಡೊಗಳನ್ನು ಬೆಂಬಲಿಸುವುದಿಲ್ಲ"</string>
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"ಅಡ್ಡಲಾಗಿ ವಿಭಜಿಸಿದ"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"ಲಂಬವಾಗಿ ವಿಭಜಿಸಿದ"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"ಕಸ್ಟಮ್ ವಿಭಜಿಸಿದ"</string>
@@ -451,18 +459,23 @@
     <string name="enable_bluetooth_title" msgid="5027037706500635269">"ಬ್ಲೂಟೂತ್ ಆನ್ ಮಾಡುವುದೇ?"</string>
     <string name="enable_bluetooth_message" msgid="9106595990708985385">"ನಿಮ್ಮ ಕೀಬೋರ್ಡ್ ಅನ್ನು ಟ್ಯಾಬ್ಲೆಟ್‌ಗೆ ಸಂಪರ್ಕಿಸಲು, ನೀವು ಮೊದಲು ಬ್ಲೂಟೂತ್ ಆನ್ ಮಾಡಬೇಕಾಗುತ್ತದೆ."</string>
     <string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"ಆನ್ ಮಾಡು"</string>
-    <string name="apply_to_topic" msgid="3641403489318659666">"<xliff:g id="TOPIC_NAME">%1$s</xliff:g> ಅಧಿಸೂಚನೆಗಳಿಗೆ ಅನ್ವಯಿಸಿ"</string>
-    <string name="apply_to_app" msgid="363016783939815960">"ಈ ಅಪ್ಲಿಕೇಶನ್‌ನಿಂದ ಎಲ್ಲಾ ಅಧಿಸೂಚನೆಗಳಿಗೆ ಅನ್ವಯಿಸಿ"</string>
+    <string name="show_silently" msgid="6841966539811264192">"ಸ್ಥಬ್ಧವಾಗಿ ಅಧಿಸೂಚನೆಗಳನ್ನು ತೋರಿಸಿ"</string>
+    <string name="block" msgid="2734508760962682611">"ಎಲ್ಲಾ ಅಧಿಸೂಚನೆಗಳನ್ನು ನಿರ್ಬಂಧಿಸಿ"</string>
+    <string name="do_not_silence" msgid="6878060322594892441">"ಮೌನವಾಗಿಸಬೇಡಿ"</string>
+    <string name="do_not_silence_block" msgid="4070647971382232311">"ಸ್ಥಬ್ದ ಅಥವಾ ನಿರ್ಬಂಧಿಸಬೇಡಿ"</string>
+    <string name="tuner_full_importance_settings" msgid="8103289238676424226">"ಪೂರ್ಣ ಪ್ರಾಮುಖ್ಯತೆ ಸೆಟ್ಟಿಂಗ್‌ಗಳನ್ನು ತೋರಿಸಿ"</string>
     <string name="blocked_importance" msgid="5198578988978234161">"ನಿರ್ಬಂಧಿಸಲಾಗಿದೆ"</string>
+    <string name="min_importance" msgid="1901894910809414782">"ಕನಿಷ್ಟ ಪ್ರಾಮುಖ್ಯತೆ"</string>
     <string name="low_importance" msgid="4109929986107147930">"ಕಡಿಮೆ ಪ್ರಾಮುಖ್ಯತೆ"</string>
     <string name="default_importance" msgid="8192107689995742653">"ಸಾಮಾನ್ಯ ಪ್ರಾಮುಖ್ಯತೆ"</string>
     <string name="high_importance" msgid="1527066195614050263">"ಉನ್ನತ ಪ್ರಾಮುಖ್ಯತೆ"</string>
     <string name="max_importance" msgid="5089005872719563894">"ತುರ್ತು ಪ್ರಾಮುಖ್ಯತೆ"</string>
     <string name="notification_importance_blocked" msgid="2397192642657872872">"ಈ ಅಧಿಸೂಚನೆಗಳನ್ನು ಎಂದಿಗೂ ತೋರಿಸಬೇಡ"</string>
-    <string name="notification_importance_low" msgid="4383563267370859725">"ಅಧಿಸೂಚನೆ ಪಟ್ಟಿಯ ಕೆಳಭಾಗದಲ್ಲಿ ಸ್ಥಬ್ಧವಾಗಿ ತೋರಿಸು"</string>
-    <string name="notification_importance_default" msgid="4926529615920610817">"ಈ ಅಧಿಸೂಚನೆಗಳನ್ನು ಸ್ಥಬ್ಧವಾಗಿ ತೋರಿಸು"</string>
-    <string name="notification_importance_high" msgid="3222680136612408223">"ಅಧಿಸೂಚನೆಗಳ ಪಟ್ಟಿಯ ಮೇಲ್ಭಾಗದಲ್ಲಿ ತೋರಿಸು ಮತ್ತು ಧ್ವನಿ ಮಾಡು"</string>
-    <string name="notification_importance_max" msgid="5236987171904756134">"ಪರದೆಯನ್ನು ವೀಕ್ಷಿಸಿ ಮತ್ತು ಧ್ವನಿ ಮಾಡು"</string>
+    <string name="notification_importance_min" msgid="1938190340516905748">"ಅಧಿಸೂಚನೆ ಪಟ್ಟಿಯ ಕೆಳಭಾಗದಲ್ಲಿ ಸ್ಥಬ್ಧವಾಗಿ ತೋರಿಸು"</string>
+    <string name="notification_importance_low" msgid="3657252049508213048">"ಈ ಅಧಿಸೂಚನೆಗಳನ್ನು ಸ್ಥಬ್ಧವಾಗಿ ತೋರಿಸು"</string>
+    <string name="notification_importance_default" msgid="4466466472622442175">"ಈ ಅಧಿಸೂಚನೆಯು ಧ್ವನಿಗಳನ್ನು ಮಾಡಲು ಅನುಮತಿಸಿ"</string>
+    <string name="notification_importance_high" msgid="2135428926525093825">"ಪರದೆಯನ್ನು ವೀಕ್ಷಿಸಿ ಮತ್ತು ಧ್ವನಿ ಅನುಮತಿಸಿ ಮತ್ತು ಧ್ವನಿ ಅನುಮತಿಸಿ"</string>
+    <string name="notification_importance_max" msgid="5806278962376556491">"ಅಧಿಸೂಚನೆಗಳ ಪಟ್ಟಿಯ ಮೇಲ್ಭಾಗದಲ್ಲಿ ತೋರಿಸು, ಪರದೆಯನ್ನು ವೀಕ್ಷಿಸಿ ಮತ್ತು ಧ್ವನಿ ಅನುಮತಿಸಿ"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"ಹೆಚ್ಚಿನ ಸೆಟ್ಟಿಂಗ್‌ಗಳು"</string>
     <string name="notification_done" msgid="5279426047273930175">"ಮುಗಿದಿದೆ"</string>
     <string name="color_and_appearance" msgid="1254323855964993144">"ಬಣ್ಣ ಮತ್ತು ಗೋಚರತೆ"</string>
@@ -476,7 +489,7 @@
     <string name="use_dark_theme" msgid="2900938704964299312">"Android OS ಗೆ ಕಪ್ಪು ಥೀಮ್‌ ಬಳಸಿ"</string>
     <string name="adjust_tint" msgid="3398569573231409878">"ಟಿಂಟ್‌ ಸರಿಹೊಂದಿಸು"</string>
     <string name="adjust_brightness" msgid="980039329808178246">"ಪ್ರಖರತೆಯನ್ನು ಸರಿಹೊಂದಿಸು"</string>
-    <string name="night_mode_disclaimer" msgid="3297928749219711334">"ಕಪ್ಪು ಥೀಮ್‌ ಅನ್ನು Android OS ನ ಕೋರ್‌ ಪ್ರದೇಶಗಳಿಗೆ ಅನ್ವಯಿಸಲಾಗಿರುತ್ತದೆ. ಇದನ್ನು ಸೆಟ್ಟಿಂಗ್‌‌ಗಳು ಮತ್ತು ಅಧಿಸೂಚನೆಗಳಂತಹ ತಿಳಿಯಾದ ಥೀಮ್‌ನಲ್ಲಿ ಸಾಮಾನ್ಯವಾಗಿ ಪ್ರದರ್ಶಿಸಲಾಗುತ್ತದೆ."</string>
+    <string name="night_mode_disclaimer" msgid="598914896926759578">"ಕಪ್ಪು ಥೀಮ್‌ ಅನ್ನು Android OS ನ ಕೋರ್‌ ಪ್ರದೇಶಗಳಿಗೆ ಅನ್ವಯಿಸಲಾಗಿರುತ್ತದೆ. ಇದನ್ನು ಸೆಟ್ಟಿಂಗ್‌‌ಗಳಂತಹ ತಿಳಿಯಾದ ಥೀಮ್‌ನಲ್ಲಿ ಸಾಮಾನ್ಯವಾಗಿ ಪ್ರದರ್ಶಿಸಲಾಗುತ್ತದೆ."</string>
     <string name="color_apply" msgid="9212602012641034283">"ಅನ್ವಯಿಸು"</string>
     <string name="color_revert_title" msgid="4746666545480534663">"ಸೆಟ್ಟಿಂಗ್‌ಗಳನ್ನು ಖಚಿತಪಡಿಸಿ"</string>
     <string name="color_revert_message" msgid="9116001069397996691">"ಕೆಲವು ಬಣ್ಣ ಸೆಟ್ಟಿಂಗ್‌ಗಳು ಈ ಸಾಧನವನ್ನು ಅನುಪಯುಕ್ತಗೊಳಿಸಬಹುದು. ಈ ಬಣ್ಣ ಸೆಟ್ಟಿಂಗ್‌ಗಳನ್ನು ಖಚಿತಪಡಿಸಲು ಸರಿ ಕ್ಲಿಕ್ ಮಾಡಿ, ಇಲ್ಲವಾದರೆ ಈ ಸೆಟ್ಟಿಂಗ್‌ಗಳನ್ನು 10 ಸೆಕೆಂಡುಗಳ ನಂತರ ಮರುಹೊಂದಿಸಿ."</string>
@@ -535,4 +548,10 @@
     <item msgid="2139628951880142927">"ಚಾರ್ಜ್‌ ಮಾಡುವಾಗ ಪ್ರತಿಶತವನ್ನು ತೋರಿಸು (ಡಿಫಾಲ್ಟ್‌)"</item>
     <item msgid="3327323682209964956">"ಈ ಐಕಾನ್ ತೋರಿಸಬೇಡ"</item>
   </string-array>
+    <string name="other" msgid="4060683095962566764">"ಇತರ"</string>
+    <string name="accessibility_divider" msgid="5903423481953635044">"ಸ್ಪ್ಲಿಟ್-ಪರದೆ ಡಿವೈಡರ್"</string>
+    <string name="accessibility_action_divider_move_down" msgid="704893304141890042">"ಕೆಳಗೆ ಸರಿಸಿ"</string>
+    <string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"ಮೇಲೆ ಸರಿಸಿ"</string>
+    <string name="accessibility_action_divider_move_left" msgid="9218189832115847253">"ಎಡಕ್ಕೆ ಸರಿಸಿ"</string>
+    <string name="accessibility_action_divider_move_right" msgid="4671522715182567972">"ಬಲಕ್ಕೆ ಸರಿಸಿ"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-kn-rIN/strings_tv.xml b/packages/SystemUI/res/values-kn-rIN/strings_tv.xml
new file mode 100644
index 0000000..09d7b07
--- /dev/null
+++ b/packages/SystemUI/res/values-kn-rIN/strings_tv.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.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="pip_close" msgid="3480680679023423574">"PIP ಮುಚ್ಚಿ"</string>
+    <string name="pip_fullscreen" msgid="8604643018538487816">"ಪೂರ್ಣ ಪರದೆ"</string>
+    <string name="pip_play" msgid="674145557658227044">"ಪ್ಲೇ"</string>
+    <string name="pip_pause" msgid="8412075640017218862">"ವಿರಾಮ"</string>
+    <string name="pip_hold_home" msgid="340086535668778109">"PIP ನಿಯಂತ್ರಿಸಲು "<b>"HOME"</b>" ಕೀಯನ್ನು ಹಿಡಿದುಕೊಳ್ಳಿ"</string>
+    <string name="pip_onboarding_description" msgid="2627737116380318292">"PIP ನಿಯಂತ್ರಿಸಲು HOME\n ಬಟನ್ ಒತ್ತಿರಿ ಮತ್ತು ಹಿಡಿದುಕೊಳ್ಳಿ"</string>
+    <string name="pip_onboarding_button" msgid="3957426748484904611">"ಅರ್ಥವಾಯಿತು"</string>
+</resources>
diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml
index 64e0e27..1a1cabe 100644
--- a/packages/SystemUI/res/values-ko/strings.xml
+++ b/packages/SystemUI/res/values-ko/strings.xml
@@ -73,7 +73,8 @@
     <string name="screenshot_saved_title" msgid="6461865960961414961">"캡쳐화면 저장됨"</string>
     <string name="screenshot_saved_text" msgid="1152839647677558815">"캡쳐화면을 보려면 터치하세요."</string>
     <string name="screenshot_failed_title" msgid="705781116746922771">"캡쳐화면을 캡쳐하지 못했습니다."</string>
-    <string name="screenshot_failed_text" msgid="1260203058661337274">"저장 공간이 부족하거나 앱 또는 소속 조직에서 허용하지 않아 스크린샷을 찍을 수 없습니다."</string>
+    <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"저장용량이 부족하여 스크린샷을 저장할 수 없습니다."</string>
+    <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"앱이나 조직에서 스크린샷 촬영을 허용하지 않습니다."</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"USB 파일 전송 옵션"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"미디어 플레이어로 마운트(MTP)"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"카메라로 마운트(PTP)"</string>
@@ -206,6 +207,7 @@
     <string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"시간 늘리기"</string>
     <string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"시간 줄이기"</string>
     <string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"손전등: 사용 중지"</string>
+    <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"손전등을 사용할 수 없습니다."</string>
     <string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"손전등: 사용"</string>
     <string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"손전등이 사용 중지되었습니다."</string>
     <string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"손전등을 사용합니다."</string>
@@ -218,6 +220,10 @@
     <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"작업 모드가 사용 설정되었습니다."</string>
     <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"작업 모드가 사용 중지되었습니다."</string>
     <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"작업 모드가 사용 설정되었습니다."</string>
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_off (650231949881093289) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_on (4218725402373934151) -->
+    <skip />
     <string name="accessibility_brightness" msgid="8003681285547803095">"디스플레이 밝기"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"2G-3G 데이터 사용 중지됨"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"4G 데이터 사용 중지됨"</string>
@@ -304,6 +310,8 @@
     <string name="recents_launch_disabled_message" msgid="1624523193008871793">"<xliff:g id="APP">%s</xliff:g>은(는) 안전 모드에서 사용 중지됩니다."</string>
     <string name="recents_history_button_label" msgid="5153358867807604821">"기록"</string>
     <string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"삭제"</string>
+    <string name="recents_drag_non_dockable_task_message" msgid="2935843902795166158">"이 앱은 다중 창을 지원하지 않습니다."</string>
+    <string name="recents_launch_non_dockable_task_label" msgid="7862379814938391888">"앱이 다중 창을 지원하지 않습니다."</string>
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"수평 분할"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"수직 분할"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"맞춤 분할"</string>
@@ -451,18 +459,23 @@
     <string name="enable_bluetooth_title" msgid="5027037706500635269">"블루투스를 켜시겠습니까?"</string>
     <string name="enable_bluetooth_message" msgid="9106595990708985385">"키보드를 태블릿에 연결하려면 먼저 블루투스를 켜야 합니다."</string>
     <string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"사용"</string>
-    <string name="apply_to_topic" msgid="3641403489318659666">"<xliff:g id="TOPIC_NAME">%1$s</xliff:g> 알림에 적용"</string>
-    <string name="apply_to_app" msgid="363016783939815960">"이 앱의 전체 알림에 적용"</string>
+    <string name="show_silently" msgid="6841966539811264192">"무음으로 알림 표시"</string>
+    <string name="block" msgid="2734508760962682611">"모든 알림 차단"</string>
+    <string name="do_not_silence" msgid="6878060322594892441">"무음 모드 사용 안함"</string>
+    <string name="do_not_silence_block" msgid="4070647971382232311">"무음 모드 또는 차단 사용 안함"</string>
+    <string name="tuner_full_importance_settings" msgid="8103289238676424226">"전체 중요도 설정 표시"</string>
     <string name="blocked_importance" msgid="5198578988978234161">"차단됨"</string>
+    <string name="min_importance" msgid="1901894910809414782">"중요도 최소"</string>
     <string name="low_importance" msgid="4109929986107147930">"중요도 낮음"</string>
     <string name="default_importance" msgid="8192107689995742653">"중요도 보통"</string>
     <string name="high_importance" msgid="1527066195614050263">"중요도 높음"</string>
     <string name="max_importance" msgid="5089005872719563894">"중요도 긴급"</string>
     <string name="notification_importance_blocked" msgid="2397192642657872872">"알림 다시 표시 안함"</string>
-    <string name="notification_importance_low" msgid="4383563267370859725">"알림 목록 하단에 무음으로 표시"</string>
-    <string name="notification_importance_default" msgid="4926529615920610817">"무음으로 알림 표시"</string>
-    <string name="notification_importance_high" msgid="3222680136612408223">"알림 목록 상단에 표시하고 소리로 알림"</string>
-    <string name="notification_importance_max" msgid="5236987171904756134">"화면에 표시하고 소리로 알림"</string>
+    <string name="notification_importance_min" msgid="1938190340516905748">"알림 목록 맨 아래에 무음으로 표시"</string>
+    <string name="notification_importance_low" msgid="3657252049508213048">"무음으로 알림 표시"</string>
+    <string name="notification_importance_default" msgid="4466466472622442175">"알림을 소리로 알리도록 허용"</string>
+    <string name="notification_importance_high" msgid="2135428926525093825">"화면에 표시하고 소리로 알림"</string>
+    <string name="notification_importance_max" msgid="5806278962376556491">"알림 목록 맨 위에 표시, 화면에 표시하고 소리로 알림"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"설정 더보기"</string>
     <string name="notification_done" msgid="5279426047273930175">"완료"</string>
     <string name="color_and_appearance" msgid="1254323855964993144">"색상 및 모양"</string>
@@ -476,7 +489,7 @@
     <string name="use_dark_theme" msgid="2900938704964299312">"Android OS용 어두운 테마 사용"</string>
     <string name="adjust_tint" msgid="3398569573231409878">"농담 효과 조정"</string>
     <string name="adjust_brightness" msgid="980039329808178246">"밝기 조정"</string>
-    <string name="night_mode_disclaimer" msgid="3297928749219711334">"설정 및 알림 등 밝은 테마에서 일반적으로 표시되는 Android OS의 핵심 영역에 어두운 테마가 적용됩니다."</string>
+    <string name="night_mode_disclaimer" msgid="598914896926759578">"설정 등 밝은 테마에서 일반적으로 표시되는 Android OS의 핵심 영역에 어두운 테마가 적용됩니다."</string>
     <string name="color_apply" msgid="9212602012641034283">"적용"</string>
     <string name="color_revert_title" msgid="4746666545480534663">"설정 확인"</string>
     <string name="color_revert_message" msgid="9116001069397996691">"일부 색상 설정으로 인해 이 기기를 사용하지 못할 수 있습니다. 확인을 클릭하여 이러한 색상 설정을 확인하지 않으면 10초 후에 설정이 초기화됩니다."</string>
@@ -535,4 +548,10 @@
     <item msgid="2139628951880142927">"충전할 때 퍼센트 표시(기본값)"</item>
     <item msgid="3327323682209964956">"이 아이콘 표시 안함"</item>
   </string-array>
+    <string name="other" msgid="4060683095962566764">"기타"</string>
+    <string name="accessibility_divider" msgid="5903423481953635044">"화면 분할기"</string>
+    <string name="accessibility_action_divider_move_down" msgid="704893304141890042">"아래로 이동"</string>
+    <string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"위로 이동"</string>
+    <string name="accessibility_action_divider_move_left" msgid="9218189832115847253">"왼쪽으로 이동"</string>
+    <string name="accessibility_action_divider_move_right" msgid="4671522715182567972">"오른쪽으로 이동"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ko/strings_tv.xml b/packages/SystemUI/res/values-ko/strings_tv.xml
new file mode 100644
index 0000000..e7cac9f
--- /dev/null
+++ b/packages/SystemUI/res/values-ko/strings_tv.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2016, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <!-- no translation found for pip_close (3480680679023423574) -->
+    <skip />
+    <string name="pip_fullscreen" msgid="8604643018538487816">"전체화면"</string>
+    <string name="pip_play" msgid="674145557658227044">"재생"</string>
+    <string name="pip_pause" msgid="8412075640017218862">"일시중지"</string>
+    <!-- no translation found for pip_hold_home (340086535668778109) -->
+    <skip />
+    <!-- no translation found for pip_onboarding_description (2627737116380318292) -->
+    <skip />
+    <!-- no translation found for pip_onboarding_button (3957426748484904611) -->
+    <skip />
+</resources>
diff --git a/packages/SystemUI/res/values-ky-rKG/strings.xml b/packages/SystemUI/res/values-ky-rKG/strings.xml
index e8d32a9..571b691 100644
--- a/packages/SystemUI/res/values-ky-rKG/strings.xml
+++ b/packages/SystemUI/res/values-ky-rKG/strings.xml
@@ -73,7 +73,8 @@
     <string name="screenshot_saved_title" msgid="6461865960961414961">"Скриншот тартылды."</string>
     <string name="screenshot_saved_text" msgid="1152839647677558815">"Тийип, скриншотту көрүңүз."</string>
     <string name="screenshot_failed_title" msgid="705781116746922771">"Скриншот кылынбай жатат."</string>
-    <string name="screenshot_failed_text" msgid="1260203058661337274">"Сактагыч орду чектелүү болгондуктан скриншот тарта албайт, же буга колдонмо же ишканаңыз тарабынан уруксат жок."</string>
+    <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Сактагычта бош орун аз болгондуктан скриншот сакталбай жатат."</string>
+    <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Скриншот тартууга колдонмо же ишканаңыз уруксат бербейт."</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"USB менен файл өткөрүү мүмкүнчүлүктөрү"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Медиа ойноткуч катары кошуу (MTP)"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"Камера катары кошуу (PTP)"</string>
@@ -206,6 +207,7 @@
     <string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"Көбүрөөк убакыт."</string>
     <string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"Азыраак убакыт."</string>
     <string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"Колчырак өчүк."</string>
+    <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"Кол чырак жок."</string>
     <string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"Колчырак күйүк."</string>
     <string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"Колчырак өчүрүлдү."</string>
     <string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"Колчырак күйгүзүлдү."</string>
@@ -218,6 +220,10 @@
     <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"Иштөө режими күйүк."</string>
     <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"Иштөө режими өчүрүлдү."</string>
     <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"Иштөө режими күйгүзүлдү."</string>
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_off (650231949881093289) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_on (4218725402373934151) -->
+    <skip />
     <string name="accessibility_brightness" msgid="8003681285547803095">"Жарыктыгын көрсөтүү"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"2G-3G дайындары тындырылды."</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"4G дайындары тындырылды"</string>
@@ -304,6 +310,8 @@
     <string name="recents_launch_disabled_message" msgid="1624523193008871793">"<xliff:g id="APP">%s</xliff:g> коопсуз режиминде өчүрүлдү."</string>
     <string name="recents_history_button_label" msgid="5153358867807604821">"Таржымал"</string>
     <string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"Тазалоо"</string>
+    <string name="recents_drag_non_dockable_task_message" msgid="2935843902795166158">"Бул колдонмодо бир нече терезе режими колдоого алынбайт"</string>
+    <string name="recents_launch_non_dockable_task_label" msgid="7862379814938391888">"Колдонмодо бир нече терезе режими колдоого алынбайт"</string>
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Туурасынан бөлүү"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Тигинен бөлүү"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Ыңгайлаштырылган бөлүү"</string>
@@ -451,18 +459,23 @@
     <string name="enable_bluetooth_title" msgid="5027037706500635269">"Bluetooth күйгүзүлсүнбү?"</string>
     <string name="enable_bluetooth_message" msgid="9106595990708985385">"Баскычтобуңузду планшетиңизге туташтыруу үчүн, адегенде Bluetooth\'ту күйгүзүшүңүз керек."</string>
     <string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"Күйгүзүү"</string>
-    <string name="apply_to_topic" msgid="3641403489318659666">"<xliff:g id="TOPIC_NAME">%1$s</xliff:g> эскертмелерине колдонулсун"</string>
-    <string name="apply_to_app" msgid="363016783939815960">"Ушул колдонмодон алынган бардык эскертмелерге колдонулсун"</string>
+    <string name="show_silently" msgid="6841966539811264192">"Эскертмелер үнсүз көрсөтүлсүн"</string>
+    <string name="block" msgid="2734508760962682611">"Бардык эскертмелерди бөгөттөө"</string>
+    <string name="do_not_silence" msgid="6878060322594892441">"Үнү менен көрсөтүлсүн"</string>
+    <string name="do_not_silence_block" msgid="4070647971382232311">"Үнү менен көрсөтүлүп бөгөттөлбөсүн"</string>
+    <string name="tuner_full_importance_settings" msgid="8103289238676424226">"Маанилүүлүк жөндөөлөрү толук көрсөтүлсүн"</string>
     <string name="blocked_importance" msgid="5198578988978234161">"Бөгөттөлгөн"</string>
+    <string name="min_importance" msgid="1901894910809414782">"Маанилүүлүгү эң төмөн"</string>
     <string name="low_importance" msgid="4109929986107147930">"Маанилүүлүгү төмөн"</string>
     <string name="default_importance" msgid="8192107689995742653">"Маанилүүлүгү орточо"</string>
     <string name="high_importance" msgid="1527066195614050263">"Маанилүүлүгү жогору"</string>
     <string name="max_importance" msgid="5089005872719563894">"Маанилүүлүгү шашылыш"</string>
     <string name="notification_importance_blocked" msgid="2397192642657872872">"Бул эскертмелер эч качан көрсөтүлбөсүн"</string>
-    <string name="notification_importance_low" msgid="4383563267370859725">"Эскертмелер тизмесинин эң ылдыйында үнсүз көрсөтүлсүн"</string>
-    <string name="notification_importance_default" msgid="4926529615920610817">"Бул эскертмелер үнсүз көрсөтүлсүн"</string>
-    <string name="notification_importance_high" msgid="3222680136612408223">"Эскертмелер тизмесинин эң жогорусунда үн чыгарып көрсөтүлсүн"</string>
-    <string name="notification_importance_max" msgid="5236987171904756134">"Үн менен коштолуп, экранга чыгарылсын"</string>
+    <string name="notification_importance_min" msgid="1938190340516905748">"Эскертмелер тизмесинин соңунда үнсүз көрсөтүлсүн"</string>
+    <string name="notification_importance_low" msgid="3657252049508213048">"Бул эскертмелер үнсүз көрсөтүлсүн"</string>
+    <string name="notification_importance_default" msgid="4466466472622442175">"Бул эскертмелер үнү менен көрсөтүлсүн"</string>
+    <string name="notification_importance_high" msgid="2135428926525093825">"Үн менен коштолуп, экранга чыгарылсын"</string>
+    <string name="notification_importance_max" msgid="5806278962376556491">"Эскертмелер тизмесинин эң башында көрсөтүлүп, үн менен коштолуп, экранга чыгарылсын"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"Дагы жөндөөлөр"</string>
     <string name="notification_done" msgid="5279426047273930175">"Аткарылды"</string>
     <string name="color_and_appearance" msgid="1254323855964993144">"Түсү жана көрүнүшү"</string>
@@ -476,7 +489,7 @@
     <string name="use_dark_theme" msgid="2900938704964299312">"Android OS үчүн караңгы тема колдонуу"</string>
     <string name="adjust_tint" msgid="3398569573231409878">"Кошумча түсүн тууралоо"</string>
     <string name="adjust_brightness" msgid="980039329808178246">"Жарыктыгын тууралоо"</string>
-    <string name="night_mode_disclaimer" msgid="3297928749219711334">"Адатта жарык темада көрсөтүлгөн Android OS\'тин, Жөндөөлөр жана эскертмелер сыяктуу негизги аймактарына караңгы тема колдонулат."</string>
+    <string name="night_mode_disclaimer" msgid="598914896926759578">"Адатта жарык темада көрсөтүлүүчү Android тутумунун негизги элементтерине (Жөндөөлөр сыяктуу) колдонула турган караңгы тема."</string>
     <string name="color_apply" msgid="9212602012641034283">"Колдонуу"</string>
     <string name="color_revert_title" msgid="4746666545480534663">"Жөндөөлөрдү ырастоо"</string>
     <string name="color_revert_message" msgid="9116001069397996691">"Айрым түс жөндөөлөрү бул түзмөктү колдонулгус кылып коюшу мүмкүн. Бул түс жөндөөлөрүн ырастоо үчүн OK баскычын чыкылдатыңыз, болбосо бул жөндөөлөр 10 секунддан кийин баштапкы абалына келтирилет."</string>
@@ -535,4 +548,10 @@
     <item msgid="2139628951880142927">"Кубаттоо учурунда пайызы көрсөтүлсүн (демейки)"</item>
     <item msgid="3327323682209964956">"Бул сөлөкөт көрсөтүлбөсүн"</item>
   </string-array>
+    <string name="other" msgid="4060683095962566764">"Башка"</string>
+    <string name="accessibility_divider" msgid="5903423481953635044">"Экранды бөлгүч"</string>
+    <string name="accessibility_action_divider_move_down" msgid="704893304141890042">"Төмөн жылдыруу"</string>
+    <string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"Жогору жылдыруу"</string>
+    <string name="accessibility_action_divider_move_left" msgid="9218189832115847253">"Солго жылдыруу"</string>
+    <string name="accessibility_action_divider_move_right" msgid="4671522715182567972">"Оңго жылдыруу"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ky-rKG/strings_tv.xml b/packages/SystemUI/res/values-ky-rKG/strings_tv.xml
new file mode 100644
index 0000000..2724230
--- /dev/null
+++ b/packages/SystemUI/res/values-ky-rKG/strings_tv.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2016, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <!-- no translation found for pip_close (3480680679023423574) -->
+    <skip />
+    <string name="pip_fullscreen" msgid="8604643018538487816">"Толук экран"</string>
+    <string name="pip_play" msgid="674145557658227044">"Ойнотуу"</string>
+    <string name="pip_pause" msgid="8412075640017218862">"Тындыруу"</string>
+    <!-- no translation found for pip_hold_home (340086535668778109) -->
+    <skip />
+    <!-- no translation found for pip_onboarding_description (2627737116380318292) -->
+    <skip />
+    <!-- no translation found for pip_onboarding_button (3957426748484904611) -->
+    <skip />
+</resources>
diff --git a/packages/SystemUI/res/values-land/dimens.xml b/packages/SystemUI/res/values-land/dimens.xml
index 26a81c8..585984c 100644
--- a/packages/SystemUI/res/values-land/dimens.xml
+++ b/packages/SystemUI/res/values-land/dimens.xml
@@ -22,6 +22,9 @@
     <!-- Standard notification gravity -->
     <integer name="notification_panel_layout_gravity">@integer/standard_notification_panel_layout_gravity</integer>
 
+    <!-- The size of the initial peek area at the bottom of the stack (above the nav bar). -->
+    <dimen name="recents_initial_bottom_peek_size">@dimen/recents_task_bar_height</dimen>
+
     <dimen name="docked_divider_handle_width">2dp</dimen>
     <dimen name="docked_divider_handle_height">16dp</dimen>
 </resources>
diff --git a/packages/SystemUI/res/values-lo-rLA/strings.xml b/packages/SystemUI/res/values-lo-rLA/strings.xml
index b4dd69d..823e02b 100644
--- a/packages/SystemUI/res/values-lo-rLA/strings.xml
+++ b/packages/SystemUI/res/values-lo-rLA/strings.xml
@@ -73,7 +73,8 @@
     <string name="screenshot_saved_title" msgid="6461865960961414961">"ຖ່າຍຮູບໜ້າຈໍແລ້ວ"</string>
     <string name="screenshot_saved_text" msgid="1152839647677558815">"ແຕະເພື່ອເບິ່ງພາບໜ້າຈໍຂອງທ່ານ."</string>
     <string name="screenshot_failed_title" msgid="705781116746922771">"ບໍ່ສາມາດຖ່າຍຮູບໜ້າຈໍໄດ້"</string>
-    <string name="screenshot_failed_text" msgid="1260203058661337274">"ບໍ່​ສາມາດ​ຖ່າຍ​ຮູບ​ໜ້າ​ຈໍ​ໄດ້​ເນື່ອງ​ຈາກ​ບ່ອນ​ຈັດ​ເກັບ​ຂໍ້ມູນ​ທີ່​ຈຳກັດ ຫຼື​ແອັບຯ ຫຼື​ອົງກອນ​ຂອງ​ທ່ານ​ບໍ່​ອະນຸຍາດ​ໃຫ້​ເຮັດ​ໄດ້."</string>
+    <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"ບໍ່ສາມາດຖ່າຍຮູບໜ້າຈໍໄດ້ເນື່ອງຈາກພື້ນທີ່ຈັດເກັບຂໍ້ມູນມີຈຳກັດ."</string>
+    <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"ແອັບ ຫຼື ອົງກອນຂອງທ່ານບໍ່ອະນຸຍາດໃຫ້ມີການຖ່າຍຮູບໜ້າຈໍ."</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"USB ໂຕເລືອກການຍ້າຍໄຟລ໌"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"ເຊື່ອມຕໍ່ເປັນ media player (MTP)"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"ເຊື່ອມຕໍ່ເປັນກ້ອງຖ່າຍຮູບ (PTP)"</string>
@@ -206,6 +207,7 @@
     <string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"​ເພີ່ມ​ເວ​ລາ."</string>
     <string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"ຫຼຸດ​ເວ​ລາ."</string>
     <string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"ໄຟ​ສາຍ​ປິດ."</string>
+    <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"ບໍ່ສາມາດໃຊ້ໄຟສາຍໄດ້"</string>
     <string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"ໄຟ​ສາຍ​ເປີດ."</string>
     <string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"ປິດ​ໄຟ​ສາຍ​ແລ້ວ."</string>
     <string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"​ເປີດ​ໄຟ​ສາຍ​ແລ້ວ."</string>
@@ -218,6 +220,10 @@
     <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"ໂໝດການເຮັດວຽກເປີດຢູ່."</string>
     <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"ໂໝດການເຮັດວຽກປິດຢູ່."</string>
     <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"ໂໝດການເຮັດວຽກເປີດຢູ່."</string>
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_off (650231949881093289) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_on (4218725402373934151) -->
+    <skip />
     <string name="accessibility_brightness" msgid="8003681285547803095">"​ຄວາມ​ແຈ້ງ​​ຂອງ​ຈໍ"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"ຂໍ້​ມູນ 2G​-3G ຢຸດ​ຊົ່ວ​ຄາວແລ້ວ"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"ຂໍ້​ມູນ 4G ຢຸດ​ຊົ່ວ​ຄາວແລ້ວ"</string>
@@ -304,6 +310,8 @@
     <string name="recents_launch_disabled_message" msgid="1624523193008871793">"<xliff:g id="APP">%s</xliff:g> ຖືກປິດໃຊ້ໃນໂໝດຄວາມມປອດໄພ."</string>
     <string name="recents_history_button_label" msgid="5153358867807604821">"ປະຫວັດ"</string>
     <string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"ລຶບ"</string>
+    <string name="recents_drag_non_dockable_task_message" msgid="2935843902795166158">"ແອັບນີ້ບໍ່ຮອງຮັບຫຼາຍໜ້າຈໍ"</string>
+    <string name="recents_launch_non_dockable_task_label" msgid="7862379814938391888">"ແອັບບໍ່ຮອງຮັບຫຼາຍໜ້າຈໍ"</string>
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"ການ​ແຍກ​ລວງ​ຂວາງ"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"ການ​ແຍກ​ລວງ​ຕັ້ງ"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"ການ​ແຍກ​ກຳ​ນົດ​ເອງ"</string>
@@ -451,18 +459,23 @@
     <string name="enable_bluetooth_title" msgid="5027037706500635269">"ເປີດ​ໃຊ້ Bluetooth ບໍ່?"</string>
     <string name="enable_bluetooth_message" msgid="9106595990708985385">"ເພື່ອ​ເຊື່ອມ​ຕໍ່​ແປ້ນ​ພິມ​ຂອງ​ທ່ານ​ກັບ​ແທັບ​ເລັດ​ຂອງ​ທ່ານ, ກ່ອນ​ອື່ນ​ໝົດ​ທ່ານ​ຕ້ອງ​ເປີດ Bluetooth."</string>
     <string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"ເປີດ​"</string>
-    <string name="apply_to_topic" msgid="3641403489318659666">"ນຳໃຊ້ກັບການແຈ້ງເຕືອນ <xliff:g id="TOPIC_NAME">%1$s</xliff:g>"</string>
-    <string name="apply_to_app" msgid="363016783939815960">"ນຳໃຊ້ກັບທຸກການແຈ້ງເຕືອນຈາກແອັບນີ້"</string>
+    <string name="show_silently" msgid="6841966539811264192">"ສະແດງການແຈ້ງເຕືອນແບບບໍ່ມີສຽງ"</string>
+    <string name="block" msgid="2734508760962682611">"ບລັອກການແຈ້ງເຕືອນທັງໝົດ"</string>
+    <string name="do_not_silence" msgid="6878060322594892441">"ຢ່າງຽບ"</string>
+    <string name="do_not_silence_block" msgid="4070647971382232311">"ຢ່າງຽບ ຫຼື ບລັອກ"</string>
+    <string name="tuner_full_importance_settings" msgid="8103289238676424226">"ສະແດງການຕັ້ງຄ່າຄວາມສຳຄັນແບບເຕັມ"</string>
     <string name="blocked_importance" msgid="5198578988978234161">"ບລັອກໄວ້​ແລ້ວ"</string>
+    <string name="min_importance" msgid="1901894910809414782">"ຄວາມສຳຄັນໜ້ອຍສຸດ"</string>
     <string name="low_importance" msgid="4109929986107147930">"ຄວາມ​ສໍາ​ຄັນ​ຕໍ່າ"</string>
     <string name="default_importance" msgid="8192107689995742653">"ຄວາມສຳຄັນປົກກະຕິ"</string>
     <string name="high_importance" msgid="1527066195614050263">"ຄວາມ​ສໍາ​ຄັນ​ສູງ"</string>
     <string name="max_importance" msgid="5089005872719563894">"ຄວາມ​ສໍາ​ຄັນ​ຮີບ​ດ່ວນ"</string>
     <string name="notification_importance_blocked" msgid="2397192642657872872">"ຢ່າ​ສະ​ແດງ​ການ​ແຈ້ງ​ເຕືອນ​ເຫຼົ່າ​ນີ້"</string>
-    <string name="notification_importance_low" msgid="4383563267370859725">"ສະແດງຢູ່ສ່ວນລຸ່ມຂອງລາຍການແຈ້ງເຕືອນແບບມີບໍ່ສຽງ"</string>
-    <string name="notification_importance_default" msgid="4926529615920610817">"ສະແດງການແຈ້ງເຕືອນເຫຼົ່ານີ້ແບບບໍ່ມີສຽງ"</string>
-    <string name="notification_importance_high" msgid="3222680136612408223">"ສະແດງຢູ່ສ່ວນເທິງຂອງລາຍການແຈ້ງເຕືອນ ແລະສົ່ງສຽງດັງ"</string>
-    <string name="notification_importance_max" msgid="5236987171904756134">"ເດັ້ງຂຶ້ນເທິງຫນ້າຈໍ ແລະສົ່ງສຽງດັງ"</string>
+    <string name="notification_importance_min" msgid="1938190340516905748">"ສະແດງຢູ່ລຸ່ມສຸດຂອງລາຍການແຈ້ງເຕືອນແບບມີບໍ່ສຽງ"</string>
+    <string name="notification_importance_low" msgid="3657252049508213048">"ສະແດງການແຈ້ງເຕືອນເຫຼົ່ານີ້ແບບບໍ່ມີສຽງ"</string>
+    <string name="notification_importance_default" msgid="4466466472622442175">"ອະນຸຍາດໃຫ້ການແຈ້ງເຕືອນເຫຼົ່ານີ້ໃຊ້ສຽງໄດ້"</string>
+    <string name="notification_importance_high" msgid="2135428926525093825">"ແຈ້ງໄປໜ້າຈໍ ແລະ ອະນຸຍາດໃຫ້ໃຊ້ສຽງໄດ້"</string>
+    <string name="notification_importance_max" msgid="5806278962376556491">"ສະແດງຢູ່ເທິງສຸດຂອງລາຍການແຈ້ງເຕືອນ, ແຈ້ງໄປໜ້າຈໍ ແລະ ອະນຸຍາດໃຫ້ໃຊ້ສຽງໄດ້"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"​ການ​ຕັ້ງ​ຄ່າ​ເພີ່ມ​ເຕີມ"</string>
     <string name="notification_done" msgid="5279426047273930175">"ສຳເລັດແລ້ວ"</string>
     <string name="color_and_appearance" msgid="1254323855964993144">"ສີ ແລະ ລັກສະນະ"</string>
@@ -476,7 +489,7 @@
     <string name="use_dark_theme" msgid="2900938704964299312">"ໃຊ້ຮູບແບບສີສັນແບບມືດສຳລັບ Android OS"</string>
     <string name="adjust_tint" msgid="3398569573231409878">"ປັບແຕ່ງໂທນສີ"</string>
     <string name="adjust_brightness" msgid="980039329808178246">"ປັບແຕ່ງຄວາມສະຫວ່າງ"</string>
-    <string name="night_mode_disclaimer" msgid="3297928749219711334">"ຮູບແບບສີສັນແບບມືດແມ່ນຖືກນຳໃຊ້ກັບສ່ວນຫຼັກຂອງ Android OS ທີ່ປົກກະຕິຈະສະແດງໃນແບບສີສັນແບບແຈ້ງແລ້ວ ເຊັ່ນ: ການຕັ້ງຄ່າ ແລະ ການແຈ້ງເຕືອນ."</string>
+    <string name="night_mode_disclaimer" msgid="598914896926759578">"ຮູບແບບສີສັນມືດແມ່ນນຳໃຊ້ກັບພື້ນທີ່ຫຼັກຂອງ Android OS ທີ່ປົກກະຕິຈະສະແດງເປັນຮູບແບບສີສັນແຈ້ງ ເຊັ່ນ: ການຕັ້ງຄ່າ."</string>
     <string name="color_apply" msgid="9212602012641034283">"ນຳໃຊ້"</string>
     <string name="color_revert_title" msgid="4746666545480534663">"ຢືນ​ຢັນ​ການ​ຕັ້ງ​ຄ່າ"</string>
     <string name="color_revert_message" msgid="9116001069397996691">"ບາງການຕັ້ງຄ່າສີສາມາດເຮັດໃຫ້ອຸປະກອນນີ້ບໍ່ສາມາດໃຊ້ໄດ້. ຄລິກ ຕົກລົງ ເພື່ອຢືນຢັນການຕັ້ງຄ່າສີເຫຼົ່ານີ້, ຖ້າບໍ່ດັ່ງນັ້ນ ການຕັ້ງຄ່າເຫຼົ່ານີ້ຈະຕັ້ງຄືນໃໝ່ ຫຼັງຈາກ 10 ວິນາທີ."</string>
@@ -535,4 +548,10 @@
     <item msgid="2139628951880142927">"ສະແດງເປີເຊັນເມື່ອກຳລັງສາກໄຟ (ຄ່າເລີ່ມຕົ້ນ)"</item>
     <item msgid="3327323682209964956">"ຢ່າສະແດງໄອຄອນນີ້"</item>
   </string-array>
+    <string name="other" msgid="4060683095962566764">"ອື່ນໆ"</string>
+    <string name="accessibility_divider" msgid="5903423481953635044">"ຕົວຂັ້ນການແບ່ງໜ້າຈໍ"</string>
+    <string name="accessibility_action_divider_move_down" msgid="704893304141890042">"ເລື່ອນລົງ"</string>
+    <string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"ເລື່ອນຂຶ້ນ"</string>
+    <string name="accessibility_action_divider_move_left" msgid="9218189832115847253">"ເລື່ອນຊ້າຍ"</string>
+    <string name="accessibility_action_divider_move_right" msgid="4671522715182567972">"ເລື່ອນຂວາ"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-lo-rLA/strings_tv.xml b/packages/SystemUI/res/values-lo-rLA/strings_tv.xml
new file mode 100644
index 0000000..47374e8
--- /dev/null
+++ b/packages/SystemUI/res/values-lo-rLA/strings_tv.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2016, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <!-- no translation found for pip_close (3480680679023423574) -->
+    <skip />
+    <string name="pip_fullscreen" msgid="8604643018538487816">"ເຕັມໜ້າຈໍ"</string>
+    <string name="pip_play" msgid="674145557658227044">"ຫຼິ້ນ"</string>
+    <string name="pip_pause" msgid="8412075640017218862">"ຢຸດຊົ່ວຄາວ"</string>
+    <!-- no translation found for pip_hold_home (340086535668778109) -->
+    <skip />
+    <!-- no translation found for pip_onboarding_description (2627737116380318292) -->
+    <skip />
+    <!-- no translation found for pip_onboarding_button (3957426748484904611) -->
+    <skip />
+</resources>
diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml
index ba98690..db354eb 100644
--- a/packages/SystemUI/res/values-lt/strings.xml
+++ b/packages/SystemUI/res/values-lt/strings.xml
@@ -75,7 +75,8 @@
     <string name="screenshot_saved_title" msgid="6461865960961414961">"Ekrano kopija užfiksuota."</string>
     <string name="screenshot_saved_text" msgid="1152839647677558815">"Palieskite, kad peržiūrėtumėte ekrano kopiją."</string>
     <string name="screenshot_failed_title" msgid="705781116746922771">"Nepavyko užfiksuoti ekrano kopijos."</string>
-    <string name="screenshot_failed_text" msgid="1260203058661337274">"Neg. daryti ekr. kopijų dėl ribotos saugyklos vietos arba to atlikti neleidžia progr. ar organiz."</string>
+    <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Negalima išsaugoti ekrano kopijos dėl ribotos saugyklos vietos."</string>
+    <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Jūsų organizacijoje arba naudojant šią programą neleidžiama daryti ekrano kopijų"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"USB failo perdavimo parinktys"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Įmontuoti kaip medijos leistuvę (MTP)"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"Įmontuoti kaip fotoaparatą (PTP)"</string>
@@ -208,6 +209,7 @@
     <string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"Daugiau laiko."</string>
     <string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"Mažiau laiko."</string>
     <string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"Blykstė išjungta."</string>
+    <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"Blykstė nepasiekiama."</string>
     <string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"Blykstė įjungta."</string>
     <string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"Blykstė išjungta."</string>
     <string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"Blykstė įjungta."</string>
@@ -220,6 +222,10 @@
     <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"Darbo režimas įjungtas."</string>
     <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"Darbo režimas išjungtas."</string>
     <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"Darbo režimas įjungtas."</string>
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_off (650231949881093289) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_on (4218725402373934151) -->
+    <skip />
     <string name="accessibility_brightness" msgid="8003681285547803095">"Ekrano šviesumas"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"2G–3G duomenys pristabdyti"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"4G duomenys pristabdyti"</string>
@@ -306,6 +312,8 @@
     <string name="recents_launch_disabled_message" msgid="1624523193008871793">"Programa „<xliff:g id="APP">%s</xliff:g>“ išjungta saugos režimu."</string>
     <string name="recents_history_button_label" msgid="5153358867807604821">"Istorija"</string>
     <string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"Išvalyti"</string>
+    <string name="recents_drag_non_dockable_task_message" msgid="2935843902795166158">"Ši programa nepalaiko kelių langų režimo"</string>
+    <string name="recents_launch_non_dockable_task_label" msgid="7862379814938391888">"Programa nepalaiko kelių langų režimo"</string>
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Horizontalus skaidymas"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Vertikalus skaidymas"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Tinkintas skaidymas"</string>
@@ -453,18 +461,23 @@
     <string name="enable_bluetooth_title" msgid="5027037706500635269">"Įjungti „Bluetooth“?"</string>
     <string name="enable_bluetooth_message" msgid="9106595990708985385">"Kad galėtumėte prijungti klaviatūrą prie planšetinio kompiuterio, pirmiausia turite įjungti „Bluetooth“."</string>
     <string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"Įjungti"</string>
-    <string name="apply_to_topic" msgid="3641403489318659666">"Taikyti „<xliff:g id="TOPIC_NAME">%1$s</xliff:g>“ pranešimams"</string>
-    <string name="apply_to_app" msgid="363016783939815960">"Taikyti visiems pranešimams iš šios programos"</string>
+    <string name="show_silently" msgid="6841966539811264192">"Tyliai rodyti pranešimus"</string>
+    <string name="block" msgid="2734508760962682611">"Blokuoti visus pranešimus"</string>
+    <string name="do_not_silence" msgid="6878060322594892441">"Netylėti"</string>
+    <string name="do_not_silence_block" msgid="4070647971382232311">"Netylėti arba blokuoti"</string>
+    <string name="tuner_full_importance_settings" msgid="8103289238676424226">"Rodyti visos svarbos nustatymus"</string>
     <string name="blocked_importance" msgid="5198578988978234161">"Užblokuota"</string>
+    <string name="min_importance" msgid="1901894910809414782">"Min. svarba"</string>
     <string name="low_importance" msgid="4109929986107147930">"Maža svarba"</string>
     <string name="default_importance" msgid="8192107689995742653">"Įprasta svarba"</string>
     <string name="high_importance" msgid="1527066195614050263">"Didelė svarba"</string>
     <string name="max_importance" msgid="5089005872719563894">"Skubi svarba"</string>
     <string name="notification_importance_blocked" msgid="2397192642657872872">"Niekada nerodyti šių pranešimų"</string>
-    <string name="notification_importance_low" msgid="4383563267370859725">"Tyliai rodyti pranešimų sąrašo apačioje"</string>
-    <string name="notification_importance_default" msgid="4926529615920610817">"Tyliai rodyti šiuos pranešimus"</string>
-    <string name="notification_importance_high" msgid="3222680136612408223">"Rodyti pranešimų sąrašo viršuje ir skambėti"</string>
-    <string name="notification_importance_max" msgid="5236987171904756134">"Rodyti ekrane ir skambėti"</string>
+    <string name="notification_importance_min" msgid="1938190340516905748">"Tyliai rodyti pranešimų sąrašo apačioje"</string>
+    <string name="notification_importance_low" msgid="3657252049508213048">"Tyliai rodyti šiuos pranešimus"</string>
+    <string name="notification_importance_default" msgid="4466466472622442175">"Leisti šiems pranešimams skambėti"</string>
+    <string name="notification_importance_high" msgid="2135428926525093825">"Rodyti ekrane ir leisti skambėti"</string>
+    <string name="notification_importance_max" msgid="5806278962376556491">"Rodyti pranešimų sąrašo viršuje, rodyti ekrane ir leisti skambėti"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"Daugiau nustatymų"</string>
     <string name="notification_done" msgid="5279426047273930175">"Atlikta"</string>
     <string name="color_and_appearance" msgid="1254323855964993144">"Spalva ir išvaizda"</string>
@@ -478,7 +491,7 @@
     <string name="use_dark_theme" msgid="2900938704964299312">"Naudoti tamsią „Android“ OS temą"</string>
     <string name="adjust_tint" msgid="3398569573231409878">"Koreguoti atspalvį"</string>
     <string name="adjust_brightness" msgid="980039329808178246">"Koreguoti šviesumą"</string>
-    <string name="night_mode_disclaimer" msgid="3297928749219711334">"Pagrindinėms „Android“ OS dalims, kurioms paprastai taikoma šviesi tema, pvz., Nustatymams ir pranešimams, bus taikoma tamsi tema."</string>
+    <string name="night_mode_disclaimer" msgid="598914896926759578">"Pagrindinėms „Android“ OS dalims, kurioms paprastai taikoma šviesi tema, pvz., skilčiai „Nustatymai“, bus pritaikyta tamsi tema."</string>
     <string name="color_apply" msgid="9212602012641034283">"Taikyti"</string>
     <string name="color_revert_title" msgid="4746666545480534663">"Nustatymų patvirtinimas"</string>
     <string name="color_revert_message" msgid="9116001069397996691">"Dėl kai kurių spalvų nustatymų įrenginys gali būti netinkamas naudoti. Spustelėkite „Gerai“, kad patvirtintumėte šiuos spalvų nustatymus. Kitaip šie nustatymai bus nustatyti iš naujo po 10 sekundžių."</string>
@@ -537,4 +550,10 @@
     <item msgid="2139628951880142927">"Rodyti procentus kraunant (numatytasis nustatymas)"</item>
     <item msgid="3327323682209964956">"Nerodyti šios piktogramos"</item>
   </string-array>
+    <string name="other" msgid="4060683095962566764">"Kita"</string>
+    <string name="accessibility_divider" msgid="5903423481953635044">"Skaidyto ekrano daliklis"</string>
+    <string name="accessibility_action_divider_move_down" msgid="704893304141890042">"Perkelti žemyn"</string>
+    <string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"Perkelti aukštyn"</string>
+    <string name="accessibility_action_divider_move_left" msgid="9218189832115847253">"Perkelti kairėn"</string>
+    <string name="accessibility_action_divider_move_right" msgid="4671522715182567972">"Perkelti dešinėn"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-lt/strings_tv.xml b/packages/SystemUI/res/values-lt/strings_tv.xml
new file mode 100644
index 0000000..ac3a44e
--- /dev/null
+++ b/packages/SystemUI/res/values-lt/strings_tv.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2016, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <!-- no translation found for pip_close (3480680679023423574) -->
+    <skip />
+    <string name="pip_fullscreen" msgid="8604643018538487816">"Visas ekranas"</string>
+    <string name="pip_play" msgid="674145557658227044">"Leisti"</string>
+    <string name="pip_pause" msgid="8412075640017218862">"Pristabdyti"</string>
+    <!-- no translation found for pip_hold_home (340086535668778109) -->
+    <skip />
+    <!-- no translation found for pip_onboarding_description (2627737116380318292) -->
+    <skip />
+    <!-- no translation found for pip_onboarding_button (3957426748484904611) -->
+    <skip />
+</resources>
diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml
index 0dab947..29e1b95 100644
--- a/packages/SystemUI/res/values-lv/strings.xml
+++ b/packages/SystemUI/res/values-lv/strings.xml
@@ -74,7 +74,8 @@
     <string name="screenshot_saved_title" msgid="6461865960961414961">"Ekrānuzņēmums ir uzņemts."</string>
     <string name="screenshot_saved_text" msgid="1152839647677558815">"Pieskarieties, lai skatītu ekrānuzņēmumu."</string>
     <string name="screenshot_failed_title" msgid="705781116746922771">"Nevarēja uzņemt ekrānuzņēmumu."</string>
-    <string name="screenshot_failed_text" msgid="1260203058661337274">"Nevar veikt ekrānuzņēmumu (krātuvē nepietiek vietas, vai to neļauj lietotne vai jūsu organizācija)."</string>
+    <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Nevar saglabāt ekrānuzņēmumu, jo krātuvē nepietiek vietas."</string>
+    <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Lietotne vai jūsu organizācija neatļauj veikt ekrānuzņēmumus."</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"USB failu pārsūtīšanas opcijas"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Pievienot kā multivides atskaņotāju (MTP)"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"Pievienot kā kameru (PTP)"</string>
@@ -207,6 +208,7 @@
     <string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"Vairāk laika."</string>
     <string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"Mazāk laika."</string>
     <string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"Apgaismojums ir izslēgts."</string>
+    <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"Zibspuldze nav pieejama."</string>
     <string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"Apgaismojums ir ieslēgts."</string>
     <string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"Apgaismojums ir izslēgts."</string>
     <string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"Apgaismojums ir ieslēgts."</string>
@@ -219,6 +221,10 @@
     <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"Darba režīms ir ieslēgts."</string>
     <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"Darba režīms ir izslēgts."</string>
     <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"Darba režīms ir ieslēgts."</string>
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_off (650231949881093289) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_on (4218725402373934151) -->
+    <skip />
     <string name="accessibility_brightness" msgid="8003681285547803095">"Ekrāna spilgtums"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"2G–3G datu lietojums ir apturēts"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"4G datu lietojums ir apturēts"</string>
@@ -305,6 +311,8 @@
     <string name="recents_launch_disabled_message" msgid="1624523193008871793">"Lietotne <xliff:g id="APP">%s</xliff:g> ir atspējota drošajā režīmā."</string>
     <string name="recents_history_button_label" msgid="5153358867807604821">"Vēsture"</string>
     <string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"Notīrīt"</string>
+    <string name="recents_drag_non_dockable_task_message" msgid="2935843902795166158">"Šajā lietotnē netiek atbalstīts vairāku logu režīms."</string>
+    <string name="recents_launch_non_dockable_task_label" msgid="7862379814938391888">"Lietotnē netiek atbalstīts vairāku logu režīms"</string>
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Horizontāls dalījums"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Vertikāls dalījums"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Pielāgots dalījums"</string>
@@ -452,18 +460,23 @@
     <string name="enable_bluetooth_title" msgid="5027037706500635269">"Vai ieslēgt Bluetooth savienojumu?"</string>
     <string name="enable_bluetooth_message" msgid="9106595990708985385">"Lai pievienotu tastatūru planšetdatoram, vispirms ir jāieslēdz Bluetooth savienojums."</string>
     <string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"Ieslēgt"</string>
-    <string name="apply_to_topic" msgid="3641403489318659666">"Lietot paziņojumiem “<xliff:g id="TOPIC_NAME">%1$s</xliff:g>”"</string>
-    <string name="apply_to_app" msgid="363016783939815960">"Lietot visiem šīs lietotnes paziņojumiem"</string>
+    <string name="show_silently" msgid="6841966539811264192">"Rādīt paziņojumus bez skaņas signāla"</string>
+    <string name="block" msgid="2734508760962682611">"Bloķēt visus paziņojumus"</string>
+    <string name="do_not_silence" msgid="6878060322594892441">"Neizslēgt skaņu"</string>
+    <string name="do_not_silence_block" msgid="4070647971382232311">"Neizslēgt skaņu vai nebloķēt"</string>
+    <string name="tuner_full_importance_settings" msgid="8103289238676424226">"Rādīt ļoti svarīgu paziņojumu iestatījumus"</string>
     <string name="blocked_importance" msgid="5198578988978234161">"Bloķēts"</string>
+    <string name="min_importance" msgid="1901894910809414782">"Minimāls svarīguma līmenis"</string>
     <string name="low_importance" msgid="4109929986107147930">"Nav svarīgs"</string>
     <string name="default_importance" msgid="8192107689995742653">"Parasts"</string>
     <string name="high_importance" msgid="1527066195614050263">"Ļoti svarīgs"</string>
     <string name="max_importance" msgid="5089005872719563894">"Steidzams"</string>
     <string name="notification_importance_blocked" msgid="2397192642657872872">"Nekad nerādīt šos paziņojumus"</string>
-    <string name="notification_importance_low" msgid="4383563267370859725">"Rādīt paziņojumu saraksta apakšdaļā bez skaņas signāla"</string>
-    <string name="notification_importance_default" msgid="4926529615920610817">"Rādīt šos paziņojumus bez skaņas signāla"</string>
-    <string name="notification_importance_high" msgid="3222680136612408223">"Rādīt paziņojumu saraksta augšdaļā un ar skaņas signālu"</string>
-    <string name="notification_importance_max" msgid="5236987171904756134">"Rādīt ekrānā ar skaņas signālu"</string>
+    <string name="notification_importance_min" msgid="1938190340516905748">"Rādīt paziņojumu saraksta apakšdaļā bez skaņas signāla"</string>
+    <string name="notification_importance_low" msgid="3657252049508213048">"Rādīt šos paziņojumus bez skaņas signāla"</string>
+    <string name="notification_importance_default" msgid="4466466472622442175">"Atļaut skaņas signālu šiem paziņojumiem"</string>
+    <string name="notification_importance_high" msgid="2135428926525093825">"Rādīt ekrānā un atļaut skaņas signālu"</string>
+    <string name="notification_importance_max" msgid="5806278962376556491">"Rādīt paziņojumu saraksta augšdaļā, rādīt ekrānā ar skaņas signālu"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"Citi iestatījumi"</string>
     <string name="notification_done" msgid="5279426047273930175">"Gatavs"</string>
     <string name="color_and_appearance" msgid="1254323855964993144">"Krāsas un izskats"</string>
@@ -477,7 +490,7 @@
     <string name="use_dark_theme" msgid="2900938704964299312">"Izmantot tumšo motīvu operētājsistēmai Android"</string>
     <string name="adjust_tint" msgid="3398569573231409878">"Regulēt toni"</string>
     <string name="adjust_brightness" msgid="980039329808178246">"Regulēt spilgtumu"</string>
-    <string name="night_mode_disclaimer" msgid="3297928749219711334">"Tumšais motīvs tiek lietots galvenajos operētājsistēmas Android elementos, kas parasti tiek rādīti ar gaišu motīvu, piemēram, lietotnē Iestatījumi un paziņojumos."</string>
+    <string name="night_mode_disclaimer" msgid="598914896926759578">"Tumšais motīvs tiek lietots galvenajos operētājsistēmas Android elementos, kas parasti tiek rādīti ar gaišu motīvu, piemēram, lietotnē Iestatījumi."</string>
     <string name="color_apply" msgid="9212602012641034283">"Lietot"</string>
     <string name="color_revert_title" msgid="4746666545480534663">"Iestatījumu apstiprināšana"</string>
     <string name="color_revert_message" msgid="9116001069397996691">"Noteiktu krāsu iestatījumu dēļ šī ierīce var kļūt nelietojama. Lai apstiprinātu šos krāsu iestatījumus, noklikšķiniet uz Labi. Ja to neizdarīsiet, pēc 10 sekundēm šie iestatījumi tiks atiestatīti."</string>
@@ -536,4 +549,10 @@
     <item msgid="2139628951880142927">"Rādīt procentuālo vērtību uzlādes laikā (noklusējums)"</item>
     <item msgid="3327323682209964956">"Nerādīt šo ikonu"</item>
   </string-array>
+    <string name="other" msgid="4060683095962566764">"Citi"</string>
+    <string name="accessibility_divider" msgid="5903423481953635044">"Ekrāna sadalītājs"</string>
+    <string name="accessibility_action_divider_move_down" msgid="704893304141890042">"Pārvietot uz leju"</string>
+    <string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"Pārvietot uz augšu"</string>
+    <string name="accessibility_action_divider_move_left" msgid="9218189832115847253">"Pārvietot pa kreisi"</string>
+    <string name="accessibility_action_divider_move_right" msgid="4671522715182567972">"Pārvietot pa labi"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-lv/strings_tv.xml b/packages/SystemUI/res/values-lv/strings_tv.xml
new file mode 100644
index 0000000..7fa804d
--- /dev/null
+++ b/packages/SystemUI/res/values-lv/strings_tv.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2016, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <!-- no translation found for pip_close (3480680679023423574) -->
+    <skip />
+    <string name="pip_fullscreen" msgid="8604643018538487816">"Pilnekrāna režīms"</string>
+    <string name="pip_play" msgid="674145557658227044">"Atskaņot"</string>
+    <string name="pip_pause" msgid="8412075640017218862">"Apturēt"</string>
+    <!-- no translation found for pip_hold_home (340086535668778109) -->
+    <skip />
+    <!-- no translation found for pip_onboarding_description (2627737116380318292) -->
+    <skip />
+    <!-- no translation found for pip_onboarding_button (3957426748484904611) -->
+    <skip />
+</resources>
diff --git a/packages/SystemUI/res/values-mk-rMK/strings.xml b/packages/SystemUI/res/values-mk-rMK/strings.xml
index 2ce778f..cf97df8 100644
--- a/packages/SystemUI/res/values-mk-rMK/strings.xml
+++ b/packages/SystemUI/res/values-mk-rMK/strings.xml
@@ -73,7 +73,8 @@
     <string name="screenshot_saved_title" msgid="6461865960961414961">"Сликата на екранот е снимена."</string>
     <string name="screenshot_saved_text" msgid="1152839647677558815">"Допрете за да ја видите сликата на екранот."</string>
     <string name="screenshot_failed_title" msgid="705781116746922771">"Сликата на екранот не можеше да се сними."</string>
-    <string name="screenshot_failed_text" msgid="1260203058661337274">"Не може да направи слика на екран поради огран. простор или не дозволува аплика. или организацијата."</string>
+    <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Сликата од екранот не може да се зачува поради ограничена меморија."</string>
+    <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Апликацијата или вашата организација не дозволува создавање слики од екранот."</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"Пренос на датотека со УСБ"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Монтирај како мултимедијален плеер (MTP)"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"Монтирај како фотоапарат (PTP)"</string>
@@ -206,6 +207,7 @@
     <string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"Повеќе време."</string>
     <string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"Помалку време."</string>
     <string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"Блицот е исклучен."</string>
+    <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"Светилката е недостапна."</string>
     <string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"Блицот е вклучен."</string>
     <string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"Блицот е исклучен."</string>
     <string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"Блицот е вклучен."</string>
@@ -218,6 +220,10 @@
     <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"Режимот на работа е вклучен."</string>
     <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"Режимот на работа е исклучен."</string>
     <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"Режимот на работа е вклучен."</string>
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_off (650231949881093289) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_on (4218725402373934151) -->
+    <skip />
     <string name="accessibility_brightness" msgid="8003681285547803095">"Осветленост на екранот"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"Податоците 2G-3G се паузирани"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"Податоците 4G се паузирани"</string>
@@ -304,6 +310,8 @@
     <string name="recents_launch_disabled_message" msgid="1624523193008871793">"<xliff:g id="APP">%s</xliff:g> е оневозможен во безбеден режим."</string>
     <string name="recents_history_button_label" msgid="5153358867807604821">"Историја"</string>
     <string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"Исчисти"</string>
+    <string name="recents_drag_non_dockable_task_message" msgid="2935843902795166158">"Апликацијава не поддржува повеќе прозорци"</string>
+    <string name="recents_launch_non_dockable_task_label" msgid="7862379814938391888">"Апликацијата не поддржува повеќе прозорци"</string>
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Раздели хоризонтално"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Раздели вертикално"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Раздели прилагодено"</string>
@@ -451,18 +459,23 @@
     <string name="enable_bluetooth_title" msgid="5027037706500635269">"Да се вклучи Bluetooth?"</string>
     <string name="enable_bluetooth_message" msgid="9106595990708985385">"За да ја поврзете тастатурата со таблетот, најпрво треба да вклучите Bluetooth."</string>
     <string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"Вклучи"</string>
-    <string name="apply_to_topic" msgid="3641403489318659666">"Важи за известувањата за <xliff:g id="TOPIC_NAME">%1$s</xliff:g>"</string>
-    <string name="apply_to_app" msgid="363016783939815960">"Важи за сите известувања од оваа апликација"</string>
+    <string name="show_silently" msgid="6841966539811264192">"Тивко прикажувај ги известувањата"</string>
+    <string name="block" msgid="2734508760962682611">"Блокирај ги сите известувања"</string>
+    <string name="do_not_silence" msgid="6878060322594892441">"Не стишувај"</string>
+    <string name="do_not_silence_block" msgid="4070647971382232311">"Не стишувај или блокирај"</string>
+    <string name="tuner_full_importance_settings" msgid="8103289238676424226">"Прикажи ги поставките со целосна важност"</string>
     <string name="blocked_importance" msgid="5198578988978234161">"Блокирано"</string>
+    <string name="min_importance" msgid="1901894910809414782">"Минимална важност"</string>
     <string name="low_importance" msgid="4109929986107147930">"Мала важност"</string>
     <string name="default_importance" msgid="8192107689995742653">"Нормална важност"</string>
     <string name="high_importance" msgid="1527066195614050263">"Голема важност"</string>
     <string name="max_importance" msgid="5089005872719563894">"Итна важност"</string>
     <string name="notification_importance_blocked" msgid="2397192642657872872">"Никогаш не ги прикажувај известувањава"</string>
-    <string name="notification_importance_low" msgid="4383563267370859725">"Тивко прикажувај ги на дното на списокот со известувања"</string>
-    <string name="notification_importance_default" msgid="4926529615920610817">"Тивко прикажувај ги известувањава"</string>
-    <string name="notification_importance_high" msgid="3222680136612408223">"Прикажувај ги на врвот на списокот со известувања и дај звучен сигнал"</string>
-    <string name="notification_importance_max" msgid="5236987171904756134">"Појави се на екранот и дај звучен сигнал"</string>
+    <string name="notification_importance_min" msgid="1938190340516905748">"Тивко прикажувај ги на дното на списокот со известувања"</string>
+    <string name="notification_importance_low" msgid="3657252049508213048">"Тивко прикажувај ги известувањава"</string>
+    <string name="notification_importance_default" msgid="4466466472622442175">"Овозможи им на известувањава да прават звуци"</string>
+    <string name="notification_importance_high" msgid="2135428926525093825">"Ѕиркање на екранот и овозможен звук и овозможен звук"</string>
+    <string name="notification_importance_max" msgid="5806278962376556491">"Прикажувај ги на врвот на списокот со известувања, ѕиркање на екранот и овозможи звук"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"Повеќе поставки"</string>
     <string name="notification_done" msgid="5279426047273930175">"Готово"</string>
     <string name="color_and_appearance" msgid="1254323855964993144">"Боја и изглед"</string>
@@ -476,7 +489,7 @@
     <string name="use_dark_theme" msgid="2900938704964299312">"Користете ја темната тема за ОС Android"</string>
     <string name="adjust_tint" msgid="3398569573231409878">"Приспособи ја бојата"</string>
     <string name="adjust_brightness" msgid="980039329808178246">"Приспособи ја осветленоста"</string>
-    <string name="night_mode_disclaimer" msgid="3297928749219711334">"Темната тема се применува на основните области на ОС Android што обично се прикажуваат во светла тема, како Поставки и известувања."</string>
+    <string name="night_mode_disclaimer" msgid="598914896926759578">"Темната тема се применува на основните области на Android OS што обично се прикажуваат во светла тема, како Поставки."</string>
     <string name="color_apply" msgid="9212602012641034283">"Примени"</string>
     <string name="color_revert_title" msgid="4746666545480534663">"Потврдете ги поставките"</string>
     <string name="color_revert_message" msgid="9116001069397996691">"Некои поставки на боите може да го направат уредот неупотреблив. Кликнете на Во ред за да ги потврдите овие поставки на боите, инаку тие поставки ќе се ресетираат по 10 секунди."</string>
@@ -535,4 +548,10 @@
     <item msgid="2139628951880142927">"Прикажи процент кога се полни (стандардно)"</item>
     <item msgid="3327323682209964956">"Не прикажувај ја иконава"</item>
   </string-array>
+    <string name="other" msgid="4060683095962566764">"Друго"</string>
+    <string name="accessibility_divider" msgid="5903423481953635044">"Разделник на поделен екран"</string>
+    <string name="accessibility_action_divider_move_down" msgid="704893304141890042">"Преместете надолу"</string>
+    <string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"Преместете нагоре"</string>
+    <string name="accessibility_action_divider_move_left" msgid="9218189832115847253">"Преместете налево"</string>
+    <string name="accessibility_action_divider_move_right" msgid="4671522715182567972">"Преместете надесно"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-mk-rMK/strings_tv.xml b/packages/SystemUI/res/values-mk-rMK/strings_tv.xml
new file mode 100644
index 0000000..30c6db9
--- /dev/null
+++ b/packages/SystemUI/res/values-mk-rMK/strings_tv.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2016, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <!-- no translation found for pip_close (3480680679023423574) -->
+    <skip />
+    <string name="pip_fullscreen" msgid="8604643018538487816">"Цел екран"</string>
+    <string name="pip_play" msgid="674145557658227044">"Пушти"</string>
+    <string name="pip_pause" msgid="8412075640017218862">"Пауза"</string>
+    <!-- no translation found for pip_hold_home (340086535668778109) -->
+    <skip />
+    <!-- no translation found for pip_onboarding_description (2627737116380318292) -->
+    <skip />
+    <!-- no translation found for pip_onboarding_button (3957426748484904611) -->
+    <skip />
+</resources>
diff --git a/packages/SystemUI/res/values-ml-rIN/strings.xml b/packages/SystemUI/res/values-ml-rIN/strings.xml
index e6d2e90..df69933 100644
--- a/packages/SystemUI/res/values-ml-rIN/strings.xml
+++ b/packages/SystemUI/res/values-ml-rIN/strings.xml
@@ -73,7 +73,8 @@
     <string name="screenshot_saved_title" msgid="6461865960961414961">"സ്‌ക്രീൻഷോട്ട് എടുത്തു."</string>
     <string name="screenshot_saved_text" msgid="1152839647677558815">"നിങ്ങളുടെ സ്‌ക്രീൻഷോട്ട് കാണാനായി സ്‌പർശിക്കുക."</string>
     <string name="screenshot_failed_title" msgid="705781116746922771">"സ്‌ക്രീൻഷോട്ട് എടുക്കാൻ കഴിഞ്ഞില്ല."</string>
-    <string name="screenshot_failed_text" msgid="1260203058661337274">"സംഭരണ ഇടം പരിമിതമായതിനാൽ സ്‌ക്രീൻഷോട്ട് എടുക്കാനാകില്ല, അല്ലെങ്കിൽ ഇത് അപ്ലിക്കേഷനോ നിങ്ങളുടെ ഓർഗനൈസേഷനോ അനുവദിക്കുന്നില്ല."</string>
+    <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"സ്റ്റോറേജ് ഇടം പരിമിതമായതിനാൽ സ്ക്രീൻഷോട്ട് സംരക്ഷിക്കാൻ കഴിയില്ല."</string>
+    <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"സ്ക്രീൻഷോട്ടുകൾ എടുക്കുന്നത് ആപ്പോ നിങ്ങളുടെ സ്ഥാപനമോ അനുവദിക്കുന്നില്ല."</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"USB ഫയൽ കൈമാറൽ ഓപ്‌ഷനുകൾ"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"ഒരു മീഡിയ പ്ലേയറായി (MTP) മൗണ്ടുചെയ്യുക"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"ഒരു ക്യാമറയായി (PTP) മൗണ്ടുചെയ്യുക"</string>
@@ -206,6 +207,7 @@
     <string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"കൂടുതൽ സമയം."</string>
     <string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"സമയം കുറയ്‌ക്കുക."</string>
     <string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"ടോർച്ച് ഓഫാണ്."</string>
+    <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"ടോർച്ച് ലഭ്യമല്ല."</string>
     <string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"ടോർച്ച് ഓണാണ്."</string>
     <string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"ടോർച്ച് ഓഫാക്കി."</string>
     <string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"ടോർച്ച് ഓണാക്കി."</string>
@@ -218,6 +220,10 @@
     <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"പ്രവർത്തന മോഡ് ഓണാണ്."</string>
     <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"പ്രവർത്തന മോഡ് ഓഫാക്കി."</string>
     <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"പ്രവർത്തന മോഡ് ഓണാക്കി."</string>
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_off (650231949881093289) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_on (4218725402373934151) -->
+    <skip />
     <string name="accessibility_brightness" msgid="8003681285547803095">"ഡിസ്പ്ലേ തെളിച്ചം"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"2G-3G ഡാറ്റ താൽക്കാലികമായി നിർത്തി"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"4G ഡാറ്റ താൽക്കാലികമായി നിർത്തി"</string>
@@ -304,6 +310,8 @@
     <string name="recents_launch_disabled_message" msgid="1624523193008871793">"സുരക്ഷിത മോഡിൽ <xliff:g id="APP">%s</xliff:g> പ്രവർത്തനരഹിതമാക്കിയിരിക്കുന്നു."</string>
     <string name="recents_history_button_label" msgid="5153358867807604821">"ചരിത്രം"</string>
     <string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"മായ്‌ക്കുക"</string>
+    <string name="recents_drag_non_dockable_task_message" msgid="2935843902795166158">"ഒന്നിലധികം വിൻഡോകളെ ഈ ആപ്പ് പിന്തുണയ്ക്കുന്നില്ല"</string>
+    <string name="recents_launch_non_dockable_task_label" msgid="7862379814938391888">"ഒന്നിലധികം വിൻഡോകളെ ആപ്പ് പിന്തുണയ്ക്കുന്നില്ല"</string>
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"തിരശ്ചീനമായി വേർതിരിക്കുക"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"ലംബമായി വേർതിരിക്കുക"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"ഇഷ്‌ടാനുസൃതമായി വേർതിരിക്കുക"</string>
@@ -451,18 +459,23 @@
     <string name="enable_bluetooth_title" msgid="5027037706500635269">"Bluetooth ഓണാക്കണോ?"</string>
     <string name="enable_bluetooth_message" msgid="9106595990708985385">"നിങ്ങളുടെ ടാബ്‌ലെറ്റുമായി കീബോർഡ് കണക്റ്റുചെയ്യുന്നതിന്, ആദ്യം Bluetooth ഓണാക്കേണ്ടതുണ്ട്."</string>
     <string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"ഓണാക്കുക"</string>
-    <string name="apply_to_topic" msgid="3641403489318659666">"<xliff:g id="TOPIC_NAME">%1$s</xliff:g> അറിയിപ്പുകളിലേക്ക് പ്രയോഗിക്കുക"</string>
-    <string name="apply_to_app" msgid="363016783939815960">"ഈ ആപ്പിൽ നിന്നുള്ള എല്ലാ അറിയിപ്പുകളിലേക്കും പ്രയോഗിക്കുക"</string>
+    <string name="show_silently" msgid="6841966539811264192">"അറിയിപ്പുകൾ നിശ്ശബ്ദമായി കാണിക്കുക"</string>
+    <string name="block" msgid="2734508760962682611">"എല്ലാ അറിയിപ്പുകളും ബ്ലോക്കുചെയ്യുക"</string>
+    <string name="do_not_silence" msgid="6878060322594892441">"നിശബ്ദമാക്കരുത്"</string>
+    <string name="do_not_silence_block" msgid="4070647971382232311">"നിശബ്ദമാക്കുകയോ ബ്ലോക്കുചെയ്യുകയോ അരുത്"</string>
+    <string name="tuner_full_importance_settings" msgid="8103289238676424226">"പൂർണ്ണ പ്രാധാന്യ ക്രമീകരണം കാണിക്കുക"</string>
     <string name="blocked_importance" msgid="5198578988978234161">"ബ്ലോക്കുചെയ്തു"</string>
+    <string name="min_importance" msgid="1901894910809414782">"കുറഞ്ഞ പ്രാധാന്യം"</string>
     <string name="low_importance" msgid="4109929986107147930">"താഴ്ന്ന പ്രാധാന്യം"</string>
     <string name="default_importance" msgid="8192107689995742653">"സാധാരണ പ്രാധാന്യം"</string>
     <string name="high_importance" msgid="1527066195614050263">"ഉയർന്ന പ്രാധാന്യം"</string>
     <string name="max_importance" msgid="5089005872719563894">"അടിയന്തര പ്രാധാന്യം"</string>
     <string name="notification_importance_blocked" msgid="2397192642657872872">"ഈ അറിയിപ്പുകൾ ഒരിക്കലും കാണിക്കരുത്"</string>
-    <string name="notification_importance_low" msgid="4383563267370859725">"അറിയിപ്പ് ലിസ്റ്റിന്റെ താഴെ ശബ്ദമുണ്ടാക്കാതെ കാണിക്കുക"</string>
-    <string name="notification_importance_default" msgid="4926529615920610817">"ഈ അറിയിപ്പുകൾ നിശബ്ദമായി കാണിക്കുക"</string>
-    <string name="notification_importance_high" msgid="3222680136612408223">"അറിയിപ്പ് ലിസ്റ്റിന്റെ ഏറ്റവും മുകളിൽ കാണിക്കുക, ശബ്ദമുണ്ടാക്കുക"</string>
-    <string name="notification_importance_max" msgid="5236987171904756134">"സ്ക്രീനിൽ ദൃശ്യമാക്കുക, ശബ്ദമുണ്ടാക്കുക"</string>
+    <string name="notification_importance_min" msgid="1938190340516905748">"അറിയിപ്പ് ലിസ്റ്റിന്റെ താഴെ ശബ്ദമുണ്ടാക്കാതെ കാണിക്കുക"</string>
+    <string name="notification_importance_low" msgid="3657252049508213048">"ഈ അറിയിപ്പുകൾ നിശബ്ദമായി കാണിക്കുക"</string>
+    <string name="notification_importance_default" msgid="4466466472622442175">"ശബ്ദമുണ്ടാക്കാൻ ഈ അറിയിപ്പുകളെ അനുവദിക്കുക"</string>
+    <string name="notification_importance_high" msgid="2135428926525093825">"സ്ക്രീനിൽ ദൃശ്യമാക്കുക, ശബ്ദമുണ്ടാക്കുക"</string>
+    <string name="notification_importance_max" msgid="5806278962376556491">"അറിയിപ്പ് ലിസ്റ്റിന്റെ ഏറ്റവും മുകളിൽ കാണിക്കുക, ശബ്ദമുണ്ടാക്കുക"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"കൂടുതൽ ക്രമീകരണം"</string>
     <string name="notification_done" msgid="5279426047273930175">"പൂർത്തിയായി"</string>
     <string name="color_and_appearance" msgid="1254323855964993144">"വർണ്ണവും രൂപഭാവവും"</string>
@@ -476,7 +489,7 @@
     <string name="use_dark_theme" msgid="2900938704964299312">"Android OS-നുള്ള ഇരുണ്ട തീം ഉപയോഗിക്കുക"</string>
     <string name="adjust_tint" msgid="3398569573231409878">"ടിന്റ് ക്രമപ്പെടുത്തുക"</string>
     <string name="adjust_brightness" msgid="980039329808178246">"തെളിച്ചം ക്രമപ്പെടുത്തുക"</string>
-    <string name="night_mode_disclaimer" msgid="3297928749219711334">"ക്രമീകരണവും അറിയിപ്പുകളും പോലെയുള്ള, ഒരു ലൈറ്റ് തീമിൽ സാധാരണ ഗതിയിൽ പ്രദർശിപ്പിക്കപ്പെടുന്ന Android OS-ന്റെ അടിസ്ഥാന ഇടങ്ങളിലേക്ക്, ഇരുണ്ട തീം പ്രയോഗിക്കുന്നു."</string>
+    <string name="night_mode_disclaimer" msgid="598914896926759578">"ക്രമീകരണം പോലെയുള്ള, ഒരു ലൈറ്റ് തീമിൽ സാധാരണ ഗതിയിൽ പ്രദർശിപ്പിക്കപ്പെടുന്ന Android OS-ന്റെ അടിസ്ഥാന ഇടങ്ങളിലേക്ക്, ഇരുണ്ട തീം പ്രയോഗിക്കുന്നു."</string>
     <string name="color_apply" msgid="9212602012641034283">"ബാധകമാക്കുക"</string>
     <string name="color_revert_title" msgid="4746666545480534663">"ക്രമീകരണം സ്ഥിരീകരിക്കുക"</string>
     <string name="color_revert_message" msgid="9116001069397996691">"ചില വർണ്ണ ക്രമീകരണത്തിന് ഈ ഉപകരണത്തെ ഉപയോഗരഹിതമാക്കാനാകും. ഈ വർണ്ണ ക്രമീകരണം സ്ഥിരീകരിക്കുന്നതിന് ശരി എന്നതിൽ ക്ലിക്കുചെയ്യുക, അല്ലെങ്കിൽ 10 സെക്കൻഡിന് ശേഷം ഈ ക്രമീകരണം പുനഃക്രമീകരിക്കപ്പെടും."</string>
@@ -535,4 +548,10 @@
     <item msgid="2139628951880142927">"ചാർജ്ജുചെയ്യുമ്പോൾ ശതമാനം കാണിക്കുക (ഡിഫോൾട്ട്)"</item>
     <item msgid="3327323682209964956">"ഈ ഐക്കൺ കാണിക്കരുത്"</item>
   </string-array>
+    <string name="other" msgid="4060683095962566764">"മറ്റുള്ളവ"</string>
+    <string name="accessibility_divider" msgid="5903423481953635044">"സ്പ്ലിറ്റ്-സ്ക്രീൻ ഡിവൈഡർ"</string>
+    <string name="accessibility_action_divider_move_down" msgid="704893304141890042">"താഴേക്ക് നീക്കുക"</string>
+    <string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"മുകളിലേക്ക് നീക്കുക"</string>
+    <string name="accessibility_action_divider_move_left" msgid="9218189832115847253">"ഇടത്തേക്ക് നീക്കുക"</string>
+    <string name="accessibility_action_divider_move_right" msgid="4671522715182567972">"വലത്തേക്ക് നീക്കുക"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ml-rIN/strings_tv.xml b/packages/SystemUI/res/values-ml-rIN/strings_tv.xml
new file mode 100644
index 0000000..564a32a
--- /dev/null
+++ b/packages/SystemUI/res/values-ml-rIN/strings_tv.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2016, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <!-- no translation found for pip_close (3480680679023423574) -->
+    <skip />
+    <string name="pip_fullscreen" msgid="8604643018538487816">"പൂര്‍ണ്ണ സ്ക്രീന്‍"</string>
+    <string name="pip_play" msgid="674145557658227044">"പ്ലേ ചെയ്യുക"</string>
+    <string name="pip_pause" msgid="8412075640017218862">"തൽക്കാലം നിർത്തൂ"</string>
+    <!-- no translation found for pip_hold_home (340086535668778109) -->
+    <skip />
+    <!-- no translation found for pip_onboarding_description (2627737116380318292) -->
+    <skip />
+    <!-- no translation found for pip_onboarding_button (3957426748484904611) -->
+    <skip />
+</resources>
diff --git a/packages/SystemUI/res/values-mn-rMN/strings.xml b/packages/SystemUI/res/values-mn-rMN/strings.xml
index 37d1ba7..793e165 100644
--- a/packages/SystemUI/res/values-mn-rMN/strings.xml
+++ b/packages/SystemUI/res/values-mn-rMN/strings.xml
@@ -71,7 +71,8 @@
     <string name="screenshot_saved_title" msgid="6461865960961414961">"Дэлгэцийн агшинг авсан."</string>
     <string name="screenshot_saved_text" msgid="1152839647677558815">"Дэлгэцийн агшныг харах бол хүрнэ үү."</string>
     <string name="screenshot_failed_title" msgid="705781116746922771">"Дэлгэцийн агшинг авч чадсангүй."</string>
-    <string name="screenshot_failed_text" msgid="1260203058661337274">"Хадгалах сан хязгаартай эсхүл таны байгууллага буюу апп-с зөвшөөрөөгүй учир дэлгэцийн зургийг авах боломжгүй."</string>
+    <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Хадгалах сангийн багтаамж бага байгаа тул дэлгэцийн авсан зургийг хадгалах боломжгүй байна."</string>
+    <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Дэлгэцийн зураг авахыг апп эсвэл танай байгууллагаас зөвшөөрөөгүй байна."</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"USB файл шилжүүлэх сонголт"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Медиа тоглуулагч(MTP) болгон залгах"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"Камер болгон(PTP) залгах"</string>
@@ -204,6 +205,7 @@
     <string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"Хугацаа нэмэх."</string>
     <string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"Хугацаа хасах."</string>
     <string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"Флаш гэрэл унтарсан."</string>
+    <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"Гэрэлтүүлэгч боломжгүй байна."</string>
     <string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"Флаш гэрэл ассан."</string>
     <string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"Флаш гэрлийг унтраасан."</string>
     <string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"Флаш гэрлийг асаасан."</string>
@@ -216,6 +218,10 @@
     <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"Ажлын горимыг асаасан."</string>
     <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"Ажлын горимыг унтраасан."</string>
     <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"Ажлын горимыг асаасан."</string>
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_off (650231949881093289) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_on (4218725402373934151) -->
+    <skip />
     <string name="accessibility_brightness" msgid="8003681285547803095">"Дэлгэцийн гэрэлтэлт"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"2G-3G дата-г түр зогсоосон байна"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"4G дата-г түр зогсоосон байна"</string>
@@ -302,6 +308,8 @@
     <string name="recents_launch_disabled_message" msgid="1624523193008871793">"<xliff:g id="APP">%s</xliff:g>-г аюулгүй горимд идэвхгүй болгосон."</string>
     <string name="recents_history_button_label" msgid="5153358867807604821">"Түүх"</string>
     <string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"Устгах"</string>
+    <string name="recents_drag_non_dockable_task_message" msgid="2935843902795166158">"Энэ апп олон цонхыг дэмждэггүй"</string>
+    <string name="recents_launch_non_dockable_task_label" msgid="7862379814938391888">"Апп олон цонхыг дэмждэггүй"</string>
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Хэвтээ чиглэлд хуваах"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Босоо чиглэлд хуваах"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Хүссэн хэлбэрээр хуваах"</string>
@@ -449,18 +457,23 @@
     <string name="enable_bluetooth_title" msgid="5027037706500635269">"Bluetooth-г асаах уу?"</string>
     <string name="enable_bluetooth_message" msgid="9106595990708985385">"Компьютерийн гараа таблетад холбохын тулд эхлээд Bluetooth-г асаана уу."</string>
     <string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"Асаах"</string>
-    <string name="apply_to_topic" msgid="3641403489318659666">"<xliff:g id="TOPIC_NAME">%1$s</xliff:g> мэдэгдэлд хэрэгжүүлэх"</string>
-    <string name="apply_to_app" msgid="363016783939815960">"Энэ апп-н бүх мэдэгдэлд хэрэгжүүлэх"</string>
+    <string name="show_silently" msgid="6841966539811264192">"Мэдэгдлийг чимээгүй харуулах"</string>
+    <string name="block" msgid="2734508760962682611">"Бүх мэдэгдлийг блоклох"</string>
+    <string name="do_not_silence" msgid="6878060322594892441">"Дуугүй болгох хэрэггүй"</string>
+    <string name="do_not_silence_block" msgid="4070647971382232311">"Дууг нь хаах эсвэл блоклох хэрэггүй"</string>
+    <string name="tuner_full_importance_settings" msgid="8103289238676424226">"Бүрэн ач холбогдлын тохиргоог харуулах"</string>
     <string name="blocked_importance" msgid="5198578988978234161">"Блоклосон"</string>
+    <string name="min_importance" msgid="1901894910809414782">"Хамгийн бага ач холбогдол"</string>
     <string name="low_importance" msgid="4109929986107147930">"Бага ач холбогдолтой"</string>
     <string name="default_importance" msgid="8192107689995742653">"Энгийн ач холбогдолтой"</string>
     <string name="high_importance" msgid="1527066195614050263">"Өндөр ач холбогдолтой"</string>
     <string name="max_importance" msgid="5089005872719563894">"Яаралтай ач холбогдолтой"</string>
     <string name="notification_importance_blocked" msgid="2397192642657872872">"Эдгээр мэдэгдлийг хэзээ ч харуулахгүй"</string>
-    <string name="notification_importance_low" msgid="4383563267370859725">"Мэдэгдлийг жагсаалтын доод хэсэгт дуугүй харуулах"</string>
-    <string name="notification_importance_default" msgid="4926529615920610817">"Эдгээр мэдэгдлийг дуугүй харуулах"</string>
-    <string name="notification_importance_high" msgid="3222680136612408223">"Мэдэгдлийг жагсаалтын эхэнд дуутай харуулах"</string>
-    <string name="notification_importance_max" msgid="5236987171904756134">"Дэлгэцэнд яаралтайгаар дуутай гаргах"</string>
+    <string name="notification_importance_min" msgid="1938190340516905748">"Мэдэгдлийг жагсаалтын доод хэсэгт дуугүй харуулах"</string>
+    <string name="notification_importance_low" msgid="3657252049508213048">"Эдгээр мэдэгдлийг дуугүй харуулах"</string>
+    <string name="notification_importance_default" msgid="4466466472622442175">"Эдгээр мэдэгдлийг дуу гаргахыг зөвшөөрөх"</string>
+    <string name="notification_importance_high" msgid="2135428926525093825">"Дэлгэцэд яаралтайгаар дуутай гаргах"</string>
+    <string name="notification_importance_max" msgid="5806278962376556491">"Мэдэгдлийг жагсаалтын эхэнд яаралтай дуутай харуулах"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"Бусад тохиргоо"</string>
     <string name="notification_done" msgid="5279426047273930175">"Дууссан"</string>
     <string name="color_and_appearance" msgid="1254323855964993144">"Өнгө, харагдах байдал"</string>
@@ -474,7 +487,7 @@
     <string name="use_dark_theme" msgid="2900938704964299312">"Android-н үйлдлийн системд бараан загварыг ашиглах"</string>
     <string name="adjust_tint" msgid="3398569573231409878">"Өнгөний нягтаршилыг тохируулах"</string>
     <string name="adjust_brightness" msgid="980039329808178246">"Гэрэлтүүлгийг тохируулах"</string>
-    <string name="night_mode_disclaimer" msgid="3297928749219711334">"Тохиргоо, мэдэгдэл зэрэг тогтмол цайвар загварт харуулдаг Android үйлдлийн системийн гол хэсгийг бараан загварт харуулна."</string>
+    <string name="night_mode_disclaimer" msgid="598914896926759578">"Тохиргоо зэрэг тогтмол цайвар загварт харуулдаг Android үйлдлийн системийн гол хэсгийг бараан загварт харуулна."</string>
     <string name="color_apply" msgid="9212602012641034283">"Хэрэгжүүлэх"</string>
     <string name="color_revert_title" msgid="4746666545480534663">"Тохиргоог баталгаажуулах"</string>
     <string name="color_revert_message" msgid="9116001069397996691">"Зарим өнгөний тохиргоо энэ төхөөрөмжийг ашиглах боломжгүй болгож болзошгүй. OK товчлуурыг дарж эдгээр өнгөний тохиргоог зөвшөөрөхгүй бол энэ тохиргоо нь 10 секундын дараа шинэчлэгдэх болно."</string>
@@ -533,4 +546,10 @@
     <item msgid="2139628951880142927">"Цэнэглэх үед хувийг тогтмол харуулах (өгөгдмөл)"</item>
     <item msgid="3327323682209964956">"Энэ дүрс тэмдгийг бүү үзүүл"</item>
   </string-array>
+    <string name="other" msgid="4060683095962566764">"Бусад"</string>
+    <string name="accessibility_divider" msgid="5903423481953635044">"\"Дэлгэц хуваах\" хуваагч"</string>
+    <string name="accessibility_action_divider_move_down" msgid="704893304141890042">"Доош зөөх"</string>
+    <string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"Дээш зөөх"</string>
+    <string name="accessibility_action_divider_move_left" msgid="9218189832115847253">"Зүүн тийш зөөх"</string>
+    <string name="accessibility_action_divider_move_right" msgid="4671522715182567972">"Баруун тийш зөөх"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-mn-rMN/strings_tv.xml b/packages/SystemUI/res/values-mn-rMN/strings_tv.xml
new file mode 100644
index 0000000..ae4029f
--- /dev/null
+++ b/packages/SystemUI/res/values-mn-rMN/strings_tv.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2016, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <!-- no translation found for pip_close (3480680679023423574) -->
+    <skip />
+    <string name="pip_fullscreen" msgid="8604643018538487816">"Бүтэн дэлгэц"</string>
+    <string name="pip_play" msgid="674145557658227044">"Тоглуулах"</string>
+    <string name="pip_pause" msgid="8412075640017218862">"Түр зогсоох"</string>
+    <!-- no translation found for pip_hold_home (340086535668778109) -->
+    <skip />
+    <!-- no translation found for pip_onboarding_description (2627737116380318292) -->
+    <skip />
+    <!-- no translation found for pip_onboarding_button (3957426748484904611) -->
+    <skip />
+</resources>
diff --git a/packages/SystemUI/res/values-mr-rIN/strings.xml b/packages/SystemUI/res/values-mr-rIN/strings.xml
index 3156b5c..e39db5d 100644
--- a/packages/SystemUI/res/values-mr-rIN/strings.xml
+++ b/packages/SystemUI/res/values-mr-rIN/strings.xml
@@ -73,7 +73,8 @@
     <string name="screenshot_saved_title" msgid="6461865960961414961">"स्क्रीनशॉट कॅप्चर केला."</string>
     <string name="screenshot_saved_text" msgid="1152839647677558815">"आपला स्क्रीनशॉट पाहण्यासाठी स्पर्श करा."</string>
     <string name="screenshot_failed_title" msgid="705781116746922771">"स्क्रीनशॉट कॅप्चर करू शकलो नाही."</string>
-    <string name="screenshot_failed_text" msgid="1260203058661337274">"मर्यादित संचयन स्‍थानामुळे किंवा अ‍ॅपद्वारे किंवा आपल्‍या संस्‍थेद्वारे त्याची अनुमती नसल्‍यामुळे स्‍क्रीनशॉट घेऊ शकत नाही."</string>
+    <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"मर्यादित संचय जागेमुळे स्क्रीनशॉट जतन करू शकत नाही."</string>
+    <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"अॅप किंवा आपल्या संस्थेद्वारे स्क्रीनशॉट घेण्यास अनुमती नाही."</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"USB फाईल स्थानांतरण पर्याय"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"मीडिया प्लेअर म्हणून माउंट करा (MTP)"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"कॅमेरा म्हणून माउंट करा (PTP)"</string>
@@ -206,6 +207,7 @@
     <string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"अधिक वेळ."</string>
     <string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"कमी वेळ."</string>
     <string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"फ्लॅशलाइट बंद."</string>
+    <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"फ्लॅशलाइट अनुपलब्ध आहे."</string>
     <string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"फ्लॅशलाइट चालू."</string>
     <string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"फ्लॅशलाइट बंद केला."</string>
     <string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"फ्लॅशलाइट चालू केला."</string>
@@ -218,6 +220,10 @@
     <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"कार्य मोड चालू."</string>
     <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"कार्य मोड बंद केला."</string>
     <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"कार्य मोड चालू केला."</string>
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_off (650231949881093289) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_on (4218725402373934151) -->
+    <skip />
     <string name="accessibility_brightness" msgid="8003681285547803095">"प्रदर्शन चमक"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"2G-3G डेटास विराम दिला आहे"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"4G डेटास विराम दिला आहे"</string>
@@ -304,6 +310,8 @@
     <string name="recents_launch_disabled_message" msgid="1624523193008871793">"<xliff:g id="APP">%s</xliff:g> सुरक्षित-मोडमध्ये अक्षम केला आहे."</string>
     <string name="recents_history_button_label" msgid="5153358867807604821">"इतिहास"</string>
     <string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"साफ करा"</string>
+    <string name="recents_drag_non_dockable_task_message" msgid="2935843902795166158">"हा अॅप एकाधिक-विंडोला समर्थन देत नाही"</string>
+    <string name="recents_launch_non_dockable_task_label" msgid="7862379814938391888">"अॅप एकाधिक-विंडोला समर्थन देत नाही"</string>
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"क्षैतिज विभाजित करा"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"अनुलंब विभाजित करा"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"सानुकूल विभाजित करा"</string>
@@ -451,18 +459,23 @@
     <string name="enable_bluetooth_title" msgid="5027037706500635269">"ब्लूटुथ सुरू करायचे?"</string>
     <string name="enable_bluetooth_message" msgid="9106595990708985385">"आपला कीबोर्ड आपल्या टॅब्लेटसह कनेक्ट करण्यासाठी, आपल्याला प्रथम ब्लूटुथ चालू करणे आवश्यक आहे."</string>
     <string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"चालू करा"</string>
-    <string name="apply_to_topic" msgid="3641403489318659666">"<xliff:g id="TOPIC_NAME">%1$s</xliff:g> सूचनांवर लागू करा"</string>
-    <string name="apply_to_app" msgid="363016783939815960">"या अॅपमधील सर्व सूचनांवर लागू करा"</string>
+    <string name="show_silently" msgid="6841966539811264192">"सूचना शांतपणे दर्शवा"</string>
+    <string name="block" msgid="2734508760962682611">"सर्व सूचना अवरोधित करा"</string>
+    <string name="do_not_silence" msgid="6878060322594892441">"शांत करू नका"</string>
+    <string name="do_not_silence_block" msgid="4070647971382232311">"शांत किंवा अवरोधित करू नका"</string>
+    <string name="tuner_full_importance_settings" msgid="8103289238676424226">"पूर्ण महत्त्व सेटिंग्ज दर्शवा"</string>
     <string name="blocked_importance" msgid="5198578988978234161">"अवरोधित केले"</string>
+    <string name="min_importance" msgid="1901894910809414782">"किमान महत्त्व"</string>
     <string name="low_importance" msgid="4109929986107147930">"कमी महत्त्व"</string>
     <string name="default_importance" msgid="8192107689995742653">"सामान्य महत्त्व"</string>
     <string name="high_importance" msgid="1527066195614050263">"सर्वाधिक महत्व"</string>
     <string name="max_importance" msgid="5089005872719563894">"त्वरित महत्त्व"</string>
     <string name="notification_importance_blocked" msgid="2397192642657872872">"या सूचना कधीही दर्शवू नका"</string>
-    <string name="notification_importance_low" msgid="4383563267370859725">"सूचना सूचीच्या तळाशी शांतपणे दर्शवा"</string>
-    <string name="notification_importance_default" msgid="4926529615920610817">"या सूचना शांतपणे दर्शवा"</string>
-    <string name="notification_importance_high" msgid="3222680136612408223">"सूचना सूचीच्या शीर्षस्थानी दर्शवा आणि ध्वनी चालू करा"</string>
-    <string name="notification_importance_max" msgid="5236987171904756134">"स्क्रीनवर डोकावून पहा आणि ध्वनी चालू करा"</string>
+    <string name="notification_importance_min" msgid="1938190340516905748">"सूचना सूचीच्या तळाशी शांतपणे दर्शवा"</string>
+    <string name="notification_importance_low" msgid="3657252049508213048">"या सूचना शांतपणे दर्शवा"</string>
+    <string name="notification_importance_default" msgid="4466466472622442175">"या सूचनांना ध्वनी चालू करण्याची अनुमती द्या"</string>
+    <string name="notification_importance_high" msgid="2135428926525093825">"स्क्रीनवर पहा आणि ध्वनीस अनुमती द्या ध्वनीस अनुमती द्या"</string>
+    <string name="notification_importance_max" msgid="5806278962376556491">"सूचनांच्या शीर्षस्थानी दर्शवा, स्क्रीनवर पहा आणि ध्वनीस अनुमती द्या"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"अधिक सेटिंग्ज"</string>
     <string name="notification_done" msgid="5279426047273930175">"पूर्ण झाले"</string>
     <string name="color_and_appearance" msgid="1254323855964993144">"रंग आणि स्वरूप"</string>
@@ -476,7 +489,7 @@
     <string name="use_dark_theme" msgid="2900938704964299312">"Android OS साठी गडद थीमचा वापर करा"</string>
     <string name="adjust_tint" msgid="3398569573231409878">"रंगाची छटा समायोजित करा"</string>
     <string name="adjust_brightness" msgid="980039329808178246">"चकाकी समायोजित करा"</string>
-    <string name="night_mode_disclaimer" msgid="3297928749219711334">"सामान्यपणे सेटिंग्ज आणि सूचना यासारख्या प्रकाश थीममध्ये दर्शविल्या जाणार्‍या Android OS च्या मुख्य क्षेत्रांवर गडद थीम लागू केली जाते."</string>
+    <string name="night_mode_disclaimer" msgid="598914896926759578">"सेटिंग्ज सारख्या प्रकाश थीममध्ये प्रदर्शित केल्या जाणाऱ्या Android OS च्या मुख्य क्षेत्रांवर गडद थीम लागू केली जाते."</string>
     <string name="color_apply" msgid="9212602012641034283">"लागू करा"</string>
     <string name="color_revert_title" msgid="4746666545480534663">"सेटिंग्जची पुष्टी करा"</string>
     <string name="color_revert_message" msgid="9116001069397996691">"काही रंग सेटिंग्ज या डिव्हाइसला निरुपयोगी करू शकतात. या रंग सेटिंग्जची पुष्टी करण्‍यासाठी ठीक आहे दाबा अन्यथा या सेटिंग्ज 10 सेकंदांनंतर रीसेट होतील."</string>
@@ -535,4 +548,10 @@
     <item msgid="2139628951880142927">"चार्ज करताना टक्केवारी दर्शवा (डीफॉल्ट)"</item>
     <item msgid="3327323682209964956">"हे चिन्ह दर्शवू नका"</item>
   </string-array>
+    <string name="other" msgid="4060683095962566764">"अन्य"</string>
+    <string name="accessibility_divider" msgid="5903423481953635044">"विभाजित-स्क्रीन विभाजक"</string>
+    <string name="accessibility_action_divider_move_down" msgid="704893304141890042">"खाली हलवा"</string>
+    <string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"वर हलवा"</string>
+    <string name="accessibility_action_divider_move_left" msgid="9218189832115847253">"डावीकडे हलवा"</string>
+    <string name="accessibility_action_divider_move_right" msgid="4671522715182567972">"उजवीकडे हलवा"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-mr-rIN/strings_tv.xml b/packages/SystemUI/res/values-mr-rIN/strings_tv.xml
new file mode 100644
index 0000000..fd76c53
--- /dev/null
+++ b/packages/SystemUI/res/values-mr-rIN/strings_tv.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.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="pip_close" msgid="3480680679023423574">"PIP बंद करा"</string>
+    <string name="pip_fullscreen" msgid="8604643018538487816">"पूर्ण स्क्रीन"</string>
+    <string name="pip_play" msgid="674145557658227044">"प्ले करा"</string>
+    <string name="pip_pause" msgid="8412075640017218862">"विराम द्या"</string>
+    <string name="pip_hold_home" msgid="340086535668778109">"PIP नियंत्रित करण्यासाठी "<b>"मुख्यपृष्ठ"</b>" धरून ठेवा"</string>
+    <string name="pip_onboarding_description" msgid="2627737116380318292">"PIP नियंत्रित करण्यासाठी\nमुख्यपृष्ठ बटण धरून ठेवा"</string>
+    <string name="pip_onboarding_button" msgid="3957426748484904611">"समजले"</string>
+</resources>
diff --git a/packages/SystemUI/res/values-ms-rMY/strings.xml b/packages/SystemUI/res/values-ms-rMY/strings.xml
index 2191228..3ec3db1 100644
--- a/packages/SystemUI/res/values-ms-rMY/strings.xml
+++ b/packages/SystemUI/res/values-ms-rMY/strings.xml
@@ -73,7 +73,8 @@
     <string name="screenshot_saved_title" msgid="6461865960961414961">"Tangkapan skrin ditangkap."</string>
     <string name="screenshot_saved_text" msgid="1152839647677558815">"Sentuh untuk melihat tangkapan skrin anda."</string>
     <string name="screenshot_failed_title" msgid="705781116746922771">"Tidak dapat menangkap tangkapan skrin."</string>
-    <string name="screenshot_failed_text" msgid="1260203058661337274">"Tdk dpt mngmbil tgkapn skrin krn ruang storan trhad atau tdk dibenarkn olh apl atau organisasi anda."</string>
+    <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Tidak dapat menyimpan tangkapan skrin kerana ruang storan terhad."</string>
+    <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Apl atau organisasi anda tidak membenarkan pengambilan tangkapan skrin."</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"Pilihan pemindahan fail USB"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Lekapkan sebagai pemain media (MTP)"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"Lekapkan sebagai kamera (PTP)"</string>
@@ -206,6 +207,7 @@
     <string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"Lagi masa."</string>
     <string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"Kurang masa."</string>
     <string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"Lampu suluh dimatikan."</string>
+    <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"Lampu suluh tidak tersedia."</string>
     <string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"Lampu suluh dihidupkan."</string>
     <string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"Lampu suluh dimatikan."</string>
     <string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"Lampu suluh dihidupkan."</string>
@@ -218,6 +220,10 @@
     <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"Mod kerja hidup."</string>
     <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"Mod kerja dimatikan."</string>
     <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"Mod kerja dihidupkan."</string>
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_off (650231949881093289) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_on (4218725402373934151) -->
+    <skip />
     <string name="accessibility_brightness" msgid="8003681285547803095">"Kecerahan paparan"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"Data 2G-3G dijeda"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"Data 4G dijeda"</string>
@@ -304,6 +310,8 @@
     <string name="recents_launch_disabled_message" msgid="1624523193008871793">"<xliff:g id="APP">%s</xliff:g> dilumpuhkan dalam mod selamat."</string>
     <string name="recents_history_button_label" msgid="5153358867807604821">"Sejarah"</string>
     <string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"Kosongkan"</string>
+    <string name="recents_drag_non_dockable_task_message" msgid="2935843902795166158">"Apl ini tidak menyokong berbilang tetingkap"</string>
+    <string name="recents_launch_non_dockable_task_label" msgid="7862379814938391888">"Apl tidak menyokong berbilang tetingkap"</string>
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Mendatar Terpisah"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Menegak Terpisah"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Tersuai Terpisah"</string>
@@ -451,18 +459,23 @@
     <string name="enable_bluetooth_title" msgid="5027037706500635269">"Hidupkan Bluetooth?"</string>
     <string name="enable_bluetooth_message" msgid="9106595990708985385">"Untuk menyambungkan papan kekunci anda dengan tablet, anda perlu menghidupkan Bluetooth terlebih dahulu."</string>
     <string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"Hidupkan"</string>
-    <string name="apply_to_topic" msgid="3641403489318659666">"Gunakan untuk pemberitahuan <xliff:g id="TOPIC_NAME">%1$s</xliff:g>"</string>
-    <string name="apply_to_app" msgid="363016783939815960">"Gunakan untuk semua pemberitahuan daripada apl ini"</string>
+    <string name="show_silently" msgid="6841966539811264192">"Tunjukkan pemberitahuan secara senyap"</string>
+    <string name="block" msgid="2734508760962682611">"Sekat semua pemberitahuan"</string>
+    <string name="do_not_silence" msgid="6878060322594892441">"Jangan senyapkan"</string>
+    <string name="do_not_silence_block" msgid="4070647971382232311">"Jangan senyapkan atau sekat"</string>
+    <string name="tuner_full_importance_settings" msgid="8103289238676424226">"Tunjukkan tetapan kepentingan penuh"</string>
     <string name="blocked_importance" msgid="5198578988978234161">"Disekat"</string>
+    <string name="min_importance" msgid="1901894910809414782">"Kurang penting"</string>
     <string name="low_importance" msgid="4109929986107147930">"Kepentingan rendah"</string>
     <string name="default_importance" msgid="8192107689995742653">"Kepentingan biasa"</string>
     <string name="high_importance" msgid="1527066195614050263">"Kepentingan tinggi"</string>
     <string name="max_importance" msgid="5089005872719563894">"Kepentingan segera"</string>
     <string name="notification_importance_blocked" msgid="2397192642657872872">"Jangan sekali-kali tunjukkan pemberitahuan ini"</string>
-    <string name="notification_importance_low" msgid="4383563267370859725">"Tunjukkan pada bahagian bawah senarai pemberitahuan secara senyap"</string>
-    <string name="notification_importance_default" msgid="4926529615920610817">"Tunjukkan pemberitahuan ini secara senyap"</string>
-    <string name="notification_importance_high" msgid="3222680136612408223">"Tunjukkan pada bahagian atas senarai pemberitahuan dan bunyikan"</string>
-    <string name="notification_importance_max" msgid="5236987171904756134">"Intai pada skrin dan bunyikan"</string>
+    <string name="notification_importance_min" msgid="1938190340516905748">"Tunjukkan pada bahagian bawah senarai pemberitahuan secara senyap"</string>
+    <string name="notification_importance_low" msgid="3657252049508213048">"Tunjukkan pemberitahuan ini secara senyap"</string>
+    <string name="notification_importance_default" msgid="4466466472622442175">"Benarkan pemberitahuan ini berbunyi"</string>
+    <string name="notification_importance_high" msgid="2135428926525093825">"Intai pada skrin dan benarkan bunyi"</string>
+    <string name="notification_importance_max" msgid="5806278962376556491">"Tunjukkan pada bahagian atas senarai pemberitahuan, intai pada skrin dan benarkan bunyi"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"Lagi tetapan"</string>
     <string name="notification_done" msgid="5279426047273930175">"Selesai"</string>
     <string name="color_and_appearance" msgid="1254323855964993144">"Warna dan penampilan"</string>
@@ -476,7 +489,7 @@
     <string name="use_dark_theme" msgid="2900938704964299312">"Gunakan tema gelap untuk OS Android"</string>
     <string name="adjust_tint" msgid="3398569573231409878">"Laraskan seri warna"</string>
     <string name="adjust_brightness" msgid="980039329808178246">"Laraskan kecerahan"</string>
-    <string name="night_mode_disclaimer" msgid="3297928749219711334">"Tema gelap digunakan pada kawasan teras OS Android yang biasanya dipaparkan dalam tema cerah, seperti Tetapan dan pemberitahuan."</string>
+    <string name="night_mode_disclaimer" msgid="598914896926759578">"Tema gelap digunakan pada bahagian teras OS Android yang biasanya dipaparkan dalam tema cerah, seperti Tetapan."</string>
     <string name="color_apply" msgid="9212602012641034283">"Gunakan"</string>
     <string name="color_revert_title" msgid="4746666545480534663">"Sahkan tetapan"</string>
     <string name="color_revert_message" msgid="9116001069397996691">"Sesetengah tetapan warna boleh menjadikan peranti ini tidak dapat digunakan. Klik OK untuk mengesahkan tetapan warna ini, jika tidak, tetapan ini akan ditetapkan semula selepas 10 saat."</string>
@@ -535,4 +548,10 @@
     <item msgid="2139628951880142927">"Tunjukkan peratusan semasa mengecas (lalai)"</item>
     <item msgid="3327323682209964956">"Jangan tunjukkan ikon ini"</item>
   </string-array>
+    <string name="other" msgid="4060683095962566764">"Lain-lain"</string>
+    <string name="accessibility_divider" msgid="5903423481953635044">"Pembahagi skrin pisah"</string>
+    <string name="accessibility_action_divider_move_down" msgid="704893304141890042">"Alih ke bawah"</string>
+    <string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"Alih ke atas"</string>
+    <string name="accessibility_action_divider_move_left" msgid="9218189832115847253">"Alih ke kiri"</string>
+    <string name="accessibility_action_divider_move_right" msgid="4671522715182567972">"Alih ke kanan"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ms-rMY/strings_tv.xml b/packages/SystemUI/res/values-ms-rMY/strings_tv.xml
new file mode 100644
index 0000000..feae042
--- /dev/null
+++ b/packages/SystemUI/res/values-ms-rMY/strings_tv.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2016, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <!-- no translation found for pip_close (3480680679023423574) -->
+    <skip />
+    <string name="pip_fullscreen" msgid="8604643018538487816">"Skrin penuh"</string>
+    <string name="pip_play" msgid="674145557658227044">"Main"</string>
+    <string name="pip_pause" msgid="8412075640017218862">"Jeda"</string>
+    <!-- no translation found for pip_hold_home (340086535668778109) -->
+    <skip />
+    <!-- no translation found for pip_onboarding_description (2627737116380318292) -->
+    <skip />
+    <!-- no translation found for pip_onboarding_button (3957426748484904611) -->
+    <skip />
+</resources>
diff --git a/packages/SystemUI/res/values-my-rMM/strings.xml b/packages/SystemUI/res/values-my-rMM/strings.xml
index 9e519e7..ca34144 100644
--- a/packages/SystemUI/res/values-my-rMM/strings.xml
+++ b/packages/SystemUI/res/values-my-rMM/strings.xml
@@ -73,7 +73,8 @@
     <string name="screenshot_saved_title" msgid="6461865960961414961">"ဖန်သားပြင်ဓါတ်ပုံရိုက်ခြင်းအား ဖမ်းယူပြီး"</string>
     <string name="screenshot_saved_text" msgid="1152839647677558815">"သင့်ဖန်သားပြင်ဓါတ်ပုံရိုက်ခြင်းအား ကြည့်ရှုရန် ထိပါ"</string>
     <string name="screenshot_failed_title" msgid="705781116746922771">"ဖန်သားပြင်ဓါတ်ပုံရိုက်ခြင်းအား မဖမ်းစီးနိုင်ပါ"</string>
-    <string name="screenshot_failed_text" msgid="1260203058661337274">"မျက်နှာပြင်လျှပ်တပြက်ပုံကို မရုက်နိုင်ခဲ့ပါ၊ သိုလှောင်မှု နေရာ အကန့်အသတ် ရှိနေ၍ သို့မဟုတ် app သို့မဟုတ် သင်၏ အဖွဲ့အစည်းက ခွင့်မပြု၍ ဖြစ်နိုင်သည်။"</string>
+    <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"သိုလှောင်ခန်းနေရာ အကန့်အသတ်ရှိသောကြောင့် ဖန်သားပြင်ဓာတ်ပုံကို သိမ်းဆည်း၍မရပါ။"</string>
+    <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"ဖန်သားပြင်ဓာတ်ပုံရိုက်ကူးခြင်းကို အက်ပ်မှ သို့မဟုတ် သင့်အဖွဲ့အစည်းမှ ခွင့်မပြုပါ။"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"USB ဖိုင်ပြောင်း ရွေးမှုများ"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"မီဒီယာပလေရာအနေဖြင့် တပ်ဆင်ရန် (MTP)"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"ကင်မရာအနေဖြင့် တပ်ဆင်ရန် (PTP)"</string>
@@ -206,6 +207,7 @@
     <string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"အချိန် တိုး"</string>
     <string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"အချိန် လျှော့"</string>
     <string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"ဖလက်ရှမီး ပိတ်ထား"</string>
+    <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"ဓာတ်မီးမရသေးပါ။"</string>
     <string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"ဖလက်ရှမီး ဖွင့်ထား။"</string>
     <string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"ဖလက်ရှမီး ပိတ်ထားသည်။"</string>
     <string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"ဖလက်ရှမီး ဖွင့်ထားသည်။"</string>
@@ -218,6 +220,10 @@
     <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"အလုပ် မုဒ်ကို ဖွင့်ထားပါသည်။"</string>
     <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"အလုပ် မုဒ်ကို ပိတ်ထားပါသည်။"</string>
     <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"အလုပ် မုဒ်ကို ဖွင့်ထားပါသည်။"</string>
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_off (650231949881093289) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_on (4218725402373934151) -->
+    <skip />
     <string name="accessibility_brightness" msgid="8003681285547803095">"တောက်ပမှုကို ပြရန်"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"2G-3G ဒေတာ ခေတ္တရပ်တန့်သည်"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"4G data ခေတ္တရပ်တန့်သည်"</string>
@@ -304,6 +310,8 @@
     <string name="recents_launch_disabled_message" msgid="1624523193008871793">"<xliff:g id="APP">%s</xliff:g> ကို ဘေးကင်းလုံခြုံသည့်မုဒ်တွင် ပိတ်ထားပါသည်။"</string>
     <string name="recents_history_button_label" msgid="5153358867807604821">"မှတ်တမ်း"</string>
     <string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"ရှင်းလင်းပါ"</string>
+    <string name="recents_drag_non_dockable_task_message" msgid="2935843902795166158">"ဤအက်ပ်သည် ဝင်းဒိုးများစွာဖွင့်ခြင်းကို ပံ့ပိုးမထားပါ"</string>
+    <string name="recents_launch_non_dockable_task_label" msgid="7862379814938391888">"အက်ပ်သည် ဝင်းဒိုးများစွာဖွင့်ခြင်းကို ပံ့ပိုးမထားပါ"</string>
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"ရေပြင်ညီ ပိုင်းမည်"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"ဒေါင်လိုက်ပိုင်းမည်"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"စိတ်ကြိုက် ပိုင်းမည်"</string>
@@ -451,18 +459,23 @@
     <string name="enable_bluetooth_title" msgid="5027037706500635269">"ဘလူးတုသ် ဖွင့်ရမလား။"</string>
     <string name="enable_bluetooth_message" msgid="9106595990708985385">"ကီးဘုတ်ကို တပ်ဘလက်နှင့် ချိတ်ဆက်ရန်၊ ပမထဦးစွာ ဘလူးတုသ်ကို ဖွင့်ပါ။"</string>
     <string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"ဖွင့်ပါ"</string>
-    <string name="apply_to_topic" msgid="3641403489318659666">"သတိပေးချက် <xliff:g id="TOPIC_NAME">%1$s</xliff:g> ခုသို့သက်ရောက်စေပါ"</string>
-    <string name="apply_to_app" msgid="363016783939815960">"ဤအက်ပ်မှ သတိပေးချက်များအားလုံးသို့ သက်ရောက်စေပါ"</string>
+    <string name="show_silently" msgid="6841966539811264192">"သတိပေးချက်များကို တိတ်ဆိတ်စွာပြပါ"</string>
+    <string name="block" msgid="2734508760962682611">"သတိပေးချက်များအားလုံးကို ပိတ်ဆို့ပါ"</string>
+    <string name="do_not_silence" msgid="6878060322594892441">"အသံ မတိတ်ပါနှင့်"</string>
+    <string name="do_not_silence_block" msgid="4070647971382232311">"အသံ မတိတ်ပါနှင့် သို့မဟုတ် မပိတ်ဆို့ပါနှင့်"</string>
+    <string name="tuner_full_importance_settings" msgid="8103289238676424226">"အပြည့်အဝအရေးပါသည့် ဆက်တင်များကိုပြပါ"</string>
     <string name="blocked_importance" msgid="5198578988978234161">"ပိတ်ဆို့ထားသည်"</string>
+    <string name="min_importance" msgid="1901894910809414782">"အနည်းဆုံး အရေးပါမှု"</string>
     <string name="low_importance" msgid="4109929986107147930">"အနည်းငယ်သာ အရေးပါသည်"</string>
     <string name="default_importance" msgid="8192107689995742653">"သာမန်သာ အရေးပါသည်"</string>
     <string name="high_importance" msgid="1527066195614050263">"အလွန်အရေးပါသည်"</string>
     <string name="max_importance" msgid="5089005872719563894">"အရေးတကြီး အရေးပါသည်"</string>
     <string name="notification_importance_blocked" msgid="2397192642657872872">"ဤသတိပေးချက်များကို ဘယ်တော့မှမပြပါနှင့်"</string>
-    <string name="notification_importance_low" msgid="4383563267370859725">"သတိပေးချက်စာရင်း၏ အောက်ဆုံးတွင် တိတ်တဆိတ်ပြပါ"</string>
-    <string name="notification_importance_default" msgid="4926529615920610817">"ဤသတိပေးချက်များကို တိတ်တဆိတ်ပြပါ"</string>
-    <string name="notification_importance_high" msgid="3222680136612408223">"သတိပေးချက်စာရင်းများ၏ ထိပ်တွင်ပြကာ အသံဖွင့်ပါ"</string>
-    <string name="notification_importance_max" msgid="5236987171904756134">"မျက်နှာပြင်ပေါ်သို့ ဖော်ပြကာ အသံဖွင့်ပါ"</string>
+    <string name="notification_importance_min" msgid="1938190340516905748">"သတိပေးချက်စာရင်း၏ အောက်ဆုံးတွင် တိတ်ဆိတ်စွာပြပါ"</string>
+    <string name="notification_importance_low" msgid="3657252049508213048">"ဤသတိပေးချက်များကို တိတ်ဆိတ်စွာပြပါ"</string>
+    <string name="notification_importance_default" msgid="4466466472622442175">"ဤသတိပေးချက်များကို အသံထွက်ခွင့်ပြုပါ"</string>
+    <string name="notification_importance_high" msgid="2135428926525093825">"ဖန်သားပြင်ပေါ်တွင် ပေါ်စေပြီး အသံထွက်ခွင့်ပြုပါ"</string>
+    <string name="notification_importance_max" msgid="5806278962376556491">"သတိပေးချက်စာရင်း၏ ထိပ်ဆုံးတွင်ပြပြီး ဖန်သားပြင်ပေါ်တွင် ပေါ်စေကာ အသံထွက်ခွင့်ပြုပါ"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"နောက်ထပ် ဆက်တင်များ"</string>
     <string name="notification_done" msgid="5279426047273930175">"ပြီးပါပြီ"</string>
     <string name="color_and_appearance" msgid="1254323855964993144">"အရောင်နှင့် အပြင်အဆင်"</string>
@@ -476,7 +489,7 @@
     <string name="use_dark_theme" msgid="2900938704964299312">"Android OS အတွက်အရောင်ရင့်အပြင်အဆင်ကို သုံးပါ"</string>
     <string name="adjust_tint" msgid="3398569573231409878">"အရောင်မွဲမှုကို ချိန်ပါ"</string>
     <string name="adjust_brightness" msgid="980039329808178246">"အလင်းအမှောင်ချိန်ပါ"</string>
-    <string name="night_mode_disclaimer" msgid="3297928749219711334">"အရောင်ရင့်အပြင်အဆင်သည် ဆက်တင်များနှင့် သတိပေးချက်များကဲ့သို့ ပုံမှန်အားဖြင့် အရောင်ဖျော့အပြင်အဆင်အဖြစ်ရှိသည့် Android OS ၏အဓိကနေရာများကို ပြောင်းလဲပေးပါသည်။"</string>
+    <string name="night_mode_disclaimer" msgid="598914896926759578">"အရောင်ရင့်အပြင်အဆင်သည် ဆက်တင်များကဲ့သို့ ပုံမှန်အားဖြင့် အရောင်ဖျော့အပြင်အဆင်အဖြစ်ရှိသည့် Android OS ၏အဓိကနေရာများကို ပြောင်းလဲပေးပါသည်။"</string>
     <string name="color_apply" msgid="9212602012641034283">"အသုံးပြုပါ"</string>
     <string name="color_revert_title" msgid="4746666545480534663">"ဆက်တင်များကို အတည်ပြုပါ"</string>
     <string name="color_revert_message" msgid="9116001069397996691">"အချို့သော အရောင်ဆက်တက်များက ဤကိရိယာကို သုံးမရအောင် လုပ်ပစ်နိုင်ပါသည်။ ဤအရောင် ဆက်တင်များကို အတည်ပြုရန် အိုကေကို နှိပ်ပါ၊ သို့မဟုတ် ဤဆက်တင်များကို ၁၀ စက္ကန့် အကြာတွင် ပြန်ညှိလိုက်ပါမည်။"</string>
@@ -535,4 +548,10 @@
     <item msgid="2139628951880142927">"အားသွင်းနေစဉ်တွင် ရာခိုင်နှုန်းကိုပြပါ (ပုံသေ)"</item>
     <item msgid="3327323682209964956">"ဤသင်္ကေတပုံကို မပြပါနှင့်"</item>
   </string-array>
+    <string name="other" msgid="4060683095962566764">"အခြား"</string>
+    <string name="accessibility_divider" msgid="5903423481953635044">"မျက်နှာပြင်ခွဲခြမ်း ပိုင်းခြားပေးသည့်စနစ်"</string>
+    <string name="accessibility_action_divider_move_down" msgid="704893304141890042">"အောက်သို့ရွှေ့ပါ"</string>
+    <string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"အပေါ်သို့ရွှေ့ပါ"</string>
+    <string name="accessibility_action_divider_move_left" msgid="9218189832115847253">"ဘယ်ဘက်သို့ရွှေ့ပါ"</string>
+    <string name="accessibility_action_divider_move_right" msgid="4671522715182567972">"ညာဘက်သို့ရွှေ့ပါ"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-my-rMM/strings_tv.xml b/packages/SystemUI/res/values-my-rMM/strings_tv.xml
new file mode 100644
index 0000000..ebadebe
--- /dev/null
+++ b/packages/SystemUI/res/values-my-rMM/strings_tv.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.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="pip_close" msgid="3480680679023423574">"PIP ကိုပိတ်ပါ"</string>
+    <string name="pip_fullscreen" msgid="8604643018538487816">"မျက်နှာပြင် အပြည့်"</string>
+    <string name="pip_play" msgid="674145557658227044">"ဖွင့်ပါ"</string>
+    <string name="pip_pause" msgid="8412075640017218862">"ဆိုင်းငံ့ပါ"</string>
+    <string name="pip_hold_home" msgid="340086535668778109">"PIP ကိုထိန်းချုပ်ရန် "<b>"ပင်မခလုတ်"</b>" ကိုဖိထားပါ"</string>
+    <string name="pip_onboarding_description" msgid="2627737116380318292">"PIP ကိုထိန်းချုပ်ရန် ပင်မခလုတ်\nကိုနှိပ်ပြီးဖိထားပါ"</string>
+    <string name="pip_onboarding_button" msgid="3957426748484904611">"ရပါပြီ"</string>
+</resources>
diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml
index 3a603c2..269746e 100644
--- a/packages/SystemUI/res/values-nb/strings.xml
+++ b/packages/SystemUI/res/values-nb/strings.xml
@@ -73,7 +73,8 @@
     <string name="screenshot_saved_title" msgid="6461865960961414961">"Skjermdumpen er lagret."</string>
     <string name="screenshot_saved_text" msgid="1152839647677558815">"Trykk for å se skjermdumpen."</string>
     <string name="screenshot_failed_title" msgid="705781116746922771">"Kan ikke lagre skjermdumpen."</string>
-    <string name="screenshot_failed_text" msgid="1260203058661337274">"Kan ikke ta skjermdump grunnet plassbegrensning, app- eller organisasjonstillatelser."</string>
+    <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Kan ikke lagre skjermdumpen på grunn av begrenset lagringsplass."</string>
+    <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Appen eller organisasjonen din tillater ikke at du tar skjermdumper."</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"Altern. for USB-filoverføring"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Sett inn som mediespiller (MTP)"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"Sett inn som kamera (PTP)"</string>
@@ -206,6 +207,7 @@
     <string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"Mer tid."</string>
     <string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"Mindre tid."</string>
     <string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"Lommelykten er av."</string>
+    <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"Lommelykt er ikke tilgjengelig."</string>
     <string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"Lommelykten er på."</string>
     <string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"Lommelykten er slått av."</string>
     <string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"Lommelykten er slått på."</string>
@@ -218,6 +220,10 @@
     <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"Arbeidsmodusen er på."</string>
     <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"Arbeidsmodusen er slått av."</string>
     <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"Arbeidsmodusen er slått på."</string>
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_off (650231949881093289) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_on (4218725402373934151) -->
+    <skip />
     <string name="accessibility_brightness" msgid="8003681285547803095">"Lysstyrken på skjermen"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"2G- og 3G-data er satt på pause"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"4G-data er satt på pause"</string>
@@ -304,6 +310,8 @@
     <string name="recents_launch_disabled_message" msgid="1624523193008871793">"<xliff:g id="APP">%s</xliff:g> er slått av i sikker modus."</string>
     <string name="recents_history_button_label" msgid="5153358867807604821">"Logg"</string>
     <string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"Tøm"</string>
+    <string name="recents_drag_non_dockable_task_message" msgid="2935843902795166158">"Denne appen har ikke støtte for flervindusmodus"</string>
+    <string name="recents_launch_non_dockable_task_label" msgid="7862379814938391888">"Appen har ikke støtte for flervindusmodus"</string>
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Del horisontalt"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Del vertikalt"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Del tilpasset"</string>
@@ -451,18 +459,23 @@
     <string name="enable_bluetooth_title" msgid="5027037706500635269">"Vil du slå på Bluetooth?"</string>
     <string name="enable_bluetooth_message" msgid="9106595990708985385">"For å koble tastaturet til nettbrettet ditt må du først slå på Bluetooth."</string>
     <string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"Slå på"</string>
-    <string name="apply_to_topic" msgid="3641403489318659666">"Bruk for varsler for <xliff:g id="TOPIC_NAME">%1$s</xliff:g>"</string>
-    <string name="apply_to_app" msgid="363016783939815960">"Bruk for alle varslene fra denne appen"</string>
+    <string name="show_silently" msgid="6841966539811264192">"Vis varsler uten lyd"</string>
+    <string name="block" msgid="2734508760962682611">"Blokkér alle varsler"</string>
+    <string name="do_not_silence" msgid="6878060322594892441">"Ikke slå av lyden"</string>
+    <string name="do_not_silence_block" msgid="4070647971382232311">"Ikke slå av lyden eller blokkér anrop"</string>
+    <string name="tuner_full_importance_settings" msgid="8103289238676424226">"Vis alle viktighetsinnstillingene"</string>
     <string name="blocked_importance" msgid="5198578988978234161">"Blokkert"</string>
+    <string name="min_importance" msgid="1901894910809414782">"Laveste prioritet"</string>
     <string name="low_importance" msgid="4109929986107147930">"Lav viktighet"</string>
     <string name="default_importance" msgid="8192107689995742653">"Vanlig viktighet"</string>
     <string name="high_importance" msgid="1527066195614050263">"Høy viktighet"</string>
     <string name="max_importance" msgid="5089005872719563894">"Svært høy viktighet"</string>
     <string name="notification_importance_blocked" msgid="2397192642657872872">"Aldri vis disse varslene"</string>
-    <string name="notification_importance_low" msgid="4383563267370859725">"Vis nederst på varsellisten uten lyd"</string>
-    <string name="notification_importance_default" msgid="4926529615920610817">"Vis disse varslene uten lyd"</string>
-    <string name="notification_importance_high" msgid="3222680136612408223">"Vis øverst på varsellisten med lyd"</string>
-    <string name="notification_importance_max" msgid="5236987171904756134">"Vis fort på skjermen med lyd"</string>
+    <string name="notification_importance_min" msgid="1938190340516905748">"Vis nederst på varsellisten uten lyd"</string>
+    <string name="notification_importance_low" msgid="3657252049508213048">"Vis disse varslene uten lyd"</string>
+    <string name="notification_importance_default" msgid="4466466472622442175">"Tillat at disse varslene vises med lyd"</string>
+    <string name="notification_importance_high" msgid="2135428926525093825">"Vis fort på skjermen og tillat lyd"</string>
+    <string name="notification_importance_max" msgid="5806278962376556491">"Vis øverst på varsellisten, vis fort på skjermen og tillat lyd"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"Flere innstillinger"</string>
     <string name="notification_done" msgid="5279426047273930175">"Ferdig"</string>
     <string name="color_and_appearance" msgid="1254323855964993144">"Farge og utseende"</string>
@@ -476,7 +489,7 @@
     <string name="use_dark_theme" msgid="2900938704964299312">"Bruk et mørkt tema for Android OS"</string>
     <string name="adjust_tint" msgid="3398569573231409878">"Juster fargen"</string>
     <string name="adjust_brightness" msgid="980039329808178246">"Juster lysstyrken"</string>
-    <string name="night_mode_disclaimer" msgid="3297928749219711334">"Det mørke temaet brukes på kjerneområdene i Android OS som vanligvis vises i et lyst tema, for eksempel Innstillinger og varsler."</string>
+    <string name="night_mode_disclaimer" msgid="598914896926759578">"Det mørke temaet brukes på kjerneområdene i Android OS som vanligvis vises i et lyst tema, for eksempel Innstillinger."</string>
     <string name="color_apply" msgid="9212602012641034283">"Bruk"</string>
     <string name="color_revert_title" msgid="4746666545480534663">"Bekreft innstillingene"</string>
     <string name="color_revert_message" msgid="9116001069397996691">"Noen fargeinnstillinger kan gjøre denne enheten ubrukelig. Klikk på OK for å bekrefte disse fargeinnstillingene, ellers blir de tilbakestilt etter ti sekunder."</string>
@@ -535,4 +548,10 @@
     <item msgid="2139628951880142927">"Vis prosentandel under lading (standard)"</item>
     <item msgid="3327323682209964956">"Ikke vis dette ikonet"</item>
   </string-array>
+    <string name="other" msgid="4060683095962566764">"Annet"</string>
+    <string name="accessibility_divider" msgid="5903423481953635044">"Skilleelement for delt skjerm"</string>
+    <string name="accessibility_action_divider_move_down" msgid="704893304141890042">"Flytt ned"</string>
+    <string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"Flytt opp"</string>
+    <string name="accessibility_action_divider_move_left" msgid="9218189832115847253">"Flytt mot venstre"</string>
+    <string name="accessibility_action_divider_move_right" msgid="4671522715182567972">"Flytt mot høyre"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-nb/strings_tv.xml b/packages/SystemUI/res/values-nb/strings_tv.xml
new file mode 100644
index 0000000..8574d66
--- /dev/null
+++ b/packages/SystemUI/res/values-nb/strings_tv.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.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="pip_close" msgid="3480680679023423574">"Lukk PIP"</string>
+    <string name="pip_fullscreen" msgid="8604643018538487816">"Fullskjerm"</string>
+    <string name="pip_play" msgid="674145557658227044">"Spill av"</string>
+    <string name="pip_pause" msgid="8412075640017218862">"Sett på pause"</string>
+    <string name="pip_hold_home" msgid="340086535668778109">"Hold inne "<b>"STARTSIDE"</b>" for å kontrollere PIP"</string>
+    <string name="pip_onboarding_description" msgid="2627737116380318292">"Trykk og hold STARTSIDE-\nknappen for å kontrollere PIP"</string>
+    <string name="pip_onboarding_button" msgid="3957426748484904611">"Greit"</string>
+</resources>
diff --git a/packages/SystemUI/res/values-ne-rNP/strings.xml b/packages/SystemUI/res/values-ne-rNP/strings.xml
index e2588da..882a194 100644
--- a/packages/SystemUI/res/values-ne-rNP/strings.xml
+++ b/packages/SystemUI/res/values-ne-rNP/strings.xml
@@ -73,7 +73,8 @@
     <string name="screenshot_saved_title" msgid="6461865960961414961">"स्क्रिनसट क्याप्चर गरियो।"</string>
     <string name="screenshot_saved_text" msgid="1152839647677558815">"तपाईँको स्क्रिनसट हेर्न छुनुहोस्।"</string>
     <string name="screenshot_failed_title" msgid="705781116746922771">"स्क्रिनसट क्याप्चर गर्न सकिएन।"</string>
-    <string name="screenshot_failed_text" msgid="1260203058661337274">"सीमित भण्डारण ठाउँको कारणले स्क्रिनसट लिन सकिएन, वा यो अनुप्रयोग वा आफ्नो संगठन द्वारा अनुमति छैन।"</string>
+    <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"सीमित भण्डारण स्थान उपलब्ध रहेको हुनाले स्क्रिनसटलाई सुरक्षित गर्न सकिँदैन।"</string>
+    <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"अनुप्रयोग वा तपाईँको संगठनले स्क्रिनसट लिन अनुमति दॅिंदैन।"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"USB फाइल सार्ने विकल्पहरू"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"मिडिया प्लेयर(MTP)को रूपमा माउन्ट गर्नुहोस्"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"क्यामेराको रूपमा माउन्ट गर्नुहोस् (PTP)"</string>
@@ -206,6 +207,7 @@
     <string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"थप समय।"</string>
     <string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"कम समय।"</string>
     <string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"टर्च बन्द छ।"</string>
+    <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"फ्ल्यासलाइट उपलब्ध छैन।"</string>
     <string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"टर्च खुला छ।"</string>
     <string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"टर्च बन्द गरियो।"</string>
     <string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"टर्च खुला गरियो।"</string>
@@ -218,6 +220,10 @@
     <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"कार्य मोड अन।"</string>
     <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"कार्य मोड बन्द भयो।"</string>
     <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"कार्य मोड सक्रिय भयो।"</string>
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_off (650231949881093289) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_on (4218725402373934151) -->
+    <skip />
     <string name="accessibility_brightness" msgid="8003681285547803095">"प्रदर्शन चमक"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"2G-3G डेटा रोकिएको छ"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"4G डेटा रोकिएको छ"</string>
@@ -301,10 +307,11 @@
     <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"स्क्रिन पिन गर्दै"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"खोजी गर्नुहोस्"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"सुरु गर्न सकिएन <xliff:g id="APP">%s</xliff:g>।"</string>
-    <!-- no translation found for recents_launch_disabled_message (1624523193008871793) -->
-    <skip />
+    <string name="recents_launch_disabled_message" msgid="1624523193008871793">"<xliff:g id="APP">%s</xliff:g> लाई सुरक्षित-मोडमा असक्षम गरिएको छ।"</string>
     <string name="recents_history_button_label" msgid="5153358867807604821">"इतिहास"</string>
     <string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"मेटाउनुहोस्"</string>
+    <string name="recents_drag_non_dockable_task_message" msgid="2935843902795166158">"यस अनुप्रयोगले बहु-विन्डोलाई समर्थन गर्दैन"</string>
+    <string name="recents_launch_non_dockable_task_label" msgid="7862379814938391888">"अनुप्रयोगले बहु-विन्डोलाई समर्थन गर्दैन"</string>
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"तेर्सो रूपमा विभाजन गर्नुहोस्"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"ठाडो रूपमा विभाजन गर्नुहोस्"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"अनुकूलन विभाजन गर्नुहोस्"</string>
@@ -452,32 +459,37 @@
     <string name="enable_bluetooth_title" msgid="5027037706500635269">"ब्लुटुथ सक्रिय पार्ने हो?"</string>
     <string name="enable_bluetooth_message" msgid="9106595990708985385">"आफ्नो ट्याब्लेटसँग किबोर्ड जोड्न, पहिले तपाईँले ब्लुटुथ सक्रिय गर्नुपर्छ।"</string>
     <string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"सक्रिय पार्नुहोस्"</string>
-    <string name="apply_to_topic" msgid="3641403489318659666">"<xliff:g id="TOPIC_NAME">%1$s</xliff:g> सूचनाहरूमा लागू गर्नुहोस्"</string>
-    <string name="apply_to_app" msgid="363016783939815960">"यो अनुप्रयोगका सबै सूचनाहरूमा लागू गर्नुहोस्"</string>
+    <string name="show_silently" msgid="6841966539811264192">"सूचनाहरूलाई बिना आवाज देखाउने"</string>
+    <string name="block" msgid="2734508760962682611">"सबै सूचनाहरूलाई रोक्नुहोस्"</string>
+    <string name="do_not_silence" msgid="6878060322594892441">"मौन नगर्नुहोस्"</string>
+    <string name="do_not_silence_block" msgid="4070647971382232311">"मौन नगर्नुहोस् वा नरोक्नुहोस्"</string>
+    <string name="tuner_full_importance_settings" msgid="8103289238676424226">"पूर्ण महत्त्व सेटिङहरू देखाउने"</string>
     <string name="blocked_importance" msgid="5198578988978234161">"रोकियो"</string>
+    <string name="min_importance" msgid="1901894910809414782">"न्यूनतम महत्त्व"</string>
     <string name="low_importance" msgid="4109929986107147930">"न्यून महत्त्व"</string>
     <string name="default_importance" msgid="8192107689995742653">"सामान्य महत्त्व"</string>
     <string name="high_importance" msgid="1527066195614050263">"उच्च महत्त्व"</string>
     <string name="max_importance" msgid="5089005872719563894">"जरूरी महत्त्व"</string>
     <string name="notification_importance_blocked" msgid="2397192642657872872">"यी सूचनाहरू कहिल्यै नदेखाउनुहोस्"</string>
-    <string name="notification_importance_low" msgid="4383563267370859725">"सूचीको फेदमा बिना आवाज देखाउनुहोस्"</string>
-    <string name="notification_importance_default" msgid="4926529615920610817">"यी सूचनाहरू बिना आवाज देखाउनुहोस्"</string>
-    <string name="notification_importance_high" msgid="3222680136612408223">"सूचना सूचीको शीर्षमा देखाउनुहोस् र आवाज निकाल्नुहोस्"</string>
-    <string name="notification_importance_max" msgid="5236987171904756134">"स्क्रिनमा हेर्नुहोस् र आवाज निकाल्नुहोस्"</string>
+    <string name="notification_importance_min" msgid="1938190340516905748">"सूचना सूचीको फेदमा बिना आवाज देखाउने"</string>
+    <string name="notification_importance_low" msgid="3657252049508213048">"यी सूचनाहरूलाई बिना आवाज देखाउने"</string>
+    <string name="notification_importance_default" msgid="4466466472622442175">"यी सूचनाहरूलाई ध्वनि निकाल्न अनुमति दिने"</string>
+    <string name="notification_importance_high" msgid="2135428926525093825">"स्क्रिनमा चियाउने र ध्वनि निकाल्न अनुमति दिने"</string>
+    <string name="notification_importance_max" msgid="5806278962376556491">"सूचना सूचीको शीर्षमा देखाउने, स्क्रिनमा चियाउने र ध्वनि निकाल्न अनुमति दिने"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"थप सेटिङहरू"</string>
     <string name="notification_done" msgid="5279426047273930175">"सम्पन्‍न भयो"</string>
     <string name="color_and_appearance" msgid="1254323855964993144">"रंग र रूप"</string>
     <string name="night_mode" msgid="3540405868248625488">"रात्री मोड"</string>
-    <string name="calibrate_display" msgid="5974642573432039217">"प्रदर्शन  जाँच्नुहोस्"</string>
-    <string name="night_mode_on" msgid="5597545513026541108">"खोल्नुहोस्"</string>
-    <string name="night_mode_off" msgid="8035605276956057508">"बन्द गर्नुहोस्"</string>
-    <string name="turn_on_automatically" msgid="4167565356762016083">"स्वतः खोल्नुहोस्"</string>
-    <string name="turn_on_auto_summary" msgid="2190994512406701520">"स्थान र दिनको समयको लागि उपयुक्त रूपमा रात्री मोडमा स्विच गर्नुहोस्"</string>
-    <string name="when_night_mode_on" msgid="2969436026899172821">"रात्री मोड खुला भएको समय"</string>
+    <string name="calibrate_display" msgid="5974642573432039217">"प्रदर्शनको स्तर  मिलाउनुहोस्"</string>
+    <string name="night_mode_on" msgid="5597545513026541108">"सक्रिय"</string>
+    <string name="night_mode_off" msgid="8035605276956057508">"निष्क्रिय"</string>
+    <string name="turn_on_automatically" msgid="4167565356762016083">"स्वतः सक्रिय पार्नुहोस्"</string>
+    <string name="turn_on_auto_summary" msgid="2190994512406701520">"स्थान र दिनको समयको लागि उपयुक्त रात्री मोडमा स्विच गर्नुहोस्"</string>
+    <string name="when_night_mode_on" msgid="2969436026899172821">"रात्री मोड सक्रिय हुँदा"</string>
     <string name="use_dark_theme" msgid="2900938704964299312">"Android OS का लागि गाढा रंगको विषयवस्तु प्रयोग गर्नुहोस्"</string>
-    <string name="adjust_tint" msgid="3398569573231409878">"रङ्ग समायोजन गर्नुहोस्"</string>
-    <string name="adjust_brightness" msgid="980039329808178246">"चमक समायोजन गर्नुहोस्"</string>
-    <string name="night_mode_disclaimer" msgid="3297928749219711334">"Android OS कोर क्षेत्रमा गहिरो रंगको विषयवस्तु लागू हुन्छ, जुन सामान्यतया एउटा हल्का रंगको विषयवस्तुमा प्रदर्शन गरिन्छ, जस्तै सेटिङ र सूचनाहरू ।"</string>
+    <string name="adjust_tint" msgid="3398569573231409878">"रङ्गलाई समायोजन गर्नुहोस्"</string>
+    <string name="adjust_brightness" msgid="980039329808178246">"चमकलाई समायोजन गर्नुहोस्"</string>
+    <string name="night_mode_disclaimer" msgid="598914896926759578">"गहिरो रंगको विषयवस्तुलाई Android OS का त्यस्ता मुख्य क्षेत्रहरूमा लागू गरिन्छ जसलाई सामान्यतया हल्का रंगमा देखाइन्छ, जस्तै सेटिङहरू।"</string>
     <string name="color_apply" msgid="9212602012641034283">"लागू गर्नुहोस्"</string>
     <string name="color_revert_title" msgid="4746666545480534663">"सेटिङहरूको पुष्टि गर्नुहोस्"</string>
     <string name="color_revert_message" msgid="9116001069397996691">"केही रङ सेटिङहरूले यस यन्त्रलाई अनुपयोगी बनाउन सक्छन्। यी रङ सेटिङहरू पुष्टि गर्न ठीक छ मा क्लिक गर्नुहोस्, अन्यथा यी सेटिङहरू १० सेकेण्डपछि रिसेट हुनेछन्।"</string>
@@ -489,9 +501,9 @@
     <string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"गृह"</string>
     <string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"हालैका"</string>
     <string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"पछाडि"</string>
-    <string name="tuner_full_zen_title" msgid="4540823317772234308">"भोल्युम नियन्त्रणसंग देखाउनुहोस्"</string>
+    <string name="tuner_full_zen_title" msgid="4540823317772234308">"भोल्युम नियन्त्रणसहित देखाउनुहोस्"</string>
     <string name="volume_and_do_not_disturb" msgid="3373784330208603030">"बाधा नपुर्याउनुहोस्"</string>
-    <string name="volume_dnd_silent" msgid="4363882330723050727">"भोल्युम बटन सर्टकट"</string>
+    <string name="volume_dnd_silent" msgid="4363882330723050727">"भोल्युम बटनका सर्टकट"</string>
     <string name="volume_up_silent" msgid="7141255269783588286">"भोल्युम बढाउनेमा बाधा नपुर्याउनुहोस् प्रविष्ट गर्नुहोस्"</string>
     <string name="battery" msgid="7498329822413202973">"ब्याट्री"</string>
     <string name="clock" msgid="7416090374234785905">"घडी"</string>
@@ -502,7 +514,7 @@
     <string name="accessibility_data_saver_on" msgid="8454111686783887148">"डेटा सेभर अन छ"</string>
     <string name="accessibility_data_saver_off" msgid="8841582529453005337">"डेटा सेभर बन्द छ"</string>
     <string name="switch_bar_on" msgid="1142437840752794229">"सक्रिय गर्नुहोस्"</string>
-    <string name="switch_bar_off" msgid="8803270596930432874">"बन्द गर्नुहोस्"</string>
+    <string name="switch_bar_off" msgid="8803270596930432874">"निष्क्रिय"</string>
     <string name="nav_bar" msgid="1993221402773877607">"नेभिगेशन पट्टी"</string>
     <string name="start" msgid="6873794757232879664">"सुरु गर्नुहोस्"</string>
     <string name="center" msgid="4327473927066010960">"केन्द्र"</string>
@@ -536,4 +548,10 @@
     <item msgid="2139628951880142927">"चार्ज गर्दा प्रतिशत देखाउनुहोस् (पूर्वनिर्धारित)"</item>
     <item msgid="3327323682209964956">"यो आइकन नदेखाउनुहोस्"</item>
   </string-array>
+    <string name="other" msgid="4060683095962566764">"अन्य"</string>
+    <string name="accessibility_divider" msgid="5903423481953635044">"विभाजित-स्क्रिन छुट्याउने"</string>
+    <string name="accessibility_action_divider_move_down" msgid="704893304141890042">"तल सार्नुहोस्"</string>
+    <string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"माथि सार्नुहोस्"</string>
+    <string name="accessibility_action_divider_move_left" msgid="9218189832115847253">"बाँया सार्नुहोस्"</string>
+    <string name="accessibility_action_divider_move_right" msgid="4671522715182567972">"दायाँ सार्नुहोस्"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ne-rNP/strings_tv.xml b/packages/SystemUI/res/values-ne-rNP/strings_tv.xml
new file mode 100644
index 0000000..68c86ca
--- /dev/null
+++ b/packages/SystemUI/res/values-ne-rNP/strings_tv.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.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="pip_close" msgid="3480680679023423574">"PIP लाई बन्द गर्नुहोस्"</string>
+    <string name="pip_fullscreen" msgid="8604643018538487816">"पूर्ण स्क्रिन"</string>
+    <string name="pip_play" msgid="674145557658227044">"प्ले गर्नुहोस्"</string>
+    <string name="pip_pause" msgid="8412075640017218862">"रोक्नुहोस्"</string>
+    <string name="pip_hold_home" msgid="340086535668778109">"PIP लाई नियन्त्रण गर्न "<b>"गृह"</b>" कुञ्जीलाई थिचिरहनुहोस्"</string>
+    <string name="pip_onboarding_description" msgid="2627737116380318292">"PIP लाई नियन्त्रण गर्न गृह\nबटनलाई थिचेर होल्ड गर्नुहोस्"</string>
+    <string name="pip_onboarding_button" msgid="3957426748484904611">"बुझेँ"</string>
+</resources>
diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml
index cf6c5bf..99acbaa 100644
--- a/packages/SystemUI/res/values-nl/strings.xml
+++ b/packages/SystemUI/res/values-nl/strings.xml
@@ -73,7 +73,8 @@
     <string name="screenshot_saved_title" msgid="6461865960961414961">"Screenshot gemaakt."</string>
     <string name="screenshot_saved_text" msgid="1152839647677558815">"Raak aan om je screenshot te bekijken."</string>
     <string name="screenshot_failed_title" msgid="705781116746922771">"Screenshot is niet gemaakt."</string>
-    <string name="screenshot_failed_text" msgid="1260203058661337274">"Kan geen screenshot maken wegens beperkte opslagruimte of omdat de app of je organisatie dit niet toestaat."</string>
+    <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Kan screenshot niet opslaan vanwege beperkte opslagruimte."</string>
+    <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Het maken van screenshots wordt niet toegestaan door de app of je organisatie."</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"Opties voor USB-bestandsoverdracht"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Koppelen als mediaspeler (MTP)"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"Koppelen als camera (PTP)"</string>
@@ -206,6 +207,7 @@
     <string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"Meer tijd."</string>
     <string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"Minder tijd."</string>
     <string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"Zaklamp uit."</string>
+    <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"Zaklamp niet beschikbaar."</string>
     <string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"Zaklamp aan."</string>
     <string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"Zaklamp uitgeschakeld."</string>
     <string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"Zaklamp ingeschakeld."</string>
@@ -218,6 +220,10 @@
     <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"Werkmodus aan."</string>
     <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"Werkmodus uitgeschakeld."</string>
     <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"Werkmodus ingeschakeld."</string>
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_off (650231949881093289) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_on (4218725402373934151) -->
+    <skip />
     <string name="accessibility_brightness" msgid="8003681285547803095">"Helderheid van het scherm"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"2G/3G-data zijn onderbroken"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"4G-data zijn onderbroken"</string>
@@ -304,6 +310,8 @@
     <string name="recents_launch_disabled_message" msgid="1624523193008871793">"<xliff:g id="APP">%s</xliff:g> is uitgeschakeld in de veilige modus"</string>
     <string name="recents_history_button_label" msgid="5153358867807604821">"Geschiedenis"</string>
     <string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"Wissen"</string>
+    <string name="recents_drag_non_dockable_task_message" msgid="2935843902795166158">"Deze app ondersteunt de modus voor meerdere vensters niet"</string>
+    <string name="recents_launch_non_dockable_task_label" msgid="7862379814938391888">"App ondersteunt meerdere vensters niet"</string>
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Horizontaal splitsen"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Verticaal splitsen"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Aangepast splitsen"</string>
@@ -451,18 +459,23 @@
     <string name="enable_bluetooth_title" msgid="5027037706500635269">"Bluetooth inschakelen?"</string>
     <string name="enable_bluetooth_message" msgid="9106595990708985385">"Als je je toetsenbord wilt verbinden met je tablet, moet je eerst Bluetooth inschakelen."</string>
     <string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"Inschakelen"</string>
-    <string name="apply_to_topic" msgid="3641403489318659666">"Toepassen op meldingen voor <xliff:g id="TOPIC_NAME">%1$s</xliff:g>"</string>
-    <string name="apply_to_app" msgid="363016783939815960">"Toepassen op alle meldingen van deze app"</string>
+    <string name="show_silently" msgid="6841966539811264192">"Meldingen zonder geluid weergeven"</string>
+    <string name="block" msgid="2734508760962682611">"Alle meldingen blokkeren"</string>
+    <string name="do_not_silence" msgid="6878060322594892441">"Niet zonder geluid weergeven"</string>
+    <string name="do_not_silence_block" msgid="4070647971382232311">"Niet zonder geluid weergeven of blokkeren"</string>
+    <string name="tuner_full_importance_settings" msgid="8103289238676424226">"Volledige instellingen voor belang weergeven"</string>
     <string name="blocked_importance" msgid="5198578988978234161">"Geblokkeerd"</string>
+    <string name="min_importance" msgid="1901894910809414782">"Minimaal belang"</string>
     <string name="low_importance" msgid="4109929986107147930">"Klein belang"</string>
     <string name="default_importance" msgid="8192107689995742653">"Normaal belang"</string>
     <string name="high_importance" msgid="1527066195614050263">"Groot belang"</string>
     <string name="max_importance" msgid="5089005872719563894">"Urgent belang"</string>
     <string name="notification_importance_blocked" msgid="2397192642657872872">"Deze meldingen nooit weergeven"</string>
-    <string name="notification_importance_low" msgid="4383563267370859725">"Onder aan de lijst met meldingen weergeven zonder geluid"</string>
-    <string name="notification_importance_default" msgid="4926529615920610817">"Deze meldingen zonder geluid weergeven"</string>
-    <string name="notification_importance_high" msgid="3222680136612408223">"Boven aan de lijst met meldingen weergeven en geluid laten horen"</string>
-    <string name="notification_importance_max" msgid="5236987171904756134">"Op het scherm weergeven en geluid laten horen"</string>
+    <string name="notification_importance_min" msgid="1938190340516905748">"Onder aan de lijst met meldingen weergeven zonder geluid"</string>
+    <string name="notification_importance_low" msgid="3657252049508213048">"Deze meldingen zonder geluid weergeven"</string>
+    <string name="notification_importance_default" msgid="4466466472622442175">"Toestaan dat deze meldingen geluid laten horen"</string>
+    <string name="notification_importance_high" msgid="2135428926525093825">"Op het scherm weergeven en geluid toestaan"</string>
+    <string name="notification_importance_max" msgid="5806278962376556491">"Boven aan de lijst met meldingen weergeven, op het scherm weergeven en geluid toestaan"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"Meer instellingen"</string>
     <string name="notification_done" msgid="5279426047273930175">"Gereed"</string>
     <string name="color_and_appearance" msgid="1254323855964993144">"Kleur en uiterlijk"</string>
@@ -476,7 +489,7 @@
     <string name="use_dark_theme" msgid="2900938704964299312">"Donker thema gebruiken voor Android OS"</string>
     <string name="adjust_tint" msgid="3398569573231409878">"Tint aanpassen"</string>
     <string name="adjust_brightness" msgid="980039329808178246">"Helderheid aanpassen"</string>
-    <string name="night_mode_disclaimer" msgid="3297928749219711334">"Het donkere thema wordt toegepast op kerngedeelten van Android OS die normaal gesproken worden weergegeven met een licht thema, zoals Instellingen en meldingen."</string>
+    <string name="night_mode_disclaimer" msgid="598914896926759578">"Het donkere thema wordt toegepast op kerngedeelten van het Android-besturingssysteem die normaal gesproken worden weergegeven met een licht thema, zoals Instellingen."</string>
     <string name="color_apply" msgid="9212602012641034283">"Toepassen"</string>
     <string name="color_revert_title" msgid="4746666545480534663">"Instellingen bevestigen"</string>
     <string name="color_revert_message" msgid="9116001069397996691">"Bij sommige kleurinstellingen kan het apparaat onbruikbaar worden. Klik op OK om deze kleurinstellingen te bevestigen, anders worden deze instellingen na tien seconden gereset."</string>
@@ -535,4 +548,10 @@
     <item msgid="2139628951880142927">"Percentage weergeven tijdens opladen (standaard)"</item>
     <item msgid="3327323682209964956">"Dit pictogram niet weergeven"</item>
   </string-array>
+    <string name="other" msgid="4060683095962566764">"Overig"</string>
+    <string name="accessibility_divider" msgid="5903423481953635044">"Scheiding voor gesplitst scherm"</string>
+    <string name="accessibility_action_divider_move_down" msgid="704893304141890042">"Omlaag"</string>
+    <string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"Omhoog"</string>
+    <string name="accessibility_action_divider_move_left" msgid="9218189832115847253">"Naar links"</string>
+    <string name="accessibility_action_divider_move_right" msgid="4671522715182567972">"Naar rechts"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-nl/strings_tv.xml b/packages/SystemUI/res/values-nl/strings_tv.xml
new file mode 100644
index 0000000..c116f81
--- /dev/null
+++ b/packages/SystemUI/res/values-nl/strings_tv.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.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="pip_close" msgid="3480680679023423574">"PIP sluiten"</string>
+    <string name="pip_fullscreen" msgid="8604643018538487816">"Volledig scherm"</string>
+    <string name="pip_play" msgid="674145557658227044">"Afspelen"</string>
+    <string name="pip_pause" msgid="8412075640017218862">"Onderbreken"</string>
+    <string name="pip_hold_home" msgid="340086535668778109">"Bedien PIP met "<b>"HOME"</b></string>
+    <string name="pip_onboarding_description" msgid="2627737116380318292">"Houd HOME ingedrukt\nom PIP te bedienen"</string>
+    <string name="pip_onboarding_button" msgid="3957426748484904611">"OK"</string>
+</resources>
diff --git a/packages/SystemUI/res/values-pa-rIN/strings.xml b/packages/SystemUI/res/values-pa-rIN/strings.xml
index 8c7028d..2de6583 100644
--- a/packages/SystemUI/res/values-pa-rIN/strings.xml
+++ b/packages/SystemUI/res/values-pa-rIN/strings.xml
@@ -73,7 +73,8 @@
     <string name="screenshot_saved_title" msgid="6461865960961414961">"ਸਕ੍ਰੀਨਸ਼ੌਟ ਕੈਪਚਰ ਕੀਤਾ।"</string>
     <string name="screenshot_saved_text" msgid="1152839647677558815">"ਆਪਣਾ ਸਕ੍ਰੀਨਸ਼ੌਟ ਦੇਖਣ ਲਈ ਛੋਹਵੋ।"</string>
     <string name="screenshot_failed_title" msgid="705781116746922771">"ਸਕ੍ਰੀਨਸ਼ੌਟ ਕੈਪਚਰ ਨਹੀਂ ਕਰ ਸਕਿਆ।"</string>
-    <string name="screenshot_failed_text" msgid="1260203058661337274">"ਸੀਮਿਤ ਸਟੋਰੇਜ ਸਪੇਸ ਦੇ ਕਾਰਨ ਸਕ੍ਰੀਨਸ਼ੌਟ ਨਹੀਂ ਲੈ ਸਕਦਾ ਜਾਂ ਐਪ ਜਾਂ ਤੁਹਾਡੀ ਕੰਪਨੀ ਵੱਲੋਂ ਇਸਦੀ ਆਗਿਆ ਨਹੀਂ ਹੈ।"</string>
+    <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"ਸੀਮਿਤ ਸਟੋਰੇਜ ਥਾਂ ਦੇ ਕਾਰਨ ਸਕ੍ਰੀਨਸ਼ਾਟ ਰੱਖਿਅਤ ਨਹੀਂ ਕੀਤਾ ਸਕਦਾ।"</string>
+    <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"ਐਪ ਜਾਂ ਤੁਹਾਡੀ ਸੰਸਥਾ ਦੁਆਰਾ ਸਕ੍ਰੀਨਸ਼ਾਟ ਲੈਣ ਦੀ ਮਨਜ਼ੂਰੀ ਨਹੀਂ ਹੈ।"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"USB ਫਾਈਲ ਟ੍ਰਾਂਸਫਰ ਚੋਣਾਂ"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"ਇੱਕ ਮੀਡੀਆ ਪਲੇਅਰ (MTP) ਦੇ ਤੌਰ ਤੇ ਮਾਊਂਟ ਕਰੋ"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"ਇੱਕ ਕੈਮਰੇ (PTP) ਦੇ ਤੌਰ ਤੇ ਮਾਊਂਟ ਕਰੋ"</string>
@@ -206,6 +207,7 @@
     <string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"ਹੋਰ ਸਮਾਂ।"</string>
     <string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"ਘੱਟ ਸਮਾਂ।"</string>
     <string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"ਫਲੈਸ਼ਲਾਈਟ ਬੰਦ।"</string>
+    <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"ਫਲੈਸ਼ਲਾਈਟ ਉਪਲਬਧ ਨਹੀਂ ਹੈ।"</string>
     <string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"ਫਲੈਸ਼ਲਾਈਟ ਚਾਲੂ।"</string>
     <string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"ਫਲੈਸ਼ਲਾਈਟ ਬੰਦ ਕੀਤਾ।"</string>
     <string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"ਫਲੈਸ਼ਲਾਈਟ ਚਾਲੂ ਕੀਤੀ।"</string>
@@ -218,6 +220,10 @@
     <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"ਕੰਮ ਮੋਡ ਚਾਲੂ ਹੈ।"</string>
     <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"ਕੰਮ ਮੋਡ ਬੰਦ ਕੀਤਾ ਗਿਆ।"</string>
     <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"ਕੰਮ ਮੋਡ ਚਾਲੂ ਕੀਤਾ ਗਿਆ।"</string>
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_off (650231949881093289) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_on (4218725402373934151) -->
+    <skip />
     <string name="accessibility_brightness" msgid="8003681285547803095">"ਡਿਸਪਲੇ ਚਮਕ"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"2G-3G ਡਾਟਾ ਰੁਕ ਗਿਆ ਹੈ"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"4G ਡਾਟਾ ਰੁਕ ਗਿਆ ਹੈ"</string>
@@ -304,6 +310,8 @@
     <string name="recents_launch_disabled_message" msgid="1624523193008871793">"<xliff:g id="APP">%s</xliff:g> ਨੂੰ ਸੁਰੱਖਿਅਤ-ਮੋਡ ਵਿੱਚ ਅਯੋਗ ਬਣਾਇਆ ਗਿਆ ਹੈ।"</string>
     <string name="recents_history_button_label" msgid="5153358867807604821">"ਇਤਿਹਾਸ"</string>
     <string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"ਸਾਫ਼ ਕਰੋ"</string>
+    <string name="recents_drag_non_dockable_task_message" msgid="2935843902795166158">"ਇਹ ਐਪ ਮਲਟੀ-ਵਿੰਡੋ ਨੂੰ ਸਮਰਥਨ ਨਹੀਂ ਕਰਦੀ"</string>
+    <string name="recents_launch_non_dockable_task_label" msgid="7862379814938391888">"ਐਪ ਮਲਟੀ-ਵਿੰਡੋ ਨੂੰ ਸਮਰਥਨ ਨਹੀਂ ਕਰਦੀ"</string>
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"ਹੌਰੀਜ਼ੌਂਟਲ ਸਪਲਿਟ"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"ਵਰਟੀਕਲ ਸਪਲਿਟ"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"ਕਸਟਮ ਸਪਲਿਟ"</string>
@@ -451,18 +459,23 @@
     <string name="enable_bluetooth_title" msgid="5027037706500635269">"Bluetooth ਚਾਲੂ ਕਰੋ?"</string>
     <string name="enable_bluetooth_message" msgid="9106595990708985385">"ਆਪਣੇ ਟੈਬਲੇਟ ਨਾਲ ਆਪਣਾ ਕੀ-ਬੋਰਡ ਕਨੈਕਟ ਕਰਨ ਲਈ, ਤੁਹਾਨੂੰ ਪਹਿਲਾਂ Bluetooth ਚਾਲੂ ਕਰਨ ਦੀ ਜ਼ਰੂਰਤ ਹੈ।"</string>
     <string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"ਚਾਲੂ ਕਰੋ"</string>
-    <string name="apply_to_topic" msgid="3641403489318659666">"<xliff:g id="TOPIC_NAME">%1$s</xliff:g> ਸੂਚਨਾਵਾਂ \'ਤੇ ਲਾਗੂ ਕਰੋ"</string>
-    <string name="apply_to_app" msgid="363016783939815960">"ਇਸ ਐਪ ਦੀਆਂ ਸਾਰੀਆਂ ਸੂਚਨਾਵਾਂ \'ਤੇ ਲਾਗੂ ਕਰੋ"</string>
+    <string name="show_silently" msgid="6841966539811264192">"ਸੂਚਨਾਵਾਂ ਚੁੱਪਚਾਪ ਢੰਗ ਨਾਲ ਵਿਖਾਓ"</string>
+    <string name="block" msgid="2734508760962682611">"ਸਾਰੀਆਂ ਸੂਚਨਾਵਾਂ ਨੂੰ ਬਲੌਕ ਕਰੋ"</string>
+    <string name="do_not_silence" msgid="6878060322594892441">"ਚੁੱਪ ਨਾ ਕਰਵਾਓ"</string>
+    <string name="do_not_silence_block" msgid="4070647971382232311">"ਚੁੱਪ ਨਾ ਕਰਵਾਓ ਜਾਂ ਬਲੌਕ ਨਾ ਕਰੋ"</string>
+    <string name="tuner_full_importance_settings" msgid="8103289238676424226">"ਪੂਰੀ ਮਹੱਤਤਾ ਵਾਲੀਆਂ ਸੈਟਿੰਗਾਂ ਨੂੰ ਵਿਖਾਓ"</string>
     <string name="blocked_importance" msgid="5198578988978234161">"ਬਲੌਕ ਕੀਤਾ"</string>
+    <string name="min_importance" msgid="1901894910809414782">"ਨਿਊਨਤਮ ਮਹੱਤਤਾ"</string>
     <string name="low_importance" msgid="4109929986107147930">"ਘੱਟ ਮਹੱਤਤਾ"</string>
     <string name="default_importance" msgid="8192107689995742653">"ਸਧਾਰਨ ਮਹੱਤਤਾ"</string>
     <string name="high_importance" msgid="1527066195614050263">"ਵੱਧ ਮਹੱਤਤਾ"</string>
     <string name="max_importance" msgid="5089005872719563894">"ਜ਼ਰੂਰੀ ਮਹੱਤਤਾ"</string>
     <string name="notification_importance_blocked" msgid="2397192642657872872">"ਇਹਨਾਂ ਸੂਚਨਾਵਾਂ ਨੂੰ ਕਦੇ ਨਾ ਵਿਖਾਓ"</string>
-    <string name="notification_importance_low" msgid="4383563267370859725">"ਸੂਚਨਾ ਸੂਚੀ ਦੇ ਹੇਠਾਂ ਚੁੱਪਚਾਪ ਢੰਗ ਨਾਲ ਵਿਖਾਓ"</string>
-    <string name="notification_importance_default" msgid="4926529615920610817">"ਇਹਨਾਂ ਸੂਚਨਾਵਾਂ ਨੂੰ ਚੁੱਪਚਾਪ ਢੰਗ ਨਾਲ ਵਿਖਾਓ"</string>
-    <string name="notification_importance_high" msgid="3222680136612408223">"ਸੂਚਨਾਵਾਂ ਸੂਚੀ ਦੇ ਸਿਖਰ \'ਤੇ ਵਿਖਾਓ ਅਤੇ ਆਵਾਜ਼ ਕਰੋ"</string>
-    <string name="notification_importance_max" msgid="5236987171904756134">"ਸਕਰੀਨ \'ਤੇ ਝਾਤੀ ਮਾਰੋ ਅਤੇ ਆਵਾਜ਼ ਕਰੋ"</string>
+    <string name="notification_importance_min" msgid="1938190340516905748">"ਸੂਚਨਾ ਸੂਚੀ ਦੇ ਹੇਠਾਂ ਚੁੱਪਚਾਪ ਢੰਗ ਨਾਲ ਵਿਖਾਓ"</string>
+    <string name="notification_importance_low" msgid="3657252049508213048">"ਇਹਨਾਂ ਸੂਚਨਾਵਾਂ ਨੂੰ ਚੁੱਪਚਾਪ ਢੰਗ ਨਾਲ ਵਿਖਾਓ"</string>
+    <string name="notification_importance_default" msgid="4466466472622442175">"ਇਹਨਾਂ ਸੂਚਨਾਵਾਂ ਨੂੰ ਧੁਨੀ ਪੈਦਾ ਕਰਨ ਦੀ ਮਨਜ਼ੂਰੀ ਦਿਓ"</string>
+    <string name="notification_importance_high" msgid="2135428926525093825">"ਸਕ੍ਰੀਨ \'ਤੇ ਝਲਕ ਵਿਖਾਉਣ ਅਤੇ ਧੁਨੀ ਦੀ ਮਨਜ਼ੂਰੀ ਦਿਓ"</string>
+    <string name="notification_importance_max" msgid="5806278962376556491">"ਸੂਚਨਾਵਾਂ ਸੂਚੀ ਦੇ ਸਿਖਰ \'ਤੇ ਵਿਖਾਓ, ਸਕ੍ਰੀਨ \'ਤੇ ਝਲਕ ਵਿਖਾਉਣ ਅਤੇ ਧੁਨੀ ਦੀ ਮਨਜ਼ੂਰੀ ਦਿਓ"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"ਹੋਰ ਸੈਟਿੰਗਾਂ"</string>
     <string name="notification_done" msgid="5279426047273930175">"ਹੋ ਗਿਆ"</string>
     <string name="color_and_appearance" msgid="1254323855964993144">"ਰੰਗ ਅਤੇ ਵਿਖਾਲਾ"</string>
@@ -476,7 +489,7 @@
     <string name="use_dark_theme" msgid="2900938704964299312">"Android OS ਲਈ ਗੂੜ੍ਹੇ ਥੀਮ ਦੀ ਵਰਤੋਂ ਕਰੋ"</string>
     <string name="adjust_tint" msgid="3398569573231409878">"ਟਿੰਟ ਨੂੰ ਵਿਵਸਥਿਤ ਕਰੋ"</string>
     <string name="adjust_brightness" msgid="980039329808178246">"ਚਮਕ ਨੂੰ ਵਿਵਸਥਿਤ ਕਰੋ"</string>
-    <string name="night_mode_disclaimer" msgid="3297928749219711334">"ਗੂੜ੍ਹੇ ਥੀਮ ਨੂੰ Android OS ਦੇ ਉਹਨਾਂ ਮੁੱਖ ਖੇਤਰਾਂ \'ਤੇ ਲਾਗੂ ਕੀਤਾ ਜਾਂਦਾ ਹੈ  ਜੋ ਆਮ ਤੌਰ \'ਤੇ ਇੱਕ ਹਲਕੇ ਥੀਮ ਵਿੱਚ ਵਿਖਾਏ ਜਾਂਦੇ ਹਨ, ਜਿਵੇਂ ਕਿ ਸੈਟਿੰਗਾਂ ਅਤੇ ਸੂਚਨਾਵਾਂ।"</string>
+    <string name="night_mode_disclaimer" msgid="598914896926759578">"ਗੂੜ੍ਹੇ ਥੀਮ ਨੂੰ Android OS ਦੇ ਉਹਨਾਂ ਮੁੱਖ ਖੇਤਰਾਂ \'ਤੇ ਲਾਗੂ ਕੀਤਾ ਜਾਂਦਾ ਹੈ ਜੋ ਆਮ ਤੌਰ \'ਤੇ ਇੱਕ ਹਲਕੇ ਥੀਮ ਵਿੱਚ ਵਿਖਾਏ ਜਾਂਦੇ ਹਨ, ਜਿਵੇਂ ਕਿ ਸੈਟਿੰਗਾਂ।"</string>
     <string name="color_apply" msgid="9212602012641034283">"ਲਾਗੂ ਕਰੋ"</string>
     <string name="color_revert_title" msgid="4746666545480534663">"ਸੈਟਿੰਗਾਂ ਦੀ ਪੁਸ਼ਟੀ ਕਰੋ"</string>
     <string name="color_revert_message" msgid="9116001069397996691">"ਕੁਝ ਰੰਗ ਸੈਟਿੰਗਾਂ ਇਸ ਡੀਵਾਈਸ ਨੂੰ ਬੇਕਾਰ ਕਰ ਸਕਦੀਆਂ ਹਨ। ਇਹਨਾਂ ਰੰਗ ਸੈਟਿੰਗਾਂ ਦੀ ਪੁਸ਼ਟੀ ਕਰਨ ਲਈ ਠੀਕ \'ਤੇ ਕਲਿੱਕ ਕਰੋ, ਨਹੀਂ ਤਾਂ ਇਹ ਸੈਟਿੰਗਾਂ 10 ਸਕਿੰਟ ਬਾਅਦ ਮੁੜ-ਸੈੱਟ ਹੋ ਜਾਣਗੀਆਂ।"</string>
@@ -535,4 +548,10 @@
     <item msgid="2139628951880142927">"ਚਾਰਜਿੰਗ ਦੌਰਾਨ ਪ੍ਰਤੀਸ਼ਤਤਾ ਵਿਖਾਓ (ਪੂਰਵ-ਨਿਰਧਾਰਤ)"</item>
     <item msgid="3327323682209964956">"ਇਸ ਚਿੰਨ੍ਹ ਨੂੰ ਨਾ ਵਿਖਾਓ"</item>
   </string-array>
+    <string name="other" msgid="4060683095962566764">"ਹੋਰ"</string>
+    <string name="accessibility_divider" msgid="5903423481953635044">"ਸਪਲਿਟ-ਸਕ੍ਰੀਨ ਡਿਵਾਈਡਰ"</string>
+    <string name="accessibility_action_divider_move_down" msgid="704893304141890042">"ਹੇਠਾਂ ਲੈ ਜਾਓ"</string>
+    <string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"ਉੱਪਰ ਲੈ ਜਾਓ"</string>
+    <string name="accessibility_action_divider_move_left" msgid="9218189832115847253">"ਖੱਬੇ ਲੈ ਜਾਓ"</string>
+    <string name="accessibility_action_divider_move_right" msgid="4671522715182567972">"ਸੱਜੇ ਲੈ ਜਾਓ"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-pa-rIN/strings_tv.xml b/packages/SystemUI/res/values-pa-rIN/strings_tv.xml
new file mode 100644
index 0000000..1bf28af
--- /dev/null
+++ b/packages/SystemUI/res/values-pa-rIN/strings_tv.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.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="pip_close" msgid="3480680679023423574">"PIP ਬੰਦ ਕਰੋ"</string>
+    <string name="pip_fullscreen" msgid="8604643018538487816">"ਪੂਰੀ ਸਕ੍ਰੀਨ"</string>
+    <string name="pip_play" msgid="674145557658227044">"ਚਲਾਓ"</string>
+    <string name="pip_pause" msgid="8412075640017218862">"ਰੋਕੋ"</string>
+    <string name="pip_hold_home" msgid="340086535668778109">"PIP ਕੰਟਰੋਲ ਕਰਨ ਲਈ "<b>"ਹੋਮ"</b>" ਦਬਾਈ ਰੱਖੋ"</string>
+    <string name="pip_onboarding_description" msgid="2627737116380318292">"PIP ਕੰਟਰੋਲ ਕਰਨ ਲਈ ਹੋਮ\nਬਟਨ ਦਬਾਈ ਰੱਖੋ"</string>
+    <string name="pip_onboarding_button" msgid="3957426748484904611">"ਸਮਝ ਲਿਆ"</string>
+</resources>
diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml
index e3082476..0fdb4df 100644
--- a/packages/SystemUI/res/values-pl/strings.xml
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -75,7 +75,8 @@
     <string name="screenshot_saved_title" msgid="6461865960961414961">"Wykonano zrzut ekranu."</string>
     <string name="screenshot_saved_text" msgid="1152839647677558815">"Dotknij, aby wyświetlić zrzut ekranu."</string>
     <string name="screenshot_failed_title" msgid="705781116746922771">"Nie udało się wykonać zrzutu ekranu."</string>
-    <string name="screenshot_failed_text" msgid="1260203058661337274">"Nie można wykonać zrzutu ekranu, bo brak miejsca albo nie zezwala na to aplikacja lub Twoja organizacja."</string>
+    <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Nie można zapisać zrzutu ekranu, bo brakuje miejsca w pamięci."</string>
+    <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Nie możesz wykonać zrzutu ekranu, bo nie zezwala na to aplikacja lub Twoja organizacja."</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"USB – opcje przesyłania plików"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Podłącz jako odtwarzacz multimedialny (MTP)"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"Podłącz jako aparat (PTP)"</string>
@@ -208,6 +209,7 @@
     <string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"Więcej czasu."</string>
     <string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"Mniej czasu."</string>
     <string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"Latarka wyłączona."</string>
+    <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"Latarka niedostępna."</string>
     <string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"Latarka włączona."</string>
     <string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"Latarka została wyłączona."</string>
     <string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"Latarka została włączona."</string>
@@ -220,6 +222,10 @@
     <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"Tryb pracy włączony."</string>
     <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"Tryb pracy wyłączony."</string>
     <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"Tryb pracy włączony."</string>
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_off (650231949881093289) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_on (4218725402373934151) -->
+    <skip />
     <string name="accessibility_brightness" msgid="8003681285547803095">"Jasność wyświetlacza"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"Transmisja danych 2G-3G została wstrzymana"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"Transmisja danych 4G została wstrzymana"</string>
@@ -276,7 +282,7 @@
     <string name="quick_settings_cast_title" msgid="7709016546426454729">"Przesyłanie"</string>
     <string name="quick_settings_casting" msgid="6601710681033353316">"Przesyłam"</string>
     <string name="quick_settings_cast_device_default_name" msgid="5367253104742382945">"Urządzenie bez nazwy"</string>
-    <string name="quick_settings_cast_device_default_description" msgid="2484573682378634413">"Wszystko gotowe do przesyłania"</string>
+    <string name="quick_settings_cast_device_default_description" msgid="2484573682378634413">"Gotowy do działania"</string>
     <string name="quick_settings_cast_detail_empty_text" msgid="311785821261640623">"Brak dostępnych urządzeń"</string>
     <string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"Jasność"</string>
     <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTOMATYCZNA"</string>
@@ -306,6 +312,8 @@
     <string name="recents_launch_disabled_message" msgid="1624523193008871793">"Aplikacja <xliff:g id="APP">%s</xliff:g> została wyłączona w trybie bezpiecznym."</string>
     <string name="recents_history_button_label" msgid="5153358867807604821">"Historia"</string>
     <string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"Wyczyść"</string>
+    <string name="recents_drag_non_dockable_task_message" msgid="2935843902795166158">"Ta aplikacja nie obsługuje trybu wielu okien"</string>
+    <string name="recents_launch_non_dockable_task_label" msgid="7862379814938391888">"Aplikacja nie obsługuje trybu wielu okien"</string>
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Podziel poziomo"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Podziel pionowo"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Podziel niestandardowo"</string>
@@ -453,18 +461,23 @@
     <string name="enable_bluetooth_title" msgid="5027037706500635269">"Włączyć Bluetooth?"</string>
     <string name="enable_bluetooth_message" msgid="9106595990708985385">"Aby połączyć klawiaturę z tabletem, musisz najpierw włączyć Bluetooth."</string>
     <string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"Włącz"</string>
-    <string name="apply_to_topic" msgid="3641403489318659666">"Zastosuj do powiadomień typu <xliff:g id="TOPIC_NAME">%1$s</xliff:g>"</string>
-    <string name="apply_to_app" msgid="363016783939815960">"Zastosuj do wszystkich powiadomień z tej aplikacji"</string>
+    <string name="show_silently" msgid="6841966539811264192">"Pokazuj powiadomienia bez sygnału dźwiękowego"</string>
+    <string name="block" msgid="2734508760962682611">"Blokuj wszystkie powiadomienia"</string>
+    <string name="do_not_silence" msgid="6878060322594892441">"Nie ignoruj"</string>
+    <string name="do_not_silence_block" msgid="4070647971382232311">"Nie ignoruj ani nie blokuj"</string>
+    <string name="tuner_full_importance_settings" msgid="8103289238676424226">"Pokaż pełne ustawienia ważności"</string>
     <string name="blocked_importance" msgid="5198578988978234161">"Zablokowane"</string>
+    <string name="min_importance" msgid="1901894910809414782">"Najmniejsza ważność"</string>
     <string name="low_importance" msgid="4109929986107147930">"Mało ważne"</string>
     <string name="default_importance" msgid="8192107689995742653">"Ważne"</string>
     <string name="high_importance" msgid="1527066195614050263">"Bardzo ważne"</string>
     <string name="max_importance" msgid="5089005872719563894">"Pilne"</string>
     <string name="notification_importance_blocked" msgid="2397192642657872872">"Nigdy nie pokazuj tych powiadomień"</string>
-    <string name="notification_importance_low" msgid="4383563267370859725">"Pokazuj na dole listy powiadomień bez sygnału dźwiękowego"</string>
-    <string name="notification_importance_default" msgid="4926529615920610817">"Pokazuj te powiadomienia bez sygnału dźwiękowego"</string>
-    <string name="notification_importance_high" msgid="3222680136612408223">"Pokazuj na górze listy powiadomień i sygnalizuj dźwiękiem"</string>
-    <string name="notification_importance_max" msgid="5236987171904756134">"Wyświetlaj na ekranie i odtwarzaj dźwięk"</string>
+    <string name="notification_importance_min" msgid="1938190340516905748">"Pokazuj na końcu listy powiadomień bez sygnału dźwiękowego"</string>
+    <string name="notification_importance_low" msgid="3657252049508213048">"Pokazuj te powiadomienia bez sygnału dźwiękowego"</string>
+    <string name="notification_importance_default" msgid="4466466472622442175">"Zezwól na sygnalizowanie tych powiadomień dźwiękiem"</string>
+    <string name="notification_importance_high" msgid="2135428926525093825">"Wyświetlaj na ekranie i sygnalizuj dźwiękiem"</string>
+    <string name="notification_importance_max" msgid="5806278962376556491">"Pokazuj na początku listy powiadomień, wyświetlaj na ekranie i sygnalizuj dźwiękiem"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"Więcej ustawień"</string>
     <string name="notification_done" msgid="5279426047273930175">"Gotowe"</string>
     <string name="color_and_appearance" msgid="1254323855964993144">"Kolor i wygląd"</string>
@@ -478,7 +491,7 @@
     <string name="use_dark_theme" msgid="2900938704964299312">"Użyj motywu ciemnego dla Androida"</string>
     <string name="adjust_tint" msgid="3398569573231409878">"Dostosuj odcień"</string>
     <string name="adjust_brightness" msgid="980039329808178246">"Dostosuj jasność"</string>
-    <string name="night_mode_disclaimer" msgid="3297928749219711334">"Motyw ciemny zostanie zastosowany do głównych obszarów Androida, które normalnie są jasne, takich jak Ustawienia czy powiadomienia."</string>
+    <string name="night_mode_disclaimer" msgid="598914896926759578">"Motyw ciemny zostanie zastosowany do głównych obszarów Androida, które normalnie są jasne, takich jak Ustawienia."</string>
     <string name="color_apply" msgid="9212602012641034283">"Zastosuj"</string>
     <string name="color_revert_title" msgid="4746666545480534663">"Potwierdź ustawienia"</string>
     <string name="color_revert_message" msgid="9116001069397996691">"Niektóre ustawienia kolorów mogą utrudniać korzystanie z urządzenia. Kliknij OK, by potwierdzić te ustawienia kolorów. Jeśli tego nie zrobisz, zostaną one zresetowane po 10 sekundach."</string>
@@ -537,4 +550,10 @@
     <item msgid="2139628951880142927">"Pokazuj procent podczas ładowania (domyślnie)"</item>
     <item msgid="3327323682209964956">"Nie pokazuj tej ikony"</item>
   </string-array>
+    <string name="other" msgid="4060683095962566764">"Inne"</string>
+    <string name="accessibility_divider" msgid="5903423481953635044">"Linia dzielenia ekranu"</string>
+    <string name="accessibility_action_divider_move_down" msgid="704893304141890042">"Przesuń w dół"</string>
+    <string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"Przesuń w górę"</string>
+    <string name="accessibility_action_divider_move_left" msgid="9218189832115847253">"Przesuń w lewo"</string>
+    <string name="accessibility_action_divider_move_right" msgid="4671522715182567972">"Przesuń w prawo"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-pl/strings_tv.xml b/packages/SystemUI/res/values-pl/strings_tv.xml
new file mode 100644
index 0000000..b804146
--- /dev/null
+++ b/packages/SystemUI/res/values-pl/strings_tv.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.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="pip_close" msgid="3480680679023423574">"Zamknij PIP"</string>
+    <string name="pip_fullscreen" msgid="8604643018538487816">"Pełny ekran"</string>
+    <string name="pip_play" msgid="674145557658227044">"Odtwórz"</string>
+    <string name="pip_pause" msgid="8412075640017218862">"Wstrzymaj"</string>
+    <string name="pip_hold_home" msgid="340086535668778109">"Przytrzymaj "<b>"EKRAN GŁÓWNY"</b>", by sterować PIP"</string>
+    <string name="pip_onboarding_description" msgid="2627737116380318292">"Przytrzymaj EKRAN GŁÓWNY,\nby sterować PIP"</string>
+    <string name="pip_onboarding_button" msgid="3957426748484904611">"OK"</string>
+</resources>
diff --git a/packages/SystemUI/res/values-pt-rBR/strings.xml b/packages/SystemUI/res/values-pt-rBR/strings.xml
index efcd7dc..86b94ab 100644
--- a/packages/SystemUI/res/values-pt-rBR/strings.xml
+++ b/packages/SystemUI/res/values-pt-rBR/strings.xml
@@ -73,7 +73,8 @@
     <string name="screenshot_saved_title" msgid="6461865960961414961">"Captura de tela obtida."</string>
     <string name="screenshot_saved_text" msgid="1152839647677558815">"Toque para visualizar a captura de tela."</string>
     <string name="screenshot_failed_title" msgid="705781116746922771">"Não foi possível obter a captura de tela."</string>
-    <string name="screenshot_failed_text" msgid="1260203058661337274">"Não é possível capturar a tela porque não há espaço suficiente ou o app ou organização não permite."</string>
+    <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Não é possível salvar a captura de tela, porque não há espaço suficiente."</string>
+    <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Capturas de tela não são permitidas pelo app ou por sua organização."</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"Opções transf. arq. por USB"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Conectar como media player (MTP)"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"Montar como uma câmera (PTP)"</string>
@@ -206,6 +207,7 @@
     <string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"Mais tempo."</string>
     <string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"Menos tempo."</string>
     <string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"Lanterna desativada."</string>
+    <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"Lanterna indisponível."</string>
     <string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"Lanterna ativada."</string>
     <string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"A lanterna foi desativada."</string>
     <string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"A lanterna foi ativada."</string>
@@ -218,6 +220,10 @@
     <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"Modo de trabalho ativado."</string>
     <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"Modo de trabalho desativado."</string>
     <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"Modo de trabalho ativado."</string>
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_off (650231949881093289) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_on (4218725402373934151) -->
+    <skip />
     <string name="accessibility_brightness" msgid="8003681285547803095">"Brilho da tela"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"Os dados 2G e 3G foram pausados"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"Os dados 4G foram pausados"</string>
@@ -301,10 +307,11 @@
     <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"fixação de tela"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"pesquisar"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"Não foi possível iniciar <xliff:g id="APP">%s</xliff:g>."</string>
-    <!-- no translation found for recents_launch_disabled_message (1624523193008871793) -->
-    <skip />
+    <string name="recents_launch_disabled_message" msgid="1624523193008871793">"O app <xliff:g id="APP">%s</xliff:g> está desativado no modo de segurança."</string>
     <string name="recents_history_button_label" msgid="5153358867807604821">"Histórico"</string>
     <string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"Limpar"</string>
+    <string name="recents_drag_non_dockable_task_message" msgid="2935843902795166158">"Este app não é compatível com o modo de várias janelas"</string>
+    <string name="recents_launch_non_dockable_task_label" msgid="7862379814938391888">"O app não é compatível com o modo de várias janelas"</string>
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Divisão horizontal"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Divisão vertical"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Divisão personalizada"</string>
@@ -452,18 +459,23 @@
     <string name="enable_bluetooth_title" msgid="5027037706500635269">"Ativar o Bluetooth?"</string>
     <string name="enable_bluetooth_message" msgid="9106595990708985385">"Para conectar o teclado ao tablet, é preciso primeiro ativar o Bluetooth."</string>
     <string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"Ativar"</string>
-    <string name="apply_to_topic" msgid="3641403489318659666">"Aplicar a notificações de <xliff:g id="TOPIC_NAME">%1$s</xliff:g>"</string>
-    <string name="apply_to_app" msgid="363016783939815960">"Aplicar a todas as notificações deste app"</string>
+    <string name="show_silently" msgid="6841966539811264192">"Mostrar notificações de forma silenciosa"</string>
+    <string name="block" msgid="2734508760962682611">"Bloquear todas as notificações"</string>
+    <string name="do_not_silence" msgid="6878060322594892441">"Não silenciar"</string>
+    <string name="do_not_silence_block" msgid="4070647971382232311">"Não silenciar ou bloquear"</string>
+    <string name="tuner_full_importance_settings" msgid="8103289238676424226">"Mostrar todas as configurações de importância"</string>
     <string name="blocked_importance" msgid="5198578988978234161">"Bloqueadas"</string>
+    <string name="min_importance" msgid="1901894910809414782">"Importância mínima"</string>
     <string name="low_importance" msgid="4109929986107147930">"Importância baixa"</string>
     <string name="default_importance" msgid="8192107689995742653">"Importância normal"</string>
     <string name="high_importance" msgid="1527066195614050263">"Importância elevada"</string>
     <string name="max_importance" msgid="5089005872719563894">"Importância urgente"</string>
     <string name="notification_importance_blocked" msgid="2397192642657872872">"Nunca mostrar essas notificações"</string>
-    <string name="notification_importance_low" msgid="4383563267370859725">"Mostrar na parte inferior da lista de notificações de forma silenciosa"</string>
-    <string name="notification_importance_default" msgid="4926529615920610817">"Mostrar essas notificações de forma silenciosa"</string>
-    <string name="notification_importance_high" msgid="3222680136612408223">"Mostrar na parte superior da lista de notificações e emitir som"</string>
-    <string name="notification_importance_max" msgid="5236987171904756134">"Mostrar parcialmente na tela e emitir som"</string>
+    <string name="notification_importance_min" msgid="1938190340516905748">"Mostrar na parte inferior da lista de notificações de forma silenciosa"</string>
+    <string name="notification_importance_low" msgid="3657252049508213048">"Mostrar essas notificações de forma silenciosa"</string>
+    <string name="notification_importance_default" msgid="4466466472622442175">"Permitir que essas notificações emitam sons"</string>
+    <string name="notification_importance_high" msgid="2135428926525093825">"Mostrar parcialmente na tela e permitir som"</string>
+    <string name="notification_importance_max" msgid="5806278962376556491">"Mostrar na parte superior da lista de notificações, mostrar parcialmente na tela e permitir sons"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"Mais configurações"</string>
     <string name="notification_done" msgid="5279426047273930175">"Concluído"</string>
     <string name="color_and_appearance" msgid="1254323855964993144">"Cor e aparência"</string>
@@ -477,7 +489,7 @@
     <string name="use_dark_theme" msgid="2900938704964299312">"Usar o tema escuro para o SO Android"</string>
     <string name="adjust_tint" msgid="3398569573231409878">"Ajustar tonalidade"</string>
     <string name="adjust_brightness" msgid="980039329808178246">"Ajustar brilho"</string>
-    <string name="night_mode_disclaimer" msgid="3297928749219711334">"O tema escuro é aplicado a áreas centrais do sistema operacional Android que normalmente são exibidas em um tema claro, como configurações e notificações."</string>
+    <string name="night_mode_disclaimer" msgid="598914896926759578">"O tema escuro é aplicado a áreas centrais do sistema operacional Android que normalmente são exibidas em um tema claro, como as configurações."</string>
     <string name="color_apply" msgid="9212602012641034283">"Aplicar"</string>
     <string name="color_revert_title" msgid="4746666545480534663">"Confirmar configurações"</string>
     <string name="color_revert_message" msgid="9116001069397996691">"Algumas configurações de cor podem tornar o dispositivo inutilizável. Clique em \"OK\" para confirmar essas configurações de cor; caso contrário, essas configurações serão redefinidas após 10 segundos."</string>
@@ -536,4 +548,10 @@
     <item msgid="2139628951880142927">"Mostrar porcentagem durante o carregamento (padrão)"</item>
     <item msgid="3327323682209964956">"Não mostrar este ícone"</item>
   </string-array>
+    <string name="other" msgid="4060683095962566764">"Outros"</string>
+    <string name="accessibility_divider" msgid="5903423481953635044">"Divisor de tela"</string>
+    <string name="accessibility_action_divider_move_down" msgid="704893304141890042">"Mover para baixo"</string>
+    <string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"Mover para cima"</string>
+    <string name="accessibility_action_divider_move_left" msgid="9218189832115847253">"Mover para a esquerda"</string>
+    <string name="accessibility_action_divider_move_right" msgid="4671522715182567972">"Mover para a direita"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-pt-rBR/strings_tv.xml b/packages/SystemUI/res/values-pt-rBR/strings_tv.xml
new file mode 100644
index 0000000..742ea28
--- /dev/null
+++ b/packages/SystemUI/res/values-pt-rBR/strings_tv.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2016, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <!-- no translation found for pip_close (3480680679023423574) -->
+    <skip />
+    <string name="pip_fullscreen" msgid="8604643018538487816">"Tela cheia"</string>
+    <string name="pip_play" msgid="674145557658227044">"Reproduzir"</string>
+    <string name="pip_pause" msgid="8412075640017218862">"Pausar"</string>
+    <!-- no translation found for pip_hold_home (340086535668778109) -->
+    <skip />
+    <!-- no translation found for pip_onboarding_description (2627737116380318292) -->
+    <skip />
+    <!-- no translation found for pip_onboarding_button (3957426748484904611) -->
+    <skip />
+</resources>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml
index 4cceb07..35ef0dd 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -73,7 +73,8 @@
     <string name="screenshot_saved_title" msgid="6461865960961414961">"Captura de ecrã efetuada"</string>
     <string name="screenshot_saved_text" msgid="1152839647677558815">"Toque para ver a captura de ecrã"</string>
     <string name="screenshot_failed_title" msgid="705781116746922771">"Não foi possível obter captura de ecrã."</string>
-    <string name="screenshot_failed_text" msgid="1260203058661337274">"Imp. tirar capt. ecrã devido ao espaço de armaz. limit. ou isso não é permitido pela aplic. da sua ent."</string>
+    <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Não é possível guardar a captura de ecrã devido a espaço de armazenamento limitado."</string>
+    <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"A aplicação ou a sua entidade não tem autorização para tirar capturas de ecrã."</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"Opções de transm. de fich. USB"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Montar como leitor de multimédia (MTP)"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"Montar como câmara (PTP)"</string>
@@ -206,6 +207,7 @@
     <string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"Mais tempo."</string>
     <string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"Menos tempo."</string>
     <string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"Lanterna desligada."</string>
+    <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"Lanterna indisponível."</string>
     <string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"Lanterna ligada."</string>
     <string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"Lanterna desligada."</string>
     <string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"Lanterna ligada."</string>
@@ -218,6 +220,10 @@
     <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"Modo de trabalho ativado."</string>
     <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"O modo de trabalho foi desativado."</string>
     <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"O modo de trabalho foi ativado."</string>
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_off (650231949881093289) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_on (4218725402373934151) -->
+    <skip />
     <string name="accessibility_brightness" msgid="8003681285547803095">"Brilho do visor"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"Dados 2G-3G em pausa"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"Dados 4G em pausa"</string>
@@ -304,6 +310,8 @@
     <string name="recents_launch_disabled_message" msgid="1624523193008871793">"O <xliff:g id="APP">%s</xliff:g> está desativado no modo de segurança."</string>
     <string name="recents_history_button_label" msgid="5153358867807604821">"Histórico"</string>
     <string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"Limpar"</string>
+    <string name="recents_drag_non_dockable_task_message" msgid="2935843902795166158">"Esta aplicação não é compatível com várias janelas"</string>
+    <string name="recents_launch_non_dockable_task_label" msgid="7862379814938391888">"A aplicação não é compatível com várias janelas"</string>
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Divisão horizontal"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Divisão vertical"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Divisão personalizada"</string>
@@ -451,18 +459,23 @@
     <string name="enable_bluetooth_title" msgid="5027037706500635269">"Pretende ativar o Bluetooth?"</string>
     <string name="enable_bluetooth_message" msgid="9106595990708985385">"Para ligar o teclado ao tablet, tem de ativar primeiro o Bluetooth."</string>
     <string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"Ativar"</string>
-    <string name="apply_to_topic" msgid="3641403489318659666">"Aplicar a notificações de <xliff:g id="TOPIC_NAME">%1$s</xliff:g>"</string>
-    <string name="apply_to_app" msgid="363016783939815960">"Aplicar a todas as notificações desta aplicação"</string>
+    <string name="show_silently" msgid="6841966539811264192">"Mostrar notificações sem som"</string>
+    <string name="block" msgid="2734508760962682611">"Bloquear todas as notificações"</string>
+    <string name="do_not_silence" msgid="6878060322594892441">"Não silenciar"</string>
+    <string name="do_not_silence_block" msgid="4070647971382232311">"Não silenciar nem bloquear"</string>
+    <string name="tuner_full_importance_settings" msgid="8103289238676424226">"Mostrar definições de importância completas"</string>
     <string name="blocked_importance" msgid="5198578988978234161">"Bloqueado"</string>
+    <string name="min_importance" msgid="1901894910809414782">"Importância mín."</string>
     <string name="low_importance" msgid="4109929986107147930">"Importância baixa"</string>
     <string name="default_importance" msgid="8192107689995742653">"Importância normal"</string>
     <string name="high_importance" msgid="1527066195614050263">"Importância alta"</string>
     <string name="max_importance" msgid="5089005872719563894">"Urgente"</string>
     <string name="notification_importance_blocked" msgid="2397192642657872872">"Nunca mostrar estas notificações"</string>
-    <string name="notification_importance_low" msgid="4383563267370859725">"Mostrar na parte inferior da lista de notificações sem som"</string>
-    <string name="notification_importance_default" msgid="4926529615920610817">"Mostrar estas notificações sem som"</string>
-    <string name="notification_importance_high" msgid="3222680136612408223">"Mostrar na parte superior da lista de notificações e emitir som"</string>
-    <string name="notification_importance_max" msgid="5236987171904756134">"Mostrar no ecrã e emitir som"</string>
+    <string name="notification_importance_min" msgid="1938190340516905748">"Mostrar na parte inferior da lista de notificações sem som"</string>
+    <string name="notification_importance_low" msgid="3657252049508213048">"Mostrar estas notificações sem som"</string>
+    <string name="notification_importance_default" msgid="4466466472622442175">"Permitir que estas notificações emitam sons"</string>
+    <string name="notification_importance_high" msgid="2135428926525093825">"Mostrar no ecrã e permitir som"</string>
+    <string name="notification_importance_max" msgid="5806278962376556491">"Mostrar na parte superior da lista de notificações, mostrar no ecrã e permitir som"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"Mais definições"</string>
     <string name="notification_done" msgid="5279426047273930175">"Concluído"</string>
     <string name="color_and_appearance" msgid="1254323855964993144">"Cor e aspeto"</string>
@@ -476,7 +489,7 @@
     <string name="use_dark_theme" msgid="2900938704964299312">"Utilizar o tema escuro para o SO Android"</string>
     <string name="adjust_tint" msgid="3398569573231409878">"Ajustar tonalidade"</string>
     <string name="adjust_brightness" msgid="980039329808178246">"Ajustar brilho"</string>
-    <string name="night_mode_disclaimer" msgid="3297928749219711334">"O tema escuro é aplicado a áreas essenciais do SO Android que são normalmente apresentadas num tema claro, como as Definições e as notificações."</string>
+    <string name="night_mode_disclaimer" msgid="598914896926759578">"O tema escuro é aplicado a áreas essenciais do SO Android que são normalmente apresentadas num tema claro, como as Definições."</string>
     <string name="color_apply" msgid="9212602012641034283">"Aplicar"</string>
     <string name="color_revert_title" msgid="4746666545480534663">"Confirmar as definições"</string>
     <string name="color_revert_message" msgid="9116001069397996691">"Algumas definições de cor podem tornar este dispositivo instável. Clique em OK para confirmar estas definições de cor. Caso contrário, estas definições serão repostas após 10 segundos."</string>
@@ -535,4 +548,10 @@
     <item msgid="2139628951880142927">"Mostrar a percentagem durante o carregamento (predefinição)"</item>
     <item msgid="3327323682209964956">"Não mostrar este ícone"</item>
   </string-array>
+    <string name="other" msgid="4060683095962566764">"Outro"</string>
+    <string name="accessibility_divider" msgid="5903423481953635044">"Divisor do ecrã dividido"</string>
+    <string name="accessibility_action_divider_move_down" msgid="704893304141890042">"Mover para baixo"</string>
+    <string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"Mover para cima"</string>
+    <string name="accessibility_action_divider_move_left" msgid="9218189832115847253">"Mover para a esquerda"</string>
+    <string name="accessibility_action_divider_move_right" msgid="4671522715182567972">"Mover para a direita"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings_tv.xml b/packages/SystemUI/res/values-pt-rPT/strings_tv.xml
new file mode 100644
index 0000000..8b1b032
--- /dev/null
+++ b/packages/SystemUI/res/values-pt-rPT/strings_tv.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.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="pip_close" msgid="3480680679023423574">"Fechar PIP"</string>
+    <string name="pip_fullscreen" msgid="8604643018538487816">"Ecrã inteiro"</string>
+    <string name="pip_play" msgid="674145557658227044">"Reproduzir"</string>
+    <string name="pip_pause" msgid="8412075640017218862">"Interromper"</string>
+    <string name="pip_hold_home" msgid="340086535668778109">"Prima sem soltar o botão "<b>"HOME"</b>" para controlar o PIP"</string>
+    <string name="pip_onboarding_description" msgid="2627737116380318292">"Prima sem soltar o botão HOME\npara controlar o PIP"</string>
+    <string name="pip_onboarding_button" msgid="3957426748484904611">"Compreendi"</string>
+</resources>
diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml
index efcd7dc..86b94ab 100644
--- a/packages/SystemUI/res/values-pt/strings.xml
+++ b/packages/SystemUI/res/values-pt/strings.xml
@@ -73,7 +73,8 @@
     <string name="screenshot_saved_title" msgid="6461865960961414961">"Captura de tela obtida."</string>
     <string name="screenshot_saved_text" msgid="1152839647677558815">"Toque para visualizar a captura de tela."</string>
     <string name="screenshot_failed_title" msgid="705781116746922771">"Não foi possível obter a captura de tela."</string>
-    <string name="screenshot_failed_text" msgid="1260203058661337274">"Não é possível capturar a tela porque não há espaço suficiente ou o app ou organização não permite."</string>
+    <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Não é possível salvar a captura de tela, porque não há espaço suficiente."</string>
+    <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Capturas de tela não são permitidas pelo app ou por sua organização."</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"Opções transf. arq. por USB"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Conectar como media player (MTP)"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"Montar como uma câmera (PTP)"</string>
@@ -206,6 +207,7 @@
     <string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"Mais tempo."</string>
     <string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"Menos tempo."</string>
     <string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"Lanterna desativada."</string>
+    <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"Lanterna indisponível."</string>
     <string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"Lanterna ativada."</string>
     <string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"A lanterna foi desativada."</string>
     <string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"A lanterna foi ativada."</string>
@@ -218,6 +220,10 @@
     <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"Modo de trabalho ativado."</string>
     <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"Modo de trabalho desativado."</string>
     <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"Modo de trabalho ativado."</string>
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_off (650231949881093289) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_on (4218725402373934151) -->
+    <skip />
     <string name="accessibility_brightness" msgid="8003681285547803095">"Brilho da tela"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"Os dados 2G e 3G foram pausados"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"Os dados 4G foram pausados"</string>
@@ -301,10 +307,11 @@
     <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"fixação de tela"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"pesquisar"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"Não foi possível iniciar <xliff:g id="APP">%s</xliff:g>."</string>
-    <!-- no translation found for recents_launch_disabled_message (1624523193008871793) -->
-    <skip />
+    <string name="recents_launch_disabled_message" msgid="1624523193008871793">"O app <xliff:g id="APP">%s</xliff:g> está desativado no modo de segurança."</string>
     <string name="recents_history_button_label" msgid="5153358867807604821">"Histórico"</string>
     <string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"Limpar"</string>
+    <string name="recents_drag_non_dockable_task_message" msgid="2935843902795166158">"Este app não é compatível com o modo de várias janelas"</string>
+    <string name="recents_launch_non_dockable_task_label" msgid="7862379814938391888">"O app não é compatível com o modo de várias janelas"</string>
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Divisão horizontal"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Divisão vertical"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Divisão personalizada"</string>
@@ -452,18 +459,23 @@
     <string name="enable_bluetooth_title" msgid="5027037706500635269">"Ativar o Bluetooth?"</string>
     <string name="enable_bluetooth_message" msgid="9106595990708985385">"Para conectar o teclado ao tablet, é preciso primeiro ativar o Bluetooth."</string>
     <string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"Ativar"</string>
-    <string name="apply_to_topic" msgid="3641403489318659666">"Aplicar a notificações de <xliff:g id="TOPIC_NAME">%1$s</xliff:g>"</string>
-    <string name="apply_to_app" msgid="363016783939815960">"Aplicar a todas as notificações deste app"</string>
+    <string name="show_silently" msgid="6841966539811264192">"Mostrar notificações de forma silenciosa"</string>
+    <string name="block" msgid="2734508760962682611">"Bloquear todas as notificações"</string>
+    <string name="do_not_silence" msgid="6878060322594892441">"Não silenciar"</string>
+    <string name="do_not_silence_block" msgid="4070647971382232311">"Não silenciar ou bloquear"</string>
+    <string name="tuner_full_importance_settings" msgid="8103289238676424226">"Mostrar todas as configurações de importância"</string>
     <string name="blocked_importance" msgid="5198578988978234161">"Bloqueadas"</string>
+    <string name="min_importance" msgid="1901894910809414782">"Importância mínima"</string>
     <string name="low_importance" msgid="4109929986107147930">"Importância baixa"</string>
     <string name="default_importance" msgid="8192107689995742653">"Importância normal"</string>
     <string name="high_importance" msgid="1527066195614050263">"Importância elevada"</string>
     <string name="max_importance" msgid="5089005872719563894">"Importância urgente"</string>
     <string name="notification_importance_blocked" msgid="2397192642657872872">"Nunca mostrar essas notificações"</string>
-    <string name="notification_importance_low" msgid="4383563267370859725">"Mostrar na parte inferior da lista de notificações de forma silenciosa"</string>
-    <string name="notification_importance_default" msgid="4926529615920610817">"Mostrar essas notificações de forma silenciosa"</string>
-    <string name="notification_importance_high" msgid="3222680136612408223">"Mostrar na parte superior da lista de notificações e emitir som"</string>
-    <string name="notification_importance_max" msgid="5236987171904756134">"Mostrar parcialmente na tela e emitir som"</string>
+    <string name="notification_importance_min" msgid="1938190340516905748">"Mostrar na parte inferior da lista de notificações de forma silenciosa"</string>
+    <string name="notification_importance_low" msgid="3657252049508213048">"Mostrar essas notificações de forma silenciosa"</string>
+    <string name="notification_importance_default" msgid="4466466472622442175">"Permitir que essas notificações emitam sons"</string>
+    <string name="notification_importance_high" msgid="2135428926525093825">"Mostrar parcialmente na tela e permitir som"</string>
+    <string name="notification_importance_max" msgid="5806278962376556491">"Mostrar na parte superior da lista de notificações, mostrar parcialmente na tela e permitir sons"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"Mais configurações"</string>
     <string name="notification_done" msgid="5279426047273930175">"Concluído"</string>
     <string name="color_and_appearance" msgid="1254323855964993144">"Cor e aparência"</string>
@@ -477,7 +489,7 @@
     <string name="use_dark_theme" msgid="2900938704964299312">"Usar o tema escuro para o SO Android"</string>
     <string name="adjust_tint" msgid="3398569573231409878">"Ajustar tonalidade"</string>
     <string name="adjust_brightness" msgid="980039329808178246">"Ajustar brilho"</string>
-    <string name="night_mode_disclaimer" msgid="3297928749219711334">"O tema escuro é aplicado a áreas centrais do sistema operacional Android que normalmente são exibidas em um tema claro, como configurações e notificações."</string>
+    <string name="night_mode_disclaimer" msgid="598914896926759578">"O tema escuro é aplicado a áreas centrais do sistema operacional Android que normalmente são exibidas em um tema claro, como as configurações."</string>
     <string name="color_apply" msgid="9212602012641034283">"Aplicar"</string>
     <string name="color_revert_title" msgid="4746666545480534663">"Confirmar configurações"</string>
     <string name="color_revert_message" msgid="9116001069397996691">"Algumas configurações de cor podem tornar o dispositivo inutilizável. Clique em \"OK\" para confirmar essas configurações de cor; caso contrário, essas configurações serão redefinidas após 10 segundos."</string>
@@ -536,4 +548,10 @@
     <item msgid="2139628951880142927">"Mostrar porcentagem durante o carregamento (padrão)"</item>
     <item msgid="3327323682209964956">"Não mostrar este ícone"</item>
   </string-array>
+    <string name="other" msgid="4060683095962566764">"Outros"</string>
+    <string name="accessibility_divider" msgid="5903423481953635044">"Divisor de tela"</string>
+    <string name="accessibility_action_divider_move_down" msgid="704893304141890042">"Mover para baixo"</string>
+    <string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"Mover para cima"</string>
+    <string name="accessibility_action_divider_move_left" msgid="9218189832115847253">"Mover para a esquerda"</string>
+    <string name="accessibility_action_divider_move_right" msgid="4671522715182567972">"Mover para a direita"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-pt/strings_tv.xml b/packages/SystemUI/res/values-pt/strings_tv.xml
new file mode 100644
index 0000000..742ea28
--- /dev/null
+++ b/packages/SystemUI/res/values-pt/strings_tv.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2016, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <!-- no translation found for pip_close (3480680679023423574) -->
+    <skip />
+    <string name="pip_fullscreen" msgid="8604643018538487816">"Tela cheia"</string>
+    <string name="pip_play" msgid="674145557658227044">"Reproduzir"</string>
+    <string name="pip_pause" msgid="8412075640017218862">"Pausar"</string>
+    <!-- no translation found for pip_hold_home (340086535668778109) -->
+    <skip />
+    <!-- no translation found for pip_onboarding_description (2627737116380318292) -->
+    <skip />
+    <!-- no translation found for pip_onboarding_button (3957426748484904611) -->
+    <skip />
+</resources>
diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml
index 47cf729..b854ffb 100644
--- a/packages/SystemUI/res/values-ro/strings.xml
+++ b/packages/SystemUI/res/values-ro/strings.xml
@@ -74,7 +74,8 @@
     <string name="screenshot_saved_title" msgid="6461865960961414961">"Captură de ecran realizată."</string>
     <string name="screenshot_saved_text" msgid="1152839647677558815">"Atingeți pentru a vedea captura de ecran."</string>
     <string name="screenshot_failed_title" msgid="705781116746922771">"Captura de ecran nu a putut fi realizată."</string>
-    <string name="screenshot_failed_text" msgid="1260203058661337274">"Captură de ecran impos. de realizat: spațiu de stoc. limitat sau nu este permisă de apl. sau de organiz."</string>
+    <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Captura de ecran nu poate fi salvată din cauza spațiului de stocare limitat."</string>
+    <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Crearea capturilor de ecran nu este permisă de aplicație sau de organizația dvs."</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"Opțiuni pentru transferul de fișiere prin USB"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Montați ca player media (MTP)"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"Montați drept cameră foto (PTP)"</string>
@@ -207,6 +208,7 @@
     <string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"Mai mult timp."</string>
     <string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"Mai puțin timp."</string>
     <string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"Lanterna este dezactivată."</string>
+    <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"Lanterna nu este disponibilă."</string>
     <string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"Lanterna este activată."</string>
     <string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"Lanterna este dezactivată."</string>
     <string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"Lanterna este activată."</string>
@@ -219,6 +221,10 @@
     <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"Modul de lucru este activat."</string>
     <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"Modul de lucru a fost dezactivat."</string>
     <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"Modul de lucru a fost activat."</string>
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_off (650231949881093289) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_on (4218725402373934151) -->
+    <skip />
     <string name="accessibility_brightness" msgid="8003681285547803095">"Luminozitatea ecranului"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"Conexiunea de date 2G – 3G este întreruptă"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"Conexiunea de date 4G este întreruptă"</string>
@@ -305,6 +311,8 @@
     <string name="recents_launch_disabled_message" msgid="1624523193008871793">"Aplicația <xliff:g id="APP">%s</xliff:g> este dezactivată în modul sigur."</string>
     <string name="recents_history_button_label" msgid="5153358867807604821">"Istoric"</string>
     <string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"Ștergeți"</string>
+    <string name="recents_drag_non_dockable_task_message" msgid="2935843902795166158">"Această aplicație nu acceptă ferestre multiple"</string>
+    <string name="recents_launch_non_dockable_task_label" msgid="7862379814938391888">"Aplicația nu acceptă ferestre multiple"</string>
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Divizare pe orizontală"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Divizare pe verticală"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Divizare personalizată"</string>
@@ -452,18 +460,23 @@
     <string name="enable_bluetooth_title" msgid="5027037706500635269">"Activați Bluetooth?"</string>
     <string name="enable_bluetooth_message" msgid="9106595990708985385">"Pentru a conecta tastatura la tabletă, mai întâi trebuie să activați Bluetooth."</string>
     <string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"Activați"</string>
-    <string name="apply_to_topic" msgid="3641403489318659666">"Aplicați notificărilor de tip <xliff:g id="TOPIC_NAME">%1$s</xliff:g>"</string>
-    <string name="apply_to_app" msgid="363016783939815960">"Aplicați tuturor notificărilor de la această aplicație"</string>
+    <string name="show_silently" msgid="6841966539811264192">"Notificările se afișează fără a se emite un sunet"</string>
+    <string name="block" msgid="2734508760962682611">"Blocați toate notificările"</string>
+    <string name="do_not_silence" msgid="6878060322594892441">"Nu dezactivați sunetul"</string>
+    <string name="do_not_silence_block" msgid="4070647971382232311">"Nu dezactivați sunetul și nu blocați"</string>
+    <string name="tuner_full_importance_settings" msgid="8103289238676424226">"Afișați toate setările privind importanța"</string>
     <string name="blocked_importance" msgid="5198578988978234161">"Blocate"</string>
+    <string name="min_importance" msgid="1901894910809414782">"Importanță minimă"</string>
     <string name="low_importance" msgid="4109929986107147930">"Importanță redusă"</string>
     <string name="default_importance" msgid="8192107689995742653">"Importanță normală"</string>
     <string name="high_importance" msgid="1527066195614050263">"Importanță ridicată"</string>
     <string name="max_importance" msgid="5089005872719563894">"Importanță: urgente"</string>
     <string name="notification_importance_blocked" msgid="2397192642657872872">"Aceste notificări nu se afișează niciodată"</string>
-    <string name="notification_importance_low" msgid="4383563267370859725">"Se afișează în partea de jos a listei cu notificări fără a se emite un sunet"</string>
-    <string name="notification_importance_default" msgid="4926529615920610817">"Aceste notificări se afișează fără a se emite un sunet"</string>
-    <string name="notification_importance_high" msgid="3222680136612408223">"Se afișează în partea de sus a listei cu notificări și se emite un sunet"</string>
-    <string name="notification_importance_max" msgid="5236987171904756134">"Se afișează pentru o scurtă durată pe ecran și se emite un sunet"</string>
+    <string name="notification_importance_min" msgid="1938190340516905748">"Se afișează în partea de jos a listei cu notificări fără a se emite un sunet"</string>
+    <string name="notification_importance_low" msgid="3657252049508213048">"Aceste notificări se afișează fără a se emite un sunet"</string>
+    <string name="notification_importance_default" msgid="4466466472622442175">"Permiteți acestor notificări să emită sunete"</string>
+    <string name="notification_importance_high" msgid="2135428926525093825">"Se afișează pentru o scurtă durată pe ecran și se permite un sunet"</string>
+    <string name="notification_importance_max" msgid="5806278962376556491">"Apar în partea de sus a listei cu notificări, se afișează pentru scurt timp pe ecran și se permite un sunet"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"Mai multe setări"</string>
     <string name="notification_done" msgid="5279426047273930175">"Terminat"</string>
     <string name="color_and_appearance" msgid="1254323855964993144">"Culoare și aspect"</string>
@@ -477,7 +490,7 @@
     <string name="use_dark_theme" msgid="2900938704964299312">"Folosiți tema întunecată pentru SO Android"</string>
     <string name="adjust_tint" msgid="3398569573231409878">"Ajustați culoarea"</string>
     <string name="adjust_brightness" msgid="980039329808178246">"Ajustați luminozitatea"</string>
-    <string name="night_mode_disclaimer" msgid="3297928749219711334">"Tema întunecată se aplică zonelor principale ale sistemului de operare Android care sunt de obicei afișate cu o temă deschisă la culoare, cum ar fi Setările și notificările."</string>
+    <string name="night_mode_disclaimer" msgid="598914896926759578">"Tema întunecată se aplică zonelor principale ale sistemului de operare Android care sunt de obicei afișate cu o temă deschisă la culoare, cum ar fi Setările."</string>
     <string name="color_apply" msgid="9212602012641034283">"Aplicați"</string>
     <string name="color_revert_title" msgid="4746666545480534663">"Confirmați setările"</string>
     <string name="color_revert_message" msgid="9116001069397996691">"Unele setări pentru culori pot face dispozitivul să nu mai funcționeze. Dați clic pe OK pentru a confirma aceste setări pentru culori. În caz contrar, acestea se vor reseta după 10 secunde."</string>
@@ -536,4 +549,10 @@
     <item msgid="2139628951880142927">"Afișează procentajul când se încarcă (prestabilit)"</item>
     <item msgid="3327323682209964956">"Nu afișa această pictogramă"</item>
   </string-array>
+    <string name="other" msgid="4060683095962566764">"Altele"</string>
+    <string name="accessibility_divider" msgid="5903423481953635044">"Separator pentru ecranul împărțit"</string>
+    <string name="accessibility_action_divider_move_down" msgid="704893304141890042">"Mutați în jos"</string>
+    <string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"Mutați în sus"</string>
+    <string name="accessibility_action_divider_move_left" msgid="9218189832115847253">"Mutați spre stânga"</string>
+    <string name="accessibility_action_divider_move_right" msgid="4671522715182567972">"Mutați spre dreapta"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ro/strings_tv.xml b/packages/SystemUI/res/values-ro/strings_tv.xml
new file mode 100644
index 0000000..cbe5e38
--- /dev/null
+++ b/packages/SystemUI/res/values-ro/strings_tv.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2016, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <!-- no translation found for pip_close (3480680679023423574) -->
+    <skip />
+    <string name="pip_fullscreen" msgid="8604643018538487816">"Ecran complet"</string>
+    <string name="pip_play" msgid="674145557658227044">"Redați"</string>
+    <string name="pip_pause" msgid="8412075640017218862">"Întrerupeți"</string>
+    <!-- no translation found for pip_hold_home (340086535668778109) -->
+    <skip />
+    <!-- no translation found for pip_onboarding_description (2627737116380318292) -->
+    <skip />
+    <!-- no translation found for pip_onboarding_button (3957426748484904611) -->
+    <skip />
+</resources>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index 425d527..5a7e51c 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -75,7 +75,8 @@
     <string name="screenshot_saved_title" msgid="6461865960961414961">"Скриншот сохранен"</string>
     <string name="screenshot_saved_text" msgid="1152839647677558815">"Нажмите, чтобы просмотреть"</string>
     <string name="screenshot_failed_title" msgid="705781116746922771">"Не удалось сохранить скриншот."</string>
-    <string name="screenshot_failed_text" msgid="1260203058661337274">"Не удается сделать скриншот: не хватает памяти или нет разрешения от приложения или организации."</string>
+    <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Не удалось сохранить скриншот: недостаточно места."</string>
+    <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Не удалось сделать скриншот: нет разрешения от приложения или организации."</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"Параметры передачи через USB"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Подключить как мультимедийный проигрыватель (MTP)"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"Установить как камеру (PTP)"</string>
@@ -208,6 +209,7 @@
     <string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"Увеличить время."</string>
     <string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"Уменьшить время."</string>
     <string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"Фонарик отключен."</string>
+    <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"Фонарик недоступен."</string>
     <string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"Фонарик включен."</string>
     <string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"Фонарик отключен."</string>
     <string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"Фонарик включен."</string>
@@ -220,6 +222,10 @@
     <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"Рабочий режим включен."</string>
     <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"Рабочий режим отключен."</string>
     <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"Рабочий режим включен."</string>
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_off (650231949881093289) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_on (4218725402373934151) -->
+    <skip />
     <string name="accessibility_brightness" msgid="8003681285547803095">"Яркость экрана"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"Передача данных 2G и 3G приостановлена"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"Передача данных 4G приостановлена"</string>
@@ -306,6 +312,8 @@
     <string name="recents_launch_disabled_message" msgid="1624523193008871793">"Приложение \"<xliff:g id="APP">%s</xliff:g>\" отключено в безопасном режиме."</string>
     <string name="recents_history_button_label" msgid="5153358867807604821">"Журнал"</string>
     <string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"Очистить"</string>
+    <string name="recents_drag_non_dockable_task_message" msgid="2935843902795166158">"Приложение не поддерживает многооконный режим"</string>
+    <string name="recents_launch_non_dockable_task_label" msgid="7862379814938391888">"Приложение не поддерживает многооконный режим"</string>
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Разделить по горизонтали"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Разделить по вертикали"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Разделить по-другому"</string>
@@ -453,32 +461,37 @@
     <string name="enable_bluetooth_title" msgid="5027037706500635269">"Подключение по Bluetooth"</string>
     <string name="enable_bluetooth_message" msgid="9106595990708985385">"Чтобы подключить клавиатуру к планшету, включите Bluetooth."</string>
     <string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"Включить"</string>
-    <string name="apply_to_topic" msgid="3641403489318659666">"Применить к уведомлениям на тему \"<xliff:g id="TOPIC_NAME">%1$s</xliff:g>\""</string>
-    <string name="apply_to_app" msgid="363016783939815960">"Применить ко всем уведомлениям этого приложения"</string>
+    <string name="show_silently" msgid="6841966539811264192">"Показывать без звука"</string>
+    <string name="block" msgid="2734508760962682611">"Блокировать все уведомления"</string>
+    <string name="do_not_silence" msgid="6878060322594892441">"Показывать со звуком"</string>
+    <string name="do_not_silence_block" msgid="4070647971382232311">"Не блокировать, показывать со звуком"</string>
+    <string name="tuner_full_importance_settings" msgid="8103289238676424226">"Показывать все настройки важности"</string>
     <string name="blocked_importance" msgid="5198578988978234161">"Блокировка"</string>
+    <string name="min_importance" msgid="1901894910809414782">"Наименьшая важность"</string>
     <string name="low_importance" msgid="4109929986107147930">"Низкая важность"</string>
     <string name="default_importance" msgid="8192107689995742653">"Средняя важность"</string>
     <string name="high_importance" msgid="1527066195614050263">"Высокая важность"</string>
     <string name="max_importance" msgid="5089005872719563894">"Крайняя важность"</string>
     <string name="notification_importance_blocked" msgid="2397192642657872872">"Не показывать эти уведомления."</string>
-    <string name="notification_importance_low" msgid="4383563267370859725">"Показывать без звука в конце списка уведомлений."</string>
-    <string name="notification_importance_default" msgid="4926529615920610817">"Показывать уведомления без звука."</string>
-    <string name="notification_importance_high" msgid="3222680136612408223">"Показывать со звуком в начале списка уведомлений."</string>
-    <string name="notification_importance_max" msgid="5236987171904756134">"Показывать со звуком поверх всех окон."</string>
+    <string name="notification_importance_min" msgid="1938190340516905748">"Показывать без звука в конце списка уведомлений"</string>
+    <string name="notification_importance_low" msgid="3657252049508213048">"Показывать без звука"</string>
+    <string name="notification_importance_default" msgid="4466466472622442175">"Показывать со звуком"</string>
+    <string name="notification_importance_high" msgid="2135428926525093825">"Показывать со звуком поверх всех окон"</string>
+    <string name="notification_importance_max" msgid="5806278962376556491">"Показывать со звуком в начале списка уведомлений и поверх всех окон"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"Другие настройки"</string>
     <string name="notification_done" msgid="5279426047273930175">"Готово"</string>
     <string name="color_and_appearance" msgid="1254323855964993144">"Цвета и стиль"</string>
     <string name="night_mode" msgid="3540405868248625488">"Ночной режим"</string>
-    <string name="calibrate_display" msgid="5974642573432039217">"Настройка дисплея"</string>
+    <string name="calibrate_display" msgid="5974642573432039217">"Калибровка дисплея"</string>
     <string name="night_mode_on" msgid="5597545513026541108">"Включен"</string>
     <string name="night_mode_off" msgid="8035605276956057508">"Отключен"</string>
     <string name="turn_on_automatically" msgid="4167565356762016083">"Включать автоматически"</string>
-    <string name="turn_on_auto_summary" msgid="2190994512406701520">"Включать ночной режим в определенное время суток и в определенном месте"</string>
+    <string name="turn_on_auto_summary" msgid="2190994512406701520">"Включать ночной режим с учетом местоположения и времени суток"</string>
     <string name="when_night_mode_on" msgid="2969436026899172821">"В ночном режиме"</string>
     <string name="use_dark_theme" msgid="2900938704964299312">"Использовать темное оформление для Android"</string>
-    <string name="adjust_tint" msgid="3398569573231409878">"Выбрать оттенок"</string>
+    <string name="adjust_tint" msgid="3398569573231409878">"Изменять оттенок"</string>
     <string name="adjust_brightness" msgid="980039329808178246">"Яркость"</string>
-    <string name="night_mode_disclaimer" msgid="3297928749219711334">"Темное оформление применяется к основным областям экрана Android (такие как настройки и уведомления), которые обычно показываются в светлом."</string>
+    <string name="night_mode_disclaimer" msgid="598914896926759578">"Темное оформление применяется к основным элементам системы Android (таким, как приложение \"Настройки\"), которые обычно показываются в светлом."</string>
     <string name="color_apply" msgid="9212602012641034283">"Применить"</string>
     <string name="color_revert_title" msgid="4746666545480534663">"Подтвердите настройки"</string>
     <string name="color_revert_message" msgid="9116001069397996691">"Некоторые цветовые настройки могут затруднить работу с устройством. Чтобы применить выбранные параметры, нажмите \"ОК\". В противном случае они будут сброшены через 10 секунд."</string>
@@ -490,7 +503,7 @@
     <string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"Главный экран"</string>
     <string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"Недавние"</string>
     <string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"Назад"</string>
-    <string name="tuner_full_zen_title" msgid="4540823317772234308">"Показывать панель с кнопками регулировки громкости"</string>
+    <string name="tuner_full_zen_title" msgid="4540823317772234308">"Показывать при нажатии кнопок регулировки громкости"</string>
     <string name="volume_and_do_not_disturb" msgid="3373784330208603030">"Не беспокоить"</string>
     <string name="volume_dnd_silent" msgid="4363882330723050727">"Кнопки регулировки громкости"</string>
     <string name="volume_up_silent" msgid="7141255269783588286">"Отключать режим \"Не беспокоить\" при увеличении громкости"</string>
@@ -537,4 +550,10 @@
     <item msgid="2139628951880142927">"Показывать процент во время зарядки (по умолчанию)"</item>
     <item msgid="3327323682209964956">"Не показывать этот значок"</item>
   </string-array>
+    <string name="other" msgid="4060683095962566764">"Другое"</string>
+    <string name="accessibility_divider" msgid="5903423481953635044">"Разделитель экрана"</string>
+    <string name="accessibility_action_divider_move_down" msgid="704893304141890042">"Опустить"</string>
+    <string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"Поднять"</string>
+    <string name="accessibility_action_divider_move_left" msgid="9218189832115847253">"Сдвинуть влево"</string>
+    <string name="accessibility_action_divider_move_right" msgid="4671522715182567972">"Сдвинуть вправо"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ru/strings_tv.xml b/packages/SystemUI/res/values-ru/strings_tv.xml
new file mode 100644
index 0000000..dd9cb5a
--- /dev/null
+++ b/packages/SystemUI/res/values-ru/strings_tv.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2016, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <!-- no translation found for pip_close (3480680679023423574) -->
+    <skip />
+    <string name="pip_fullscreen" msgid="8604643018538487816">"Во весь экран"</string>
+    <string name="pip_play" msgid="674145557658227044">"Воспроизвести"</string>
+    <string name="pip_pause" msgid="8412075640017218862">"Приостановить"</string>
+    <!-- no translation found for pip_hold_home (340086535668778109) -->
+    <skip />
+    <!-- no translation found for pip_onboarding_description (2627737116380318292) -->
+    <skip />
+    <!-- no translation found for pip_onboarding_button (3957426748484904611) -->
+    <skip />
+</resources>
diff --git a/packages/SystemUI/res/values-si-rLK/strings.xml b/packages/SystemUI/res/values-si-rLK/strings.xml
index bac8ef4..1e178cf 100644
--- a/packages/SystemUI/res/values-si-rLK/strings.xml
+++ b/packages/SystemUI/res/values-si-rLK/strings.xml
@@ -73,7 +73,8 @@
     <string name="screenshot_saved_title" msgid="6461865960961414961">"තිර රුව ග්‍රහණය කරන ලදි."</string>
     <string name="screenshot_saved_text" msgid="1152839647677558815">"ඔබගේ තිර රුව බැලීමට ස්පර්ශ කරන්න."</string>
     <string name="screenshot_failed_title" msgid="705781116746922771">"තිර රුව ග්‍රහණය කිරීමට නොහැකි විය."</string>
-    <string name="screenshot_failed_text" msgid="1260203058661337274">"සීමිත ආචයනය ඉඩ හේතුවෙන් තිර රුව ලබාගත නොහැක, හෝ ඔබගේ යෙදුම හෝ ඔබගේ සංවිධානය විසින් එය ඉඩ නොදී තිබේ."</string>
+    <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"සීමිත ගබඩා ඉඩ නිසා තිර රුව සුරැකිය නොහැකිය."</string>
+    <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"තිර රූ ගැනීමට යෙදුම හෝ ඔබගේ සංවිධානය ඉඩ නොදේ."</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"USB ගොනු හුවමාරු විකල්ප"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"මධ්‍ය ධාවකයක් (MTP) ලෙස සවි කරන්න"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"කැමරාවක් (PTP) ලෙස සවි කරන්න"</string>
@@ -206,6 +207,7 @@
     <string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"වේලාව වැඩියෙන්."</string>
     <string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"වේලාව අඩුවෙන්."</string>
     <string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"සැණෙළි ආලෝකය අක්‍රිය කරන ලදි."</string>
+    <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"සැණෙළි ආලෝකය ලබා ගත නොහැකිය."</string>
     <string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"සැණෙළි ආලෝකය සක්‍රිය කරන ලදි."</string>
     <string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"සැණෙළි ආලෝකය අක්‍රිය කරන ලදි."</string>
     <string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"සැණෙළි ආලෝකය සක්‍රිය කරන ලදි."</string>
@@ -218,6 +220,10 @@
     <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"වැඩ ප්‍රකාරය ක්‍රියාත්මකයි."</string>
     <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"වැඩ ප්‍රකාරය ක්‍රියාවිරහිත කරන ලදී."</string>
     <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"වැඩ ප්‍රකාරය ක්‍රියාත්මක කරන ලදී."</string>
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_off (650231949881093289) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_on (4218725402373934151) -->
+    <skip />
     <string name="accessibility_brightness" msgid="8003681285547803095">"දීප්තිය දර්ශනය කරන්න"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"2G-3G දත්ත විරාම කර ඇත"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"4G දත්ත විරාම කර ඇත"</string>
@@ -304,6 +310,8 @@
     <string name="recents_launch_disabled_message" msgid="1624523193008871793">"<xliff:g id="APP">%s</xliff:g> ආරක්ෂිත ප්‍රකාරය තුළ අබලයි."</string>
     <string name="recents_history_button_label" msgid="5153358867807604821">"ඉතිහාසය"</string>
     <string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"හිස් කරන්න"</string>
+    <string name="recents_drag_non_dockable_task_message" msgid="2935843902795166158">"මෙම යෙදුම බහු-කවුළුව සඳහා සහාය නොදක්වයි"</string>
+    <string name="recents_launch_non_dockable_task_label" msgid="7862379814938391888">"යෙදුම බහු-කවුළුව සඳහා සහාය නොදක්වයි"</string>
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"තිරස්ව වෙන් කරන්න"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"සිරස්ව වෙන් කරන්න"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"අභිමත ලෙස වෙන් කරන්න"</string>
@@ -451,18 +459,23 @@
     <string name="enable_bluetooth_title" msgid="5027037706500635269">"බ්ලූටූත් ක්‍රියාත්මක කරන්නද?"</string>
     <string name="enable_bluetooth_message" msgid="9106595990708985385">"ඔබේ යතුරු පුවරුව ඔබේ ටැබ්ලට් පරිගණකයට සම්බන්ධ කිරීමට, ඔබ පළමුව බ්ලූටූත් ක්‍රියාත්මක කළ යුතුය."</string>
     <string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"ක්‍රියාත්මක කරන්න"</string>
-    <string name="apply_to_topic" msgid="3641403489318659666">"<xliff:g id="TOPIC_NAME">%1$s</xliff:g> දැනුම්දීම් වෙත යොදන්න"</string>
-    <string name="apply_to_app" msgid="363016783939815960">"මෙම යෙදුම වෙතින් වන සියලු දැනුම්දීම් සඳහා යොදන්න"</string>
+    <string name="show_silently" msgid="6841966539811264192">"නිශ්ශබ්දව දැනුම්දීම් පෙන්වන්න"</string>
+    <string name="block" msgid="2734508760962682611">"සියලු දැනුම්දීම් අවහිර කරන්න"</string>
+    <string name="do_not_silence" msgid="6878060322594892441">"නිශ්ශබ්ද නොකරන්න"</string>
+    <string name="do_not_silence_block" msgid="4070647971382232311">"නිශ්ශබ්ද හෝ අවහිර නොකරන්න"</string>
+    <string name="tuner_full_importance_settings" msgid="8103289238676424226">"පූර්ණ වැදගත්කම් සැකසීම් පෙන්වන්න"</string>
     <string name="blocked_importance" msgid="5198578988978234161">"අවහිර කරන ලදි"</string>
+    <string name="min_importance" msgid="1901894910809414782">"අවම වැදගත්කම"</string>
     <string name="low_importance" msgid="4109929986107147930">"අඩු වැදගත්කම"</string>
     <string name="default_importance" msgid="8192107689995742653">"සාමාන්‍ය වැදගත්කම"</string>
     <string name="high_importance" msgid="1527066195614050263">"වැඩි වැදගත්කම"</string>
     <string name="max_importance" msgid="5089005872719563894">"හදිසි වැදගත්කම"</string>
     <string name="notification_importance_blocked" msgid="2397192642657872872">"මෙම දැනුම්දීම් කිසිදා නොපෙන්වන්න"</string>
-    <string name="notification_importance_low" msgid="4383563267370859725">"දැනුම්දීම් ලැයිස්තුවෙහි පහළින්ම නිශ්ශබ්දව පෙන්වන්න"</string>
-    <string name="notification_importance_default" msgid="4926529615920610817">"නිශ්ශබ්දව මෙම දැනුම්දීම් පෙන්වන්න"</string>
-    <string name="notification_importance_high" msgid="3222680136612408223">"දැනුම්දීම් ලැයිස්තුවෙහි ඉහළින්ම පෙන්වන්න සහ ශබ්ද කරන්න"</string>
-    <string name="notification_importance_max" msgid="5236987171904756134">"තිරයට පැමිණ ශබ්ද කරන්න"</string>
+    <string name="notification_importance_min" msgid="1938190340516905748">"දැනුම්දීම් ලැයිස්තුවෙහි පහළින්ම නිශ්ශබ්දව පෙන්වන්න"</string>
+    <string name="notification_importance_low" msgid="3657252049508213048">"නිශ්ශබ්දව මෙම දැනුම්දීම් පෙන්වන්න"</string>
+    <string name="notification_importance_default" msgid="4466466472622442175">"මෙම දැනුම්දීම්වලට ශබ්ද නැගීමට ඉඩ දෙන්න"</string>
+    <string name="notification_importance_high" msgid="2135428926525093825">"තිරයට එබිකම් කර ශබ්දයට ඉඩ දෙන්න සහ ශබ්දයට ඉඩ දෙන්න"</string>
+    <string name="notification_importance_max" msgid="5806278962376556491">"දැනුම්දීම් ලැයිස්තුවෙහි ඉහළින්ම පෙන්වන්න, තිරයට එබිකම් කර ශබ්දයට ඉඩ දෙන්න"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"තව සැකසීම්"</string>
     <string name="notification_done" msgid="5279426047273930175">"නිමයි"</string>
     <string name="color_and_appearance" msgid="1254323855964993144">"වර්ණය සහ පෙනුම"</string>
@@ -476,7 +489,7 @@
     <string name="use_dark_theme" msgid="2900938704964299312">"Android OS සඳහා අඳුරු තේමාව භාවිත කරන්න"</string>
     <string name="adjust_tint" msgid="3398569573231409878">"පැහැය සීරුමාරු කරන්න"</string>
     <string name="adjust_brightness" msgid="980039329808178246">"දීප්තිය සීරුමාරු කරන්න"</string>
-    <string name="night_mode_disclaimer" msgid="3297928749219711334">"සැකසීම් සහ දැනුම්දීම් වැනි, සාමාන්‍යයෙන් ලා පැහැ තේමාවක සංදර්ශනය වන Android OS හි මූලික ප්‍රදේශවලට අඳුරු තේමාව යෙදේ."</string>
+    <string name="night_mode_disclaimer" msgid="598914896926759578">"සැකසීම් වැනි, සාමාන්‍යයෙන් ලා පැහැ තේමාවක සංදර්ශනය වන Android OS හි මූලික ප්‍රදේශවලට අඳුරු තේමාව යෙදේ."</string>
     <string name="color_apply" msgid="9212602012641034283">"යොදන්න"</string>
     <string name="color_revert_title" msgid="4746666545480534663">"සැකසීම් තහවුරු කරන්න"</string>
     <string name="color_revert_message" msgid="9116001069397996691">"සමහර වර්ණ සැකසීම් මෙම උපාංගය භාවිත කළ නොහැකි තත්ත්වයට පත් කළ හැකිය. මෙම වර්ණ සැකසීම් තහවුරු කිරීමට හරි ක්ලික් කරන්න, නැතහොත් මෙම සැකසීම් තත්පර 10කට පසුව යළි සකසනු ඇත."</string>
@@ -531,8 +544,14 @@
     <item msgid="3830170141562534721">"මෙම නිරූපකය නොපෙන්වන්න"</item>
   </string-array>
   <string-array name="battery_options">
-    <item msgid="3160236755818672034">"සෑම විටම ප්රතිශතය පෙන්වන්න"</item>
+    <item msgid="3160236755818672034">"සෑම විටම ප්‍රතිශතය පෙන්වන්න"</item>
     <item msgid="2139628951880142927">"ආරෝපණය වන විට ප්‍රතිශතය පෙන්වන්න (පෙරනිමි)"</item>
     <item msgid="3327323682209964956">"මෙම නිරූපකය නොපෙන්වන්න"</item>
   </string-array>
+    <string name="other" msgid="4060683095962566764">"වෙනත්"</string>
+    <string name="accessibility_divider" msgid="5903423481953635044">"බෙදුම්-තිර වෙන්කරණය"</string>
+    <string name="accessibility_action_divider_move_down" msgid="704893304141890042">"පහළට ගෙන යන්න"</string>
+    <string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"ඉහළට ගෙන යන්න"</string>
+    <string name="accessibility_action_divider_move_left" msgid="9218189832115847253">"වමට ගෙන යන්න"</string>
+    <string name="accessibility_action_divider_move_right" msgid="4671522715182567972">"දකුණට ගෙන යන්න"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-si-rLK/strings_tv.xml b/packages/SystemUI/res/values-si-rLK/strings_tv.xml
new file mode 100644
index 0000000..b2c6485
--- /dev/null
+++ b/packages/SystemUI/res/values-si-rLK/strings_tv.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.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="pip_close" msgid="3480680679023423574">"PIP වසන්න"</string>
+    <string name="pip_fullscreen" msgid="8604643018538487816">"සම්පූර්ණ තිරය"</string>
+    <string name="pip_play" msgid="674145557658227044">"ධාවනය කරන්න"</string>
+    <string name="pip_pause" msgid="8412075640017218862">"විරාමය"</string>
+    <string name="pip_hold_home" msgid="340086535668778109">"PIP පාලනයට "<b>"HOME"</b>" අල්ලාගන්න"</string>
+    <string name="pip_onboarding_description" msgid="2627737116380318292">"PIP පාලනයට HOME\nඔබා අල්ලාගන්න"</string>
+    <string name="pip_onboarding_button" msgid="3957426748484904611">"හරි, තේරුණා"</string>
+</resources>
diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml
index 8930038..c075980 100644
--- a/packages/SystemUI/res/values-sk/strings.xml
+++ b/packages/SystemUI/res/values-sk/strings.xml
@@ -75,7 +75,8 @@
     <string name="screenshot_saved_title" msgid="6461865960961414961">"Snímka obrazovky bola zaznamenaná."</string>
     <string name="screenshot_saved_text" msgid="1152839647677558815">"Snímku obrazovky zobrazíte dotykom."</string>
     <string name="screenshot_failed_title" msgid="705781116746922771">"Snímku obrazovky sa nepodarilo zachytiť."</string>
-    <string name="screenshot_failed_text" msgid="1260203058661337274">"Nie je možné vytvoriť viac sním. obraz. pre obmedz. úlož. priestor alebo to nie je povolené apl. či vašou organiz."</string>
+    <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Snímku obrazovky nie je možné vytvoriť z dôvodu nedostatku miesta v úložisku."</string>
+    <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Vytváranie snímok obrazovky je zakázané aplikáciou alebo vašou organizáciou."</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"Možnosti prenosu súborov USB"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Pripojiť ako prehrávač médií (MTP)"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"Pripojiť ako fotoaparát (PTP)"</string>
@@ -208,6 +209,7 @@
     <string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"Dlhší čas"</string>
     <string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"Kratší čas"</string>
     <string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"Svietidlo je vypnuté."</string>
+    <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"Svietidlo nie je k dispozícii."</string>
     <string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"Svietidlo je zapnuté."</string>
     <string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"Svietidlo je vypnuté."</string>
     <string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"Svietidlo je zapnuté."</string>
@@ -220,6 +222,10 @@
     <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"Pracovný režim – zap."</string>
     <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"Pracovný režim je vypnutý."</string>
     <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"Pracovný režim je zapnutý."</string>
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_off (650231949881093289) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_on (4218725402373934151) -->
+    <skip />
     <string name="accessibility_brightness" msgid="8003681285547803095">"Jas displeja"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"Dátové prenosy 2G a 3G sú pozastavené"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"Dátové prenosy 4G sú pozastavené"</string>
@@ -306,6 +312,8 @@
     <string name="recents_launch_disabled_message" msgid="1624523193008871793">"Aplikácia <xliff:g id="APP">%s</xliff:g> je v núdzovom režime zakázaná."</string>
     <string name="recents_history_button_label" msgid="5153358867807604821">"História"</string>
     <string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"Vymazať"</string>
+    <string name="recents_drag_non_dockable_task_message" msgid="2935843902795166158">"Táto aplikácia nepodporuje režim viacerých okien"</string>
+    <string name="recents_launch_non_dockable_task_label" msgid="7862379814938391888">"Aplikácia nepodporuje režim viacerých okien"</string>
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Rozdeliť vodorovné"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Rozdeliť zvislé"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Rozdeliť vlastné"</string>
@@ -453,18 +461,23 @@
     <string name="enable_bluetooth_title" msgid="5027037706500635269">"Zapnúť Bluetooth?"</string>
     <string name="enable_bluetooth_message" msgid="9106595990708985385">"Ak chcete klávesnicu pripojiť k tabletu, najprv musíte zapnúť Bluetooth."</string>
     <string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"Zapnúť"</string>
-    <string name="apply_to_topic" msgid="3641403489318659666">"Použiť na upozornenia týkajúce sa témy <xliff:g id="TOPIC_NAME">%1$s</xliff:g>"</string>
-    <string name="apply_to_app" msgid="363016783939815960">"Použiť na všetky upozornenia z tejto aplikácie"</string>
+    <string name="show_silently" msgid="6841966539811264192">"Zobrazovať upozornenia bez zvukového signálu"</string>
+    <string name="block" msgid="2734508760962682611">"Blokovať všetky upozornenia"</string>
+    <string name="do_not_silence" msgid="6878060322594892441">"Nestíšiť"</string>
+    <string name="do_not_silence_block" msgid="4070647971382232311">"Nestíšiť ani neblokovať"</string>
+    <string name="tuner_full_importance_settings" msgid="8103289238676424226">"Zobraziť nastavenia vysokej dôležitosti"</string>
     <string name="blocked_importance" msgid="5198578988978234161">"Zablokované"</string>
+    <string name="min_importance" msgid="1901894910809414782">"Minimálna dôležitosť"</string>
     <string name="low_importance" msgid="4109929986107147930">"Nízka dôležitosť"</string>
     <string name="default_importance" msgid="8192107689995742653">"Normálna dôležitosť"</string>
     <string name="high_importance" msgid="1527066195614050263">"Vysoká dôležitosť"</string>
     <string name="max_importance" msgid="5089005872719563894">"Neodkladná dôležitosť"</string>
     <string name="notification_importance_blocked" msgid="2397192642657872872">"Tieto upozornenia nikdy nezobrazovať"</string>
-    <string name="notification_importance_low" msgid="4383563267370859725">"Zobrazovať v dolnej časti zoznamu upozornení bez zvukového signálu"</string>
-    <string name="notification_importance_default" msgid="4926529615920610817">"Tieto upozornenia zobrazovať bez zvukového signálu"</string>
-    <string name="notification_importance_high" msgid="3222680136612408223">"Zobrazovať v hornej časti zoznamu upozornení so zvukovým signálom"</string>
-    <string name="notification_importance_max" msgid="5236987171904756134">"Zobrazovať cez obrazovku so zvukovým signálom"</string>
+    <string name="notification_importance_min" msgid="1938190340516905748">"Zobrazovať v dolnej časti zoznamu upozornení bez zvukového signálu"</string>
+    <string name="notification_importance_low" msgid="3657252049508213048">"Tieto upozornenia zobrazovať bez zvukového signálu"</string>
+    <string name="notification_importance_default" msgid="4466466472622442175">"Umožniť týmto upozorneniam vydávať zvukové signály"</string>
+    <string name="notification_importance_high" msgid="2135428926525093825">"Zobrazovať cez obrazovku a povoliť zvukový signál"</string>
+    <string name="notification_importance_max" msgid="5806278962376556491">"Zobrazovať v hornej časti zoznamu upozornení, zobrazovať cez obrazovku a povoliť zvukový signál"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"Ďalšie nastavenia"</string>
     <string name="notification_done" msgid="5279426047273930175">"Hotovo"</string>
     <string name="color_and_appearance" msgid="1254323855964993144">"Farba a vzhľad"</string>
@@ -478,7 +491,7 @@
     <string name="use_dark_theme" msgid="2900938704964299312">"Použiť tmavý motív pre systém Android OS"</string>
     <string name="adjust_tint" msgid="3398569573231409878">"Upraviť tónovanie"</string>
     <string name="adjust_brightness" msgid="980039329808178246">"Upraviť jas"</string>
-    <string name="night_mode_disclaimer" msgid="3297928749219711334">"V hlavných oblastiach systému Android OS (ako sú Nastavenia a upozornenia), ktoré sú obyčajne zobrazené v svetlom motíve, je použitý tmavý motív."</string>
+    <string name="night_mode_disclaimer" msgid="598914896926759578">"V hlavných oblastiach systému Android OS (ako sú Nastavenia), ktoré sú obyčajne zobrazené vo svetlom motíve, je použitý tmavý motív."</string>
     <string name="color_apply" msgid="9212602012641034283">"Použiť"</string>
     <string name="color_revert_title" msgid="4746666545480534663">"Potvrdenie nastavení"</string>
     <string name="color_revert_message" msgid="9116001069397996691">"Niektoré nastavenia farieb môžu toto zariadenie znefunkčniť. Tieto nastavenia farieb potvrdíte kliknutím na tlačidlo OK, ináč sa tieto nastavenia o 10 sekúnd obnovia."</string>
@@ -537,4 +550,10 @@
     <item msgid="2139628951880142927">"Zobrazovať percentá počas nabíjania (predvolené)"</item>
     <item msgid="3327323682209964956">"Nezobrazovať túto ikonu"</item>
   </string-array>
+    <string name="other" msgid="4060683095962566764">"Ďalšie"</string>
+    <string name="accessibility_divider" msgid="5903423481953635044">"Rozdeľovač obrazovky"</string>
+    <string name="accessibility_action_divider_move_down" msgid="704893304141890042">"Posunúť nadol"</string>
+    <string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"Posunúť nahor"</string>
+    <string name="accessibility_action_divider_move_left" msgid="9218189832115847253">"Posunúť doľava"</string>
+    <string name="accessibility_action_divider_move_right" msgid="4671522715182567972">"Posunúť doprava"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-sk/strings_tv.xml b/packages/SystemUI/res/values-sk/strings_tv.xml
new file mode 100644
index 0000000..46f88f9
--- /dev/null
+++ b/packages/SystemUI/res/values-sk/strings_tv.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.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="pip_close" msgid="3480680679023423574">"Zavrieť režim PIP"</string>
+    <string name="pip_fullscreen" msgid="8604643018538487816">"Celá obrazovka"</string>
+    <string name="pip_play" msgid="674145557658227044">"Prehrať"</string>
+    <string name="pip_pause" msgid="8412075640017218862">"Pozastaviť"</string>
+    <string name="pip_hold_home" msgid="340086535668778109">"Režim PIP ovládajte pomocou tlačidla "<b>"PLOCHA"</b></string>
+    <string name="pip_onboarding_description" msgid="2627737116380318292">"Režim PIP ovládajte stlačením a podržaním tlačidla PLOCHA\n"</string>
+    <string name="pip_onboarding_button" msgid="3957426748484904611">"Dobre"</string>
+</resources>
diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml
index 089cd4f..8aa79be 100644
--- a/packages/SystemUI/res/values-sl/strings.xml
+++ b/packages/SystemUI/res/values-sl/strings.xml
@@ -75,7 +75,8 @@
     <string name="screenshot_saved_title" msgid="6461865960961414961">"Posnetek zaslona je shranjen."</string>
     <string name="screenshot_saved_text" msgid="1152839647677558815">"Dotaknite se, če si želite ogledati posnetek zaslona."</string>
     <string name="screenshot_failed_title" msgid="705781116746922771">"Posnetka zaslona ni bilo mogoče shraniti."</string>
-    <string name="screenshot_failed_text" msgid="1260203058661337274">"Izdelava posnetka zaslona ni mogoča zaradi omejenega prostora za shranjevanje ali pa tega ne dovoli aplikacija ali vaša organizacija."</string>
+    <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Shranjevanje posnetka zaslona ni mogoče zaradi omejenega prostora za shranjevanje."</string>
+    <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Aplikacija ali organizacija ne dovoljuje posnetkov zaslona."</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"Možnosti prenosa datotek prek USB-ja"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Vpni kot predvajalnik (MTP)"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"Vpni kot fotoaparat (PTP)"</string>
@@ -208,6 +209,7 @@
     <string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"Daljši čas."</string>
     <string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"Krajši čas."</string>
     <string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"Svetilka je izklopljena."</string>
+    <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"Svetilka ni na voljo."</string>
     <string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"Svetilka je vklopljena."</string>
     <string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"Svetilka je izklopljena."</string>
     <string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"Svetilka je vklopljena."</string>
@@ -220,6 +222,10 @@
     <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"Način za delo vklopljen."</string>
     <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"Način za delo je izklopljen."</string>
     <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"Način za delo je vklopljen."</string>
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_off (650231949881093289) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_on (4218725402373934151) -->
+    <skip />
     <string name="accessibility_brightness" msgid="8003681285547803095">"Svetlost zaslona"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"Prenos podatkov v omrežju 2G/3G je zaustavljen"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"Prenos podatkov v omrežju 4G je zaustavljen"</string>
@@ -306,6 +312,8 @@
     <string name="recents_launch_disabled_message" msgid="1624523193008871793">"Aplikacija <xliff:g id="APP">%s</xliff:g> je v varnem načinu onemogočena."</string>
     <string name="recents_history_button_label" msgid="5153358867807604821">"Zgodovina"</string>
     <string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"Izbriši"</string>
+    <string name="recents_drag_non_dockable_task_message" msgid="2935843902795166158">"Ta aplikacija ne podpira načina z več okni"</string>
+    <string name="recents_launch_non_dockable_task_label" msgid="7862379814938391888">"Aplikacija ne podpira načina z več okni"</string>
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Razdeli vodoravno"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Razdeli navpično"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Razdeli po meri"</string>
@@ -453,18 +461,23 @@
     <string name="enable_bluetooth_title" msgid="5027037706500635269">"Želite vklopiti Bluetooth?"</string>
     <string name="enable_bluetooth_message" msgid="9106595990708985385">"Če želite povezati tipkovnico in tablični računalnik, vklopite Bluetooth."</string>
     <string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"Vklop"</string>
-    <string name="apply_to_topic" msgid="3641403489318659666">"Uporabi za obvestila za temo <xliff:g id="TOPIC_NAME">%1$s</xliff:g>"</string>
-    <string name="apply_to_app" msgid="363016783939815960">"Uporabi za vsa obvestila za to aplikacijo"</string>
+    <string name="show_silently" msgid="6841966539811264192">"Prikaži obvestila brez zvoka"</string>
+    <string name="block" msgid="2734508760962682611">"Blokiraj vsa obvestila"</string>
+    <string name="do_not_silence" msgid="6878060322594892441">"Ne utišaj"</string>
+    <string name="do_not_silence_block" msgid="4070647971382232311">"Ne utišaj ali blokiraj"</string>
+    <string name="tuner_full_importance_settings" msgid="8103289238676424226">"Prikaz celotnih nastavitev za pomembnost"</string>
     <string name="blocked_importance" msgid="5198578988978234161">"Blokirano"</string>
+    <string name="min_importance" msgid="1901894910809414782">"Najmanjša pomembnost"</string>
     <string name="low_importance" msgid="4109929986107147930">"Nizka pomembnost"</string>
     <string name="default_importance" msgid="8192107689995742653">"Običajna pomembnost"</string>
     <string name="high_importance" msgid="1527066195614050263">"Visoka pomembnost"</string>
     <string name="max_importance" msgid="5089005872719563894">"Nujna pomembnost"</string>
     <string name="notification_importance_blocked" msgid="2397192642657872872">"Nikoli ne prikaži teh obvestil"</string>
-    <string name="notification_importance_low" msgid="4383563267370859725">"Prikaži na dnu seznama obvestil brez zvoka"</string>
-    <string name="notification_importance_default" msgid="4926529615920610817">"Prikaži ta obvestila brez zvoka"</string>
-    <string name="notification_importance_high" msgid="3222680136612408223">"Prikaži na vrhu seznama obvestil in predvajaj zvok"</string>
-    <string name="notification_importance_max" msgid="5236987171904756134">"Za hip pokaži predogled na zaslonu in predvajaj zvok"</string>
+    <string name="notification_importance_min" msgid="1938190340516905748">"Prikaži na dnu seznama obvestil brez zvoka"</string>
+    <string name="notification_importance_low" msgid="3657252049508213048">"Prikaži ta obvestila brez zvoka"</string>
+    <string name="notification_importance_default" msgid="4466466472622442175">"Dovoli zvoke za ta obvestila"</string>
+    <string name="notification_importance_high" msgid="2135428926525093825">"Za hip pokaži predogled na zaslonu in dovoli zvok"</string>
+    <string name="notification_importance_max" msgid="5806278962376556491">"Prikaži na vrhu seznama obvestil, za hip pokaži predogled na zaslonu in dovoli zvok"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"Več nastavitev"</string>
     <string name="notification_done" msgid="5279426047273930175">"Dokončano"</string>
     <string name="color_and_appearance" msgid="1254323855964993144">"Barva in videz"</string>
@@ -478,7 +491,7 @@
     <string name="use_dark_theme" msgid="2900938704964299312">"Uporaba temne teme za sistem Android"</string>
     <string name="adjust_tint" msgid="3398569573231409878">"Prilagodi odtenek"</string>
     <string name="adjust_brightness" msgid="980039329808178246">"Prilagodi svetlost"</string>
-    <string name="night_mode_disclaimer" msgid="3297928749219711334">"Za osrednja področja sistema Android, ki so običajno prikazana v svetli temi, na primer nastavitve in obvestila, je uporabljena temna tema."</string>
+    <string name="night_mode_disclaimer" msgid="598914896926759578">"Za osrednja področja sistema Android, ki so običajno prikazana v svetli temi, na primer nastavitve, je uporabljena temna tema."</string>
     <string name="color_apply" msgid="9212602012641034283">"Uporabi"</string>
     <string name="color_revert_title" msgid="4746666545480534663">"Potrditev nastavitev"</string>
     <string name="color_revert_message" msgid="9116001069397996691">"Zaradi nekaterih barvnih nastavitev lahko postane ta naprava neuporabna. Kliknite »V redu«, če želite potrditi te barvne nastavitve. V nasprotnem primeru se bodo čez 10 sekund ponastavile na prvotno vrednost."</string>
@@ -491,7 +504,7 @@
     <string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"Nedavni"</string>
     <string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"Nazaj"</string>
     <string name="tuner_full_zen_title" msgid="4540823317772234308">"Prikaži s kontrolniki glasnosti"</string>
-    <string name="volume_and_do_not_disturb" msgid="3373784330208603030">"ne moti"</string>
+    <string name="volume_and_do_not_disturb" msgid="3373784330208603030">"Ne moti"</string>
     <string name="volume_dnd_silent" msgid="4363882330723050727">"Bližnjica z gumboma za glasnost"</string>
     <string name="volume_up_silent" msgid="7141255269783588286">"Zapustitev načina »ne moti« pri povečanju glasnosti"</string>
     <string name="battery" msgid="7498329822413202973">"Akumulator"</string>
@@ -537,4 +550,10 @@
     <item msgid="2139628951880142927">"Prikaži odstotek med polnjenjem (privzeto)"</item>
     <item msgid="3327323682209964956">"Ne prikaži te ikone"</item>
   </string-array>
+    <string name="other" msgid="4060683095962566764">"Drugo"</string>
+    <string name="accessibility_divider" msgid="5903423481953635044">"Razdelilnik zaslonov"</string>
+    <string name="accessibility_action_divider_move_down" msgid="704893304141890042">"Premakni navzdol"</string>
+    <string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"Premakni navzgor"</string>
+    <string name="accessibility_action_divider_move_left" msgid="9218189832115847253">"Premakni levo"</string>
+    <string name="accessibility_action_divider_move_right" msgid="4671522715182567972">"Premakni desno"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-sl/strings_tv.xml b/packages/SystemUI/res/values-sl/strings_tv.xml
new file mode 100644
index 0000000..9fab6e1
--- /dev/null
+++ b/packages/SystemUI/res/values-sl/strings_tv.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2016, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <!-- no translation found for pip_close (3480680679023423574) -->
+    <skip />
+    <string name="pip_fullscreen" msgid="8604643018538487816">"Celozaslonsko"</string>
+    <string name="pip_play" msgid="674145557658227044">"Predvajanje"</string>
+    <string name="pip_pause" msgid="8412075640017218862">"Zaustavitev"</string>
+    <!-- no translation found for pip_hold_home (340086535668778109) -->
+    <skip />
+    <!-- no translation found for pip_onboarding_description (2627737116380318292) -->
+    <skip />
+    <!-- no translation found for pip_onboarding_button (3957426748484904611) -->
+    <skip />
+</resources>
diff --git a/packages/SystemUI/res/values-sq-rAL/strings.xml b/packages/SystemUI/res/values-sq-rAL/strings.xml
index 3e1df4d..8314044 100644
--- a/packages/SystemUI/res/values-sq-rAL/strings.xml
+++ b/packages/SystemUI/res/values-sq-rAL/strings.xml
@@ -73,7 +73,8 @@
     <string name="screenshot_saved_title" msgid="6461865960961414961">"Pamja e ekranit u kap."</string>
     <string name="screenshot_saved_text" msgid="1152839647677558815">"Prek për të parë pamjen e ekranit tënd."</string>
     <string name="screenshot_failed_title" msgid="705781116746922771">"Nuk mundi të kapte pamjen e ekranit."</string>
-    <string name="screenshot_failed_text" msgid="1260203058661337274">"Nuk pranon pamje ekrani për shkak të hapësirës së kufizuar ruajtëse, ose një gjë e tillë nuk lejohet nga aplikacioni apo organizata jote."</string>
+    <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Pamja e ekranit nuk mund të ruhet për shkak të hapësirës ruajtëse të kufizuar."</string>
+    <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Nxjerrja e pamjeve të ekranit nuk lejohet nga aplikacioni ose organizata jote."</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"Opsionet e transferimit të dosjeve të USB-së"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Lidh si një lexues \"media\" (MTP)"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"Montoje si kamerë (PTP)"</string>
@@ -206,6 +207,7 @@
     <string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"Më shumë kohë."</string>
     <string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"Më pak kohë."</string>
     <string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"Elektriku është i çaktivizuar."</string>
+    <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"Blici është i padisponueshëm"</string>
     <string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"Elektriku u aktivizua."</string>
     <string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"Elektriku u çaktivizua."</string>
     <string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"Elektriku është i aktivizuar."</string>
@@ -218,6 +220,10 @@
     <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"Modaliteti i punës është i aktivizuar."</string>
     <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"Modaliteti i punës është i çaktivizuar."</string>
     <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"Modaliteti i punës është i aktivizuar."</string>
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_off (650231949881093289) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_on (4218725402373934151) -->
+    <skip />
     <string name="accessibility_brightness" msgid="8003681285547803095">"Ndriçimi i ekranit"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"Të dhënat 2G-3G janë ndërprerë"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"Të dhënat 4G janë ndërprerë"</string>
@@ -304,6 +310,8 @@
     <string name="recents_launch_disabled_message" msgid="1624523193008871793">"<xliff:g id="APP">%s</xliff:g> është i çaktivizuar në modalitetin e sigurt."</string>
     <string name="recents_history_button_label" msgid="5153358867807604821">"Historiku"</string>
     <string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"Pastro"</string>
+    <string name="recents_drag_non_dockable_task_message" msgid="2935843902795166158">"Ky aplikacion nuk e mbështet modalitetin me shumë dritare"</string>
+    <string name="recents_launch_non_dockable_task_label" msgid="7862379814938391888">"Aplikacioni nuk e mbështet modalitetin me shumë dritare"</string>
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Ndaje horizontalisht"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Ndaj vertikalisht"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Ndaj të personalizuarën"</string>
@@ -451,18 +459,23 @@
     <string name="enable_bluetooth_title" msgid="5027037706500635269">"Të aktivizohet \"bluetooth-i\"?"</string>
     <string name="enable_bluetooth_message" msgid="9106595990708985385">"Për të lidhur tastierën me tabletin, në fillim duhet të aktivizosh \"bluetooth-in\"."</string>
     <string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"Aktivizo"</string>
-    <string name="apply_to_topic" msgid="3641403489318659666">"Zbatoje për njoftimet nga <xliff:g id="TOPIC_NAME">%1$s</xliff:g>"</string>
-    <string name="apply_to_app" msgid="363016783939815960">"Zbatoje për të gjitha njoftimet nga ky aplikacion"</string>
+    <string name="show_silently" msgid="6841966539811264192">"Shfaqi njoftimet në heshtje"</string>
+    <string name="block" msgid="2734508760962682611">"Blloko të gjitha njoftimet"</string>
+    <string name="do_not_silence" msgid="6878060322594892441">"Mos e vendos në heshtje"</string>
+    <string name="do_not_silence_block" msgid="4070647971382232311">"Mos e vendos në heshtje ose mos e blloko"</string>
+    <string name="tuner_full_importance_settings" msgid="8103289238676424226">"Shfaq cilësimet e plota të rëndësisë"</string>
     <string name="blocked_importance" msgid="5198578988978234161">"I bllokuar"</string>
+    <string name="min_importance" msgid="1901894910809414782">"Rëndësi minimale"</string>
     <string name="low_importance" msgid="4109929986107147930">"Rëndësi e ulët"</string>
     <string name="default_importance" msgid="8192107689995742653">"Rëndësi normale"</string>
     <string name="high_importance" msgid="1527066195614050263">"Rëndësi e lartë"</string>
     <string name="max_importance" msgid="5089005872719563894">"Rëndësi urgjente"</string>
     <string name="notification_importance_blocked" msgid="2397192642657872872">"Mos i shfaq asnjëherë këto njoftime"</string>
-    <string name="notification_importance_low" msgid="4383563267370859725">"Shfaqi në heshtje në fund të listës së njoftimeve"</string>
-    <string name="notification_importance_default" msgid="4926529615920610817">"Shfaqi këto njoftime në heshtje"</string>
-    <string name="notification_importance_high" msgid="3222680136612408223">"Shfaqi në krye të listës së njoftimeve dhe lësho tingull"</string>
-    <string name="notification_importance_max" msgid="5236987171904756134">"Shfaq një vështrim të shpejtë në ekran dhe lësho tingull"</string>
+    <string name="notification_importance_min" msgid="1938190340516905748">"Shfaqi në heshtje në fund të listës së njoftimeve"</string>
+    <string name="notification_importance_low" msgid="3657252049508213048">"Shfaqi këto njoftime në heshtje"</string>
+    <string name="notification_importance_default" msgid="4466466472622442175">"Lejoji këto njoftime të nxjerrin tinguj"</string>
+    <string name="notification_importance_high" msgid="2135428926525093825">"Shfaq një vështrim të shpejtë në ekran dhe lësho një tingull"</string>
+    <string name="notification_importance_max" msgid="5806278962376556491">"Shfaqi në krye të listës së njoftimeve, shfaq vështrim të shpejtë në ekran dhe lësho një tingull"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"Cilësime të tjera"</string>
     <string name="notification_done" msgid="5279426047273930175">"U krye"</string>
     <string name="color_and_appearance" msgid="1254323855964993144">"Ngjyra dhe pamja"</string>
@@ -476,7 +489,7 @@
     <string name="use_dark_theme" msgid="2900938704964299312">"Përdor temën e errët për Android OS"</string>
     <string name="adjust_tint" msgid="3398569573231409878">"Rregullo nuancën"</string>
     <string name="adjust_brightness" msgid="980039329808178246">"Rregullo ndriçimin"</string>
-    <string name="night_mode_disclaimer" msgid="3297928749219711334">"Tema e errët është aplikuar në fushat kryesore të Android OS që shfaqen zakonisht në një temë të çelur, siç janë \"Cilësimet\" dhe njoftimet."</string>
+    <string name="night_mode_disclaimer" msgid="598914896926759578">"Tema e errët zbatohet në zonat kryesore të Android OS që shfaqen zakonisht në një temë të çelur, siç janë \"Cilësimet\"."</string>
     <string name="color_apply" msgid="9212602012641034283">"Zbato"</string>
     <string name="color_revert_title" msgid="4746666545480534663">"Konfirmo cilësimet"</string>
     <string name="color_revert_message" msgid="9116001069397996691">"Disa cilësime ngjyrash mund ta bëjnë këtë pajisje të papërdorshme. Kliko OK për të konfirmuar këto cilësime ngjyrash, përndryshe këto cilësime do të rivendosen pas 10 sekondash."</string>
@@ -535,4 +548,10 @@
     <item msgid="2139628951880142927">"Shfaq përqindjen gjatë ngarkimit (e parazgjedhur)"</item>
     <item msgid="3327323682209964956">"Mos e shfaq këtë ikonë"</item>
   </string-array>
+    <string name="other" msgid="4060683095962566764">"Të tjera"</string>
+    <string name="accessibility_divider" msgid="5903423481953635044">"Ndarësi i ekranit të ndarë"</string>
+    <string name="accessibility_action_divider_move_down" msgid="704893304141890042">"Lëviz poshtë"</string>
+    <string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"Lëviz lart"</string>
+    <string name="accessibility_action_divider_move_left" msgid="9218189832115847253">"Lëviz majtas"</string>
+    <string name="accessibility_action_divider_move_right" msgid="4671522715182567972">"Lëviz djathtas"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-sq-rAL/strings_tv.xml b/packages/SystemUI/res/values-sq-rAL/strings_tv.xml
new file mode 100644
index 0000000..10cf2f9
--- /dev/null
+++ b/packages/SystemUI/res/values-sq-rAL/strings_tv.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2016, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <!-- no translation found for pip_close (3480680679023423574) -->
+    <skip />
+    <string name="pip_fullscreen" msgid="8604643018538487816">"Ekrani i plotë"</string>
+    <string name="pip_play" msgid="674145557658227044">"Luaj"</string>
+    <string name="pip_pause" msgid="8412075640017218862">"Pauzë"</string>
+    <!-- no translation found for pip_hold_home (340086535668778109) -->
+    <skip />
+    <!-- no translation found for pip_onboarding_description (2627737116380318292) -->
+    <skip />
+    <!-- no translation found for pip_onboarding_button (3957426748484904611) -->
+    <skip />
+</resources>
diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml
index f603a50..318a92a 100644
--- a/packages/SystemUI/res/values-sr/strings.xml
+++ b/packages/SystemUI/res/values-sr/strings.xml
@@ -74,7 +74,8 @@
     <string name="screenshot_saved_title" msgid="6461865960961414961">"Снимак екрана је направљен."</string>
     <string name="screenshot_saved_text" msgid="1152839647677558815">"Додирните да бисте видели снимак екрана."</string>
     <string name="screenshot_failed_title" msgid="705781116746922771">"Није могуће направити снимак екрана."</string>
-    <string name="screenshot_failed_text" msgid="1260203058661337274">"Није могуће снимити екран због недовољне меморије или то не дозвољава апликација или организација."</string>
+    <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Чување снимка екрана није успело због ограниченог меморијског простора."</string>
+    <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Апликација или организација не дозвољавају прављење снимака екрана."</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"Опције USB преноса датотека"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Прикључи као медија плејер (MTP)"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"Прикључи као камеру (PTP)"</string>
@@ -207,6 +208,7 @@
     <string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"Више времена."</string>
     <string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"Мање времена."</string>
     <string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"Батеријска лампа је искључена."</string>
+    <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"Лампа није доступна."</string>
     <string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"Батеријска лампа је укључена."</string>
     <string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"Батеријска лампа је искључена."</string>
     <string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"Батеријска лампа је укључена."</string>
@@ -219,6 +221,10 @@
     <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"Режим рада је укључен."</string>
     <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"Режим рада је искључен."</string>
     <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"Режим рада је укључен."</string>
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_off (650231949881093289) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_on (4218725402373934151) -->
+    <skip />
     <string name="accessibility_brightness" msgid="8003681285547803095">"Осветљеност екрана"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"2G–3G подаци су паузирани"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"4G подаци су паузирани"</string>
@@ -305,6 +311,8 @@
     <string name="recents_launch_disabled_message" msgid="1624523193008871793">"Апликација <xliff:g id="APP">%s</xliff:g> је онемогућена у безбедном режиму."</string>
     <string name="recents_history_button_label" msgid="5153358867807604821">"Историја"</string>
     <string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"Обриши"</string>
+    <string name="recents_drag_non_dockable_task_message" msgid="2935843902795166158">"Ова апликација не подржава режим са више прозора"</string>
+    <string name="recents_launch_non_dockable_task_label" msgid="7862379814938391888">"Апликација не подржава режим са више прозора"</string>
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Подели хоризонтално"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Подели вертикално"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Прилагођено дељење"</string>
@@ -452,18 +460,23 @@
     <string name="enable_bluetooth_title" msgid="5027037706500635269">"Желите ли да укључите Bluetooth?"</string>
     <string name="enable_bluetooth_message" msgid="9106595990708985385">"Да бисте повезали тастатуру са таблетом, прво морате да укључите Bluetooth."</string>
     <string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"Укључи"</string>
-    <string name="apply_to_topic" msgid="3641403489318659666">"Примени на обавештења о теми <xliff:g id="TOPIC_NAME">%1$s</xliff:g>"</string>
-    <string name="apply_to_app" msgid="363016783939815960">"Примени на сва обавештења из ове апликације"</string>
+    <string name="show_silently" msgid="6841966539811264192">"Приказуј обавештења без звука"</string>
+    <string name="block" msgid="2734508760962682611">"Блокирај сва обавештења"</string>
+    <string name="do_not_silence" msgid="6878060322594892441">"Не искључуј звук"</string>
+    <string name="do_not_silence_block" msgid="4070647971382232311">"Не искључују звук нити блокирај"</string>
+    <string name="tuner_full_importance_settings" msgid="8103289238676424226">"Прикажи комплетна подешавања важности"</string>
     <string name="blocked_importance" msgid="5198578988978234161">"Блокирана"</string>
+    <string name="min_importance" msgid="1901894910809414782">"Веома мала важност"</string>
     <string name="low_importance" msgid="4109929986107147930">"Мала важност"</string>
     <string name="default_importance" msgid="8192107689995742653">"Уобичајена важност"</string>
     <string name="high_importance" msgid="1527066195614050263">"Велика важност"</string>
     <string name="max_importance" msgid="5089005872719563894">"Важност: хитно"</string>
     <string name="notification_importance_blocked" msgid="2397192642657872872">"Ова обавештења се никада не приказују"</string>
-    <string name="notification_importance_low" msgid="4383563267370859725">"Приказују се у дну листе обавештења без звука"</string>
-    <string name="notification_importance_default" msgid="4926529615920610817">"Ова обавештења се приказују без звука"</string>
-    <string name="notification_importance_high" msgid="3222680136612408223">"Приказују се у врху листе обавештења и емитује се звук"</string>
-    <string name="notification_importance_max" msgid="5236987171904756134">"Накратко се приказују на екрану и емитује се звук"</string>
+    <string name="notification_importance_min" msgid="1938190340516905748">"Приказују се у дну листе обавештења без звука"</string>
+    <string name="notification_importance_low" msgid="3657252049508213048">"Ова обавештења се приказују без звука"</string>
+    <string name="notification_importance_default" msgid="4466466472622442175">"Дозволите да ова обавештења емитују звук"</string>
+    <string name="notification_importance_high" msgid="2135428926525093825">"Накратко се приказују на екрану и емитују звук"</string>
+    <string name="notification_importance_max" msgid="5806278962376556491">"Приказују се у врху листе обавештења, накратко се приказују на екрану и емитују звук"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"Још подешавања"</string>
     <string name="notification_done" msgid="5279426047273930175">"Готово"</string>
     <string name="color_and_appearance" msgid="1254323855964993144">"Боја и изглед"</string>
@@ -477,7 +490,7 @@
     <string name="use_dark_theme" msgid="2900938704964299312">"Користи тамну тему за Android ОС"</string>
     <string name="adjust_tint" msgid="3398569573231409878">"Прилагоди сенку"</string>
     <string name="adjust_brightness" msgid="980039329808178246">"Прилагоди осветљеност"</string>
-    <string name="night_mode_disclaimer" msgid="3297928749219711334">"Тамна тема се примењује на кључне области Android ОС-а које се обично приказују у светлој теми, као што су подешавања и обавештења."</string>
+    <string name="night_mode_disclaimer" msgid="598914896926759578">"Тамна тема се примењује на кључне делове Android ОС-а који се обично приказују у светлој теми, попут Подешавања."</string>
     <string name="color_apply" msgid="9212602012641034283">"Примени"</string>
     <string name="color_revert_title" msgid="4746666545480534663">"Потврдите подешавања"</string>
     <string name="color_revert_message" msgid="9116001069397996691">"Нека подешавања боја могу да учине уређај неупотребљивим. Кликните на Потврди да бисте потврдили ова подешавања боја, пошто ће се у супротном ова подешавања ресетовати након 10 секунди."</string>
@@ -536,4 +549,10 @@
     <item msgid="2139628951880142927">"Прикажи проценат током пуњења (подразумевано)"</item>
     <item msgid="3327323682209964956">"Не приказуј ову икону"</item>
   </string-array>
+    <string name="other" msgid="4060683095962566764">"Друго"</string>
+    <string name="accessibility_divider" msgid="5903423481953635044">"Разделник подељеног екрана"</string>
+    <string name="accessibility_action_divider_move_down" msgid="704893304141890042">"Помери надоле"</string>
+    <string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"Помери нагоре"</string>
+    <string name="accessibility_action_divider_move_left" msgid="9218189832115847253">"Помери улево"</string>
+    <string name="accessibility_action_divider_move_right" msgid="4671522715182567972">"Помери удесно"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-sr/strings_tv.xml b/packages/SystemUI/res/values-sr/strings_tv.xml
new file mode 100644
index 0000000..4b03b68
--- /dev/null
+++ b/packages/SystemUI/res/values-sr/strings_tv.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.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="pip_close" msgid="3480680679023423574">"Затвори PIP"</string>
+    <string name="pip_fullscreen" msgid="8604643018538487816">"Цео екран"</string>
+    <string name="pip_play" msgid="674145557658227044">"Пусти"</string>
+    <string name="pip_pause" msgid="8412075640017218862">"Паузирај"</string>
+    <string name="pip_hold_home" msgid="340086535668778109"><b>"ПОЧЕТНИ ЕКРАН"</b>" конт. PIP"</string>
+    <string name="pip_onboarding_description" msgid="2627737116380318292">"Притисните и задржите дугме ПОЧЕТНИ ЕКРАН\n да бисте контролисали PIP"</string>
+    <string name="pip_onboarding_button" msgid="3957426748484904611">"Важи"</string>
+</resources>
diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml
index f35024d..a50e744 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -73,7 +73,8 @@
     <string name="screenshot_saved_title" msgid="6461865960961414961">"Skärmdumpen har tagits."</string>
     <string name="screenshot_saved_text" msgid="1152839647677558815">"Tryck här om du vill visa skärmdumpen."</string>
     <string name="screenshot_failed_title" msgid="705781116746922771">"Det gick inte att ta någon skärmdump."</string>
-    <string name="screenshot_failed_text" msgid="1260203058661337274">"Skärmdump misslyckades. Lagringsutrymmet räcker inte eller appen/organisationen tillåter det inte."</string>
+    <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Det går inte att spara skärmdumpen eftersom lagringsutrymmet inte räcker."</string>
+    <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Appen eller organisationen tillåter inte att du tar skärmdumpar."</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"Överföringsalternativ"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Montera som mediaspelare (MTP)"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"Montera som kamera (PTP)"</string>
@@ -206,6 +207,7 @@
     <string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"Längre tid."</string>
     <string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"Kortare tid."</string>
     <string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"Ficklampa av."</string>
+    <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"Ficklampan är inte tillgänglig."</string>
     <string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"Ficklampa på."</string>
     <string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"Ficklampan har inaktiverats."</string>
     <string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"Ficklampan har aktiverats."</string>
@@ -218,6 +220,10 @@
     <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"Arbetsläget aktiverat."</string>
     <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"Arbetsläget har inaktiverats."</string>
     <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"Arbetsläget har aktiverats."</string>
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_off (650231949881093289) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_on (4218725402373934151) -->
+    <skip />
     <string name="accessibility_brightness" msgid="8003681285547803095">"Skärmens ljusstyrka"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"2G- och 3G-data har pausats"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"4G-data har pausats"</string>
@@ -304,6 +310,8 @@
     <string name="recents_launch_disabled_message" msgid="1624523193008871793">"<xliff:g id="APP">%s</xliff:g> är inaktiverad i säkert läge."</string>
     <string name="recents_history_button_label" msgid="5153358867807604821">"Historik"</string>
     <string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"Rensa"</string>
+    <string name="recents_drag_non_dockable_task_message" msgid="2935843902795166158">"Den här appen har inte stöd för flera fönster"</string>
+    <string name="recents_launch_non_dockable_task_label" msgid="7862379814938391888">"Appen har inte stöd för flera fönster"</string>
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Dela horisontellt"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Dela vertikalt"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Dela anpassad"</string>
@@ -451,18 +459,23 @@
     <string name="enable_bluetooth_title" msgid="5027037706500635269">"Vill du aktivera Bluetooth?"</string>
     <string name="enable_bluetooth_message" msgid="9106595990708985385">"Om du vill ansluta tangentbordet till surfplattan måste du först aktivera Bluetooth."</string>
     <string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"Aktivera"</string>
-    <string name="apply_to_topic" msgid="3641403489318659666">"Ändra för alla aviseringar för <xliff:g id="TOPIC_NAME">%1$s</xliff:g>"</string>
-    <string name="apply_to_app" msgid="363016783939815960">"Ändra för alla aviseringar från den här appen"</string>
+    <string name="show_silently" msgid="6841966539811264192">"Visa aviseringar utan ljud"</string>
+    <string name="block" msgid="2734508760962682611">"Blockera alla aviseringar"</string>
+    <string name="do_not_silence" msgid="6878060322594892441">"Stäng inte av ljudet"</string>
+    <string name="do_not_silence_block" msgid="4070647971382232311">"Stäng inte av ljudet och blockera inte"</string>
+    <string name="tuner_full_importance_settings" msgid="8103289238676424226">"Visa alla relevansinställningarna"</string>
     <string name="blocked_importance" msgid="5198578988978234161">"Blockerad"</string>
+    <string name="min_importance" msgid="1901894910809414782">"Oviktig avisering"</string>
     <string name="low_importance" msgid="4109929986107147930">"Oviktig avisering"</string>
     <string name="default_importance" msgid="8192107689995742653">"Vanlig avisering"</string>
     <string name="high_importance" msgid="1527066195614050263">"Viktig avisering"</string>
     <string name="max_importance" msgid="5089005872719563894">"Brådskande avisering"</string>
     <string name="notification_importance_blocked" msgid="2397192642657872872">"Visa aldrig de här aviseringarna"</string>
-    <string name="notification_importance_low" msgid="4383563267370859725">"Visa längst ned på listan, utan ljud"</string>
-    <string name="notification_importance_default" msgid="4926529615920610817">"Visa aviseringarna utan ljud"</string>
-    <string name="notification_importance_high" msgid="3222680136612408223">"Visa högst upp på listan, med ljud"</string>
-    <string name="notification_importance_max" msgid="5236987171904756134">"Visa på skärmen, med ljud"</string>
+    <string name="notification_importance_min" msgid="1938190340516905748">"Visa längst ned i listan, utan ljud"</string>
+    <string name="notification_importance_low" msgid="3657252049508213048">"Visa aviseringarna utan ljud"</string>
+    <string name="notification_importance_default" msgid="4466466472622442175">"Tillåt ljud för de här aviseringarna"</string>
+    <string name="notification_importance_high" msgid="2135428926525093825">"Visa med snabbtitt på skärmen och tillåt ljud"</string>
+    <string name="notification_importance_max" msgid="5806278962376556491">"Visa högst upp i aviseringslistan och med snabbtitt på skärmen samt tillåt ljud"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"Fler inställningar"</string>
     <string name="notification_done" msgid="5279426047273930175">"Klar"</string>
     <string name="color_and_appearance" msgid="1254323855964993144">"Färg och utseende"</string>
@@ -476,7 +489,7 @@
     <string name="use_dark_theme" msgid="2900938704964299312">"Använd mörkt tema för Android OS"</string>
     <string name="adjust_tint" msgid="3398569573231409878">"Justera ton"</string>
     <string name="adjust_brightness" msgid="980039329808178246">"Justera ljusstyrka"</string>
-    <string name="night_mode_disclaimer" msgid="3297928749219711334">"Det mörka temat används på viktiga områden i Android OS som brukar visas med ett ljust tema, t.ex. Inställningar och aviseringar."</string>
+    <string name="night_mode_disclaimer" msgid="598914896926759578">"Det mörka temat används för kärnfunktioner i Android OS som brukar visas med ett ljust tema, t.ex. inställningarna."</string>
     <string name="color_apply" msgid="9212602012641034283">"Verkställ"</string>
     <string name="color_revert_title" msgid="4746666545480534663">"Bekräfta inställningarna"</string>
     <string name="color_revert_message" msgid="9116001069397996691">"Vissa färginställningar kan göra den här enheten oanvändbar. Klicka på OK om du vill bekräfta färginställningarna, annars återställs inställningarna efter 10 sekunder."</string>
@@ -535,4 +548,10 @@
     <item msgid="2139628951880142927">"Visa procent under laddning (standard)"</item>
     <item msgid="3327323682209964956">"Visa inte den här ikonen"</item>
   </string-array>
+    <string name="other" msgid="4060683095962566764">"Annat"</string>
+    <string name="accessibility_divider" msgid="5903423481953635044">"Avdelare för delad skärm"</string>
+    <string name="accessibility_action_divider_move_down" msgid="704893304141890042">"Flytta nedåt"</string>
+    <string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"Flytta uppåt"</string>
+    <string name="accessibility_action_divider_move_left" msgid="9218189832115847253">"Flytta åt vänster"</string>
+    <string name="accessibility_action_divider_move_right" msgid="4671522715182567972">"Flytta åt höger"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-sv/strings_tv.xml b/packages/SystemUI/res/values-sv/strings_tv.xml
new file mode 100644
index 0000000..dc65877
--- /dev/null
+++ b/packages/SystemUI/res/values-sv/strings_tv.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.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="pip_close" msgid="3480680679023423574">"Stäng PIP"</string>
+    <string name="pip_fullscreen" msgid="8604643018538487816">"Helskärm"</string>
+    <string name="pip_play" msgid="674145557658227044">"Spela upp"</string>
+    <string name="pip_pause" msgid="8412075640017218862">"Pausa"</string>
+    <string name="pip_hold_home" msgid="340086535668778109">"Styr PIP med "<b>"startknappen"</b></string>
+    <string name="pip_onboarding_description" msgid="2627737116380318292">"Håll ned startknappen\n för att styra PIP"</string>
+    <string name="pip_onboarding_button" msgid="3957426748484904611">"OK"</string>
+</resources>
diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml
index e5da9e2..2a10259b 100644
--- a/packages/SystemUI/res/values-sw/strings.xml
+++ b/packages/SystemUI/res/values-sw/strings.xml
@@ -73,7 +73,8 @@
     <string name="screenshot_saved_title" msgid="6461865960961414961">"Picha ya skrini imenaswa."</string>
     <string name="screenshot_saved_text" msgid="1152839647677558815">"Gusa ili kuona picha yako ya skrini."</string>
     <string name="screenshot_failed_title" msgid="705781116746922771">"Haikuweza kunasa picha ya skrini"</string>
-    <string name="screenshot_failed_text" msgid="1260203058661337274">"Haiwezi kupiga picha ya skrini kwa sababu nafasi ya hifadhi haitoshi, au hairuhusiwi na programu yako au ya shirika."</string>
+    <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Haina nafasi ya kutosha kuhifadhi picha ya skrini."</string>
+    <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Shirika au programu yako haikuruhusu upige picha za skrini."</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"Machaguo ya uhamisho wa faili la USB"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Angika kama kichezeshi cha midia (MTP)"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"Angika kama kamera (PTP)"</string>
@@ -206,6 +207,7 @@
     <string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"Muda zaidi."</string>
     <string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"Muda kidogo"</string>
     <string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"Tochi imezimwa."</string>
+    <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"Tochi haipatikani."</string>
     <string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"Tochi inawaka."</string>
     <string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"Tochi imezimwa."</string>
     <string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"Tochi imewashwa."</string>
@@ -218,6 +220,10 @@
     <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"Hali ya kazi imewashwa."</string>
     <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"Hali ya kazi imezimwa."</string>
     <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"Hali ya kazi imewashwa."</string>
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_off (650231949881093289) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_on (4218725402373934151) -->
+    <skip />
     <string name="accessibility_brightness" msgid="8003681285547803095">"Ung\'aavu wa skrini"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"Data ya 2G-3G imesitishwa"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"Data ya 4G imesitishwa"</string>
@@ -304,6 +310,8 @@
     <string name="recents_launch_disabled_message" msgid="1624523193008871793">"<xliff:g id="APP">%s</xliff:g> imezimwa katika hali salama."</string>
     <string name="recents_history_button_label" msgid="5153358867807604821">"Historia"</string>
     <string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"Futa"</string>
+    <string name="recents_drag_non_dockable_task_message" msgid="2935843902795166158">"Programu hii haitumiki katika hali ya madirisha mengi"</string>
+    <string name="recents_launch_non_dockable_task_label" msgid="7862379814938391888">"Programu haitumiki katika hali ya madirisha mengi"</string>
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Gawanya Mlalo"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Gawanya Wima"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Maalum Iliyogawanywa"</string>
@@ -451,18 +459,23 @@
     <string name="enable_bluetooth_title" msgid="5027037706500635269">"Je, ungependa kuwasha Bluetooth?"</string>
     <string name="enable_bluetooth_message" msgid="9106595990708985385">"Ili uunganishe Kibodi yako kwenye kompyuta yako kibao, lazima kwanza uwashe Bluetooth."</string>
     <string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"Washa"</string>
-    <string name="apply_to_topic" msgid="3641403489318659666">"Tumia katika arifa za <xliff:g id="TOPIC_NAME">%1$s</xliff:g>"</string>
-    <string name="apply_to_app" msgid="363016783939815960">"Tumia katika arifa zote kutoka programu hii"</string>
+    <string name="show_silently" msgid="6841966539811264192">"Onyesha arifa bila sauti"</string>
+    <string name="block" msgid="2734508760962682611">"Zuia arifa zote"</string>
+    <string name="do_not_silence" msgid="6878060322594892441">"Usinyamazishe"</string>
+    <string name="do_not_silence_block" msgid="4070647971382232311">"Usinyamazishe wala kuzuia"</string>
+    <string name="tuner_full_importance_settings" msgid="8103289238676424226">"Onyesha mipangilio kamili ya umuhimu"</string>
     <string name="blocked_importance" msgid="5198578988978234161">"Amezuiwa"</string>
+    <string name="min_importance" msgid="1901894910809414782">"Umuhimu wa kiwango cha chini"</string>
     <string name="low_importance" msgid="4109929986107147930">"Umuhimu kiwango cha chini"</string>
     <string name="default_importance" msgid="8192107689995742653">"Umuhimu wa kiwango cha kawaida"</string>
     <string name="high_importance" msgid="1527066195614050263">"Umuhimu wa kiwango cha juu"</string>
     <string name="max_importance" msgid="5089005872719563894">"Umuhimu wa hali ya dharura"</string>
     <string name="notification_importance_blocked" msgid="2397192642657872872">"Usionyeshe arifa hizi kamwe"</string>
-    <string name="notification_importance_low" msgid="4383563267370859725">"Onyesha katika sehemu ya chini ya orodha ya arifa bila sauti"</string>
-    <string name="notification_importance_default" msgid="4926529615920610817">"Onyesha arifa hizi bila sauti"</string>
-    <string name="notification_importance_high" msgid="3222680136612408223">"Onyesha katika sehemu ya juu ya orodha ya arifa na itoe sauti"</string>
-    <string name="notification_importance_max" msgid="5236987171904756134">"Weka onyesho la kuchungulia kwenye skrini na itoe sauti"</string>
+    <string name="notification_importance_min" msgid="1938190340516905748">"Onyesha katika sehemu ya chini ya orodha ya arifa bila sauti"</string>
+    <string name="notification_importance_low" msgid="3657252049508213048">"Onyesha arifa hizi bila sauti"</string>
+    <string name="notification_importance_default" msgid="4466466472622442175">"Ruhusu arifa hizi zitoe sauti"</string>
+    <string name="notification_importance_high" msgid="2135428926525093825">"Chungulia kwenye skrini na uruhusu sauti"</string>
+    <string name="notification_importance_max" msgid="5806278962376556491">"Onyesha katika sehemu ya juu ya orodha ya arifa, chungulia kwenye skrini na uruhusu sauti"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"Mipangilio zaidi"</string>
     <string name="notification_done" msgid="5279426047273930175">"Nimemaliza"</string>
     <string name="color_and_appearance" msgid="1254323855964993144">"Rangi na mwonekano"</string>
@@ -476,7 +489,7 @@
     <string name="use_dark_theme" msgid="2900938704964299312">"Tumia mandhari ya giza katika Mfumo wa Uendeshaji wa Android"</string>
     <string name="adjust_tint" msgid="3398569573231409878">"Rekebisha kivulivuli"</string>
     <string name="adjust_brightness" msgid="980039329808178246">"Rekebisha mwangaza"</string>
-    <string name="night_mode_disclaimer" msgid="3297928749219711334">"Mandhari yenye giza yametumika katika maeneo muhimu ya Mfumo wa Uendeshaji wa Android ambayo kwa kawaida huonyeshwa katika mandhari yenye mwangaza, kama vile Mipangilio na arifa."</string>
+    <string name="night_mode_disclaimer" msgid="598914896926759578">"Mandhari yenye giza yametumika katika maeneo muhimu ya Mfumo wa Uendeshaji wa Android ambayo kwa kawaida huonyeshwa katika mandhari yenye mwangaza, kama vile Mipangilio."</string>
     <string name="color_apply" msgid="9212602012641034283">"Tumia"</string>
     <string name="color_revert_title" msgid="4746666545480534663">"Thibitisha mipangilio"</string>
     <string name="color_revert_message" msgid="9116001069397996691">"Baadhi ya mipangilio ya rangi inaweza kufanya kifaa hiki kisitumike. Bofya Sawa ili uthibitishe mipangilio hii ya rangi, vinginevyo, mipangilio hii itajiweka upya baada ya sekunde 10."</string>
@@ -535,4 +548,10 @@
     <item msgid="2139628951880142927">"Onyesha asilimia wakati inachaji (chaguo-msingi)"</item>
     <item msgid="3327323682209964956">"Usionyeshe aikoni hii"</item>
   </string-array>
+    <string name="other" msgid="4060683095962566764">"Nyingine"</string>
+    <string name="accessibility_divider" msgid="5903423481953635044">"Kitenganishi cha skrini inayogawanywa"</string>
+    <string name="accessibility_action_divider_move_down" msgid="704893304141890042">"Sogeza chini"</string>
+    <string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"Sogeza juu"</string>
+    <string name="accessibility_action_divider_move_left" msgid="9218189832115847253">"Sogeza kushoto"</string>
+    <string name="accessibility_action_divider_move_right" msgid="4671522715182567972">"Sogeza kulia"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-sw/strings_tv.xml b/packages/SystemUI/res/values-sw/strings_tv.xml
new file mode 100644
index 0000000..9b3799a
--- /dev/null
+++ b/packages/SystemUI/res/values-sw/strings_tv.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.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="pip_close" msgid="3480680679023423574">"Funga PIP"</string>
+    <string name="pip_fullscreen" msgid="8604643018538487816">"Skrini nzima"</string>
+    <string name="pip_play" msgid="674145557658227044">"Cheza"</string>
+    <string name="pip_pause" msgid="8412075640017218862">"Sitisha"</string>
+    <string name="pip_hold_home" msgid="340086535668778109">"Shikilia kitufe cha "<b>"HOME"</b>" ili udhibiti PIP"</string>
+    <string name="pip_onboarding_description" msgid="2627737116380318292">"Bonyeza na ushikilie kitufe cha\nHOME ili udhibiti PIP"</string>
+    <string name="pip_onboarding_button" msgid="3957426748484904611">"Nimeelewa"</string>
+</resources>
diff --git a/packages/SystemUI/res/values-sw600dp/dimens.xml b/packages/SystemUI/res/values-sw600dp/dimens.xml
index 122413d..a2fa3b9 100644
--- a/packages/SystemUI/res/values-sw600dp/dimens.xml
+++ b/packages/SystemUI/res/values-sw600dp/dimens.xml
@@ -99,6 +99,9 @@
     <!-- The top padding for the task stack. -->
     <dimen name="recents_stack_top_padding">40dp</dimen>
 
+    <!-- The size of the initial peek area at the bottom of the stack (above the nav bar). -->
+    <dimen name="recents_initial_bottom_peek_size">100dp</dimen>
+
     <!-- The side padding for the task stack. -->
     <dimen name="recents_stack_left_right_padding">64dp</dimen>
 </resources>
diff --git a/packages/SystemUI/res/values-ta-rIN/strings.xml b/packages/SystemUI/res/values-ta-rIN/strings.xml
index 05f3ce5..eb7dbe4 100644
--- a/packages/SystemUI/res/values-ta-rIN/strings.xml
+++ b/packages/SystemUI/res/values-ta-rIN/strings.xml
@@ -73,7 +73,8 @@
     <string name="screenshot_saved_title" msgid="6461865960961414961">"ஸ்கிரீன் ஷாட் எடுக்கப்பட்டது."</string>
     <string name="screenshot_saved_text" msgid="1152839647677558815">"உங்கள் ஸ்க்ரீன் ஷாட்டைப் பார்க்க தொடவும்."</string>
     <string name="screenshot_failed_title" msgid="705781116746922771">"ஸ்க்ரீன் ஷாட்டை எடுக்க முடியவில்லை."</string>
-    <string name="screenshot_failed_text" msgid="1260203058661337274">"குறைந்த சேமிப்பகம் காரணமாக ஸ்கிரீன்ஷாட் எடுக்க முடியவில்லை, அல்லது பயன்பாடு அல்லது உங்கள் நிறுவனத்தால் அனுமதிக்கப்படவில்லை."</string>
+    <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"போதுமான சேமிப்பிடம் இல்லாததால் ஸ்கிரீன்ஷாட்டைச் சேமிக்க முடியவில்லை."</string>
+    <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"பயன்பாடு அல்லது உங்கள் நிறுவனம் ஸ்கிரீன்ஷாட்டுகளை எடுக்க அனுமதிக்கவில்லை."</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"USB கோப்பு இடமாற்ற விருப்பங்கள்"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"(MTP) மீடியா பிளேயராக ஏற்று"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"(PTP) கேமராவாக ஏற்று"</string>
@@ -206,6 +207,7 @@
     <string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"நேரத்தை அதிகரி."</string>
     <string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"நேரத்தைக் குறை."</string>
     <string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"ஃபிளாஷ்லைட் முடக்கத்தில்."</string>
+    <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"ஃபிளாஷ்லைட் இல்லை."</string>
     <string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"ஃபிளாஷ்லைட் இயக்கத்தில்."</string>
     <string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"ஃபிளாஷ்லைட் முடக்கப்பட்டது."</string>
     <string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"ஃபிளாஷ்லைட் இயக்கப்பட்டது."</string>
@@ -218,6 +220,10 @@
     <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"பணிப் பயன்முறை இயக்கப்பட்டுள்ளது."</string>
     <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"பணிப் பயன்முறை முடக்கப்பட்டது."</string>
     <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"பணிப் பயன்முறை இயக்கப்பட்டது."</string>
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_off (650231949881093289) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_on (4218725402373934151) -->
+    <skip />
     <string name="accessibility_brightness" msgid="8003681285547803095">"திரை பிரகாசம்"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"2G-3G டேட்டா இடைநிறுத்தப்பட்டது"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"4G டேட்டா இடைநிறுத்தப்பட்டது"</string>
@@ -304,6 +310,8 @@
     <string name="recents_launch_disabled_message" msgid="1624523193008871793">"பாதுகாப்புப் பயன்முறையில் <xliff:g id="APP">%s</xliff:g> முடக்கப்பட்டது."</string>
     <string name="recents_history_button_label" msgid="5153358867807604821">"வரலாறு"</string>
     <string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"அழி"</string>
+    <string name="recents_drag_non_dockable_task_message" msgid="2935843902795166158">"இந்தப் பயன்பாடு பல சாளர அம்சத்தை ஆதரிக்கவில்லை"</string>
+    <string name="recents_launch_non_dockable_task_label" msgid="7862379814938391888">"பயன்பாடு பல சாளர அம்சத்தை ஆதரிக்காது"</string>
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"கிடைமட்டமாகப் பிரி"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"செங்குத்தாகப் பிரி"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"தனிவிருப்பத்தில் பிரி"</string>
@@ -451,23 +459,28 @@
     <string name="enable_bluetooth_title" msgid="5027037706500635269">"புளூடூத்தை இயக்கவா?"</string>
     <string name="enable_bluetooth_message" msgid="9106595990708985385">"உங்கள் டேப்லெட்டுடன் விசைப்பலகையை இணைக்க, முதலில் புளூடூத்தை இயக்க வேண்டும்."</string>
     <string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"இயக்கு"</string>
-    <string name="apply_to_topic" msgid="3641403489318659666">"<xliff:g id="TOPIC_NAME">%1$s</xliff:g> அறிவிப்புகளுக்குப் பயன்படுத்து"</string>
-    <string name="apply_to_app" msgid="363016783939815960">"இந்தப் பயன்பாட்டிலிருந்து வரும் எல்லா அறிவிப்புகளுக்கும் பயன்படுத்து"</string>
+    <string name="show_silently" msgid="6841966539811264192">"ஒலியின்றி அறிவிப்புகளைக் காட்டு"</string>
+    <string name="block" msgid="2734508760962682611">"எல்லா அறிவிப்புகளையும் தடு"</string>
+    <string name="do_not_silence" msgid="6878060322594892441">"ஒலியை அனுமதி"</string>
+    <string name="do_not_silence_block" msgid="4070647971382232311">"ஒலி அல்லது அறிவிப்பைத் தடுக்காதே"</string>
+    <string name="tuner_full_importance_settings" msgid="8103289238676424226">"முக்கியத்துவ அமைப்புகள் முழுவதையும் காட்டு"</string>
     <string name="blocked_importance" msgid="5198578988978234161">"தடுக்கப்பட்டது"</string>
+    <string name="min_importance" msgid="1901894910809414782">"குறைந்தபட்ச முக்கியத்துவம்"</string>
     <string name="low_importance" msgid="4109929986107147930">"முக்கியத்துவம் (குறைவு)"</string>
     <string name="default_importance" msgid="8192107689995742653">"முக்கியத்துவம் (இயல்பு)"</string>
     <string name="high_importance" msgid="1527066195614050263">"முக்கியத்துவம் (அதிகம்)"</string>
     <string name="max_importance" msgid="5089005872719563894">"முக்கியத்துவம் (அவசரம்)"</string>
     <string name="notification_importance_blocked" msgid="2397192642657872872">"இந்த அறிவிப்புகளை ஒருபோதும் காட்டாதே"</string>
-    <string name="notification_importance_low" msgid="4383563267370859725">"ஒலியின்றி அறிவிப்புப் பட்டியலின் கீழே காட்டு"</string>
-    <string name="notification_importance_default" msgid="4926529615920610817">"ஒலியின்றி இந்த அறிவிப்புகளைக் காட்டு"</string>
-    <string name="notification_importance_high" msgid="3222680136612408223">"அறிவிப்புகள் பட்டியலின் மேல் பகுதியில் ஒலியுடன் காட்டு"</string>
-    <string name="notification_importance_max" msgid="5236987171904756134">"ஒலியுடன் திரையில் காட்டு"</string>
+    <string name="notification_importance_min" msgid="1938190340516905748">"ஒலியின்றி அறிவிப்புப் பட்டியலின் கீழே காட்டு"</string>
+    <string name="notification_importance_low" msgid="3657252049508213048">"ஒலியின்றி இந்த அறிவிப்புகளைக் காட்டு"</string>
+    <string name="notification_importance_default" msgid="4466466472622442175">"இந்த அறிவிப்புகளுக்கு ஒலியை அனுமதி"</string>
+    <string name="notification_importance_high" msgid="2135428926525093825">"சில வினாடிகளுக்கு ஒலியுடன் திரையில் காட்டு"</string>
+    <string name="notification_importance_max" msgid="5806278962376556491">"அறிவிப்புகள் பட்டியலின் மேற்பகுதியில், சில வினாடிகளுக்கு ஒலியுடன் திரையில் காட்டு"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"மேலும் அமைப்புகள்"</string>
     <string name="notification_done" msgid="5279426047273930175">"முடிந்தது"</string>
     <string name="color_and_appearance" msgid="1254323855964993144">"வண்ணமும் தோற்றமும்"</string>
     <string name="night_mode" msgid="3540405868248625488">"இரவுப் பயன்முறை"</string>
-    <string name="calibrate_display" msgid="5974642573432039217">"திரையை அளவீடு செய்"</string>
+    <string name="calibrate_display" msgid="5974642573432039217">"திரையை அளவுத்திருத்தம் செய்"</string>
     <string name="night_mode_on" msgid="5597545513026541108">"இயக்கத்தில்"</string>
     <string name="night_mode_off" msgid="8035605276956057508">"முடக்கத்தில்"</string>
     <string name="turn_on_automatically" msgid="4167565356762016083">"தானாகவே இயக்கு"</string>
@@ -476,7 +489,7 @@
     <string name="use_dark_theme" msgid="2900938704964299312">"Android OSக்காக அடர் தீமினைப் பயன்படுத்து"</string>
     <string name="adjust_tint" msgid="3398569573231409878">"டிண்ட்டைச் சரிசெய்"</string>
     <string name="adjust_brightness" msgid="980039329808178246">"ஒளிர்வைச் சரிசெய்"</string>
-    <string name="night_mode_disclaimer" msgid="3297928749219711334">"வழக்கமாக வெளிர் தீமில் காட்டப்படுகிற Android OS இன் முக்கிய பகுதிகளில் (எ.கா., அமைப்புகள், அறிவிப்புகள் போன்றவை) அடர் தீம் பயன்படுத்தப்படுகிறது."</string>
+    <string name="night_mode_disclaimer" msgid="598914896926759578">"வழக்கமாக வெளிர் தீமில் காட்டப்படுகிற Android OS இன் முக்கிய பகுதிகளில் (எ.கா. அமைப்புகள்) அடர் தீம் பயன்படுத்தப்படுகிறது."</string>
     <string name="color_apply" msgid="9212602012641034283">"பயன்படுத்து"</string>
     <string name="color_revert_title" msgid="4746666545480534663">"அமைப்புகளை உறுதிப்படுத்து"</string>
     <string name="color_revert_message" msgid="9116001069397996691">"சில வண்ண அமைப்புகள் இந்தச் சாதனத்தைப் பயன்படுத்த முடியாதபடி செய்யலாம். இந்த வண்ண அமைப்புகளை உறுதிப்படுத்த, சரி என்பதைக் கிளிக் செய்யவும், இல்லையெனில் இந்த அமைப்புகள் 10 வினாடிகளுக்குப் பின் மீட்டமைக்கப்படும்."</string>
@@ -535,4 +548,10 @@
     <item msgid="2139628951880142927">"சார்ஜ் செய்யும் போது சதவீதத்தைக் காட்டு (இயல்பு)"</item>
     <item msgid="3327323682209964956">"இந்த ஐகானைக் காட்டாதே"</item>
   </string-array>
+    <string name="other" msgid="4060683095962566764">"மற்றவை"</string>
+    <string name="accessibility_divider" msgid="5903423481953635044">"திரையைப் பிரிக்கும் பிரிப்பான்"</string>
+    <string name="accessibility_action_divider_move_down" msgid="704893304141890042">"கீழே நகர்த்து"</string>
+    <string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"மேலே நகர்த்து"</string>
+    <string name="accessibility_action_divider_move_left" msgid="9218189832115847253">"இடப்புறம் நகர்த்து"</string>
+    <string name="accessibility_action_divider_move_right" msgid="4671522715182567972">"வலப்புறம் நகர்த்து"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ta-rIN/strings_tv.xml b/packages/SystemUI/res/values-ta-rIN/strings_tv.xml
new file mode 100644
index 0000000..d4d661a
--- /dev/null
+++ b/packages/SystemUI/res/values-ta-rIN/strings_tv.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.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="pip_close" msgid="3480680679023423574">"PIPஐ மூடு"</string>
+    <string name="pip_fullscreen" msgid="8604643018538487816">"முழுத்திரை"</string>
+    <string name="pip_play" msgid="674145557658227044">"இயக்கு"</string>
+    <string name="pip_pause" msgid="8412075640017218862">"இடைநிறுத்து"</string>
+    <string name="pip_hold_home" msgid="340086535668778109">"PIPஐக் கட்டுப்படுத்த, "<b>"முகப்பைப்"</b>" பிடித்திருக்கவும்"</string>
+    <string name="pip_onboarding_description" msgid="2627737116380318292">"PIPஐக் கட்டுப்படுத்த, முகப்புப்\nபொத்தானை அழுத்தவும், பிடிக்கவும்"</string>
+    <string name="pip_onboarding_button" msgid="3957426748484904611">"சரி"</string>
+</resources>
diff --git a/packages/SystemUI/res/values-te-rIN/strings.xml b/packages/SystemUI/res/values-te-rIN/strings.xml
index 28065c0..29e2539 100644
--- a/packages/SystemUI/res/values-te-rIN/strings.xml
+++ b/packages/SystemUI/res/values-te-rIN/strings.xml
@@ -73,7 +73,8 @@
     <string name="screenshot_saved_title" msgid="6461865960961414961">"స్క్రీన్‌షాట్ క్యాప్చర్ చేయబడింది."</string>
     <string name="screenshot_saved_text" msgid="1152839647677558815">"మీ స్క్రీన్‌షాట్‌ను వీక్షించడానికి తాకండి."</string>
     <string name="screenshot_failed_title" msgid="705781116746922771">"స్క్రీన్‌షాట్‌ను క్యాప్చర్ చేయడం సాధ్యపడలేదు."</string>
-    <string name="screenshot_failed_text" msgid="1260203058661337274">"పరిమిత నిల్వ స్థలం కారణంగా స్క్రీన్‌షాట్‌‌ను తీయడం సాధ్యపడదు లేదా దీన్ని మీ అనువర్తనం లేదా మీ సంస్థ అనుమతించలేదు."</string>
+    <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"పరిమిత నిల్వ స్థలం కారణంగా స్క్రీన్‌షాట్‌ను సేవ్ చేయడం సాధ్యపడదు."</string>
+    <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"స్క్రీన్‌షాట్‌లు తీయడానికి అనువర్తనం లేదా మీ సంస్థ అనుమతించలేదు."</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"USB ఫైల్ బదిలీ ఎంపికలు"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"మీడియా ప్లేయర్‌గా (MTP) మౌంట్ చేయి"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"కెమెరాగా (PTP) మౌంట్ చేయి"</string>
@@ -206,6 +207,7 @@
     <string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"ఎక్కువ సమయం."</string>
     <string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"తక్కువ సమయం."</string>
     <string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"ఫ్లాష్‌లైట్ ఆఫ్‌లో ఉంది."</string>
+    <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"ఫ్లాష్‌లైట్ అందుబాటులో లేదు."</string>
     <string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"ఫ్లాష్‌లైట్ ఆన్‌లో ఉంది."</string>
     <string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"ఫ్లాష్‌లైట్ ఆఫ్ చేయబడింది."</string>
     <string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"ఫ్లాష్‌లైట్ ఆన్ చేయబడింది."</string>
@@ -218,6 +220,10 @@
     <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"పని మోడ్ ఆన్‌లో ఉంది."</string>
     <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"పని మోడ్ ఆఫ్ చేయబడింది."</string>
     <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"పని మోడ్ ఆన్ చేయబడింది."</string>
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_off (650231949881093289) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_on (4218725402373934151) -->
+    <skip />
     <string name="accessibility_brightness" msgid="8003681285547803095">"ప్రదర్శన ప్రకాశం"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"2G-3G డేటా పాజ్ చేయబడింది"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"4G డేటా పాజ్ చేయబడింది"</string>
@@ -304,6 +310,8 @@
     <string name="recents_launch_disabled_message" msgid="1624523193008871793">"<xliff:g id="APP">%s</xliff:g> సురక్షిత-మోడ్‌లో నిలిపివేయబడింది."</string>
     <string name="recents_history_button_label" msgid="5153358867807604821">"చరిత్ర"</string>
     <string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"తీసివేయి"</string>
+    <string name="recents_drag_non_dockable_task_message" msgid="2935843902795166158">"ఈ అనువర్తనం బహుళ విండోలకు మద్దతు ఇవ్వదు"</string>
+    <string name="recents_launch_non_dockable_task_label" msgid="7862379814938391888">"అనువర్తనం బహుళ విండోలకు మద్దతు ఇవ్వదు"</string>
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"సమతలంగా విభజించు"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"లంబంగా విభజించు"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"అనుకూలంగా విభజించు"</string>
@@ -451,18 +459,23 @@
     <string name="enable_bluetooth_title" msgid="5027037706500635269">"బ్లూటూత్ ఆన్ చేయాలా?"</string>
     <string name="enable_bluetooth_message" msgid="9106595990708985385">"మీ కీబోర్డ్‌ను మీ టాబ్లెట్‌తో కనెక్ట్ చేయడానికి, మీరు ముందుగా బ్లూటూత్ ఆన్ చేయాలి."</string>
     <string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"ఆన్ చేయి"</string>
-    <string name="apply_to_topic" msgid="3641403489318659666">"<xliff:g id="TOPIC_NAME">%1$s</xliff:g> నోటిఫికేషన్‌లకు వర్తింపజేయి"</string>
-    <string name="apply_to_app" msgid="363016783939815960">"ఈ అనువర్తనం నుండి అందించబడే అన్ని నోటిఫికేషన్‌లకు వర్తింపజేయి"</string>
+    <string name="show_silently" msgid="6841966539811264192">"నోటిఫికేషన్‌లను శబ్దం లేకుండా చూపు"</string>
+    <string name="block" msgid="2734508760962682611">"అన్ని నోటిఫికేషన్‌లను బ్లాక్ చేయి"</string>
+    <string name="do_not_silence" msgid="6878060322594892441">"నిశ్శబ్దం చేయవద్దు"</string>
+    <string name="do_not_silence_block" msgid="4070647971382232311">"నిశ్శబ్దం చేయవద్దు లేదా బ్లాక్ చేయవద్దు"</string>
+    <string name="tuner_full_importance_settings" msgid="8103289238676424226">"పూర్తి ప్రాముఖ్యత సెట్టింగ్‌లను చూపండి"</string>
     <string name="blocked_importance" msgid="5198578988978234161">"బ్లాక్ చేయబడింది"</string>
+    <string name="min_importance" msgid="1901894910809414782">"కని. ప్రాముఖ్యత"</string>
     <string name="low_importance" msgid="4109929986107147930">"తక్కువ ప్రాముఖ్యత"</string>
     <string name="default_importance" msgid="8192107689995742653">"సాధారణ ప్రాముఖ్యత"</string>
     <string name="high_importance" msgid="1527066195614050263">"అధిక ప్రాముఖ్యత"</string>
     <string name="max_importance" msgid="5089005872719563894">"అత్యవసర ప్రాముఖ్యత"</string>
     <string name="notification_importance_blocked" msgid="2397192642657872872">"ఈ నోటిఫికేషన్‌లను ఎప్పుడూ చూపదు"</string>
-    <string name="notification_importance_low" msgid="4383563267370859725">"నోటిఫికేషన్‌ల జాబితా దిగువ భాగంలో శబ్దం లేకుండా చూపుతుంది"</string>
-    <string name="notification_importance_default" msgid="4926529615920610817">"ఈ నోటిఫికేషన్‌లను శబ్దం లేకుండా చూపుతుంది"</string>
-    <string name="notification_importance_high" msgid="3222680136612408223">"నోటిఫికేషన్‌ల జాబితా ఎగువ భాగంలో శబ్దంతో చూపుతుంది"</string>
-    <string name="notification_importance_max" msgid="5236987171904756134">"స్క్రీన్‌పై శీఘ్రంగా శబ్దంతో చూపుతుంది"</string>
+    <string name="notification_importance_min" msgid="1938190340516905748">"నోటిఫికేషన్‌ల జాబితా దిగువ భాగంలో శబ్దం లేకుండా చూపుతుంది"</string>
+    <string name="notification_importance_low" msgid="3657252049508213048">"ఈ నోటిఫికేషన్‌లను శబ్దం లేకుండా చూపుతుంది"</string>
+    <string name="notification_importance_default" msgid="4466466472622442175">"ఈ నోటిఫికేషన్‌లను శబ్దంతో చూపేలా అనుమతిస్తుంది"</string>
+    <string name="notification_importance_high" msgid="2135428926525093825">"స్క్రీన్‌పై శీఘ్రంగా శబ్దంతో చూపుతుంది"</string>
+    <string name="notification_importance_max" msgid="5806278962376556491">"నోటిఫికేషన్‌ల జాబితా అగ్ర భాగాన, స్క్రీన్‌పై శీఘ్రంగా శబ్దంతో చూపుతుంది"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"మరిన్ని సెట్టింగ్‌లు"</string>
     <string name="notification_done" msgid="5279426047273930175">"పూర్తయింది"</string>
     <string name="color_and_appearance" msgid="1254323855964993144">"రంగు మరియు కనిపించే తీరు"</string>
@@ -476,7 +489,7 @@
     <string name="use_dark_theme" msgid="2900938704964299312">"Android OS కోసం ముదురు రంగు థీమ్ ఉపయోగించండి"</string>
     <string name="adjust_tint" msgid="3398569573231409878">"లేత రంగును సర్దుబాటు చేయండి"</string>
     <string name="adjust_brightness" msgid="980039329808178246">"ప్రకాశాన్ని సర్దుబాటు చేయండి"</string>
-    <string name="night_mode_disclaimer" msgid="3297928749219711334">"సాధారణంగా లేత రంగు థీమ్‌లో ప్రదర్శించబడే సెట్టింగ్‌లు మరియు నోటిఫికేషన్‌ల వంటి Android OS ప్రధాన అంశాలకు ముదురు రంగు థీమ్ వర్తింపజేయబడుతుంది."</string>
+    <string name="night_mode_disclaimer" msgid="598914896926759578">"సాధారణంగా లేత రంగు థీమ్‌లో ప్రదర్శించబడే సెట్టింగ్‌ల వంటి Android OS ప్రధాన అంశాలకు ముదురు రంగు థీమ్ వర్తింపజేయబడుతుంది."</string>
     <string name="color_apply" msgid="9212602012641034283">"వర్తింపజేయి"</string>
     <string name="color_revert_title" msgid="4746666545480534663">"సెట్టింగ్‌లను నిర్ధారించండి"</string>
     <string name="color_revert_message" msgid="9116001069397996691">"కొన్ని రంగు సెట్టింగ్‌ల వలన ఈ పరికరం ఉపయోగించలేని విధంగా అయిపోవచ్చు. ఈ రంగు సెట్టింగ్‌లను నిర్ధారించడానికి సరే క్లిక్ చేయండి లేదంటే ఈ సెట్టింగ్‌లు 10 సెకన్ల తర్వాత రీసెట్ చేయబడతాయి."</string>
@@ -535,4 +548,10 @@
     <item msgid="2139628951880142927">"ఛార్జ్ అవుతున్నప్పుడు శాతాన్ని చూపు (డిఫాల్ట్)"</item>
     <item msgid="3327323682209964956">"ఈ చిహ్నాన్ని చూపవద్దు"</item>
   </string-array>
+    <string name="other" msgid="4060683095962566764">"ఇతరం"</string>
+    <string name="accessibility_divider" msgid="5903423481953635044">"విభజన స్క్రీన్ విభాగిని"</string>
+    <string name="accessibility_action_divider_move_down" msgid="704893304141890042">"క్రిందికి తరలించు"</string>
+    <string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"పైకి తరలించు"</string>
+    <string name="accessibility_action_divider_move_left" msgid="9218189832115847253">"ఎడమవైపుకు తరలించు"</string>
+    <string name="accessibility_action_divider_move_right" msgid="4671522715182567972">"కుడివైపుకు తరలించు"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-te-rIN/strings_tv.xml b/packages/SystemUI/res/values-te-rIN/strings_tv.xml
new file mode 100644
index 0000000..4c18743
--- /dev/null
+++ b/packages/SystemUI/res/values-te-rIN/strings_tv.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.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="pip_close" msgid="3480680679023423574">"PIPని మూసివేయి"</string>
+    <string name="pip_fullscreen" msgid="8604643018538487816">"పూర్తి స్క్రీన్"</string>
+    <string name="pip_play" msgid="674145557658227044">"ప్లే చేయి"</string>
+    <string name="pip_pause" msgid="8412075640017218862">"పాజ్ చేయి"</string>
+    <string name="pip_hold_home" msgid="340086535668778109">"PIP నియం. "<b>"HOME"</b>"నొక్కిఉంచండి"</string>
+    <string name="pip_onboarding_description" msgid="2627737116380318292">"PIPని నియంత్రించడానికి HOME\nబటన్‌ను నొక్కి ఉంచండి"</string>
+    <string name="pip_onboarding_button" msgid="3957426748484904611">"అర్థమైంది"</string>
+</resources>
diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml
index 0164ad7..2fb82b7 100644
--- a/packages/SystemUI/res/values-th/strings.xml
+++ b/packages/SystemUI/res/values-th/strings.xml
@@ -73,7 +73,8 @@
     <string name="screenshot_saved_title" msgid="6461865960961414961">"จับภาพหน้าจอแล้ว"</string>
     <string name="screenshot_saved_text" msgid="1152839647677558815">"แตะเพื่อดูภาพหน้าจอของคุณ"</string>
     <string name="screenshot_failed_title" msgid="705781116746922771">"ไม่สามารถจับภาพหน้าจอ"</string>
-    <string name="screenshot_failed_text" msgid="1260203058661337274">"ไม่สามารถจับภาพหน้าจอได้ เนื่องจากพื้นที่ว่างมีจำกัด หรือไม่ได้รับอนุญาตจากแอปหรือองค์กรของคุณ"</string>
+    <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"ไม่สามารถบันทึกภาพหน้าจอเนื่องจากพื้นที่เก็บข้อมูลมีจำกัด"</string>
+    <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"แอปหรือองค์กรของคุณไม่อนุญาตให้จับภาพหน้าจอ"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"ตัวเลือกการถ่ายโอนไฟล์ USB"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"ต่อเชื่อมเป็นโปรแกรมเล่นสื่อ (MTP)"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"ต่อเชื่อมเป็นกล้องถ่ายรูป (PTP)"</string>
@@ -206,6 +207,7 @@
     <string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"เวลามากขึ้น"</string>
     <string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"เวลาน้อยลง"</string>
     <string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"ไฟฉายปิดอยู่"</string>
+    <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"ไฟฉายไม่พร้อมใช้งาน"</string>
     <string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"ไฟฉายเปิดอยู่"</string>
     <string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"ปิดไฟฉายแล้ว"</string>
     <string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"เปิดไฟฉายแล้ว"</string>
@@ -218,6 +220,10 @@
     <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"โหมดการทำงานเปิดอยู่"</string>
     <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"ปิดโหมดการทำงานแล้ว"</string>
     <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"เปิดโหมดการทำงานแล้ว"</string>
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_off (650231949881093289) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_on (4218725402373934151) -->
+    <skip />
     <string name="accessibility_brightness" msgid="8003681285547803095">"ความสว่างของหน้าจอ"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"หยุดการใช้ข้อมูล 2G-3G ชั่วคราวแล้ว"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"หยุดการใช้ข้อมูล 4G ชั่วคราวแล้ว"</string>
@@ -304,6 +310,8 @@
     <string name="recents_launch_disabled_message" msgid="1624523193008871793">"<xliff:g id="APP">%s</xliff:g> ปิดใช้ในโหมดปลอดภัย"</string>
     <string name="recents_history_button_label" msgid="5153358867807604821">"ประวัติ"</string>
     <string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"ล้าง"</string>
+    <string name="recents_drag_non_dockable_task_message" msgid="2935843902795166158">"แอปนี้ไม่สนับสนุนหลายหน้าต่าง"</string>
+    <string name="recents_launch_non_dockable_task_label" msgid="7862379814938391888">"แอปไม่สนับสนุนหลายหน้าต่าง"</string>
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"แยกในแนวนอน"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"แยกในแนวตั้ง"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"แยกแบบกำหนดเอง"</string>
@@ -451,18 +459,23 @@
     <string name="enable_bluetooth_title" msgid="5027037706500635269">"เปิดบลูทูธไหม"</string>
     <string name="enable_bluetooth_message" msgid="9106595990708985385">"หากต้องการเชื่อมต่อแป้นพิมพ์กับแท็บเล็ต คุณต้องเปิดบลูทูธก่อน"</string>
     <string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"เปิด"</string>
-    <string name="apply_to_topic" msgid="3641403489318659666">"นำไปใช้กับการแจ้งเตือน <xliff:g id="TOPIC_NAME">%1$s</xliff:g>"</string>
-    <string name="apply_to_app" msgid="363016783939815960">"นำไปใช้กับการแจ้งเตือนทั้งหมดจากแอปนี้"</string>
+    <string name="show_silently" msgid="6841966539811264192">"แสดงการแจ้งเตือนโดยไม่ส่งเสียง"</string>
+    <string name="block" msgid="2734508760962682611">"บล็อกการแจ้งเตือนทั้งหมด"</string>
+    <string name="do_not_silence" msgid="6878060322594892441">"ไม่ปิดเสียง"</string>
+    <string name="do_not_silence_block" msgid="4070647971382232311">"ไม่ปิดเสียงหรือบล็อก"</string>
+    <string name="tuner_full_importance_settings" msgid="8103289238676424226">"แสดงการตั้งค่าความสำคัญแบบเต็ม"</string>
     <string name="blocked_importance" msgid="5198578988978234161">"บล็อกแล้ว"</string>
+    <string name="min_importance" msgid="1901894910809414782">"ความสำคัญน้อย"</string>
     <string name="low_importance" msgid="4109929986107147930">"ความสำคัญต่ำ"</string>
     <string name="default_importance" msgid="8192107689995742653">"ความสำคัญปกติ"</string>
     <string name="high_importance" msgid="1527066195614050263">"ความสำคัญสูง"</string>
     <string name="max_importance" msgid="5089005872719563894">"ความสำคัญเร่งด่วน"</string>
     <string name="notification_importance_blocked" msgid="2397192642657872872">"ไม่ต้องแสดงการแจ้งเตือนเหล่านี้"</string>
-    <string name="notification_importance_low" msgid="4383563267370859725">"แสดงที่ด้านล่างของรายการแจ้งเตือนโดยไม่ส่งเสียง"</string>
-    <string name="notification_importance_default" msgid="4926529615920610817">"แสดงการแจ้งเตือนเหล่านี้โดยไม่ส่งเสียง"</string>
-    <string name="notification_importance_high" msgid="3222680136612408223">"แสดงที่ด้านบนของรายการแจ้งเตือนและส่งเสียง"</string>
-    <string name="notification_importance_max" msgid="5236987171904756134">"แสดงบนหน้าจอในช่วงเวลาสั้นๆ และส่งเสียง"</string>
+    <string name="notification_importance_min" msgid="1938190340516905748">"แสดงที่ด้านล่างของรายการแจ้งเตือนโดยไม่ส่งเสียง"</string>
+    <string name="notification_importance_low" msgid="3657252049508213048">"แสดงการแจ้งเตือนเหล่านี้โดยไม่ส่งเสียง"</string>
+    <string name="notification_importance_default" msgid="4466466472622442175">"ให้การแจ้งเตือนเหล่านี้ส่งเสียงได้"</string>
+    <string name="notification_importance_high" msgid="2135428926525093825">"แสดงบนหน้าจอและให้ส่งเสียงได้"</string>
+    <string name="notification_importance_max" msgid="5806278962376556491">"แสดงที่ด้านบนของรายการการแจ้งเตือน แสดงบนหน้าจอและให้ส่งเสียงได้"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"การตั้งค่าเพิ่มเติม"</string>
     <string name="notification_done" msgid="5279426047273930175">"เสร็จสิ้น"</string>
     <string name="color_and_appearance" msgid="1254323855964993144">"สีและลักษณะที่ปรากฏ"</string>
@@ -476,7 +489,7 @@
     <string name="use_dark_theme" msgid="2900938704964299312">"ใช้ธีมสีเข้มสำหรับ Android OS"</string>
     <string name="adjust_tint" msgid="3398569573231409878">"ปรับการแต้มสี"</string>
     <string name="adjust_brightness" msgid="980039329808178246">"ปรับความสว่าง"</string>
-    <string name="night_mode_disclaimer" msgid="3297928749219711334">"ใช้ธีมสีเข้มในบริเวณสำคัญของ Android OS ซึ่งปกติแล้วจะแสดงในธีมสีอ่อน เช่น การตั้งค่า และการแจ้งเตือน"</string>
+    <string name="night_mode_disclaimer" msgid="598914896926759578">"ใช้ธีมสีเข้มในบริเวณสำคัญของระบบปฏิบัติการ Android ซึ่งปกติแล้วจะแสดงด้วยธีมสีอ่อน เช่น การตั้งค่า"</string>
     <string name="color_apply" msgid="9212602012641034283">"ใช้"</string>
     <string name="color_revert_title" msgid="4746666545480534663">"ยืนยันการตั้งค่า"</string>
     <string name="color_revert_message" msgid="9116001069397996691">"การตั้งค่าสีบางอย่างอาจทำให้อุปกรณ์นี้ใช้งานไม่ได้ คลิกตกลงเพื่อยืนยันการตั้งค่าสีเหล่านี้ มิฉะนั้นระบบจะรีเซ็ตการตั้งค่าหลังจาก 10 วินาที"</string>
@@ -535,4 +548,10 @@
     <item msgid="2139628951880142927">"แสดงเปอร์เซ็นต์เมื่อชาร์จ (ค่าเริ่มต้น)"</item>
     <item msgid="3327323682209964956">"อย่าแสดงไอคอนนี้"</item>
   </string-array>
+    <string name="other" msgid="4060683095962566764">"อื่นๆ"</string>
+    <string name="accessibility_divider" msgid="5903423481953635044">"เส้นแบ่งหน้าจอ"</string>
+    <string name="accessibility_action_divider_move_down" msgid="704893304141890042">"เลื่อนลง"</string>
+    <string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"เลื่อนขึ้น"</string>
+    <string name="accessibility_action_divider_move_left" msgid="9218189832115847253">"เลื่อนไปทางซ้าย"</string>
+    <string name="accessibility_action_divider_move_right" msgid="4671522715182567972">"เลื่อนไปทางขวา"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-th/strings_tv.xml b/packages/SystemUI/res/values-th/strings_tv.xml
new file mode 100644
index 0000000..78fd1b8
--- /dev/null
+++ b/packages/SystemUI/res/values-th/strings_tv.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2016, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <!-- no translation found for pip_close (3480680679023423574) -->
+    <skip />
+    <string name="pip_fullscreen" msgid="8604643018538487816">"เต็มหน้าจอ"</string>
+    <string name="pip_play" msgid="674145557658227044">"เล่น"</string>
+    <string name="pip_pause" msgid="8412075640017218862">"หยุดชั่วคราว"</string>
+    <!-- no translation found for pip_hold_home (340086535668778109) -->
+    <skip />
+    <!-- no translation found for pip_onboarding_description (2627737116380318292) -->
+    <skip />
+    <!-- no translation found for pip_onboarding_button (3957426748484904611) -->
+    <skip />
+</resources>
diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml
index ccd1e37..943d21f 100644
--- a/packages/SystemUI/res/values-tl/strings.xml
+++ b/packages/SystemUI/res/values-tl/strings.xml
@@ -73,7 +73,8 @@
     <string name="screenshot_saved_title" msgid="6461865960961414961">"Nakuha ang screenshot."</string>
     <string name="screenshot_saved_text" msgid="1152839647677558815">"Pindutin upang tingnan ang iyong screenshot."</string>
     <string name="screenshot_failed_title" msgid="705781116746922771">"Hindi makuha ang screenshot."</string>
-    <string name="screenshot_failed_text" msgid="1260203058661337274">"Di makapag-screenshot dahil sa limitadong storage space o di ito pinapayagan ng app o organisasyon."</string>
+    <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Hindi ma-save ang screenshot dahil sa limitadong espasyo ng storage."</string>
+    <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Hindi pinapayagan ng app o ng iyong organisasyon ang pagkuha ng mga screenshot."</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"Opsyon paglipat ng USB file"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"I-mount bilang isang media player (MTP)"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"I-mount bilang camera (PTP)"</string>
@@ -206,6 +207,7 @@
     <string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"Higit pang oras."</string>
     <string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"Mas kaunting oras."</string>
     <string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"Naka-off ang flashlight."</string>
+    <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"Hindi available ang flashlight."</string>
     <string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"Naka-on ang flashlight."</string>
     <string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"Na-off ang flashlight."</string>
     <string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"Na-on ang flashlight."</string>
@@ -218,6 +220,10 @@
     <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"Naka-on ang work mode."</string>
     <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"Na-off ang work mode."</string>
     <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"Na-on ang work mode."</string>
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_off (650231949881093289) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_on (4218725402373934151) -->
+    <skip />
     <string name="accessibility_brightness" msgid="8003681285547803095">"Liwanag ng display"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"Naka-pause ang 2G-3G data"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"Naka-pause ang 4G data"</string>
@@ -304,6 +310,8 @@
     <string name="recents_launch_disabled_message" msgid="1624523193008871793">"Naka-disable ang <xliff:g id="APP">%s</xliff:g> sa safe-mode."</string>
     <string name="recents_history_button_label" msgid="5153358867807604821">"History"</string>
     <string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"I-clear"</string>
+    <string name="recents_drag_non_dockable_task_message" msgid="2935843902795166158">"Hindi sinusuportahan ng app na ito ang multi-window"</string>
+    <string name="recents_launch_non_dockable_task_label" msgid="7862379814938391888">"Hindi sinusuportahan ng app na ito ang multi-window"</string>
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Split Horizontal"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Split Vertical"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Split Custom"</string>
@@ -451,18 +459,23 @@
     <string name="enable_bluetooth_title" msgid="5027037706500635269">"I-on ang Bluetooth?"</string>
     <string name="enable_bluetooth_message" msgid="9106595990708985385">"Upang ikonekta ang iyong keyboard sa iyong tablet, kailangan mo munang i-on ang Bluetooth."</string>
     <string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"I-on"</string>
-    <string name="apply_to_topic" msgid="3641403489318659666">"Naaangkop sa mga notification tungkol sa <xliff:g id="TOPIC_NAME">%1$s</xliff:g>"</string>
-    <string name="apply_to_app" msgid="363016783939815960">"Naaangkop sa lahat ng notification mula sa app na ito"</string>
+    <string name="show_silently" msgid="6841966539811264192">"Tahimik na ipakita ang mga notification"</string>
+    <string name="block" msgid="2734508760962682611">"I-block ang lahat ng notification"</string>
+    <string name="do_not_silence" msgid="6878060322594892441">"Huwag i-silent"</string>
+    <string name="do_not_silence_block" msgid="4070647971382232311">"Huwag i-silent o i-block"</string>
+    <string name="tuner_full_importance_settings" msgid="8103289238676424226">"Ipakita ang kumpletong mga setting ng kahalagahan"</string>
     <string name="blocked_importance" msgid="5198578988978234161">"Na-block"</string>
+    <string name="min_importance" msgid="1901894910809414782">"Hindi masyadong mahalaga"</string>
     <string name="low_importance" msgid="4109929986107147930">"Hindi masyadong mahalaga"</string>
     <string name="default_importance" msgid="8192107689995742653">"Mahalaga"</string>
     <string name="high_importance" msgid="1527066195614050263">"Napakahalaga"</string>
     <string name="max_importance" msgid="5089005872719563894">"Mahalagang-mahalaga"</string>
     <string name="notification_importance_blocked" msgid="2397192642657872872">"Huwag kailanman ipakita ang mga notification na ito"</string>
-    <string name="notification_importance_low" msgid="4383563267370859725">"Tahimik na ipakita sa ibaba ng listahan ng notification"</string>
-    <string name="notification_importance_default" msgid="4926529615920610817">"Tahimik na ipakita ang mga notification na ito"</string>
-    <string name="notification_importance_high" msgid="3222680136612408223">"Ipakita sa itaas ng listahan ng mga notification at mag-play ng tunog"</string>
-    <string name="notification_importance_max" msgid="5236987171904756134">"Ipasilip sa screen at mag-play ng tunog"</string>
+    <string name="notification_importance_min" msgid="1938190340516905748">"Tahimik na ipakita sa ibaba ng listahan ng notification"</string>
+    <string name="notification_importance_low" msgid="3657252049508213048">"Tahimik na ipakita ang mga notification na ito"</string>
+    <string name="notification_importance_default" msgid="4466466472622442175">"Payagan ang mga notification na ito na tumunog"</string>
+    <string name="notification_importance_high" msgid="2135428926525093825">"Palitawin sa screen at payagang tumunog"</string>
+    <string name="notification_importance_max" msgid="5806278962376556491">"Ipakita sa itaas ng listahan ng mga notification, palitawin sa screen at payagang tumunog"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"Higit pang mga setting"</string>
     <string name="notification_done" msgid="5279426047273930175">"Tapos Na"</string>
     <string name="color_and_appearance" msgid="1254323855964993144">"Kulay at hitsura"</string>
@@ -476,7 +489,7 @@
     <string name="use_dark_theme" msgid="2900938704964299312">"Gumamit ng madilim na tema para sa Android OS"</string>
     <string name="adjust_tint" msgid="3398569573231409878">"Isaayos ang tint"</string>
     <string name="adjust_brightness" msgid="980039329808178246">"Isaayos ang liwanag"</string>
-    <string name="night_mode_disclaimer" msgid="3297928749219711334">"Ilalapat ang madilim na tema sa mahahalagang bahagi ng Android OS na karaniwang ipinapakita nang may maliwanag na tema, gaya ng Mga Setting at mga notification."</string>
+    <string name="night_mode_disclaimer" msgid="598914896926759578">"Ilalapat ang madilim na tema sa mga mahalagang bahagi ng Android OS na karaniwang ipinapakita nang may maliwanag na tema, gaya ng Mga Setting."</string>
     <string name="color_apply" msgid="9212602012641034283">"Ilapat"</string>
     <string name="color_revert_title" msgid="4746666545480534663">"Kumpirmahin ang mga setting"</string>
     <string name="color_revert_message" msgid="9116001069397996691">"Maaaring hindi magamit ang device na ito dahil sa ilang setting ng kulay. I-click ang OK upang kumpirmahin ang mga setting ng kulay na ito, kung hindi ay mare-reset ang mga setting na ito pagkatapos ng 10 segundo."</string>
@@ -535,4 +548,10 @@
     <item msgid="2139628951880142927">"Ipakita ang porsyento kapag nagcha-charge (default)"</item>
     <item msgid="3327323682209964956">"Huwag ipakita ang icon na ito"</item>
   </string-array>
+    <string name="other" msgid="4060683095962566764">"Iba pa"</string>
+    <string name="accessibility_divider" msgid="5903423481953635044">"Divider ng split-screen"</string>
+    <string name="accessibility_action_divider_move_down" msgid="704893304141890042">"Ilipat pababa"</string>
+    <string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"Ilipat pataas"</string>
+    <string name="accessibility_action_divider_move_left" msgid="9218189832115847253">"Ilipat pakaliwa"</string>
+    <string name="accessibility_action_divider_move_right" msgid="4671522715182567972">"Ilipat pakanan"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-tl/strings_tv.xml b/packages/SystemUI/res/values-tl/strings_tv.xml
new file mode 100644
index 0000000..db898c6
--- /dev/null
+++ b/packages/SystemUI/res/values-tl/strings_tv.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2016, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <!-- no translation found for pip_close (3480680679023423574) -->
+    <skip />
+    <string name="pip_fullscreen" msgid="8604643018538487816">"Full screen"</string>
+    <string name="pip_play" msgid="674145557658227044">"I-play"</string>
+    <string name="pip_pause" msgid="8412075640017218862">"I-pause"</string>
+    <!-- no translation found for pip_hold_home (340086535668778109) -->
+    <skip />
+    <!-- no translation found for pip_onboarding_description (2627737116380318292) -->
+    <skip />
+    <!-- no translation found for pip_onboarding_button (3957426748484904611) -->
+    <skip />
+</resources>
diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml
index b343d08..a294977 100644
--- a/packages/SystemUI/res/values-tr/strings.xml
+++ b/packages/SystemUI/res/values-tr/strings.xml
@@ -73,7 +73,8 @@
     <string name="screenshot_saved_title" msgid="6461865960961414961">"Ekran görüntüsü alındı."</string>
     <string name="screenshot_saved_text" msgid="1152839647677558815">"Ekran görüntünüzü izlemek için dokunun."</string>
     <string name="screenshot_failed_title" msgid="705781116746922771">"Ekran görüntüsü alınamadı."</string>
-    <string name="screenshot_failed_text" msgid="1260203058661337274">"Depolama alanı sınırlı olduğundan veya uygulamanız ya da kuruluşunuz tarafından izin verilmediğinden ekran görüntüsü alınamıyor."</string>
+    <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Depolama alanı sınırlı olduğundan ekran görüntüsü kaydedilemiyor."</string>
+    <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Uygulama veya kuruluşunuz, ekran görüntüsü alınmasına izin vermiyor."</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"USB dosya aktarım seçenekleri"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Medya oynatıcı olarak ekle (MTP)"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"Kamera olarak ekle (PTP)"</string>
@@ -206,6 +207,7 @@
     <string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"Daha uzun süre."</string>
     <string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"Daha kısa süre."</string>
     <string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"El feneri kapalı."</string>
+    <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"El feneri kullanılamıyor."</string>
     <string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"El feneri açık."</string>
     <string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"El feneri kapatıldı."</string>
     <string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"El feneri açıldı."</string>
@@ -218,6 +220,10 @@
     <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"Çalışma modu açık."</string>
     <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"Çalışma modu kapatıldı."</string>
     <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"Çalışma modu açıldı."</string>
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_off (650231949881093289) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_on (4218725402373934151) -->
+    <skip />
     <string name="accessibility_brightness" msgid="8003681285547803095">"Ekran parlaklığı"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"2G-3G veri kullanımı duraklatıldı"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"4G veri kullanımı duraklatıldı"</string>
@@ -304,6 +310,8 @@
     <string name="recents_launch_disabled_message" msgid="1624523193008871793">"<xliff:g id="APP">%s</xliff:g>, güvenli modda devre dışıdır."</string>
     <string name="recents_history_button_label" msgid="5153358867807604821">"Geçmiş"</string>
     <string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"Sil"</string>
+    <string name="recents_drag_non_dockable_task_message" msgid="2935843902795166158">"Bu uygulama, çoklu pencere kullanımını desteklemiyor"</string>
+    <string name="recents_launch_non_dockable_task_label" msgid="7862379814938391888">"Uygulama, çoklu pencere kullanımını desteklemiyor"</string>
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Yatay Ayırma"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Dikey Ayırma"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Özel Ayırma"</string>
@@ -451,18 +459,23 @@
     <string name="enable_bluetooth_title" msgid="5027037706500635269">"Bluetooth açılsın mı?"</string>
     <string name="enable_bluetooth_message" msgid="9106595990708985385">"Klavyenizi tabletinize bağlamak için önce Bluetooth\'u açmanız gerekir."</string>
     <string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"Aç"</string>
-    <string name="apply_to_topic" msgid="3641403489318659666">"<xliff:g id="TOPIC_NAME">%1$s</xliff:g> bildirimlerine uygula"</string>
-    <string name="apply_to_app" msgid="363016783939815960">"Bu uygulamadan gelen tüm bildirimlere uygulansın mı?"</string>
+    <string name="show_silently" msgid="6841966539811264192">"Bildirimleri sessizce göster"</string>
+    <string name="block" msgid="2734508760962682611">"Tüm bildirimleri engelle"</string>
+    <string name="do_not_silence" msgid="6878060322594892441">"Sessiz moda alma"</string>
+    <string name="do_not_silence_block" msgid="4070647971382232311">"Sessiz moda alma veya engelleme"</string>
+    <string name="tuner_full_importance_settings" msgid="8103289238676424226">"Tüm önem ayarlarını göster"</string>
     <string name="blocked_importance" msgid="5198578988978234161">"Engellendi"</string>
+    <string name="min_importance" msgid="1901894910809414782">"Önemi en düşük"</string>
     <string name="low_importance" msgid="4109929986107147930">"Önem düzeyi düşük"</string>
     <string name="default_importance" msgid="8192107689995742653">"Önem düzeyi normal"</string>
     <string name="high_importance" msgid="1527066195614050263">"Önem düzeyi yüksek"</string>
     <string name="max_importance" msgid="5089005872719563894">"Önem düzeyi acil"</string>
     <string name="notification_importance_blocked" msgid="2397192642657872872">"Bu bildirimleri hiçbir zaman gösterme"</string>
-    <string name="notification_importance_low" msgid="4383563267370859725">"Bildirim listesinin en altında sessizce göster"</string>
-    <string name="notification_importance_default" msgid="4926529615920610817">"Bu bildirimleri sessizce göster"</string>
-    <string name="notification_importance_high" msgid="3222680136612408223">"Bildirim listesinin en üstünde göster ve ses çıkar"</string>
-    <string name="notification_importance_max" msgid="5236987171904756134">"Ekrana getir ve ses çıkar"</string>
+    <string name="notification_importance_min" msgid="1938190340516905748">"Bildirim listesinin en altında sessizce göster"</string>
+    <string name="notification_importance_low" msgid="3657252049508213048">"Bu bildirimleri sessizce göster"</string>
+    <string name="notification_importance_default" msgid="4466466472622442175">"Bu bildirimlerin ses çıkarmasına izin ver"</string>
+    <string name="notification_importance_high" msgid="2135428926525093825">"Ekrana getir ve sesli bildirime izin ver"</string>
+    <string name="notification_importance_max" msgid="5806278962376556491">"Bildirim listesinin üstünde göster, ekrana getir ve sesli bildirime izin ver"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"Diğer ayarlar"</string>
     <string name="notification_done" msgid="5279426047273930175">"Bitti"</string>
     <string name="color_and_appearance" msgid="1254323855964993144">"Renk ve görünüm"</string>
@@ -476,7 +489,7 @@
     <string name="use_dark_theme" msgid="2900938704964299312">"Android OS için koyu renk tema kullan"</string>
     <string name="adjust_tint" msgid="3398569573231409878">"Tonu ayarla"</string>
     <string name="adjust_brightness" msgid="980039329808178246">"Parlaklığı ayarla"</string>
-    <string name="night_mode_disclaimer" msgid="3297928749219711334">"Koyu renk tema, Android OS\'nin normalde Ayarlar ve bildirimler gibi açık renk bir temayla görüntülenen temel alanlarına uygulanır."</string>
+    <string name="night_mode_disclaimer" msgid="598914896926759578">"Koyu renk tema, Android OS\'nin normalde Ayarlar gibi açık renk bir temayla görüntülenen temel alanlarına uygulanır."</string>
     <string name="color_apply" msgid="9212602012641034283">"Uygula"</string>
     <string name="color_revert_title" msgid="4746666545480534663">"Ayarları onaylayın"</string>
     <string name="color_revert_message" msgid="9116001069397996691">"Bazı renkler bu cihazı kullanılmaz yapabilir. Bu renkleri onaylamak için Tamam\'ı tıklayın. Tıklamazsanız bu ayarlar 10 saniye sonra sıfırlanacaktır."</string>
@@ -535,4 +548,10 @@
     <item msgid="2139628951880142927">"Şarj olurken yüzdeyi göster (varsayılan)"</item>
     <item msgid="3327323682209964956">"Bu simgeyi gösterme"</item>
   </string-array>
+    <string name="other" msgid="4060683095962566764">"Diğer"</string>
+    <string name="accessibility_divider" msgid="5903423481953635044">"Bölünmüş ekran ayırıcı"</string>
+    <string name="accessibility_action_divider_move_down" msgid="704893304141890042">"Aşağı taşı"</string>
+    <string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"Yukarı taşı"</string>
+    <string name="accessibility_action_divider_move_left" msgid="9218189832115847253">"Sola taşı"</string>
+    <string name="accessibility_action_divider_move_right" msgid="4671522715182567972">"Sağa taşı"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-tr/strings_tv.xml b/packages/SystemUI/res/values-tr/strings_tv.xml
new file mode 100644
index 0000000..255df49
--- /dev/null
+++ b/packages/SystemUI/res/values-tr/strings_tv.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2016, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <!-- no translation found for pip_close (3480680679023423574) -->
+    <skip />
+    <string name="pip_fullscreen" msgid="8604643018538487816">"Tam ekran"</string>
+    <string name="pip_play" msgid="674145557658227044">"Oynat"</string>
+    <string name="pip_pause" msgid="8412075640017218862">"Duraklat"</string>
+    <!-- no translation found for pip_hold_home (340086535668778109) -->
+    <skip />
+    <!-- no translation found for pip_onboarding_description (2627737116380318292) -->
+    <skip />
+    <!-- no translation found for pip_onboarding_button (3957426748484904611) -->
+    <skip />
+</resources>
diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml
index 6a47d84..41b89f9 100644
--- a/packages/SystemUI/res/values-uk/strings.xml
+++ b/packages/SystemUI/res/values-uk/strings.xml
@@ -75,7 +75,8 @@
     <string name="screenshot_saved_title" msgid="6461865960961414961">"Знімок екрана зроблено."</string>
     <string name="screenshot_saved_text" msgid="1152839647677558815">"Торкніться, щоб переглянути знімок екрана."</string>
     <string name="screenshot_failed_title" msgid="705781116746922771">"Не вдалося зробити знімок екрана."</string>
-    <string name="screenshot_failed_text" msgid="1260203058661337274">"Не вдається зробити знімок екрана через обмежений обсяг пам’яті або заборону додатка чи організації."</string>
+    <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Не вдалося зберегти знімок екрана через обмежений обсяг пам’яті."</string>
+    <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Додаток або ваша організація не дозволяють робити знімки екрана."</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"Парам.передав.файлів через USB"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Підключити як медіапрогравач (MTP)"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"Підключити як камеру (PTP)"</string>
@@ -208,6 +209,7 @@
     <string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"Більше часу."</string>
     <string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"Менше часу."</string>
     <string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"Ліхтарик вимк."</string>
+    <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"Ліхтарик недоступний."</string>
     <string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"Ліхтарик увімк."</string>
     <string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"Ліхтарик вимкнено."</string>
     <string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"Ліхтарик увімкнено."</string>
@@ -220,6 +222,10 @@
     <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"Робочий режим увімкнено."</string>
     <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"Робочий режим вимкнено."</string>
     <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"Робочий режим увімкнено."</string>
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_off (650231949881093289) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_on (4218725402373934151) -->
+    <skip />
     <string name="accessibility_brightness" msgid="8003681285547803095">"Яскравість дисплея"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"Передавання даних 2G–3G призупинено"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"Передавання даних 4G призупинено"</string>
@@ -306,6 +312,8 @@
     <string name="recents_launch_disabled_message" msgid="1624523193008871793">"Додаток <xliff:g id="APP">%s</xliff:g> вимкнено в безпечному режимі."</string>
     <string name="recents_history_button_label" msgid="5153358867807604821">"Історія"</string>
     <string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"Очистити"</string>
+    <string name="recents_drag_non_dockable_task_message" msgid="2935843902795166158">"Цей додаток не підтримує багатоекранний режим"</string>
+    <string name="recents_launch_non_dockable_task_label" msgid="7862379814938391888">"Додаток не підтримує багатоекранний режим"</string>
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Розділити горизонтально"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Розділити вертикально"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Розділити (власний варіант)"</string>
@@ -453,18 +461,23 @@
     <string name="enable_bluetooth_title" msgid="5027037706500635269">"Увімкнути Bluetooth?"</string>
     <string name="enable_bluetooth_message" msgid="9106595990708985385">"Щоб під’єднати клавіатуру до планшета, спершу потрібно ввімкнути Bluetooth."</string>
     <string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"Увімкнути"</string>
-    <string name="apply_to_topic" msgid="3641403489318659666">"Застосувати до сповіщень на тему \"<xliff:g id="TOPIC_NAME">%1$s</xliff:g>\""</string>
-    <string name="apply_to_app" msgid="363016783939815960">"Застосувати до всіх сповіщень із цього додатка"</string>
+    <string name="show_silently" msgid="6841966539811264192">"Показувати сповіщення без звукового сигналу"</string>
+    <string name="block" msgid="2734508760962682611">"Блокувати всі сповіщення"</string>
+    <string name="do_not_silence" msgid="6878060322594892441">"Не вимикати звуковий сигнал"</string>
+    <string name="do_not_silence_block" msgid="4070647971382232311">"Не вимикати звуковий сигнал і не блокувати"</string>
+    <string name="tuner_full_importance_settings" msgid="8103289238676424226">"Показати налаштування пріоритетності"</string>
     <string name="blocked_importance" msgid="5198578988978234161">"Заблоковано"</string>
+    <string name="min_importance" msgid="1901894910809414782">"Низький пріоритет"</string>
     <string name="low_importance" msgid="4109929986107147930">"Низький пріоритет"</string>
     <string name="default_importance" msgid="8192107689995742653">"Стандартний пріоритет"</string>
     <string name="high_importance" msgid="1527066195614050263">"Високий пріоритет"</string>
     <string name="max_importance" msgid="5089005872719563894">"Терміново"</string>
     <string name="notification_importance_blocked" msgid="2397192642657872872">"Ніколи не показувати ці сповіщення"</string>
-    <string name="notification_importance_low" msgid="4383563267370859725">"Показувати сповіщення внизу списку без звукового сигналу"</string>
-    <string name="notification_importance_default" msgid="4926529615920610817">"Показувати ці сповіщення без звукового сигналу"</string>
-    <string name="notification_importance_high" msgid="3222680136612408223">"Показувати сповіщення вгорі списку зі звуковим сигналом"</string>
-    <string name="notification_importance_max" msgid="5236987171904756134">"Показувати сповіщення на екрані зі звуковим сигналом"</string>
+    <string name="notification_importance_min" msgid="1938190340516905748">"Показувати сповіщення внизу списку без звукового сигналу"</string>
+    <string name="notification_importance_low" msgid="3657252049508213048">"Показувати ці сповіщення без звукового сигналу"</string>
+    <string name="notification_importance_default" msgid="4466466472622442175">"Увімкнути звуковий сигнал для цих сповіщень"</string>
+    <string name="notification_importance_high" msgid="2135428926525093825">"Показувати сповіщення на екрані зі звуковим сигналом"</string>
+    <string name="notification_importance_max" msgid="5806278962376556491">"Показувати сповіщення вгорі списку, на екрані та зі звуковим сигналом"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"Більше налаштувань"</string>
     <string name="notification_done" msgid="5279426047273930175">"Готово"</string>
     <string name="color_and_appearance" msgid="1254323855964993144">"Колір і вигляд"</string>
@@ -478,7 +491,7 @@
     <string name="use_dark_theme" msgid="2900938704964299312">"Використати нічну тему для ОС Android"</string>
     <string name="adjust_tint" msgid="3398569573231409878">"Налаштувати відтінок"</string>
     <string name="adjust_brightness" msgid="980039329808178246">"Регулювати яскравість"</string>
-    <string name="night_mode_disclaimer" msgid="3297928749219711334">"Нічна тема застосовується в основних областях ОС Android, які зазвичай відображаються у світлій темі, як-от у Налаштуваннях і сповіщеннях."</string>
+    <string name="night_mode_disclaimer" msgid="598914896926759578">"Темна тема застосовується в основних областях ОС Android, які зазвичай відображаються у світлій темі, як-от у налаштуваннях."</string>
     <string name="color_apply" msgid="9212602012641034283">"Застосувати"</string>
     <string name="color_revert_title" msgid="4746666545480534663">"Підтвердити налаштування"</string>
     <string name="color_revert_message" msgid="9116001069397996691">"Деякі налаштування кольорів можуть зробити цей пристрій непридатним для використання. Натисніть OK, щоб підтвердити налаштування, інакше їх буде скинуто через 10 секунд."</string>
@@ -537,4 +550,10 @@
     <item msgid="2139628951880142927">"Показувати відсотки під час заряджання (за умовчанням)"</item>
     <item msgid="3327323682209964956">"Не показувати цей значок"</item>
   </string-array>
+    <string name="other" msgid="4060683095962566764">"Інше"</string>
+    <string name="accessibility_divider" msgid="5903423481953635044">"Розділювач екрана"</string>
+    <string name="accessibility_action_divider_move_down" msgid="704893304141890042">"Перемістити вниз"</string>
+    <string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"Перемістити вгору"</string>
+    <string name="accessibility_action_divider_move_left" msgid="9218189832115847253">"Перемістити ліворуч"</string>
+    <string name="accessibility_action_divider_move_right" msgid="4671522715182567972">"Перемістити праворуч"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-uk/strings_tv.xml b/packages/SystemUI/res/values-uk/strings_tv.xml
new file mode 100644
index 0000000..22bcf52
--- /dev/null
+++ b/packages/SystemUI/res/values-uk/strings_tv.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.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="pip_close" msgid="3480680679023423574">"Закрити PIP"</string>
+    <string name="pip_fullscreen" msgid="8604643018538487816">"На весь екран"</string>
+    <string name="pip_play" msgid="674145557658227044">"Відтворити"</string>
+    <string name="pip_pause" msgid="8412075640017218862">"Призупинити"</string>
+    <string name="pip_hold_home" msgid="340086535668778109">"Щоб керувати PIP, утримуйте кнопку "<b>"ГОЛОВНИЙ ЕКРАН"</b></string>
+    <string name="pip_onboarding_description" msgid="2627737116380318292">"Щоб керувати PIP,\nутримуйте кнопку \"ГОЛОВНИЙ ЕКРАН\""</string>
+    <string name="pip_onboarding_button" msgid="3957426748484904611">"OK"</string>
+</resources>
diff --git a/packages/SystemUI/res/values-ur-rPK/strings.xml b/packages/SystemUI/res/values-ur-rPK/strings.xml
index afb5db8..ba2d014 100644
--- a/packages/SystemUI/res/values-ur-rPK/strings.xml
+++ b/packages/SystemUI/res/values-ur-rPK/strings.xml
@@ -73,7 +73,8 @@
     <string name="screenshot_saved_title" msgid="6461865960961414961">"اسکرین شاٹ کیپچر کیا گیا۔"</string>
     <string name="screenshot_saved_text" msgid="1152839647677558815">"اپنے اسکرین شاٹ دیکھنے کیلئے چھوئیں۔"</string>
     <string name="screenshot_failed_title" msgid="705781116746922771">"اسکرین شاٹ کیپچر نہیں کر سکے۔"</string>
-    <string name="screenshot_failed_text" msgid="1260203058661337274">"اسٹوریج کی محدود جگہ کی وجہ سے اسکرین شاٹ نہیں لے سکتے، یا ایپ یا آپکی تنظیم کے ذریعے یہ مجاز نہیں ہے۔"</string>
+    <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"محدود اسٹوریج جگہ کی وجہ سے اسکرین شاٹس نہیں لئے جا سکتے۔"</string>
+    <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"ایپ یا آپ کی تنظیم کی جانب سے اسکرین شاٹس لینے کی اجازت نہیں ہے۔"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"‏USB فائل منتقل کرنیکے اختیارات"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"‏ایک میڈیا پلیئر (MTP) کے بطور ماؤنٹ کریں"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"‏ایک کیمرہ (PTP) کے بطور ماؤنٹ کریں"</string>
@@ -206,6 +207,7 @@
     <string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"مزید وقت۔"</string>
     <string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"کم وقت۔"</string>
     <string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"فلیش لائٹ آف ہے۔"</string>
+    <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"فلیش لائٹ دستیاب نہیں ہے"</string>
     <string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"فلیش لائٹ آن ہے۔"</string>
     <string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"فلیش لائٹ کو آف کر دیا گیا۔"</string>
     <string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"فلیش لائٹ کو آن کر دیا گیا۔"</string>
@@ -218,6 +220,10 @@
     <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"کام موڈ آن ہے۔"</string>
     <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"کام موڈ آف ہو گیا۔"</string>
     <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"کام موڈ آن ہو گیا۔"</string>
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_off (650231949881093289) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_on (4218725402373934151) -->
+    <skip />
     <string name="accessibility_brightness" msgid="8003681285547803095">"ڈسپلے کی چمک"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"‏2G-3G ڈیٹا موقوف کر دیا گیا"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"‏4G ڈیٹا موقوف کر دیا گیا"</string>
@@ -304,6 +310,8 @@
     <string name="recents_launch_disabled_message" msgid="1624523193008871793">"محفوظ موڈ میں <xliff:g id="APP">%s</xliff:g> غیر فعال ہوتی ہے۔"</string>
     <string name="recents_history_button_label" msgid="5153358867807604821">"سرگزشت"</string>
     <string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"صاف کریں"</string>
+    <string name="recents_drag_non_dockable_task_message" msgid="2935843902795166158">"یہ ایپ ملٹی ونڈو کی معاونت نہیں کرتی"</string>
+    <string name="recents_launch_non_dockable_task_label" msgid="7862379814938391888">"ایپ ملٹی ونڈز کی معاونت نہیں کرتی"</string>
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"بلحاظ افقی الگ کریں"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"بلحاظ عمودی الگ کریں"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"بلحاظ حسب ضرورت الگ کریں"</string>
@@ -451,18 +459,23 @@
     <string name="enable_bluetooth_title" msgid="5027037706500635269">"بلوٹوتھ آن کریں؟"</string>
     <string name="enable_bluetooth_message" msgid="9106595990708985385">"اپنے کی بورڈ کو اپنے ٹیبلٹ کے ساتھ منسلک کرنے کیلئے پہلے آپ کو اپنا بلو ٹوتھ آن کرنا ہو گا۔"</string>
     <string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"آن کریں"</string>
-    <string name="apply_to_topic" msgid="3641403489318659666">"<xliff:g id="TOPIC_NAME">%1$s</xliff:g> اطلاعات پر لاگو کریں"</string>
-    <string name="apply_to_app" msgid="363016783939815960">"اس ایپ سے تمام اطلاعات پر لاگو کریں"</string>
+    <string name="show_silently" msgid="6841966539811264192">"اطلاعات خاموشی سے دکھائیں"</string>
+    <string name="block" msgid="2734508760962682611">"تمام اطلاعات کو مسدود کریں"</string>
+    <string name="do_not_silence" msgid="6878060322594892441">"خاموش نہ کریں"</string>
+    <string name="do_not_silence_block" msgid="4070647971382232311">"خاموش یا مسدود نہ کریں"</string>
+    <string name="tuner_full_importance_settings" msgid="8103289238676424226">"اہمیت کی پوری ترتیبات دکھائیں"</string>
     <string name="blocked_importance" msgid="5198578988978234161">"مسدود کردہ"</string>
+    <string name="min_importance" msgid="1901894910809414782">"کم سے کم اہمیت"</string>
     <string name="low_importance" msgid="4109929986107147930">"کم اہمیت"</string>
     <string name="default_importance" msgid="8192107689995742653">"عمومی اہمیت"</string>
     <string name="high_importance" msgid="1527066195614050263">"زیادہ اہمیت"</string>
     <string name="max_importance" msgid="5089005872719563894">"فوری اہمیت"</string>
     <string name="notification_importance_blocked" msgid="2397192642657872872">"یہ اطلاعات کبھی مت دکھائیں"</string>
-    <string name="notification_importance_low" msgid="4383563267370859725">"اطلاعات کی فہرست کے سب سے نیچے خاموشی سے دکھائیں"</string>
-    <string name="notification_importance_default" msgid="4926529615920610817">"خاموشی سے یہ اطلاعات دکھائیں"</string>
-    <string name="notification_importance_high" msgid="3222680136612408223">"اطلاعات کی فہرست پر سب سے اوپر دکھائیں اور آواز چلائیں"</string>
-    <string name="notification_importance_max" msgid="5236987171904756134">"اسکرین پر دکھائیں اور آواز چلائیں"</string>
+    <string name="notification_importance_min" msgid="1938190340516905748">"اطلاعات کی فہرست کے سب سے نیچے خاموشی سے دکھائیں"</string>
+    <string name="notification_importance_low" msgid="3657252049508213048">"خاموشی سے یہ اطلاعات دکھائیں"</string>
+    <string name="notification_importance_default" msgid="4466466472622442175">"ان اطلاعات کو آواز نکالنے کی اجازت دیں"</string>
+    <string name="notification_importance_high" msgid="2135428926525093825">"اسکرین پر دکھائیں اور آواز کی اجازت دیں"</string>
+    <string name="notification_importance_max" msgid="5806278962376556491">"اطلاعات کی فہرست پر سب سے اوپر دکھائیں، اسکرین پر دکھائیں اور آواز کی اجازت دیں"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"مزید ترتیبات"</string>
     <string name="notification_done" msgid="5279426047273930175">"ہوگیا"</string>
     <string name="color_and_appearance" msgid="1254323855964993144">"رنگ اور ظہور"</string>
@@ -476,7 +489,7 @@
     <string name="use_dark_theme" msgid="2900938704964299312">"‏Android OS کیلئے ڈارک تھیم استعمال کریں"</string>
     <string name="adjust_tint" msgid="3398569573231409878">"ٹنٹ ایڈجسٹ کریں"</string>
     <string name="adjust_brightness" msgid="980039329808178246">"چمک کو ایڈجسٹ کریں"</string>
-    <string name="night_mode_disclaimer" msgid="3297928749219711334">"‏ڈارک تھیم Android OS کی بنیادی جگہوں پر لاگو کی جاتی ہے جو عام طور لائٹ تھیم میں ڈسپلے ہوتے ہیں، جیسے ترتیبات اور اطلاعات۔"</string>
+    <string name="night_mode_disclaimer" msgid="598914896926759578">"‏ڈارک تھیم Android OS کی بنیادی جگہوں پر لاگو کی جاتی ہے جو عام طور لائٹ تھیم میں ڈسپلے ہوتے ہیں، جیسے ترتیبات۔"</string>
     <string name="color_apply" msgid="9212602012641034283">"لاگو کریں"</string>
     <string name="color_revert_title" msgid="4746666545480534663">"ترتیبات کی توثیق کریں"</string>
     <string name="color_revert_message" msgid="9116001069397996691">"رنگوں کی کچھ ترتیبات اس آلے کو ناقابل استعمال بنا سکتی ہیں۔ رنگوں کی ان ترتیبات کی توثیق کرنے کیلئے ٹھیک ہے پر کلک کریں، بصورت دیگر 10 سیکنڈ بعد یہ ترتیبات ری سیٹ ہو جائیں گی۔"</string>
@@ -535,4 +548,10 @@
     <item msgid="2139628951880142927">"چارج ہوتے وقت فیصد دکھائیں (ڈیفالٹ)"</item>
     <item msgid="3327323682209964956">"یہ آئیکن نہ دکھائیں"</item>
   </string-array>
+    <string name="other" msgid="4060683095962566764">"دیگر"</string>
+    <string name="accessibility_divider" msgid="5903423481953635044">"سپلٹ اسکرین تقسیم کار"</string>
+    <string name="accessibility_action_divider_move_down" msgid="704893304141890042">"نیچے منتقل کریں"</string>
+    <string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"اوپر منتقل کریں"</string>
+    <string name="accessibility_action_divider_move_left" msgid="9218189832115847253">"بائیں منتقل کریں"</string>
+    <string name="accessibility_action_divider_move_right" msgid="4671522715182567972">"دائیں منتقل کریں"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ur-rPK/strings_tv.xml b/packages/SystemUI/res/values-ur-rPK/strings_tv.xml
new file mode 100644
index 0000000..28987c3
--- /dev/null
+++ b/packages/SystemUI/res/values-ur-rPK/strings_tv.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2016, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <!-- no translation found for pip_close (3480680679023423574) -->
+    <skip />
+    <string name="pip_fullscreen" msgid="8604643018538487816">"فُل اسکرین"</string>
+    <string name="pip_play" msgid="674145557658227044">"چلائیں"</string>
+    <string name="pip_pause" msgid="8412075640017218862">"موقوف کریں"</string>
+    <!-- no translation found for pip_hold_home (340086535668778109) -->
+    <skip />
+    <!-- no translation found for pip_onboarding_description (2627737116380318292) -->
+    <skip />
+    <!-- no translation found for pip_onboarding_button (3957426748484904611) -->
+    <skip />
+</resources>
diff --git a/packages/SystemUI/res/values-uz-rUZ/strings.xml b/packages/SystemUI/res/values-uz-rUZ/strings.xml
index eafe80c..0ad7df6 100644
--- a/packages/SystemUI/res/values-uz-rUZ/strings.xml
+++ b/packages/SystemUI/res/values-uz-rUZ/strings.xml
@@ -73,7 +73,8 @@
     <string name="screenshot_saved_title" msgid="6461865960961414961">"Skrinshot saqlandi."</string>
     <string name="screenshot_saved_text" msgid="1152839647677558815">"Ko‘rish uchun bu yerga bosing."</string>
     <string name="screenshot_failed_title" msgid="705781116746922771">"Skrinshot saqlanmadi."</string>
-    <string name="screenshot_failed_text" msgid="1260203058661337274">"Ekrandan suratga olib bo‘lmadi: xotirada joy kam yoki ilova/tashkilot bunga ruxsat bermagan."</string>
+    <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Xotirada joy kamligi uchun skrinshotni saqlab bo‘lmadi."</string>
+    <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Ilova yoki tashkilotingiz skrinshot olishni taqiqlagan."</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"USB fayl ko‘chirish moslamalari"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Media pleyer sifatida ulash (MTP)"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"Kamera sifatida ulash (PTP)"</string>
@@ -206,6 +207,7 @@
     <string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"Ko‘proq vaqt."</string>
     <string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"Kamroq vaqt."</string>
     <string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"Fonar o‘chirilgan."</string>
+    <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"Bu yerda fonar yo‘q."</string>
     <string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"Fonar yoqilgan."</string>
     <string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"Fonar o‘chirildi."</string>
     <string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"Fonar yoqildi."</string>
@@ -217,7 +219,11 @@
     <string name="accessibility_quick_settings_work_mode_off" msgid="7045417396436552890">"Ish rejimi o‘chiq."</string>
     <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"Ish rejimi yoniq."</string>
     <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"Ish rejimi o‘chirib qo‘yildi."</string>
-    <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"Ish rejimi yoqildi."</string>
+    <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"Ishchi rejim yoqildi."</string>
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_off (650231949881093289) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_on (4218725402373934151) -->
+    <skip />
     <string name="accessibility_brightness" msgid="8003681285547803095">"Ekran yorqinligi"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"2G-3G internet to‘xtatib qo‘yildi"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"4G internet to‘xtatib qo‘yildi"</string>
@@ -304,6 +310,8 @@
     <string name="recents_launch_disabled_message" msgid="1624523193008871793">"Xavfsiz rejimda <xliff:g id="APP">%s</xliff:g> ilovasi o‘chirib qo‘yildi."</string>
     <string name="recents_history_button_label" msgid="5153358867807604821">"Jurnal"</string>
     <string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"Tozalash"</string>
+    <string name="recents_drag_non_dockable_task_message" msgid="2935843902795166158">"Bu ilova ko‘p oynali rejimni qo‘llab-quvvatlamaydi"</string>
+    <string name="recents_launch_non_dockable_task_label" msgid="7862379814938391888">"Bu ilova ko‘p oynali rejimni qo‘llab-quvvatlamaydi"</string>
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Gorizontal yo‘nalishda bo‘lish"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Vertikal yo‘nalishda bo‘lish"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Boshqa usulda bo‘lish"</string>
@@ -364,8 +372,8 @@
     <string name="user_remove_user_message" msgid="1453218013959498039">"Ushbu foydalanuvchining barcha ilovalari va ma’lumotlari o‘chirib tashlanadi."</string>
     <string name="user_remove_user_remove" msgid="7479275741742178297">"Olib tashlash"</string>
     <string name="battery_saver_notification_title" msgid="237918726750955859">"Quvvat tejash rejimi yoqildi"</string>
-    <string name="battery_saver_notification_text" msgid="820318788126672692">"Unumdorlikni pasaytiradi va fonda int-dan foyd-ni cheklaydi"</string>
-    <string name="battery_saver_notification_action_text" msgid="109158658238110382">"Quvvat tejash funksiyasini o‘chiring"</string>
+    <string name="battery_saver_notification_text" msgid="820318788126672692">"Unumdorlik pasayadi va fonda internetdan foydalanish cheklanadi"</string>
+    <string name="battery_saver_notification_action_text" msgid="109158658238110382">"Quvvat tejash rejimidan chiqish"</string>
     <string name="media_projection_dialog_text" msgid="3071431025448218928">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ilovasi qurilma ekranidagi har qanday tasvirni ko‘rishni boshlaydi."</string>
     <string name="media_projection_remember_text" msgid="3103510882172746752">"Boshqa ko‘rsatilmasin"</string>
     <string name="clear_all_notifications_text" msgid="814192889771462828">"Barchasini tozalash"</string>
@@ -451,18 +459,23 @@
     <string name="enable_bluetooth_title" msgid="5027037706500635269">"Bluetooth yoqilsinmi?"</string>
     <string name="enable_bluetooth_message" msgid="9106595990708985385">"Klaviaturani planshetingizga ulash uchun Bluetooth xizmatini yoqishingiz kerak."</string>
     <string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"Yoqish"</string>
-    <string name="apply_to_topic" msgid="3641403489318659666">"“<xliff:g id="TOPIC_NAME">%1$s</xliff:g>” bildirishnomalariga qo‘llash"</string>
-    <string name="apply_to_app" msgid="363016783939815960">"Ushbu ilovaning barcha bildirishnomalariga qo‘llash"</string>
+    <string name="show_silently" msgid="6841966539811264192">"Bildirishnomalar ovozsiz ko‘rsatilsin"</string>
+    <string name="block" msgid="2734508760962682611">"Barcha bildirishnomalar bloklansin"</string>
+    <string name="do_not_silence" msgid="6878060322594892441">"Ovozi o‘chirilmasin"</string>
+    <string name="do_not_silence_block" msgid="4070647971382232311">"Ovozi o‘chirilmasin yoki bloklanmasin"</string>
+    <string name="tuner_full_importance_settings" msgid="8103289238676424226">"Barcha muhimlik sozlamalarini ko‘rsatish"</string>
     <string name="blocked_importance" msgid="5198578988978234161">"Bloklangan"</string>
+    <string name="min_importance" msgid="1901894910809414782">"Kamroq muhim"</string>
     <string name="low_importance" msgid="4109929986107147930">"Kamroq muhim"</string>
     <string name="default_importance" msgid="8192107689995742653">"O‘rtacha muhim"</string>
     <string name="high_importance" msgid="1527066195614050263">"Juda muhim"</string>
     <string name="max_importance" msgid="5089005872719563894">"Favqulodda muhim"</string>
     <string name="notification_importance_blocked" msgid="2397192642657872872">"Bu bildirishnomalar boshqa ko‘rsatilmasin"</string>
-    <string name="notification_importance_low" msgid="4383563267370859725">"Bildirishnomalar ro‘yxatining oxirida ovozsiz ko‘rsatilsin"</string>
-    <string name="notification_importance_default" msgid="4926529615920610817">"Bu bildirishnomalar ovozsiz ko‘rsatilsin"</string>
-    <string name="notification_importance_high" msgid="3222680136612408223">"Bildirishnomalar ro‘yxatining boshida ovoz bilan ko‘rsatilsin"</string>
-    <string name="notification_importance_max" msgid="5236987171904756134">"Barcha oynalar ustida signal ovozi bilan ko‘rsatilsin"</string>
+    <string name="notification_importance_min" msgid="1938190340516905748">"Bildirishnomalar ro‘yxatining oxirida ovozsiz ko‘rsatilsin"</string>
+    <string name="notification_importance_low" msgid="3657252049508213048">"Bu bildirishnomalar ovozsiz ko‘rsatilsin"</string>
+    <string name="notification_importance_default" msgid="4466466472622442175">"Bu bildirishnomalar ovoz bilan ko‘rsatilsin"</string>
+    <string name="notification_importance_high" msgid="2135428926525093825">"Barcha oynalar ustida ovoz bilan ko‘rsatilsin"</string>
+    <string name="notification_importance_max" msgid="5806278962376556491">"Bildirishnomalar ro‘yxatining boshida va barcha oynalar ustida ovoz bilan ko‘rsatilsin"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"Boshqa sozlamalar"</string>
     <string name="notification_done" msgid="5279426047273930175">"Tayyor"</string>
     <string name="color_and_appearance" msgid="1254323855964993144">"Rang va ko‘rinishi"</string>
@@ -473,24 +486,24 @@
     <string name="turn_on_automatically" msgid="4167565356762016083">"Avtomatik yoqish"</string>
     <string name="turn_on_auto_summary" msgid="2190994512406701520">"Joylashuv va vaqtga mos ravishda tungi rejimga o‘tish"</string>
     <string name="when_night_mode_on" msgid="2969436026899172821">"Agar tungi rejim yoniq bo‘lsa"</string>
-    <string name="use_dark_theme" msgid="2900938704964299312">"Android OS uchun to‘q rangli mavzudan foyd-sh"</string>
-    <string name="adjust_tint" msgid="3398569573231409878">"Rangni o‘zgartirish"</string>
+    <string name="use_dark_theme" msgid="2900938704964299312">"Android uchun to‘q rangli mavzudan foydalanish"</string>
+    <string name="adjust_tint" msgid="3398569573231409878">"Rang tusini o‘zgartirish"</string>
     <string name="adjust_brightness" msgid="980039329808178246">"Yorqinlikni o‘zgartirish"</string>
-    <string name="night_mode_disclaimer" msgid="3297928749219711334">"To‘q rangli mavzu Android OS’ning o‘zak sahifalariga ham qo‘llaniladi va bu Sozlamalar va bildirishnomalar kabi och rangli mavzularda odatdagiday ko‘rsatiladi."</string>
+    <string name="night_mode_disclaimer" msgid="598914896926759578">"To‘q rangli mavzu Android tizimining odatda och rangda ko‘rsatiladigan o‘zak sahifalariga (masalan, Sozlamalar) nisbatan qo‘llaniladi."</string>
     <string name="color_apply" msgid="9212602012641034283">"Qo‘llash"</string>
     <string name="color_revert_title" msgid="4746666545480534663">"Sozlamalarni tasdiqlang"</string>
     <string name="color_revert_message" msgid="9116001069397996691">"Ba’zi rang sozlamalari qurilmadan foydalanishni qiyinlashtirish mumkin. Tanlgan parametrlarni tasdiqlash uchun “OK” tugmasini bosing. Aks holda, ular 10 soniyadan so‘ng qayta tiklanadi."</string>
     <string name="battery_panel_title" msgid="7944156115535366613">"Batareya sarfi"</string>
     <string name="battery_detail_charging_summary" msgid="1279095653533044008">"Quvvat tejash rejimidan quvvatlash vaqtida foydalanib bo‘lmaydi"</string>
     <string name="battery_detail_switch_title" msgid="6285872470260795421">"Quvvat tejash rejimi"</string>
-    <string name="battery_detail_switch_summary" msgid="9049111149407626804">"Unumdorlikni pasaytiradi va fonda internetdan foydalanishni cheklaydi"</string>
+    <string name="battery_detail_switch_summary" msgid="9049111149407626804">"Unumdorlik pasayadi va fonda internetdan foydalanish cheklanadi"</string>
     <string name="keyboard_shortcut_group_system" msgid="6472647649616541064">"Tizim"</string>
     <string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"Bosh ekran"</string>
     <string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"So‘nggi ishlatilganlar"</string>
     <string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"Orqaga"</string>
-    <string name="tuner_full_zen_title" msgid="4540823317772234308">"Ovoz balandligini boshqarish tugmalari bilan ko‘rsatilsin"</string>
+    <string name="tuner_full_zen_title" msgid="4540823317772234308">"Ovoz balandligini boshqarish tugmalari bilan ko‘rsatish"</string>
     <string name="volume_and_do_not_disturb" msgid="3373784330208603030">"Bezovta qilinmasin"</string>
-    <string name="volume_dnd_silent" msgid="4363882330723050727">"Ovoz balandligini boshqarish tezkor tugmalari"</string>
+    <string name="volume_dnd_silent" msgid="4363882330723050727">"Ovoz balandligini boshqarish tugmalari"</string>
     <string name="volume_up_silent" msgid="7141255269783588286">"Ovozni ko‘targanda “Bezovta qilinmasin” rejimini o‘chirish"</string>
     <string name="battery" msgid="7498329822413202973">"Batareya"</string>
     <string name="clock" msgid="7416090374234785905">"Soat"</string>
@@ -528,11 +541,17 @@
   <string-array name="clock_options">
     <item msgid="5965318737560463480">"Soat, daqiqa va soniyalar ko‘rsatilsin"</item>
     <item msgid="1427801730816895300">"Soat va daqiqalar ko‘rsatilsin (birlamchi)"</item>
-    <item msgid="3830170141562534721">"Bu ikonka boshqa ko‘rsatilmasin"</item>
+    <item msgid="3830170141562534721">"Bu belgi boshqa ko‘rsatilmasin"</item>
   </string-array>
   <string-array name="battery_options">
     <item msgid="3160236755818672034">"Har doim foizda ko‘rsatilsin"</item>
     <item msgid="2139628951880142927">"Quvvat olayotganda foizda ko‘rsatilsin (birlamchi)"</item>
-    <item msgid="3327323682209964956">"Bu ikonka boshqa ko‘rsatilmasin"</item>
+    <item msgid="3327323682209964956">"Bu belgi boshqa ko‘rsatilmasin"</item>
   </string-array>
+    <string name="other" msgid="4060683095962566764">"Boshqa"</string>
+    <string name="accessibility_divider" msgid="5903423481953635044">"Ekranni ikkiga bo‘lish chizig‘i"</string>
+    <string name="accessibility_action_divider_move_down" msgid="704893304141890042">"Pastga siljitish"</string>
+    <string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"Tepaga siljitish"</string>
+    <string name="accessibility_action_divider_move_left" msgid="9218189832115847253">"Chapga siljitish"</string>
+    <string name="accessibility_action_divider_move_right" msgid="4671522715182567972">"O‘ngga siljitish"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-uz-rUZ/strings_tv.xml b/packages/SystemUI/res/values-uz-rUZ/strings_tv.xml
new file mode 100644
index 0000000..00d25960
--- /dev/null
+++ b/packages/SystemUI/res/values-uz-rUZ/strings_tv.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2016, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <!-- no translation found for pip_close (3480680679023423574) -->
+    <skip />
+    <string name="pip_fullscreen" msgid="8604643018538487816">"To‘liq ekran"</string>
+    <string name="pip_play" msgid="674145557658227044">"Ijro"</string>
+    <string name="pip_pause" msgid="8412075640017218862">"Pauza"</string>
+    <!-- no translation found for pip_hold_home (340086535668778109) -->
+    <skip />
+    <!-- no translation found for pip_onboarding_description (2627737116380318292) -->
+    <skip />
+    <!-- no translation found for pip_onboarding_button (3957426748484904611) -->
+    <skip />
+</resources>
diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml
index aca359e..9a80cb2 100644
--- a/packages/SystemUI/res/values-vi/strings.xml
+++ b/packages/SystemUI/res/values-vi/strings.xml
@@ -73,7 +73,8 @@
     <string name="screenshot_saved_title" msgid="6461865960961414961">"Đã chụp ảnh màn hình."</string>
     <string name="screenshot_saved_text" msgid="1152839647677558815">"Chạm để xem ảnh chụp màn hình của bạn."</string>
     <string name="screenshot_failed_title" msgid="705781116746922771">"Không thể chụp ảnh màn hình."</string>
-    <string name="screenshot_failed_text" msgid="1260203058661337274">"Ko thể chụp ảnh màn hình do dung lượng bộ nhớ hạn chế hoặc ứng dụng hay tổ chức của bạn ko cho phép."</string>
+    <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Không thể lưu ảnh chụp màn hình do giới hạn dung lượng bộ nhớ."</string>
+    <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Ứng dụng hoặc tổ chức của bạn không cho phép chụp ảnh màn hình."</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"Tùy chọn truyền tệp USB"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Gắn như một trình phát đa phương tiện (MTP)"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"Gắn như một máy ảnh (PTP)"</string>
@@ -206,6 +207,7 @@
     <string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"Nhiều thời gian hơn."</string>
     <string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"Ít thời gian hơn."</string>
     <string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"Đèn pin tắt."</string>
+    <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"Đèn flash không khả dụng."</string>
     <string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"Đèn pin bật."</string>
     <string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"Đã tắt đèn pin."</string>
     <string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"Đã bật đèn pin."</string>
@@ -218,6 +220,10 @@
     <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"Chế độ làm việc bật."</string>
     <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"Chế độ làm việc đã tắt."</string>
     <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"Chế độ làm việc đã bật."</string>
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_off (650231949881093289) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_on (4218725402373934151) -->
+    <skip />
     <string name="accessibility_brightness" msgid="8003681285547803095">"Độ sáng màn hình"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"Đã tạm dừng dữ liệu 2G-3G"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"Đã tạm dừng dữ liệu 4G"</string>
@@ -301,10 +307,11 @@
     <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"khóa màn hình"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"tìm kiếm"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"Không thể khởi động <xliff:g id="APP">%s</xliff:g>."</string>
-    <!-- no translation found for recents_launch_disabled_message (1624523193008871793) -->
-    <skip />
+    <string name="recents_launch_disabled_message" msgid="1624523193008871793">"<xliff:g id="APP">%s</xliff:g> bị tắt ở chế độ an toàn."</string>
     <string name="recents_history_button_label" msgid="5153358867807604821">"Lịch sử"</string>
     <string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"Xóa"</string>
+    <string name="recents_drag_non_dockable_task_message" msgid="2935843902795166158">"Ứng dụng này không hỗ trợ chế độ nhiều cửa sổ"</string>
+    <string name="recents_launch_non_dockable_task_label" msgid="7862379814938391888">"Ứng dụng không hỗ trợ chế độ nhiều cửa sổ"</string>
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Phân tách ngang"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Phân tách dọc"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Tùy chỉnh phân tách"</string>
@@ -452,18 +459,23 @@
     <string name="enable_bluetooth_title" msgid="5027037706500635269">"Bật Bluetooth?"</string>
     <string name="enable_bluetooth_message" msgid="9106595990708985385">"Để kết nối bàn phím với máy tính bảng, trước tiên, bạn phải bật Bluetooth."</string>
     <string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"Bật"</string>
-    <string name="apply_to_topic" msgid="3641403489318659666">"Áp dụng cho thông báo <xliff:g id="TOPIC_NAME">%1$s</xliff:g>"</string>
-    <string name="apply_to_app" msgid="363016783939815960">"Áp dụng cho tất cả thông báo từ ứng dụng này"</string>
+    <string name="show_silently" msgid="6841966539811264192">"Hiển thị im lặng các thông báo"</string>
+    <string name="block" msgid="2734508760962682611">"Chặn tất cả thông báo"</string>
+    <string name="do_not_silence" msgid="6878060322594892441">"Không im lặng"</string>
+    <string name="do_not_silence_block" msgid="4070647971382232311">"Không im lặng hoặc chặn"</string>
+    <string name="tuner_full_importance_settings" msgid="8103289238676424226">"Hiển thị cài đặt tầm quan trọng đầy đủ"</string>
     <string name="blocked_importance" msgid="5198578988978234161">"Bị chặn"</string>
+    <string name="min_importance" msgid="1901894910809414782">"Tầm quan trọng thấp nhất"</string>
     <string name="low_importance" msgid="4109929986107147930">"Tầm quan trọng thấp"</string>
     <string name="default_importance" msgid="8192107689995742653">"Tầm quan trọng bình thường"</string>
     <string name="high_importance" msgid="1527066195614050263">"Tầm quan trọng cao"</string>
     <string name="max_importance" msgid="5089005872719563894">"Tầm quan trọng khẩn cấp"</string>
     <string name="notification_importance_blocked" msgid="2397192642657872872">"Không bao giờ hiển thị các thông báo này"</string>
-    <string name="notification_importance_low" msgid="4383563267370859725">"Hiển thị im lặng ở cuối danh sách thông báo"</string>
-    <string name="notification_importance_default" msgid="4926529615920610817">"Hiển thị im lặng các thông báo này"</string>
-    <string name="notification_importance_high" msgid="3222680136612408223">"Hiển thị ở đầu danh sách thông báo và phát ra âm thanh"</string>
-    <string name="notification_importance_max" msgid="5236987171904756134">"Hiển thị trên màn hình và phát ra âm thanh"</string>
+    <string name="notification_importance_min" msgid="1938190340516905748">"Hiển thị im lặng ở cuối danh sách thông báo"</string>
+    <string name="notification_importance_low" msgid="3657252049508213048">"Hiển thị im lặng các thông báo này"</string>
+    <string name="notification_importance_default" msgid="4466466472622442175">"Cho phép các thông báo này phát ra âm thanh"</string>
+    <string name="notification_importance_high" msgid="2135428926525093825">"Hiển thị trên màn hình và phát ra âm thanh"</string>
+    <string name="notification_importance_max" msgid="5806278962376556491">"Hiển thị ở đầu danh sách thông báo, hiển thị trên màn hình và phát ra âm thanh"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"Cài đặt khác"</string>
     <string name="notification_done" msgid="5279426047273930175">"Xong"</string>
     <string name="color_and_appearance" msgid="1254323855964993144">"Màu sắc và giao diện"</string>
@@ -477,7 +489,7 @@
     <string name="use_dark_theme" msgid="2900938704964299312">"Sử dụng chủ đề sẫm màu cho Android OS"</string>
     <string name="adjust_tint" msgid="3398569573231409878">"Điều chỉnh phủ màu"</string>
     <string name="adjust_brightness" msgid="980039329808178246">"Điều chỉnh độ sáng"</string>
-    <string name="night_mode_disclaimer" msgid="3297928749219711334">"Chủ đề sẫm màu được áp dụng cho các vùng chính của Android OS được hiển thị bình thường trong chủ đề sáng màu, chẳng hạn như Cài đặt và thông báo."</string>
+    <string name="night_mode_disclaimer" msgid="598914896926759578">"Chủ đề sẫm màu được áp dụng cho các vùng chính của Android OS được hiển thị bình thường trong chủ đề sáng màu, chẳng hạn như Cài đặt."</string>
     <string name="color_apply" msgid="9212602012641034283">"Áp dụng"</string>
     <string name="color_revert_title" msgid="4746666545480534663">"Xác nhận cài đặt"</string>
     <string name="color_revert_message" msgid="9116001069397996691">"Một số cài đặt màu có thể khiến thiết bị này không sử dụng được. Hãy nhấp vào OK để xác nhận các cài đặt màu này, nếu không những cài đặt này sẽ được đặt lại sau 10 giây."</string>
@@ -536,4 +548,10 @@
     <item msgid="2139628951880142927">"Hiển thị phần trăm khi sạc (mặc định)"</item>
     <item msgid="3327323682209964956">"Không hiển thị biểu tượng này"</item>
   </string-array>
+    <string name="other" msgid="4060683095962566764">"Khác"</string>
+    <string name="accessibility_divider" msgid="5903423481953635044">"Bộ chia chia đôi màn hình"</string>
+    <string name="accessibility_action_divider_move_down" msgid="704893304141890042">"Chuyển xuống"</string>
+    <string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"Chuyển lên"</string>
+    <string name="accessibility_action_divider_move_left" msgid="9218189832115847253">"Di chuyển sang trái"</string>
+    <string name="accessibility_action_divider_move_right" msgid="4671522715182567972">"Di chuyển sang phải"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-vi/strings_tv.xml b/packages/SystemUI/res/values-vi/strings_tv.xml
new file mode 100644
index 0000000..e4cbc48
--- /dev/null
+++ b/packages/SystemUI/res/values-vi/strings_tv.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2016, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <!-- no translation found for pip_close (3480680679023423574) -->
+    <skip />
+    <string name="pip_fullscreen" msgid="8604643018538487816">"Toàn màn hình"</string>
+    <string name="pip_play" msgid="674145557658227044">"Phát"</string>
+    <string name="pip_pause" msgid="8412075640017218862">"Tạm dừng"</string>
+    <!-- no translation found for pip_hold_home (340086535668778109) -->
+    <skip />
+    <!-- no translation found for pip_onboarding_description (2627737116380318292) -->
+    <skip />
+    <!-- no translation found for pip_onboarding_button (3957426748484904611) -->
+    <skip />
+</resources>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
index 1c8c71e..7f7108c 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -73,7 +73,8 @@
     <string name="screenshot_saved_title" msgid="6461865960961414961">"已抓取屏幕截图。"</string>
     <string name="screenshot_saved_text" msgid="1152839647677558815">"触摸可查看您的屏幕截图。"</string>
     <string name="screenshot_failed_title" msgid="705781116746922771">"无法抓取屏幕截图。"</string>
-    <string name="screenshot_failed_text" msgid="1260203058661337274">"无法进行屏幕截图,原因可能是存储空间不足,或者该应用或您所属的单位不允许执行此操作。"</string>
+    <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"由于存储空间有限,无法保存屏幕截图。"</string>
+    <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"此应用或贵单位不允许进行屏幕截图。"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"USB文件传输选项"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"作为媒体播放器(MTP)装载"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"作为相机(PTP)装载"</string>
@@ -206,6 +207,7 @@
     <string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"延长时间。"</string>
     <string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"缩短时间。"</string>
     <string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"手电筒关闭。"</string>
+    <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"无法使用手电筒。"</string>
     <string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"手电筒打开。"</string>
     <string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"手电筒已关闭。"</string>
     <string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"手电筒已打开。"</string>
@@ -218,6 +220,10 @@
     <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"工作模式开启。"</string>
     <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"工作模式已关闭。"</string>
     <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"工作模式已开启。"</string>
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_off (650231949881093289) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_on (4218725402373934151) -->
+    <skip />
     <string name="accessibility_brightness" msgid="8003681285547803095">"屏幕亮度"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"2G-3G 数据网络已暂停使用"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"4G 数据网络已暂停使用"</string>
@@ -304,6 +310,8 @@
     <string name="recents_launch_disabled_message" msgid="1624523193008871793">"<xliff:g id="APP">%s</xliff:g>已在安全模式下停用。"</string>
     <string name="recents_history_button_label" msgid="5153358867807604821">"历史记录"</string>
     <string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"清除"</string>
+    <string name="recents_drag_non_dockable_task_message" msgid="2935843902795166158">"此应用不支持多窗口模式"</string>
+    <string name="recents_launch_non_dockable_task_label" msgid="7862379814938391888">"应用不支持多窗口模式"</string>
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"水平分割"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"垂直分割"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"自定义分割"</string>
@@ -451,18 +459,23 @@
     <string name="enable_bluetooth_title" msgid="5027037706500635269">"要开启蓝牙吗?"</string>
     <string name="enable_bluetooth_message" msgid="9106595990708985385">"要将您的键盘连接到平板电脑,您必须先开启蓝牙。"</string>
     <string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"开启"</string>
-    <string name="apply_to_topic" msgid="3641403489318659666">"应用于<xliff:g id="TOPIC_NAME">%1$s</xliff:g>通知"</string>
-    <string name="apply_to_app" msgid="363016783939815960">"应用于来自此应用的所有通知"</string>
+    <string name="show_silently" msgid="6841966539811264192">"显示通知,但不发出提示音"</string>
+    <string name="block" msgid="2734508760962682611">"屏蔽所有通知"</string>
+    <string name="do_not_silence" msgid="6878060322594892441">"不静音"</string>
+    <string name="do_not_silence_block" msgid="4070647971382232311">"不静音也不屏蔽"</string>
+    <string name="tuner_full_importance_settings" msgid="8103289238676424226">"显示完整的重要性设置"</string>
     <string name="blocked_importance" msgid="5198578988978234161">"屏蔽"</string>
+    <string name="min_importance" msgid="1901894910809414782">"重要性最低"</string>
     <string name="low_importance" msgid="4109929986107147930">"重要性:低"</string>
     <string name="default_importance" msgid="8192107689995742653">"重要性:一般"</string>
     <string name="high_importance" msgid="1527066195614050263">"重要性:高"</string>
     <string name="max_importance" msgid="5089005872719563894">"重要性:紧急"</string>
     <string name="notification_importance_blocked" msgid="2397192642657872872">"一律不显示这些通知"</string>
-    <string name="notification_importance_low" msgid="4383563267370859725">"在通知列表底部显示,但不发出提示音"</string>
-    <string name="notification_importance_default" msgid="4926529615920610817">"显示这些通知,但不发出提示音"</string>
-    <string name="notification_importance_high" msgid="3222680136612408223">"在通知列表顶部显示,并发出提示音"</string>
-    <string name="notification_importance_max" msgid="5236987171904756134">"在屏幕上持续显示,并发出提示音"</string>
+    <string name="notification_importance_min" msgid="1938190340516905748">"在通知列表底部显示,但不发出提示音"</string>
+    <string name="notification_importance_low" msgid="3657252049508213048">"显示这些通知,但不发出提示音"</string>
+    <string name="notification_importance_default" msgid="4466466472622442175">"允许这些通知发出提示音"</string>
+    <string name="notification_importance_high" msgid="2135428926525093825">"在屏幕上短暂显示,并允许发出提示音"</string>
+    <string name="notification_importance_max" msgid="5806278962376556491">"在通知列表顶部显示,同时在屏幕上短暂显示,并允许发出提示音"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"更多设置"</string>
     <string name="notification_done" msgid="5279426047273930175">"完成"</string>
     <string name="color_and_appearance" msgid="1254323855964993144">"颜色和外观"</string>
@@ -476,7 +489,7 @@
     <string name="use_dark_theme" msgid="2900938704964299312">"对 Android 操作系统使用深色主题背景"</string>
     <string name="adjust_tint" msgid="3398569573231409878">"调整色调"</string>
     <string name="adjust_brightness" msgid="980039329808178246">"调整亮度"</string>
-    <string name="night_mode_disclaimer" msgid="3297928749219711334">"系统会将深色主题背景应用于 Android 操作系统的核心区域(通常以浅色主题背景显示),例如设置和通知。"</string>
+    <string name="night_mode_disclaimer" msgid="598914896926759578">"系统会将深色主题背景应用于 Android 操作系统的核心区域(通常以浅色主题背景显示),例如“设置”部分。"</string>
     <string name="color_apply" msgid="9212602012641034283">"应用"</string>
     <string name="color_revert_title" msgid="4746666545480534663">"确认设置"</string>
     <string name="color_revert_message" msgid="9116001069397996691">"部分颜色设置可能会导致此设备无法使用。请点击“确定”确认这些颜色设置,否则,系统将在 10 秒后重置这些设置。"</string>
@@ -535,4 +548,10 @@
     <item msgid="2139628951880142927">"充电时显示百分比(默认)"</item>
     <item msgid="3327323682209964956">"不显示此图标"</item>
   </string-array>
+    <string name="other" msgid="4060683095962566764">"其他"</string>
+    <string name="accessibility_divider" msgid="5903423481953635044">"分屏分隔线"</string>
+    <string name="accessibility_action_divider_move_down" msgid="704893304141890042">"下移"</string>
+    <string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"上移"</string>
+    <string name="accessibility_action_divider_move_left" msgid="9218189832115847253">"左移"</string>
+    <string name="accessibility_action_divider_move_right" msgid="4671522715182567972">"右移"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings_tv.xml b/packages/SystemUI/res/values-zh-rCN/strings_tv.xml
new file mode 100644
index 0000000..2abd338
--- /dev/null
+++ b/packages/SystemUI/res/values-zh-rCN/strings_tv.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2016, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <!-- no translation found for pip_close (3480680679023423574) -->
+    <skip />
+    <string name="pip_fullscreen" msgid="8604643018538487816">"全屏"</string>
+    <string name="pip_play" msgid="674145557658227044">"播放"</string>
+    <string name="pip_pause" msgid="8412075640017218862">"暂停"</string>
+    <!-- no translation found for pip_hold_home (340086535668778109) -->
+    <skip />
+    <!-- no translation found for pip_onboarding_description (2627737116380318292) -->
+    <skip />
+    <!-- no translation found for pip_onboarding_button (3957426748484904611) -->
+    <skip />
+</resources>
diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml
index f4ac5b4..13a6682 100644
--- a/packages/SystemUI/res/values-zh-rHK/strings.xml
+++ b/packages/SystemUI/res/values-zh-rHK/strings.xml
@@ -73,7 +73,8 @@
     <string name="screenshot_saved_title" msgid="6461865960961414961">"已擷取螢幕畫面。"</string>
     <string name="screenshot_saved_text" msgid="1152839647677558815">"輕觸即可查看螢幕擷取畫面。"</string>
     <string name="screenshot_failed_title" msgid="705781116746922771">"無法擷取螢幕畫面。"</string>
-    <string name="screenshot_failed_text" msgid="1260203058661337274">"由於儲存空間有限,或被應用程式或貴機構禁止,因此無法擷取螢幕擷圖。"</string>
+    <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"由於儲存空間有限,因此無法儲存螢幕擷取畫面。"</string>
+    <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"此應用程式或您的機構禁止擷取螢幕畫面。"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"USB 檔案傳輸選項"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"掛接為媒體播放器 (MTP)"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"掛接為相機 (PTP)"</string>
@@ -206,6 +207,7 @@
     <string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"增加時間。"</string>
     <string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"減少時間。"</string>
     <string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"閃光燈已關閉。"</string>
+    <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"無法使用手電筒。"</string>
     <string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"閃光燈已開啟。"</string>
     <string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"閃光燈已關閉。"</string>
     <string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"閃光燈已開啟。"</string>
@@ -218,6 +220,10 @@
     <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"工作模式已開啟。"</string>
     <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"已關閉工作模式。"</string>
     <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"已開啟工作模式。"</string>
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_off (650231949881093289) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_on (4218725402373934151) -->
+    <skip />
     <string name="accessibility_brightness" msgid="8003681285547803095">"顯示光暗度"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"已暫停 2G-3G 數據"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"已暫停 4G 數據"</string>
@@ -304,6 +310,8 @@
     <string name="recents_launch_disabled_message" msgid="1624523193008871793">"「<xliff:g id="APP">%s</xliff:g>」已在安全模式中停用。"</string>
     <string name="recents_history_button_label" msgid="5153358867807604821">"記錄"</string>
     <string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"清除"</string>
+    <string name="recents_drag_non_dockable_task_message" msgid="2935843902795166158">"此應用程式不支援多視窗模式"</string>
+    <string name="recents_launch_non_dockable_task_label" msgid="7862379814938391888">"應用程式不支援多視窗模式"</string>
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"水平分割"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"垂直分割"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"自訂分割"</string>
@@ -451,18 +459,23 @@
     <string name="enable_bluetooth_title" msgid="5027037706500635269">"要開啟藍牙嗎?"</string>
     <string name="enable_bluetooth_message" msgid="9106595990708985385">"如要將鍵盤連接至平板電腦,請先開啟藍牙。"</string>
     <string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"開啟"</string>
-    <string name="apply_to_topic" msgid="3641403489318659666">"套用到「<xliff:g id="TOPIC_NAME">%1$s</xliff:g>」通知"</string>
-    <string name="apply_to_app" msgid="363016783939815960">"套用到此應用程式的所有通知"</string>
+    <string name="show_silently" msgid="6841966539811264192">"顯示通知,但不發出音效"</string>
+    <string name="block" msgid="2734508760962682611">"封鎖所有通知"</string>
+    <string name="do_not_silence" msgid="6878060322594892441">"不設為靜音"</string>
+    <string name="do_not_silence_block" msgid="4070647971382232311">"不設為靜音或封鎖"</string>
+    <string name="tuner_full_importance_settings" msgid="8103289238676424226">"顯示所有重要性設定"</string>
     <string name="blocked_importance" msgid="5198578988978234161">"已封鎖"</string>
+    <string name="min_importance" msgid="1901894910809414782">"最低重要性"</string>
     <string name="low_importance" msgid="4109929986107147930">"低重要性"</string>
     <string name="default_importance" msgid="8192107689995742653">"一般重要性"</string>
     <string name="high_importance" msgid="1527066195614050263">"高重要性"</string>
     <string name="max_importance" msgid="5089005872719563894">"緊急重要性"</string>
     <string name="notification_importance_blocked" msgid="2397192642657872872">"永不顯示這些通知"</string>
-    <string name="notification_importance_low" msgid="4383563267370859725">"顯示在通知清單底部但不發出音效"</string>
-    <string name="notification_importance_default" msgid="4926529615920610817">"顯示這些通知但不發出音效"</string>
-    <string name="notification_importance_high" msgid="3222680136612408223">"顯示在通知清單頂部並發出音效"</string>
-    <string name="notification_importance_max" msgid="5236987171904756134">"不時於螢幕出現並發出音效"</string>
+    <string name="notification_importance_min" msgid="1938190340516905748">"在通知清單底部顯示但不發出音效"</string>
+    <string name="notification_importance_low" msgid="3657252049508213048">"顯示這些通知但不發出音效"</string>
+    <string name="notification_importance_default" msgid="4466466472622442175">"允許這些通知發出音效"</string>
+    <string name="notification_importance_high" msgid="2135428926525093825">"不時於螢幕出現並發出音效"</string>
+    <string name="notification_importance_max" msgid="5806278962376556491">"在通知清單頂部顯示,並不時於螢幕出現及發出音效"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"更多設定"</string>
     <string name="notification_done" msgid="5279426047273930175">"完成"</string>
     <string name="color_and_appearance" msgid="1254323855964993144">"顏色和外觀"</string>
@@ -476,7 +489,7 @@
     <string name="use_dark_theme" msgid="2900938704964299312">"在 Android OS 中使用深色主題背景"</string>
     <string name="adjust_tint" msgid="3398569573231409878">"調整色調"</string>
     <string name="adjust_brightness" msgid="980039329808178246">"調整亮度"</string>
-    <string name="night_mode_disclaimer" msgid="3297928749219711334">"系統會將深色主題背景套用到 Android OS 核心區域 (一般以淺色主題背景顯示),例如「設定」和通知。"</string>
+    <string name="night_mode_disclaimer" msgid="598914896926759578">"系統會將深色主題背景套用至 Android OS 核心區域 (一般以淺色主題背景顯示),例如「設定」。"</string>
     <string name="color_apply" msgid="9212602012641034283">"套用"</string>
     <string name="color_revert_title" msgid="4746666545480534663">"確認設定"</string>
     <string name="color_revert_message" msgid="9116001069397996691">"部分顏色設定會令此裝置無法使用。請按一下 [確定] 加以確認,否則這些顏色設定將於 10 秒後重設。"</string>
@@ -535,4 +548,10 @@
     <item msgid="2139628951880142927">"充電時顯示百分比 (預設)"</item>
     <item msgid="3327323682209964956">"不顯示這個圖示"</item>
   </string-array>
+    <string name="other" msgid="4060683095962566764">"其他"</string>
+    <string name="accessibility_divider" msgid="5903423481953635044">"分割畫面分隔線"</string>
+    <string name="accessibility_action_divider_move_down" msgid="704893304141890042">"向下移"</string>
+    <string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"向上移"</string>
+    <string name="accessibility_action_divider_move_left" msgid="9218189832115847253">"向左移"</string>
+    <string name="accessibility_action_divider_move_right" msgid="4671522715182567972">"向右移"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-zh-rHK/strings_tv.xml b/packages/SystemUI/res/values-zh-rHK/strings_tv.xml
new file mode 100644
index 0000000..8707d32
--- /dev/null
+++ b/packages/SystemUI/res/values-zh-rHK/strings_tv.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2016, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <!-- no translation found for pip_close (3480680679023423574) -->
+    <skip />
+    <string name="pip_fullscreen" msgid="8604643018538487816">"全螢幕"</string>
+    <string name="pip_play" msgid="674145557658227044">"播放"</string>
+    <string name="pip_pause" msgid="8412075640017218862">"暫停"</string>
+    <!-- no translation found for pip_hold_home (340086535668778109) -->
+    <skip />
+    <!-- no translation found for pip_onboarding_description (2627737116380318292) -->
+    <skip />
+    <!-- no translation found for pip_onboarding_button (3957426748484904611) -->
+    <skip />
+</resources>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml
index 2690eb6..e7172ac 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings.xml
@@ -73,7 +73,8 @@
     <string name="screenshot_saved_title" msgid="6461865960961414961">"已拍攝螢幕擷取畫面。"</string>
     <string name="screenshot_saved_text" msgid="1152839647677558815">"輕觸即可查看螢幕擷取畫面。"</string>
     <string name="screenshot_failed_title" msgid="705781116746922771">"無法拍攝螢幕擷取畫面。"</string>
-    <string name="screenshot_failed_text" msgid="1260203058661337274">"由於儲存空間有限,或是遭到應用程式或貴機構禁止,因此無法擷取螢幕畫面。"</string>
+    <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"由於儲存空間有限,因此無法儲存螢幕擷取畫面。"</string>
+    <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"這個應用程式或貴機構禁止擷取螢幕畫面。"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"USB 檔案傳輸選項"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"掛接為媒體播放器 (MTP)"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"掛接為相機 (PTP)"</string>
@@ -206,6 +207,7 @@
     <string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"增加時間。"</string>
     <string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"減少時間。"</string>
     <string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"閃光燈已關閉。"</string>
+    <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"無法使用手電筒。"</string>
     <string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"閃光燈已開啟。"</string>
     <string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"閃光燈已關閉。"</string>
     <string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"閃光燈已開啟。"</string>
@@ -218,6 +220,10 @@
     <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"工作模式已開啟。"</string>
     <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"工作模式已關閉。"</string>
     <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"工作模式已開啟。"</string>
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_off (650231949881093289) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_on (4218725402373934151) -->
+    <skip />
     <string name="accessibility_brightness" msgid="8003681285547803095">"螢幕亮度"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"已暫停 2G-3G 數據連線"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"已暫停 4G 數據連線"</string>
@@ -304,6 +310,8 @@
     <string name="recents_launch_disabled_message" msgid="1624523193008871793">"「<xliff:g id="APP">%s</xliff:g>」在安全模式中為停用狀態。"</string>
     <string name="recents_history_button_label" msgid="5153358867807604821">"紀錄"</string>
     <string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"清除"</string>
+    <string name="recents_drag_non_dockable_task_message" msgid="2935843902795166158">"這個應用程式不支援多視窗模式"</string>
+    <string name="recents_launch_non_dockable_task_label" msgid="7862379814938391888">"應用程式不支援多視窗模式"</string>
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"水平分割"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"垂直分割"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"自訂分割"</string>
@@ -451,18 +459,23 @@
     <string name="enable_bluetooth_title" msgid="5027037706500635269">"要開啟藍牙功能嗎?"</string>
     <string name="enable_bluetooth_message" msgid="9106595990708985385">"如要將鍵盤連線到平板電腦,您必須先開啟藍牙。"</string>
     <string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"開啟"</string>
-    <string name="apply_to_topic" msgid="3641403489318659666">"套用到「<xliff:g id="TOPIC_NAME">%1$s</xliff:g>」通知"</string>
-    <string name="apply_to_app" msgid="363016783939815960">"套用到這個應用程式的所有通知"</string>
+    <string name="show_silently" msgid="6841966539811264192">"顯示通知,但不發出任何音效"</string>
+    <string name="block" msgid="2734508760962682611">"封鎖所有通知"</string>
+    <string name="do_not_silence" msgid="6878060322594892441">"不設定靜音"</string>
+    <string name="do_not_silence_block" msgid="4070647971382232311">"不設定靜音或封鎖"</string>
+    <string name="tuner_full_importance_settings" msgid="8103289238676424226">"顯示完整的重要性設定"</string>
     <string name="blocked_importance" msgid="5198578988978234161">"封鎖"</string>
+    <string name="min_importance" msgid="1901894910809414782">"最低重要性"</string>
     <string name="low_importance" msgid="4109929986107147930">"低重要性"</string>
     <string name="default_importance" msgid="8192107689995742653">"一般重要性"</string>
     <string name="high_importance" msgid="1527066195614050263">"高重要性"</string>
     <string name="max_importance" msgid="5089005872719563894">"緊急重要性"</string>
     <string name="notification_importance_blocked" msgid="2397192642657872872">"一律不顯示這些通知"</string>
-    <string name="notification_importance_low" msgid="4383563267370859725">"顯示在通知清單底部且不發出任何音效"</string>
-    <string name="notification_importance_default" msgid="4926529615920610817">"顯示這些通知且不發出任何音效"</string>
-    <string name="notification_importance_high" msgid="3222680136612408223">"顯示在通知清單頂端並發出音效"</string>
-    <string name="notification_importance_max" msgid="5236987171904756134">"短暫顯示在螢幕上並發出音效"</string>
+    <string name="notification_importance_min" msgid="1938190340516905748">"顯示在通知清單底端,但不發出任何音效"</string>
+    <string name="notification_importance_low" msgid="3657252049508213048">"顯示這些通知,但不發出任何音效"</string>
+    <string name="notification_importance_default" msgid="4466466472622442175">"允許這些通知發出音效"</string>
+    <string name="notification_importance_high" msgid="2135428926525093825">"短暫顯示在畫面上並發出音效"</string>
+    <string name="notification_importance_max" msgid="5806278962376556491">"顯示在通知清單頂端,同時短暫顯示在畫面上並發出音效"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"更多設定"</string>
     <string name="notification_done" msgid="5279426047273930175">"完成"</string>
     <string name="color_and_appearance" msgid="1254323855964993144">"顏色和外觀"</string>
@@ -476,7 +489,7 @@
     <string name="use_dark_theme" msgid="2900938704964299312">"針對 Android 作業系統使用深色主題"</string>
     <string name="adjust_tint" msgid="3398569573231409878">"調整色調"</string>
     <string name="adjust_brightness" msgid="980039329808178246">"調整亮度"</string>
-    <string name="night_mode_disclaimer" msgid="3297928749219711334">"深色主題會套用到 Android 作業系統的核心區塊 (一般是以淺色主題顯示),例如設定和通知。"</string>
+    <string name="night_mode_disclaimer" msgid="598914896926759578">"深色主題會套用到 Android 作業系統的核心區塊 (一般是以淺色主題顯示),例如「設定」區塊。"</string>
     <string name="color_apply" msgid="9212602012641034283">"套用"</string>
     <string name="color_revert_title" msgid="4746666545480534663">"確認設定"</string>
     <string name="color_revert_message" msgid="9116001069397996691">"部分顏色設定可能會造成這部裝置無法使用。請按一下 [確定] 來確認您要使用這類顏色設定,否則系統將在 10 秒後重設這些設定。"</string>
@@ -535,4 +548,10 @@
     <item msgid="2139628951880142927">"充電時顯示百分比 (預設)"</item>
     <item msgid="3327323682209964956">"不顯示這個圖示"</item>
   </string-array>
+    <string name="other" msgid="4060683095962566764">"其他"</string>
+    <string name="accessibility_divider" msgid="5903423481953635044">"分割畫面分隔線"</string>
+    <string name="accessibility_action_divider_move_down" msgid="704893304141890042">"向下移"</string>
+    <string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"向上移"</string>
+    <string name="accessibility_action_divider_move_left" msgid="9218189832115847253">"向左移"</string>
+    <string name="accessibility_action_divider_move_right" msgid="4671522715182567972">"向右移"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings_tv.xml b/packages/SystemUI/res/values-zh-rTW/strings_tv.xml
new file mode 100644
index 0000000..8707d32
--- /dev/null
+++ b/packages/SystemUI/res/values-zh-rTW/strings_tv.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2016, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <!-- no translation found for pip_close (3480680679023423574) -->
+    <skip />
+    <string name="pip_fullscreen" msgid="8604643018538487816">"全螢幕"</string>
+    <string name="pip_play" msgid="674145557658227044">"播放"</string>
+    <string name="pip_pause" msgid="8412075640017218862">"暫停"</string>
+    <!-- no translation found for pip_hold_home (340086535668778109) -->
+    <skip />
+    <!-- no translation found for pip_onboarding_description (2627737116380318292) -->
+    <skip />
+    <!-- no translation found for pip_onboarding_button (3957426748484904611) -->
+    <skip />
+</resources>
diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml
index 33f0e9a..5868b2a 100644
--- a/packages/SystemUI/res/values-zu/strings.xml
+++ b/packages/SystemUI/res/values-zu/strings.xml
@@ -73,7 +73,8 @@
     <string name="screenshot_saved_title" msgid="6461865960961414961">"Umfanekiso weskrini uqoshiwe"</string>
     <string name="screenshot_saved_text" msgid="1152839647677558815">"Thinta ukubona imifanekiso yakho yeskrini"</string>
     <string name="screenshot_failed_title" msgid="705781116746922771">"Yehlulekile ukulondoloza umfanekiso weskrini."</string>
-    <string name="screenshot_failed_text" msgid="1260203058661337274">"Ayikwazi ukuthatha izithombe zesikrini ngenxa yesikhala sesitoreji esikhawulelwe ngohlelo lokusebenza noma inhlangano yakho."</string>
+    <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Ayikwazi ukulondoloza isithombe-skrini ngenxa yesikhala sesitoreji esikhawulelwe."</string>
+    <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Ukuthatha izithombe-skrini akuvunyelwe uhlelo lokusebenza noma inhlangano yakho."</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"Okukhethwa kokudluliswa kwefayela ye-USB"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Lengisa njengesidlali semediya (MTP)"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"Lengisa ikhamera (PTP)"</string>
@@ -206,6 +207,7 @@
     <string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"Isikhathi esiningi."</string>
     <string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"Isikhathi esincane."</string>
     <string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"I-Flashlight ivaliwe."</string>
+    <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"I-Flashlight ayitholakali."</string>
     <string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"I-Flashlight ivuliwe."</string>
     <string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"I-Flashlight ivaliwe."</string>
     <string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"I-Flashlight ivuliwe."</string>
@@ -218,6 +220,10 @@
     <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"Imodi yomsebenzi ivuliwe."</string>
     <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"Imodi yomsebenzi ivaliwe."</string>
     <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"Imodi yomsebenzi ivuliwe."</string>
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_off (650231949881093289) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_on (4218725402373934151) -->
+    <skip />
     <string name="accessibility_brightness" msgid="8003681285547803095">"Bonisa ukukhanya"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"2G-3G idatha imisiwe"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"4G idatha imisiwe"</string>
@@ -304,6 +310,8 @@
     <string name="recents_launch_disabled_message" msgid="1624523193008871793">"I-<xliff:g id="APP">%s</xliff:g> ikhutshaziwe kumodi yokuphepha."</string>
     <string name="recents_history_button_label" msgid="5153358867807604821">"Umlando"</string>
     <string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"Sula"</string>
+    <string name="recents_drag_non_dockable_task_message" msgid="2935843902795166158">"Lolu hlelo lokusebenza alusekeli amawindi amaningi"</string>
+    <string name="recents_launch_non_dockable_task_label" msgid="7862379814938391888">"Uhlelo lokusebenza alusekeli amawindi amaningi"</string>
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Hlukanisa okuvundlile"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Hlukanisa okumile"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Hlukanisa kwezifiso"</string>
@@ -451,18 +459,23 @@
     <string name="enable_bluetooth_title" msgid="5027037706500635269">"Vula i-Bluetooth?"</string>
     <string name="enable_bluetooth_message" msgid="9106595990708985385">"Ukuze uxhume ikhibhodi yakho nethebhulethi yakho, kufanele uqale ngokuvula i-Bluetooth."</string>
     <string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"Vula"</string>
-    <string name="apply_to_topic" msgid="3641403489318659666">"Sebenzisa kuzaziso ze-<xliff:g id="TOPIC_NAME">%1$s</xliff:g>"</string>
-    <string name="apply_to_app" msgid="363016783939815960">"Sebenzisa kuzo zonke izaziso ezivela kulolu hlelo lokusebenza"</string>
+    <string name="show_silently" msgid="6841966539811264192">"Bonisa izaziso ngokuthulile"</string>
+    <string name="block" msgid="2734508760962682611">"Vimbela zonke izaziso"</string>
+    <string name="do_not_silence" msgid="6878060322594892441">"Ungathulisi"</string>
+    <string name="do_not_silence_block" msgid="4070647971382232311">"Ungathulisi noma uvimbele"</string>
+    <string name="tuner_full_importance_settings" msgid="8103289238676424226">"Bonisa izilungiselelo ezibalulekile ezigcwele"</string>
     <string name="blocked_importance" msgid="5198578988978234161">"Kuvinjelwe"</string>
+    <string name="min_importance" msgid="1901894910809414782">"Okubaluleke kancane"</string>
     <string name="low_importance" msgid="4109929986107147930">"Ukubaluleka okuphansi"</string>
     <string name="default_importance" msgid="8192107689995742653">"Ukubaluleka okujwayelekile"</string>
     <string name="high_importance" msgid="1527066195614050263">"Ukubaluleka okuphezulu"</string>
     <string name="max_importance" msgid="5089005872719563894">"Ukubaluleka okusheshayo"</string>
     <string name="notification_importance_blocked" msgid="2397192642657872872">"Ungalokothi ubonise lezi zaziso"</string>
-    <string name="notification_importance_low" msgid="4383563267370859725">"Bonisa ngokuthulile ngaphansi kohlu lwesaziso"</string>
-    <string name="notification_importance_default" msgid="4926529615920610817">"Bonisa ngokuthulile lezi zaziso"</string>
-    <string name="notification_importance_high" msgid="3222680136612408223">"Bonisa ngaphezulu kohlu lwezaziso uphinde wenze umsindo"</string>
-    <string name="notification_importance_max" msgid="5236987171904756134">"Bheka kusikrini uphinde wenze umsindo"</string>
+    <string name="notification_importance_min" msgid="1938190340516905748">"Bonisa ngokuthulile ngaphansi kohlu lwesaziso"</string>
+    <string name="notification_importance_low" msgid="3657252049508213048">"Bonisa ngokuthulile lezi zaziso"</string>
+    <string name="notification_importance_default" msgid="4466466472622442175">"Vumela lezi zaziso ukwenza umsindo"</string>
+    <string name="notification_importance_high" msgid="2135428926525093825">"Beka kusikrini futhi uvumele umsindo"</string>
+    <string name="notification_importance_max" msgid="5806278962376556491">"Bonisa phezulu kohlu lwezaziso, beka phezu kwesikrini futhi uvumele umsindo"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"Izilungiselelo eziningi"</string>
     <string name="notification_done" msgid="5279426047273930175">"Kwenziwe"</string>
     <string name="color_and_appearance" msgid="1254323855964993144">"Umbala nokubonakala"</string>
@@ -476,7 +489,7 @@
     <string name="use_dark_theme" msgid="2900938704964299312">"Sebenzisa ingqikithi emnyama ku-Android OS"</string>
     <string name="adjust_tint" msgid="3398569573231409878">"Lungisa i-tint"</string>
     <string name="adjust_brightness" msgid="980039329808178246">"Lungisa ukukhanya"</string>
-    <string name="night_mode_disclaimer" msgid="3297928749219711334">"Ingqikithi emnyama isetshenziswa ezindaweni eziqinile ze-Android OS ezivame ukuboniswa ngengqikithi ekhanyayo, njengamasethingi nezaziso."</string>
+    <string name="night_mode_disclaimer" msgid="598914896926759578">"Itimu emnyama isetshenziswa ezindaweni eziqinile ze-Android OS ezivamise ukuoniswa ngetimu ekhanyayo, efana nezilungiselelo."</string>
     <string name="color_apply" msgid="9212602012641034283">"Sebenzisa"</string>
     <string name="color_revert_title" msgid="4746666545480534663">"Qinisekisa izilungiselelo"</string>
     <string name="color_revert_message" msgid="9116001069397996691">"Ezinye izilungiselelo zombala zingenza le divayisi ingasebenziseki. Chofoza ku-KULUNGILE ukuze uqinisekise lezi zilungiselelo zombala, uma kungenjalo lezi zilungiselelo zizosethwa kabusha ngemuva kwamasekhondi angu-10."</string>
@@ -535,4 +548,10 @@
     <item msgid="2139628951880142927">"Bonisa iphesentheji uma ishaja (okuzenzakalelayo)"</item>
     <item msgid="3327323682209964956">"Ungabonisi lesi sithonjana"</item>
   </string-array>
+    <string name="other" msgid="4060683095962566764">"Okunye"</string>
+    <string name="accessibility_divider" msgid="5903423481953635044">"Isihlukanisi sokuhlukanisa isikrini"</string>
+    <string name="accessibility_action_divider_move_down" msgid="704893304141890042">"Iya phansi"</string>
+    <string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"Iya phezulu"</string>
+    <string name="accessibility_action_divider_move_left" msgid="9218189832115847253">"Iya kwesokunxele"</string>
+    <string name="accessibility_action_divider_move_right" msgid="4671522715182567972">"Iya kwesokudla"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-zu/strings_tv.xml b/packages/SystemUI/res/values-zu/strings_tv.xml
new file mode 100644
index 0000000..b901f90
--- /dev/null
+++ b/packages/SystemUI/res/values-zu/strings_tv.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.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="pip_close" msgid="3480680679023423574">"Vala i-PIP"</string>
+    <string name="pip_fullscreen" msgid="8604643018538487816">"Iskrini esigcwele"</string>
+    <string name="pip_play" msgid="674145557658227044">"Dlala"</string>
+    <string name="pip_pause" msgid="8412075640017218862">"Misa isikhashana"</string>
+    <string name="pip_hold_home" msgid="340086535668778109">"Bamba "<b>"IKHAYA"</b>" ukuze ulawule i-PIP"</string>
+    <string name="pip_onboarding_description" msgid="2627737116380318292">"Cindezela uphinde ubambe inkinobho YASEKHAYA\nukuze ulawule i-PIP"</string>
+    <string name="pip_onboarding_button" msgid="3957426748484904611">"Ngiyezwa"</string>
+</resources>
diff --git a/packages/SystemUI/res/values/attrs.xml b/packages/SystemUI/res/values/attrs.xml
index 189eb3b..e040ab2 100644
--- a/packages/SystemUI/res/values/attrs.xml
+++ b/packages/SystemUI/res/values/attrs.xml
@@ -93,5 +93,9 @@
         <attr name="defValue" format="boolean" />
         <attr name="metricsAction" format="integer" />
     </declare-styleable>
+
+    <declare-styleable name="DensityContainer">
+        <attr name="android:layout" />
+    </declare-styleable>
 </resources>
 
diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml
index 8f69bbb..d65ab04 100644
--- a/packages/SystemUI/res/values/colors.xml
+++ b/packages/SystemUI/res/values/colors.xml
@@ -31,7 +31,7 @@
     <color name="batterymeter_bolt_color">#FFFFFFFF</color>
     <color name="qs_batterymeter_frame_color">#FF404040</color>
     <color name="system_primary_color">#ff263238</color><!-- blue grey 900 -->
-    <color name="system_secondary_color">#ff384248</color>
+    <color name="system_secondary_color">#ff37474F</color><!-- blue grey 800 -->
     <color name="system_accent_color">#ff80CBC4</color><!-- deep teal 200 -->
     <color name="system_warning_color">#fff4511e</color><!-- deep orange 600 -->
     <color name="qs_text">#FFFFFFFF</color>
@@ -165,4 +165,7 @@
     <!-- Keyboard shortcuts colors -->
     <color name="ksh_system_group_color">#ff00bcd4</color>
     <color name="ksh_application_group_color">#fff44336</color>
+
+    <!-- Background color of edit overflow -->
+    <color name="qs_edit_overflow_bg">#455A64</color>
 </resources>
diff --git a/packages/SystemUI/res/values/colors_tv.xml b/packages/SystemUI/res/values/colors_tv.xml
index 6f4c983..af99aae 100644
--- a/packages/SystemUI/res/values/colors_tv.xml
+++ b/packages/SystemUI/res/values/colors_tv.xml
@@ -18,7 +18,5 @@
 -->
 <resources>
     <color name="recents_tv_card_background_color">#FF37474F</color>
-    <color name="recents_tv_card_title_text_color">#FFEEEEEE</color>
-    <color name="recents_tv_card_content_text_color">#99EEEEEE</color>
-    <color name="recents_tv_card_source_text_color">#99EEEEEE</color>
+    <color name="recents_tv_card_title_text_color">#CCEEEEEE</color>
 </resources>
\ No newline at end of file
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index fbe0207..e50f975 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -58,19 +58,19 @@
     <item name="status_bar_icon_scale_factor" format="float" type="dimen">1.0</item>
 
     <!-- Height of a small notification in the status bar-->
-    <dimen name="notification_min_height">86dp</dimen>
+    <dimen name="notification_min_height">92dp</dimen>
 
     <!-- Height of a small notification in the status bar which was used before android N -->
     <dimen name="notification_min_height_legacy">64dp</dimen>
 
     <!-- Height of a large notification in the status bar -->
-    <dimen name="notification_max_height">276dp</dimen>
+    <dimen name="notification_max_height">284dp</dimen>
 
     <!-- Height of a heads up notification in the status bar for legacy custom views -->
     <dimen name="notification_max_heads_up_height_legacy">128dp</dimen>
 
     <!-- Height of a heads up notification in the status bar -->
-    <dimen name="notification_max_heads_up_height">141dp</dimen>
+    <dimen name="notification_max_heads_up_height">148dp</dimen>
 
     <!-- Height of a the summary ("more card") notification on keyguard. -->
     <dimen name="notification_summary_height">44dp</dimen>
@@ -292,6 +292,12 @@
     <!-- The amount to allow the stack to overscroll. -->
     <dimen name="recents_stack_overscroll">24dp</dimen>
 
+    <!-- The size of the initial peek area at the top of the stack (below the status bar). -->
+    <dimen name="recents_initial_top_peek_size">8dp</dimen>
+
+    <!-- The size of the initial peek area at the bottom of the stack (above the nav bar). -->
+    <dimen name="recents_initial_bottom_peek_size">100dp</dimen>
+
     <!-- The size of the peek area at the top of the stack (below the status bar). -->
     <dimen name="recents_layout_focused_top_peek_size">@dimen/recents_history_button_height</dimen>
 
@@ -304,6 +310,9 @@
     <!-- The padding between freeform workspace tasks -->
     <dimen name="recents_freeform_workspace_task_padding">8dp</dimen>
 
+    <!-- The offsets the tasks animate from when recents is launched while docking -->
+    <dimen name="recents_task_view_launched_while_docking_offset">144dp</dimen>
+
     <!-- Space reserved for the cards behind the top card in the bottom stack -->
     <dimen name="bottom_stack_peek_amount">12dp</dimen>
 
@@ -326,9 +335,6 @@
     <!-- The minimum amount of top overscroll to go to the quick settings. -->
     <dimen name="min_top_overscroll_to_qs">36dp</dimen>
 
-    <!-- The padding to the second card when the notifications collapse. -->
-    <dimen name="notification_collapse_second_card_padding">8dp</dimen>
-
     <!-- The height of the speed bump view. -->
     <dimen name="speed_bump_height">16dp</dimen>
 
diff --git a/packages/SystemUI/res/values/dimens_tv.xml b/packages/SystemUI/res/values/dimens_tv.xml
index bf32cc7..b589110 100644
--- a/packages/SystemUI/res/values/dimens_tv.xml
+++ b/packages/SystemUI/res/values/dimens_tv.xml
@@ -18,15 +18,21 @@
 -->
 <resources>
     <!-- Dimens for recents card in the recents view on tv -->
-    <dimen name="recents_tv_card_width">150dip</dimen>
-    <dimen name="recents_tv_card_height">85dip</dimen>
-    <dimen name="recents_tv_card_extra_badge_size">16dip</dimen>
+    <dimen name="recents_tv_card_width">268dip</dimen>
+    <dimen name="recents_tv_card_height">151dip</dimen>
+    <dimen name="recents_tv_card_extra_badge_size">20dip</dimen>
+    <dimen name="recents_tv_banner_width">114dip</dimen>
+    <dimen name="recents_tv_banner_height">64dip</dimen>
+    <dimen name="recents_tv_banner_margin_top">16dip</dimen>
+    <dimen name="recents_tv_icon_padding_bottom">8dip</dimen>
+    <dimen name="recents_tv_icon_padding_end">12dip</dimen>
+    <dimen name="recents_tv_text_padding_bottom">12dip</dimen>
 
     <!-- Padding for grid view in recents view on tv -->
     <dimen name="recents_tv_grid_row_padding">56dip</dimen>
     <dimen name="recents_tv_gird_row_top_padding">57dip</dimen>
-    <dimen name="recents_tv_grid_max_row_height">200dip</dimen>
-    <dimen name="recents_tv_gird_card_spacing">8dip</dimen>
+    <dimen name="recents_tv_grid_max_row_height">268dip</dimen>
+    <dimen name="recents_tv_gird_card_spacing">20dip</dimen>
 
     <!-- Values for focus animation -->
     <dimen name="recents_tv_unselected_item_z">6dp</dimen>
@@ -34,4 +40,7 @@
 
     <!-- Extra space around the PIP and its outline in PIP onboarding activity  -->
     <dimen name="tv_pip_bounds_space">3dp</dimen>
+
+    <!-- Values for text on recents cards on tv -->
+    <dimen name="recents_tv_title_text_size">12sp</dimen>
 </resources>
diff --git a/packages/SystemUI/res/values/ids.xml b/packages/SystemUI/res/values/ids.xml
index b9eee2e..9697ea6 100644
--- a/packages/SystemUI/res/values/ids.xml
+++ b/packages/SystemUI/res/values/ids.xml
@@ -48,6 +48,7 @@
     <item type="id" name="transformation_start_y_tag"/>
     <item type="id" name="transformation_start_scale_x_tag"/>
     <item type="id" name="transformation_start_scale_y_tag"/>
+    <item type="id" name="custom_background_color"/>
 
     <!-- Whether the icon is from a notification for which targetSdk < L -->
     <item type="id" name="icon_is_pre_L"/>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index ac6e3ac..8af413c 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -185,7 +185,9 @@
     <string name="screenshot_saved_text">Touch to view your screenshot.</string>
     <!-- Notification title displayed when we fail to take a screenshot. [CHAR LIMIT=50] -->
     <string name="screenshot_failed_title">Couldn\'t capture screenshot.</string>
-    <!-- Notification text displayed when we fail to take a screenshot. [CHAR LIMIT=100] -->
+    <!-- Notification text displayed when we fail to save a screenshot for unknown reasons. [CHAR LIMIT=100] -->
+    <string name="screenshot_failed_to_save_unknown_text">Problem encountered while saving screenshot.</string>
+    <!-- Notification text displayed when we fail to save a screenshot. [CHAR LIMIT=100] -->
     <string name="screenshot_failed_to_save_text">Can\'t save screenshot due to limited storage space.</string>
     <!-- Notification text displayed when we fail to take a screenshot. [CHAR LIMIT=100] -->
     <string name="screenshot_failed_to_capture_text">Taking screenshots is not allowed by the app or your organization.</string>
@@ -497,6 +499,8 @@
     <string name="accessibility_quick_settings_less_time">Less time.</string>
     <!-- Content description of the flashlight tile in quick settings when off (not shown on the screen). [CHAR LIMIT=NONE] -->
     <string name="accessibility_quick_settings_flashlight_off">Flashlight off.</string>
+    <!-- Content description of the flashlight tile in quick settings when unavailable (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_quick_settings_flashlight_unavailable">Flashlight unavailable.</string>
     <!-- Content description of the flashlight tile in quick settings when on (not shown on the screen). [CHAR LIMIT=NONE] -->
     <string name="accessibility_quick_settings_flashlight_on">Flashlight on.</string>
     <!-- Announcement made when the flashlight state changes to off (not shown on the screen). [CHAR LIMIT=NONE] -->
@@ -521,6 +525,10 @@
     <string name="accessibility_quick_settings_work_mode_changed_off">Work mode turned off.</string>
     <!-- Announcement made when the work mode changes to on (not shown on the screen). [CHAR LIMIT=NONE] -->
     <string name="accessibility_quick_settings_work_mode_changed_on">Work mode turned on.</string>
+    <!-- Announcement made when the Data Saver changes to off (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_quick_settings_data_saver_changed_off">Data Saver turned off.</string>
+    <!-- Announcement made when the Data Saver changes to on (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_quick_settings_data_saver_changed_on">Data Saver turned on.</string>
 
     <!-- Content description of the display brightness slider (not shown on the screen). [CHAR LIMIT=NONE] -->
     <string name="accessibility_brightness">Display brightness</string>
@@ -1205,12 +1213,22 @@
     <!-- Bluetooth enablement ok text [CHAR LIMIT=40] -->
     <string name="enable_bluetooth_confirmation_ok">Turn on</string>
 
-    <!-- Apply notification importance setting to a topic [CHAR LIMIT=NONE] -->
-    <string name="apply_to_topic">Apply to <xliff:g id="topic_name" example="Friend Request">%1$s</xliff:g> notifications</string>
-    <!-- Apply notification importance setting to an app [CHAR LIMIT=NONE] -->
-    <string name="apply_to_app">Apply to all notifications from this app</string>
+    <!-- [CHAR LIMIT=100] Notification importance option -->
+    <string name="show_silently">Show notifications silently</string>
+    <!-- [CHAR LIMIT=100] Notification importance option -->
+    <string name="block">Block all notifications</string>
+    <!-- [CHAR LIMIT=100] Notification importance option -->
+    <string name="do_not_silence">Don\'t silence</string>
+    <!-- [CHAR LIMIT=100] Notification importance option -->
+    <string name="do_not_silence_block">Don\'t silence or block</string>
+
+    <!-- [CHAR LIMIT=NONE] Importance Tuner setting title -->
+    <string name="tuner_full_importance_settings">Show full importance settings</string>
+
     <!-- Notification importance title, blocked status-->
     <string name="blocked_importance">Blocked</string>
+    <!-- Notification importance title, min status-->
+    <string name="min_importance">Min importance</string>
     <!-- Notification importance title, low status-->
     <string name="low_importance">Low importance</string>
     <!-- Notification importance title, normal status-->
@@ -1223,17 +1241,20 @@
     <!-- [CHAR LIMIT=100] Notification Importance slider: blocked importance level description -->
     <string name="notification_importance_blocked">Never show these notifications</string>
 
+    <!-- [CHAR LIMIT=100] Notification Importance slider: min importance level description -->
+    <string name="notification_importance_min">Silently show at the bottom of the notification list</string>
+
     <!-- [CHAR LIMIT=100] Notification Importance slider: low importance level description -->
-    <string name="notification_importance_low">Silently show at the bottom of the notification list</string>
+    <string name="notification_importance_low">Silently show these notifications</string>
 
     <!-- [CHAR LIMIT=100] Notification Importance slider: normal importance level description -->
-    <string name="notification_importance_default">Silently show these notifications</string>
+    <string name="notification_importance_default">Allow these notification to make sounds</string>
 
     <!-- [CHAR LIMIT=100] Notification Importance slider: high importance level description -->
-    <string name="notification_importance_high">Show at the top of the notifications list and make sound</string>
+    <string name="notification_importance_high">Peek onto the screen and allow sound and allow sound</string>
 
     <!-- [CHAR LIMIT=100] Notification Importance slider: max importance level description -->
-    <string name="notification_importance_max">Peek onto the screen and make sound</string>
+    <string name="notification_importance_max">Show at the top of the notifications list, peek onto the screen and allow sound</string>
 
     <!-- Notification: Control panel: Label for button that launches notification settings. [CHAR LIMIT=NONE] -->
     <string name="notification_more_settings">More settings</string>
@@ -1434,6 +1455,9 @@
         <item>Don\'t show this icon</item>
     </string-array>
 
+    <!-- SysUI Tuner: Other section -->
+    <string name="other">Other</string>
+
     <!-- Accessibility label for the divider that separates the windows in split-screen mode [CHAR LIMIT=NONE] -->
     <string name="accessibility_divider">Split-screen divider</string>
 
@@ -1448,4 +1472,5 @@
 
     <!-- Accessibility action for moving down the docked stack divider [CHAR LIMIT=NONE] -->
     <string name="accessibility_action_divider_move_right">Move right</string>
+
 </resources>
diff --git a/packages/SystemUI/res/values/strings_tv.xml b/packages/SystemUI/res/values/strings_tv.xml
index 4f382ea..b35038d 100644
--- a/packages/SystemUI/res/values/strings_tv.xml
+++ b/packages/SystemUI/res/values/strings_tv.xml
@@ -17,25 +17,26 @@
  */
 -->
 <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- Picture-in-Picture menu -->
+    <!-- Picture-in-Picture (PIP) menu -->
     <eat-comment />
-    <!-- Button to close PIP on PIP UI -->
-    <string name="pip_close" translatable="false">Close PIP</string>
-    <!-- Button to move PIP screen to the fullscreen on PIP UI -->
-    <string name="pip_fullscreen" translatable="false">Full screen</string>
-    <!-- Button to play the current media on PIP UI -->
-    <string name="pip_play" translatable="false">Play</string>
-    <!-- Button to pause the current media on PIP UI -->
-    <string name="pip_pause" translatable="false">Pause</string>
-    <!-- Button to close PIP overlay menu on PIP UI -->
-    <string name="pip_cancel" translatable="false">Cancel</string>
-    <!-- Overlay text on PIP -->
-    <string name="pip_hold_home" translatable="false">Hold HOME to control PIP</string>
-
-    <!-- Picture-in-Picture onboarding screen -->
+    <!-- Button to close picture-in-picture (PIP) in PIP menu [CHAR LIMIT=16] -->
+    <string name="pip_close">Close PIP</string>
+    <!-- Button to move picture-in-picture (PIP) screen to the fullscreen in PIP menu [CHAR LIMIT=16] -->
+    <string name="pip_fullscreen">Full screen</string>
+    <!-- Button to play the current media on picture-in-picture (PIP) [CHAR LIMIT=16] -->
+    <string name="pip_play">Play</string>
+    <!-- Button to pause the current media on picture-in-picture (PIP) [CHAR LIMIT=16] -->
+    <string name="pip_pause">Pause</string>
+    <!-- Overlay text on picture-in-picture (PIP) to indicate that longpress HOME key to control PIP [CHAR LIMIT=25] -->
+    <string name="pip_hold_home">Hold <b>HOME</b> to control PIP</string>
+    <!-- Picture-in-Picture (PIP) onboarding screen -->
     <eat-comment />
-    <!-- Description for onboarding screen. -->
-    <string name="pip_onboarding_description" translatable="false">Press and hold the HOME\nbutton to close or control it</string>
-    <!-- Button to close onboarding screen. -->
-    <string name="pip_onboarding_button" translatable="false">Got it</string>
+    <!-- Description for picture-in-picture (PIP) onboarding screen to indicate that longpress HOME key to control PIP.
+         Line break is needed as if we have CHAR LIMIT=25. [CHAR LIMIT=NONE] -->
+    <string name="pip_onboarding_description">Press and hold the HOME\nbutton to control PIP</string>
+    <!-- Button to close picture-in-picture (PIP) onboarding screen. -->
+    <string name="pip_onboarding_button">Got it</string>
+    <!-- Font for Recents -->
+    <!-- DO NOT TRANSLATE -->
+    <string name="font_roboto_regular" translatable="false">sans-serif</string>
 </resources>
diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml
index a51b931..2660926 100644
--- a/packages/SystemUI/res/values/styles.xml
+++ b/packages/SystemUI/res/values/styles.xml
@@ -214,7 +214,7 @@
 
     <style name="QSBorderlessButton">
         <item name="android:padding">12dp</item>
-        <item name="android:background">@drawable/btn_borderless_rect</item>
+        <item name="android:background">@drawable/qs_btn_borderless_rect</item>
         <item name="android:gravity">center</item>
     </style>
 
@@ -323,6 +323,10 @@
         <item name="android:textSize">16sp</item>
     </style>
 
+    <style name="TextAppearance.NotificationGuts.Radio">
+        <item name="android:alpha">.87</item>
+    </style>
+
     <style name="TextAppearance.NotificationGuts.Button">
         <item name="android:textSize">14sp</item>
         <item name="android:textAllCaps">true</item>
@@ -335,4 +339,8 @@
         <item name="android:colorAccent">@color/switch_accent_color</item>
     </style>
 
+    <style name="edit_theme" parent="@android:style/Theme.Material">
+        <item name="android:colorBackground">@color/qs_edit_overflow_bg</item>
+    </style>
+
 </resources>
diff --git a/packages/SystemUI/res/values/styles_tv.xml b/packages/SystemUI/res/values/styles_tv.xml
index 3f0caab..263e1a4 100644
--- a/packages/SystemUI/res/values/styles_tv.xml
+++ b/packages/SystemUI/res/values/styles_tv.xml
@@ -22,4 +22,11 @@
         <item name="android:windowBackground">@android:color/transparent</item>
         <item name="android:backgroundDimEnabled">false</item>
      </style>
+
+    <style name="RecentsTvTheme.Wallpaper" parent="@android:style/Theme.Material.NoActionBar.Overscan">
+        <item name="android:windowBackground">@android:color/transparent</item>
+        <item name="android:backgroundDimEnabled">false</item>
+        <item name="android:colorBackgroundCacheHint">@null</item>
+        <item name="android:windowIsTranslucent">true</item>
+    </style>
 </resources>
diff --git a/packages/SystemUI/res/xml/tuner_prefs.xml b/packages/SystemUI/res/xml/tuner_prefs.xml
index f4a0cc9..ddc03a3 100644
--- a/packages/SystemUI/res/xml/tuner_prefs.xml
+++ b/packages/SystemUI/res/xml/tuner_prefs.xml
@@ -134,8 +134,8 @@
     -->
 
     <PreferenceScreen
-        android:key="overview"
-        android:title="@string/overview" >
+        android:key="other"
+        android:title="@string/other" >
 
         <com.android.systemui.tuner.TunerSwitch
             android:key="overview_disable_fast_toggle_via_button"
@@ -147,6 +147,11 @@
             android:title="@string/overview_nav_bar_gesture"
             android:summary="@string/overview_nav_bar_gesture_desc" />
 
+        <!-- importance -->
+        <com.android.systemui.tuner.TunerSwitch
+                android:key="show_importance_slider"
+                android:title="@string/tuner_full_importance_settings" />
+
     </PreferenceScreen>
 
     <!-- Warning, this goes last. -->
diff --git a/packages/SystemUI/src/com/android/systemui/DensityContainer.java b/packages/SystemUI/src/com/android/systemui/DensityContainer.java
new file mode 100644
index 0000000..2e3cb49
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/DensityContainer.java
@@ -0,0 +1,78 @@
+/*
+ * 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;
+
+import android.annotation.Nullable;
+import android.content.Context;
+import android.content.res.Configuration;
+import android.content.res.TypedArray;
+import android.util.AttributeSet;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.FrameLayout;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class DensityContainer extends FrameLayout {
+
+    private final List<InflateListener> mInflateListeners = new ArrayList<>();
+    private final int mLayout;
+    private int mDensity;
+
+    public DensityContainer(Context context, @Nullable AttributeSet attrs) {
+        super(context, attrs);
+
+        mDensity = context.getResources().getConfiguration().densityDpi;
+
+        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.DensityContainer);
+        if (!a.hasValue(R.styleable.DensityContainer_android_layout)) {
+            throw new IllegalArgumentException("DensityContainer must contain a layout");
+        }
+        mLayout = a.getResourceId(R.styleable.DensityContainer_android_layout, 0);
+        inflateLayout();
+    }
+
+    @Override
+    protected void onConfigurationChanged(Configuration newConfig) {
+        super.onConfigurationChanged(newConfig);
+        int density = newConfig.densityDpi;
+        if (density != mDensity) {
+            mDensity = density;
+            inflateLayout();
+        }
+    }
+
+    private void inflateLayout() {
+        removeAllViews();
+        LayoutInflater.from(getContext()).inflate(mLayout, this);
+        final int N = mInflateListeners.size();
+        for (int i = 0; i < N; i++) {
+            mInflateListeners.get(i).onInflated(getChildAt(0));
+        }
+    }
+
+    public void addInflateListener(InflateListener listener) {
+        mInflateListeners.add(listener);
+        listener.onInflated(getChildAt(0));
+    }
+
+    public interface InflateListener {
+        /**
+         * Called whenever a new view is inflated.
+         */
+        void onInflated(View v);
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/Prefs.java b/packages/SystemUI/src/com/android/systemui/Prefs.java
index 1471622..9f2745b 100644
--- a/packages/SystemUI/src/com/android/systemui/Prefs.java
+++ b/packages/SystemUI/src/com/android/systemui/Prefs.java
@@ -48,6 +48,7 @@
         Key.QS_DATA_SAVER_ADDED,
         Key.QS_INVERT_COLORS_ADDED,
         Key.QS_WORK_ADDED,
+        Key.QS_NIGHT_ADDED,
     })
     public @interface Key {
         String OVERVIEW_SEARCH_APP_WIDGET_ID = "searchAppWidgetId";
@@ -68,6 +69,7 @@
         String QS_DATA_SAVER_ADDED = "QsDataSaverAdded";
         String QS_INVERT_COLORS_ADDED = "QsInvertColorsAdded";
         String QS_WORK_ADDED = "QsWorkAdded";
+        String QS_NIGHT_ADDED = "QsNightAdded";
     }
 
     public static boolean getBoolean(Context context, @Key String key, boolean defaultValue) {
diff --git a/packages/SystemUI/src/com/android/systemui/SwipeHelper.java b/packages/SystemUI/src/com/android/systemui/SwipeHelper.java
index 33f3c30..81ba23f 100644
--- a/packages/SystemUI/src/com/android/systemui/SwipeHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/SwipeHelper.java
@@ -32,6 +32,7 @@
 import android.view.accessibility.AccessibilityEvent;
 
 import com.android.systemui.classifier.FalsingManager;
+import com.android.systemui.statusbar.FlingAnimationUtils;
 
 public class SwipeHelper implements Gefingerpoken {
     static final String TAG = "com.android.systemui.SwipeHelper";
@@ -58,6 +59,7 @@
     private float mMinSwipeProgress = 0f;
     private float mMaxSwipeProgress = 1f;
 
+    private FlingAnimationUtils mFlingAnimationUtils;
     private float mPagingTouchSlop;
     private Callback mCallback;
     private Handler mHandler;
@@ -95,6 +97,8 @@
         mFalsingThreshold = context.getResources().getDimensionPixelSize(
                 R.dimen.swipe_helper_falsing_threshold);
         mFalsingManager = FalsingManager.getInstance(context);
+        mFlingAnimationUtils = new FlingAnimationUtils(context,
+                MAX_ESCAPE_ANIMATION_DURATION / 1000f /* maxLengthSeconds */);
     }
 
     public void setLongPressListener(LongPressListener listener) {
@@ -144,7 +148,9 @@
     protected Animator getViewTranslationAnimator(View v, float target,
             AnimatorUpdateListener listener) {
         ObjectAnimator anim = createTranslationAnimation(v, target);
-        anim.addUpdateListener(listener);
+        if (listener != null) {
+            anim.addUpdateListener(listener);
+        }
         return anim;
     }
 
@@ -318,7 +324,8 @@
      * @param velocity The desired pixels/second speed at which the view should move
      */
     public void dismissChild(final View view, float velocity) {
-        dismissChild(view, velocity, null, 0, false, 0);
+        dismissChild(view, velocity, null /* endAction */, 0 /* delay */,
+                velocity == 0 /* useAccelerateInterpolator */, 0 /* fixedDuration */);
     }
 
     /**
@@ -370,12 +377,16 @@
         };
 
         Animator anim = getViewTranslationAnimator(animView, newPos, updateListener);
+        if (anim == null) {
+            return;
+        }
         if (useAccelerateInterpolator) {
             anim.setInterpolator(Interpolators.FAST_OUT_LINEAR_IN);
+            anim.setDuration(duration);
         } else {
-            anim.setInterpolator(Interpolators.LINEAR);
+            mFlingAnimationUtils.applyDismissing(anim, getTranslation(animView),
+                    newPos, velocity, getSize(animView));
         }
-        anim.setDuration(duration);
         if (delay > 0) {
             anim.setStartDelay(delay);
         }
@@ -411,6 +422,9 @@
         };
 
         Animator anim = getViewTranslationAnimator(animView, targetLeft, updateListener);
+        if (anim == null) {
+            return;
+        }
         int duration = SNAP_ANIM_LEN;
         anim.setDuration(duration);
         anim.addListener(new AnimatorListenerAdapter() {
@@ -503,35 +517,16 @@
                 break;
             case MotionEvent.ACTION_UP:
             case MotionEvent.ACTION_CANCEL:
-                if (mCurrView != null) {
-                    float maxVelocity = MAX_DISMISS_VELOCITY * mDensityScale;
-                    mVelocityTracker.computeCurrentVelocity(1000 /* px/sec */, maxVelocity);
-                    float escapeVelocity = SWIPE_ESCAPE_VELOCITY * mDensityScale;
-                    float velocity = getVelocity(mVelocityTracker);
-                    float perpendicularVelocity = getPerpendicularVelocity(mVelocityTracker);
+                if (mCurrView == null) {
+                    break;
+                }
+                mVelocityTracker.computeCurrentVelocity(1000 /* px/sec */, getMaxVelocity());
+                float velocity = getVelocity(mVelocityTracker);
 
-                    float translation = getTranslation(mCurrView);
-                    // Decide whether to dismiss the current view
-                    boolean childSwipedFarEnough = DISMISS_IF_SWIPED_FAR_ENOUGH &&
-                            Math.abs(translation) > 0.4 * getSize(mCurrView);
-                    boolean childSwipedFastEnough = (Math.abs(velocity) > escapeVelocity) &&
-                            (Math.abs(velocity) > Math.abs(perpendicularVelocity)) &&
-                            (velocity > 0) == (translation > 0);
-                    boolean falsingDetected = mCallback.isAntiFalsingNeeded();
-
-                    if (mFalsingManager.isClassiferEnabled()) {
-                        falsingDetected = falsingDetected && mFalsingManager.isFalseTouch();
-                    } else {
-                        falsingDetected = falsingDetected && !mTouchAboveFalsingThreshold;
-                    }
-
-                    boolean dismissChild = mCallback.canChildBeDismissed(mCurrView)
-                            && !falsingDetected && (childSwipedFastEnough || childSwipedFarEnough)
-                            && ev.getActionMasked() == MotionEvent.ACTION_UP;
-
-                    if (dismissChild) {
+                if (!handleUpEvent(ev, mCurrView, velocity, getTranslation(mCurrView))) {
+                    if (isDismissGesture(ev)) {
                         // flingadingy
-                        dismissChild(mCurrView, childSwipedFastEnough ? velocity : 0f);
+                        dismissChild(mCurrView, swipedFastEnough() ? velocity : 0f);
                     } else {
                         // snappity
                         mCallback.onDragCancelled(mCurrView);
@@ -548,6 +543,46 @@
         return (int) (mFalsingThreshold * factor);
     }
 
+    private float getMaxVelocity() {
+        return MAX_DISMISS_VELOCITY * mDensityScale;
+    }
+
+    protected float getEscapeVelocity() {
+        return SWIPE_ESCAPE_VELOCITY * mDensityScale;
+    }
+
+    protected boolean swipedFarEnough() {
+        float translation = getTranslation(mCurrView);
+        return DISMISS_IF_SWIPED_FAR_ENOUGH && Math.abs(translation) > 0.4 * getSize(mCurrView);
+    }
+
+    protected boolean isDismissGesture(MotionEvent ev) {
+        boolean falsingDetected = mCallback.isAntiFalsingNeeded();
+        if (mFalsingManager.isClassiferEnabled()) {
+            falsingDetected = falsingDetected && mFalsingManager.isFalseTouch();
+        } else {
+            falsingDetected = falsingDetected && !mTouchAboveFalsingThreshold;
+        }
+        return !falsingDetected && (swipedFastEnough() || swipedFarEnough())
+                && ev.getActionMasked() == MotionEvent.ACTION_UP
+                && mCallback.canChildBeDismissed(mCurrView);
+    }
+
+    protected boolean swipedFastEnough() {
+        float velocity = getVelocity(mVelocityTracker);
+        float perpendicularVelocity = getPerpendicularVelocity(mVelocityTracker);
+        float translation = getTranslation(mCurrView);
+        boolean ret = (Math.abs(velocity) > getEscapeVelocity()) &&
+                (Math.abs(velocity) > Math.abs(perpendicularVelocity)) &&
+                (velocity > 0) == (translation > 0);
+        return ret;
+    }
+
+    protected boolean handleUpEvent(MotionEvent ev, View animView, float velocity,
+            float translation) {
+        return false;
+    }
+
     public interface Callback {
         View getChildAtPosition(MotionEvent ev);
 
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java b/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
index 472648a..b2b6127 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
@@ -54,7 +54,8 @@
             com.android.systemui.power.PowerUI.class,
             com.android.systemui.media.RingtonePlayer.class,
             com.android.systemui.keyboard.KeyboardUI.class,
-            com.android.systemui.tv.pip.PipUI.class
+            com.android.systemui.tv.pip.PipUI.class,
+            com.android.systemui.shortcut.ShortcutKeyDispatcher.class
     };
 
     /**
@@ -143,12 +144,14 @@
             Class<?> cl = services[i];
             if (DEBUG) Log.d(TAG, "loading: " + cl);
             try {
-                mServices[i] = (SystemUI) cl.newInstance();
+                Object newService = SystemUIFactory.getInstance().createInstance(cl);
+                mServices[i] = (SystemUI) ((newService == null) ? cl.newInstance() : newService);
             } catch (IllegalAccessException ex) {
                 throw new RuntimeException(ex);
             } catch (InstantiationException ex) {
                 throw new RuntimeException(ex);
             }
+
             mServices[i].mContext = this;
             mServices[i].mComponents = mComponents;
             if (DEBUG) Log.d(TAG, "running: " + mServices[i]);
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java b/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
index 41cce74..2e94bc7 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
@@ -71,7 +71,11 @@
     }
 
     public ScrimController createScrimController(ScrimView scrimBehind, ScrimView scrimInFront,
-            View headsUpScrim, boolean scrimSrcEnabled) {
-        return new ScrimController(scrimBehind, scrimInFront, headsUpScrim, scrimSrcEnabled);
+            View headsUpScrim) {
+        return new ScrimController(scrimBehind, scrimInFront, headsUpScrim);
+    }
+
+    public <T> T createInstance(Class<T> classType) {
+        return null;
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/AccelerationClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/AccelerationClassifier.java
index 86bea87..bad739fd 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/AccelerationClassifier.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/AccelerationClassifier.java
@@ -36,6 +36,11 @@
     }
 
     @Override
+    public String getTag() {
+        return "ACC";
+    }
+
+    @Override
     public void onTouchEvent(MotionEvent event) {
         int action = event.getActionMasked();
 
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/AnglesClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/AnglesClassifier.java
index dba731a..526e5fa 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/AnglesClassifier.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/AnglesClassifier.java
@@ -54,6 +54,11 @@
     }
 
     @Override
+    public String getTag() {
+        return "ANG";
+    }
+
+    @Override
     public void onTouchEvent(MotionEvent event) {
         int action = event.getActionMasked();
 
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/Classifier.java b/packages/SystemUI/src/com/android/systemui/classifier/Classifier.java
index 89d20de..cb761a9 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/Classifier.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/Classifier.java
@@ -48,4 +48,6 @@
      */
     public void onSensorChanged(SensorEvent event) {
     }
+
+    public abstract String getTag();
 }
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/DirectionClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/DirectionClassifier.java
index 299d0e3..610e219 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/DirectionClassifier.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/DirectionClassifier.java
@@ -25,6 +25,11 @@
     }
 
     @Override
+    public String getTag() {
+        return "DIR";
+    }
+
+    @Override
     public float getFalseTouchEvaluation(int type, Stroke stroke) {
         Point firstPoint = stroke.getPoints().get(0);
         Point lastPoint = stroke.getPoints().get(stroke.getPoints().size() - 1);
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/DurationCountClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/DurationCountClassifier.java
index 8924694..77fda20 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/DurationCountClassifier.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/DurationCountClassifier.java
@@ -25,6 +25,11 @@
     }
 
     @Override
+    public String getTag() {
+        return "DUR";
+    }
+
+    @Override
     public float getFalseTouchEvaluation(int type, Stroke stroke) {
         return DurationCountEvaluator.evaluate(stroke.getDurationSeconds() / stroke.getCount());
     }
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/EndPointLengthClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/EndPointLengthClassifier.java
index 78bc0dd..de8a188 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/EndPointLengthClassifier.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/EndPointLengthClassifier.java
@@ -24,6 +24,11 @@
     }
 
     @Override
+    public String getTag() {
+        return "END_LNGTH";
+    }
+
+    @Override
     public float getFalseTouchEvaluation(int type, Stroke stroke) {
         return EndPointLengthEvaluator.evaluate(stroke.getEndPointLength());
     }
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/EndPointRatioClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/EndPointRatioClassifier.java
index 652d969..9b6ddc8 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/EndPointRatioClassifier.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/EndPointRatioClassifier.java
@@ -26,6 +26,11 @@
     }
 
     @Override
+    public String getTag() {
+        return "END_RTIO";
+    }
+
+    @Override
     public float getFalseTouchEvaluation(int type, Stroke stroke) {
         float ratio;
         if (stroke.getTotalLength() == 0.0f) {
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/FalsingLog.java b/packages/SystemUI/src/com/android/systemui/classifier/FalsingLog.java
new file mode 100644
index 0000000..1338d9d
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/classifier/FalsingLog.java
@@ -0,0 +1,166 @@
+/*
+ * 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.classifier;
+
+import android.app.ActivityThread;
+import android.app.Application;
+import android.os.Build;
+import android.os.SystemProperties;
+import android.util.Log;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.text.SimpleDateFormat;
+import java.util.ArrayDeque;
+import java.util.Date;
+import java.util.Locale;
+
+/**
+ * Keeps track of interesting falsing data.
+ *
+ * By default the log only gets collected on userdebug builds. To turn it on on user:
+ *  adb shell setprop debug.falsing_log true
+ *
+ * The log gets dumped as part of the SystemUI services. To dump on demand:
+ *  adb shell dumpsys activity service com.android.systemui SystemBars | grep -A 999 FALSING | less
+ *
+ * To dump into logcat:
+ *  adb shell setprop debug.falsing_logcat true
+ *
+ * To adjust the log buffer size:
+ *  adb shell setprop debug.falsing_log_size 200
+ */
+public class FalsingLog {
+    public static final boolean ENABLED = SystemProperties.getBoolean("debug.falsing_log",
+            Build.IS_DEBUGGABLE);
+    private static final boolean LOGCAT = SystemProperties.getBoolean("debug.falsing_logcat",
+            false);
+
+    public static final boolean VERBOSE = false;
+
+    private static final int MAX_SIZE = SystemProperties.getInt("debug.falsing_log_size", 100);
+
+    private static final String TAG = "FalsingLog";
+
+    private final ArrayDeque<String> mLog = new ArrayDeque<>(MAX_SIZE);
+    private final SimpleDateFormat mFormat = new SimpleDateFormat("MM-dd HH:mm:ss", Locale.US);
+
+    private static FalsingLog sInstance;
+
+    private FalsingLog() {
+    }
+
+    public static void v(String tag, String s) {
+        if (!VERBOSE) {
+            return;
+        }
+        if (LOGCAT) {
+            Log.v(TAG, tag + "\t" + s);
+        }
+        log("V", tag, s);
+    }
+
+    public static void i(String tag, String s) {
+        if (LOGCAT) {
+            Log.i(TAG, tag + "\t" + s);
+        }
+        log("I", tag, s);
+    }
+
+    public static void w(String tag, String s) {
+        if (LOGCAT) {
+            Log.w(TAG, tag + "\t" + s);
+        }
+        log("W", tag, s);
+    }
+
+    public static void e(String tag, String s) {
+        if (LOGCAT) {
+            Log.e(TAG, tag + "\t" + s);
+        }
+        log("E", tag, s);
+    }
+
+    public static synchronized void log(String level, String tag, String s) {
+        if (!ENABLED) {
+            return;
+        }
+        if (sInstance == null) {
+            sInstance = new FalsingLog();
+        }
+
+        if (sInstance.mLog.size() >= MAX_SIZE) {
+            sInstance.mLog.removeFirst();
+        }
+        String entry = new StringBuilder().append(sInstance.mFormat.format(new Date()))
+            .append(" ").append(level).append(" ")
+            .append(tag).append(" ").append(s).toString();
+        sInstance.mLog.add(entry);
+    }
+
+    public static synchronized void dump(PrintWriter pw) {
+        pw.println("FALSING LOG:");
+        if (!ENABLED) {
+            pw.println("Disabled, to enable: setprop debug.falsing_log 1");
+            pw.println();
+            return;
+        }
+        if (sInstance == null || sInstance.mLog.isEmpty()) {
+            pw.println("<empty>");
+            pw.println();
+            return;
+        }
+        for (String s : sInstance.mLog) {
+            pw.println(s);
+        }
+        pw.println();
+    }
+
+    public static synchronized void wtf(String tag, String s) {
+        if (!ENABLED) {
+            return;
+        }
+        e(tag, s);
+
+        Application application = ActivityThread.currentApplication();
+        String fileMessage = "";
+        if (Build.IS_DEBUGGABLE && application != null) {
+            File f = new File(application.getDataDir(), "falsing-"
+                    + new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss").format(new Date()) + ".txt");
+            PrintWriter pw = null;
+            try {
+                pw = new PrintWriter(f);
+                dump(pw);
+                pw.close();
+                fileMessage = "Log written to " + f.getAbsolutePath();
+            } catch (IOException e) {
+                Log.e(TAG, "Unable to write falsing log", e);
+            } finally {
+                if (pw != null) {
+                    pw.close();
+                }
+            }
+        } else {
+            Log.e(TAG, "Unable to write log, build must be debuggable.");
+        }
+
+        Log.wtf(TAG, tag + " " + s + "; " + fileMessage);
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/FalsingManager.java b/packages/SystemUI/src/com/android/systemui/classifier/FalsingManager.java
index c09376b..937f7d3 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/FalsingManager.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/FalsingManager.java
@@ -31,6 +31,8 @@
 import com.android.systemui.analytics.DataCollector;
 import com.android.systemui.statusbar.StatusBarState;
 
+import java.io.PrintWriter;
+
 /**
  * When the phone is locked, listens to touch, sensor and phone events and sends them to
  * DataCollector and HumanInteractionClassifier.
@@ -102,8 +104,14 @@
     }
 
     private boolean shouldSessionBeActive() {
-        return isEnabled() && mScreenOn &&
-                (mState == StatusBarState.KEYGUARD || mState == StatusBarState.SHADE_LOCKED);
+        if (FalsingLog.ENABLED && FalsingLog.VERBOSE)
+            FalsingLog.v("shouldBeActive", new StringBuilder()
+                    .append("enabled=").append(isEnabled() ? 1 : 0)
+                    .append(" mScreenOn=").append(mScreenOn ? 1 : 0)
+                    .append(" mState=").append(StatusBarState.toShortString(mState))
+                    .toString()
+            );
+        return isEnabled() && mScreenOn && (mState == StatusBarState.KEYGUARD);
     }
 
     private boolean sessionEntrypoint() {
@@ -122,6 +130,9 @@
     }
 
     private void onSessionStart() {
+        if (FalsingLog.ENABLED) {
+            FalsingLog.i("onSessionStart", "classifierEnabled=" + isClassiferEnabled());
+        }
         mBouncerOn = false;
         mSessionActive = true;
 
@@ -154,6 +165,16 @@
      * @return true if the classifier determined that this is not a human interacting with the phone
      */
     public boolean isFalseTouch() {
+        if (FalsingLog.ENABLED) {
+            if (!mSessionActive) {
+                FalsingLog.wtf("isFalseTouch", new StringBuilder()
+                        .append("Session is not active, yet there's a query for a false touch.")
+                        .append(" enabled=").append(isEnabled() ? 1 : 0)
+                        .append(" mScreenOn=").append(mScreenOn ? 1 : 0)
+                        .append(" mState=").append(StatusBarState.toShortString(mState))
+                        .toString());
+            }
+        }
         return mHumanInteractionClassifier.isFalseTouch();
     }
 
@@ -173,6 +194,12 @@
     }
 
     public void setStatusBarState(int state) {
+        if (FalsingLog.ENABLED) {
+            FalsingLog.i("setStatusBarState", new StringBuilder()
+                    .append("from=").append(StatusBarState.toShortString(mState))
+                    .append(" to=").append(StatusBarState.toShortString(state))
+                    .toString());
+        }
         mState = state;
         if (shouldSessionBeActive()) {
             sessionEntrypoint();
@@ -182,6 +209,11 @@
     }
 
     public void onScreenTurningOn() {
+        if (FalsingLog.ENABLED) {
+            FalsingLog.i("onScreenTurningOn", new StringBuilder()
+                    .append("from=").append(mScreenOn ? 1 : 0)
+                    .toString());
+        }
         mScreenOn = true;
         if (sessionEntrypoint()) {
             mDataCollector.onScreenTurningOn();
@@ -189,6 +221,11 @@
     }
 
     public void onScreenOnFromTouch() {
+        if (FalsingLog.ENABLED) {
+            FalsingLog.i("onScreenOnFromTouch", new StringBuilder()
+                    .append("from=").append(mScreenOn ? 1 : 0)
+                    .toString());
+        }
         mScreenOn = true;
         if (sessionEntrypoint()) {
             mDataCollector.onScreenOnFromTouch();
@@ -196,17 +233,30 @@
     }
 
     public void onScreenOff() {
+        if (FalsingLog.ENABLED) {
+            FalsingLog.i("onScreenOff", new StringBuilder()
+                    .append("from=").append(mScreenOn ? 1 : 0)
+                    .toString());
+        }
         mDataCollector.onScreenOff();
         mScreenOn = false;
         sessionExitpoint(false /* force */);
     }
 
     public void onSucccessfulUnlock() {
+        if (FalsingLog.ENABLED) {
+            FalsingLog.i("onSucccessfulUnlock", "");
+        }
         mDataCollector.onSucccessfulUnlock();
         sessionExitpoint(true /* force */);
     }
 
     public void onBouncerShown() {
+        if (FalsingLog.ENABLED) {
+            FalsingLog.i("onBouncerShown", new StringBuilder()
+                    .append("from=").append(mBouncerOn ? 1 : 0)
+                    .toString());
+        }
         if (!mBouncerOn) {
             mBouncerOn = true;
             mDataCollector.onBouncerShown();
@@ -214,6 +264,11 @@
     }
 
     public void onBouncerHidden() {
+        if (FalsingLog.ENABLED) {
+            FalsingLog.i("onBouncerHidden", new StringBuilder()
+                    .append("from=").append(mBouncerOn ? 1 : 0)
+                    .toString());
+        }
         if (mBouncerOn) {
             mBouncerOn = false;
             mDataCollector.onBouncerHidden();
@@ -221,6 +276,9 @@
     }
 
     public void onQsDown() {
+        if (FalsingLog.ENABLED) {
+            FalsingLog.i("onQsDown", "");
+        }
         mHumanInteractionClassifier.setType(Classifier.QUICK_SETTINGS);
         mDataCollector.onQsDown();
     }
@@ -230,6 +288,9 @@
     }
 
     public void onTrackingStarted() {
+        if (FalsingLog.ENABLED) {
+            FalsingLog.i("onTrackingStarted", "");
+        }
         mHumanInteractionClassifier.setType(Classifier.UNLOCK);
         mDataCollector.onTrackingStarted();
     }
@@ -251,6 +312,9 @@
     }
 
     public void onNotificatonStartDraggingDown() {
+        if (FalsingLog.ENABLED) {
+            FalsingLog.i("onNotificatonStartDraggingDown", "");
+        }
         mHumanInteractionClassifier.setType(Classifier.NOTIFICATION_DRAG_DOWN);
         mDataCollector.onNotificatonStartDraggingDown();
     }
@@ -264,6 +328,9 @@
     }
 
     public void onNotificatonStartDismissing() {
+        if (FalsingLog.ENABLED) {
+            FalsingLog.i("onNotificatonStartDismissing", "");
+        }
         mHumanInteractionClassifier.setType(Classifier.NOTIFICATION_DISMISS);
         mDataCollector.onNotificatonStartDismissing();
     }
@@ -281,6 +348,9 @@
     }
 
     public void onAffordanceSwipingStarted(boolean rightCorner) {
+        if (FalsingLog.ENABLED) {
+            FalsingLog.i("onAffordanceSwipingStarted", "");
+        }
         if (rightCorner) {
             mHumanInteractionClassifier.setType(Classifier.RIGHT_AFFORDANCE);
         } else {
@@ -311,4 +381,14 @@
             mHumanInteractionClassifier.onTouchEvent(event);
         }
     }
+
+    public void dump(PrintWriter pw) {
+        pw.println("FALSING MANAGER");
+        pw.print("classifierEnabled="); pw.println(isClassiferEnabled() ? 1 : 0);
+        pw.print("mSessionActive="); pw.println(mSessionActive ? 1 : 0);
+        pw.print("mBouncerOn="); pw.println(mSessionActive ? 1 : 0);
+        pw.print("mState="); pw.println(StatusBarState.toShortString(mState));
+        pw.print("mScreenOn="); pw.println(mScreenOn ? 1 : 0);
+        pw.println();
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/HumanInteractionClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/HumanInteractionClassifier.java
index 45eb9ad..5e35d76 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/HumanInteractionClassifier.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/HumanInteractionClassifier.java
@@ -23,6 +23,7 @@
 import android.os.UserHandle;
 import android.provider.Settings;
 import android.util.DisplayMetrics;
+import android.util.Log;
 import android.view.MotionEvent;
 
 import java.util.ArrayDeque;
@@ -43,14 +44,12 @@
     private final Handler mHandler = new Handler();
     private final Context mContext;
 
-    private ArrayList<StrokeClassifier> mStrokeClassifiers = new ArrayList<>();
-    private ArrayList<GestureClassifier> mGestureClassifiers = new ArrayList<>();
-    private ArrayDeque<MotionEvent> mBufferedEvents = new ArrayDeque<>();
-    private final int mStrokeClassifiersSize;
-    private final int mGestureClassifiersSize;
+    private final StrokeClassifier[] mStrokeClassifiers;
+    private final GestureClassifier[] mGestureClassifiers;
+    private final ArrayDeque<MotionEvent> mBufferedEvents = new ArrayDeque<>();
+    private final HistoryEvaluator mHistoryEvaluator;
     private final float mDpi;
 
-    private HistoryEvaluator mHistoryEvaluator;
     private boolean mEnableClassifier = false;
     private int mCurrentType = Classifier.GENERIC;
 
@@ -68,25 +67,27 @@
         // If the phone is rotated to landscape, the calculations would be wrong if xdpi and ydpi
         // were to be used separately. Due negligible differences in xdpi and ydpi we can just
         // take the average.
+        // TODO: make this respect DPI changes.
         mDpi = (displayMetrics.xdpi + displayMetrics.ydpi) / 2.0f;
         mClassifierData = new ClassifierData(mDpi);
         mHistoryEvaluator = new HistoryEvaluator();
 
-        mStrokeClassifiers.add(new AnglesClassifier(mClassifierData));
-        mStrokeClassifiers.add(new SpeedClassifier(mClassifierData));
-        mStrokeClassifiers.add(new DurationCountClassifier(mClassifierData));
-        mStrokeClassifiers.add(new EndPointRatioClassifier(mClassifierData));
-        mStrokeClassifiers.add(new EndPointLengthClassifier(mClassifierData));
-        mStrokeClassifiers.add(new AccelerationClassifier(mClassifierData));
-        mStrokeClassifiers.add(new SpeedAnglesClassifier(mClassifierData));
-        mStrokeClassifiers.add(new LengthCountClassifier(mClassifierData));
-        mStrokeClassifiers.add(new DirectionClassifier(mClassifierData));
+        mStrokeClassifiers = new StrokeClassifier[]{
+                new AnglesClassifier(mClassifierData),
+                new SpeedClassifier(mClassifierData),
+                new DurationCountClassifier(mClassifierData),
+                new EndPointRatioClassifier(mClassifierData),
+                new EndPointLengthClassifier(mClassifierData),
+                new AccelerationClassifier(mClassifierData),
+                new SpeedAnglesClassifier(mClassifierData),
+                new LengthCountClassifier(mClassifierData),
+                new DirectionClassifier(mClassifierData),
+        };
 
-        mGestureClassifiers.add(new PointerCountClassifier(mClassifierData));
-        mGestureClassifiers.add(new ProximityClassifier(mClassifierData));
-
-        mStrokeClassifiersSize = mStrokeClassifiers.size();
-        mGestureClassifiersSize = mGestureClassifiers.size();
+        mGestureClassifiers = new GestureClassifier[] {
+                new PointerCountClassifier(mClassifierData),
+                new ProximityClassifier(mClassifierData)
+        };
 
         mContext.getContentResolver().registerContentObserver(
                 Settings.Global.getUriFor(HIC_ENABLE), false,
@@ -150,21 +151,30 @@
     private void addTouchEvent(MotionEvent event) {
         mClassifierData.update(event);
 
-        for (int i = 0; i < mStrokeClassifiersSize; i++) {
-            mStrokeClassifiers.get(i).onTouchEvent(event);
+        for (StrokeClassifier c : mStrokeClassifiers) {
+            c.onTouchEvent(event);
         }
 
-        for (int i = 0; i < mGestureClassifiersSize; i++) {
-            mGestureClassifiers.get(i).onTouchEvent(event);
+        for (GestureClassifier c : mGestureClassifiers) {
+            c.onTouchEvent(event);
         }
 
         int size = mClassifierData.getEndingStrokes().size();
         for (int i = 0; i < size; i++) {
             Stroke stroke = mClassifierData.getEndingStrokes().get(i);
             float evaluation = 0.0f;
-            for (int j = 0; j < mStrokeClassifiersSize; j++) {
-                evaluation += mStrokeClassifiers.get(j).getFalseTouchEvaluation(
-                        mCurrentType, stroke);
+            StringBuilder sb = FalsingLog.ENABLED ? new StringBuilder("stroke") : null;
+            for (StrokeClassifier c : mStrokeClassifiers) {
+                float e = c.getFalseTouchEvaluation(mCurrentType, stroke);
+                if (FalsingLog.ENABLED) {
+                    String tag = c.getTag();
+                    sb.append(" ").append(e >= 1f ? tag : tag.toLowerCase()).append("=").append(e);
+                }
+                evaluation += e;
+            }
+
+            if (FalsingLog.ENABLED) {
+                FalsingLog.i(" addTouchEvent", sb.toString());
             }
             mHistoryEvaluator.addStroke(evaluation);
         }
@@ -172,8 +182,17 @@
         int action = event.getActionMasked();
         if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) {
             float evaluation = 0.0f;
-            for (int i = 0; i < mGestureClassifiersSize; i++) {
-                evaluation += mGestureClassifiers.get(i).getFalseTouchEvaluation(mCurrentType);
+            StringBuilder sb = FalsingLog.ENABLED ? new StringBuilder("gesture") : null;
+            for (GestureClassifier c : mGestureClassifiers) {
+                float e = c.getFalseTouchEvaluation(mCurrentType);
+                if (FalsingLog.ENABLED) {
+                    String tag = c.getTag();
+                    sb.append(" ").append(e >= 1f ? tag : tag.toLowerCase()).append("=").append(e);
+                }
+                evaluation += e;
+            }
+            if (FalsingLog.ENABLED) {
+                FalsingLog.i(" addTouchEvent", sb.toString());
             }
             mHistoryEvaluator.addGesture(evaluation);
             setType(Classifier.GENERIC);
@@ -184,18 +203,25 @@
 
     @Override
     public void onSensorChanged(SensorEvent event) {
-        for (int i = 0; i < mStrokeClassifiers.size(); i++) {
-            mStrokeClassifiers.get(i).onSensorChanged(event);
+        for (Classifier c : mStrokeClassifiers) {
+            c.onSensorChanged(event);
         }
 
-        for (int i = 0; i < mGestureClassifiers.size(); i++) {
-            mGestureClassifiers.get(i).onSensorChanged(event);
+        for (Classifier c : mGestureClassifiers) {
+            c.onSensorChanged(event);
         }
     }
 
     public boolean isFalseTouch() {
         if (mEnableClassifier) {
-            return mHistoryEvaluator.getEvaluation() >= 5.0f;
+            float evaluation = mHistoryEvaluator.getEvaluation();
+            boolean result = evaluation >= 5.0f;
+            if (FalsingLog.ENABLED) {
+                FalsingLog.i("isFalseTouch", new StringBuilder()
+                        .append("eval=").append(evaluation).append(" result=")
+                        .append(result ? 1 : 0).toString());
+            }
+            return result;
         }
         return false;
     }
@@ -203,4 +229,9 @@
     public boolean isEnabled() {
         return mEnableClassifier;
     }
+
+    @Override
+    public String getTag() {
+        return "HIC";
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/LengthCountClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/LengthCountClassifier.java
index cedf467..53678a6 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/LengthCountClassifier.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/LengthCountClassifier.java
@@ -28,6 +28,11 @@
     }
 
     @Override
+    public String getTag() {
+        return "LEN_CNT";
+    }
+
+    @Override
     public float getFalseTouchEvaluation(int type, Stroke stroke) {
         return LengthCountEvaluator.evaluate(stroke.getTotalLength()
                 / Math.max(1.0f, stroke.getCount() - 2));
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/PointerCountClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/PointerCountClassifier.java
index 5097b63..136c433 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/PointerCountClassifier.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/PointerCountClassifier.java
@@ -29,6 +29,11 @@
     }
 
     @Override
+    public String getTag() {
+        return "PTR_CNT";
+    }
+
+    @Override
     public void onTouchEvent(MotionEvent event) {
         int action = event.getActionMasked();
 
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/ProximityClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/ProximityClassifier.java
index 6995064..62adfc8 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/ProximityClassifier.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/ProximityClassifier.java
@@ -35,6 +35,11 @@
     }
 
     @Override
+    public String getTag() {
+        return "PROX";
+    }
+
+    @Override
     public void onSensorChanged(SensorEvent event) {
         if (event.sensor.getType() == Sensor.TYPE_PROXIMITY) {
             update(event.values[0] < event.sensor.getMaximumRange(), event.timestamp);
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/SpeedAnglesClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/SpeedAnglesClassifier.java
index d58274d..6df72b1 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/SpeedAnglesClassifier.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/SpeedAnglesClassifier.java
@@ -41,6 +41,11 @@
     }
 
     @Override
+    public String getTag() {
+        return "SPD_ANG";
+    }
+
+    @Override
     public void onTouchEvent(MotionEvent event) {
         int action = event.getActionMasked();
 
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/SpeedClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/SpeedClassifier.java
index 81b78c7..01fcc37 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/SpeedClassifier.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/SpeedClassifier.java
@@ -27,6 +27,11 @@
     }
 
     @Override
+    public String getTag() {
+        return "SPD";
+    }
+
+    @Override
     public float getFalseTouchEvaluation(int type, Stroke stroke) {
         float duration = (float) stroke.getDurationNanos() / NANOS_TO_SECONDS;
         if (duration == 0.0f) {
diff --git a/packages/SystemUI/src/com/android/systemui/keyboard/KeyboardUI.java b/packages/SystemUI/src/com/android/systemui/keyboard/KeyboardUI.java
index ea7270d..4b775a5 100644
--- a/packages/SystemUI/src/com/android/systemui/keyboard/KeyboardUI.java
+++ b/packages/SystemUI/src/com/android/systemui/keyboard/KeyboardUI.java
@@ -38,7 +38,9 @@
 import android.os.UserHandle;
 import android.provider.Settings.Secure;
 import android.text.TextUtils;
+import android.util.Pair;
 import android.util.Slog;
+import android.widget.Toast;
 
 import com.android.settingslib.bluetooth.BluetoothCallback;
 import com.android.settingslib.bluetooth.CachedBluetoothDevice;
@@ -46,6 +48,7 @@
 import com.android.settingslib.bluetooth.LocalBluetoothAdapter;
 import com.android.settingslib.bluetooth.LocalBluetoothManager;
 import com.android.settingslib.bluetooth.LocalBluetoothProfileManager;
+import com.android.settingslib.bluetooth.Utils;
 import com.android.systemui.R;
 import com.android.systemui.SystemUI;
 
@@ -76,8 +79,9 @@
     private static final int STATE_WAITING_FOR_BLUETOOTH = 4;
     private static final int STATE_PAIRING = 5;
     private static final int STATE_PAIRED = 6;
-    private static final int STATE_USER_CANCELLED = 7;
-    private static final int STATE_DEVICE_NOT_FOUND = 8;
+    private static final int STATE_PAIRING_FAILED = 7;
+    private static final int STATE_USER_CANCELLED = 8;
+    private static final int STATE_DEVICE_NOT_FOUND = 9;
 
     private static final int MSG_INIT = 0;
     private static final int MSG_ON_BOOT_COMPLETED = 1;
@@ -90,6 +94,7 @@
     private static final int MSG_SHOW_BLUETOOTH_DIALOG = 8;
     private static final int MSG_DISMISS_BLUETOOTH_DIALOG = 9;
     private static final int MSG_BLE_ABORT_SCAN = 10;
+    private static final int MSG_SHOW_ERROR = 11;
 
     private volatile KeyboardHandler mHandler;
     private volatile KeyboardUIHandler mUIHandler;
@@ -178,6 +183,7 @@
         mLocalBluetoothAdapter = bluetoothManager.getBluetoothAdapter();
         mProfileManager = bluetoothManager.getProfileManager();
         bluetoothManager.getEventManager().registerCallback(new BluetoothCallbackHandler());
+        Utils.setErrorListener(new BluetoothErrorListener());
 
         InputManager im = context.getSystemService(InputManager.class);
         im.registerOnTabletModeChangedListener(this, mHandler);
@@ -204,13 +210,15 @@
         if (mInTabletMode != InputManager.SWITCH_STATE_OFF) {
             if (mState == STATE_WAITING_FOR_DEVICE_DISCOVERY) {
                 stopScanning();
+            } else if (mState == STATE_WAITING_FOR_BLUETOOTH) {
+                mUIHandler.sendEmptyMessage(MSG_DISMISS_BLUETOOTH_DIALOG);
             }
             mState = STATE_WAITING_FOR_TABLET_MODE_EXIT;
             return;
         }
 
         final int btState = mLocalBluetoothAdapter.getState();
-        if (btState == BluetoothAdapter.STATE_TURNING_ON || btState == BluetoothAdapter.STATE_ON
+        if ((btState == BluetoothAdapter.STATE_TURNING_ON || btState == BluetoothAdapter.STATE_ON)
                 && mState == STATE_WAITING_FOR_BLUETOOTH) {
             // If we're waiting for bluetooth but it has come on in the meantime, or is coming
             // on, just dismiss the dialog. This frequently happens during device startup.
@@ -334,7 +342,10 @@
 
     private void stopScanning() {
         if (mScanCallback != null) {
-            mLocalBluetoothAdapter.getBluetoothLeScanner().stopScan(mScanCallback);
+            BluetoothLeScanner scanner = mLocalBluetoothAdapter.getBluetoothLeScanner();
+            if (scanner != null) {
+                scanner.stopScan(mScanCallback);
+            }
             mScanCallback = null;
         }
     }
@@ -370,10 +381,14 @@
 
     // Should only be called on the handler thread
     private void onDeviceBondStateChangedInternal(CachedBluetoothDevice d, int bondState) {
-        if (d.getName().equals(mKeyboardName) && bondState == BluetoothDevice.BOND_BONDED) {
-            // We don't need to manually connect to the device here because it will automatically
-            // try to connect after it has been paired.
-            mState = STATE_PAIRED;
+        if (mState == STATE_PAIRING && d.getName().equals(mKeyboardName)) {
+            if (bondState == BluetoothDevice.BOND_BONDED) {
+                // We don't need to manually connect to the device here because it will
+                // automatically try to connect after it has been paired.
+                mState = STATE_PAIRED;
+            } else if (bondState == BluetoothDevice.BOND_NONE) {
+                mState = STATE_PAIRING_FAILED;
+            }
         }
     }
 
@@ -385,6 +400,17 @@
         }
     }
 
+    // Should only be called on the handler thread. We want to be careful not to show errors for
+    // pairings not initiated by this UI, so we only pop up the toast when we're at an appropriate
+    // point in our pairing flow and it's the expected device.
+    private void onShowErrorInternal(Context context, String name, int messageResId) {
+        if ((mState == STATE_PAIRING || mState == STATE_PAIRING_FAILED)
+                && mKeyboardName.equals(name)) {
+            String message = context.getString(messageResId, name);
+            Toast.makeText(context, message, Toast.LENGTH_SHORT).show();
+        }
+    }
+
     private final class KeyboardUIHandler extends Handler {
         public KeyboardUIHandler() {
             super(Looper.getMainLooper(), null, true /*async*/);
@@ -393,19 +419,27 @@
         public void handleMessage(Message msg) {
             switch(msg.what) {
                 case MSG_SHOW_BLUETOOTH_DIALOG: {
-                    DialogInterface.OnClickListener listener = new BluetoothDialogClickListener();
+                    if (mDialog != null) {
+                        // Don't show another dialog if one is already present
+                        break;
+                    }
+                    DialogInterface.OnClickListener clickListener =
+                            new BluetoothDialogClickListener();
+                    DialogInterface.OnDismissListener dismissListener =
+                            new BluetoothDialogDismissListener();
                     mDialog = new BluetoothDialog(mContext);
                     mDialog.setTitle(R.string.enable_bluetooth_title);
                     mDialog.setMessage(R.string.enable_bluetooth_message);
-                    mDialog.setPositiveButton(R.string.enable_bluetooth_confirmation_ok, listener);
-                    mDialog.setNegativeButton(android.R.string.cancel, listener);
+                    mDialog.setPositiveButton(
+                            R.string.enable_bluetooth_confirmation_ok, clickListener);
+                    mDialog.setNegativeButton(android.R.string.cancel, clickListener);
+                    mDialog.setOnDismissListener(dismissListener);
                     mDialog.show();
                     break;
                 }
                 case MSG_DISMISS_BLUETOOTH_DIALOG: {
                     if (mDialog != null) {
                         mDialog.dismiss();
-                        mDialog = null;
                     }
                     break;
                 }
@@ -469,6 +503,10 @@
                     onBleScanFailedInternal();
                     break;
                 }
+                case MSG_SHOW_ERROR: {
+                    Pair<Context, String> p = (Pair<Context, String>) msg.obj;
+                    onShowErrorInternal(p.first, p.second, msg.arg1);
+                }
             }
         }
     }
@@ -482,6 +520,14 @@
         }
     }
 
+    private final class BluetoothDialogDismissListener
+            implements DialogInterface.OnDismissListener {
+        @Override
+        public void onDismiss(DialogInterface dialog) {
+            mDialog = null;
+        }
+    }
+
     private final class KeyboardScanCallback extends ScanCallback {
 
         private boolean isDeviceDiscoverable(ScanResult result) {
@@ -564,6 +610,13 @@
         public void onConnectionStateChanged(CachedBluetoothDevice cachedDevice, int state) { }
     }
 
+    private final class BluetoothErrorListener implements Utils.ErrorListener {
+        public void onShowError(Context context, String name, int messageResId) {
+            mHandler.obtainMessage(MSG_SHOW_ERROR, messageResId, 0 /*unused*/,
+                    new Pair<>(context, name)).sendToTarget();
+        }
+    }
+
     private static String stateToString(int state) {
         switch (state) {
             case STATE_NOT_ENABLED:
@@ -580,13 +633,15 @@
                 return "STATE_PAIRING";
             case STATE_PAIRED:
                 return "STATE_PAIRED";
+            case STATE_PAIRING_FAILED:
+                return "STATE_PAIRING_FAILED";
             case STATE_USER_CANCELLED:
                 return "STATE_USER_CANCELLED";
             case STATE_DEVICE_NOT_FOUND:
                 return "STATE_DEVICE_NOT_FOUND";
             case STATE_UNKNOWN:
             default:
-                return "STATE_UNKNOWN";
+                return "STATE_UNKNOWN (" + state + ")";
         }
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index 6029c23..312d3c5 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -684,7 +684,7 @@
             doKeyguardLocked(null);
             mUpdateMonitor.registerCallback(mUpdateCallback);
         }
-        mIsPerUserLock = StorageManager.isFileBasedEncryptionEnabled();
+        mIsPerUserLock = StorageManager.isFileEncryptedNativeOrEmulated();
         // Most services aren't available until the system reaches the ready state, so we
         // send it here when the device first boots.
         maybeSendUserPresentBroadcast();
diff --git a/packages/SystemUI/src/com/android/systemui/media/RingtonePlayer.java b/packages/SystemUI/src/com/android/systemui/media/RingtonePlayer.java
index f39f302..ab612dd 100644
--- a/packages/SystemUI/src/com/android/systemui/media/RingtonePlayer.java
+++ b/packages/SystemUI/src/com/android/systemui/media/RingtonePlayer.java
@@ -16,8 +16,10 @@
 
 package com.android.systemui.media;
 
+import android.content.ContentResolver;
 import android.content.Context;
 import android.content.pm.PackageManager.NameNotFoundException;
+import android.database.Cursor;
 import android.media.AudioAttributes;
 import android.media.IAudioService;
 import android.media.IRingtonePlayer;
@@ -25,15 +27,20 @@
 import android.net.Uri;
 import android.os.Binder;
 import android.os.IBinder;
+import android.os.ParcelFileDescriptor;
 import android.os.Process;
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.UserHandle;
+import android.provider.MediaStore;
+import android.provider.MediaStore.Audio.AudioColumns;
 import android.util.Log;
 
+import com.android.internal.util.Preconditions;
 import com.android.systemui.SystemUI;
 
 import java.io.FileDescriptor;
+import java.io.IOException;
 import java.io.PrintWriter;
 import java.util.HashMap;
 
@@ -180,6 +187,34 @@
             return Ringtone.getTitle(getContextForUser(user), uri,
                     false /*followSettingsUri*/, false /*allowRemote*/);
         }
+
+        @Override
+        public ParcelFileDescriptor openRingtone(Uri uri) {
+            final UserHandle user = Binder.getCallingUserHandle();
+            final ContentResolver resolver = getContextForUser(user).getContentResolver();
+
+            // Only open the requested Uri if it's a well-known ringtone or
+            // other sound from the platform media store, otherwise this opens
+            // up arbitrary access to any file on external storage.
+            if (uri.toString().startsWith(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI.toString())) {
+                try (Cursor c = resolver.query(uri, new String[] {
+                        MediaStore.Audio.AudioColumns.IS_RINGTONE,
+                        MediaStore.Audio.AudioColumns.IS_ALARM,
+                        MediaStore.Audio.AudioColumns.IS_NOTIFICATION
+                }, null, null, null)) {
+                    if (c.moveToFirst()) {
+                        if (c.getInt(0) != 0 || c.getInt(1) != 0 || c.getInt(2) != 0) {
+                            try {
+                                return resolver.openFileDescriptor(uri, "r");
+                            } catch (IOException e) {
+                                throw new SecurityException(e);
+                            }
+                        }
+                    }
+                }
+            }
+            throw new SecurityException("Uri is not ringtone, alarm, or notification: " + uri);
+        }
     };
 
     private Context getContextForUser(UserHandle user) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java b/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java
index 2c5cb89..24b45cc 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java
@@ -77,7 +77,9 @@
 
     @Override
     public int getOffsetTop(TileRecord tile) {
-        return ((ViewGroup) tile.tileView.getParent()).getTop() + getTop();
+        final ViewGroup parent = (ViewGroup) tile.tileView.getParent();
+        if (parent == null) return 0;
+        return parent.getTop() + getTop();
     }
 
     @Override
@@ -165,6 +167,11 @@
         }
     };
 
+    public int getColumnCount() {
+        if (mPages.size() == 0) return 0;
+        return mPages.get(0).mColumns;
+    }
+
     public static class TilePage extends TileLayout {
         private int mMaxRows = 3;
 
diff --git a/packages/SystemUI/src/com/android/systemui/qs/PathInterpolatorBuilder.java b/packages/SystemUI/src/com/android/systemui/qs/PathInterpolatorBuilder.java
new file mode 100644
index 0000000..b8cb92a
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/PathInterpolatorBuilder.java
@@ -0,0 +1,153 @@
+/*
+ * 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;
+
+import android.graphics.Path;
+import android.view.animation.BaseInterpolator;
+import android.view.animation.Interpolator;
+
+public class PathInterpolatorBuilder {
+
+    // This governs how accurate the approximation of the Path is.
+    private static final float PRECISION = 0.002f;
+
+    private float[] mX; // x coordinates in the line
+    private float[] mY; // y coordinates in the line
+    private float[] mDist; // Cumulative percentage length of the line
+
+    public PathInterpolatorBuilder(Path path) {
+        initPath(path);
+    }
+
+    public PathInterpolatorBuilder(float controlX, float controlY) {
+        initQuad(controlX, controlY);
+    }
+
+    public PathInterpolatorBuilder(float controlX1, float controlY1, float controlX2,
+            float controlY2) {
+        initCubic(controlX1, controlY1, controlX2, controlY2);
+    }
+
+    private void initQuad(float controlX, float controlY) {
+        Path path = new Path();
+        path.moveTo(0, 0);
+        path.quadTo(controlX, controlY, 1f, 1f);
+        initPath(path);
+    }
+
+    private void initCubic(float x1, float y1, float x2, float y2) {
+        Path path = new Path();
+        path.moveTo(0, 0);
+        path.cubicTo(x1, y1, x2, y2, 1f, 1f);
+        initPath(path);
+    }
+
+    private void initPath(Path path) {
+        float[] pointComponents = path.approximate(PRECISION);
+
+        int numPoints = pointComponents.length / 3;
+        if (pointComponents[1] != 0 || pointComponents[2] != 0
+                || pointComponents[pointComponents.length - 2] != 1
+                || pointComponents[pointComponents.length - 1] != 1) {
+            throw new IllegalArgumentException("The Path must start at (0,0) and end at (1,1)");
+        }
+
+        mX = new float[numPoints];
+        mY = new float[numPoints];
+        mDist = new float[numPoints];
+        float prevX = 0;
+        float prevFraction = 0;
+        int componentIndex = 0;
+        for (int i = 0; i < numPoints; i++) {
+            float fraction = pointComponents[componentIndex++];
+            float x = pointComponents[componentIndex++];
+            float y = pointComponents[componentIndex++];
+            if (fraction == prevFraction && x != prevX) {
+                throw new IllegalArgumentException(
+                        "The Path cannot have discontinuity in the X axis.");
+            }
+            if (x < prevX) {
+                throw new IllegalArgumentException("The Path cannot loop back on itself.");
+            }
+            mX[i] = x;
+            mY[i] = y;
+            if (i > 0) {
+                float dx = mX[i] - mX[i - 1];
+                float dy = mY[i] - mY[i - 1];
+                float dist = (float) Math.sqrt(dx * dx + dy * dy);
+                mDist[i] = mDist[i - 1] + dist;
+            }
+            prevX = x;
+            prevFraction = fraction;
+        }
+        // Scale down dist to 0-1.
+        float max = mDist[mDist.length - 1];
+        for (int i = 0; i < numPoints; i++) {
+            mDist[i] /= max;
+        }
+    }
+
+    public Interpolator getXInterpolator() {
+        return new PathInterpolator(mDist, mX);
+    }
+
+    public Interpolator getYInterpolator() {
+        return new PathInterpolator(mDist, mY);
+    }
+
+    private static class PathInterpolator extends BaseInterpolator {
+        private final float[] mX; // x coordinates in the line
+        private final float[] mY; // y coordinates in the line
+
+        private PathInterpolator(float[] xs, float[] ys) {
+            mX = xs;
+            mY = ys;
+        }
+
+        @Override
+        public float getInterpolation(float t) {
+            if (t <= 0) {
+                return 0;
+            } else if (t >= 1) {
+                return 1;
+            }
+            // Do a binary search for the correct x to interpolate between.
+            int startIndex = 0;
+            int endIndex = mX.length - 1;
+
+            while (endIndex - startIndex > 1) {
+                int midIndex = (startIndex + endIndex) / 2;
+                if (t < mX[midIndex]) {
+                    endIndex = midIndex;
+                } else {
+                    startIndex = midIndex;
+                }
+            }
+
+            float xRange = mX[endIndex] - mX[startIndex];
+            if (xRange == 0) {
+                return mY[startIndex];
+            }
+
+            float tInRange = t - mX[startIndex];
+            float fraction = tInRange / xRange;
+
+            float startY = mY[startIndex];
+            float endY = mY[endIndex];
+            return startY + (fraction * (endY - startY));
+        }
+    }
+
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java b/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java
index c31bb33..f601f90 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java
@@ -14,10 +14,11 @@
 
 package com.android.systemui.qs;
 
+import android.graphics.Path;
 import android.util.Log;
 import android.view.View;
+import android.view.View.OnAttachStateChangeListener;
 import android.view.View.OnLayoutChangeListener;
-import android.view.animation.PathInterpolator;
 import android.widget.TextView;
 import com.android.systemui.qs.PagedTileLayout.PageListener;
 import com.android.systemui.qs.QSPanel.QSTileLayout;
@@ -25,16 +26,19 @@
 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;
 
 import java.util.ArrayList;
 import java.util.Collection;
 
-public class QSAnimator implements Callback, PageListener, Listener, OnLayoutChangeListener {
+public class QSAnimator implements Callback, PageListener, Listener, OnLayoutChangeListener,
+        OnAttachStateChangeListener, Tunable {
 
     private static final String TAG = "QSAnimator";
 
-    public static final PathInterpolator TRANSLATION_Y_INTERPOLATOR =
-            new PathInterpolator(.1f, .3f, 1, 1);
+    private static final String ALLOW_FANCY_ANIMATION = "sysui_qs_fancy_anim";
+    private static final String MOVE_FULL_ROWS = "sysui_qs_move_whole_rows";
 
     public static final float EXPANDED_TILE_DELAY = .7f;
 
@@ -44,35 +48,78 @@
     private final QSPanel mQsPanel;
     private final QSContainer mQsContainer;
 
+    private PagedTileLayout mPagedLayout;
+
     private boolean mOnFirstPage = true;
     private TouchAnimator mFirstPageAnimator;
     private TouchAnimator mFirstPageDelayedAnimator;
+    private TouchAnimator mTranslationXAnimator;
     private TouchAnimator mTranslationYAnimator;
     private TouchAnimator mNonfirstPageAnimator;
 
+    private boolean mOnKeyguard;
+
+    private boolean mAllowFancy;
+    private boolean mFullRows;
+    private int mNumQuickTiles;
+
     public QSAnimator(QSContainer container, QuickQSPanel quickPanel, QSPanel panel) {
         mQsContainer = container;
         mQuickQsPanel = quickPanel;
         mQsPanel = panel;
-        mQuickQsPanel.addOnLayoutChangeListener(this);
-        mQsPanel.addOnLayoutChangeListener(this);
+        mQsPanel.addOnAttachStateChangeListener(this);
+        container.addOnLayoutChangeListener(this);
         QSTileLayout tileLayout = mQsPanel.getTileLayout();
         if (tileLayout instanceof PagedTileLayout) {
-            ((PagedTileLayout) tileLayout).setPageListener(this);
+            mPagedLayout = ((PagedTileLayout) tileLayout);
+            mPagedLayout.setPageListener(this);
         } else {
             Log.w(TAG, "QS Not using page layout");
         }
     }
 
+    public void setOnKeyguard(boolean onKeyguard) {
+        mOnKeyguard = onKeyguard;
+        if (mOnKeyguard) {
+            clearAnimationState();
+        }
+    }
+
     public void setHost(QSTileHost qsh) {
         qsh.addCallback(this);
     }
 
     @Override
+    public void onViewAttachedToWindow(View v) {
+        TunerService.get(mQsContainer.getContext()).addTunable(this, ALLOW_FANCY_ANIMATION,
+                MOVE_FULL_ROWS, QuickQSPanel.NUM_QUICK_TILES);
+    }
+
+    @Override
+    public void onViewDetachedFromWindow(View v) {
+        TunerService.get(mQsContainer.getContext()).removeTunable(this);
+    }
+
+    @Override
+    public void onTuningChanged(String key, String newValue) {
+        if (ALLOW_FANCY_ANIMATION.equals(key)) {
+            mAllowFancy = newValue == null || Integer.parseInt(newValue) != 0;
+            if (!mAllowFancy) {
+                clearAnimationState();
+            }
+        } else if (MOVE_FULL_ROWS.equals(key)) {
+            mFullRows = newValue == null || Integer.parseInt(newValue) != 0;
+        } else if (QuickQSPanel.NUM_QUICK_TILES.equals(key)) {
+            mNumQuickTiles = QuickQSPanel.getNumQuickTiles(mQsContainer.getContext());
+            clearAnimationState();
+        }
+        updateAnimators();
+    }
+
+    @Override
     public void onPageChanged(boolean isFirst) {
         if (mOnFirstPage == isFirst) return;
         if (!isFirst) {
-            setPosition(1);
             clearAnimationState();
         }
         mOnFirstPage = isFirst;
@@ -80,33 +127,37 @@
 
     private void updateAnimators() {
         TouchAnimator.Builder firstPageBuilder = new Builder();
+        TouchAnimator.Builder translationXBuilder = new Builder();
         TouchAnimator.Builder translationYBuilder = new Builder();
         TouchAnimator.Builder firstPageDelayedBuilder = new Builder();
         Collection<QSTile<?>> tiles = mQsPanel.getHost().getTiles();
         int count = 0;
         int[] loc1 = new int[2];
         int[] loc2 = new int[2];
+        int lastYDiff = 0;
         firstPageDelayedBuilder.setStartDelay(EXPANDED_TILE_DELAY);
         firstPageBuilder.setListener(this);
-        translationYBuilder.setInterpolator(TRANSLATION_Y_INTERPOLATOR);
         // Fade in the tiles/labels as we reach the final position.
         firstPageDelayedBuilder.addFloat(mQsPanel.getTileLayout(), "alpha", 0, 1);
+        clearAnimationState();
         mAllViews.clear();
         mTopFiveQs.clear();
+        mAllViews.add((View) mQsPanel.getTileLayout());
         for (QSTile<?> tile : tiles) {
             QSTileBaseView tileView = mQsPanel.getTileView(tile);
             final TextView label = ((QSTileView) tileView).getLabel();
-            if (count++ < 5) {
+            final View tileIcon = tileView.getIcon();
+            if (count < mNumQuickTiles && mAllowFancy) {
                 // Quick tiles.
                 QSTileBaseView quickTileView = mQuickQsPanel.getTileView(tile);
-                final View tileIcon = tileView.getIcon();
 
                 getRelativePosition(loc1, quickTileView.getIcon(), mQsContainer);
                 getRelativePosition(loc2, tileIcon, mQsContainer);
                 final int xDiff = loc2[0] - loc1[0];
                 final int yDiff = loc2[1] - loc1[1];
+                lastYDiff = yDiff;
                 // Move the quick tile right from its location to the new one.
-                firstPageBuilder.addFloat(quickTileView, "translationX", 0, xDiff);
+                translationXBuilder.addFloat(quickTileView, "translationX", 0, xDiff);
                 translationYBuilder.addFloat(quickTileView, "translationY", 0, yDiff);
 
                 // Counteract the parent translation on the tile. So we have a static base to
@@ -115,25 +166,51 @@
 
                 // Move the real tile's label from the quick tile position to its final
                 // location.
-                firstPageBuilder.addFloat(label, "translationX", -xDiff, 0);
+                translationXBuilder.addFloat(label, "translationX", -xDiff, 0);
                 translationYBuilder.addFloat(label, "translationY", -yDiff, 0);
 
                 mTopFiveQs.add(tileIcon);
                 mAllViews.add(tileIcon);
+                mAllViews.add(label);
                 mAllViews.add(quickTileView);
+            } else if (mFullRows && isIconInAnimatedRow(count)) {
+                firstPageBuilder.addFloat(tileView, "translationY", mQsPanel.getHeight(), 0);
+                translationYBuilder.addFloat(label, "translationY", -lastYDiff, 0);
+                translationYBuilder.addFloat(tileIcon, "translationY", -lastYDiff, 0);
+                mAllViews.add(tileIcon);
+                mAllViews.add(label);
             }
             mAllViews.add(tileView);
             mAllViews.add(label);
+            count++;
         }
-        mFirstPageAnimator = firstPageBuilder.build();
-        mFirstPageDelayedAnimator = firstPageDelayedBuilder.build();
-        mTranslationYAnimator = translationYBuilder.build();
+        if (mAllowFancy) {
+            mFirstPageAnimator = firstPageBuilder.build();
+            mFirstPageDelayedAnimator = firstPageDelayedBuilder.build();
+            Path path = new Path();
+            path.moveTo(0, 0);
+            path.cubicTo(0, 0, 0, 1, 1, 1);
+            PathInterpolatorBuilder interpolatorBuilder = new PathInterpolatorBuilder(0, 0, 0, 1);
+            translationXBuilder.setInterpolator(interpolatorBuilder.getXInterpolator());
+            translationYBuilder.setInterpolator(interpolatorBuilder.getYInterpolator());
+            mTranslationXAnimator = translationXBuilder.build();
+            mTranslationYAnimator = translationYBuilder.build();
+        }
         mNonfirstPageAnimator = new TouchAnimator.Builder()
                 .addFloat(mQuickQsPanel, "alpha", 1, 0)
+                .setListener(mNonFirstPageListener)
                 .setEndDelay(.5f)
                 .build();
     }
 
+    private boolean isIconInAnimatedRow(int count) {
+        if (mPagedLayout == null) {
+            return false;
+        }
+        final int columnCount = mPagedLayout.getColumnCount();
+        return count < ((mNumQuickTiles + columnCount - 1) / columnCount) * columnCount;
+    }
+
     private void getRelativePosition(int[] loc1, View view, View parent) {
         loc1[0] = 0 + view.getWidth() / 2;
         loc1[1] = 0;
@@ -149,10 +226,14 @@
 
     public void setPosition(float position) {
         if (mFirstPageAnimator == null) return;
-        if (mOnFirstPage) {
+        if (mOnKeyguard) {
+            return;
+        }
+        if (mOnFirstPage && mAllowFancy) {
             mQuickQsPanel.setAlpha(1);
             mFirstPageAnimator.setPosition(position);
             mFirstPageDelayedAnimator.setPosition(position);
+            mTranslationXAnimator.setPosition(position);
             mTranslationYAnimator.setPosition(position);
         } else {
             mNonfirstPageAnimator.setPosition(position);
@@ -161,6 +242,7 @@
 
     @Override
     public void onAnimationAtStart() {
+        mQuickQsPanel.setVisibility(View.VISIBLE);
     }
 
     @Override
@@ -186,12 +268,17 @@
     private void clearAnimationState() {
         final int N = mAllViews.size();
         mQuickQsPanel.setAlpha(0);
+        mQuickQsPanel.setVisibility(View.INVISIBLE);
         for (int i = 0; i < N; i++) {
             View v = mAllViews.get(i);
             v.setAlpha(1);
             v.setTranslationX(1);
             v.setTranslationY(1);
         }
+        final int N2 = mTopFiveQs.size();
+        for (int i = 0; i < N2; i++) {
+            mTopFiveQs.get(i).setVisibility(View.VISIBLE);
+        }
     }
 
     @Override
@@ -207,6 +294,14 @@
         mQsPanel.post(mUpdateAnimators);
     }
 
+    private final TouchAnimator.Listener mNonFirstPageListener =
+            new TouchAnimator.ListenerAdapter() {
+                @Override
+                public void onAnimationStarted() {
+                    mQuickQsPanel.setVisibility(View.VISIBLE);
+                }
+            };
+
     private Runnable mUpdateAnimators = new Runnable() {
         @Override
         public void run() {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSContainer.java b/packages/SystemUI/src/com/android/systemui/qs/QSContainer.java
index c59da8d..5b05e84 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSContainer.java
@@ -19,6 +19,7 @@
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
 import android.content.Context;
+import android.graphics.Point;
 import android.util.AttributeSet;
 import android.util.Log;
 import android.view.View;
@@ -26,7 +27,9 @@
 import android.widget.FrameLayout;
 import com.android.systemui.Interpolators;
 import com.android.systemui.R;
+import com.android.systemui.qs.customize.QSCustomizer;
 import com.android.systemui.statusbar.phone.BaseStatusBarHeader;
+import com.android.systemui.statusbar.phone.NotificationPanelView;
 import com.android.systemui.statusbar.phone.QSTileHost;
 import com.android.systemui.statusbar.stack.StackStateAnimator;
 
@@ -39,6 +42,8 @@
     private static final String TAG = "QSContainer";
     private static final boolean DEBUG = false;
 
+    private final Point mSizePoint = new Point();
+
     private int mHeightOverride = -1;
     private QSPanel mQSPanel;
     private QSDetail mQSDetail;
@@ -51,6 +56,8 @@
 
     private long mDelay;
     private QSAnimator mQSAnimator;
+    private QSCustomizer mQSCustomizer;
+    private NotificationPanelView mPanelView;
 
     public QSContainer(Context context, AttributeSet attrs) {
         super(context, attrs);
@@ -65,21 +72,33 @@
         mHeader = (BaseStatusBarHeader) findViewById(R.id.header);
         mQSAnimator = new QSAnimator(this, (QuickQSPanel) mHeader.findViewById(R.id.quick_qs_panel),
                 mQSPanel);
+        mQSCustomizer = (QSCustomizer) findViewById(R.id.qs_customize);
+        mQSCustomizer.setQsContainer(this);
     }
 
     public void setHost(QSTileHost qsh) {
-        mQSPanel.setHost(qsh);
+        mQSPanel.setHost(qsh, mQSCustomizer);
         mHeader.setQSPanel(mQSPanel);
         mQSDetail.setHost(qsh);
         mQSAnimator.setHost(qsh);
     }
 
+    public void setPanelView(NotificationPanelView panelView) {
+        mPanelView = panelView;
+    }
+
     @Override
     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
         // Since we control our own bottom, be whatever size we want.
         // Otherwise the QSPanel ends up with 0 height when the window is only the
         // size of the status bar.
         super.onMeasure(widthMeasureSpec, MeasureSpec.UNSPECIFIED);
+
+        // QSCustomizer is always be the height of the screen, but do this after
+        // other measuring to avoid changing the height of the QSContainer.
+        getDisplay().getRealSize(mSizePoint);
+        mQSCustomizer.measure(widthMeasureSpec,
+                MeasureSpec.makeMeasureSpec(mSizePoint.y, MeasureSpec.EXACTLY));
     }
 
     @Override
@@ -88,6 +107,10 @@
         updateBottom();
     }
 
+    public boolean isCustomizing() {
+        return mQSCustomizer.isCustomizing();
+    }
+
     /**
      * Overrides the height of this view (post-layout), so that the content is clipped to that
      * height and the background is set to that height.
@@ -104,6 +127,9 @@
      * during closing the detail panel, this already returns the smaller height.
      */
     public int getDesiredHeight() {
+        if (isCustomizing()) {
+            return getHeight();
+        }
         if (mQSDetail.isClosingDetail()) {
             return mQSPanel.getGridHeight() + mHeader.getCollapsedHeight() + getPaddingBottom();
         } else {
@@ -111,9 +137,18 @@
         }
     }
 
+    public void notifyCustomizeChanged() {
+        // The customize state changed, so our height changed.
+        updateBottom();
+        // Let the panel know the position changed and it needs to update where notifications
+        // and whatnot are.
+        mPanelView.onQsHeightChanged();
+    }
+
     private void updateBottom() {
         int heightOverride = mHeightOverride != -1 ? mHeightOverride : getMeasuredHeight();
-        int height = (int) (mQsExpansion * (heightOverride - mHeader.getCollapsedHeight()))
+        int height = mQSCustomizer.isCustomizing() ? mQSCustomizer.getHeight()
+                : (int) (mQsExpansion * (heightOverride - mHeader.getCollapsedHeight()))
                 + mHeader.getCollapsedHeight();
         setBottom(getTop() + height);
         mQSDetail.setBottom(getTop() + height);
@@ -138,6 +173,10 @@
         return mQSPanel;
     }
 
+    public QSCustomizer getCustomizer() {
+        return mQSCustomizer;
+    }
+
     public boolean isShowingDetail() {
         return mQSPanel.isShowingCustomize() || mQSDetail.isShowingDetail();
     }
@@ -156,6 +195,7 @@
     public void setKeyguardShowing(boolean keyguardShowing) {
         if (DEBUG) Log.d(TAG, "setKeyguardShowing " + keyguardShowing);
         mKeyguardShowing = keyguardShowing;
+        mQSAnimator.setOnKeyguard(keyguardShowing);
         updateQsState();
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSIconView.java b/packages/SystemUI/src/com/android/systemui/qs/QSIconView.java
index 267ed16..546f8c3 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSIconView.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSIconView.java
@@ -23,7 +23,6 @@
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.ImageView;
-
 import android.widget.ImageView.ScaleType;
 import com.android.systemui.R;
 
@@ -34,6 +33,7 @@
     private final View mIcon;
     private final int mIconSizePx;
     private final int mTilePaddingBelowIconPx;
+    private boolean mAnimationEnabled = true;
 
     public QSIconView(Context context) {
         super(context);
@@ -46,6 +46,10 @@
         addView(mIcon);
     }
 
+    public void disableAnimation() {
+        mAnimationEnabled = false;
+    }
+
     @Override
     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
         final int w = MeasureSpec.getSize(widthMeasureSpec);
@@ -69,7 +73,9 @@
 
     protected void setIcon(ImageView iv, QSTile.State state) {
         if (!Objects.equals(state.icon, iv.getTag(R.id.qs_icon_tag))) {
-            Drawable d = state.icon != null ? state.icon.getDrawable(mContext) : null;
+            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() : null;
             if (d != null && state.autoMirrorDrawable) {
                 d.setAutoMirrored(true);
@@ -77,7 +83,7 @@
             iv.setImageDrawable(d);
             iv.setTag(R.id.qs_icon_tag, state.icon);
             iv.setPadding(0, padding, 0, padding);
-            if (d instanceof Animatable) {
+            if (d instanceof Animatable && iv.isShown()) {
                 Animatable a = (Animatable) d;
                 a.start();
                 if (!iv.isShown()) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
index 30a9850..899b0ef 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
@@ -31,6 +31,7 @@
 import com.android.internal.logging.MetricsProto.MetricsEvent;
 import com.android.systemui.R;
 import com.android.systemui.qs.QSTile.DetailAdapter;
+import com.android.systemui.qs.QSTile.Host.Callback;
 import com.android.systemui.qs.customize.QSCustomizer;
 import com.android.systemui.qs.external.CustomTile;
 import com.android.systemui.settings.BrightnessController;
@@ -44,7 +45,7 @@
 import java.util.Collection;
 
 /** View that represents the quick settings tile panel. **/
-public class QSPanel extends LinearLayout implements Tunable {
+public class QSPanel extends LinearLayout implements Tunable, Callback {
 
     public static final String QS_SHOW_BRIGHTNESS = "qs_show_brightness";
 
@@ -123,10 +124,16 @@
     @Override
     protected void onDetachedFromWindow() {
         TunerService.get(mContext).removeTunable(this);
+        mHost.removeCallback(this);
         super.onDetachedFromWindow();
     }
 
     @Override
+    public void onTilesChanged() {
+        setTiles(mHost.getTiles());
+    }
+
+    @Override
     public void onTuningChanged(String key, String newValue) {
         if (QS_SHOW_BRIGHTNESS.equals(key)) {
             mBrightnessView.setVisibility(newValue == null || Integer.parseInt(newValue) != 0
@@ -148,12 +155,6 @@
         return mHost.createTile(subPanel);
     }
 
-    protected void createCustomizePanel() {
-        mCustomizePanel = (QSCustomizer) LayoutInflater.from(mContext)
-                .inflate(R.layout.qs_customize_panel, null);
-        mCustomizePanel.setHost(mHost);
-    }
-
     public void setBrightnessMirror(BrightnessMirrorController c) {
         super.onFinishInflate();
         ToggleSlider brightnessSlider = (ToggleSlider) findViewById(R.id.brightness_slider);
@@ -166,10 +167,15 @@
         mCallback = callback;
     }
 
-    public void setHost(QSTileHost host) {
+    public void setHost(QSTileHost host, QSCustomizer customizer) {
         mHost = host;
+        mHost.addCallback(this);
+        setTiles(mHost.getTiles());
         mFooter.setHost(host);
-        createCustomizePanel();
+        mCustomizePanel = customizer;
+        if (mCustomizePanel != null) {
+            mCustomizePanel.setHost(mHost);
+        }
     }
 
     public QSTileHost getHost() {
@@ -272,7 +278,7 @@
         }
     }
 
-    private void drawTile(TileRecord r, QSTile.State state) {
+    protected void drawTile(TileRecord r, QSTile.State state) {
         r.tileView.onStateChanged(state);
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSTile.java b/packages/SystemUI/src/com/android/systemui/qs/QSTile.java
index df622b8..42e98aa 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSTile.java
@@ -390,6 +390,7 @@
         Context getContext();
         Collection<QSTile<?>> getTiles();
         void addCallback(Callback callback);
+        void removeCallback(Callback callback);
         BluetoothController getBluetoothController();
         LocationController getLocationController();
         RotationLockController getRotationLockController();
@@ -416,6 +417,10 @@
     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();
@@ -437,6 +442,11 @@
         public Drawable getDrawable(Context context) {
             return mDrawable;
         }
+
+        @Override
+        public Drawable getInvisibleDrawable(Context context) {
+            return mDrawable;
+        }
     }
 
     public static class ResourceIcon extends Icon {
@@ -463,6 +473,11 @@
         }
 
         @Override
+        public Drawable getInvisibleDrawable(Context context) {
+            return context.getDrawable(mResId);
+        }
+
+        @Override
         public boolean equals(Object o) {
             return o instanceof ResourceIcon && ((ResourceIcon) o).mResId == mResId;
         }
@@ -474,14 +489,17 @@
     }
 
     protected class AnimationIcon extends ResourceIcon {
-        public AnimationIcon(int resId) {
-            super(resId);
+        private final int mAnimatedResId;
+
+        public AnimationIcon(int resId, int staticResId) {
+            super(staticResId);
+            mAnimatedResId = resId;
         }
 
         @Override
         public Drawable getDrawable(Context context) {
             // workaround: get a clean state for every new AVD
-            return context.getDrawable(mResId).getConstantState().newDrawable();
+            return context.getDrawable(mAnimatedResId).getConstantState().newDrawable();
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSTileBaseView.java b/packages/SystemUI/src/com/android/systemui/qs/QSTileBaseView.java
index f35aacf..9e40cfd 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSTileBaseView.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSTileBaseView.java
@@ -48,7 +48,7 @@
 
         // Default to Quick Tile padding, and QSTileView will specify its own padding.
         int padding = context.getResources().getDimensionPixelSize(R.dimen.qs_quick_tile_padding);
-        setPadding(padding, padding, padding, padding);
+        setPadding(0, padding, 0, padding);
         setClipChildren(false);
         setClipToPadding(false);
     }
@@ -113,7 +113,7 @@
         setContentDescription(state.contentDescription);
     }
 
-    View getIcon() {
+    public QSIconView getIcon() {
         return mIcon;
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java
index 4408dbf..d0e034b 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java
@@ -24,6 +24,10 @@
 import android.widget.LinearLayout;
 import android.widget.Space;
 import com.android.systemui.R;
+import com.android.systemui.qs.QSTile.SignalState;
+import com.android.systemui.qs.QSTile.State;
+import com.android.systemui.tuner.TunerService;
+import com.android.systemui.tuner.TunerService.Tunable;
 
 import java.util.ArrayList;
 import java.util.Collection;
@@ -33,6 +37,8 @@
  */
 public class QuickQSPanel extends QSPanel {
 
+    public static final String NUM_QUICK_TILES = "sysui_qqs_count";
+
     private int mMaxTiles;
     private QSPanel mFullPanel;
     private View mHeader;
@@ -50,8 +56,15 @@
     }
 
     @Override
-    protected void createCustomizePanel() {
-        // No customizing from the header.
+    protected void onAttachedToWindow() {
+        super.onAttachedToWindow();
+        TunerService.get(mContext).addTunable(mNumTiles, NUM_QUICK_TILES);
+    }
+
+    @Override
+    protected void onDetachedFromWindow() {
+        super.onDetachedFromWindow();
+        TunerService.get(mContext).removeTunable(mNumTiles);
     }
 
     public void setQSPanelAndHeader(QSPanel fullPanel, View header) {
@@ -60,6 +73,19 @@
     }
 
     @Override
+    protected void drawTile(TileRecord r, State state) {
+        if (state instanceof SignalState) {
+            State copy = r.tile.newTileState();
+            state.copyTo(copy);
+            // No activity shown in the quick panel.
+            ((SignalState) copy).activityIn = false;
+            ((SignalState) copy).activityOut = false;
+            state = copy;
+        }
+        super.drawTile(r, state);
+    }
+
+    @Override
     protected void showDetail(boolean show, Record r) {
         // Do nothing, will be handled by the QSPanel.
     }
@@ -71,6 +97,7 @@
 
     public void setMaxTiles(int maxTiles) {
         mMaxTiles = maxTiles;
+        setTiles(mHost.getTiles());
     }
 
     @Override
@@ -99,6 +126,17 @@
         super.setTiles(quickTiles);
     }
 
+    private final Tunable mNumTiles = new Tunable() {
+        @Override
+        public void onTuningChanged(String key, String newValue) {
+            setMaxTiles(getNumQuickTiles(mContext));
+        }
+    };
+
+    public static int getNumQuickTiles(Context context) {
+        return TunerService.get(context).getValue(NUM_QUICK_TILES, 5);
+    }
+
     private static class HeaderTileLayout extends LinearLayout implements QSTileLayout {
 
         private final Space mEndSpacer;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/TouchAnimator.java b/packages/SystemUI/src/com/android/systemui/qs/TouchAnimator.java
index 026dd0e..37f2528 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/TouchAnimator.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/TouchAnimator.java
@@ -14,6 +14,7 @@
 
 package com.android.systemui.qs;
 
+import android.util.FloatProperty;
 import android.util.MathUtils;
 import android.util.Property;
 import android.view.View;
@@ -38,7 +39,7 @@
     private final float mSpan;
     private final Interpolator mInterpolator;
     private final Listener mListener;
-    private float mLastT;
+    private float mLastT = -1;
 
     private TouchAnimator(Object[] targets, KeyframeSet[] keyframeSets,
             float startDelay, float endDelay, Interpolator interpolator, Listener listener) {
@@ -56,15 +57,16 @@
         if (mInterpolator != null) {
             t = mInterpolator.getInterpolation(t);
         }
+        if (t == mLastT) {
+            return;
+        }
         if (mListener != null) {
-            if (mLastT == 0 || mLastT == 1) {
-                if (t != mLastT) {
-                    mListener.onAnimationStarted();
-                }
-            } else if (t == 1) {
+            if (t == 1) {
                 mListener.onAnimationAtEnd();
             } else if (t == 0) {
                 mListener.onAnimationAtStart();
+            } else if (mLastT <= 0 || mLastT == 1) {
+                mListener.onAnimationStarted();
             }
             mLastT = t;
         }
@@ -73,6 +75,19 @@
         }
     }
 
+    private static final FloatProperty<TouchAnimator> POSITION =
+            new FloatProperty<TouchAnimator>("position") {
+        @Override
+        public void setValue(TouchAnimator touchAnimator, float value) {
+            touchAnimator.setPosition(value);
+        }
+
+        @Override
+        public Float get(TouchAnimator touchAnimator) {
+            return touchAnimator.mLastT;
+        }
+    };
+
     public static class ListenerAdapter implements Listener {
         @Override
         public void onAnimationAtStart() { }
@@ -114,12 +129,12 @@
         private Listener mListener;
 
         public Builder addFloat(Object target, String property, float... values) {
-            add(target, KeyframeSet.ofFloat(getProperty(target, property), values));
+            add(target, KeyframeSet.ofFloat(getProperty(target, property, float.class), values));
             return this;
         }
 
         public Builder addInt(Object target, String property, int... values) {
-            add(target, KeyframeSet.ofInt(getProperty(target, property), values));
+            add(target, KeyframeSet.ofInt(getProperty(target, property, int.class), values));
             return this;
         }
 
@@ -128,7 +143,7 @@
             mValues.add(keyframeSet);
         }
 
-        private static Property getProperty(Object target, String property) {
+        private static Property getProperty(Object target, String property, Class<?> cls) {
             if (target instanceof View) {
                 switch (property) {
                     case "translationX":
@@ -151,7 +166,10 @@
                         return View.SCALE_Y;
                 }
             }
-            return Property.of(target.getClass(), float.class, property);
+            if (target instanceof TouchAnimator && "position".equals(property)) {
+                return POSITION;
+            }
+            return Property.of(target.getClass(), cls, property);
         }
 
         public Builder setStartDelay(float startDelay) {
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 67fe8e5e..72a59d7 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java
@@ -25,6 +25,7 @@
 import android.util.AttributeSet;
 import android.util.TypedValue;
 import android.view.ContextThemeWrapper;
+import android.view.LayoutInflater;
 import android.view.Menu;
 import android.view.MenuItem;
 import android.view.View;
@@ -32,8 +33,10 @@
 import android.widget.Toolbar;
 import android.widget.Toolbar.OnMenuItemClickListener;
 import com.android.systemui.R;
+import com.android.systemui.qs.QSContainer;
 import com.android.systemui.qs.QSDetailClipper;
 import com.android.systemui.qs.QSTile;
+import com.android.systemui.statusbar.phone.NotificationsQuickSettingsContainer;
 import com.android.systemui.statusbar.phone.PhoneStatusBar;
 import com.android.systemui.statusbar.phone.QSTileHost;
 
@@ -59,35 +62,31 @@
     private RecyclerView mRecyclerView;
     private TileAdapter mTileAdapter;
     private Toolbar mToolbar;
+    private boolean mCustomizing;
+    private NotificationsQuickSettingsContainer mNotifQsContainer;
+    private QSContainer mQsContainer;
 
     public QSCustomizer(Context context, AttributeSet attrs) {
-        super(new ContextThemeWrapper(context, android.R.style.Theme_Material), attrs);
+        super(new ContextThemeWrapper(context, R.style.edit_theme), attrs);
         mClipper = new QSDetailClipper(this);
-    }
 
-    public void setHost(QSTileHost host) {
-        mHost = host;
-        mPhoneStatusBar = host.getPhoneStatusBar();
-    }
+        LayoutInflater.from(getContext()).inflate(R.layout.qs_customize_panel_content, this);
 
-    @Override
-    protected void onFinishInflate() {
-        super.onFinishInflate();
         mToolbar = (Toolbar) findViewById(com.android.internal.R.id.action_bar);
         TypedValue value = new TypedValue();
         mContext.getTheme().resolveAttribute(android.R.attr.homeAsUpIndicator, value, true);
         mToolbar.setNavigationIcon(
-                getResources().getDrawable(R.drawable.ic_close_white, mContext.getTheme()));
+                getResources().getDrawable(value.resourceId, mContext.getTheme()));
         mToolbar.setNavigationOnClickListener(new OnClickListener() {
             @Override
             public void onClick(View v) {
-                save();
                 hide((int) v.getX() + v.getWidth() / 2, (int) v.getY() + v.getHeight() / 2);
             }
         });
         mToolbar.setOnMenuItemClickListener(this);
         mToolbar.getMenu().add(Menu.NONE, MENU_RESET, 0,
                 mContext.getString(com.android.internal.R.string.reset));
+        mToolbar.setTitle(R.string.qs_edit);
 
         mRecyclerView = (RecyclerView) findViewById(android.R.id.list);
         mTileAdapter = new TileAdapter(getContext());
@@ -102,25 +101,47 @@
         mRecyclerView.setItemAnimator(animator);
     }
 
+    public void setHost(QSTileHost host) {
+        mHost = host;
+        mPhoneStatusBar = host.getPhoneStatusBar();
+    }
+
+    public void setContainer(NotificationsQuickSettingsContainer notificationsQsContainer) {
+        mNotifQsContainer = notificationsQsContainer;
+    }
+
+    public void setQsContainer(QSContainer qsContainer) {
+        mQsContainer = qsContainer;
+    }
+
     public void show(int x, int y) {
         if (!isShown) {
             isShown = true;
-            mPhoneStatusBar.getStatusBarWindow().addView(this);
             setTileSpecs();
-            mClipper.animateCircularClip(x, y, true, null);
+            setVisibility(View.VISIBLE);
+            mClipper.animateCircularClip(x, y, true, mExpandAnimationListener);
             new TileQueryHelper(mContext, mHost).setListener(mTileAdapter);
+            mNotifQsContainer.setCustomizerAnimating(true);
         }
     }
 
     public void hide(int x, int y) {
         if (isShown) {
             isShown = false;
+            setCustomizing(false);
+            save();
             mClipper.animateCircularClip(x, y, false, mCollapseAnimationListener);
+            mNotifQsContainer.setCustomizerAnimating(true);
         }
     }
 
+    private void setCustomizing(boolean customizing) {
+        mCustomizing = customizing;
+        mQsContainer.notifyCustomizeChanged();
+    }
+
     public boolean isCustomizing() {
-        return isShown;
+        return mCustomizing;
     }
 
     @Override
@@ -154,19 +175,34 @@
         mTileAdapter.saveSpecs(mHost);
     }
 
+    private final AnimatorListener mExpandAnimationListener = new AnimatorListenerAdapter() {
+        @Override
+        public void onAnimationEnd(Animator animation) {
+            setCustomizing(true);
+            mNotifQsContainer.setCustomizerAnimating(false);
+        }
+
+        @Override
+        public void onAnimationCancel(Animator animation) {
+            mNotifQsContainer.setCustomizerAnimating(false);
+        }
+    };
+
     private final AnimatorListener mCollapseAnimationListener = new AnimatorListenerAdapter() {
         @Override
         public void onAnimationEnd(Animator animation) {
             if (!isShown) {
-                mPhoneStatusBar.getStatusBarWindow().removeView(QSCustomizer.this);
+                setVisibility(View.GONE);
             }
+            mNotifQsContainer.setCustomizerAnimating(false);
         }
 
         @Override
         public void onAnimationCancel(Animator animation) {
             if (!isShown) {
-                mPhoneStatusBar.getStatusBarWindow().removeView(QSCustomizer.this);
+                setVisibility(View.GONE);
             }
+            mNotifQsContainer.setCustomizerAnimating(false);
         }
     };
 }
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 876f417..d9b3b3f 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java
@@ -25,9 +25,7 @@
 import android.support.v7.widget.RecyclerView.ViewHolder;
 import android.support.v7.widget.helper.ItemTouchHelper;
 import android.view.LayoutInflater;
-import android.view.MotionEvent;
 import android.view.View;
-import android.view.View.OnTouchListener;
 import android.view.ViewGroup;
 import android.widget.FrameLayout;
 import com.android.systemui.R;
@@ -107,7 +105,10 @@
         mOtherTiles = new ArrayList<TileInfo>(mAllTiles);
         mTiles.clear();
         for (int i = 0; i < mCurrentSpecs.size(); i++) {
-            mTiles.add(getAndRemoveOther(mCurrentSpecs.get(i)));
+            final TileInfo tile = getAndRemoveOther(mCurrentSpecs.get(i));
+            if (tile != null) {
+                mTiles.add(tile);
+            }
         }
         mTiles.add(null);
         mTiles.addAll(mOtherTiles);
@@ -156,13 +157,6 @@
 
         TileInfo info = mTiles.get(position);
         holder.mTileView.onStateChanged(info.state);
-        holder.mTileView.setOnTouchListener(new OnTouchListener() {
-            @Override
-            public boolean onTouch(View v, MotionEvent event) {
-                mItemTouchHelper.startDrag(holder);
-                return true;
-            }
-        });
     }
 
     public SpanSizeLookup getSizeLookup() {
@@ -176,6 +170,8 @@
             super(itemView);
             if (itemView instanceof FrameLayout) {
                 mTileView = (QSTileView) ((FrameLayout) itemView).getChildAt(0);
+                mTileView.setBackground(null);
+                mTileView.getIcon().disableAnimation();
             }
         }
 
@@ -280,9 +276,6 @@
                     return false;
                 }
             }
-            if (target.getItemViewType() == TYPE_EDIT && from < mDividerIndex) {
-                to++;
-            }
             move(from, to, mTiles);
             mDividerIndex = mTiles.indexOf(null);
             notifyItemMoved(from, to);
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 c3610d9..d95d3ef 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java
@@ -33,6 +33,7 @@
 import com.android.systemui.qs.QSTile.DrawableIcon;
 import com.android.systemui.qs.external.CustomTile;
 import com.android.systemui.statusbar.phone.QSTileHost;
+import com.android.systemui.tuner.TunerService;
 
 import java.util.ArrayList;
 import java.util.Collection;
@@ -54,9 +55,8 @@
     }
 
     private void addSystemTiles(QSTileHost host) {
-        boolean hasColorMod = host.getNightModeController().isEnabled();
         String possible = mContext.getString(R.string.quick_settings_tiles_default)
-                + ",hotspot,inversion,saver,work,cast" + (hasColorMod ? ",night" : "");
+                + ",hotspot,inversion,saver,work,cast,night";
         String[] possibleTiles = possible.split(",");
         final Handler qsHandler = new Handler(host.getLooper());
         final Handler mainHandler = new Handler(Looper.getMainLooper());
@@ -88,7 +88,12 @@
         qsHandler.post(new Runnable() {
             @Override
             public void run() {
-                new QueryTilesTask().execute();
+                mainHandler.post(new Runnable() {
+                    @Override
+                    public void run() {
+                        new QueryTilesTask().execute();
+                    }
+                });
             }
         });
     }
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 0709992..db686a8 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java
@@ -58,6 +58,7 @@
     private final IBinder mToken = new Binder();
     private final IQSTileService mService;
     private final TileServiceManager mServiceManager;
+    private final int mUser;
 
     private boolean mListening;
     private boolean mBound;
@@ -71,6 +72,7 @@
         mServiceManager = host.getTileServices().getTileWrapper(this);
         mService = mServiceManager.getTileService();
         mTile = new Tile(mComponent);
+        mUser = ActivityManager.getCurrentUser();
         try {
             PackageManager pm = mContext.getPackageManager();
             ServiceInfo info = pm.getServiceInfo(mComponent, 0);
@@ -86,6 +88,10 @@
         }
     }
 
+    public int getUser() {
+        return mUser;
+    }
+
     public ComponentName getComponent() {
         return mComponent;
     }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/external/TileLifecycleManager.java b/packages/SystemUI/src/com/android/systemui/qs/external/TileLifecycleManager.java
index c4436f4..2aad161 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/external/TileLifecycleManager.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/external/TileLifecycleManager.java
@@ -85,6 +85,7 @@
         mHandler = handler;
         mIntent = intent;
         mUser = user;
+        if (DEBUG) Log.d(TAG, "Creating " + mIntent + " " + mUser);
     }
 
     public ComponentName getComponent() {
@@ -116,13 +117,13 @@
             if (!checkComponentState()) {
                 return;
             }
-            if (DEBUG) Log.d(TAG, "Binding service " + mIntent);
+            if (DEBUG) Log.d(TAG, "Binding service " + mIntent + " " + mUser);
             mBindTryCount++;
             mContext.bindServiceAsUser(mIntent, this,
                     Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE_WHILE_AWAKE,
                     mUser);
         } else {
-            if (DEBUG) Log.d(TAG, "Unbinding service " + mIntent);
+            if (DEBUG) Log.d(TAG, "Unbinding service " + mIntent + " " + mUser);
             // Give it another chance next time it needs to be bound, out of kindness.
             mBindTryCount = 0;
             mWrapper = null;
@@ -350,7 +351,7 @@
 
     @Override
     public void onClick(IBinder iBinder) {
-        if (DEBUG) Log.d(TAG, "onClick " + iBinder);
+        if (DEBUG) Log.d(TAG, "onClick " + iBinder + " " + mUser);
         if (mWrapper == null || !mWrapper.onClick(iBinder)) {
             mClickBinder = iBinder;
             queueMessage(MSG_ON_CLICK);
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 f0860fe..89f1985b 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/AirplaneModeTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/AirplaneModeTile.java
@@ -33,9 +33,11 @@
 /** Quick settings tile: Airplane mode **/
 public class AirplaneModeTile extends QSTile<QSTile.BooleanState> {
     private final AnimationIcon mEnable =
-            new AnimationIcon(R.drawable.ic_signal_airplane_enable_animation);
+            new AnimationIcon(R.drawable.ic_signal_airplane_enable_animation,
+                    R.drawable.ic_signal_airplane_disable);
     private final AnimationIcon mDisable =
-            new AnimationIcon(R.drawable.ic_signal_airplane_disable_animation);
+            new AnimationIcon(R.drawable.ic_signal_airplane_disable_animation,
+                    R.drawable.ic_signal_airplane_enable);
     private final GlobalSetting mSetting;
 
     private boolean mListening;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/BatteryTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/BatteryTile.java
index 39d1447..2e87525 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/BatteryTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/BatteryTile.java
@@ -172,6 +172,7 @@
         }
 
         private void postBindView() {
+            if (mCurrentView == null) return;
             mCurrentView.post(new Runnable() {
                 @Override
                 public void run() {
@@ -181,6 +182,9 @@
         }
 
         private void bindView() {
+            if (mCurrentView == null) {
+                return;
+            }
             mDrawable.onBatteryLevelChanged(100, false, false);
             mDrawable.onPowerSaveChanged(true);
             mDrawable.disableShowPercent();
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 42ce69c..a608316 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java
@@ -30,9 +30,11 @@
 public class ColorInversionTile extends QSTile<QSTile.BooleanState> {
 
     private final AnimationIcon mEnable
-            = new AnimationIcon(R.drawable.ic_invert_colors_enable_animation);
+            = new AnimationIcon(R.drawable.ic_invert_colors_enable_animation,
+            R.drawable.ic_invert_colors_disable);
     private final AnimationIcon mDisable
-            = new AnimationIcon(R.drawable.ic_invert_colors_disable_animation);
+            = new AnimationIcon(R.drawable.ic_invert_colors_disable_animation,
+            R.drawable.ic_invert_colors_enable);
     private final SecureSetting mSetting;
 
     private boolean mListening;
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 fa235d3..74b3fdc 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/DataSaverTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/DataSaverTile.java
@@ -73,6 +73,15 @@
     }
 
     @Override
+    protected String composeChangeAnnouncement() {
+        if (mState.value) {
+            return mContext.getString(R.string.accessibility_quick_settings_data_saver_changed_on);
+        } else {
+            return mContext.getString(R.string.accessibility_quick_settings_data_saver_changed_off);
+        }
+    }
+
+    @Override
     public void onDataSaverChanged(boolean isDataSaving) {
         refreshState(isDataSaving);
     }
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 8982b3e..8b22868 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java
@@ -56,9 +56,11 @@
             ResourceIcon.get(R.drawable.ic_qs_dnd_on_total_silence);
 
     private final AnimationIcon mDisable =
-            new AnimationIcon(R.drawable.ic_dnd_disable_animation);
+            new AnimationIcon(R.drawable.ic_dnd_disable_animation,
+                    R.drawable.ic_qs_dnd_off);
     private final AnimationIcon mDisableTotalSilence =
-            new AnimationIcon(R.drawable.ic_dnd_total_silence_disable_animation);
+            new AnimationIcon(R.drawable.ic_dnd_total_silence_disable_animation,
+                    R.drawable.ic_qs_dnd_off);
 
     private final ZenModeController mController;
     private final DndDetailAdapter mDetailAdapter;
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 c10843a..a01a9a5 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java
@@ -17,9 +17,11 @@
 package com.android.systemui.qs.tiles;
 
 import android.app.ActivityManager;
-
 import android.content.Intent;
+import android.graphics.drawable.Drawable;
 import android.provider.MediaStore;
+import android.text.SpannableStringBuilder;
+import android.text.style.ForegroundColorSpan;
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.MetricsProto.MetricsEvent;
 import com.android.systemui.R;
@@ -31,9 +33,11 @@
         FlashlightController.FlashlightListener {
 
     private final AnimationIcon mEnable
-            = new AnimationIcon(R.drawable.ic_signal_flashlight_enable_animation);
+            = new AnimationIcon(R.drawable.ic_signal_flashlight_enable_animation,
+            R.drawable.ic_signal_flashlight_disable);
     private final AnimationIcon mDisable
-            = new AnimationIcon(R.drawable.ic_signal_flashlight_disable_animation);
+            = new AnimationIcon(R.drawable.ic_signal_flashlight_disable_animation,
+            R.drawable.ic_signal_flashlight_enable);
     private final FlashlightController mFlashlightController;
 
     public FlashlightTile(Host host) {
@@ -67,6 +71,11 @@
     }
 
     @Override
+    public boolean isAvailable() {
+        return mFlashlightController.hasFlashlight();
+    }
+
+    @Override
     protected void handleClick() {
         if (ActivityManager.isUserAMonkey()) {
             return;
@@ -79,9 +88,19 @@
 
     @Override
     protected void handleUpdateState(BooleanState state, Object arg) {
-        // TODO: Flashlight available handling...
-//        state.visible = mFlashlightController.isAvailable();
         state.label = mHost.getContext().getString(R.string.quick_settings_flashlight_label);
+        if (!mFlashlightController.isAvailable()) {
+            Drawable icon = mHost.getContext().getDrawable(R.drawable.ic_signal_flashlight_disable);
+            final int disabledColor = mHost.getContext().getColor(R.color.qs_tile_tint_unavailable);
+            icon.setTint(disabledColor);
+            state.icon = new DrawableIcon(icon);
+            state.label = new SpannableStringBuilder().append(state.label,
+                    new ForegroundColorSpan(disabledColor),
+                    SpannableStringBuilder.SPAN_INCLUSIVE_INCLUSIVE);
+            state.contentDescription = mContext.getString(
+                    R.string.accessibility_quick_settings_flashlight_unavailable);
+            return;
+        }
         if (arg instanceof Boolean) {
             boolean value = (Boolean) arg;
             if (value == state.value) {
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 ad1c7a0..da93120 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java
@@ -29,9 +29,11 @@
 /** Quick settings tile: Hotspot **/
 public class HotspotTile extends QSTile<QSTile.BooleanState> {
     private final AnimationIcon mEnable =
-            new AnimationIcon(R.drawable.ic_hotspot_enable_animation);
+            new AnimationIcon(R.drawable.ic_hotspot_enable_animation,
+                    R.drawable.ic_hotspot_disable);
     private final AnimationIcon mDisable =
-            new AnimationIcon(R.drawable.ic_hotspot_disable_animation);
+            new AnimationIcon(R.drawable.ic_hotspot_disable_animation,
+                    R.drawable.ic_hotspot_enable);
     private final HotspotController mController;
     private final Callback mCallback = new Callback();
 
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 6533252..b1d1c77 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java
@@ -32,9 +32,11 @@
 public class LocationTile extends QSTile<QSTile.BooleanState> {
 
     private final AnimationIcon mEnable =
-            new AnimationIcon(R.drawable.ic_signal_location_enable_animation);
+            new AnimationIcon(R.drawable.ic_signal_location_enable_animation,
+                    R.drawable.ic_signal_location_disable);
     private final AnimationIcon mDisable =
-            new AnimationIcon(R.drawable.ic_signal_location_disable_animation);
+            new AnimationIcon(R.drawable.ic_signal_location_disable_animation,
+                    R.drawable.ic_signal_location_enable);
 
     private final LocationController mController;
     private final KeyguardMonitor mKeyguard;
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 b267ccd..d80ca10 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/RotationLockTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/RotationLockTile.java
@@ -31,14 +31,18 @@
 /** Quick settings tile: Rotation **/
 public class RotationLockTile extends QSTile<QSTile.BooleanState> {
     private final AnimationIcon mPortraitToAuto
-            = new AnimationIcon(R.drawable.ic_portrait_to_auto_rotate_animation);
+            = new AnimationIcon(R.drawable.ic_portrait_to_auto_rotate_animation,
+            R.drawable.ic_portrait_from_auto_rotate);
     private final AnimationIcon mAutoToPortrait
-            = new AnimationIcon(R.drawable.ic_portrait_from_auto_rotate_animation);
+            = new AnimationIcon(R.drawable.ic_portrait_from_auto_rotate_animation,
+            R.drawable.ic_portrait_to_auto_rotate);
 
     private final AnimationIcon mLandscapeToAuto
-            = new AnimationIcon(R.drawable.ic_landscape_to_auto_rotate_animation);
+            = new AnimationIcon(R.drawable.ic_landscape_to_auto_rotate_animation,
+            R.drawable.ic_landscape_from_auto_rotate);
     private final AnimationIcon mAutoToLandscape
-            = new AnimationIcon(R.drawable.ic_landscape_from_auto_rotate_animation);
+            = new AnimationIcon(R.drawable.ic_landscape_from_auto_rotate_animation,
+            R.drawable.ic_landscape_to_auto_rotate);
 
     private final RotationLockController mController;
 
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 003e9c1..421a2cf 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/WorkModeTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/WorkModeTile.java
@@ -28,9 +28,11 @@
 public class WorkModeTile extends QSTile<QSTile.BooleanState> implements
         ManagedProfileController.Callback {
     private final AnimationIcon mEnable =
-            new AnimationIcon(R.drawable.ic_signal_workmode_enable_animation);
+            new AnimationIcon(R.drawable.ic_signal_workmode_enable_animation,
+                    R.drawable.ic_signal_workmode_disable);
     private final AnimationIcon mDisable =
-            new AnimationIcon(R.drawable.ic_signal_workmode_disable_animation);
+            new AnimationIcon(R.drawable.ic_signal_workmode_disable_animation,
+                    R.drawable.ic_signal_workmode_enable);
 
     private final ManagedProfileController mProfileController;
 
diff --git a/packages/SystemUI/src/com/android/systemui/recents/IRecentsSystemUserCallbacks.aidl b/packages/SystemUI/src/com/android/systemui/recents/IRecentsSystemUserCallbacks.aidl
index cb8f0e7..9a00d95 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/IRecentsSystemUserCallbacks.aidl
+++ b/packages/SystemUI/src/com/android/systemui/recents/IRecentsSystemUserCallbacks.aidl
@@ -16,6 +16,8 @@
 
 package com.android.systemui.recents;
 
+import android.graphics.Rect;
+
 /**
  * Due to the fact that RecentsActivity is per-user, we need to establish an
  * interface (this) for the non-system user to register itself for callbacks and to
@@ -27,6 +29,6 @@
     void updateRecentsVisibility(boolean visible);
     void startScreenPinning();
     void sendRecentsDrawnEvent();
-    void sendDockingTopTaskEvent(int dragMode);
+    void sendDockingTopTaskEvent(int dragMode, in Rect initialRect);
     void sendLaunchRecentsEvent();
 }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/Recents.java b/packages/SystemUI/src/com/android/systemui/recents/Recents.java
index f5ae351..73ce26f 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/Recents.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/Recents.java
@@ -23,7 +23,9 @@
 import android.content.Intent;
 import android.content.ServiceConnection;
 import android.content.res.Configuration;
+import android.graphics.Point;
 import android.graphics.Rect;
+import android.hardware.display.DisplayManager;
 import android.os.Build;
 import android.os.Handler;
 import android.os.IBinder;
@@ -35,13 +37,15 @@
 import android.util.Log;
 import android.view.Display;
 import android.view.View;
+import android.widget.Toast;
 
 import com.android.systemui.EventLogConstants;
 import com.android.systemui.EventLogTags;
+import com.android.systemui.R;
 import com.android.systemui.RecentsComponent;
 import com.android.systemui.SystemUI;
 import com.android.systemui.recents.events.EventBus;
-import com.android.systemui.recents.events.activity.DockingTopTaskEvent;
+import com.android.systemui.recents.events.activity.DockedTopTaskEvent;
 import com.android.systemui.recents.events.activity.RecentsActivityStartingEvent;
 import com.android.systemui.recents.events.component.RecentsVisibilityChangedEvent;
 import com.android.systemui.recents.events.component.ScreenPinningRequestEvent;
@@ -387,34 +391,48 @@
             return false;
         }
 
+        Point realSize = new Point();
+        if (initialBounds == null) {
+            mContext.getSystemService(DisplayManager.class).getDisplay(Display.DEFAULT_DISPLAY)
+                    .getRealSize(realSize);
+            initialBounds = new Rect(0, 0, realSize.x, realSize.y);
+        }
+
         int currentUser = sSystemServicesProxy.getCurrentUser();
         SystemServicesProxy ssp = Recents.getSystemServices();
         ActivityManager.RunningTaskInfo topTask = ssp.getTopMostTask();
         boolean screenPinningActive = ssp.isScreenPinningActive();
         boolean isTopTaskHome = topTask != null && SystemServicesProxy.isHomeStack(topTask.stackId);
         if (topTask != null && !isTopTaskHome && !screenPinningActive) {
-            if (sSystemServicesProxy.isSystemUser(currentUser)) {
-                mImpl.dockTopTask(topTask.id, dragMode, stackCreateMode, initialBounds);
-            } else {
-                if (mSystemToUserCallbacks != null) {
-                    IRecentsNonSystemUserCallbacks callbacks =
-                            mSystemToUserCallbacks.getNonSystemUserRecentsForUser(currentUser);
-                    if (callbacks != null) {
-                        try {
-                            callbacks.dockTopTask(topTask.id, dragMode, stackCreateMode,
-                                    initialBounds);
-                        } catch (RemoteException e) {
-                            Log.e(TAG, "Callback failed", e);
+            if (topTask.isDockable) {
+                if (sSystemServicesProxy.isSystemUser(currentUser)) {
+                    mImpl.dockTopTask(topTask.id, dragMode, stackCreateMode, initialBounds);
+                } else {
+                    if (mSystemToUserCallbacks != null) {
+                        IRecentsNonSystemUserCallbacks callbacks =
+                                mSystemToUserCallbacks.getNonSystemUserRecentsForUser(currentUser);
+                        if (callbacks != null) {
+                            try {
+                                callbacks.dockTopTask(topTask.id, dragMode, stackCreateMode,
+                                        initialBounds);
+                            } catch (RemoteException e) {
+                                Log.e(TAG, "Callback failed", e);
+                            }
+                        } else {
+                            Log.e(TAG, "No SystemUI callbacks found for user: " + currentUser);
                         }
-                    } else {
-                        Log.e(TAG, "No SystemUI callbacks found for user: " + currentUser);
                     }
                 }
+                mDraggingInRecentsCurrentUser = currentUser;
+                return true;
+            } else {
+                Toast.makeText(mContext, R.string.recents_drag_non_dockable_task_message,
+                        Toast.LENGTH_SHORT).show();
+                return false;
             }
-            mDraggingInRecentsCurrentUser = currentUser;
-            return true;
+        } else {
+            return false;
         }
-        return false;
     }
 
     @Override
@@ -513,8 +531,9 @@
      * Handle Recents activity visibility changed.
      */
     public final void onBusEvent(final RecentsVisibilityChangedEvent event) {
-        int processUser = event.systemServicesProxy.getProcessUser();
-        if (event.systemServicesProxy.isSystemUser(processUser)) {
+        SystemServicesProxy ssp = Recents.getSystemServices();
+        int processUser = ssp.getProcessUser();
+        if (ssp.isSystemUser(processUser)) {
             mImpl.onVisibilityChanged(event.applicationContext, event.visible);
         } else {
             postToSystemUser(new Runnable() {
@@ -567,14 +586,15 @@
         }
     }
 
-    public final void onBusEvent(final DockingTopTaskEvent event) {
+    public final void onBusEvent(final DockedTopTaskEvent event) {
         int processUser = sSystemServicesProxy.getProcessUser();
         if (!sSystemServicesProxy.isSystemUser(processUser)) {
             postToSystemUser(new Runnable() {
                 @Override
                 public void run() {
                     try {
-                        mUserToSystemCallbacks.sendDockingTopTaskEvent(event.dragMode);
+                        mUserToSystemCallbacks.sendDockingTopTaskEvent(event.dragMode,
+                                event.initialRect);
                     } catch (RemoteException e) {
                         Log.e(TAG, "Callback failed", e);
                     }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
index c41098f..473956f 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
@@ -43,6 +43,7 @@
 import com.android.systemui.recents.events.EventBus;
 import com.android.systemui.recents.events.activity.AppWidgetProviderChangedEvent;
 import com.android.systemui.recents.events.activity.CancelEnterRecentsWindowAnimationEvent;
+import com.android.systemui.recents.events.activity.ConfigurationChangedEvent;
 import com.android.systemui.recents.events.activity.DebugFlagsChangedEvent;
 import com.android.systemui.recents.events.activity.DismissRecentsToHomeAnimationStarted;
 import com.android.systemui.recents.events.activity.EnterRecentsWindowAnimationCompletedEvent;
@@ -54,7 +55,7 @@
 import com.android.systemui.recents.events.activity.LaunchTaskFailedEvent;
 import com.android.systemui.recents.events.activity.LaunchTaskSucceededEvent;
 import com.android.systemui.recents.events.activity.ShowHistoryEvent;
-import com.android.systemui.recents.events.activity.TaskStackUpdatedEvent;
+import com.android.systemui.recents.events.activity.MultiWindowStateChangedEvent;
 import com.android.systemui.recents.events.activity.ToggleRecentsEvent;
 import com.android.systemui.recents.events.component.RecentsVisibilityChangedEvent;
 import com.android.systemui.recents.events.component.ScreenPinningRequestEvent;
@@ -96,6 +97,7 @@
     private long mLastTabKeyEventTime;
     private boolean mFinishedOnStartup;
     private boolean mIgnoreAltTabRelease;
+    private boolean mIsVisible;
 
     // Top level views
     private RecentsView mRecentsView;
@@ -107,7 +109,7 @@
     private RecentsAppWidgetHostView mSearchWidgetHostView;
 
     // Runnables to finish the Recents activity
-    private FinishRecentsRunnable mFinishLaunchHomeRunnable;
+    private Intent mHomeIntent;
 
     // The trigger to automatically launch the current task
     private int mFocusTimerDuration;
@@ -119,7 +121,7 @@
      * last activity launch state. Generally we always launch home when we exit Recents rather than
      * just finishing the activity since we don't know what is behind Recents in the task stack.
      */
-    class FinishRecentsRunnable implements Runnable {
+    class LaunchHomeRunnable implements Runnable {
 
         Intent mLaunchIntent;
         ActivityOptions mOpts;
@@ -127,7 +129,7 @@
         /**
          * Creates a finish runnable that starts the specified intent.
          */
-        public FinishRecentsRunnable(Intent launchIntent, ActivityOptions opts) {
+        public LaunchHomeRunnable(Intent launchIntent, ActivityOptions opts) {
             mLaunchIntent = launchIntent;
             mOpts = opts;
         }
@@ -173,59 +175,6 @@
         }
     };
 
-    /** Updates the set of recent tasks */
-    void updateRecentsTasks() {
-        // If AlternateRecentsComponent has preloaded a load plan, then use that to prevent
-        // reconstructing the task stack
-        RecentsTaskLoader loader = Recents.getTaskLoader();
-        RecentsTaskLoadPlan plan = RecentsImpl.consumeInstanceLoadPlan();
-        if (plan == null) {
-            plan = loader.createLoadPlan(this);
-        }
-
-        // Start loading tasks according to the load plan
-        RecentsConfiguration config = Recents.getConfiguration();
-        RecentsActivityLaunchState launchState = config.getLaunchState();
-        if (!plan.hasTasks()) {
-            loader.preloadTasks(plan, -1, launchState.launchedFromHome);
-        }
-        RecentsTaskLoadPlan.Options loadOpts = new RecentsTaskLoadPlan.Options();
-        loadOpts.runningTaskId = launchState.launchedToTaskId;
-        loadOpts.numVisibleTasks = launchState.launchedNumVisibleTasks;
-        loadOpts.numVisibleTaskThumbnails = launchState.launchedNumVisibleThumbnails;
-        loader.loadTasks(this, plan, loadOpts);
-
-        TaskStack stack = plan.getTaskStack();
-        mRecentsView.setTaskStack(stack);
-
-        // Animate the SystemUI scrims into view
-        Task launchTarget = stack.getLaunchTarget();
-        int taskCount = stack.getTaskCount();
-        int launchTaskIndexInStack = launchTarget != null
-                ? stack.indexOfStackTask(launchTarget)
-                : 0;
-        boolean hasNavBarScrim = (taskCount > 0) && !config.hasTransposedNavBar;
-        boolean animateNavBarScrim = !launchState.launchedWhileDocking;
-        mScrimViews.prepareEnterRecentsAnimation(hasNavBarScrim, animateNavBarScrim);
-
-        // Keep track of whether we launched from the nav bar button or via alt-tab
-        if (launchState.launchedWithAltTab) {
-            MetricsLogger.count(this, "overview_trigger_alttab", 1);
-        } else {
-            MetricsLogger.count(this, "overview_trigger_nav_btn", 1);
-        }
-        // Keep track of whether we launched from an app or from home
-        if (launchState.launchedFromAppWithThumbnail) {
-            MetricsLogger.count(this, "overview_source_app", 1);
-            // If from an app, track the stack index of the app in the stack (for affiliated tasks)
-            MetricsLogger.histogram(this, "overview_source_app_index", launchTaskIndexInStack);
-        } else {
-            MetricsLogger.count(this, "overview_source_home", 1);
-        }
-        // Keep track of the total stack task count
-        MetricsLogger.histogram(this, "overview_task_count", taskCount);
-    }
-
     /**
      * Dismisses the history view back into the stack view.
      */
@@ -294,12 +243,8 @@
     void dismissRecentsToHome(boolean animateTaskViews, ActivityOptions overrideAnimation) {
         DismissRecentsToHomeAnimationStarted dismissEvent =
                 new DismissRecentsToHomeAnimationStarted(animateTaskViews);
-        if (overrideAnimation != null) {
-            dismissEvent.addPostAnimationCallback(new FinishRecentsRunnable(
-                    mFinishLaunchHomeRunnable.mLaunchIntent, overrideAnimation));
-        } else {
-            dismissEvent.addPostAnimationCallback(mFinishLaunchHomeRunnable);
-        }
+        dismissEvent.addPostAnimationCallback(new LaunchHomeRunnable(mHomeIntent,
+                overrideAnimation));
         dismissEvent.addPostAnimationCallback(new Runnable() {
             @Override
             public void run() {
@@ -348,6 +293,7 @@
 
         // Set the Recents layout
         setContentView(R.layout.recents);
+        takeKeyEvents(true);
         mRecentsView = (RecentsView) findViewById(R.id.recents_view);
         mRecentsView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE |
                 View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN |
@@ -365,11 +311,10 @@
         });
 
         // Create the home intent runnable
-        Intent homeIntent = new Intent(Intent.ACTION_MAIN, null);
-        homeIntent.addCategory(Intent.CATEGORY_HOME);
-        homeIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
+        mHomeIntent = new Intent(Intent.ACTION_MAIN, null);
+        mHomeIntent.addCategory(Intent.CATEGORY_HOME);
+        mHomeIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
                 Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
-        mFinishLaunchHomeRunnable = new FinishRecentsRunnable(homeIntent, null);
 
         // Bind the search app widget when we first start up
         if (RecentsDebugFlags.Static.EnableSearchBar) {
@@ -386,45 +331,12 @@
     }
 
     @Override
-    protected void onNewIntent(Intent intent) {
-        super.onNewIntent(intent);
-        setIntent(intent);
-    }
-
-    @Override
     protected void onStart() {
         super.onStart();
 
-        // Update the recent tasks
-        updateRecentsTasks();
-
-        // If this is a new instance from a configuration change, then we have to manually trigger
-        // the enter animation state, or if recents was relaunched by AM, without going through
-        // the normal mechanisms
-        RecentsConfiguration config = Recents.getConfiguration();
-        RecentsActivityLaunchState launchState = config.getLaunchState();
-        boolean wasLaunchedByAm = !launchState.launchedFromHome &&
-                !launchState.launchedFromAppWithThumbnail;
-        if (launchState.launchedHasConfigurationChanged || wasLaunchedByAm) {
-            EventBus.getDefault().send(new EnterRecentsWindowAnimationCompletedEvent());
-        }
-
         // Notify that recents is now visible
-        SystemServicesProxy ssp = Recents.getSystemServices();
-        EventBus.getDefault().send(new RecentsVisibilityChangedEvent(this, ssp, true));
-
+        EventBus.getDefault().send(new RecentsVisibilityChangedEvent(this, true));
         MetricsLogger.visible(this, MetricsEvent.OVERVIEW_ACTIVITY);
-
-        mRecentsView.getViewTreeObserver().addOnPreDrawListener(
-                new ViewTreeObserver.OnPreDrawListener() {
-
-            @Override
-            public boolean onPreDraw() {
-                mRecentsView.getViewTreeObserver().removeOnPreDrawListener(this);
-                EventBus.getDefault().post(new RecentsDrawnEvent());
-                return true;
-            }
-        });
     }
 
     @Override
@@ -434,10 +346,90 @@
     }
 
     @Override
+    protected void onResume() {
+        super.onResume();
+
+        // If the Recents component has preloaded a load plan, then use that to prevent
+        // reconstructing the task stack
+        RecentsTaskLoader loader = Recents.getTaskLoader();
+        RecentsTaskLoadPlan loadPlan = RecentsImpl.consumeInstanceLoadPlan();
+        if (loadPlan == null) {
+            loadPlan = loader.createLoadPlan(this);
+        }
+
+        // Start loading tasks according to the load plan
+        RecentsConfiguration config = Recents.getConfiguration();
+        RecentsActivityLaunchState launchState = config.getLaunchState();
+        if (!loadPlan.hasTasks()) {
+            loader.preloadTasks(loadPlan, -1, launchState.launchedFromHome);
+        }
+
+        RecentsTaskLoadPlan.Options loadOpts = new RecentsTaskLoadPlan.Options();
+        loadOpts.runningTaskId = launchState.launchedToTaskId;
+        loadOpts.numVisibleTasks = launchState.launchedNumVisibleTasks;
+        loadOpts.numVisibleTaskThumbnails = launchState.launchedNumVisibleThumbnails;
+        loader.loadTasks(this, loadPlan, loadOpts);
+        TaskStack stack = loadPlan.getTaskStack();
+        mRecentsView.onResume(mIsVisible, stack);
+
+        // Animate the SystemUI scrims into view
+        Task launchTarget = stack.getLaunchTarget();
+        int taskCount = stack.getTaskCount();
+        int launchTaskIndexInStack = launchTarget != null
+                ? stack.indexOfStackTask(launchTarget)
+                : 0;
+        boolean hasNavBarScrim = (taskCount > 0) && !config.hasTransposedNavBar;
+        boolean animateNavBarScrim = !launchState.launchedWhileDocking;
+        mScrimViews.prepareEnterRecentsAnimation(hasNavBarScrim, animateNavBarScrim);
+
+        // If this is a new instance from a configuration change, then we have to manually trigger
+        // the enter animation state, or if recents was relaunched by AM, without going through
+        // the normal mechanisms
+        boolean wasLaunchedByAm = !launchState.launchedFromHome &&
+                !launchState.launchedFromApp;
+        if (launchState.launchedHasConfigurationChanged || wasLaunchedByAm) {
+            EventBus.getDefault().send(new EnterRecentsWindowAnimationCompletedEvent());
+        }
+
+        mRecentsView.getViewTreeObserver().addOnPreDrawListener(
+                new ViewTreeObserver.OnPreDrawListener() {
+
+                    @Override
+                    public boolean onPreDraw() {
+                        mRecentsView.getViewTreeObserver().removeOnPreDrawListener(this);
+                        EventBus.getDefault().post(new RecentsDrawnEvent());
+                        return true;
+                    }
+                });
+
+        // Keep track of whether we launched from the nav bar button or via alt-tab
+        if (launchState.launchedWithAltTab) {
+            MetricsLogger.count(this, "overview_trigger_alttab", 1);
+        } else {
+            MetricsLogger.count(this, "overview_trigger_nav_btn", 1);
+        }
+
+        // Keep track of whether we launched from an app or from home
+        if (launchState.launchedFromApp) {
+            MetricsLogger.count(this, "overview_source_app", 1);
+            // If from an app, track the stack index of the app in the stack (for affiliated tasks)
+            MetricsLogger.histogram(this, "overview_source_app_index", launchTaskIndexInStack);
+        } else {
+            MetricsLogger.count(this, "overview_source_home", 1);
+        }
+
+        // Keep track of the total stack task count
+        MetricsLogger.histogram(this, "overview_task_count", taskCount);
+
+        // After we have resumed, set the visible state until the next onStop() call
+        mIsVisible = true;
+    }
+
+    @Override
     protected void onPause() {
         super.onPause();
 
-        // Stop the fast-toggle dozer
+        mIgnoreAltTabRelease = false;
         mIterateTrigger.stopDozing();
     }
 
@@ -445,15 +437,15 @@
     protected void onStop() {
         super.onStop();
 
-        // Reset some states
-        mIgnoreAltTabRelease = false;
+        // Only hide the history if Recents is completely hidden
         if (RecentsDebugFlags.Static.EnableHistory && mRecentsView.isHistoryVisible()) {
             EventBus.getDefault().send(new HideHistoryEvent(false /* animate */));
         }
 
         // Notify that recents is now hidden
-        SystemServicesProxy ssp = Recents.getSystemServices();
-        EventBus.getDefault().send(new RecentsVisibilityChangedEvent(this, ssp, false));
+        mIsVisible = false;
+        EventBus.getDefault().send(new RecentsVisibilityChangedEvent(this, false));
+        MetricsLogger.hidden(this, MetricsEvent.OVERVIEW_ACTIVITY);
 
         // Workaround for b/22542869, if the RecentsActivity is started again, but without going
         // through SystemUI, we need to reset the config launch flags to ensure that we do not
@@ -461,8 +453,6 @@
         RecentsConfiguration config = Recents.getConfiguration();
         RecentsActivityLaunchState launchState = config.getLaunchState();
         launchState.reset();
-
-        MetricsLogger.hidden(this, MetricsEvent.OVERVIEW_ACTIVITY);
     }
 
     @Override
@@ -528,16 +518,23 @@
     @Override
     public void onMultiWindowChanged(boolean inMultiWindow) {
         super.onMultiWindowChanged(inMultiWindow);
+        EventBus.getDefault().send(new ConfigurationChangedEvent());
+
+        // Reload the task stack completely
+        RecentsConfiguration config = Recents.getConfiguration();
+        RecentsActivityLaunchState launchState = config.getLaunchState();
         RecentsTaskLoader loader = Recents.getTaskLoader();
-        RecentsTaskLoadPlan.Options launchOpts = new RecentsTaskLoadPlan.Options();
-        launchOpts.loadIcons = false;
-        launchOpts.loadThumbnails = false;
-        launchOpts.onlyLoadForCache = true;
         RecentsTaskLoadPlan loadPlan = loader.createLoadPlan(this);
-        loader.preloadTasks(loadPlan, -1, false);
-        loader.loadTasks(this, loadPlan, launchOpts);
-        EventBus.getDefault().send(new TaskStackUpdatedEvent(loadPlan.getTaskStack(),
-                inMultiWindow));
+        loader.preloadTasks(loadPlan, -1 /* topTaskId */, false /* isTopTaskHome */);
+
+        RecentsTaskLoadPlan.Options loadOpts = new RecentsTaskLoadPlan.Options();
+        loadOpts.numVisibleTasks = launchState.launchedNumVisibleTasks;
+        loadOpts.numVisibleTaskThumbnails = launchState.launchedNumVisibleThumbnails;
+        loader.loadTasks(this, loadPlan, loadOpts);
+
+        mRecentsView.onResume(mIsVisible, loadPlan.getTaskStack());
+
+        EventBus.getDefault().send(new MultiWindowStateChangedEvent(inMultiWindow));
     }
 
     @Override
@@ -636,7 +633,7 @@
             // Focus the next task
             EventBus.getDefault().send(new FocusNextTaskViewEvent(timerIndicatorDuration));
 
-            MetricsLogger.action(this, MetricsEvent.OVERVIEW_PAGE);
+            MetricsLogger.action(this, MetricsEvent.ACTION_OVERVIEW_PAGE);
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivityLaunchState.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivityLaunchState.java
index aa1437b..ec4820a 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivityLaunchState.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivityLaunchState.java
@@ -28,7 +28,8 @@
 public class RecentsActivityLaunchState {
 
     public boolean launchedWithAltTab;
-    public boolean launchedFromAppWithThumbnail;
+    public boolean launchedFromApp;
+    public boolean launchedFromAppDocked;
     public boolean launchedFromHome;
     public boolean launchedFromSearchHome;
     public boolean launchedReuseTaskStackViews;
@@ -42,7 +43,8 @@
     public void reset() {
         launchedFromHome = false;
         launchedFromSearchHome = false;
-        launchedFromAppWithThumbnail = false;
+        launchedFromApp = false;
+        launchedFromAppDocked = false;
         launchedToTaskId = -1;
         launchedWithAltTab = false;
         launchedHasConfigurationChanged = false;
@@ -67,7 +69,7 @@
     public int getInitialFocusTaskIndex(int numTasks) {
         RecentsDebugFlags debugFlags = Recents.getDebugFlags();
         RecentsActivityLaunchState launchState = Recents.getConfiguration().getLaunchState();
-        if (launchedFromAppWithThumbnail) {
+        if (launchedFromApp) {
             if (!launchState.launchedWithAltTab && debugFlags.isFastToggleRecentsEnabled()) {
                 // If fast toggling, focus the front most task so that the next tap will focus the
                 // N-1 task
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
index 9e43bb4..eec0411 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
@@ -69,7 +69,6 @@
     public final int smallestWidth;
 
     /** Misc **/
-    public boolean useHardwareLayers;
     public boolean fakeShadows;
     public int svelteLevel;
     public int searchBarSpaceHeightPx;
@@ -80,7 +79,6 @@
         SystemServicesProxy ssp = Recents.getSystemServices();
         Context appContext = context.getApplicationContext();
         Resources res = appContext.getResources();
-        useHardwareLayers = res.getBoolean(R.bool.config_recents_use_hardware_layers);
         fakeShadows = res.getBoolean(R.bool.config_recents_fake_shadows);
         svelteLevel = res.getInteger(R.integer.recents_svelte_level);
 
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsDebugFlags.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsDebugFlags.java
index cd64323..6feda81 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsDebugFlags.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsDebugFlags.java
@@ -39,8 +39,8 @@
         public static final boolean EnableAffiliatedTaskGroups = true;
         // Enables the history
         public static final boolean EnableHistory = false;
-        // Overrides the Tuner flags and enables the fast toggle and timeout
-        public static final boolean EnableFastToggleTimeoutOverride = true;
+        // Overrides the Tuner flags and enables the timeout
+        private static final boolean EnableFastToggleTimeout = false;
 
         // Enables us to create mock recents tasks
         public static final boolean EnableMockTasks = false;
@@ -54,9 +54,9 @@
         public static final int MockTaskGroupsTaskCount = 12;
     }
 
-    private static final String KEY_DISABLE_FAST_TOGGLE = "overview_disable_fast_toggle_via_button";
+    private static final String KEY_ENABLE_PAGING = "overview_enable_paging";
 
-    private boolean mDisableFastToggleRecents;
+    private boolean mEnablePaging;
 
     /**
      * We read the prefs once when we start the activity, then update them as the tuner changes
@@ -65,31 +65,32 @@
     public RecentsDebugFlags(Context context) {
         // Register all our flags, this will also call onTuningChanged() for each key, which will
         // initialize the current state of each flag
-        TunerService.get(context).addTunable(this, KEY_DISABLE_FAST_TOGGLE);
+        TunerService.get(context).addTunable(this, KEY_ENABLE_PAGING);
     }
 
     /**
      * @return whether we are enabling fast toggling.
      */
     public boolean isFastToggleRecentsEnabled() {
-        // These checks EnableFastToggleTimeoutOverride
         SystemServicesProxy ssp = Recents.getSystemServices();
-        if (mDisableFastToggleRecents || ssp.hasFreeformWorkspaceSupport() || ssp.hasDockedTask()
-                || ssp.isTouchExplorationEnabled()) {
+        if (ssp.hasFreeformWorkspaceSupport() || ssp.isTouchExplorationEnabled()) {
             return false;
         }
-        if (Static.EnableFastToggleTimeoutOverride) {
-            return true;
-        }
-        return true;
+        return Static.EnableFastToggleTimeout;
+    }
+
+    /**
+     * @return whether we are enabling paging.
+     */
+    public boolean isPagingEnabled() {
+        return mEnablePaging;
     }
 
     @Override
     public void onTuningChanged(String key, String newValue) {
         switch (key) {
-            case KEY_DISABLE_FAST_TOGGLE:
-                mDisableFastToggleRecents = (newValue != null) &&
-                        (Integer.parseInt(newValue) != 0);
+            case KEY_ENABLE_PAGING:
+                mEnablePaging = (newValue != null) && (Integer.parseInt(newValue) != 0);
                 break;
         }
         EventBus.getDefault().send(new DebugFlagsChangedEvent());
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
index 28b2fae..4e11bca 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
@@ -16,6 +16,8 @@
 
 package com.android.systemui.recents;
 
+import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
+
 import android.app.ActivityManager;
 import android.app.ActivityOptions;
 import android.app.ITaskStackListener;
@@ -45,7 +47,7 @@
 import com.android.systemui.R;
 import com.android.systemui.SystemUIApplication;
 import com.android.systemui.recents.events.EventBus;
-import com.android.systemui.recents.events.activity.DockingTopTaskEvent;
+import com.android.systemui.recents.events.activity.DockedTopTaskEvent;
 import com.android.systemui.recents.events.activity.EnterRecentsWindowLastAnimationFrameEvent;
 import com.android.systemui.recents.events.activity.HideRecentsEvent;
 import com.android.systemui.recents.events.activity.IterateRecentsEvent;
@@ -66,6 +68,7 @@
 import com.android.systemui.recents.model.TaskStack;
 import com.android.systemui.recents.views.TaskStackLayoutAlgorithm;
 import com.android.systemui.recents.views.TaskStackView;
+import com.android.systemui.recents.views.TaskStackViewScroller;
 import com.android.systemui.recents.views.TaskViewHeader;
 import com.android.systemui.recents.views.TaskViewTransform;
 import com.android.systemui.statusbar.BaseStatusBar;
@@ -74,8 +77,6 @@
 
 import java.util.ArrayList;
 
-import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
-
 /**
  * An implementation of the Recents component for the current user.  For secondary users, this can
  * be called remotely from the system user.
@@ -98,6 +99,7 @@
 
     //Used to store tv or non-tv activty for use in creating intents.
     private final String mRecentsIntentActivityName;
+
     /**
      * An implementation of ITaskStackListener, that allows us to listen for changes to the system
      * task stacks and update recents accordingly.
@@ -276,28 +278,24 @@
         mTriggeredFromAltTab = triggeredFromAltTab;
         mDraggingInRecents = draggingInRecents;
         mLaunchedWhileDocking = launchedWhileDockingTask;
-        if (mFastAltTabTrigger.hasTriggered()) {
-            // We are calling this from the doze trigger, so just fall through to show Recents
-            mFastAltTabTrigger.resetTrigger();
+        if (mFastAltTabTrigger.isAsleep()) {
+            // Fast alt-tab duration has elapsed, fall through to showing Recents and reset
+            mFastAltTabTrigger.stopDozing();
         } else if (mFastAltTabTrigger.isDozing()) {
-            // We are dozing but haven't yet triggered, ignore this if this is not another alt-tab,
-            // otherwise, this is an additional tab (alt-tab*), which means that we should trigger
-            // immediately (fall through and disable the pending trigger)
-            // TODO: This is tricky, we need to handle the tab key, but Recents has not yet started
-            //       so we may actually additional signal to handle multiple quick tab cases.  The
-            //       severity of this is inversely proportional to the FAST_ALT_TAB_DELAY_MS
-            //       duration though
+            // Fast alt-tab duration has not elapsed.  If this is triggered by a different
+            // showRecents() call, then ignore that call for now.
+            // TODO: We can not handle quick tabs that happen between the initial showRecents() call
+            //       that started the activity and the activity starting up.  The severity of this
+            //       is inversely proportional to the FAST_ALT_TAB_DELAY_MS duration though.
             if (!triggeredFromAltTab) {
                 return;
             }
             mFastAltTabTrigger.stopDozing();
-        } else {
-            // Otherwise, the doze trigger is not running, and if this is an alt tab, we should
-            // start the trigger and then wait for the hide (or for it to elapse)
-            if (triggeredFromAltTab) {
-                mFastAltTabTrigger.startDozing();
-                return;
-            }
+        } else if (triggeredFromAltTab) {
+            // The fast alt-tab detector is not yet running, so start the trigger and wait for the
+            // hideRecents() call, or for the fast alt-tab duration to elapse
+            mFastAltTabTrigger.startDozing();
+            return;
         }
 
         try {
@@ -321,7 +319,6 @@
 
             // Cancel the fast alt-tab trigger
             mFastAltTabTrigger.stopDozing();
-            mFastAltTabTrigger.resetTrigger();
             return;
         }
 
@@ -348,12 +345,14 @@
             long elapsedTime = SystemClock.elapsedRealtime() - mLastToggleTime;
 
             if (topTask != null && ssp.isRecentsTopMost(topTask, isTopTaskHome)) {
+                RecentsDebugFlags debugFlags = Recents.getDebugFlags();
                 RecentsConfiguration config = Recents.getConfiguration();
                 RecentsActivityLaunchState launchState = config.getLaunchState();
                 if (!launchState.launchedWithAltTab) {
                     // If the user taps quickly
-                    if (ViewConfiguration.getDoubleTapMinTime() < elapsedTime &&
-                            elapsedTime < ViewConfiguration.getDoubleTapTimeout()) {
+                    if (!debugFlags.isPagingEnabled() ||
+                            (ViewConfiguration.getDoubleTapMinTime() < elapsedTime &&
+                                    elapsedTime < ViewConfiguration.getDoubleTapTimeout())) {
                         // Launch the next focused task
                         EventBus.getDefault().post(new LaunchNextTaskRequestEvent());
                     } else {
@@ -568,11 +567,14 @@
 
         // Make sure we inform DividerView before we actually start the activity so we can change
         // the resize mode already.
-        EventBus.getDefault().send(new DockingTopTaskEvent(dragMode));
-        ssp.moveTaskToDockedStack(topTaskId, stackCreateMode, initialBounds);
-        showRecents(false /* triggeredFromAltTab */,
-                dragMode == NavigationBarGestureHelper.DRAG_MODE_RECENTS, false /* animate */,
-                true /* reloadTasks*/);
+        if (ssp.moveTaskToDockedStack(topTaskId, stackCreateMode, initialBounds)) {
+            EventBus.getDefault().send(new DockedTopTaskEvent(dragMode, initialBounds));
+            showRecents(
+                    false /* triggeredFromAltTab */,
+                    dragMode == NavigationBarGestureHelper.DRAG_MODE_RECENTS,
+                    false /* animate */,
+                    true /* launchedWhileDockingTask*/);
+        }
     }
 
     /**
@@ -599,7 +601,7 @@
                 com.android.internal.R.dimen.navigation_bar_width);
         mTaskBarHeight = res.getDimensionPixelSize(
                 R.dimen.recents_task_bar_height);
-        mDummyStackView = new TaskStackView(mContext, new TaskStack());
+        mDummyStackView = new TaskStackView(mContext);
         mHeaderBar = (TaskViewHeader) inflater.inflate(R.layout.recents_task_view_header,
                 null, false);
     }
@@ -612,8 +614,7 @@
      *                               is not already bound (can be expensive)
      * @param stack the stack to initialize the stack layout with
      */
-    private void updateHeaderBarLayout(boolean tryAndBindSearchWidget,
-            TaskStack stack) {
+    private void updateHeaderBarLayout(boolean tryAndBindSearchWidget, TaskStack stack) {
         RecentsConfiguration config = Recents.getConfiguration();
         SystemServicesProxy ssp = Recents.getSystemServices();
         Rect systemInsets = new Rect();
@@ -637,14 +638,16 @@
                 mSearchBarBounds, mTaskStackBounds);
 
         // Rebind the header bar and draw it for the transition
-        TaskStackLayoutAlgorithm algo = mDummyStackView.getStackAlgorithm();
+        TaskStackLayoutAlgorithm stackLayout = mDummyStackView.getStackAlgorithm();
         Rect taskStackBounds = new Rect(mTaskStackBounds);
-        algo.setSystemInsets(systemInsets);
+        stackLayout.setSystemInsets(systemInsets);
         if (stack != null) {
-            algo.initialize(taskStackBounds,
+            stackLayout.initialize(taskStackBounds,
                     TaskStackLayoutAlgorithm.StackState.getStackStateForStack(stack));
+            mDummyStackView.setTasks(stack, false /* notifyStackChanges */,
+                    false /* relayoutTaskStack */);
         }
-        Rect taskViewBounds = algo.getUntransformedTaskViewBounds();
+        Rect taskViewBounds = stackLayout.getUntransformedTaskViewBounds();
         if (!taskViewBounds.equals(mLastTaskViewBounds)) {
             mLastTaskViewBounds.set(taskViewBounds);
 
@@ -702,10 +705,8 @@
         updateHeaderBarLayout(false /* tryAndBindSearchWidget */, stack);
 
         // Update the destination rect
-        mDummyStackView.updateLayoutForStack(stack);
         final Task toTask = new Task();
-        final TaskViewTransform toTransform = getThumbnailTransitionTransform(stack, stackView,
-                toTask);
+        final TaskViewTransform toTransform = getThumbnailTransitionTransform(stackView, toTask);
         ForegroundThread.getHandler().postAtFrontOfQueue(new Runnable() {
             @Override
             public void run() {
@@ -751,17 +752,20 @@
      * Creates the activity options for an app->recents transition.
      */
     private ActivityOptions getThumbnailTransitionActivityOptions(
-            ActivityManager.RunningTaskInfo topTask, TaskStack stack, TaskStackView stackView) {
+            ActivityManager.RunningTaskInfo topTask, TaskStackView stackView) {
         if (topTask.stackId == FREEFORM_WORKSPACE_STACK_ID) {
             ArrayList<AppTransitionAnimationSpec> specs = new ArrayList<>();
-            stackView.getScroller().setStackScrollToInitialState();
-            ArrayList<Task> tasks = stack.getStackTasks();
+            ArrayList<Task> tasks = stackView.getStack().getStackTasks();
+            TaskStackLayoutAlgorithm stackLayout = stackView.getStackAlgorithm();
+            TaskStackViewScroller stackScroller = stackView.getScroller();
+
+            stackView.updateToInitialState();
+
             for (int i = tasks.size() - 1; i >= 0; i--) {
                 Task task = tasks.get(i);
                 if (task.isFreeformTask()) {
-                    mTmpTransform = stackView.getStackAlgorithm()
-                            .getStackTransformScreenCoordinates(task,
-                                    stackView.getScroller().getStackScroll(), mTmpTransform, null);
+                    mTmpTransform = stackLayout.getStackTransformScreenCoordinates(task,
+                                    stackScroller.getStackScroll(), mTmpTransform, null);
                     Rect toTaskRect = new Rect();
                     mTmpTransform.rect.round(toTaskRect);
                     Bitmap thumbnail = getThumbnailBitmap(topTask, task, mTmpTransform);
@@ -775,8 +779,7 @@
         } else {
             // Update the destination rect
             Task toTask = new Task();
-            TaskViewTransform toTransform = getThumbnailTransitionTransform(stack, stackView,
-                    toTask);
+            TaskViewTransform toTransform = getThumbnailTransitionTransform(stackView, toTask);
             RectF toTaskRect = toTransform.rect;
             Bitmap thumbnail = getThumbnailBitmap(topTask, toTask, toTransform);
             if (thumbnail != null) {
@@ -808,9 +811,10 @@
     /**
      * Returns the transition rect for the given task id.
      */
-    private TaskViewTransform getThumbnailTransitionTransform(TaskStack stack,
-            TaskStackView stackView, Task runningTaskOut) {
+    private TaskViewTransform getThumbnailTransitionTransform(TaskStackView stackView,
+            Task runningTaskOut) {
         // Find the running task in the TaskStack
+        TaskStack stack = stackView.getStack();
         Task launchTask = stack.getLaunchTarget();
         if (launchTask != null) {
             runningTaskOut.copyFrom(launchTask);
@@ -821,7 +825,7 @@
         }
 
         // Get the transform for the running task
-        stackView.getScroller().setStackScrollToInitialState();
+        stackView.updateToInitialState();
         mTmpTransform = stackView.getStackAlgorithm().getStackTransformScreenCoordinates(launchTask,
                 stackView.getScroller().getStackScroll(), mTmpTransform, null);
         return mTmpTransform;
@@ -849,6 +853,7 @@
                     c.scale(toTransform.scale, toTransform.scale);
                     mHeaderBar.rebindToTask(toTask, false /* touchExplorationEnabled */,
                             disabledInSafeMode);
+                    mHeaderBar.setDimAlpha(toTransform.dimAlpha);
                     mHeaderBar.draw(c);
                     c.setBitmap(null);
                 }
@@ -881,7 +886,6 @@
         updateHeaderBarLayout(false /* tryAndBindSearchWidget */, stack);
 
         // Prepare the dummy stack for the transition
-        mDummyStackView.updateLayoutForStack(stack);
         TaskStackLayoutAlgorithm.VisibilityReport stackVr =
                 mDummyStackView.computeStackVisibilityReport();
 
@@ -897,8 +901,7 @@
 
         if (useThumbnailTransition) {
             // Try starting with a thumbnail transition
-            ActivityOptions opts = getThumbnailTransitionActivityOptions(topTask, stack,
-                    mDummyStackView);
+            ActivityOptions opts = getThumbnailTransitionActivityOptions(topTask, mDummyStackView);
             if (opts != null) {
                 startRecentsActivity(topTask, opts, false /* fromHome */,
                         false /* fromSearchHome */, true /* fromThumbnail */, stackVr);
@@ -945,14 +948,15 @@
      * Starts the recents activity.
      */
     private void startRecentsActivity(ActivityManager.RunningTaskInfo topTask,
-              ActivityOptions opts, boolean fromHome, boolean fromSearchHome, boolean fromThumbnail,
-              TaskStackLayoutAlgorithm.VisibilityReport vr) {
+                ActivityOptions opts, boolean fromHome, boolean fromSearchHome,
+                boolean fromThumbnail, TaskStackLayoutAlgorithm.VisibilityReport vr) {
         // Update the configuration based on the launch options
         RecentsConfiguration config = Recents.getConfiguration();
         RecentsActivityLaunchState launchState = config.getLaunchState();
         launchState.launchedFromHome = fromSearchHome || fromHome;
         launchState.launchedFromSearchHome = fromSearchHome;
-        launchState.launchedFromAppWithThumbnail = fromThumbnail;
+        launchState.launchedFromApp = fromThumbnail || mLaunchedWhileDocking;
+        launchState.launchedFromAppDocked = mLaunchedWhileDocking;
         launchState.launchedToTaskId = (topTask != null) ? topTask.id : -1;
         launchState.launchedWithAltTab = mTriggeredFromAltTab;
         launchState.launchedReuseTaskStackViews = mCanReuseTaskStackViews;
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsSystemUser.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsSystemUser.java
index f8000b8..ffeb4a1 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsSystemUser.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsSystemUser.java
@@ -17,6 +17,7 @@
 package com.android.systemui.recents;
 
 import android.content.Context;
+import android.graphics.Rect;
 import android.os.IBinder;
 import android.os.RemoteException;
 import android.util.EventLog;
@@ -26,7 +27,7 @@
 import com.android.systemui.EventLogConstants;
 import com.android.systemui.EventLogTags;
 import com.android.systemui.recents.events.EventBus;
-import com.android.systemui.recents.events.activity.DockingTopTaskEvent;
+import com.android.systemui.recents.events.activity.DockedTopTaskEvent;
 import com.android.systemui.recents.events.activity.RecentsActivityStartingEvent;
 import com.android.systemui.recents.events.ui.RecentsDrawnEvent;
 
@@ -91,8 +92,8 @@
     }
 
     @Override
-    public void sendDockingTopTaskEvent(int dragMode) throws RemoteException {
-        EventBus.getDefault().post(new DockingTopTaskEvent(dragMode));
+    public void sendDockingTopTaskEvent(int dragMode, Rect initialRect) throws RemoteException {
+        EventBus.getDefault().post(new DockedTopTaskEvent(dragMode, initialRect));
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/activity/DockingTopTaskEvent.java b/packages/SystemUI/src/com/android/systemui/recents/events/activity/ConfigurationChangedEvent.java
similarity index 71%
copy from packages/SystemUI/src/com/android/systemui/recents/events/activity/DockingTopTaskEvent.java
copy to packages/SystemUI/src/com/android/systemui/recents/events/activity/ConfigurationChangedEvent.java
index 264c2c4..0ad4681 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/events/activity/DockingTopTaskEvent.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/events/activity/ConfigurationChangedEvent.java
@@ -11,7 +11,7 @@
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT 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.recents.events.activity;
@@ -19,13 +19,8 @@
 import com.android.systemui.recents.events.EventBus;
 
 /**
- * Fires when the user invoked the gesture to dock the top/left task.
+ * This is sent when the Recents activity configuration has changed.
  */
-public class DockingTopTaskEvent extends EventBus.Event {
-
-    public int dragMode;
-
-    public DockingTopTaskEvent(int dragMode) {
-        this.dragMode = dragMode;
-    }
+public class ConfigurationChangedEvent extends EventBus.AnimatedEvent {
+    // Simple event
 }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/activity/DockingTopTaskEvent.java b/packages/SystemUI/src/com/android/systemui/recents/events/activity/DockedTopTaskEvent.java
similarity index 74%
rename from packages/SystemUI/src/com/android/systemui/recents/events/activity/DockingTopTaskEvent.java
rename to packages/SystemUI/src/com/android/systemui/recents/events/activity/DockedTopTaskEvent.java
index 264c2c4..f1bc214 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/events/activity/DockingTopTaskEvent.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/events/activity/DockedTopTaskEvent.java
@@ -16,16 +16,21 @@
 
 package com.android.systemui.recents.events.activity;
 
+import android.graphics.Rect;
+
 import com.android.systemui.recents.events.EventBus;
 
 /**
- * Fires when the user invoked the gesture to dock the top/left task.
+ * Fires when the user invoked the gesture to dock the top/left task after we called into window
+ * manager and before we start recents.
  */
-public class DockingTopTaskEvent extends EventBus.Event {
+public class DockedTopTaskEvent extends EventBus.Event {
 
     public int dragMode;
+    public Rect initialRect;
 
-    public DockingTopTaskEvent(int dragMode) {
+    public DockedTopTaskEvent(int dragMode, Rect initialRect) {
         this.dragMode = dragMode;
+        this.initialRect = initialRect;
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/activity/LaunchTvTaskEvent.java b/packages/SystemUI/src/com/android/systemui/recents/events/activity/LaunchTvTaskEvent.java
new file mode 100644
index 0000000..04ca68f
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/recents/events/activity/LaunchTvTaskEvent.java
@@ -0,0 +1,39 @@
+/*
+ * 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.recents.events.activity;
+
+
+import android.graphics.Rect;
+import com.android.systemui.recents.events.EventBus;
+import com.android.systemui.recents.model.Task;
+import com.android.systemui.recents.tv.views.TaskCardView;
+
+public class LaunchTvTaskEvent extends EventBus.Event {
+
+    public final TaskCardView taskView;
+    public final Task task;
+    public final Rect targetTaskBounds;
+    public final int targetTaskStack;
+
+    public LaunchTvTaskEvent(TaskCardView taskView, Task task, Rect targetTaskBounds,
+            int targetTaskStack) {
+        this.taskView = taskView;
+        this.task = task;
+        this.targetTaskBounds = targetTaskBounds;
+        this.targetTaskStack = targetTaskStack;
+    }
+
+}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/activity/DockingTopTaskEvent.java b/packages/SystemUI/src/com/android/systemui/recents/events/activity/LaunchTvTaskStartedEvent.java
similarity index 62%
copy from packages/SystemUI/src/com/android/systemui/recents/events/activity/DockingTopTaskEvent.java
copy to packages/SystemUI/src/com/android/systemui/recents/events/activity/LaunchTvTaskStartedEvent.java
index 264c2c4..75d3efa 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/events/activity/DockingTopTaskEvent.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/events/activity/LaunchTvTaskStartedEvent.java
@@ -11,21 +11,24 @@
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT 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.recents.events.activity;
 
 import com.android.systemui.recents.events.EventBus;
+import com.android.systemui.recents.tv.views.TaskCardView;
 
 /**
- * Fires when the user invoked the gesture to dock the top/left task.
+ * This event is sent following {@link LaunchTvTaskEvent} after the call to the system is made to
+ * start the task, only used on TV.
  */
-public class DockingTopTaskEvent extends EventBus.Event {
+public class LaunchTvTaskStartedEvent extends EventBus.AnimatedEvent {
 
-    public int dragMode;
+    public final TaskCardView taskView;
 
-    public DockingTopTaskEvent(int dragMode) {
-        this.dragMode = dragMode;
+    public LaunchTvTaskStartedEvent(TaskCardView taskView) {
+        this.taskView = taskView;
     }
+
 }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/activity/DockingTopTaskEvent.java b/packages/SystemUI/src/com/android/systemui/recents/events/activity/MultiWindowStateChangedEvent.java
similarity index 63%
copy from packages/SystemUI/src/com/android/systemui/recents/events/activity/DockingTopTaskEvent.java
copy to packages/SystemUI/src/com/android/systemui/recents/events/activity/MultiWindowStateChangedEvent.java
index 264c2c4..19245d9 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/events/activity/DockingTopTaskEvent.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/events/activity/MultiWindowStateChangedEvent.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2016 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,7 +11,7 @@
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT 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.recents.events.activity;
@@ -19,13 +19,13 @@
 import com.android.systemui.recents.events.EventBus;
 
 /**
- * Fires when the user invoked the gesture to dock the top/left task.
+ * This is sent by the activity whenever the multi-window state has changed.
  */
-public class DockingTopTaskEvent extends EventBus.Event {
+public class MultiWindowStateChangedEvent extends EventBus.Event {
 
-    public int dragMode;
+    public final boolean inMultiWindow;
 
-    public DockingTopTaskEvent(int dragMode) {
-        this.dragMode = dragMode;
+    public MultiWindowStateChangedEvent(boolean inMultiWindow) {
+        this.inMultiWindow = inMultiWindow;
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/component/RecentsVisibilityChangedEvent.java b/packages/SystemUI/src/com/android/systemui/recents/events/component/RecentsVisibilityChangedEvent.java
index 4140bcd..8843eb4 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/events/component/RecentsVisibilityChangedEvent.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/events/component/RecentsVisibilityChangedEvent.java
@@ -19,21 +19,18 @@
 import android.content.Context;
 
 import com.android.systemui.recents.events.EventBus;
-import com.android.systemui.recents.misc.SystemServicesProxy;
 
 /**
- * This is sent when the visibility of the RecentsActivity for the current user changes.
+ * This is sent when the visibility of the RecentsActivity for the current user changes.  Handlers
+ * of this event should not alter the UI, as the activity may still be visible.
  */
 public class RecentsVisibilityChangedEvent extends EventBus.Event {
 
     public final Context applicationContext;
-    public final SystemServicesProxy systemServicesProxy;
     public final boolean visible;
 
-    public RecentsVisibilityChangedEvent(Context context, SystemServicesProxy systemServicesProxy,
-            boolean visible) {
+    public RecentsVisibilityChangedEvent(Context context, boolean visible) {
         this.applicationContext = context.getApplicationContext();
-        this.systemServicesProxy = systemServicesProxy;
         this.visible = visible;
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/history/RecentsHistoryAdapter.java b/packages/SystemUI/src/com/android/systemui/recents/history/RecentsHistoryAdapter.java
index d7b9b9e..5eeda72 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/history/RecentsHistoryAdapter.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/history/RecentsHistoryAdapter.java
@@ -161,7 +161,7 @@
             ssp.startActivityFromRecents(v.getContext(), task.key.id, task.title,
                     ActivityOptions.makeBasic());
 
-            MetricsLogger.action(v.getContext(), MetricsEvent.OVERVIEW_SELECT,
+            MetricsLogger.action(v.getContext(), MetricsEvent.ACTION_OVERVIEW_SELECT,
                     task.key.getComponent().toString());
         }
 
diff --git a/packages/SystemUI/src/com/android/systemui/recents/misc/DozeTrigger.java b/packages/SystemUI/src/com/android/systemui/recents/misc/DozeTrigger.java
index 95aa10f..574ea03 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/misc/DozeTrigger.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/misc/DozeTrigger.java
@@ -30,7 +30,7 @@
     @ViewDebug.ExportedProperty(category="recents")
     boolean mIsDozing;
     @ViewDebug.ExportedProperty(category="recents")
-    boolean mHasTriggered;
+    boolean mIsAsleep;
     @ViewDebug.ExportedProperty(category="recents")
     int mDozeDurationMilliseconds;
     Runnable mOnSleepRunnable;
@@ -40,7 +40,7 @@
         @Override
         public void run() {
             mIsDozing = false;
-            mHasTriggered = true;
+            mIsAsleep = true;
             mOnSleepRunnable.run();
         }
     };
@@ -56,7 +56,7 @@
      */
     public void startDozing() {
         forcePoke();
-        mHasTriggered = false;
+        mIsAsleep = false;
     }
 
     /**
@@ -65,6 +65,7 @@
     public void stopDozing() {
         mHandler.removeCallbacks(mDozeRunnable);
         mIsDozing = false;
+        mIsAsleep = false;
     }
 
     /**
@@ -99,12 +100,7 @@
     }
 
     /** Returns whether the trigger has fired at least once. */
-    public boolean hasTriggered() {
-        return mHasTriggered;
-    }
-
-    /** Resets the doze trigger state. */
-    public void resetTrigger() {
-        mHasTriggered = false;
+    public boolean isAsleep() {
+        return mIsAsleep;
     }
 }
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 4b29c29..532e796 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
@@ -338,15 +338,18 @@
     }
 
     /** Docks an already resumed task to the side of the screen. */
-    public void moveTaskToDockedStack(int taskId, int createMode, Rect initialBounds) {
-        if (mIam == null) return;
+    public boolean moveTaskToDockedStack(int taskId, int createMode, Rect initialBounds) {
+        if (mIam == null) {
+            return false;
+        }
 
         try {
-            mIam.moveTaskToDockedStack(taskId, createMode, true /* onTop */, false /* animate */,
-                    initialBounds);
+            return mIam.moveTaskToDockedStack(
+                    taskId, createMode, true /* onTop */, false /* animate */, initialBounds);
         } catch (RemoteException e) {
             e.printStackTrace();
         }
+        return false;
     }
 
     /** Returns the focused stack id. */
@@ -692,6 +695,37 @@
     }
 
     /**
+     * Returns a banner used on TV for the specified Activity.
+     */
+    public Drawable getActivityBanner(ActivityInfo info) {
+        if (mPm == null) return null;
+
+        // If we are mocking, then return a mock banner
+        if (RecentsDebugFlags.Static.EnableMockTasks) {
+            return new ColorDrawable(0xFF666666);
+        }
+
+        Drawable banner = info.loadBanner(mPm);
+        return banner;
+    }
+
+    /**
+     * Returns a logo used on TV for the specified Activity.
+     */
+    public Drawable getActivityLogo(ActivityInfo info) {
+        if (mPm == null) return null;
+
+        // If we are mocking, then return a mock logo
+        if (RecentsDebugFlags.Static.EnableMockTasks) {
+            return new ColorDrawable(0xFF666666);
+        }
+
+        Drawable logo = info.loadLogo(mPm);
+        return logo;
+    }
+
+
+    /**
      * Returns the given label for a user, badging if necessary.
      */
     private String getBadgedLabel(String label, int userId) {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoadPlan.java b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoadPlan.java
index 6fef8a2..6ae07fc 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoadPlan.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoadPlan.java
@@ -133,7 +133,6 @@
         SparseIntArray affiliatedTaskCounts = new SparseIntArray();
         String dismissDescFormat = mContext.getString(
                 R.string.accessibility_recents_item_will_be_dismissed);
-        Formatter dismissDescFormatter = new Formatter();
         long lastStackActiveTime = Prefs.getLong(mContext,
                 Prefs.Key.OVERVIEW_LAST_STACK_TASK_ACTIVE_TIME, 0);
         if (RecentsDebugFlags.Static.EnableMockTasks) {
@@ -184,8 +183,7 @@
             ActivityInfo info = loader.getAndUpdateActivityInfo(taskKey);
             String title = loader.getAndUpdateActivityTitle(taskKey, t.taskDescription);
             String contentDescription = loader.getAndUpdateContentDescription(taskKey, res);
-            String dismissDescription = dismissDescFormatter.format(dismissDescFormat,
-                    contentDescription).toString();
+            String dismissDescription = String.format(dismissDescFormat, contentDescription);
             Drawable icon = isStackTask
                     ? loader.getAndUpdateActivityIcon(taskKey, t.taskDescription, res, false)
                     : null;
@@ -214,8 +212,7 @@
 
         // Initialize the stacks
         mStack = new TaskStack();
-        mStack.setTasks(allTasks, false /* notifyStackChanges */);
-        mStack.createAffiliatedGroupings(mContext);
+        mStack.setTasks(mContext, allTasks, false /* notifyStackChanges */);
     }
 
     /**
diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/Task.java b/packages/SystemUI/src/com/android/systemui/recents/model/Task.java
index e5d4f1b..b5a5949 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/model/Task.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/model/Task.java
@@ -100,11 +100,7 @@
 
         @Override
         public String toString() {
-            return "Task.Key: " + id + ", "
-                    + "s: " + stackId + ", "
-                    + "u: " + userId + ", "
-                    + "lat: " + lastActiveTime + ", "
-                    + getComponent().getPackageName();
+            return "t" + id + ", s" + stackId + ", u" + userId;
         }
 
         private void updateHashCode() {
@@ -204,7 +200,9 @@
         this.isDockable = isDockable;
     }
 
-    /** Copies the other task. */
+    /**
+     * Copies the metadata from another task, but retains the current callbacks.
+     */
     public void copyFrom(Task o) {
         this.key = o.key;
         this.group = o.group;
@@ -300,11 +298,6 @@
 
     @Override
     public String toString() {
-        String groupAffiliation = "no group";
-        if (group != null) {
-            groupAffiliation = Integer.toString(group.affiliation);
-        }
-        return "Task (" + groupAffiliation + "): " + key +
-                " [" + super.toString() + "]";
+        return "[" + key.toString() + "] " + title;
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java b/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java
index 1f91dce..4d1c552 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java
@@ -92,15 +92,6 @@
         }
     }
 
-    /**
-     * Resets the task list, but does not remove the filter.
-     */
-    void reset() {
-        mTasks.clear();
-        mFilteredTasks.clear();
-        mTaskIndices.clear();
-    }
-
     /** Removes the task filter and returns the previous touch state */
     void removeFilter() {
         mFilter = null;
@@ -481,15 +472,6 @@
         mCb = cb;
     }
 
-    /** Resets this TaskStack. */
-    public void reset() {
-        mCb = null;
-        mStackTaskList.reset();
-        mHistoryTaskList.reset();
-        mGroups.clear();
-        mAffinitiesGroups.clear();
-    }
-
     /**
      * Moves the given task to either the front of the freeform workspace or the stack.
      */
@@ -556,12 +538,12 @@
      * @param tasks the new set of tasks to replace the current set.
      * @param notifyStackChanges whether or not to callback on specific changes to the list of tasks.
      */
-    public void setTasks(List<Task> tasks, boolean notifyStackChanges) {
+    public void setTasks(Context context, List<Task> tasks, boolean notifyStackChanges) {
         // Compute a has set for each of the tasks
         ArrayMap<Task.TaskKey, Task> currentTasksMap = createTaskKeyMapFromList(mRawTaskList);
         ArrayMap<Task.TaskKey, Task> newTasksMap = createTaskKeyMapFromList(tasks);
-
-        ArrayList<Task> newTasks = new ArrayList<>();
+        ArrayList<Task> addedTasks = new ArrayList<>();
+        ArrayList<Task> allTasks = new ArrayList<>();
 
         // Disable notifications if there are no callbacks
         if (mCb == null) {
@@ -570,10 +552,13 @@
 
         // Remove any tasks that no longer exist
         int taskCount = mRawTaskList.size();
-        for (int i = 0; i < taskCount; i++) {
+        for (int i = taskCount - 1; i >= 0; i--) {
             Task task = mRawTaskList.get(i);
             if (!newTasksMap.containsKey(task.key)) {
                 if (notifyStackChanges) {
+                    // If we are notifying, then remove the task now, otherwise the raw task list
+                    // will be reset at the end of this method
+                    removeTask(task, AnimationProps.IMMEDIATE);
                     mCb.onStackTaskRemoved(this, task, i == (taskCount - 1), null,
                             AnimationProps.IMMEDIATE);
                 }
@@ -584,26 +569,28 @@
         // Add any new tasks
         taskCount = tasks.size();
         for (int i = 0; i < taskCount; i++) {
-            Task task = tasks.get(i);
-            if (!currentTasksMap.containsKey(task.key)) {
-                if (notifyStackChanges) {
-                    mCb.onStackTaskAdded(this, task);
-                }
-                newTasks.add(task);
-            } else {
-                newTasks.add(currentTasksMap.get(task.key));
+            Task newTask = tasks.get(i);
+            Task currentTask = currentTasksMap.get(newTask.key);
+            if (currentTask == null && notifyStackChanges) {
+                addedTasks.add(newTask);
+            } else if (currentTask != null) {
+                // The current task has bound callbacks, so just copy the data from the new task
+                // state and add it back into the list
+                currentTask.copyFrom(newTask);
+                newTask = currentTask;
             }
+            allTasks.add(newTask);
         }
 
         // Sort all the tasks to ensure they are ordered correctly
-        Collections.sort(newTasks, FREEFORM_LAST_ACTIVE_TIME_COMPARATOR);
+        Collections.sort(allTasks, FREEFORM_LAST_ACTIVE_TIME_COMPARATOR);
 
         // Filter out the historical tasks from this new list
         ArrayList<Task> stackTasks = new ArrayList<>();
         ArrayList<Task> historyTasks = new ArrayList<>();
-        int newTaskCount = newTasks.size();
+        int newTaskCount = allTasks.size();
         for (int i = 0; i < newTaskCount; i++) {
-            Task task = newTasks.get(i);
+            Task task = allTasks.get(i);
             if (task.isHistorical) {
                 historyTasks.add(task);
             } else {
@@ -613,10 +600,16 @@
 
         mStackTaskList.set(stackTasks);
         mHistoryTaskList.set(historyTasks);
-        mRawTaskList.clear();
-        mRawTaskList.addAll(newTasks);
-        mGroups.clear();
-        mAffinitiesGroups.clear();
+        mRawTaskList = allTasks;
+
+        // Only callback for the newly added tasks after this stack has been updated
+        int addedTaskCount = addedTasks.size();
+        for (int i = 0; i < addedTaskCount; i++) {
+            mCb.onStackTaskAdded(this, addedTasks.get(i));
+        }
+
+        // Update the affiliated groupings
+        createAffiliatedGroupings(context);
     }
 
     /**
@@ -779,9 +772,12 @@
     }
 
     /**
-     * Temporary: This method will simulate affiliation groups by
+     * Temporary: This method will simulate affiliation groups
      */
-    public void createAffiliatedGroupings(Context context) {
+    void createAffiliatedGroupings(Context context) {
+        mGroups.clear();
+        mAffinitiesGroups.clear();
+
         if (RecentsDebugFlags.Static.EnableMockTaskGroups) {
             ArrayMap<Task.TaskKey, Task> taskMap = new ArrayMap<>();
             // Sort all tasks by increasing firstActiveTime of the task
@@ -926,13 +922,13 @@
 
     @Override
     public String toString() {
-        String str = "Stack Tasks:\n";
+        String str = "Stack Tasks (" + mStackTaskList.size() + "):\n";
         for (Task t : mStackTaskList.getTasks()) {
-            str += "  " + t.toString() + "\n";
+            str += "    " + t.toString() + "\n";
         }
-        str += "Historical Tasks:\n";
+        str += "Historical Tasks(" + mHistoryTaskList.size() + "):\n";
         for (Task t : mHistoryTaskList.getTasks()) {
-            str += "  " + t.toString() + "\n";
+            str += "    " + t.toString() + "\n";
         }
         return str;
     }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/tv/RecentsTvActivity.java b/packages/SystemUI/src/com/android/systemui/recents/tv/RecentsTvActivity.java
index 9450287..dae522f 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/tv/RecentsTvActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/tv/RecentsTvActivity.java
@@ -40,7 +40,6 @@
 import com.android.systemui.recents.events.activity.EnterRecentsWindowLastAnimationFrameEvent;
 import com.android.systemui.recents.events.activity.HideRecentsEvent;
 import com.android.systemui.recents.events.activity.LaunchTaskFailedEvent;
-import com.android.systemui.recents.events.activity.TaskStackUpdatedEvent;
 import com.android.systemui.recents.events.activity.ToggleRecentsEvent;
 import com.android.systemui.recents.events.component.RecentsVisibilityChangedEvent;
 import com.android.systemui.recents.events.ui.AllTaskViewsDismissedEvent;
@@ -60,6 +59,8 @@
 import com.android.systemui.tv.pip.PipManager;
 
 import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
 
 /**
  * The main TV recents activity started by the RecentsImpl.
@@ -97,6 +98,9 @@
 
         @Override
         public void onPipResizeAboutToStart() { }
+
+        @Override
+        public void onMediaControllerChanged() { }
     };
 
     /**
@@ -154,11 +158,13 @@
 
 
         mRecentsView.setTaskStack(stack);
+        List stackTasks = stack.getStackTasks();
+        Collections.reverse(stackTasks);
         if (mTaskStackViewAdapter == null) {
-            mTaskStackViewAdapter = new TaskStackHorizontalViewAdapter(stack.getStackTasks());
+            mTaskStackViewAdapter = new TaskStackHorizontalViewAdapter(stackTasks);
             mRecentsView.setTaskStackViewAdapter(mTaskStackViewAdapter);
         } else {
-            mTaskStackViewAdapter.setNewStackTasks(stack.getStackTasks());
+            mTaskStackViewAdapter.setNewStackTasks(stackTasks);
         }
 
         if (launchState.launchedToTaskId != -1) {
@@ -281,14 +287,14 @@
         RecentsConfiguration config = Recents.getConfiguration();
         RecentsActivityLaunchState launchState = config.getLaunchState();
         boolean wasLaunchedByAm = !launchState.launchedFromHome &&
-                !launchState.launchedFromAppWithThumbnail;
+                !launchState.launchedFromApp;
         if (launchState.launchedHasConfigurationChanged || wasLaunchedByAm) {
             EventBus.getDefault().send(new EnterRecentsWindowAnimationCompletedEvent());
         }
 
         // Notify that recents is now visible
         SystemServicesProxy ssp = Recents.getSystemServices();
-        EventBus.getDefault().send(new RecentsVisibilityChangedEvent(this, ssp, true));
+        EventBus.getDefault().send(new RecentsVisibilityChangedEvent(this, true));
 
         if (mPipManager.isPipShown()) {
             // Place mPipView at the PIP bounds for fine tuned focus handling.
@@ -337,8 +343,7 @@
         mPipManager.removeListener(mPipListener);
         mIgnoreAltTabRelease = false;
         // Notify that recents is now hidden
-        SystemServicesProxy ssp = Recents.getSystemServices();
-        EventBus.getDefault().send(new RecentsVisibilityChangedEvent(this, ssp, false));
+        EventBus.getDefault().send(new RecentsVisibilityChangedEvent(this, false));
 
         // Workaround for b/22542869, if the RecentsActivity is started again, but without going
         // through SystemUI, we need to reset the config launch flags to ensure that we do not
diff --git a/packages/SystemUI/src/com/android/systemui/recents/tv/views/RecentsTvTransitionHelper.java b/packages/SystemUI/src/com/android/systemui/recents/tv/views/RecentsTvTransitionHelper.java
new file mode 100644
index 0000000..ef8d48e
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/recents/tv/views/RecentsTvTransitionHelper.java
@@ -0,0 +1,132 @@
+/*
+ * 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.recents.tv.views;
+
+import android.annotation.Nullable;
+import android.app.ActivityManager;
+import android.app.ActivityOptions;
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.Rect;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.IRemoteCallback;
+import android.os.RemoteException;
+import android.util.Log;
+import android.view.WindowManagerGlobal;
+import com.android.internal.annotations.GuardedBy;
+import com.android.systemui.recents.Recents;
+import com.android.systemui.recents.events.EventBus;
+import com.android.systemui.recents.events.activity.*;
+import com.android.systemui.recents.misc.SystemServicesProxy;
+import com.android.systemui.recents.model.Task;
+import com.android.systemui.recents.model.TaskStack;
+
+
+public class RecentsTvTransitionHelper {
+    private static final String TAG = "RecentsTvTransitionHelper";
+
+    private Context mContext;
+    private Handler mHandler;
+
+    public RecentsTvTransitionHelper(Context context, Handler handler) {
+        mContext = context;
+        mHandler = handler;
+    }
+
+    public void launchTaskFromRecents(final TaskStack stack, @Nullable final Task task,
+            final TaskStackHorizontalGridView stackView, final TaskCardView taskView,
+            final Rect bounds, int destinationStack) {
+        final ActivityOptions opts = ActivityOptions.makeBasic();
+        if (bounds != null) {
+            opts.setLaunchBounds(bounds.isEmpty() ? null : bounds);
+        }
+
+        final ActivityOptions.OnAnimationStartedListener animStartedListener;
+        if (task.thumbnail != null && task.thumbnail.getWidth() > 0 &&
+                task.thumbnail.getHeight() > 0) {
+            animStartedListener = new ActivityOptions.OnAnimationStartedListener() {
+                @Override
+                public void onAnimationStarted() {
+                    // If we are launching into another task, cancel the previous task's
+                    // window transition
+                    EventBus.getDefault().send(new CancelEnterRecentsWindowAnimationEvent(task));
+                    EventBus.getDefault().send(new ExitRecentsWindowFirstAnimationFrameEvent());
+                }
+            };
+        } else {
+            // This is only the case if the task is not on screen (scrolled offscreen for example)
+            animStartedListener = new ActivityOptions.OnAnimationStartedListener() {
+                @Override
+                public void onAnimationStarted() {
+                    EventBus.getDefault().send(new ExitRecentsWindowFirstAnimationFrameEvent());
+                }
+            };
+        }
+
+        if (taskView == null) {
+            // If there is no task view, then we do not need to worry about animating out occluding
+            // task views, and we can launch immediately
+            startTaskActivity(stack, task, taskView, opts, animStartedListener);
+        } else {
+            LaunchTvTaskStartedEvent launchStartedEvent = new LaunchTvTaskStartedEvent(taskView);
+            EventBus.getDefault().send(launchStartedEvent);
+            startTaskActivity(stack, task, taskView, opts, animStartedListener);
+        }
+    }
+
+    private void startTaskActivity(TaskStack stack, Task task, @Nullable TaskCardView taskView,
+            ActivityOptions opts,final ActivityOptions.OnAnimationStartedListener animStartedListener) {
+        SystemServicesProxy ssp = Recents.getSystemServices();
+        if (ssp.startActivityFromRecents(mContext, task.key.id, task.title, opts)) {
+            // Keep track of the index of the task launch
+            int taskIndexFromFront = 0;
+            int taskIndex = stack.indexOfStackTask(task);
+            if (taskIndex > -1) {
+                taskIndexFromFront = stack.getTaskCount() - taskIndex - 1;
+            }
+            EventBus.getDefault().send(new LaunchTaskSucceededEvent(taskIndexFromFront));
+        } else {
+            // Keep track of failed launches
+            EventBus.getDefault().send(new LaunchTaskFailedEvent());
+        }
+
+        IRemoteCallback.Stub callback = null;
+        if (animStartedListener != null) {
+            callback = new IRemoteCallback.Stub() {
+                @Override
+                public void sendResult(Bundle data) throws RemoteException {
+                    mHandler.post(new Runnable() {
+                        @Override
+                        public void run() {
+                            if (animStartedListener != null) {
+                                animStartedListener.onAnimationStarted();
+                            }
+                        }
+                    });
+                }
+            };
+        }
+        try {
+            Rect taskRect = taskView.getGlobalRect();
+            WindowManagerGlobal.getWindowManagerService()
+                    .overridePendingAppTransitionThumb(task.thumbnail, taskRect.left,
+                            taskRect.top, callback, true);
+        } catch (RemoteException e) {
+            Log.w(TAG, "Failed to override transition: " + e);
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/tv/views/RecentsTvView.java b/packages/SystemUI/src/com/android/systemui/recents/tv/views/RecentsTvView.java
index 8e768a2..bf6229c 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/tv/views/RecentsTvView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/tv/views/RecentsTvView.java
@@ -17,6 +17,7 @@
 
 import android.content.Context;
 import android.graphics.Rect;
+import android.os.Handler;
 import android.util.AttributeSet;
 import android.view.LayoutInflater;
 import android.view.View;
@@ -31,7 +32,7 @@
 import com.android.systemui.recents.events.EventBus;
 import com.android.systemui.recents.events.activity.CancelEnterRecentsWindowAnimationEvent;
 import com.android.systemui.recents.events.activity.DismissRecentsToHomeAnimationStarted;
-import com.android.systemui.recents.events.activity.TaskStackUpdatedEvent;
+import com.android.systemui.recents.events.activity.LaunchTvTaskEvent;
 import com.android.systemui.recents.events.component.RecentsVisibilityChangedEvent;
 import com.android.systemui.recents.misc.SystemServicesProxy;
 import com.android.systemui.recents.model.Task;
@@ -53,7 +54,8 @@
     private View mEmptyView;
     private boolean mAwaitingFirstLayout = true;
     private Rect mSystemInsets = new Rect();
-
+    private RecentsTvTransitionHelper mTransitionHelper;
+    private Handler mHandler;
 
     public RecentsTvView(Context context) {
         this(context, null);
@@ -75,6 +77,8 @@
         LayoutInflater inflater = LayoutInflater.from(context);
         mEmptyView = inflater.inflate(R.layout.recents_empty, this, false);
         addView(mEmptyView);
+        mHandler = new Handler();
+        mTransitionHelper = new RecentsTvTransitionHelper(mContext, mHandler);
     }
 
     public void setTaskStack(TaskStack stack) {
@@ -209,6 +213,11 @@
 
     /**** EventBus Events ****/
 
+    public final void onBusEvent(LaunchTvTaskEvent event) {
+        mTransitionHelper.launchTaskFromRecents(mStack, event.task, mTaskStackHorizontalView,
+                event.taskView, event.targetTaskBounds, event.targetTaskStack);
+    }
+
     public final void onBusEvent(DismissRecentsToHomeAnimationStarted event) {
         // If we are going home, cancel the previous task's window transition
         EventBus.getDefault().send(new CancelEnterRecentsWindowAnimationEvent(null));
diff --git a/packages/SystemUI/src/com/android/systemui/recents/tv/views/TaskCardView.java b/packages/SystemUI/src/com/android/systemui/recents/tv/views/TaskCardView.java
index e275f22..7d8a3ce 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/tv/views/TaskCardView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/tv/views/TaskCardView.java
@@ -16,20 +16,20 @@
 package com.android.systemui.recents.tv.views;
 
 import android.content.Context;
+import android.graphics.Rect;
 import android.util.AttributeSet;
 import android.widget.ImageView;
-import android.widget.RelativeLayout;
+import android.widget.LinearLayout;
 import android.widget.TextView;
 
 import com.android.systemui.R;
-import com.android.systemui.recents.model.Task;
 import com.android.systemui.recents.tv.animations.ViewFocusAnimator;
+import com.android.systemui.recents.model.Task;
 
-public class TaskCardView extends RelativeLayout {
+public class TaskCardView extends LinearLayout {
 
     private ImageView mThumbnailView;
     private TextView mTitleTextView;
-    private TextView mContentTextView;
     private ImageView mBadgeView;
     private Task mTask;
 
@@ -52,7 +52,6 @@
     protected void onFinishInflate() {
         mThumbnailView = (ImageView) findViewById(R.id.card_view_thumbnail);
         mTitleTextView = (TextView) findViewById(R.id.card_title_text);
-        mContentTextView = (TextView) findViewById(R.id.card_content_text);
         mBadgeView = (ImageView) findViewById(R.id.card_extra_badge);
     }
 
@@ -60,11 +59,27 @@
         mTask = task;
         mThumbnailView.setImageBitmap(task.thumbnail);
         mTitleTextView.setText(task.title);
-        mContentTextView.setText(task.contentDescription);
         mBadgeView.setImageDrawable(task.icon);
     }
 
     public Task getTask() {
         return mTask;
     }
+
+    @Override
+    public void getFocusedRect(Rect r) {
+        mThumbnailView.getFocusedRect(r);
+    }
+
+    public Rect getFocusedRect() {
+        Rect r = new Rect();
+        getFocusedRect(r);
+        return r;
+    }
+
+    public Rect getGlobalRect() {
+        Rect r = new Rect();
+        getGlobalVisibleRect(r);
+        return r;
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/tv/views/TaskStackHorizontalGridView.java b/packages/SystemUI/src/com/android/systemui/recents/tv/views/TaskStackHorizontalGridView.java
index 58ec852..4458639 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/tv/views/TaskStackHorizontalGridView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/tv/views/TaskStackHorizontalGridView.java
@@ -15,7 +15,6 @@
  */
 package com.android.systemui.recents.tv.views;
 
-
 import android.content.Context;
 import android.support.v17.leanback.widget.HorizontalGridView;
 import android.util.AttributeSet;
@@ -36,13 +35,17 @@
 /**
  * Horizontal Grid View Implementation to show the Task Stack for TV.
  */
-public class TaskStackHorizontalGridView extends HorizontalGridView implements TaskStackCallbacks{
+public class TaskStackHorizontalGridView extends HorizontalGridView implements TaskStackCallbacks {
 
     private TaskStack mStack;
     private ArrayList<TaskCardView> mTaskViews = new ArrayList<>();
     private Task mFocusedTask;
 
 
+    public TaskStackHorizontalGridView(Context context) {
+        this(context, null);
+    }
+
     public TaskStackHorizontalGridView(Context context, AttributeSet attrs) {
         super(context, attrs);
     }
@@ -64,8 +67,6 @@
      * Resets this view for reuse.
      */
     public void reset() {
-        // Reset the focused task
-        resetFocusedTask(getFocusedTask());
         requestLayout();
     }
 
@@ -73,12 +74,6 @@
      * @param task - Task to reset
      */
     private void resetFocusedTask(Task task) {
-        if (task != null) {
-            TaskCardView tv = getChildViewForTask(task);
-            if (tv != null) {
-                tv.requestFocus();
-            }
-        }
         mFocusedTask = null;
     }
 
@@ -107,6 +102,9 @@
      * @return - The focused task.
      */
     public Task getFocusedTask() {
+        if (findFocus() != null) {
+            mFocusedTask = ((TaskCardView)findFocus()).getTask();
+        }
         return mFocusedTask;
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/recents/tv/views/TaskStackHorizontalViewAdapter.java b/packages/SystemUI/src/com/android/systemui/recents/tv/views/TaskStackHorizontalViewAdapter.java
index f154331..fba424e 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/tv/views/TaskStackHorizontalViewAdapter.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/tv/views/TaskStackHorizontalViewAdapter.java
@@ -16,7 +16,6 @@
 package com.android.systemui.recents.tv.views;
 
 import android.app.Activity;
-import android.app.ActivityManagerNative;
 import android.support.v7.widget.RecyclerView;
 import android.util.Log;
 import android.view.LayoutInflater;
@@ -24,15 +23,20 @@
 import android.view.ViewGroup;
 
 import com.android.systemui.R;
+import com.android.systemui.recents.events.EventBus;
+import com.android.systemui.recents.events.activity.LaunchTvTaskEvent;
 import com.android.systemui.recents.model.Task;
 
 import java.util.ArrayList;
 import java.util.List;
 
+import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
+
 public class TaskStackHorizontalViewAdapter extends
         RecyclerView.Adapter<TaskStackHorizontalViewAdapter.ViewHolder> {
 
-    private static final String TAG = "TaskStackHorizontalViewAdapter";
+    //Full class name is 30 characters
+    private static final String TAG = "TaskStackViewAdapter";
     private List<Task> mTaskList;
 
     static class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{
@@ -54,7 +58,8 @@
         @Override
         public void onClick(View v) {
             try {
-                ActivityManagerNative.getDefault().startActivityFromRecents(mTask.key.id, null);
+                EventBus.getDefault().send(new LaunchTvTaskEvent(mTaskCardView, mTask,
+                        null, INVALID_STACK_ID));
                 ((Activity)(v.getContext())).finish();
             } catch (Exception e) {
                 Log.e(TAG, v.getContext()
@@ -73,11 +78,12 @@
         mTaskList.addAll(tasks);
         notifyDataSetChanged();
     }
+
     @Override
     public TaskStackHorizontalViewAdapter.ViewHolder onCreateViewHolder(ViewGroup parent,
             int viewType) {
         View view = LayoutInflater.from(parent.getContext())
-                .inflate(R.layout.recents_task_card_view, parent, false);
+                .inflate(R.layout.recents_tv_task_card_view, parent, false);
         ViewHolder viewHolder = new ViewHolder(view);
         return viewHolder;
     }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/FreeformWorkspaceLayoutAlgorithm.java b/packages/SystemUI/src/com/android/systemui/recents/views/FreeformWorkspaceLayoutAlgorithm.java
index 4359101..72b914c 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/FreeformWorkspaceLayoutAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/FreeformWorkspaceLayoutAlgorithm.java
@@ -37,6 +37,13 @@
     private int mTaskPadding;
 
     public FreeformWorkspaceLayoutAlgorithm(Context context) {
+        reloadOnConfigurationChange(context);
+    }
+
+    /**
+     * Reloads the layout for the current configuration.
+     */
+    public void reloadOnConfigurationChange(Context context) {
         // This is applied to the edges of each task
         mTaskPadding = context.getResources().getDimensionPixelSize(
                 R.dimen.recents_freeform_workspace_task_padding) / 2;
@@ -72,8 +79,7 @@
                 }
                 // Bound the task width to the workspace width so that at the worst case, it will
                 // fit its own row
-                normalizedTaskWidths[i] = Math.min(rowTaskWidth,
-                        normalizedWorkspaceWidth);
+                normalizedTaskWidths[i] = Math.min(rowTaskWidth, normalizedWorkspaceWidth);
             }
 
             // Determine the scale to best fit each of the tasks in the workspace
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsTransitionHelper.java b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsTransitionHelper.java
index 37b2859..a91bbd4 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsTransitionHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsTransitionHelper.java
@@ -122,6 +122,9 @@
             animStartedListener = new ActivityOptions.OnAnimationStartedListener() {
                 @Override
                 public void onAnimationStarted() {
+                    // If we are launching into another task, cancel the previous task's
+                    // window transition
+                    EventBus.getDefault().send(new CancelEnterRecentsWindowAnimationEvent(task));
                     EventBus.getDefault().send(new ExitRecentsWindowFirstAnimationFrameEvent());
                 }
             };
@@ -176,6 +179,7 @@
             // Keep track of failed launches
             EventBus.getDefault().send(new LaunchTaskFailedEvent());
         }
+
         if (transitionFuture != null) {
             IRemoteCallback.Stub callback = null;
             if (animStartedListener != null) {
@@ -276,7 +280,8 @@
             } else {
                 layoutAlgorithm.getStackTransformScreenCoordinates(task, stackScroll, mTmpTransform,
                         null);
-                specs.add(composeAnimationSpec(taskView, mTmpTransform, true /* addHeaderBitmap */));
+                specs.add(composeAnimationSpec(stackView, taskView, mTmpTransform,
+                        true /* addHeaderBitmap */));
             }
             return specs;
         }
@@ -297,7 +302,8 @@
                 } else {
                     layoutAlgorithm.getStackTransformScreenCoordinates(t, stackScroll,
                             mTmpTransform, null);
-                    specs.add(composeAnimationSpec(tv, mTmpTransform, true /* addHeaderBitmap */));
+                    specs.add(composeAnimationSpec(stackView, tv, mTmpTransform,
+                            true /* addHeaderBitmap */));
                 }
             }
         }
@@ -316,8 +322,8 @@
     /**
      * Composes a single animation spec for the given {@link TaskView}
      */
-    private static AppTransitionAnimationSpec composeAnimationSpec(TaskView taskView,
-            TaskViewTransform transform, boolean addHeaderBitmap) {
+    private static AppTransitionAnimationSpec composeAnimationSpec(TaskStackView stackView,
+            TaskView taskView, TaskViewTransform transform, boolean addHeaderBitmap) {
         Bitmap b = null;
         if (addHeaderBitmap) {
             float scale = transform.scale;
@@ -339,6 +345,10 @@
 
         Rect taskRect = new Rect();
         transform.rect.round(taskRect);
+        if (stackView.getStack().getStackFrontMostTask(false /* includeFreeformTasks */) !=
+                taskView.getTask()) {
+            taskRect.bottom = 2 * Recents.getSystemServices().getDisplayRect().height();
+        }
         return new AppTransitionAnimationSpec(taskView.getTask().key.id, b, taskRect);
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
index 5dde926..8342de5 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
@@ -60,9 +60,7 @@
 import com.android.systemui.recents.events.activity.LaunchTaskEvent;
 import com.android.systemui.recents.events.activity.ShowHistoryButtonEvent;
 import com.android.systemui.recents.events.activity.ShowHistoryEvent;
-import com.android.systemui.recents.events.activity.TaskStackUpdatedEvent;
 import com.android.systemui.recents.events.activity.ToggleHistoryEvent;
-import com.android.systemui.recents.events.component.RecentsVisibilityChangedEvent;
 import com.android.systemui.recents.events.ui.DraggingInRecentsEndedEvent;
 import com.android.systemui.recents.events.ui.DraggingInRecentsEvent;
 import com.android.systemui.recents.events.ui.ResetBackgroundScrimEvent;
@@ -168,35 +166,40 @@
     }
 
     /** Set/get the bsp root node */
-    public void setTaskStack(TaskStack stack) {
+    public void onResume(boolean isResumingFromVisible, TaskStack stack) {
         RecentsConfiguration config = Recents.getConfiguration();
         RecentsActivityLaunchState launchState = config.getLaunchState();
-        mStack = stack;
-        if (launchState.launchedReuseTaskStackViews) {
-            if (mTaskStackView != null) {
-                // If onRecentsHidden is not triggered, we need to the stack view again here
-                mTaskStackView.reset();
-                mTaskStackView.setStack(stack);
-            } else {
-                mTaskStackView = new TaskStackView(getContext(), stack);
-                addView(mTaskStackView);
-            }
-        } else {
-            if (mTaskStackView != null) {
-                removeView(mTaskStackView);
-            }
-            mTaskStackView = new TaskStackView(getContext(), stack);
+
+        if (mTaskStackView == null || !launchState.launchedReuseTaskStackViews) {
+            isResumingFromVisible = false;
+            removeView(mTaskStackView);
+            mTaskStackView = new TaskStackView(getContext());
+            mStack = mTaskStackView.getStack();
             addView(mTaskStackView);
         }
 
-        // If we are already occluded by the app, then just set the default background scrim now.
-        // Otherwise, defer until the enter animation completes to animate the scrim with the
-        // tasks for the home animation.
-        if (launchState.launchedWhileDocking || launchState.launchedFromAppWithThumbnail
-                || mStack.getTaskCount() == 0) {
-            mBackgroundScrim.setAlpha((int) (DEFAULT_SCRIM_ALPHA * 255));
+        // Reset the state
+        mAwaitingFirstLayout = !isResumingFromVisible;
+        mLastTaskLaunchedWasFreeform = false;
+
+        // Update the stack
+        mTaskStackView.onResume(isResumingFromVisible);
+        mTaskStackView.setTasks(stack, isResumingFromVisible /* notifyStackChanges */,
+                true /* relayoutTaskStack */);
+
+        if (isResumingFromVisible) {
+            // If we are already visible, then restore the background scrim
+            animateBackgroundScrim(DEFAULT_SCRIM_ALPHA, DEFAULT_UPDATE_SCRIM_DURATION);
         } else {
-            mBackgroundScrim.setAlpha(0);
+            // If we are already occluded by the app, then set the final background scrim alpha now.
+            // Otherwise, defer until the enter animation completes to animate the scrim alpha with
+            // the tasks for the home animation.
+            if (launchState.launchedWhileDocking || launchState.launchedFromApp
+                    || mStack.getTaskCount() == 0) {
+                mBackgroundScrim.setAlpha((int) (DEFAULT_SCRIM_ALPHA * 255));
+            } else {
+                mBackgroundScrim.setAlpha(0);
+            }
         }
 
         // Update the top level view's visibilities
@@ -205,9 +208,6 @@
         } else {
             showEmptyView();
         }
-
-        // Trigger a new layout
-        requestLayout();
     }
 
     /**
@@ -662,16 +662,9 @@
         animator.start();
     }
 
-    public final void onBusEvent(TaskStackUpdatedEvent event) {
-        if (!event.inMultiWindow) {
-            mStack.setTasks(event.stack.computeAllTasksList(), true /* notifyStackChanges */);
-            mStack.createAffiliatedGroupings(getContext());
-        }
-    }
-
     public final void onBusEvent(EnterRecentsWindowAnimationCompletedEvent event) {
         RecentsActivityLaunchState launchState = Recents.getConfiguration().getLaunchState();
-        if (!launchState.launchedWhileDocking && !launchState.launchedFromAppWithThumbnail
+        if (!launchState.launchedWhileDocking && !launchState.launchedFromApp
                 && mStack.getTaskCount() > 0) {
             animateBackgroundScrim(DEFAULT_SCRIM_ALPHA,
                     TaskStackAnimationHelper.ENTER_FROM_HOME_TRANSLATION_DURATION);
@@ -686,17 +679,6 @@
         animateBackgroundScrim(DEFAULT_SCRIM_ALPHA, DEFAULT_UPDATE_SCRIM_DURATION);
     }
 
-    public final void onBusEvent(RecentsVisibilityChangedEvent event) {
-        if (!event.visible) {
-            // Reset the view state
-            mAwaitingFirstLayout = true;
-            mLastTaskLaunchedWasFreeform = false;
-            if (RecentsDebugFlags.Static.EnableHistory) {
-                hideHistoryButton(0, false /* translate */);
-            }
-        }
-    }
-
     public final void onBusEvent(ToggleHistoryEvent event) {
         if (!RecentsDebugFlags.Static.EnableHistory) {
             return;
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsViewTouchHandler.java b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsViewTouchHandler.java
index 079d7b9..84590f2 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsViewTouchHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsViewTouchHandler.java
@@ -16,6 +16,7 @@
 
 package com.android.systemui.recents.views;
 
+import android.app.ActivityManager;
 import android.content.res.Configuration;
 import android.graphics.Point;
 import android.view.MotionEvent;
@@ -149,7 +150,8 @@
         mTaskView.setTranslationY(y);
 
         mVisibleDockStates.clear();
-        if (!ssp.hasDockedTask() && mRv.getTaskStack().getTaskCount() > 1) {
+        if (ActivityManager.supportsMultiWindow() &&
+                !ssp.hasDockedTask() && mRv.getTaskStack().getTaskCount() > 1) {
             if (!event.task.isDockable) {
                 Toast.makeText(mRv.getContext(), R.string.recents_drag_non_dockable_task_message,
                         Toast.LENGTH_SHORT).show();
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/SystemBarScrimViews.java b/packages/SystemUI/src/com/android/systemui/recents/views/SystemBarScrimViews.java
index 1cd0850..19b219a 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/SystemBarScrimViews.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/SystemBarScrimViews.java
@@ -16,9 +16,11 @@
 
 package com.android.systemui.recents.views;
 
+import android.animation.AnimatorListenerAdapter;
 import android.app.Activity;
 import android.content.Context;
 import android.view.View;
+import android.view.ViewPropertyAnimator;
 
 import com.android.systemui.Interpolators;
 import com.android.systemui.R;
@@ -56,25 +58,41 @@
                 View.VISIBLE : View.INVISIBLE);
     }
 
+    /**
+     * Animates the nav bar scrim visibility.
+     */
+    public void animateNavBarScrimVisibility(boolean visible, AnimationProps animation) {
+        int toY = 0;
+        if (visible) {
+            mNavBarScrimView.setVisibility(View.VISIBLE);
+            mNavBarScrimView.setTranslationY(mNavBarScrimView.getMeasuredHeight());
+        } else {
+            toY = mNavBarScrimView.getMeasuredHeight();
+        }
+        if (animation != AnimationProps.IMMEDIATE) {
+            mNavBarScrimView.animate()
+                    .translationY(toY)
+                    .setDuration(animation.getDuration(AnimationProps.BOUNDS))
+                    .setInterpolator(animation.getInterpolator(AnimationProps.BOUNDS))
+                    .start();
+        } else {
+            mNavBarScrimView.setTranslationY(toY);
+        }
+    }
+
     /**** EventBus events ****/
 
     /**
      * Starts animating the scrim views when entering Recents.
      */
     public final void onBusEvent(EnterRecentsWindowAnimationCompletedEvent event) {
-        if (mHasNavBarScrim && mShouldAnimateNavBarScrim) {
-            mNavBarScrimView.setTranslationY(mNavBarScrimView.getMeasuredHeight());
-            mNavBarScrimView.animate()
-                    .translationY(0)
-                    .setDuration(mNavBarScrimEnterDuration)
-                    .setInterpolator(Interpolators.DECELERATE_QUINT)
-                    .withStartAction(new Runnable() {
-                        @Override
-                        public void run() {
-                            mNavBarScrimView.setVisibility(View.VISIBLE);
-                        }
-                    })
-                    .start();
+        if (mHasNavBarScrim) {
+            AnimationProps animation = mShouldAnimateNavBarScrim
+                    ? new AnimationProps()
+                            .setDuration(AnimationProps.BOUNDS, mNavBarScrimEnterDuration)
+                            .setInterpolator(AnimationProps.BOUNDS, Interpolators.DECELERATE_QUINT)
+                    : AnimationProps.IMMEDIATE;
+            animateNavBarScrimVisibility(true, animation);
         }
     }
 
@@ -83,13 +101,12 @@
      * going home).
      */
     public final void onBusEvent(DismissRecentsToHomeAnimationStarted event) {
-        if (mHasNavBarScrim && mShouldAnimateNavBarScrim) {
-            mNavBarScrimView.animate()
-                    .translationY(mNavBarScrimView.getMeasuredHeight())
-                    .setStartDelay(0)
-                    .setDuration(TaskStackAnimationHelper.EXIT_TO_HOME_TRANSLATION_DURATION)
-                    .setInterpolator(Interpolators.FAST_OUT_SLOW_IN)
-                    .start();
+        if (mHasNavBarScrim) {
+            AnimationProps animation = new AnimationProps()
+                    .setDuration(AnimationProps.BOUNDS,
+                            TaskStackAnimationHelper.EXIT_TO_HOME_TRANSLATION_DURATION)
+                    .setInterpolator(AnimationProps.BOUNDS, Interpolators.FAST_OUT_SLOW_IN);
+            animateNavBarScrimVisibility(false, animation);
         }
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackAnimationHelper.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackAnimationHelper.java
index 2cd0c19..b36d5d1 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackAnimationHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackAnimationHelper.java
@@ -20,8 +20,8 @@
 import android.animation.AnimatorListenerAdapter;
 import android.content.Context;
 import android.content.res.Resources;
-import android.graphics.Path;
 import android.graphics.RectF;
+import android.util.Log;
 import android.view.View;
 import android.view.animation.Interpolator;
 import android.view.animation.PathInterpolator;
@@ -56,8 +56,8 @@
         /**
          * Callback to start the animation for the launch target {@link TaskView}.
          */
-        void onStartLaunchTargetEnterAnimation(int duration, boolean screenPinningEnabled,
-                ReferenceCountedTrigger postAnimationTrigger);
+        void onStartLaunchTargetEnterAnimation(TaskViewTransform transform, int duration,
+                boolean screenPinningEnabled, ReferenceCountedTrigger postAnimationTrigger);
 
         /**
          * Callback to start the animation for the launch target {@link TaskView} when it is
@@ -71,6 +71,8 @@
 
     public static final int ENTER_FROM_HOME_ALPHA_DURATION = 100;
     public static final int ENTER_FROM_HOME_TRANSLATION_DURATION = 333;
+    public static final int ENTER_WHILE_DOCKING_DURATION = 150;
+
     private static final PathInterpolator ENTER_FROM_HOME_TRANSLATION_INTERPOLATOR =
             new PathInterpolator(0, 0, 0, 1f);
     private static final PathInterpolator ENTER_FROM_HOME_ALPHA_INTERPOLATOR =
@@ -90,6 +92,9 @@
     private static final PathInterpolator FOCUS_BEHIND_NEXT_TASK_INTERPOLATOR =
             new PathInterpolator(0.4f, 0, 0.2f, 1f);
 
+    private static final PathInterpolator ENTER_WHILE_DOCKING_INTERPOLATOR =
+            new PathInterpolator(0, 0, 0.2f, 1f);
+
     private TaskStackView mStackView;
 
     private TaskViewTransform mTmpTransform = new TaskViewTransform();
@@ -122,6 +127,8 @@
         int offscreenYOffset = stackLayout.mStackRect.height();
         int taskViewAffiliateGroupEnterOffset = res.getDimensionPixelSize(
                 R.dimen.recents_task_view_affiliate_group_enter_offset);
+        int launchedWhileDockingOffset = res.getDimensionPixelSize(
+                R.dimen.recents_task_view_launched_while_docking_offset);
 
         // Prepare each of the task views for their enter animation from front to back
         List<TaskView> taskViews = mStackView.getTaskViews();
@@ -141,7 +148,7 @@
                 tv.setVisibility(View.INVISIBLE);
             } else if (launchState.launchedHasConfigurationChanged) {
                 // Just load the views as-is
-            } else if (launchState.launchedFromAppWithThumbnail) {
+            } else if (launchState.launchedFromApp && !launchState.launchedWhileDocking) {
                 if (task.isLaunchTarget) {
                     tv.onPrepareLaunchTargetForEnterAnimation();
                 } else if (currentTaskOccludesLaunchTarget) {
@@ -159,6 +166,11 @@
                 bounds.offset(0, offscreenYOffset);
                 tv.setLeftTopRightBottom((int) bounds.left, (int) bounds.top, (int) bounds.right,
                         (int) bounds.bottom);
+            } else if (launchState.launchedWhileDocking) {
+                RectF bounds = new RectF(mTmpTransform.rect);
+                bounds.offset(0, launchedWhileDockingOffset);
+                tv.setLeftTopRightBottom((int) bounds.left, (int) bounds.top, (int) bounds.right,
+                        (int) bounds.bottom);
             }
         }
     }
@@ -192,6 +204,7 @@
         int taskViewCount = taskViews.size();
         for (int i = taskViewCount - 1; i >= 0; i--) {
             int taskIndexFromFront = taskViewCount - i - 1;
+            int taskIndexFromBack = i;
             final TaskView tv = taskViews.get(i);
             Task task = tv.getTask();
             boolean currentTaskOccludesLaunchTarget = false;
@@ -205,10 +218,11 @@
             stackLayout.getStackTransform(task, stackScroller.getStackScroll(), mTmpTransform,
                     null);
 
-            if (launchState.launchedFromAppWithThumbnail) {
+            if (launchState.launchedFromApp && !launchState.launchedWhileDocking) {
                 if (task.isLaunchTarget) {
-                    tv.onStartLaunchTargetEnterAnimation(taskViewEnterFromAppDuration,
-                            mStackView.mScreenPinningEnabled, postAnimationTrigger);
+                    tv.onStartLaunchTargetEnterAnimation(mTmpTransform,
+                            taskViewEnterFromAppDuration, mStackView.mScreenPinningEnabled,
+                            postAnimationTrigger);
                 } else {
                     // Animate the task up if it was occluding the launch target
                     if (currentTaskOccludesLaunchTarget) {
@@ -240,6 +254,16 @@
                         .setListener(postAnimationTrigger.decrementOnAnimationEnd());
                 postAnimationTrigger.increment();
                 mStackView.updateTaskViewToTransform(tv, mTmpTransform, taskAnimation);
+            } else if (launchState.launchedWhileDocking) {
+                // Animate the tasks up
+                AnimationProps taskAnimation = new AnimationProps()
+                        .setDuration(AnimationProps.BOUNDS, (int) (ENTER_WHILE_DOCKING_DURATION +
+                                                        (taskIndexFromBack * 2f * FRAME_OFFSET_MS)))
+                        .setInterpolator(AnimationProps.BOUNDS,
+                                ENTER_WHILE_DOCKING_INTERPOLATOR)
+                        .setListener(postAnimationTrigger.decrementOnAnimationEnd());
+                postAnimationTrigger.increment();
+                mStackView.updateTaskViewToTransform(tv, mTmpTransform, taskAnimation);
             }
         }
     }
@@ -441,11 +465,13 @@
         TaskStackViewScroller stackScroller = mStackView.getScroller();
         TaskStack stack = mStackView.getStack();
 
+        final float curScroll = stackScroller.getStackScroll();
         final float newScroll = stackLayout.getStackScrollForTask(newFocusedTask);
-        boolean willScrollToFront = newScroll > stackScroller.getStackScroll();
-        boolean willScroll = Float.compare(newScroll, stackScroller.getStackScroll()) != 0;
+        boolean willScrollToFront = newScroll > curScroll;
+        boolean willScroll = Float.compare(newScroll, curScroll) != 0;
 
         // Get the current set of task transforms
+        int taskViewCount = mStackView.getTaskViews().size();
         ArrayList<Task> stackTasks = stack.getStackTasks();
         mStackView.getCurrentTaskTransforms(stackTasks, mTmpCurrentTaskTransforms);
 
@@ -463,6 +489,13 @@
 
         // Focus the task view
         TaskView newFocusedTaskView = mStackView.getChildViewForTask(newFocusedTask);
+        if (newFocusedTaskView == null) {
+            // Log the error if we have no task view, and skip the animation
+            Log.e("TaskStackAnimationHelper", "b/27389156 null-task-view prebind:" + taskViewCount +
+                    " postbind:" + mStackView.getTaskViews().size() + " prescroll:" + curScroll +
+                    " postscroll: " + newScroll);
+            return false;
+        }
         newFocusedTaskView.setFocusedState(true, requestViewFocus);
 
         // Setup the end listener to return all the hidden views to the view pool after the
@@ -476,7 +509,7 @@
         });
 
         List<TaskView> taskViews = mStackView.getTaskViews();
-        int taskViewCount = taskViews.size();
+        taskViewCount = taskViews.size();
         int newFocusTaskViewIndex = taskViews.indexOf(newFocusedTaskView);
         for (int i = 0; i < taskViewCount; i++) {
             TaskView tv = taskViews.get(i);
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java
index 261b6f6..6df5884 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java
@@ -29,6 +29,7 @@
 import com.android.systemui.recents.Recents;
 import com.android.systemui.recents.RecentsActivityLaunchState;
 import com.android.systemui.recents.RecentsConfiguration;
+import com.android.systemui.recents.RecentsDebugFlags;
 import com.android.systemui.recents.misc.FreePathInterpolator;
 import com.android.systemui.recents.misc.SystemServicesProxy;
 import com.android.systemui.recents.misc.Utilities;
@@ -36,6 +37,7 @@
 import com.android.systemui.recents.model.TaskStack;
 
 import java.util.ArrayList;
+import java.util.List;
 
 /**
  * Used to describe a visible range that can be normalized to [0, 1].
@@ -220,6 +222,12 @@
     private Range mUnfocusedRange;
     private Range mFocusedRange;
 
+    // The initial offset from the top and bottom of the stack
+    @ViewDebug.ExportedProperty(category="recents")
+    private int mInitialTopPeekHeight;
+    @ViewDebug.ExportedProperty(category="recents")
+    private int mInitialBottomPeekHeight;
+
     // The offset from the top when scrolled to the top of the stack
     @ViewDebug.ExportedProperty(category="recents")
     private int mFocusedTopPeekHeight;
@@ -231,6 +239,10 @@
     @ViewDebug.ExportedProperty(category="recents")
     private int mStackTopOffset;
 
+    // The height of the header bar
+    @ViewDebug.ExportedProperty(category="recents")
+    private int mHeaderBarHeight;
+
     // The offset from the bottom of the stack to the bottom of the bounds when the stack is
     // scrolled to the front
     @ViewDebug.ExportedProperty(category="recents")
@@ -249,6 +261,9 @@
     private FreePathInterpolator mUnfocusedDimCurveInterpolator;
     private FreePathInterpolator mFocusedDimCurveInterpolator;
 
+    // Indexed from the front of the stack, the normalized x in the unfocused range for each task
+    private float[] mInitialNormX;
+
     // The state of the stack focus (0..1), which controls the transition of the stack from the
     // focused to non-focused state
     @ViewDebug.ExportedProperty(category="recents")
@@ -292,23 +307,34 @@
     TaskViewTransform mFrontOfStackTransform = new TaskViewTransform();
 
     public TaskStackLayoutAlgorithm(Context context, TaskStackLayoutAlgorithmCallbacks cb) {
-        Resources res = context.getResources();
         mContext = context;
         mCb = cb;
+        mFreeformLayoutAlgorithm = new FreeformWorkspaceLayoutAlgorithm(context);
+        reloadOnConfigurationChange(context);
+    }
 
+    /**
+     * Reloads the layout for the current configuration.
+     */
+    public void reloadOnConfigurationChange(Context context) {
+        Resources res = context.getResources();
         mFocusedRange = new Range(res.getFloat(R.integer.recents_layout_focused_range_min),
                 res.getFloat(R.integer.recents_layout_focused_range_max));
         mUnfocusedRange = new Range(res.getFloat(R.integer.recents_layout_unfocused_range_min),
                 res.getFloat(R.integer.recents_layout_unfocused_range_max));
-        mFocusState = getDefaultFocusState();
+        mFocusState = getInitialFocusState();
+        mInitialTopPeekHeight = res.getDimensionPixelSize(R.dimen.recents_initial_top_peek_size);
+        mInitialBottomPeekHeight =
+                res.getDimensionPixelSize(R.dimen.recents_initial_bottom_peek_size);
         mFocusedTopPeekHeight =
                 res.getDimensionPixelSize(R.dimen.recents_layout_focused_top_peek_size);
         mFocusedBottomTaskPeekHeight =
                 res.getDimensionPixelSize(R.dimen.recents_layout_focused_bottom_task_peek_size);
+        mHeaderBarHeight = res.getDimensionPixelSize(R.dimen.recents_task_bar_height);
 
         mMinTranslationZ = res.getDimensionPixelSize(R.dimen.recents_task_view_z_min);
         mMaxTranslationZ = res.getDimensionPixelSize(R.dimen.recents_task_view_z_max);
-        mFreeformLayoutAlgorithm = new FreeformWorkspaceLayoutAlgorithm(context);
+        mFreeformLayoutAlgorithm.reloadOnConfigurationChange(context);
     }
 
     /**
@@ -316,7 +342,7 @@
      */
     public void reset() {
         mTaskIndexOverrideMap.clear();
-        setFocusState(getDefaultFocusState());
+        setFocusState(getInitialFocusState());
     }
 
     /**
@@ -439,46 +465,89 @@
             mTaskIndexMap.put(task.key.id, i);
         }
 
-        // Calculate the min/max scroll
-        if (getDefaultFocusState() > 0f) {
-            mMinScrollP = 0;
-            mMaxScrollP = Math.max(mMinScrollP, mNumStackTasks - 1);
-        } else {
-            if (!ssp.hasFreeformWorkspaceSupport() && mNumStackTasks == 1) {
-                mMinScrollP = mMaxScrollP = 0;
-            } else {
-                float bottomOffsetPct = (float) (mStackBottomOffset + mTaskRect.height()) /
-                        mStackRect.height();
-                float normX = mUnfocusedCurveInterpolator.getX(bottomOffsetPct);
-                mMinScrollP = 0;
-                mMaxScrollP = Math.max(mMinScrollP, (mNumStackTasks - 1) -
-                        Math.max(0, mUnfocusedRange.getAbsoluteX(normX)));
-            }
-        }
-
+        // Update the freeform tasks
         if (!freeformTasks.isEmpty()) {
             mFreeformLayoutAlgorithm.update(freeformTasks, this);
-            mInitialScrollP = mMaxScrollP;
-        } else {
-            Task launchTask = stack.getLaunchTarget();
-            int launchTaskIndex = launchTask != null
-                    ? stack.indexOfStackTask(launchTask)
-                    : mNumStackTasks - 1;
-            if (!ssp.hasFreeformWorkspaceSupport() && mNumStackTasks == 1) {
-                mInitialScrollP = mMinScrollP;
-            } else if (getDefaultFocusState() > 0f) {
-                if (launchState.launchedFromHome) {
-                    mInitialScrollP = Utilities.clamp(launchTaskIndex, mMinScrollP, mMaxScrollP);
-                } else {
-                    mInitialScrollP = Utilities.clamp(launchTaskIndex - 1, mMinScrollP,
-                            mMaxScrollP);
-                }
+        }
+
+        // Calculate the min/max/initial scroll
+        Task launchTask = stack.getLaunchTarget();
+        int launchTaskIndex = launchTask != null
+                ? stack.indexOfStackTask(launchTask)
+                : mNumStackTasks - 1;
+        if (getInitialFocusState() == STATE_FOCUSED) {
+            mMinScrollP = 0;
+            mMaxScrollP = Math.max(mMinScrollP, mNumStackTasks - 1);
+            if (launchState.launchedFromHome) {
+                mInitialScrollP = Utilities.clamp(launchTaskIndex, mMinScrollP, mMaxScrollP);
             } else {
-                float offsetPct = (float) (mTaskRect.height() / 3) / mStackRect.height();
-                float normX = mUnfocusedCurveInterpolator.getX(offsetPct);
-                mInitialScrollP = Utilities.clamp(launchTaskIndex -
-                        mUnfocusedRange.getAbsoluteX(normX), mMinScrollP, mMaxScrollP);
+                mInitialScrollP = Utilities.clamp(launchTaskIndex - 1, mMinScrollP, mMaxScrollP);
             }
+        } else if (!ssp.hasFreeformWorkspaceSupport() && mNumStackTasks == 1) {
+            // If there is one stack task, ignore the min/max/initial scroll positions
+            mMinScrollP = 0;
+            mMaxScrollP = 0;
+            mInitialScrollP = 0;
+        } else {
+            // Set the max scroll to be the point where the front most task is visible with the
+            // stack bottom offset
+            int maxBottomOffset = mStackBottomOffset + mTaskRect.height();
+            float maxBottomOffsetPct = (float) maxBottomOffset / mStackRect.height();
+            float maxBottomNormX = mUnfocusedCurveInterpolator.getX(maxBottomOffsetPct);
+            mUnfocusedRange.offset(0f);
+            mMinScrollP = 0;
+            mMaxScrollP = Math.max(mMinScrollP, (mNumStackTasks - 1) -
+                    Math.max(0, mUnfocusedRange.getAbsoluteX(maxBottomNormX)));
+            boolean scrollToFront = launchState.launchedFromHome ||
+                    launchState.launchedFromAppDocked;
+            if (scrollToFront) {
+                mInitialScrollP = Utilities.clamp(launchTaskIndex, mMinScrollP, mMaxScrollP);
+            } else {
+                mInitialScrollP = Utilities.clamp(launchTaskIndex - 1, mMinScrollP, mMaxScrollP);
+            }
+
+            // Set the initial scroll to the predefined state (which differs from the stack)
+            int initialPeekOffset = mStackRect.height() - mInitialTopPeekHeight;
+            float initialPeekOffsetPct = (float) initialPeekOffset / mStackRect.height();
+            float initialPeekOffsetNormX = mUnfocusedCurveInterpolator.getX(initialPeekOffsetPct);
+            float initialFocusedOffset = mStackRect.height() - mInitialTopPeekHeight -
+                    (mHeaderBarHeight * 1f) + 1;
+            float initialFocusedOffsetPct = initialFocusedOffset / mStackRect.height();
+            float initialFocusedNormX = mUnfocusedCurveInterpolator.getX(initialFocusedOffsetPct);
+            float initialBottomOffset = mStackBottomOffset +
+                    (ssp.hasDockedTask()
+                        ? mHeaderBarHeight
+                        : mInitialBottomPeekHeight);
+            float initialBottomOffsetPct = initialBottomOffset / mStackRect.height();
+            float initialBottomNormX = mUnfocusedCurveInterpolator.getX(initialBottomOffsetPct);
+            /*
+            // If we want to offset the top card slightly
+            mInitialNormX = scrollToFront
+                    ? new float[] { initialFocusedNormX, initialPeekOffsetNormX, 0f }
+                    : new float[] { initialBottomNormX, initialFocusedNormX,
+                            initialPeekOffsetNormX, 0f };
+            */
+            mInitialNormX = scrollToFront
+                    ? new float[] { initialFocusedNormX, initialPeekOffsetNormX, 0f }
+                    : new float[] { initialBottomNormX, 0.5f, 0f };
+        }
+    }
+
+    public void updateToInitialState(List<Task> tasks) {
+        if (mInitialNormX == null) {
+            return;
+        }
+
+        mUnfocusedRange.offset(0f);
+        int taskCount = tasks.size();
+        for (int i = taskCount - 1; i >= 0; i--) {
+            int indexFromFront = taskCount - i - 1;
+            if (indexFromFront >= mInitialNormX.length) {
+                break;
+            }
+            float newTaskProgress = mInitialScrollP +
+                    mUnfocusedRange.getAbsoluteX(mInitialNormX[indexFromFront]);
+            mTaskIndexOverrideMap.put(tasks.get(i).key.id, newTaskProgress);
         }
     }
 
@@ -500,10 +569,18 @@
         }
     }
 
+    public void clearUnfocusedTaskOverrides() {
+        mTaskIndexOverrideMap.clear();
+    }
+
     /**
      * Updates this stack when a scroll happens.
      */
     public void updateFocusStateOnScroll(float stackScroll, float deltaScroll) {
+        if (deltaScroll == 0f) {
+            return;
+        }
+
         for (int i = mTaskIndexOverrideMap.size() - 1; i >= 0; i--) {
             int taskId = mTaskIndexOverrideMap.keyAt(i);
             float x = mTaskIndexMap.get(taskId);
@@ -523,7 +600,7 @@
             } else {
                 // Scrolling override x away from x, we should still move the scroll towards x
                 float deltaX = overrideX - x;
-                newOverrideX = Math.signum(deltaX) * (Math.abs(deltaX) - deltaScroll);
+                newOverrideX = Math.signum(deltaX) * (Math.abs(deltaX) - Math.abs(deltaScroll));
                 mTaskIndexOverrideMap.put(taskId, x + newOverrideX);
             }
         }
@@ -532,8 +609,13 @@
     /**
      * Returns the default focus state.
      */
-    public int getDefaultFocusState() {
-        return STATE_FOCUSED;
+    public int getInitialFocusState() {
+        RecentsDebugFlags debugFlags = Recents.getDebugFlags();
+        if (debugFlags.isPagingEnabled()) {
+            return STATE_FOCUSED;
+        } else {
+            return STATE_UNFOCUSED;
+        }
     }
 
     /**
@@ -559,6 +641,13 @@
     }
 
     /**
+     * Returns whether this stack layout has been initialized.
+     */
+    public boolean isInitialized() {
+        return !mStackRect.isEmpty();
+    }
+
+    /**
      * Computes the maximum number of visible tasks and thumbnails when the scroll is at the initial
      * stack scroll.  Requires that update() is called first.
      */
@@ -577,7 +666,7 @@
         // Otherwise, walk backwards in the stack and count the number of tasks and visible
         // thumbnails and add that to the total freeform task count
         TaskViewTransform tmpTransform = new TaskViewTransform();
-        Range currentRange = getDefaultFocusState() > 0f ? mFocusedRange : mUnfocusedRange;
+        Range currentRange = getInitialFocusState() > 0f ? mFocusedRange : mUnfocusedRange;
         currentRange.offset(mInitialScrollP);
         int taskBarHeight = mContext.getResources().getDimensionPixelSize(
                 R.dimen.recents_task_bar_height);
@@ -600,8 +689,9 @@
 
             boolean isFrontMostTaskInGroup = task.group == null || task.group.isFrontMostTask(task);
             if (isFrontMostTaskInGroup) {
-                getStackTransform(taskProgress, mInitialScrollP, mFocusState, tmpTransform, null,
-                        false /* ignoreSingleTaskCase */, false /* forceUpdate */);
+                getStackTransform(taskProgress, taskProgress, mInitialScrollP, mFocusState,
+                        tmpTransform, null, false /* ignoreSingleTaskCase */,
+                        false /* forceUpdate */);
                 float screenY = tmpTransform.rect.top;
                 boolean hasVisibleThumbnail = (prevScreenY - screenY) > taskBarHeight;
                 if (hasVisibleThumbnail) {
@@ -635,23 +725,34 @@
     public TaskViewTransform getStackTransform(Task task, float stackScroll,
             TaskViewTransform transformOut, TaskViewTransform frontTransform) {
         return getStackTransform(task, stackScroll, mFocusState, transformOut, frontTransform,
-                false /* forceUpdate */);
+                false /* forceUpdate */, false /* ignoreTaskOverrides */);
+    }
+
+    public TaskViewTransform getStackTransform(Task task, float stackScroll,
+            TaskViewTransform transformOut, TaskViewTransform frontTransform,
+            boolean ignoreTaskOverrides) {
+        return getStackTransform(task, stackScroll, mFocusState, transformOut, frontTransform,
+                false /* forceUpdate */, ignoreTaskOverrides);
     }
 
     public TaskViewTransform getStackTransform(Task task, float stackScroll, int focusState,
-        TaskViewTransform transformOut, TaskViewTransform frontTransform, boolean forceUpdate) {
+            TaskViewTransform transformOut, TaskViewTransform frontTransform, boolean forceUpdate,
+            boolean ignoreTaskOverrides) {
         if (mFreeformLayoutAlgorithm.isTransformAvailable(task, this)) {
             mFreeformLayoutAlgorithm.getTransform(task, transformOut, this);
             return transformOut;
         } else {
             // Return early if we have an invalid index
-            if (task == null || mTaskIndexMap.get(task.key.id, -1) == -1) {
+            int nonOverrideTaskProgress = mTaskIndexMap.get(task.key.id, -1);
+            if (task == null || nonOverrideTaskProgress == -1) {
                 transformOut.reset();
                 return transformOut;
             }
-            float taskProgress = getStackScrollForTask(task);
-            getStackTransform(taskProgress, stackScroll, focusState, transformOut,
-                    frontTransform, false /* ignoreSingleTaskCase */, forceUpdate);
+            float taskProgress = ignoreTaskOverrides
+                    ? nonOverrideTaskProgress
+                    : getStackScrollForTask(task);
+            getStackTransform(taskProgress, nonOverrideTaskProgress, stackScroll, focusState,
+                    transformOut, frontTransform, false /* ignoreSingleTaskCase */, forceUpdate);
             return transformOut;
         }
     }
@@ -676,9 +777,9 @@
      *                             internally to ensure that we can calculate the transform for any
      *                             position in the stack.
      */
-    public void getStackTransform(float taskProgress, float stackScroll, int focusState,
-            TaskViewTransform transformOut, TaskViewTransform frontTransform,
-            boolean ignoreSingleTaskCase, boolean forceUpdate) {
+    public void getStackTransform(float taskProgress, float nonOverrideTaskProgress,
+            float stackScroll, int focusState, TaskViewTransform transformOut,
+            TaskViewTransform frontTransform, boolean ignoreSingleTaskCase, boolean forceUpdate) {
         SystemServicesProxy ssp = Recents.getSystemServices();
 
         // Compute the focused and unfocused offset
@@ -687,6 +788,8 @@
         mFocusedRange.offset(boundedStackScroll);
         float boundedScrollUnfocusedRangeX = mUnfocusedRange.getNormalizedX(taskProgress);
         float boundedScrollFocusedRangeX = mFocusedRange.getNormalizedX(taskProgress);
+        float boundedScrollUnfocusedNonOverrideRangeX =
+                mUnfocusedRange.getNormalizedX(nonOverrideTaskProgress);
         mUnfocusedRange.offset(stackScroll);
         mFocusedRange.offset(stackScroll);
         boolean unfocusedVisible = mUnfocusedRange.isInRange(taskProgress);
@@ -730,7 +833,7 @@
 
             y = (mStackRect.top - mTaskRect.top) +
                     (int) Utilities.mapRange(focusState, unfocusedY, focusedY);
-            z = Utilities.mapRange(Utilities.clamp01(boundedScrollUnfocusedRangeX),
+            z = Utilities.mapRange(Utilities.clamp01(boundedScrollUnfocusedNonOverrideRangeX),
                     mMinTranslationZ, mMaxTranslationZ);
             dimAlpha = Utilities.mapRange(focusState, unfocusedDim, focusedDim);
             viewOutlineAlpha = Utilities.mapRange(Utilities.clamp01(boundedScrollUnfocusedRangeX),
@@ -820,11 +923,11 @@
         float peekHeightPct = (float) mFocusedTopPeekHeight / mStackRect.height();
         float slope = ((1f - peekHeightPct) - cpoint1Y) / (0.5f - cpoint1X);
         float b = 1f - slope * cpoint1X;
-        float cpoint2X = 0.75f;
+        float cpoint2X = 0.65f;
         float cpoint2Y = slope * cpoint2X + b;
         Path p = new Path();
         p.moveTo(0f, 1f);
-        p.cubicTo(0f, 1f, cpoint1X, 1f, 0.5f, 1f - peekHeightPct);
+        p.cubicTo(0f, 1f, cpoint1X, cpoint1Y, 0.5f, 1f - peekHeightPct);
         p.cubicTo(0.5f, 1f - peekHeightPct, cpoint2X, cpoint2Y, 1f, 0f);
         return p;
     }
@@ -851,8 +954,8 @@
         // The unfocused dim interpolator starts at max dim, reduces to zero at 0.5 (the focused
         // task), then goes back to max dim towards the front of the stack
         p.moveTo(0f, MAX_DIM);
-        p.cubicTo(0f, 0.1f, 0.4f, 0f, 0.5f, 0f);
-        p.cubicTo(0.6f, 0f, 0.9f, MAX_DIM - 0.1f, 1f, MAX_DIM / 2f);
+        p.cubicTo(0.1f, MAX_DIM, 0.4f, 0.0f, 0.5f, 0f);
+        p.cubicTo(0.6f, 0f, 0.9f, MAX_DIM / 2f, 1f, MAX_DIM / 2f);
         return p;
     }
 
@@ -870,9 +973,9 @@
                 mFocusedRange.relativeMin);
         float max = Utilities.mapRange(mFocusState, mUnfocusedRange.relativeMax,
                 mFocusedRange.relativeMax);
-        getStackTransform(min, 0f, mFocusState, mBackOfStackTransform, null,
+        getStackTransform(min, min, 0f, mFocusState, mBackOfStackTransform, null,
                 true /* ignoreSingleTaskCase */, true /* forceUpdate */);
-        getStackTransform(max, 0f, mFocusState, mFrontOfStackTransform, null,
+        getStackTransform(max, max, 0f, mFocusState, mFrontOfStackTransform, null,
                 true /* ignoreSingleTaskCase */, true /* forceUpdate */);
         mBackOfStackTransform.visible = true;
         mFrontOfStackTransform.visible = true;
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
index e1a81c8..e2830a1 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
@@ -35,7 +35,6 @@
 import android.util.ArrayMap;
 import android.util.ArraySet;
 import android.util.MutableBoolean;
-import android.util.SparseBooleanArray;
 import android.view.LayoutInflater;
 import android.view.MotionEvent;
 import android.view.View;
@@ -56,6 +55,7 @@
 import com.android.systemui.recents.RecentsDebugFlags;
 import com.android.systemui.recents.events.EventBus;
 import com.android.systemui.recents.events.activity.CancelEnterRecentsWindowAnimationEvent;
+import com.android.systemui.recents.events.activity.ConfigurationChangedEvent;
 import com.android.systemui.recents.events.activity.DismissRecentsToHomeAnimationStarted;
 import com.android.systemui.recents.events.activity.EnterRecentsTaskStackAnimationCompletedEvent;
 import com.android.systemui.recents.events.activity.EnterRecentsWindowAnimationCompletedEvent;
@@ -65,15 +65,13 @@
 import com.android.systemui.recents.events.activity.LaunchNextTaskRequestEvent;
 import com.android.systemui.recents.events.activity.LaunchTaskEvent;
 import com.android.systemui.recents.events.activity.LaunchTaskStartedEvent;
+import com.android.systemui.recents.events.activity.MultiWindowStateChangedEvent;
 import com.android.systemui.recents.events.activity.PackagesChangedEvent;
 import com.android.systemui.recents.events.activity.ShowHistoryButtonEvent;
 import com.android.systemui.recents.events.activity.ShowHistoryEvent;
-import com.android.systemui.recents.events.activity.TaskStackUpdatedEvent;
-import com.android.systemui.recents.events.component.RecentsVisibilityChangedEvent;
 import com.android.systemui.recents.events.ui.AllTaskViewsDismissedEvent;
 import com.android.systemui.recents.events.ui.DeleteTaskDataEvent;
 import com.android.systemui.recents.events.ui.DismissTaskViewEvent;
-import com.android.systemui.recents.events.ui.StackViewScrolledEvent;
 import com.android.systemui.recents.events.ui.TaskViewDismissedEvent;
 import com.android.systemui.recents.events.ui.UpdateFreeformTaskViewVisibilityEvent;
 import com.android.systemui.recents.events.ui.UserInteractionEvent;
@@ -118,7 +116,7 @@
     private static final ArraySet<Task.TaskKey> EMPTY_TASK_SET = new ArraySet<>();
 
     LayoutInflater mInflater;
-    TaskStack mStack;
+    TaskStack mStack = new TaskStack();
     @ViewDebug.ExportedProperty(deepExport=true, prefix="layout_")
     TaskStackLayoutAlgorithm mLayoutAlgorithm;
     @ViewDebug.ExportedProperty(deepExport=true, prefix="scroller_")
@@ -207,13 +205,13 @@
         }
     };
 
-    public TaskStackView(Context context, TaskStack stack) {
+    public TaskStackView(Context context) {
         super(context);
         SystemServicesProxy ssp = Recents.getSystemServices();
         Resources res = context.getResources();
 
         // Set the stack first
-        setStack(stack);
+        mStack.setCallbacks(this);
         mViewPool = new ViewPool<>(context, this);
         mInflater = LayoutInflater.from(context);
         mLayoutAlgorithm = new TaskStackLayoutAlgorithm(context, this);
@@ -249,6 +247,41 @@
         }
     }
 
+    /**
+     * Called only if we are resuming Recents.
+     */
+    void onResume(boolean isResumingFromVisible) {
+        if (!isResumingFromVisible) {
+            // Reset the focused task
+            resetFocusedTask(getFocusedTask());
+        }
+
+        // Reset the state of each of the task views
+        List<TaskView> taskViews = new ArrayList<>();
+        taskViews.addAll(getTaskViews());
+        taskViews.addAll(mViewPool.getViews());
+        for (int i = taskViews.size() - 1; i >= 0; i--) {
+            taskViews.get(i).onResume(isResumingFromVisible);
+        }
+
+        // Reset the stack state
+        readSystemFlags();
+        mTaskViewsClipDirty = true;
+        mEnterAnimationComplete = false;
+        mUIDozeTrigger.stopDozing();
+        if (isResumingFromVisible) {
+            // Animate in the freeform workspace
+            int ffBgAlpha = mLayoutAlgorithm.getStackState().freeformBackgroundAlpha;
+            animateFreeformWorkspaceBackgroundAlpha(ffBgAlpha, new AnimationProps(150,
+                    Interpolators.FAST_OUT_SLOW_IN));
+        } else {
+            mStackScroller.reset();
+            mLayoutAlgorithm.reset();
+            mAwaitingFirstLayout = true;
+            requestLayout();
+        }
+    }
+
     @Override
     protected void onAttachedToWindow() {
         EventBus.getDefault().register(this, RecentsActivity.EVENT_BUS_PRIORITY + 1);
@@ -262,22 +295,47 @@
         EventBus.getDefault().unregister(this);
     }
 
-    /** Sets the task stack */
-    void setStack(TaskStack stack) {
-        // Set the new stack
-        mStack = stack;
-        if (mStack != null) {
-            mStack.setCallbacks(this);
+    /**
+     * Sets the stack tasks of this TaskStackView from the given TaskStack.
+     */
+    public void setTasks(TaskStack stack, boolean notifyStackChanges, boolean relayoutTaskStack) {
+        boolean isInitialized = mLayoutAlgorithm.isInitialized();
+        mStack.setTasks(getContext(), stack.computeAllTasksList(),
+                notifyStackChanges && isInitialized);
+        if (isInitialized) {
+            // Only update the layout if we are notifying, otherwise, we will update it in the next
+            // measure/layout pass
+            updateLayoutAlgorithm(false /* boundScroll */, EMPTY_TASK_SET);
+            updateToInitialState();
+
+            if (relayoutTaskStack) {
+                relayoutTaskViews(AnimationProps.IMMEDIATE);
+
+                // Rebind all the task views.  This will not trigger new resources to be loaded
+                // unless they have actually changed
+                List<TaskView> taskViews = getTaskViews();
+                int taskViewCount = taskViews.size();
+                for (int i = 0; i < taskViewCount; i++) {
+                    TaskView tv = taskViews.get(i);
+                    bindTaskView(tv, tv.getTask());
+                }
+            }
         }
-        // Layout again with the new stack
-        requestLayout();
     }
 
     /** Returns the task stack. */
-    TaskStack getStack() {
+    public TaskStack getStack() {
         return mStack;
     }
 
+    /**
+     * Updates this TaskStackView to the initial state.
+     */
+    public void updateToInitialState() {
+        mStackScroller.setStackScrollToInitialState();
+        mLayoutAlgorithm.updateToInitialState(mStack.getStackTasks());
+    }
+
     /** Updates the list of task views */
     void updateTaskViewsList() {
         mTaskViews.clear();
@@ -331,37 +389,6 @@
         return null;
     }
 
-    /** Resets this TaskStackView for reuse. */
-    void reset() {
-        // Reset the focused task
-        resetFocusedTask(getFocusedTask());
-
-        // Return all the views to the pool
-        List<TaskView> taskViews = getTaskViews();
-        int taskViewCount = taskViews.size();
-        for (int i = taskViewCount - 1; i >= 0; i--) {
-            mViewPool.returnViewToPool(taskViews.get(i));
-        }
-
-        // Mark each task view for relayout
-        List<TaskView> poolViews = mViewPool.getViews();
-        for (TaskView tv : poolViews) {
-            tv.reset();
-        }
-
-        // Reset the stack state
-        mStack.reset();
-        mTaskViewsClipDirty = true;
-        mAwaitingFirstLayout = true;
-        mEnterAnimationComplete = false;
-        mUIDozeTrigger.stopDozing();
-        mUIDozeTrigger.resetTrigger();
-        mStackScroller.reset();
-        mLayoutAlgorithm.reset();
-        readSystemFlags();
-        requestLayout();
-    }
-
     /** Returns the stack algorithm for this task stack. */
     public TaskStackLayoutAlgorithm getStackAlgorithm() {
         return mLayoutAlgorithm;
@@ -410,7 +437,7 @@
      */
     int[] computeVisibleTaskTransforms(ArrayList<TaskViewTransform> taskTransforms,
             ArrayList<Task> tasks, float curStackScroll, float targetStackScroll,
-            ArraySet<Task.TaskKey> ignoreTasksSet) {
+            ArraySet<Task.TaskKey> ignoreTasksSet, boolean ignoreTaskOverrides) {
         int taskCount = tasks.size();
         int[] visibleTaskRange = mTmpIntPair;
         visibleTaskRange[0] = -1;
@@ -430,7 +457,7 @@
 
             // Calculate the current and (if necessary) the target transform for the task
             transform = mLayoutAlgorithm.getStackTransform(task, curStackScroll,
-                    taskTransforms.get(i), frontTransform);
+                    taskTransforms.get(i), frontTransform, ignoreTaskOverrides);
             if (useTargetStackScroll && !transform.visible) {
                 // If we have a target stack scroll and the task is not currently visible, then we
                 // just update the transform at the new scroll
@@ -468,11 +495,13 @@
 
     /**
      * Binds the visible {@link TaskView}s at the given target scroll.
-     *
-     * @see #bindVisibleTaskViews(float, ArraySet<Task.TaskKey>)
      */
     void bindVisibleTaskViews(float targetStackScroll) {
-        bindVisibleTaskViews(targetStackScroll, mIgnoreTasks);
+        bindVisibleTaskViews(targetStackScroll, mIgnoreTasks, false /* ignoreTaskOverrides */);
+    }
+
+    void bindVisibleTaskViews(float targetStackScroll, boolean ignoreTaskOverrides) {
+        bindVisibleTaskViews(targetStackScroll, mIgnoreTasks, ignoreTaskOverrides);
     }
 
     /**
@@ -487,12 +516,16 @@
      *                          target stack scroll.
      * @param ignoreTasksSet The set of tasks to ignore in this rebinding of the visible
      *                       {@link TaskView}s
+     * @param ignoreTaskOverrides If set, the visible task computation will get the transforms for
+     *                            tasks at their non-overridden task progress
      */
-    void bindVisibleTaskViews(float targetStackScroll, ArraySet<Task.TaskKey> ignoreTasksSet) {
+    void bindVisibleTaskViews(float targetStackScroll, ArraySet<Task.TaskKey> ignoreTasksSet,
+            boolean ignoreTaskOverrides) {
         // Get all the task transforms
         ArrayList<Task> tasks = mStack.getStackTasks();
         int[] visibleTaskRange = computeVisibleTaskTransforms(mCurrentTaskTransforms, tasks,
-                mStackScroller.getStackScroll(), targetStackScroll, ignoreTasksSet);
+                mStackScroller.getStackScroll(), targetStackScroll, ignoreTasksSet,
+                ignoreTaskOverrides);
 
         // Return all the invisible children to the pool
         mTmpTaskViewMap.clear();
@@ -502,15 +535,22 @@
         for (int i = taskViewCount - 1; i >= 0; i--) {
             TaskView tv = taskViews.get(i);
             Task task = tv.getTask();
-            int taskIndex = mStack.indexOfStackTask(task);
-            TaskViewTransform transform = mCurrentTaskTransforms.get(taskIndex);
 
             // Skip ignored tasks
             if (ignoreTasksSet.contains(task.key)) {
                 continue;
             }
 
-            if (task.isFreeformTask() || transform.visible) {
+            // It is possible for the set of lingering TaskViews to differ from the stack if the
+            // stack was updated before the relayout.  If the task view is no longer in the stack,
+            // then just return it back to the view pool.
+            int taskIndex = mStack.indexOfStackTask(task);
+            TaskViewTransform transform = null;
+            if (taskIndex != -1) {
+                transform = mCurrentTaskTransforms.get(taskIndex);
+            }
+
+            if (task.isFreeformTask() || (transform != null && transform.visible)) {
                 mTmpTaskViewMap.put(task.key, tv);
             } else {
                 if (mTouchExplorationEnabled) {
@@ -601,19 +641,17 @@
         // If we had a deferred animation, cancel that
         mDeferredTaskViewLayoutAnimation = null;
 
-        // Cancel all task view animations
-        cancelAllTaskViewAnimations();
-
         // Synchronize the current set of TaskViews
-        bindVisibleTaskViews(mStackScroller.getStackScroll(), ignoreTasksSet);
+        bindVisibleTaskViews(mStackScroller.getStackScroll(), ignoreTasksSet,
+                false /* ignoreTaskOverrides */);
 
         // Animate them to their final transforms with the given animation
         List<TaskView> taskViews = getTaskViews();
         int taskViewCount = taskViews.size();
         for (int i = 0; i < taskViewCount; i++) {
-            final TaskView tv = taskViews.get(i);
-            final int taskIndex = mStack.indexOfStackTask(tv.getTask());
-            final TaskViewTransform transform = mCurrentTaskTransforms.get(taskIndex);
+            TaskView tv = taskViews.get(i);
+            int taskIndex = mStack.indexOfStackTask(tv.getTask());
+            TaskViewTransform transform = mCurrentTaskTransforms.get(taskIndex);
 
             if (ignoreTasksSet.contains(tv.getTask().key)) {
                 continue;
@@ -637,6 +675,10 @@
      */
     public void updateTaskViewToTransform(TaskView taskView, TaskViewTransform transform,
             AnimationProps animation) {
+        if (taskView.isAnimatingTo(transform)) {
+            return;
+        }
+        taskView.cancelTransformAnimation();
         taskView.updateViewPropertiesToTaskTransform(transform, animation,
                 mRequestUpdateClippingListener);
     }
@@ -657,7 +699,8 @@
                 transform.fillIn(tv);
             } else {
                 mLayoutAlgorithm.getStackTransform(task, mStackScroller.getStackScroll(),
-                        focusState, transform, null, true /* forceUpdate */);
+                        focusState, transform, null, true /* forceUpdate */,
+                        false /* ignoreTaskOverrides */);
             }
             transform.visible = true;
         }
@@ -674,7 +717,7 @@
             Task task = tasks.get(i);
             TaskViewTransform transform = transformsOut.get(i);
             mLayoutAlgorithm.getStackTransform(task, stackScroll, focusState, transform, null,
-                    true /* forceUpdate */);
+                    true /* forceUpdate */, true /* ignoreTaskOverrides */);
             transform.visible = true;
         }
     }
@@ -759,9 +802,7 @@
                 }
             }
             tv.getViewBounds().setClipBottom(clipBottom);
-            if (!config.useHardwareLayers) {
-                tv.mThumbnailView.updateThumbnailVisibility(clipBottom - tv.getPaddingBottom());
-            }
+            tv.mThumbnailView.updateThumbnailVisibility(clipBottom - tv.getPaddingBottom());
             prevVisibleTv = tv;
         }
         mTaskViewsClipDirty = false;
@@ -860,6 +901,7 @@
                     cancelAllTaskViewAnimations();
                 }
 
+                mLayoutAlgorithm.clearUnfocusedTaskOverrides();
                 willScroll = mAnimationHelper.startScrollToFocusedTaskAnimation(newFocusedTask,
                         requestViewFocus);
             } else {
@@ -1107,15 +1149,6 @@
     }
 
     /**
-     * This is ONLY used from the Recents component to update the dummy stack view for purposes
-     * of getting the task rect to animate to.
-     */
-    public void updateLayoutForStack(TaskStack stack) {
-        mStack = stack;
-        updateLayoutAlgorithm(false /* boundScroll */, EMPTY_TASK_SET);
-    }
-
-    /**
      * Computes the maximum number of visible tasks and thumbnails. Requires that
      * updateLayoutForStack() is called first.
      */
@@ -1162,11 +1195,16 @@
 
         // If this is the first layout, then scroll to the front of the stack, then update the
         // TaskViews with the stack so that we can lay them out
-        if (mAwaitingFirstLayout) {
-            mStackScroller.setStackScrollToInitialState();
+        // TODO: The second check is a workaround for wacky layouts that we get while docking via
+        //       long pressing the recents button
+        if (mAwaitingFirstLayout ||
+                (mStackScroller.getStackScroll() == mLayoutAlgorithm.mInitialScrollP)) {
+            updateToInitialState();
         }
+
         // Rebind all the views, including the ignore ones
-        bindVisibleTaskViews(mStackScroller.getStackScroll(), EMPTY_TASK_SET);
+        bindVisibleTaskViews(mStackScroller.getStackScroll(), EMPTY_TASK_SET,
+                false /* ignoreTaskOverrides */);
 
         // Measure each of the TaskViews
         mTmpTaskViews.clear();
@@ -1405,8 +1443,8 @@
     public void onReturnViewToPool(TaskView tv) {
         final Task task = tv.getTask();
 
-        // Report that this tasks's data is no longer being used
-        Recents.getTaskLoader().unloadTaskData(task);
+        // Unbind the task from the task view
+        unbindTaskView(tv, task);
 
         // Reset the view properties and view state
         tv.resetViewProperties();
@@ -1451,14 +1489,11 @@
         // Update the task views list after adding the new task view
         updateTaskViewsList();
 
-        // Rebind the task and request that this task's data be filled into the TaskView
-        tv.onTaskBound(task);
-
-        // Load the task data
-        Recents.getTaskLoader().loadTaskData(task, true /* fetchAndInvalidateThumbnails */);
+        // Bind the task view to the new task
+        bindTaskView(tv, task);
 
         // If the doze trigger has already fired, then update the state for this task view
-        if (mUIDozeTrigger.hasTriggered()) {
+        if (mUIDozeTrigger.isAsleep()) {
             tv.setNoUserInteractionState();
         }
 
@@ -1487,6 +1522,19 @@
         return (tv.getTask() == preferredData);
     }
 
+    private void bindTaskView(TaskView tv, Task task) {
+        // Rebind the task and request that this task's data be filled into the TaskView
+        tv.onTaskBound(task);
+
+        // Load the task data
+        Recents.getTaskLoader().loadTaskData(task, true /* fetchAndInvalidateThumbnails */);
+    }
+
+    private void unbindTaskView(TaskView tv, Task task) {
+        // Report that this task's data is no longer being used
+        Recents.getTaskLoader().unloadTaskData(task);
+    }
+
     /**** TaskViewCallbacks Implementation ****/
 
     @Override
@@ -1652,12 +1700,6 @@
         }
     }
 
-    public final void onBusEvent(RecentsVisibilityChangedEvent event) {
-        if (!event.visible) {
-            reset();
-        }
-    }
-
     public final void onBusEvent(DragStartEvent event) {
         // Ensure that the drag task is not animated
         addIgnoreTask(event.task);
@@ -1754,12 +1796,14 @@
         event.taskView.setLeftTopRightBottom(taskViewRect.left, taskViewRect.top,
                 taskViewRect.right, taskViewRect.bottom);
 
-        // Animate all the TaskViews back into position
+        // Animate the non-drag TaskViews back into position
         mLayoutAlgorithm.getStackTransform(event.task, getScroller().getStackScroll(),
                 mTmpTransform, null);
         event.getAnimationTrigger().increment();
         relayoutTaskViews(new AnimationProps(DEFAULT_SYNC_STACK_DURATION,
                 Interpolators.FAST_OUT_SLOW_IN));
+
+        // Animate the drag TaskView back into position
         updateTaskViewToTransform(event.taskView, mTmpTransform,
                 new AnimationProps(DEFAULT_SYNC_STACK_DURATION, Interpolators.FAST_OUT_SLOW_IN,
                         event.getAnimationTrigger().decrementOnAnimationEnd()));
@@ -1832,31 +1876,28 @@
         mAnimationHelper.startHideHistoryAnimation();
     }
 
-    public final void onBusEvent(TaskStackUpdatedEvent event) {
+    public final void onBusEvent(MultiWindowStateChangedEvent event) {
         if (!event.inMultiWindow) {
-            // Scroll the stack to the front after it has been updated
-            event.addPostAnimationCallback(new Runnable() {
+            // Scroll the stack to the front to see the undocked task
+            mStackScroller.animateScroll(mLayoutAlgorithm.mMaxScrollP, new Runnable() {
                 @Override
                 public void run() {
-                    mStackScroller.animateScroll(mLayoutAlgorithm.mMaxScrollP,
-                            null /* postScrollRunnable */);
+                    List<TaskView> taskViews = getTaskViews();
+                    int taskViewCount = taskViews.size();
+                    for (int i = 0; i < taskViewCount; i++) {
+                        TaskView tv = taskViews.get(i);
+                        tv.getHeaderView().rebindToTask(tv.getTask(), tv.mTouchExplorationEnabled,
+                                tv.mIsDisabledInSafeMode);
+                    }
                 }
             });
         }
-        // When the multi-window state changes, rebind all task view headers again to update their
-        // dockable state
-        event.addPostAnimationCallback(new Runnable() {
-            @Override
-            public void run() {
-                List<TaskView> taskViews = getTaskViews();
-                int taskViewCount = taskViews.size();
-                for (int i = 0; i < taskViewCount; i++) {
-                    TaskView tv = taskViews.get(i);
-                    tv.getHeaderView().rebindToTask(tv.getTask(), tv.mTouchExplorationEnabled,
-                            tv.mIsDisabledInSafeMode);
-                }
-            }
-        });
+    }
+
+    public final void onBusEvent(ConfigurationChangedEvent event) {
+        mLayoutAlgorithm.reloadOnConfigurationChange(getContext());
+        mLayoutAlgorithm.initialize(mStackBounds,
+                TaskStackLayoutAlgorithm.StackState.getStackStateForStack(mStack));
     }
 
     /**
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewScroller.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewScroller.java
index 333df9d..ad46abd 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewScroller.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewScroller.java
@@ -115,13 +115,8 @@
      * @return whether the stack progress changed.
      */
     public boolean setStackScrollToInitialState() {
-        SystemServicesProxy ssp = Recents.getSystemServices();
         float prevStackScrollP = mStackScrollP;
-        if (ssp.hasDockedTask()) {
-            setStackScroll(mLayoutAlgorithm.mMaxScrollP);
-        } else {
-            setStackScroll(mLayoutAlgorithm.mInitialScrollP);
-        }
+        setStackScroll(mLayoutAlgorithm.mInitialScrollP);
         return Float.compare(prevStackScrollP, mStackScrollP) != 0;
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java
index 20933ee..8635911 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java
@@ -20,6 +20,7 @@
 import android.animation.ValueAnimator;
 import android.content.Context;
 import android.content.res.Resources;
+import android.graphics.Path;
 import android.graphics.Rect;
 import android.util.ArrayMap;
 import android.util.MutableBoolean;
@@ -44,6 +45,7 @@
 import com.android.systemui.recents.events.activity.HideRecentsEvent;
 import com.android.systemui.recents.events.ui.StackViewScrolledEvent;
 import com.android.systemui.recents.events.ui.TaskViewDismissedEvent;
+import com.android.systemui.recents.misc.FreePathInterpolator;
 import com.android.systemui.recents.misc.SystemServicesProxy;
 import com.android.systemui.recents.misc.Utilities;
 import com.android.systemui.recents.model.Task;
@@ -60,6 +62,16 @@
     private static final int INACTIVE_POINTER_ID = -1;
     private static final Interpolator STACK_TRANSFORM_INTERPOLATOR =
             new PathInterpolator(0.73f, 0.33f, 0.42f, 0.85f);
+    // The min overscroll is the amount of task progress overscroll we want / the max overscroll
+    // curve value below
+    private static final float MAX_OVERSCROLL = 0.7f / 0.3f;
+    private static final Interpolator OVERSCROLL_INTERP;
+    static {
+        Path OVERSCROLL_PATH = new Path();
+        OVERSCROLL_PATH.moveTo(0, 0);
+        OVERSCROLL_PATH.cubicTo(0.2f, 0.175f, 0.25f, 0.3f, 1f, 0.3f);
+        OVERSCROLL_INTERP = new FreePathInterpolator(OVERSCROLL_PATH);
+    }
 
     Context mContext;
     TaskStackView mSv;
@@ -245,6 +257,18 @@
                     // of the curve, so just move the scroll proportional to that
                     float deltaP = layoutAlgorithm.getDeltaPForY(mDownY, y);
                     float curScrollP = mDownScrollP + deltaP;
+
+                    // Modulate the overscroll to prevent users from pulling the stack too far
+                    float minScrollP = layoutAlgorithm.mMinScrollP;
+                    float maxScrollP = layoutAlgorithm.mMaxScrollP;
+                    if (curScrollP < minScrollP || curScrollP > maxScrollP) {
+                        float clampedScrollP = Utilities.clamp(curScrollP, minScrollP, maxScrollP);
+                        float overscrollP = (curScrollP - clampedScrollP);
+                        float overscrollX = Math.abs(overscrollP) / MAX_OVERSCROLL;
+                        curScrollP = clampedScrollP + (Math.signum(overscrollP) *
+                                (OVERSCROLL_INTERP.getInterpolation(overscrollX) * MAX_OVERSCROLL));
+                    }
+
                     mScroller.setStackScroll(curScrollP);
                     mStackViewScrolledEvent.updateY(y - mLastY);
                     EventBus.getDefault().send(mStackViewScrolledEvent);
@@ -446,7 +470,7 @@
             }
 
             // Pick up the newly visible views, not including the deleting tasks
-            mSv.bindVisibleTaskViews(newStackScroll);
+            mSv.bindVisibleTaskViews(newStackScroll, true /* ignoreTaskOverrides */);
 
             // Get the final set of task transforms (with task removed)
             mSv.getLayoutTaskTransforms(newStackScroll, TaskStackLayoutAlgorithm.STATE_UNFOCUSED,
@@ -486,6 +510,7 @@
         mSv.getScroller().setStackScroll(mTargetStackScroll, null);
         // Update the focus state to the final focus state
         mSv.getStackAlgorithm().setFocusState(TaskStackLayoutAlgorithm.STATE_UNFOCUSED);
+        mSv.getStackAlgorithm().clearUnfocusedTaskOverrides();
         // Remove the task view from the stack
         EventBus.getDefault().send(new TaskViewDismissedEvent(tv.getTask(), tv));
         // Stop tracking this deletion animation
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
index 0c78e6a..7584a2e 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
@@ -77,6 +77,24 @@
 
     /**
      * The dim overlay is generally calculated from the task progress, but occasionally (like when
+     * launching) needs to be animated independently of the task progress.  This call is only used
+     * when animating the task into Recents, when the header dim is already applied
+     */
+    public static final Property<TaskView, Float> DIM_ALPHA_WITHOUT_HEADER =
+            new FloatProperty<TaskView>("dimAlphaWithoutHeader") {
+                @Override
+                public void setValue(TaskView tv, float dimAlpha) {
+                    tv.setDimAlphaWithoutHeader(dimAlpha);
+                }
+
+                @Override
+                public Float get(TaskView tv) {
+                    return tv.getDimAlpha();
+                }
+            };
+
+    /**
+     * The dim overlay is generally calculated from the task progress, but occasionally (like when
      * launching) needs to be animated independently of the task progress.
      */
     public static final Property<TaskView, Float> DIM_ALPHA =
@@ -129,6 +147,7 @@
     AnimateableViewBounds mViewBounds;
 
     private AnimatorSet mTransformAnimation;
+    private final TaskViewTransform mTargetAnimationTransform = new TaskViewTransform();
     private ArrayList<Animator> mTmpAnimators = new ArrayList<>();
 
     View mContent;
@@ -175,11 +194,13 @@
     }
 
     /** Resets this TaskView for reuse. */
-    void reset() {
-        resetViewProperties();
+    void onResume(boolean isResumingFromVisible) {
         resetNoUserInteractionState();
         readSystemFlags();
-        setClipViewInStack(false);
+        if (!isResumingFromVisible) {
+            resetViewProperties();
+            setClipViewInStack(false);
+        }
         setCallbacks(null);
     }
 
@@ -299,6 +320,7 @@
             // Create the animator
             mTransformAnimation = toAnimation.createAnimator(mTmpAnimators);
             mTransformAnimation.start();
+            mTargetAnimationTransform.copyFrom(toTransform);
         }
     }
 
@@ -318,6 +340,14 @@
     }
 
     /**
+     * @return whether we are animating towards {@param transform}
+     */
+    boolean isAnimatingTo(TaskViewTransform transform) {
+        return mTransformAnimation != null && mTransformAnimation.isStarted()
+                && mTargetAnimationTransform.isSame(transform);
+    }
+
+    /**
      * Cancels any current transform animations.
      */
     public void cancelTransformAnimation() {
@@ -388,21 +418,17 @@
      * Sets the current dim.
      */
     public void setDimAlpha(float dimAlpha) {
-        RecentsConfiguration config = Recents.getConfiguration();
-
-        int dimAlphaInt = (int) (dimAlpha * 255);
         mDimAlpha = dimAlpha;
-        if (config.useHardwareLayers) {
-            // Defer setting hardware layers if we have not yet measured, or there is no dim to draw
-            if (getMeasuredWidth() > 0 && getMeasuredHeight() > 0) {
-                mDimColorFilter.setColor(Color.argb(dimAlphaInt, 0, 0, 0));
-                mDimLayerPaint.setColorFilter(mDimColorFilter);
-                mContent.setLayerType(LAYER_TYPE_HARDWARE, mDimLayerPaint);
-            }
-        } else {
-            mThumbnailView.setDimAlpha(dimAlpha);
-            mHeaderView.setDimAlpha(dimAlpha);
-        }
+        mThumbnailView.setDimAlpha(dimAlpha);
+        mHeaderView.setDimAlpha(dimAlpha);
+    }
+
+    /**
+     * Sets the current dim without updating the header's dim.
+     */
+    public void setDimAlphaWithoutHeader(float dimAlpha) {
+        mDimAlpha = dimAlpha;
+        mThumbnailView.setDimAlpha(dimAlpha);
     }
 
     /**
@@ -413,25 +439,6 @@
     }
 
     /**
-     * Animates the dim to the given value.
-     */
-    void animateDimAlpha(float toDimAlpha, AnimationProps animation) {
-        // Animate the dim into view as well
-        if (Float.compare(toDimAlpha, getDimAlpha()) != 0) {
-            Animator anim = animation.apply(AnimationProps.DIM_ALPHA, ObjectAnimator.ofFloat(this,
-                    DIM_ALPHA, getDimAlpha(), toDimAlpha));
-            if (animation.getListener() != null) {
-                anim.addListener(animation.getListener());
-            }
-            anim.start();
-        } else {
-            if (animation.getListener() != null) {
-                animation.getListener().onAnimationEnd(null);
-            }
-        }
-    }
-
-    /**
      * Explicitly sets the focused state of this task.
      */
     public void setFocusedState(boolean isFocused, boolean requestViewFocus) {
@@ -517,18 +524,20 @@
     @Override
     public void onPrepareLaunchTargetForEnterAnimation() {
         // These values will be animated in when onStartLaunchTargetEnterAnimation() is called
-        setDimAlpha(0);
+        setDimAlphaWithoutHeader(0);
         mActionButtonView.setAlpha(0f);
     }
 
     @Override
-    public void onStartLaunchTargetEnterAnimation(int duration, boolean screenPinningEnabled,
-            ReferenceCountedTrigger postAnimationTrigger) {
-        // Un-dim the view before/while launching the target
-        AnimationProps animation = new AnimationProps(duration, Interpolators.ALPHA_OUT)
-                .setListener(postAnimationTrigger.decrementOnAnimationEnd());
+    public void onStartLaunchTargetEnterAnimation(TaskViewTransform transform, int duration,
+            boolean screenPinningEnabled, ReferenceCountedTrigger postAnimationTrigger) {
+        // Dim the view after the app window transitions down into recents
         postAnimationTrigger.increment();
-        animateDimAlpha(0, animation);
+        AnimationProps animation = new AnimationProps(duration, Interpolators.ALPHA_OUT);
+        Animator anim = animation.apply(AnimationProps.DIM_ALPHA, ObjectAnimator.ofFloat(this,
+                DIM_ALPHA_WITHOUT_HEADER, getDimAlpha(), transform.dimAlpha));
+        anim.addListener(postAnimationTrigger.decrementOnAnimationEnd());
+        anim.start();
 
         if (screenPinningEnabled) {
             showActionButton(true /* fadeIn */, duration /* fadeInDuration */);
@@ -540,7 +549,9 @@
             ReferenceCountedTrigger postAnimationTrigger) {
         // Un-dim the view before/while launching the target
         AnimationProps animation = new AnimationProps(duration, Interpolators.ALPHA_OUT);
-        animateDimAlpha(0, animation);
+        Animator anim = animation.apply(AnimationProps.DIM_ALPHA, ObjectAnimator.ofFloat(this,
+                DIM_ALPHA, getDimAlpha(), 0));
+        anim.start();
 
         postAnimationTrigger.increment();
         hideActionButton(true /* fadeOut */, duration,
@@ -603,7 +614,7 @@
         EventBus.getDefault().send(new LaunchTaskEvent(this, mTask, null, INVALID_STACK_ID,
                 screenPinningRequested));
 
-        MetricsLogger.action(v.getContext(), MetricsEvent.OVERVIEW_SELECT,
+        MetricsLogger.action(v.getContext(), MetricsEvent.ACTION_OVERVIEW_SELECT,
                 mTask.key.getComponent().toString());
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java
index 05a8527..b2a7d90 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java
@@ -347,9 +347,11 @@
      * Sets the dim alpha, only used when we are not using hardware layers.
      * (see RecentsConfiguration.useHardwareLayers)
      */
-    void setDimAlpha(float dimAlpha) {
-        mDimAlpha = dimAlpha;
-        updateBackgroundColor(mBackground.getColor(), dimAlpha);
+    public void setDimAlpha(float dimAlpha) {
+        if (Float.compare(mDimAlpha, dimAlpha) != 0) {
+            mDimAlpha = dimAlpha;
+            updateBackgroundColor(mBackground.getColor(), dimAlpha);
+        }
     }
 
     /**
@@ -377,7 +379,9 @@
         int primaryColor = disabledInSafeMode
                 ? mDisabledTaskBarBackgroundColor
                 : t.colorPrimary;
-        updateBackgroundColor(primaryColor, mDimAlpha);
+        if (mBackground.getColor() != primaryColor) {
+            updateBackgroundColor(primaryColor, mDimAlpha);
+        }
         if (t.icon != null) {
             mIconView.setImageDrawable(t.icon);
         }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewTransform.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewTransform.java
index 0d16a79..dc76e61 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewTransform.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewTransform.java
@@ -121,6 +121,18 @@
     }
 
     /**
+     * @return whether {@param other} is the same transform as this
+     */
+    public boolean isSame(TaskViewTransform other) {
+        return translationZ == other.translationZ
+                && scale == other.scale
+                && other.alpha == alpha
+                && dimAlpha == other.dimAlpha
+                && visible == other.visible
+                && rect.equals(other.rect);
+    }
+
+    /**
      * Resets the current transform.
      */
     public void reset() {
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
index a06700d..eb08947 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
@@ -39,6 +39,7 @@
 import android.graphics.Paint;
 import android.graphics.PixelFormat;
 import android.graphics.PointF;
+import android.graphics.Rect;
 import android.media.MediaActionSound;
 import android.net.Uri;
 import android.os.AsyncTask;
@@ -92,13 +93,13 @@
 /**
  * An AsyncTask that saves an image to the media store in the background.
  */
-class SaveImageInBackgroundTask extends AsyncTask<SaveImageInBackgroundData, Void,
-        SaveImageInBackgroundData> {
+class SaveImageInBackgroundTask extends AsyncTask<Void, Void, Void> {
 
     private static final String SCREENSHOTS_DIR_NAME = "Screenshots";
     private static final String SCREENSHOT_FILE_NAME_TEMPLATE = "Screenshot_%s.png";
     private static final String SCREENSHOT_SHARE_SUBJECT_TEMPLATE = "Screenshot (%s)";
 
+    private final SaveImageInBackgroundData mParams;
     private final NotificationManager mNotificationManager;
     private final Notification.Builder mNotificationBuilder, mPublicNotificationBuilder;
     private final File mScreenshotDir;
@@ -121,6 +122,7 @@
         Resources r = context.getResources();
 
         // Prepare all the output metadata
+        mParams = data;
         mImageTime = System.currentTimeMillis();
         String imageDate = new SimpleDateFormat("yyyyMMdd-HHmmss").format(new Date(mImageTime));
         mImageFileName = String.format(SCREENSHOT_FILE_NAME_TEMPLATE, imageDate);
@@ -209,17 +211,17 @@
     }
 
     @Override
-    protected SaveImageInBackgroundData doInBackground(SaveImageInBackgroundData... params) {
+    protected Void doInBackground(Void... params) {
         if (isCancelled()) {
-            return params[0];
+            return null;
         }
 
         // By default, AsyncTask sets the worker thread to have background thread priority, so bump
         // it back up so that we save a little quicker.
         Process.setThreadPriority(Process.THREAD_PRIORITY_FOREGROUND);
 
-        Context context = params[0].context;
-        Bitmap image = params[0].image;
+        Context context = mParams.context;
+        Bitmap image = mParams.image;
         Resources r = context.getResources();
 
         try {
@@ -283,14 +285,14 @@
                     r.getString(com.android.internal.R.string.delete), deleteAction);
             mNotificationBuilder.addAction(deleteActionBuilder.build());
 
-            params[0].imageUri = uri;
-            params[0].image = null;
-            params[0].errorMsgResId = 0;
+            mParams.imageUri = uri;
+            mParams.image = null;
+            mParams.errorMsgResId = 0;
         } catch (Exception e) {
             // IOException/UnsupportedOperationException may be thrown if external storage is not
             // mounted
-            params[0].clearImage();
-            params[0].errorMsgResId = R.string.screenshot_failed_to_save_text;
+            mParams.clearImage();
+            mParams.errorMsgResId = R.string.screenshot_failed_to_save_text;
         }
 
         // Recycle the bitmap data
@@ -298,23 +300,23 @@
             image.recycle();
         }
 
-        return params[0];
+        return null;
     }
 
     @Override
-    protected void onPostExecute(SaveImageInBackgroundData params) {
-        if (params.errorMsgResId != 0) {
+    protected void onPostExecute(Void params) {
+        if (mParams.errorMsgResId != 0) {
             // Show a message that we've failed to save the image to disk
-            GlobalScreenshot.notifyScreenshotError(params.context, mNotificationManager,
-                    params.errorMsgResId);
+            GlobalScreenshot.notifyScreenshotError(mParams.context, mNotificationManager,
+                    mParams.errorMsgResId);
         } else {
             // Show the final notification to indicate screenshot saved
-            Context context = params.context;
+            Context context = mParams.context;
             Resources r = context.getResources();
 
             // Create the intent to show the screenshot in gallery
             Intent launchIntent = new Intent(Intent.ACTION_VIEW);
-            launchIntent.setDataAndType(params.imageUri, "image/png");
+            launchIntent.setDataAndType(mParams.imageUri, "image/png");
             launchIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
 
             final long now = System.currentTimeMillis();
@@ -323,7 +325,7 @@
             mPublicNotificationBuilder
                     .setContentTitle(r.getString(R.string.screenshot_saved_title))
                     .setContentText(r.getString(R.string.screenshot_saved_text))
-                    .setContentIntent(PendingIntent.getActivity(params.context, 0, launchIntent, 0))
+                    .setContentIntent(PendingIntent.getActivity(mParams.context, 0, launchIntent, 0))
                     .setWhen(now)
                     .setAutoCancel(true)
                     .setColor(context.getColor(
@@ -331,7 +333,7 @@
             mNotificationBuilder
                 .setContentTitle(r.getString(R.string.screenshot_saved_title))
                 .setContentText(r.getString(R.string.screenshot_saved_text))
-                .setContentIntent(PendingIntent.getActivity(params.context, 0, launchIntent, 0))
+                .setContentIntent(PendingIntent.getActivity(mParams.context, 0, launchIntent, 0))
                 .setWhen(now)
                 .setAutoCancel(true)
                 .setColor(context.getColor(
@@ -341,15 +343,18 @@
 
             mNotificationManager.notify(R.id.notification_screenshot, mNotificationBuilder.build());
         }
-        params.finisher.run();
-        params.clearContext();
+        mParams.finisher.run();
+        mParams.clearContext();
     }
 
     @Override
-    protected void onCancelled(SaveImageInBackgroundData params) {
-        params.finisher.run();
-        params.clearImage();
-        params.clearContext();
+    protected void onCancelled(Void params) {
+        // If we are cancelled while the task is running in the background, we may get null params.
+        // The finisher is expected to always be called back, so just use the baked-in params from
+        // the ctor in any case.
+        mParams.finisher.run();
+        mParams.clearImage();
+        mParams.clearContext();
 
         // Cancel the posted notification
         mNotificationManager.cancel(R.id.notification_screenshot);
@@ -407,6 +412,7 @@
 
     private Bitmap mScreenBitmap;
     private View mScreenshotLayout;
+    private ScreenshotSelectorView mScreenshotSelectorView;
     private ImageView mBackgroundView;
     private ImageView mScreenshotView;
     private ImageView mScreenshotFlash;
@@ -417,7 +423,7 @@
     private float mBgPadding;
     private float mBgPaddingScale;
 
-    private AsyncTask<SaveImageInBackgroundData, Void, SaveImageInBackgroundData> mSaveInBgTask;
+    private AsyncTask<Void, Void, Void> mSaveInBgTask;
 
     private MediaActionSound mCameraSound;
 
@@ -437,7 +443,11 @@
         mBackgroundView = (ImageView) mScreenshotLayout.findViewById(R.id.global_screenshot_background);
         mScreenshotView = (ImageView) mScreenshotLayout.findViewById(R.id.global_screenshot);
         mScreenshotFlash = (ImageView) mScreenshotLayout.findViewById(R.id.global_screenshot_flash);
+        mScreenshotSelectorView = (ScreenshotSelectorView) mScreenshotLayout.findViewById(
+                R.id.global_screenshot_selector);
         mScreenshotLayout.setFocusable(true);
+        mScreenshotSelectorView.setFocusable(true);
+        mScreenshotSelectorView.setFocusableInTouchMode(true);
         mScreenshotLayout.setOnTouchListener(new View.OnTouchListener() {
             @Override
             public boolean onTouch(View v, MotionEvent event) {
@@ -449,7 +459,7 @@
         // Setup the window that we are going to use
         mWindowLayoutParams = new WindowManager.LayoutParams(
                 ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT, 0, 0,
-                WindowManager.LayoutParams.TYPE_SECURE_SYSTEM_OVERLAY,
+                WindowManager.LayoutParams.TYPE_SCREENSHOT,
                 WindowManager.LayoutParams.FLAG_FULLSCREEN
                     | WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED
                     | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
@@ -504,7 +514,7 @@
             mSaveInBgTask.cancel(false);
         }
         mSaveInBgTask = new SaveImageInBackgroundTask(mContext, data, mNotificationManager)
-                .execute(data);
+                .execute();
     }
 
     /**
@@ -525,7 +535,8 @@
     /**
      * Takes a screenshot of the current display and shows an animation.
      */
-    void takeScreenshot(Runnable finisher, boolean statusBarVisible, boolean navBarVisible) {
+    void takeScreenshot(Runnable finisher, boolean statusBarVisible, boolean navBarVisible,
+            int x, int y, int width, int height) {
         // We need to orient the screenshot correctly (and the Surface api seems to take screenshots
         // only in the natural orientation of the device :!)
         mDisplay.getRealMetrics(mDisplayMetrics);
@@ -565,6 +576,13 @@
             mScreenBitmap = ss;
         }
 
+        if (width != mDisplayMetrics.widthPixels || height != mDisplayMetrics.heightPixels) {
+            // Crop the screenshot to selected region
+            Bitmap cropped = Bitmap.createBitmap(mScreenBitmap, x, y, width, height);
+            mScreenBitmap.recycle();
+            mScreenBitmap = cropped;
+        }
+
         // Optimizations
         mScreenBitmap.setHasAlpha(false);
         mScreenBitmap.prepareToDraw();
@@ -574,6 +592,71 @@
                 statusBarVisible, navBarVisible);
     }
 
+    void takeScreenshot(Runnable finisher, boolean statusBarVisible, boolean navBarVisible) {
+        mDisplay.getRealMetrics(mDisplayMetrics);
+        takeScreenshot(finisher, statusBarVisible, navBarVisible, 0, 0, mDisplayMetrics.widthPixels,
+                mDisplayMetrics.heightPixels);
+    }
+
+    /**
+     * Displays a screenshot selector
+     */
+    void takeScreenshotPartial(final Runnable finisher, final boolean statusBarVisible,
+            final boolean navBarVisible) {
+        mWindowManager.addView(mScreenshotLayout, mWindowLayoutParams);
+        mScreenshotSelectorView.setOnTouchListener(new View.OnTouchListener() {
+            @Override
+            public boolean onTouch(View v, MotionEvent event) {
+                ScreenshotSelectorView view = (ScreenshotSelectorView) v;
+                switch (event.getAction()) {
+                    case MotionEvent.ACTION_DOWN:
+                        view.startSelection((int) event.getX(), (int) event.getY());
+                        return true;
+                    case MotionEvent.ACTION_MOVE:
+                        view.updateSelection((int) event.getX(), (int) event.getY());
+                        return true;
+                    case MotionEvent.ACTION_UP:
+                        view.setVisibility(View.GONE);
+                        mWindowManager.removeView(mScreenshotLayout);
+                        final Rect rect = view.getSelectionRect();
+                        if (rect != null) {
+                            if (rect.width() != 0 && rect.height() != 0) {
+                                // Need mScreenshotLayout to handle it after the view disappears
+                                mScreenshotLayout.post(new Runnable() {
+                                    public void run() {
+                                        takeScreenshot(finisher, statusBarVisible, navBarVisible,
+                                                rect.left, rect.top, rect.width(), rect.height());
+                                    }
+                                });
+                            }
+                        }
+
+                        view.stopSelection();
+                        return true;
+                }
+
+                return false;
+            }
+        });
+        mScreenshotLayout.post(new Runnable() {
+            @Override
+            public void run() {
+                mScreenshotSelectorView.setVisibility(View.VISIBLE);
+                mScreenshotSelectorView.requestFocus();
+            }
+        });
+    }
+
+    /**
+     * Cancels screenshot request
+     */
+    void stopScreenshot() {
+        // If the selector layer still presents on screen, we remove it and resets its state.
+        if (mScreenshotSelectorView.getSelectionRect() != null) {
+            mWindowManager.removeView(mScreenshotLayout);
+            mScreenshotSelectorView.stopSelection();
+        }
+    }
 
     /**
      * Starts the animation after taking the screenshot
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotSelectorView.java b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotSelectorView.java
new file mode 100644
index 0000000..07a9246
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotSelectorView.java
@@ -0,0 +1,82 @@
+/*
+ * 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.screenshot;
+
+import android.annotation.Nullable;
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.graphics.Point;
+import android.graphics.PorterDuff;
+import android.graphics.PorterDuffXfermode;
+import android.graphics.Rect;
+import android.util.AttributeSet;
+import android.view.View;
+
+/**
+ * Draws a selection rectangle while taking screenshot
+ */
+public class ScreenshotSelectorView extends View {
+    private Point mStartPoint;
+    private Rect mSelectionRect;
+    private final Paint mPaintSelection, mPaintBackground;
+
+    public ScreenshotSelectorView(Context context) {
+        this(context, null);
+    }
+
+    public ScreenshotSelectorView(Context context, @Nullable AttributeSet attrs) {
+        super(context, attrs);
+        mPaintBackground = new Paint(Color.BLACK);
+        mPaintBackground.setAlpha(160);
+        mPaintSelection = new Paint(Color.TRANSPARENT);
+        mPaintSelection.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
+    }
+
+    public void startSelection(int x, int y) {
+        mStartPoint = new Point(x, y);
+        mSelectionRect = new Rect(x, y, x, y);
+    }
+
+    public void updateSelection(int x, int y) {
+        if (mSelectionRect != null) {
+            mSelectionRect.left = Math.min(mStartPoint.x, x);
+            mSelectionRect.right = Math.max(mStartPoint.x, x);
+            mSelectionRect.top = Math.min(mStartPoint.y, y);
+            mSelectionRect.bottom = Math.max(mStartPoint.y, y);
+            invalidate();
+        }
+    }
+
+    public Rect getSelectionRect() {
+        return mSelectionRect;
+    }
+
+    public void stopSelection() {
+        mStartPoint = null;
+        mSelectionRect = null;
+    }
+
+    @Override
+    public void draw(Canvas canvas) {
+        canvas.drawRect(mLeft, mTop, mRight, mBottom, mPaintBackground);
+        if (mSelectionRect != null) {
+            canvas.drawRect(mSelectionRect, mPaintSelection);
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotServiceErrorReceiver.java b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotServiceErrorReceiver.java
new file mode 100644
index 0000000..fc2a1e4
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotServiceErrorReceiver.java
@@ -0,0 +1,40 @@
+/*
+ * 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.screenshot;
+
+import android.app.NotificationManager;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+
+import com.android.systemui.R;
+
+/**
+ * Performs a number of miscellaneous, non-system-critical actions
+ * after the system has finished booting.
+ */
+public class ScreenshotServiceErrorReceiver extends BroadcastReceiver {
+
+    @Override
+    public void onReceive(final Context context, Intent intent) {
+        // Show a message that we've failed to save the image to disk
+        NotificationManager nm = (NotificationManager)
+                context.getSystemService(Context.NOTIFICATION_SERVICE);
+        GlobalScreenshot.notifyScreenshotError(context, nm,
+                R.string.screenshot_failed_to_save_unknown_text);
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/TakeScreenshotService.java b/packages/SystemUI/src/com/android/systemui/screenshot/TakeScreenshotService.java
index 456b5fa..4badc42 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/TakeScreenshotService.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/TakeScreenshotService.java
@@ -23,6 +23,7 @@
 import android.os.Message;
 import android.os.Messenger;
 import android.os.RemoteException;
+import android.view.WindowManager;
 
 public class TakeScreenshotService extends Service {
     private static final String TAG = "TakeScreenshotService";
@@ -32,21 +33,28 @@
     private Handler mHandler = new Handler() {
         @Override
         public void handleMessage(Message msg) {
-            switch (msg.what) {
-                case 1:
-                    final Messenger callback = msg.replyTo;
-                    if (mScreenshot == null) {
-                        mScreenshot = new GlobalScreenshot(TakeScreenshotService.this);
+            final Messenger callback = msg.replyTo;
+            Runnable finisher = new Runnable() {
+                @Override
+                public void run() {
+                    Message reply = Message.obtain(null, 1);
+                    try {
+                        callback.send(reply);
+                    } catch (RemoteException e) {
                     }
-                    mScreenshot.takeScreenshot(new Runnable() {
-                        @Override public void run() {
-                            Message reply = Message.obtain(null, 1);
-                            try {
-                                callback.send(reply);
-                            } catch (RemoteException e) {
-                            }
-                        }
-                    }, msg.arg1 > 0, msg.arg2 > 0);
+                }
+            };
+            if (mScreenshot == null) {
+                mScreenshot = new GlobalScreenshot(TakeScreenshotService.this);
+            }
+
+            switch (msg.what) {
+                case WindowManager.TAKE_SCREENSHOT_FULLSCREEN:
+                    mScreenshot.takeScreenshot(finisher, msg.arg1 > 0, msg.arg2 > 0);
+                    break;
+                case WindowManager.TAKE_SCREENSHOT_SELECTED_REGION:
+                    mScreenshot.takeScreenshotPartial(finisher, msg.arg1 > 0, msg.arg2 > 0);
+                    break;
             }
         }
     };
@@ -55,4 +63,10 @@
     public IBinder onBind(Intent intent) {
         return new Messenger(mHandler).getBinder();
     }
+
+    @Override
+    public boolean onUnbind(Intent intent) {
+        if (mScreenshot != null) mScreenshot.stopScreenshot();
+        return true;
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/shortcut/ShortcutKeyDispatcher.java b/packages/SystemUI/src/com/android/systemui/shortcut/ShortcutKeyDispatcher.java
new file mode 100644
index 0000000..69dcabe
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/shortcut/ShortcutKeyDispatcher.java
@@ -0,0 +1,124 @@
+/*
+ * 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.shortcut;
+
+import android.accessibilityservice.AccessibilityServiceInfo;
+import android.app.ActivityManager;
+import android.app.ActivityManagerNative;
+import android.app.IActivityManager;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.pm.ServiceInfo;
+import android.content.res.Configuration;
+import android.os.RemoteException;
+import android.util.DisplayMetrics;
+import android.util.Log;
+import android.view.IWindowManager;
+import android.view.KeyEvent;
+import android.view.WindowManager;
+import android.view.WindowManagerGlobal;
+import android.view.accessibility.AccessibilityManager;
+import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.MetricsProto.MetricsEvent;
+import com.android.internal.policy.DividerSnapAlgorithm;
+import com.android.settingslib.accessibility.AccessibilityUtils;
+import com.android.systemui.R;
+import com.android.systemui.SystemUI;
+import com.android.systemui.recents.Recents;
+import com.android.systemui.stackdivider.Divider;
+import com.android.systemui.stackdivider.DividerView;
+import com.android.systemui.statusbar.phone.NavigationBarGestureHelper;
+
+import java.util.List;
+import java.util.Set;
+
+/**
+ * Dispatches shortcut to System UI components
+ */
+public class ShortcutKeyDispatcher extends SystemUI
+        implements ShortcutKeyServiceProxy.Callbacks {
+
+    private static final String TAG = "ShortcutKeyDispatcher";
+
+    private ShortcutKeyServiceProxy mShortcutKeyServiceProxy = new ShortcutKeyServiceProxy(this);
+    private IWindowManager mWindowManagerService = WindowManagerGlobal.getWindowManagerService();
+    private IActivityManager mActivityManager = ActivityManagerNative.getDefault();
+
+    protected final long META_MASK = ((long) KeyEvent.META_META_ON) << Integer.SIZE;
+    protected final long ALT_MASK = ((long) KeyEvent.META_ALT_ON) << Integer.SIZE;
+    protected final long CTRL_MASK = ((long) KeyEvent.META_CTRL_ON) << Integer.SIZE;
+    protected final long SHIFT_MASK = ((long) KeyEvent.META_SHIFT_ON) << Integer.SIZE;
+
+    protected final long SC_DOCK_LEFT = META_MASK | KeyEvent.KEYCODE_LEFT_BRACKET;
+    protected final long SC_DOCK_RIGHT = META_MASK | KeyEvent.KEYCODE_RIGHT_BRACKET;
+
+    /**
+     * Registers a shortcut key to window manager.
+     * @param shortcutCode packed representation of shortcut key code and meta information
+     */
+    public void registerShortcutKey(long shortcutCode) {
+        try {
+            mWindowManagerService.registerShortcutKey(shortcutCode, mShortcutKeyServiceProxy);
+        } catch (RemoteException e) {
+            // Do nothing
+        }
+    }
+
+    @Override
+    public void onShortcutKeyPressed(long shortcutCode) {
+        int orientation = mContext.getResources().getConfiguration().orientation;
+        if ((shortcutCode == SC_DOCK_LEFT || shortcutCode == SC_DOCK_RIGHT)
+                && orientation == Configuration.ORIENTATION_LANDSCAPE) {
+            handleDockKey(shortcutCode);
+        }
+    }
+
+    @Override
+    public void start() {
+        registerShortcutKey(SC_DOCK_LEFT);
+        registerShortcutKey(SC_DOCK_RIGHT);
+    }
+
+    private void handleDockKey(long shortcutCode) {
+        try {
+            int dockSide = mWindowManagerService.getDockedStackSide();
+            if (dockSide == WindowManager.DOCKED_INVALID) {
+                // If there is no window docked, we dock the top-most window.
+                Recents recents = getComponent(Recents.class);
+                int dockMode = (shortcutCode == SC_DOCK_LEFT)
+                        ? ActivityManager.DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT
+                        : ActivityManager.DOCKED_STACK_CREATE_MODE_BOTTOM_OR_RIGHT;
+                recents.dockTopTask(NavigationBarGestureHelper.DRAG_MODE_NONE, dockMode, null);
+                MetricsLogger.action(mContext, MetricsEvent.WINDOW_DOCK_SHORTCUTS);
+            } else {
+                // If there is already a docked window, we respond by resizing the docking pane.
+                DividerView dividerView = getComponent(Divider.class).getView();
+                DividerSnapAlgorithm snapAlgorithm = dividerView.getSnapAlgorithm();
+                int dividerPosition = dividerView.getCurrentPosition();
+                DividerSnapAlgorithm.SnapTarget currentTarget =
+                        snapAlgorithm.calculateNonDismissingSnapTarget(dividerPosition);
+                int increment = (shortcutCode == SC_DOCK_LEFT) ? -1 : 1;
+                DividerSnapAlgorithm.SnapTarget target = snapAlgorithm.cycleNonDismissTarget(
+                        currentTarget, increment);
+                dividerView.startDragging(true /* animate */, false /* touching */);
+                dividerView.stopDragging(target.position, 0f, true /* avoidDismissStart */);
+            }
+        } catch (RemoteException e) {
+            Log.e(TAG, "handleDockKey() failed.");
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/shortcut/ShortcutKeyServiceProxy.java b/packages/SystemUI/src/com/android/systemui/shortcut/ShortcutKeyServiceProxy.java
new file mode 100644
index 0000000..8ec862e
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/shortcut/ShortcutKeyServiceProxy.java
@@ -0,0 +1,58 @@
+/*
+ * 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.shortcut;
+
+import android.os.Handler;
+import android.os.Message;
+import android.os.RemoteException;
+import com.android.internal.policy.IShortcutService;
+
+/**
+ * This class takes functions from IShortcutService that come in binder pool threads and
+ * post them onto shortcut handlers.
+ */
+public class ShortcutKeyServiceProxy extends IShortcutService.Stub {
+    private static final int MSG_SHORTCUT_RECEIVED = 1;
+
+    private final Object mLock = new Object();
+    private Callbacks mCallbacks;
+    private final Handler mHandler = new H();
+
+    public interface Callbacks {
+        void onShortcutKeyPressed(long shortcutCode);
+    }
+
+    public ShortcutKeyServiceProxy(Callbacks callbacks) { mCallbacks = callbacks; }
+
+    @Override
+    public void notifyShortcutKeyPressed(long shortcutCode) throws RemoteException {
+        synchronized (mLock) {
+            mHandler.obtainMessage(MSG_SHORTCUT_RECEIVED, shortcutCode).sendToTarget();
+        }
+    }
+
+    private final class H extends Handler {
+        public void handleMessage(Message msg) {
+            final int what = msg.what;
+            switch (what) {
+                case MSG_SHORTCUT_RECEIVED:
+                    mCallbacks.onShortcutKeyPressed((Long)msg.obj);
+                    break;
+            }
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
index da5cbe7..e015666 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
@@ -16,6 +16,9 @@
 
 package com.android.systemui.stackdivider;
 
+import static android.view.PointerIcon.STYLE_HORIZONTAL_DOUBLE_ARROW;
+import static android.view.PointerIcon.STYLE_VERTICAL_DOUBLE_ARROW;
+
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
 import android.animation.ValueAnimator;
@@ -31,6 +34,9 @@
 import android.util.AttributeSet;
 import android.view.Display;
 import android.view.DisplayInfo;
+import android.view.GestureDetector;
+import android.view.GestureDetector.OnDoubleTapListener;
+import android.view.GestureDetector.SimpleOnGestureListener;
 import android.view.MotionEvent;
 import android.view.PointerIcon;
 import android.view.VelocityTracker;
@@ -39,6 +45,7 @@
 import android.view.ViewConfiguration;
 import android.view.ViewTreeObserver.InternalInsetsInfo;
 import android.view.ViewTreeObserver.OnComputeInternalInsetsListener;
+import android.view.ViewTreeObserver.OnGlobalLayoutListener;
 import android.view.WindowInsets;
 import android.view.WindowManager;
 import android.view.accessibility.AccessibilityNodeInfo;
@@ -52,17 +59,16 @@
 import com.android.internal.policy.DockedDividerUtils;
 import com.android.systemui.Interpolators;
 import com.android.systemui.R;
+import com.android.systemui.recents.Recents;
 import com.android.systemui.recents.events.EventBus;
-import com.android.systemui.recents.events.activity.DockingTopTaskEvent;
+import com.android.systemui.recents.events.activity.DockedTopTaskEvent;
 import com.android.systemui.recents.events.activity.RecentsActivityStartingEvent;
 import com.android.systemui.recents.events.activity.UndockingTaskEvent;
 import com.android.systemui.recents.events.ui.RecentsDrawnEvent;
+import com.android.systemui.recents.misc.SystemServicesProxy;
 import com.android.systemui.statusbar.FlingAnimationUtils;
 import com.android.systemui.statusbar.phone.NavigationBarGestureHelper;
 
-import static android.view.PointerIcon.STYLE_HORIZONTAL_DOUBLE_ARROW;
-import static android.view.PointerIcon.STYLE_VERTICAL_DOUBLE_ARROW;
-
 /**
  * Docked stack divider.
  */
@@ -123,6 +129,7 @@
     private final Rect mDockedInsetRect = new Rect();
     private final Rect mOtherInsetRect = new Rect();
     private final Rect mLastResizeRect = new Rect();
+    private final Rect mDisplayRect = new Rect();
     private final WindowManagerProxy mWindowManagerProxy = WindowManagerProxy.getInstance();
     private DividerWindowManager mWindowManager;
     private VelocityTracker mVelocityTracker;
@@ -133,7 +140,9 @@
     private boolean mAnimateAfterRecentsDrawn;
     private boolean mGrowAfterRecentsDrawn;
     private boolean mGrowRecents;
-    private Animator mCurrentAnimator;
+    private ValueAnimator mCurrentAnimator;
+    private boolean mEntranceAnimationRunning;
+    private GestureDetector mGestureDetector;
 
     private final AccessibilityDelegate mHandleDelegate = new AccessibilityDelegate() {
         @Override
@@ -211,12 +220,35 @@
                 landscape ? STYLE_HORIZONTAL_DOUBLE_ARROW : STYLE_VERTICAL_DOUBLE_ARROW));
         getViewTreeObserver().addOnComputeInternalInsetsListener(this);
         mHandle.setAccessibilityDelegate(mHandleDelegate);
+        mGestureDetector = new GestureDetector(mContext, new SimpleOnGestureListener() {
+            @Override
+            public boolean onSingleTapUp(MotionEvent e) {
+                updateDockSide();
+                SystemServicesProxy ssp = Recents.getSystemServices();
+                if (mDockSide != WindowManager.DOCKED_INVALID
+                        && !ssp.isRecentsTopMost(ssp.getTopMostTask(), null /* isTopHome */)) {
+                    mWindowManagerProxy.swapTasks();
+                    return true;
+                }
+                return false;
+            }
+        });
     }
 
     @Override
     protected void onAttachedToWindow() {
         super.onAttachedToWindow();
         EventBus.getDefault().register(this);
+        getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
+
+            @Override
+            public void onGlobalLayout() {
+                getViewTreeObserver().removeOnGlobalLayoutListener(this);
+                mWindowManagerProxy.setTouchRegion(new Rect(mHandle.getLeft(), mHandle.getTop(),
+                        mHandle.getLeft() + mHandle.getWidth(),
+                        mHandle.getTop() + mHandle.getHeight()));
+            }
+        });
     }
 
     @Override
@@ -318,6 +350,7 @@
     @Override
     public boolean onTouch(View v, MotionEvent event) {
         convertToScreenCoordinates(event);
+        mGestureDetector.onTouchEvent(event);
         final int action = event.getAction() & MotionEvent.ACTION_MASK;
         switch (action) {
             case MotionEvent.ACTION_DOWN:
@@ -411,6 +444,7 @@
                 mWindowManagerProxy.setResizing(false);
                 mDockSide = WindowManager.DOCKED_INVALID;
                 mCurrentAnimator = null;
+                mEntranceAnimationRunning = false;
             }
         });
         mCurrentAnimator = anim;
@@ -594,7 +628,18 @@
         }
 
         mLastResizeRect.set(mDockedRect);
-        if (taskPosition != TASK_POSITION_SAME) {
+        if (mEntranceAnimationRunning && taskPosition != TASK_POSITION_SAME) {
+            if (mCurrentAnimator != null) {
+                calculateBoundsForPosition(taskPosition, mDockSide, mDockedTaskRect);
+            } else {
+                calculateBoundsForPosition(isHorizontalDivision() ? mDisplayHeight : mDisplayWidth,
+                        mDockSide, mDockedTaskRect);
+            }
+            calculateBoundsForPosition(taskPosition, DockedDividerUtils.invertDockSide(mDockSide),
+                    mOtherTaskRect);
+            mWindowManagerProxy.resizeDockedStack(mDockedRect, mDockedTaskRect, null,
+                    mOtherTaskRect, null);
+        } else if (taskPosition != TASK_POSITION_SAME) {
             calculateBoundsForPosition(position, DockedDividerUtils.invertDockSide(mDockSide),
                     mOtherRect);
             int dockSideInverted = DockedDividerUtils.invertDockSide(mDockSide);
@@ -610,16 +655,17 @@
 
             calculateBoundsForPosition(taskPositionDocked, mDockSide, mDockedTaskRect);
             calculateBoundsForPosition(taskPositionOther, dockSideInverted, mOtherTaskRect);
+            mDisplayRect.set(0, 0, mDisplayWidth, mDisplayHeight);
             alignTopLeft(mDockedRect, mDockedTaskRect);
             alignTopLeft(mOtherRect, mOtherTaskRect);
             mDockedInsetRect.set(mDockedTaskRect);
             mOtherInsetRect.set(mOtherTaskRect);
             if (dockSideTopLeft(mDockSide)) {
-                alignTopLeft(mDockedRect, mDockedInsetRect);
-                alignBottomRight(mOtherRect, mOtherInsetRect);
+                alignTopLeft(mDisplayRect, mDockedInsetRect);
+                alignBottomRight(mDisplayRect, mOtherInsetRect);
             } else {
-                alignBottomRight(mDockedRect, mDockedInsetRect);
-                alignTopLeft(mOtherRect, mOtherInsetRect);
+                alignBottomRight(mDisplayRect, mDockedInsetRect);
+                alignTopLeft(mDisplayRect, mOtherInsetRect);
             }
             applyDismissingParallax(mDockedTaskRect, mDockSide, taskSnapTarget, position,
                     taskPositionDocked);
@@ -638,6 +684,9 @@
     }
 
     private float getDimFraction(int position, SnapTarget dismissTarget) {
+        if (mEntranceAnimationRunning) {
+            return 0f;
+        }
         float fraction = mSnapAlgorithm.calculateDismissingFraction(position);
         fraction = Math.max(0, Math.min(fraction, 1f));
         fraction = DIM_INTERPOLATOR.getInterpolation(fraction);
@@ -839,12 +888,18 @@
         }
     }
 
-    public final void onBusEvent(DockingTopTaskEvent dockingEvent) {
-        if (dockingEvent.dragMode == NavigationBarGestureHelper.DRAG_MODE_NONE) {
+    public final void onBusEvent(DockedTopTaskEvent event) {
+        if (event.dragMode == NavigationBarGestureHelper.DRAG_MODE_NONE) {
             mGrowAfterRecentsDrawn = false;
             mAnimateAfterRecentsDrawn = true;
             startDragging(false /* animate */, false /* touching */);
         }
+        updateDockSide();
+        int position = DockedDividerUtils.calculatePositionForBounds(event.initialRect,
+                mDockSide, mDividerSize);
+        mEntranceAnimationRunning = true;
+        resizeStack(position, mSnapAlgorithm.getMiddleTarget().position,
+                mSnapAlgorithm.getMiddleTarget());
     }
 
     public final void onBusEvent(RecentsDrawnEvent drawnEvent) {
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/WindowManagerProxy.java b/packages/SystemUI/src/com/android/systemui/stackdivider/WindowManagerProxy.java
index 15bcaf8..e312fa2 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/WindowManagerProxy.java
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/WindowManagerProxy.java
@@ -16,6 +16,9 @@
 
 package com.android.systemui.stackdivider;
 
+import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
+import static android.view.WindowManager.DOCKED_INVALID;
+
 import android.app.ActivityManagerNative;
 import android.graphics.Rect;
 import android.os.RemoteException;
@@ -27,9 +30,6 @@
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
 
-import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
-import static android.view.WindowManager.DOCKED_INVALID;
-
 /**
  * Proxy to simplify calls into window manager/activity manager
  */
@@ -39,7 +39,7 @@
 
     private static final WindowManagerProxy sInstance = new WindowManagerProxy();
 
-    @GuardedBy("mResizeRect")
+    @GuardedBy("mDockedRect")
     private final Rect mDockedRect = new Rect();
     private final Rect mTempDockedTaskRect = new Rect();
     private final Rect mTempDockedInsetRect = new Rect();
@@ -52,6 +52,9 @@
     private final Rect mTmpRect4 = new Rect();
     private final Rect mTmpRect5 = new Rect();
 
+    @GuardedBy("mDockedRect")
+    private final Rect mTouchableRegion = new Rect();
+
     private boolean mDimLayerVisible;
     private int mDimLayerTargetStack;
     private float mDimLayerAlpha;
@@ -117,6 +120,32 @@
         }
     };
 
+    private final Runnable mSwapRunnable = new Runnable() {
+        @Override
+        public void run() {
+            try {
+                ActivityManagerNative.getDefault().swapDockedAndFullscreenStack();
+            } catch (RemoteException e) {
+                Log.w(TAG, "Failed to resize stack: " + e);
+            }
+        }
+    };
+
+    private final Runnable mSetTouchableRegionRunnable = new Runnable() {
+        @Override
+        public void run() {
+            try {
+                synchronized (mDockedRect) {
+                    mTmpRect1.set(mTouchableRegion);
+                }
+                WindowManagerGlobal.getWindowManagerService().setDockedStackDividerTouchRegion(
+                        mTmpRect1);
+            } catch (RemoteException e) {
+                Log.w(TAG, "Failed to set touchable region: " + e);
+            }
+        }
+    };
+
     private WindowManagerProxy() {
     }
 
@@ -188,4 +217,15 @@
         mDimLayerAlpha = alpha;
         mExecutor.execute(mDimLayerRunnable);
     }
+
+    public void swapTasks() {
+        mExecutor.execute(mSwapRunnable);
+    }
+
+    public void setTouchRegion(Rect region) {
+        synchronized (mDockedRect) {
+            mTouchableRegion.set(region);
+        }
+        mExecutor.execute(mSetTouchableRegionRunnable);
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java b/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java
index effe581..71f74cd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java
@@ -36,7 +36,9 @@
 import com.android.systemui.R;
 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.stack.NotificationStackScrollLayout;
+import com.android.systemui.statusbar.stack.StackStateAnimator;
 
 /**
  * Base class for both {@link ExpandableNotificationRow} and {@link NotificationOverflowContainer}
@@ -121,6 +123,7 @@
     private float mAnimationTranslationY;
     private boolean mDrawingAppearAnimation;
     private ValueAnimator mAppearAnimator;
+    private ValueAnimator mBackgroundColorAnimator;
     private float mAppearAnimationFraction = -1.0f;
     private float mAppearAnimationTranslation;
     private boolean mShowingLegacyBackground;
@@ -145,7 +148,7 @@
         public void onAnimationEnd(Animator animation) {
             super.onAnimationEnd(animation);
             mFadeInFromDarkAnimator = null;
-            updateOutlineAlpha();
+            updateBackground();
         }
     };
     private ValueAnimator.AnimatorUpdateListener mUpdateOutlineListener
@@ -157,6 +160,9 @@
     };
     private float mShadowAlpha = 1.0f;
     private FakeShadowView mFakeShadow;
+    private int mCurrentBackgroundTint;
+    private int mTargetTint;
+    private int mStartTint;
 
     public ActivatableNotificationView(Context context, AttributeSet attrs) {
         super(context, attrs);
@@ -334,9 +340,7 @@
             animator.addListener(new AnimatorListenerAdapter() {
                 @Override
                 public void onAnimationEnd(Animator animation) {
-                    if (mDimmed) {
-                        mBackgroundNormal.setVisibility(View.INVISIBLE);
-                    }
+                    updateBackground();
                 }
             });
             animator.start();
@@ -365,14 +369,14 @@
      */
     public void makeInactive(boolean animate) {
         if (mActivated) {
+            mActivated = false;
             if (mDimmed) {
                 if (animate) {
                     startActivateAnimation(true /* reverse */);
                 } else {
-                    mBackgroundNormal.setVisibility(View.INVISIBLE);
+                    updateBackground();
                 }
             }
-            mActivated = false;
         }
         if (mOnActivatedListener != null) {
             mOnActivatedListener.onActivationReset(this);
@@ -402,20 +406,9 @@
             return;
         }
         mDark = dark;
+        updateBackground();
         if (!dark && fade && !shouldHideBackground()) {
-            if (mActivated) {
-                mBackgroundDimmed.setVisibility(View.VISIBLE);
-                mBackgroundNormal.setVisibility(View.VISIBLE);
-            } else if (mDimmed) {
-                mBackgroundDimmed.setVisibility(View.VISIBLE);
-                mBackgroundNormal.setVisibility(View.INVISIBLE);
-            } else {
-                mBackgroundDimmed.setVisibility(View.INVISIBLE);
-                mBackgroundNormal.setVisibility(View.VISIBLE);
-            }
             fadeInFromDark(delay);
-        } else {
-            updateBackground();
         }
         updateOutlineAlpha();
     }
@@ -457,21 +450,63 @@
      * Sets the tint color of the background
      */
     public void setTintColor(int color) {
+        setTintColor(color, false);
+    }
+
+    /**
+     * Sets the tint color of the background
+     */
+    public void setTintColor(int color, boolean animated) {
         mBgTint = color;
-        updateBackgroundTint();
+        updateBackgroundTint(animated);
     }
 
     protected void updateBackgroundTint() {
-        int color = getBgColor();
+        updateBackgroundTint(false /* animated */);
+    }
+
+    private void updateBackgroundTint(boolean animated) {
+        if (mBackgroundColorAnimator != null) {
+            mBackgroundColorAnimator.cancel();
+        }
         int rippleColor = getRippleColor();
+        mBackgroundDimmed.setRippleColor(rippleColor);
+        mBackgroundNormal.setRippleColor(rippleColor);
+        int color = calculateBgColor();
+        if (!animated) {
+            setBackgroundTintColor(color);
+        } else if (color != mCurrentBackgroundTint) {
+            mStartTint = mCurrentBackgroundTint;
+            mTargetTint = color;
+            mBackgroundColorAnimator = ValueAnimator.ofFloat(0.0f, 1.0f);
+            mBackgroundColorAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
+                @Override
+                public void onAnimationUpdate(ValueAnimator animation) {
+                    int newColor = NotificationUtils.interpolateColors(mStartTint, mTargetTint,
+                            animation.getAnimatedFraction());
+                    setBackgroundTintColor(newColor);
+                }
+            });
+            mBackgroundColorAnimator.setDuration(StackStateAnimator.ANIMATION_DURATION_STANDARD);
+            mBackgroundColorAnimator.setInterpolator(Interpolators.LINEAR);
+            mBackgroundColorAnimator.addListener(new AnimatorListenerAdapter() {
+                @Override
+                public void onAnimationEnd(Animator animation) {
+                    mBackgroundColorAnimator = null;
+                }
+            });
+            mBackgroundColorAnimator.start();
+        }
+    }
+
+    private void setBackgroundTintColor(int color) {
+        mCurrentBackgroundTint = color;
         if (color == mNormalColor) {
             // We don't need to tint a normal notification
             color = 0;
         }
         mBackgroundDimmed.setTint(color);
         mBackgroundNormal.setTint(color);
-        mBackgroundDimmed.setRippleColor(rippleColor);
-        mBackgroundNormal.setRippleColor(rippleColor);
     }
 
     /**
@@ -480,6 +515,7 @@
     private void fadeInFromDark(long delay) {
         final View background = mDimmed ? mBackgroundDimmed : mBackgroundNormal;
         background.setAlpha(0f);
+        mBackgroundVisibilityUpdater.onAnimationUpdate(null);
         background.setPivotX(mBackgroundDimmed.getWidth() / 2f);
         background.setPivotY(getActualHeight() / 2f);
         background.setScaleX(DARK_EXIT_SCALE_START);
@@ -517,6 +553,10 @@
     private void fadeDimmedBackground() {
         mBackgroundDimmed.animate().cancel();
         mBackgroundNormal.animate().cancel();
+        if (mActivated) {
+            updateBackground();
+            return;
+        }
         if (!shouldHideBackground()) {
             if (mDimmed) {
                 mBackgroundDimmed.setVisibility(View.VISIBLE);
@@ -546,11 +586,7 @@
         mBackgroundAnimator.addListener(new AnimatorListenerAdapter() {
             @Override
             public void onAnimationEnd(Animator animation) {
-                if (mDimmed) {
-                    mBackgroundNormal.setVisibility(View.INVISIBLE);
-                } else {
-                    mBackgroundDimmed.setVisibility(View.INVISIBLE);
-                }
+                updateBackground();
                 mBackgroundAnimator = null;
             }
         });
@@ -565,12 +601,14 @@
             mBackgroundNormal.setVisibility(View.INVISIBLE);
         } else if (mDimmed) {
             mBackgroundDimmed.setVisibility(View.VISIBLE);
-            mBackgroundNormal.setVisibility(View.INVISIBLE);
+            mBackgroundNormal.setVisibility(mActivated ? View.VISIBLE : View.INVISIBLE);
         } else {
             mBackgroundDimmed.setVisibility(View.INVISIBLE);
             mBackgroundNormal.setVisibility(View.VISIBLE);
             mBackgroundNormal.setAlpha(1f);
             removeCallbacks(mTapTimeoutRunnable);
+            // make in inactive to avoid it sticking around active
+            makeInactive(false /* animate */);
         }
         setNormalBackgroundVisibilityAmount(
                 mBackgroundNormal.getVisibility() == View.VISIBLE ? 1.0f : 0.0f);
@@ -773,8 +811,12 @@
 
     protected abstract View getContentView();
 
-    public int getBgColor() {
-        if (mBgTint != 0) {
+    public int calculateBgColor() {
+        return calculateBgColor(true /* withTint */);
+    }
+
+    private int calculateBgColor(boolean withTint) {
+        if (withTint && mBgTint != 0) {
             return mBgTint;
         } else if (mShowingLegacyBackground) {
             return mLegacyColor;
@@ -839,7 +881,7 @@
     }
 
     public boolean hasSameBgColor(ActivatableNotificationView otherView) {
-        return getBgColor() == otherView.getBgColor();
+        return calculateBgColor() == otherView.calculateBgColor();
     }
 
     @Override
@@ -863,6 +905,10 @@
                 outlineTranslation);
     }
 
+    public int getBackgroundColorWithoutTint() {
+        return calculateBgColor(false /* withTint */);
+    }
+
     public interface OnActivatedListener {
         void onActivated(ActivatableNotificationView view);
         void onActivationReset(ActivatableNotificationView view);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
index 6be9512..143f160 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
@@ -110,7 +110,7 @@
 import java.util.List;
 import java.util.Locale;
 
-import static android.service.notification.NotificationListenerService.Ranking.IMPORTANCE_MAX;
+import static android.service.notification.NotificationListenerService.Ranking.IMPORTANCE_HIGH;
 import static com.android.keyguard.KeyguardHostView.OnDismissAction;
 
 public abstract class BaseStatusBar extends SystemUI implements
@@ -194,6 +194,7 @@
     // public mode, private notifications, etc
     private boolean mLockscreenPublicMode = false;
     private final SparseBooleanArray mUsersAllowingPrivateNotifications = new SparseBooleanArray();
+    private final SparseBooleanArray mUsersAllowingNotifications = new SparseBooleanArray();
 
     private UserManager mUserManager;
     private int mDensity;
@@ -959,7 +960,7 @@
         }, false /* afterKeyguardGone */);
     }
 
-    private void bindGuts(ExpandableNotificationRow row) {
+    private void bindGuts(final ExpandableNotificationRow row) {
         row.inflateGuts();
         final StatusBarNotification sbn = row.getStatusBarNotification();
         PackageManager pmUser = getPackageManagerForUser(mContext, sbn.getUser().getIdentifier());
@@ -983,7 +984,7 @@
             pkgicon = pmUser.getDefaultActivityIcon();
         }
 
-        ((ImageView) row.findViewById(android.R.id.icon)).setImageDrawable(pkgicon);
+        ((ImageView) row.findViewById(R.id.app_icon)).setImageDrawable(pkgicon);
         ((TextView) row.findViewById(R.id.pkgname)).setText(appname);
 
         final View settingsButton = guts.findViewById(R.id.more_settings);
@@ -1003,11 +1004,21 @@
             @Override
             public void onClick(View v) {
                 guts.saveImportance(sbn);
-                dismissPopups();
+
+                int[] rowLocation = new int[2];
+                int[] doneLocation = new int[2];
+                row.getLocationOnScreen(rowLocation);
+                v.getLocationOnScreen(doneLocation);
+
+                final int centerX = v.getWidth() / 2;
+                final int centerY = v.getHeight() / 2;
+                final int x = doneLocation[0] - rowLocation[0] + centerX;
+                final int y = doneLocation[1] - rowLocation[1] + centerY;
+                dismissPopups(x, y);
             }
         });
 
-        guts.bindImportance(sbn, row, mNotificationData.getImportance(sbn.getKey()));
+        guts.bindImportance(pmUser, sbn, row, mNotificationData.getImportance(sbn.getKey()));
     }
 
     protected GearDisplayedListener getGearDisplayedListener() {
@@ -1044,12 +1055,12 @@
 
                 MetricsLogger.action(mContext, MetricsEvent.ACTION_NOTE_CONTROLS);
 
-                // ensure that it's layouted but not visible until actually laid out
+                // ensure that it's laid but not visible until actually laid out
                 guts.setVisibility(View.INVISIBLE);
-                // Post to ensure the the guts are properly layed out.
+                // Post to ensure the the guts are properly laid out.
                 guts.post(new Runnable() {
                     public void run() {
-                        dismissPopups();
+                        dismissPopups(-1 /* x */, -1 /* y */, false /* resetGear */);
                         guts.setVisibility(View.VISIBLE);
                         final double horz = Math.max(guts.getWidth() - x, x);
                         final double vert = Math.max(guts.getHeight() - y, y);
@@ -1079,14 +1090,20 @@
 
     @Override
     public void onGearDisplayed(ExpandableNotificationRow row) {
+        MetricsLogger.action(mContext, MetricsEvent.ACTION_REVEAL_GEAR,
+                row.getStatusBarNotification().getPackageName());
         mNotificationGearDisplayed = row;
     }
 
     public void dismissPopups() {
-        dismissPopups(-1, -1);
+        dismissPopups(-1 /* x */, -1 /* y */, true /* resetGear */);
     }
 
     private void dismissPopups(int x, int y) {
+        dismissPopups(x, y, true /* resetGear */);
+    }
+
+    public void dismissPopups(int x, int y, boolean resetGear) {
         if (mNotificationGutsExposed != null) {
             final NotificationGuts v = mNotificationGutsExposed;
             mNotificationGutsExposed = null;
@@ -1114,8 +1131,7 @@
             v.setExposed(false);
             mStackScroller.onHeightChanged(null, true /* needsAnimation */);
         }
-
-        if (mNotificationGearDisplayed != null) {
+        if (resetGear && mNotificationGearDisplayed != null) {
             mNotificationGearDisplayed.resetTranslation();
             mNotificationGearDisplayed = null;
         }
@@ -1289,6 +1305,26 @@
     }
 
     /**
+     * Has the given user chosen to allow notifications to be shown even when the lockscreen is in
+     * "public" (secure & locked) mode?
+     */
+    public boolean userAllowsNotificationsInPublic(int userHandle) {
+        if (userHandle == UserHandle.USER_ALL) {
+            return true;
+        }
+
+        if (mUsersAllowingNotifications.indexOfKey(userHandle) < 0) {
+            final boolean allowed = 0 != Settings.Secure.getIntForUser(
+                    mContext.getContentResolver(),
+                    Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS, 0, userHandle);
+            mUsersAllowingNotifications.append(userHandle, allowed);
+            return allowed;
+        }
+
+        return mUsersAllowingNotifications.get(userHandle);
+    }
+
+    /**
      * Has the given user chosen to allow their private (full) notifications to be shown even
      * when the lockscreen is in "public" (secure & locked) mode?
      */
@@ -1320,13 +1356,30 @@
     }
 
     /**
-     * Returns true if we're on a secure lockscreen and the user wants to hide "sensitive"
-     * notification data. If so, private notifications should show their (possibly
-     * auto-generated) publicVersion, and secret notifications should be totally invisible.
+     * Returns true if we're on a secure lockscreen and the user wants to hide notification data.
+     * If so, notifications should be hidden.
      */
     @Override  // NotificationData.Environment
-    public boolean shouldHideSensitiveContents(int userid) {
-        return isLockscreenPublicMode() && !userAllowsPrivateNotificationsInPublic(userid);
+    public boolean shouldHideNotifications(int userid) {
+        return isLockscreenPublicMode() && !userAllowsNotificationsInPublic(userid);
+    }
+
+    /**
+     * Returns true if we're on a secure lockscreen and the user wants to hide notifications via
+     * package-specific override.
+     */
+    @Override // NotificationDate.Environment
+    public boolean shouldHideNotifications(String key) {
+        return isLockscreenPublicMode()
+                && mNotificationData.getVisibilityOverride(key) == Notification.VISIBILITY_SECRET;
+    }
+
+    /**
+     * Returns true if we're on a secure lockscreen.
+     */
+    @Override  // NotificationData.Environment
+    public boolean onSecureLockScreen() {
+        return isLockscreenPublicMode();
     }
 
     public void onNotificationClear(StatusBarNotification notification) {
@@ -1838,7 +1891,7 @@
         }
     }
 
-    protected abstract boolean isPanelFullyCollapsed();
+    public abstract boolean isPanelFullyCollapsed();
 
     /**
      * Cancel this notification and tell the StatusBarManagerService / NotificationManagerService
@@ -2215,6 +2268,16 @@
             return false;
         }
 
+        if (isSnoozedPackage(sbn)) {
+            if (DEBUG) Log.d(TAG, "No peeking: snoozed package: " + sbn.getKey());
+            return false;
+        }
+
+        if (mNotificationData.getImportance(sbn.getKey()) < IMPORTANCE_HIGH) {
+            if (DEBUG) Log.d(TAG, "No peeking: unimportant notification: " + sbn.getKey());
+            return false;
+        }
+
         if (sbn.getNotification().fullScreenIntent != null) {
             if (mAccessibilityManager.isTouchExplorationEnabled()) {
                 if (DEBUG) Log.d(TAG, "No peeking: accessible fullscreen: " + sbn.getKey());
@@ -2224,16 +2287,6 @@
             }
         }
 
-        if (isSnoozedPackage(sbn)) {
-            if (DEBUG) Log.d(TAG, "No peeking: snoozed package: " + sbn.getKey());
-            return false;
-        }
-
-        if (mNotificationData.getImportance(sbn.getKey()) < IMPORTANCE_MAX) {
-            if (DEBUG) Log.d(TAG, "No peeking: unimportant notification: " + sbn.getKey());
-            return false;
-        }
-
         return true;
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/DragDownHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/DragDownHelper.java
index b326552..7f87c3c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/DragDownHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/DragDownHelper.java
@@ -169,21 +169,23 @@
                 ? RUBBERBAND_FACTOR_EXPANDABLE
                 : RUBBERBAND_FACTOR_STATIC;
         float rubberband = heightDelta * rubberbandFactor;
-        if (expandable && (rubberband + child.getMinHeight()) > child.getMaxContentHeight()) {
-            float overshoot = (rubberband + child.getMinHeight()) - child.getMaxContentHeight();
+        if (expandable
+                && (rubberband + child.getMinExpandHeight()) > child.getMaxContentHeight()) {
+            float overshoot =
+                    (rubberband + child.getMinExpandHeight()) - child.getMaxContentHeight();
             overshoot *= (1 - RUBBERBAND_FACTOR_STATIC);
             rubberband -= overshoot;
         }
-        child.setActualHeight((int) (child.getMinHeight() + rubberband));
+        child.setActualHeight((int) (child.getMinExpandHeight() + rubberband));
     }
 
     private void cancelExpansion(final ExpandableView child) {
-        if (child.getActualHeight() == child.getMinHeight()) {
+        if (child.getActualHeight() == child.getMinExpandHeight()) {
             mCallback.setUserLockedChild(child, false);
             return;
         }
         ObjectAnimator anim = ObjectAnimator.ofInt(child, "actualHeight",
-                child.getActualHeight(), child.getMinHeight());
+                child.getActualHeight(), child.getMinExpandHeight());
         anim.setInterpolator(Interpolators.FAST_OUT_SLOW_IN);
         anim.setDuration(SPRING_BACK_ANIMATION_LENGTH_MS);
         anim.addListener(new AnimatorListenerAdapter() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
index da125d8..51553be 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
@@ -105,7 +105,6 @@
     private boolean mClearable;
     private ExpansionLogger mLogger;
     private String mLoggingKey;
-    private boolean mWasReset;
     private NotificationSettingsIconRow mSettingsIconRow;
     private NotificationGuts mGuts;
     private NotificationData.Entry mEntry;
@@ -569,6 +568,13 @@
         mPublicLayout.reInflateViews();
     }
 
+    public void setContentBackground(int customBackgroundColor, boolean animate,
+            NotificationContentView notificationContentView) {
+        if (getShowingLayout() == notificationContentView) {
+            setTintColor(customBackgroundColor, animate);
+        }
+    }
+
     public interface ExpansionLogger {
         public void logNotificationExpansion(String key, boolean userAction, boolean expanded);
     }
@@ -614,20 +620,16 @@
         mShowingPublicInitialized = false;
         mIsSystemExpanded = false;
         mOnKeyguard = false;
-        mPublicLayout.reset(mIsHeadsUp);
-        mPrivateLayout.reset(mIsHeadsUp);
+        mPublicLayout.reset();
+        mPrivateLayout.reset();
         resetHeight();
         resetTranslation();
         logExpansionEvent(false, wasExpanded);
     }
 
     public void resetHeight() {
-        if (mIsHeadsUp) {
-            resetActualHeight();
-        }
         mMaxExpandHeight = 0;
         mHeadsUpHeight = 0;
-        mWasReset = true;
         onHeightReset();
         requestLayout();
     }
@@ -656,7 +658,6 @@
                 mGuts = (NotificationGuts) inflated;
                 mGuts.setClipTopAmount(getClipTopAmount());
                 mGuts.setActualHeight(getActualHeight());
-                mTranslateableViews.add(mGuts);
                 mGutsStub = null;
             }
         });
@@ -684,7 +685,7 @@
         mTranslateableViews.remove(mGutsStub);
     }
 
-    public void setTranslationForOutline(float translationX) {
+    private void setTranslationForOutline(float translationX) {
         setOutlineRect(false, translationX, getTop(), getRight() + translationX, getBottom());
     }
 
@@ -704,6 +705,46 @@
         if (mTranslateAnim != null) {
             mTranslateAnim.cancel();
         }
+        mTranslateAnim = (AnimatorSet) getTranslateViewAnimator(leftTarget,
+                null /* updateListener */);
+        if (mTranslateAnim != null) {
+            mTranslateAnim.start();
+        }
+    }
+
+    @Override
+    public void setTranslation(float translationX) {
+        if (areGutsExposed()) {
+            // Don't translate if guts are showing.
+            return;
+        }
+        // Translate the group of views
+        for (int i = 0; i < mTranslateableViews.size(); i++) {
+            if (mTranslateableViews.get(i) != null) {
+                mTranslateableViews.get(i).setTranslationX(translationX);
+            }
+        }
+        setTranslationForOutline(translationX);
+        if (mSettingsIconRow != null) {
+            mSettingsIconRow.updateSettingsIcons(translationX, getMeasuredWidth());
+        }
+    }
+
+    @Override
+    public float getTranslation() {
+        if (mTranslateableViews != null && mTranslateableViews.size() > 0) {
+            // All of the views in the list should have same translation, just use first one.
+            return mTranslateableViews.get(0).getTranslationX();
+        }
+        return 0;
+    }
+
+    public Animator getTranslateViewAnimator(final float leftTarget,
+            AnimatorUpdateListener listener) {
+        if (areGutsExposed()) {
+            // No translation if guts are exposed.
+            return null;
+        }
         AnimatorSet set = new AnimatorSet();
         if (mTranslateableViews != null) {
             for (int i = 0; i < mTranslateableViews.size(); i++) {
@@ -715,8 +756,15 @@
                         @Override
                         public void onAnimationUpdate(ValueAnimator animation) {
                             setTranslationForOutline((float) animation.getAnimatedValue());
+                            if (mSettingsIconRow != null) {
+                                mSettingsIconRow.updateSettingsIcons(
+                                        (float) animation.getAnimatedValue(), getMeasuredWidth());
+                            }
                         }
                     });
+                    if (listener != null) {
+                        translateAnim.addUpdateListener(listener);
+                    }
                 }
                 translateAnim.addListener(new AnimatorListenerAdapter() {
                     @Override
@@ -730,8 +778,7 @@
                 set.play(translateAnim);
             }
         }
-        mTranslateAnim = set;
-        set.start();
+        return set;
     }
 
     public float getSpaceForGear() {
@@ -748,10 +795,6 @@
         return mSettingsIconRow;
     }
 
-    public ArrayList<View> getContentViews() {
-        return mTranslateableViews;
-    }
-
     public void inflateGuts() {
         if (mGuts == null) {
             mGutsStub.inflate();
@@ -922,18 +965,6 @@
         return mStatusBarNotification != null && mStatusBarNotification.isClearable();
     }
 
-    /**
-     * Apply an expansion state to the layout.
-     */
-    public void applyExpansionToLayout() {
-        boolean expand = isExpanded();
-        if (expand && mExpandable) {
-            setActualHeight(mMaxExpandHeight);
-        } else {
-            setActualHeight(getMinHeight());
-        }
-    }
-
     @Override
     public int getIntrinsicHeight() {
         if (isUserLocked()) {
@@ -986,7 +1017,6 @@
         }
         mPrivateLayout.updateExpandButtons(isExpandable());
         updateChildrenHeaderAppearance();
-        updateHeaderChildCount();
         updateChildrenVisibility();
     }
 
@@ -999,7 +1029,11 @@
      * @return whether the view state is currently expanded.
      */
     public boolean isExpanded() {
-        return !mOnKeyguard
+        return isExpanded(false /* allowOnKeyguard */);
+    }
+
+    public boolean isExpanded(boolean allowOnKeyguard) {
+        return (!mOnKeyguard || allowOnKeyguard)
                 && (!hasUserChangedExpansion() && (isSystemExpanded() || isSystemChildExpanded())
                 || isUserExpanded());
     }
@@ -1015,12 +1049,7 @@
     @Override
     protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
         super.onLayout(changed, left, top, right, bottom);
-        boolean updateExpandHeight = mMaxExpandHeight == 0 && !mWasReset;
         updateMaxHeights();
-        if (updateExpandHeight) {
-            applyExpansionToLayout();
-        }
-        mWasReset = false;
     }
 
     private void updateMaxHeights() {
@@ -1053,6 +1082,14 @@
 
     public void setHideSensitiveForIntrinsicHeight(boolean hideSensitive) {
         mHideSensitiveForIntrinsicHeight = hideSensitive;
+        if (mIsSummaryWithChildren) {
+            List<ExpandableNotificationRow> notificationChildren =
+                    mChildrenContainer.getNotificationChildren();
+            for (int i = 0; i < notificationChildren.size(); i++) {
+                ExpandableNotificationRow child = notificationChildren.get(i);
+                child.setHideSensitiveForIntrinsicHeight(hideSensitive);
+            }
+        }
     }
 
     public void setHideSensitive(boolean hideSensitive, boolean animated, long delay,
@@ -1076,7 +1113,8 @@
         } else {
             animateShowingPublic(delay, duration);
         }
-
+        NotificationContentView showingLayout = getShowingLayout();
+        showingLayout.updateBackgroundColor(animated);
         mPrivateLayout.updateExpandButtons(isExpandable());
         updateClearability();
         mShowingPublicInitialized = true;
@@ -1134,13 +1172,6 @@
         }
     }
 
-    public void updateHeaderChildCount() {
-        if (mIsSummaryWithChildren) {
-            mNotificationHeader.setChildCount(
-                    mChildrenContainer.getNotificationChildren().size());
-        }
-    }
-
     public static void applyTint(View v, int color) {
         int alpha;
         if (color != 0) {
@@ -1161,6 +1192,10 @@
         return mMaxExpandHeight;
     }
 
+    public boolean areGutsExposed() {
+        return (mGuts != null && mGuts.areGutsExposed());
+    }
+
     @Override
     public boolean isContentExpandable() {
         NotificationContentView showingLayout = getShowingLayout();
@@ -1175,6 +1210,10 @@
     @Override
     public void setActualHeight(int height, boolean notifyListeners) {
         super.setActualHeight(height, notifyListeners);
+        if (mGuts != null && mGuts.areGutsExposed()) {
+            mGuts.setActualHeight(height);
+            return;
+        }
         int contentHeight = Math.max(getMinHeight(), height);
         mPrivateLayout.setContentHeight(contentHeight);
         mPublicLayout.setContentHeight(contentHeight);
@@ -1184,7 +1223,6 @@
         if (mGuts != null) {
             mGuts.setActualHeight(height);
         }
-        invalidate();
     }
 
     @Override
@@ -1211,8 +1249,8 @@
 
     @Override
     public int getMinExpandHeight() {
-        if (mIsSummaryWithChildren && !mOnKeyguard) {
-            return mChildrenContainer.getMinExpandHeight();
+        if (mIsSummaryWithChildren && !mShowingPublic) {
+            return mChildrenContainer.getMinExpandHeight(mOnKeyguard);
         }
         return getMinHeight();
     }
@@ -1245,15 +1283,7 @@
             header.reapply(getContext(), mNotificationHeader);
             mNotificationHeaderWrapper.notifyContentUpdated(mEntry.notification);
         }
-        updateHeaderExpandButton();
         updateChildrenHeaderAppearance();
-        updateHeaderChildCount();
-    }
-
-    private void updateHeaderExpandButton() {
-        if (mIsSummaryWithChildren) {
-            mNotificationHeader.setIsGroupHeader(true /* isGroupHeader*/);
-        }
     }
 
     public void updateChildrenHeaderAppearance() {
@@ -1319,7 +1349,7 @@
         float y = event.getY();
         NotificationHeaderView header = getVisibleNotificationHeader();
         if (header != null) {
-            return header.isInTouchRect(x, y);
+            return header.isInTouchRect(x - getTranslation(), y);
         }
         return super.disallowSingleClick(event);
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java
index 1ff87f5..91418ad 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java
@@ -36,7 +36,6 @@
     protected OnHeightChangedListener mOnHeightChangedListener;
     private int mActualHeight;
     protected int mClipTopAmount;
-    private boolean mActualHeightInitialized;
     private boolean mDark;
     private ArrayList<View> mMatchParentViews = new ArrayList<View>();
     private int mClipTopOptimization;
@@ -44,6 +43,7 @@
     private boolean mWillBeGone;
     private int mMinClipTopAmount = 0;
     private boolean mClipToActualHeight = true;
+    private boolean mChangingPosition = false;
 
     public ExpandableView(Context context, AttributeSet attrs) {
         super(context, attrs);
@@ -99,28 +99,9 @@
     @Override
     protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
         super.onLayout(changed, left, top, right, bottom);
-        if (!mActualHeightInitialized && mActualHeight == 0) {
-            int initialHeight = getInitialHeight();
-            if (initialHeight != 0) {
-                setActualHeight(initialHeight);
-            }
-        }
         updateClipping();
     }
 
-    /**
-     * Resets the height of the view on the next layout pass
-     */
-    protected void resetActualHeight() {
-        mActualHeight = 0;
-        mActualHeightInitialized = false;
-        requestLayout();
-    }
-
-    protected int getInitialHeight() {
-        return getHeight();
-    }
-
     @Override
     public boolean pointInView(float localX, float localY, float slop) {
         float top = mClipTopAmount;
@@ -137,7 +118,6 @@
      * @param notifyListeners Whether the listener should be informed about the change.
      */
     public void setActualHeight(int actualHeight, boolean notifyListeners) {
-        mActualHeightInitialized = true;
         mActualHeight = actualHeight;
         updateClipping();
         if (notifyListeners) {
@@ -283,6 +263,20 @@
     public void setBelowSpeedBump(boolean below) {
     }
 
+    /**
+     * Sets the translation of the view.
+     */
+    public void setTranslation(float translation) {
+        setTranslationX(translation);
+    }
+
+    /**
+     * Gets the translation of the view.
+     */
+    public float getTranslation() {
+        return getTranslationX();
+    }
+
     public void onHeightReset() {
         if (mOnHeightChangedListener != null) {
             mOnHeightChangedListener.onReset(this);
@@ -414,6 +408,14 @@
         return 0;
     }
 
+    public void setChangingPosition(boolean changingPosition) {
+        mChangingPosition = changingPosition;
+    }
+
+    public boolean isChangingPosition() {
+        return mChangingPosition;
+    }
+
     /**
      * A listener notifying when {@link #getActualHeight} changes.
      */
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
index 977b37e..3b87577 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
@@ -33,6 +33,7 @@
 import com.android.systemui.statusbar.notification.HybridNotificationView;
 import com.android.systemui.statusbar.notification.HybridNotificationViewManager;
 import com.android.systemui.statusbar.notification.NotificationCustomViewWrapper;
+import com.android.systemui.statusbar.notification.NotificationUtils;
 import com.android.systemui.statusbar.notification.NotificationViewWrapper;
 import com.android.systemui.statusbar.phone.NotificationGroupManager;
 import com.android.systemui.statusbar.policy.RemoteInputView;
@@ -48,7 +49,7 @@
     private static final int VISIBLE_TYPE_EXPANDED = 1;
     private static final int VISIBLE_TYPE_HEADSUP = 2;
     private static final int VISIBLE_TYPE_SINGLELINE = 3;
-    private static final int UNDEFINED = -1;
+    public static final int UNDEFINED = -1;
 
     private final Rect mClipBounds = new Rect();
     private final int mMinContractedHeight;
@@ -92,7 +93,14 @@
             = new ViewTreeObserver.OnPreDrawListener() {
         @Override
         public boolean onPreDraw() {
-            mAnimate = true;
+            // We need to post since we don't want the notification to animate on the very first
+            // frame
+            post(new Runnable() {
+                @Override
+                public void run() {
+                    mAnimate = true;
+                }
+            });
             getViewTreeObserver().removeOnPreDrawListener(this);
             return true;
         }
@@ -113,7 +121,7 @@
                 R.dimen.min_notification_layout_height);
         mNotificationContentMarginEnd = getResources().getDimensionPixelSize(
                 com.android.internal.R.dimen.notification_content_margin_end);
-        reset(true);
+        reset();
     }
 
     public void setHeights(int smallHeight, int headsUpMaxHeight, int maxHeight) {
@@ -248,7 +256,7 @@
         updateVisibility();
     }
 
-    public void reset(boolean resetActualHeight) {
+    public void reset() {
         if (mContractedChild != null) {
             mContractedChild.animate().cancel();
             removeView(mContractedChild);
@@ -264,10 +272,6 @@
         mContractedChild = null;
         mExpandedChild = null;
         mHeadsUpChild = null;
-        mVisibleType = VISIBLE_TYPE_CONTRACTED;
-        if (resetActualHeight) {
-            mContentHeight = mSmallHeight;
-        }
     }
 
     public View getContractedChild() {
@@ -364,6 +368,7 @@
             getViewForVisibleType(visibleType).setVisibility(View.VISIBLE);
             hiddenView.transformTo(shownView, 0.0f);
             mVisibleType = visibleType;
+            updateBackgroundColor(true /* animate */);
         }
         if (mTransformationStartVisibleType != UNDEFINED
                 && mVisibleType != mTransformationStartVisibleType) {
@@ -373,11 +378,29 @@
             float transformationAmount = calculateTransformationAmount();
             shownView.transformFrom(hiddenView, transformationAmount);
             hiddenView.transformTo(shownView, transformationAmount);
+            updateBackgroundTransformation(transformationAmount);
         } else {
             updateViewVisibilities(visibleType);
+            updateBackgroundColor(false);
         }
     }
 
+    private void updateBackgroundTransformation(float transformationAmount) {
+        int endColor = getBackgroundColor(mVisibleType);
+        int startColor = getBackgroundColor(mTransformationStartVisibleType);
+        if (endColor != startColor) {
+            if (startColor == 0) {
+                startColor = mContainingNotification.getBackgroundColorWithoutTint();
+            }
+            if (endColor == 0) {
+                endColor = mContainingNotification.getBackgroundColorWithoutTint();
+            }
+            endColor = NotificationUtils.interpolateColors(startColor, endColor,
+                    transformationAmount);
+        }
+        mContainingNotification.setContentBackground(endColor, false, this);
+    }
+
     private float calculateTransformationAmount() {
         int startHeight = getViewForVisibleType(mTransformationStartVisibleType).getHeight();
         int endHeight = getViewForVisibleType(mVisibleType).getHeight();
@@ -454,9 +477,24 @@
                 updateViewVisibilities(visibleType);
             }
             mVisibleType = visibleType;
+            updateBackgroundColor(animate);
         }
     }
 
+    public void updateBackgroundColor(boolean animate) {
+        int customBackgroundColor = getBackgroundColor(mVisibleType);
+        mContainingNotification.setContentBackground(customBackgroundColor, animate, this);
+    }
+
+    private int getBackgroundColor(int visibleType) {
+        NotificationViewWrapper currentVisibleWrapper = getVisibleWrapper(visibleType);
+        int customBackgroundColor = 0;
+        if (currentVisibleWrapper != null) {
+            customBackgroundColor = currentVisibleWrapper.getCustomBackgroundColor();
+        }
+        return customBackgroundColor;
+    }
+
     private void updateViewVisibilities(int visibleType) {
         boolean contractedVisible = visibleType == VISIBLE_TYPE_CONTRACTED;
         mContractedWrapper.setVisible(contractedVisible);
@@ -477,12 +515,18 @@
     private void animateToVisibleType(int visibleType) {
         final TransformableView shownView = getTransformableViewForVisibleType(visibleType);
         final TransformableView hiddenView = getTransformableViewForVisibleType(mVisibleType);
+        if (shownView == hiddenView) {
+            shownView.setVisible(true);
+            return;
+        }
         shownView.transformFrom(hiddenView);
         getViewForVisibleType(visibleType).setVisibility(View.VISIBLE);
         hiddenView.transformTo(shownView, new Runnable() {
             @Override
             public void run() {
-                hiddenView.setVisible(false);
+                if (hiddenView != getTransformableViewForVisibleType(mVisibleType)) {
+                    hiddenView.setVisible(false);
+                }
             }
         });
     }
@@ -521,8 +565,8 @@
         }
     }
 
-    private NotificationViewWrapper getCurrentVisibleWrapper() {
-        switch (mVisibleType) {
+    private NotificationViewWrapper getVisibleWrapper(int visibleType) {
+        switch (visibleType) {
             case VISIBLE_TYPE_EXPANDED:
                 return mExpandedWrapper;
             case VISIBLE_TYPE_HEADSUP:
@@ -540,9 +584,12 @@
     private int calculateVisibleType() {
         if (mUserExpanding) {
             int height = !mIsChildInGroup || isGroupExpanded()
-                    || mContainingNotification.isExpanded()
+                    || mContainingNotification.isExpanded(true /* allowOnKeyguard */)
                     ? mContainingNotification.getMaxContentHeight()
                     : mContainingNotification.getShowingLayout().getMinHeight();
+            if (height == 0) {
+                height = mContentHeight;
+            }
             int expandedVisualType = getVisualTypeForHeight(height);
             int collapsedVisualType = getVisualTypeForHeight(
                     mContainingNotification.getMinExpandHeight());
@@ -550,7 +597,12 @@
                     ? expandedVisualType
                     : collapsedVisualType;
         }
-        int viewHeight = Math.min(mContentHeight, mContainingNotification.getIntrinsicHeight());
+        int intrinsicHeight = mContainingNotification.getIntrinsicHeight();
+        int viewHeight = mContentHeight;
+        if (intrinsicHeight != 0) {
+            // the intrinsicHeight might be 0 because it was just reset.
+            viewHeight = Math.min(mContentHeight, intrinsicHeight);
+        }
         return getVisualTypeForHeight(viewHeight);
     }
 
@@ -571,7 +623,8 @@
             }
         } else {
             if (noExpandedChild || (viewHeight <= mContractedChild.getHeight()
-                    && (!mIsChildInGroup || !mContainingNotification.isExpanded()))) {
+                    && (!mIsChildInGroup
+                            || !mContainingNotification.isExpanded(true /* allowOnKeyguard */)))) {
                 return VISIBLE_TYPE_CONTRACTED;
             } else {
                 return VISIBLE_TYPE_EXPANDED;
@@ -584,15 +637,10 @@
     }
 
     public void setDark(boolean dark, boolean fade, long delay) {
-        setDark(dark, fade, delay, false /* force */);
-    }
-
-    public void setDark(boolean dark, boolean fade, long delay, boolean force) {
-        if ((!force && mDark == dark) || mContractedChild == null) {
+        if (mContractedChild == null) {
             return;
         }
         mDark = dark;
-        dark = dark && !mShowingLegacyBackground;
         if (mVisibleType == VISIBLE_TYPE_CONTRACTED || !dark) {
             mContractedWrapper.setDark(dark, fade, delay);
         }
@@ -623,6 +671,19 @@
 
     public void setShowingLegacyBackground(boolean showing) {
         mShowingLegacyBackground = showing;
+        updateShowingLegacyBackground();
+    }
+
+    private void updateShowingLegacyBackground() {
+        if (mContractedChild != null) {
+            mContractedWrapper.setShowingLegacyBackground(mShowingLegacyBackground);
+        }
+        if (mExpandedChild != null) {
+            mExpandedWrapper.setShowingLegacyBackground(mShowingLegacyBackground);
+        }
+        if (mHeadsUpChild != null) {
+            mHeadsUpWrapper.setShowingLegacyBackground(mShowingLegacyBackground);
+        }
     }
 
     public void setIsChildInGroup(boolean isChildInGroup) {
@@ -635,7 +696,6 @@
         mBeforeN = entry.targetSdk < Build.VERSION_CODES.N;
         updateSingleLineView();
         applyRemoteInput(entry);
-        selectLayout(false /* animate */, true /* force */);
         if (mContractedChild != null) {
             mContractedWrapper.notifyContentUpdated(entry.notification);
         }
@@ -645,7 +705,9 @@
         if (mHeadsUpChild != null) {
             mHeadsUpWrapper.notifyContentUpdated(entry.notification);
         }
-        setDark(mDark, false /* animate */, 0 /* delay */, true /* force */);
+        updateShowingLegacyBackground();
+        selectLayout(false /* animate */, true /* force */);
+        setDark(mDark, false /* animate */, 0 /* delay */);
     }
 
     private void updateSingleLineView() {
@@ -765,7 +827,7 @@
     }
 
     public NotificationHeaderView getVisibleNotificationHeader() {
-        NotificationViewWrapper wrapper = getCurrentVisibleWrapper();
+        NotificationViewWrapper wrapper = getVisibleWrapper(mVisibleType);
         return wrapper == null ? null : wrapper.getNotificationHeader();
     }
 
@@ -793,6 +855,7 @@
             mTransformationStartVisibleType = UNDEFINED;
             mVisibleType = calculateVisibleType();
             updateViewVisibilities(mVisibleType);
+            updateBackgroundColor(false);
         }
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java
index ccd0ad8..c9fe2bd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java
@@ -111,11 +111,11 @@
             if (updatedNotification != null) {
                 final Notification.Builder updatedNotificationBuilder
                         = Notification.Builder.recoverBuilder(ctx, updatedNotification);
-                final RemoteViews newContentView = updatedNotificationBuilder.makeContentView();
+                final RemoteViews newContentView = updatedNotificationBuilder.createContentView();
                 final RemoteViews newBigContentView =
-                        updatedNotificationBuilder.makeBigContentView();
+                        updatedNotificationBuilder.createBigContentView();
                 final RemoteViews newHeadsUpContentView =
-                        updatedNotificationBuilder.makeHeadsUpContentView();
+                        updatedNotificationBuilder.createHeadsUpContentView();
                 final RemoteViews newPublicNotification
                         = updatedNotificationBuilder.makePublicContentView();
 
@@ -137,9 +137,9 @@
                 final Notification.Builder builder
                         = Notification.Builder.recoverBuilder(ctx, notification.getNotification());
 
-                cachedContentView = builder.makeContentView();
-                cachedBigContentView = builder.makeBigContentView();
-                cachedHeadsUpContentView = builder.makeHeadsUpContentView();
+                cachedContentView = builder.createContentView();
+                cachedBigContentView = builder.createBigContentView();
+                cachedHeadsUpContentView = builder.createHeadsUpContentView();
                 cachedPublicContentView = builder.makePublicContentView();
 
                 applyInPlace = false;
@@ -203,11 +203,11 @@
 
             String mediaNotification = mEnvironment.getCurrentMediaNotificationKey();
 
-            // PRIORITY_MIN media streams are allowed to drift to the bottom
+            // IMPORTANCE_MIN media streams are allowed to drift to the bottom
             final boolean aMedia = a.key.equals(mediaNotification)
-                    && aImportance > Ranking.IMPORTANCE_LOW;
+                    && aImportance > Ranking.IMPORTANCE_MIN;
             final boolean bMedia = b.key.equals(mediaNotification)
-                    && bImportance > Ranking.IMPORTANCE_LOW;
+                    && bImportance > Ranking.IMPORTANCE_MIN;
 
             boolean aSystemMax = aImportance >= Ranking.IMPORTANCE_MAX &&
                     isSystemNotification(na);
@@ -353,8 +353,10 @@
             return true;
         }
 
-        if (sbn.getNotification().visibility == Notification.VISIBILITY_SECRET &&
-                mEnvironment.shouldHideSensitiveContents(sbn.getUserId())) {
+        if (mEnvironment.onSecureLockScreen() &&
+                (sbn.getNotification().visibility == Notification.VISIBILITY_SECRET
+                        || mEnvironment.shouldHideNotifications(sbn.getUserId())
+                        || mEnvironment.shouldHideNotifications(sbn.getKey()))) {
             return true;
         }
 
@@ -433,7 +435,9 @@
      * Provides access to keyguard state and user settings dependent data.
      */
     public interface Environment {
-        public boolean shouldHideSensitiveContents(int userid);
+        public boolean onSecureLockScreen();
+        public boolean shouldHideNotifications(int userid);
+        public boolean shouldHideNotifications(String key);
         public boolean isDeviceProvisioned();
         public boolean isNotificationForCurrentProfiles(StatusBarNotification sbn);
         public String getCurrentMediaNotificationKey();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGuts.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGuts.java
index fe84d813..45a24a0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGuts.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGuts.java
@@ -17,7 +17,6 @@
 package com.android.systemui.statusbar;
 
 import android.app.INotificationManager;
-import android.app.Notification;
 import android.content.Context;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
@@ -39,23 +38,31 @@
 import com.android.internal.logging.MetricsProto.MetricsEvent;
 import com.android.settingslib.Utils;
 import com.android.systemui.R;
+import com.android.systemui.tuner.TunerService;
 
 /**
  * The guts of a notification revealed when performing a long press.
  */
-public class NotificationGuts extends LinearLayout {
+public class NotificationGuts extends LinearLayout implements TunerService.Tunable {
+    public static final String SHOW_SLIDER = "show_importance_slider";
 
     private Drawable mBackground;
     private int mClipTopAmount;
     private int mActualHeight;
     private boolean mExposed;
-    private SeekBar mSeekBar;
     private INotificationManager mINotificationManager;
     private int mStartingImportance;
+    private boolean mShowSlider;
+
+    private SeekBar mSeekBar;
+    private RadioButton mBlock;
+    private RadioButton mSilent;
+    private RadioButton mReset;
 
     public NotificationGuts(Context context, AttributeSet attrs) {
         super(context, attrs);
         setWillNotDraw(false);
+        TunerService.get(mContext).addTunable(this, SHOW_SLIDER);
     }
 
     @Override
@@ -102,31 +109,90 @@
         }
     }
 
-    void bindImportance(final StatusBarNotification sbn, final ExpandableNotificationRow row,
-            final int importance) {
+    void bindImportance(final PackageManager pm, final StatusBarNotification sbn,
+            final ExpandableNotificationRow row, final int importance) {
         mStartingImportance = importance;
         mINotificationManager = INotificationManager.Stub.asInterface(
                 ServiceManager.getService(Context.NOTIFICATION_SERVICE));
-
-        final TextView importanceSummary = ((TextView) row.findViewById(R.id.summary));
-        final TextView importanceTitle = ((TextView) row.findViewById(R.id.title));
-        mSeekBar = (SeekBar) row.findViewById(R.id.seekbar);
         boolean systemApp = false;
         try {
-            final PackageManager pm = BaseStatusBar.getPackageManagerForUser(
-                    getContext(), sbn.getUser().getIdentifier());
             final PackageInfo info =
                     pm.getPackageInfo(sbn.getPackageName(), PackageManager.GET_SIGNATURES);
             systemApp = Utils.isSystemPackage(pm, info);
         } catch (PackageManager.NameNotFoundException e) {
             // unlikely.
         }
+
+        final View importanceSlider = row.findViewById(R.id.importance_slider);
+        final View importanceButtons = row.findViewById(R.id.importance_buttons);
+        if (mShowSlider) {
+            bindSlider(importanceSlider, sbn, systemApp);
+            importanceSlider.setVisibility(View.VISIBLE);
+            importanceButtons.setVisibility(View.GONE);
+        } else {
+            int userImportance = NotificationListenerService.Ranking.IMPORTANCE_UNSPECIFIED;
+            try {
+                userImportance =
+                        mINotificationManager.getImportance(sbn.getPackageName(), sbn.getUid());
+            } catch (RemoteException e) {}
+            bindToggles(importanceButtons, userImportance, systemApp);
+            importanceButtons.setVisibility(View.VISIBLE);
+            importanceSlider.setVisibility(View.GONE);
+        }
+    }
+
+    void saveImportance(final StatusBarNotification sbn) {
+        int progress;
+        if (mSeekBar!= null && mSeekBar.isShown()) {
+            progress = mSeekBar.getProgress();
+        } else {
+            if (mBlock.isChecked()) {
+                progress = NotificationListenerService.Ranking.IMPORTANCE_NONE;
+            } else if (mSilent.isChecked()) {
+                progress = NotificationListenerService.Ranking.IMPORTANCE_LOW;
+            } else {
+                progress = NotificationListenerService.Ranking.IMPORTANCE_UNSPECIFIED;
+            }
+        }
+        MetricsLogger.action(mContext, MetricsEvent.ACTION_SAVE_IMPORTANCE,
+                progress - mStartingImportance);
+        try {
+            mINotificationManager.setImportance(sbn.getPackageName(), sbn.getUid(), progress);
+        } catch (RemoteException e) {
+            // :(
+        }
+    }
+
+    private void bindToggles(final View importanceButtons, final int importance,
+            final boolean systemApp) {
+        mBlock = (RadioButton) importanceButtons.findViewById(R.id.block_importance);
+        mSilent = (RadioButton) importanceButtons.findViewById(R.id.silent_importance);
+        mReset = (RadioButton) importanceButtons.findViewById(R.id.reset_importance);
         if (systemApp) {
-            ((ImageView) row.findViewById(R.id.low_importance)).getDrawable().setTint(
+            mBlock.setVisibility(View.GONE);
+            mReset.setText(mContext.getString(R.string.do_not_silence));
+        } else {
+            mReset.setText(mContext.getString(R.string.do_not_silence_block));
+        }
+        if (importance == NotificationListenerService.Ranking.IMPORTANCE_LOW) {
+            mSilent.setChecked(true);
+        } else {
+            mReset.setChecked(true);
+        }
+    }
+
+    private void bindSlider(final View importanceSlider, final StatusBarNotification sbn,
+            final boolean systemApp) {
+        final TextView importanceSummary = ((TextView) importanceSlider.findViewById(R.id.summary));
+        final TextView importanceTitle = ((TextView) importanceSlider.findViewById(R.id.title));
+        mSeekBar = (SeekBar) importanceSlider.findViewById(R.id.seekbar);
+
+        if (systemApp) {
+            ((ImageView) importanceSlider.findViewById(R.id.low_importance)).getDrawable().setTint(
                     mContext.getColor(R.color.notification_guts_disabled_icon_tint));
         }
         final int minProgress = systemApp ?
-                NotificationListenerService.Ranking.IMPORTANCE_LOW
+                NotificationListenerService.Ranking.IMPORTANCE_MIN
                 : NotificationListenerService.Ranking.IMPORTANCE_NONE;
         mSeekBar.setMax(NotificationListenerService.Ranking.IMPORTANCE_MAX);
         mSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
@@ -159,6 +225,11 @@
                                 R.string.notification_importance_blocked));
                         importanceTitle.setText(mContext.getString(R.string.blocked_importance));
                         break;
+                    case NotificationListenerService.Ranking.IMPORTANCE_MIN:
+                        importanceSummary.setText(mContext.getString(
+                                R.string.notification_importance_min));
+                        importanceTitle.setText(mContext.getString(R.string.min_importance));
+                        break;
                     case NotificationListenerService.Ranking.IMPORTANCE_LOW:
                         importanceSummary.setText(mContext.getString(
                                 R.string.notification_importance_low));
@@ -182,18 +253,7 @@
                 }
             }
         });
-        mSeekBar.setProgress(importance);
-    }
-
-    void saveImportance(final StatusBarNotification sbn) {
-        int progress = mSeekBar.getProgress();
-        MetricsLogger.action(mContext, MetricsEvent.ACTION_SAVE_IMPORTANCE,
-                progress - mStartingImportance);
-        try {
-            mINotificationManager.setImportance(sbn.getPackageName(), sbn.getUid(), progress);
-        } catch (RemoteException e) {
-            // :(
-        }
+        mSeekBar.setProgress(mStartingImportance);
     }
 
     public void setActualHeight(int actualHeight) {
@@ -224,4 +284,11 @@
     public boolean areGutsExposed() {
         return mExposed;
     }
+
+    @Override
+    public void onTuningChanged(String key, String newValue) {
+        if (SHOW_SLIDER.equals(key)) {
+            mShowSlider = newValue != null && Integer.parseInt(newValue) != 0;
+        }
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationSettingsIconRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationSettingsIconRow.java
index 4491ebd..fcc48bf 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationSettingsIconRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationSettingsIconRow.java
@@ -29,11 +29,18 @@
 
 public class NotificationSettingsIconRow extends FrameLayout implements View.OnClickListener {
 
+    private static final int GEAR_ALPHA_ANIM_DURATION = 200;
+
     public interface SettingsIconRowListener {
         /**
          * Called when the gear behind a notification is touched.
          */
-        public void onGearTouched(ExpandableNotificationRow row);
+        public void onGearTouched(ExpandableNotificationRow row, int x, int y);
+
+        /**
+         * Called when a notification is slid back over the gear.
+         */
+        public void onSettingsIconRowReset(NotificationSettingsIconRow row);
     }
 
     private ExpandableNotificationRow mParent;
@@ -45,6 +52,10 @@
     private boolean mSettingsFadedIn = false;
     private boolean mAnimating = false;
     private boolean mOnLeft = true;
+    private boolean mDismissing = false;
+    private boolean mSnapping = false;
+    private int[] mGearLocation = new int[2];
+    private int[] mParentLocation = new int[2];
 
     public NotificationSettingsIconRow(Context context) {
         this(context, null);
@@ -74,6 +85,18 @@
         resetState();
     }
 
+    public void resetState() {
+        setGearAlpha(0f);
+        mSettingsFadedIn = false;
+        mAnimating = false;
+        mSnapping = false;
+        mDismissing = false;
+        setIconLocation(true /* on left */);
+        if (mListener != null) {
+            mListener.onSettingsIconRowReset(this);
+        }
+    }
+
     public void setGearListener(SettingsIconRowListener listener) {
         mListener = listener;
     }
@@ -86,26 +109,24 @@
         return mParent;
     }
 
-    public void resetState() {
-        setGearAlpha(0f);
-        mAnimating = false;
-        setIconLocation(true /* on left */);
-    }
-
-    private void setGearAlpha(float alpha) {
+    public void setGearAlpha(float alpha) {
         if (alpha == 0) {
             mSettingsFadedIn = false; // Can fade in again once it's gone.
-            mGearIcon.setVisibility(View.INVISIBLE);
+            setVisibility(View.INVISIBLE);
         } else {
-            if (alpha == 1) {
-                mSettingsFadedIn = true;
-            }
-            mGearIcon.setVisibility(View.VISIBLE);
+            setVisibility(View.VISIBLE);
         }
         mGearIcon.setAlpha(alpha);
     }
 
     /**
+     * Returns whether the icon is on the left side of the view or not.
+     */
+    public boolean isIconOnLeft() {
+        return mOnLeft;
+    }
+
+    /**
      * Returns the horizontal space in pixels required to display the gear behind a notification.
      */
     public float getSpaceForGear() {
@@ -117,7 +138,7 @@
      * if entire view is visible.
      */
     public boolean isVisible() {
-        return mSettingsFadedIn;
+        return mGearIcon.getAlpha() > 0;
     }
 
     public void cancelFadeAnimator() {
@@ -127,16 +148,18 @@
     }
 
     public void updateSettingsIcons(final float transX, final float size) {
-        if (mAnimating || (mGearIcon.getAlpha() == 0)) {
-            // Don't adjust when animating or settings aren't visible
+        if (mAnimating || !mSettingsFadedIn) {
+            // Don't adjust when animating, or if the gear hasn't been shown yet.
             return;
         }
-        setIconLocation(transX > 0 /* fromLeft */);
+
         final float fadeThreshold = size * 0.3f;
         final float absTrans = Math.abs(transX);
         float desiredAlpha = 0;
 
-        if (absTrans <= fadeThreshold) {
+        if (absTrans == 0) {
+            desiredAlpha = 0;
+        } else if (absTrans <= fadeThreshold) {
             desiredAlpha = 1;
         } else {
             desiredAlpha = 1 - ((absTrans - fadeThreshold) / (size - fadeThreshold));
@@ -146,6 +169,12 @@
 
     public void fadeInSettings(final boolean fromLeft, final float transX,
             final float notiThreshold) {
+        if (mDismissing || mAnimating) {
+            return;
+        }
+        if (isIconLocationChange(transX)) {
+            setGearAlpha(0f);
+        }
         setIconLocation(transX > 0 /* fromLeft */);
         mFadeAnimator = ValueAnimator.ofFloat(mGearIcon.getAlpha(), 1);
         mFadeAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@@ -162,45 +191,67 @@
         });
         mFadeAnimator.addListener(new AnimatorListenerAdapter() {
             @Override
-            public void onAnimationCancel(Animator animation) {
-                super.onAnimationCancel(animation);
-                mAnimating = false;
-                mSettingsFadedIn = false;
-            }
-
-            @Override
             public void onAnimationStart(Animator animation) {
-                super.onAnimationStart(animation);
                 mAnimating = true;
             }
 
             @Override
+            public void onAnimationCancel(Animator animation) {
+                // TODO should animate back to 0f from current alpha
+                mGearIcon.setAlpha(0f);
+            }
+
+            @Override
             public void onAnimationEnd(Animator animation) {
-                super.onAnimationEnd(animation);
                 mAnimating = false;
-                mSettingsFadedIn = true;
+                mSettingsFadedIn = mGearIcon.getAlpha() == 1;
             }
         });
         mFadeAnimator.setInterpolator(Interpolators.ALPHA_IN);
-        mFadeAnimator.setDuration(200);
+        mFadeAnimator.setDuration(GEAR_ALPHA_ANIM_DURATION);
         mFadeAnimator.start();
     }
 
-    private void setIconLocation(boolean onLeft) {
-        if (onLeft == mOnLeft) {
+    public void setIconLocation(boolean onLeft) {
+        if (onLeft == mOnLeft || mSnapping) {
             // Same side? Do nothing.
             return;
         }
-
         setTranslationX(onLeft ? 0 : (mParent.getWidth() - mHorizSpaceForGear));
         mOnLeft = onLeft;
     }
 
+    public boolean isIconLocationChange(float translation) {
+        boolean onLeft = translation > mGearIcon.getPaddingStart();
+        boolean onRight = translation < -mGearIcon.getPaddingStart();
+        if ((mOnLeft && onRight) || (!mOnLeft && onLeft)) {
+            return true;
+        }
+        return false;
+    }
+
+    public void setDismissing() {
+        mDismissing = true;
+    }
+
+    public void setSnapping(boolean snapping) {
+        mSnapping = snapping;
+    }
+
     @Override
     public void onClick(View v) {
         if (v.getId() == R.id.gear_icon) {
             if (mListener != null) {
-                mListener.onGearTouched(mParent);
+                mGearIcon.getLocationOnScreen(mGearLocation);
+                mParent.getLocationOnScreen(mParentLocation);
+
+                final int centerX = (int) (mHorizSpaceForGear / 2);
+                // Top / bottom padding are not equal, need to subtract them to get center of gear.
+                final int centerY = (int) (mGearIcon.getHeight() - mGearIcon.getPaddingTop()
+                        - mGearIcon.getPaddingBottom()) / 2 + mGearIcon.getPaddingTop();
+                final int x = mGearLocation[0] - mParentLocation[0] + centerX;
+                final int y = mGearLocation[1] - mParentLocation[1] + centerY;
+                mListener.onGearTouched(mParent, x, y);
             }
         } else {
             // Do nothing when the background is touched.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java b/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java
index 444916a..988d537 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java
@@ -23,6 +23,7 @@
 import android.graphics.Color;
 import android.graphics.Rect;
 import android.graphics.drawable.Animatable;
+import android.graphics.drawable.AnimatedVectorDrawable;
 import android.graphics.drawable.Drawable;
 import android.telephony.SubscriptionInfo;
 import android.util.ArraySet;
@@ -220,12 +221,15 @@
 
         apply();
         applyIconTint();
+        mNC.addSignalCallback(this);
     }
 
     @Override
     protected void onDetachedFromWindow() {
         mMobileSignalGroup.removeAllViews();
         TunerService.get(mContext).removeTunable(this);
+        mSC.removeCallback(this);
+        mNC.removeSignalCallback(this);
 
         super.onDetachedFromWindow();
     }
@@ -636,6 +640,9 @@
 
             if (drawable instanceof Animatable) {
                 Animatable ad = (Animatable) drawable;
+                if (ad instanceof AnimatedVectorDrawable) {
+                    ((AnimatedVectorDrawable) ad).forceAnimationOnUI();
+                }
                 if (!ad.isRunning()) {
                     ad.start();
                 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarState.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarState.java
index 7e7fc3a..c0148c0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarState.java
@@ -41,4 +41,20 @@
      * Status bar is locked and shows the full screen user switcher.
      */
     public static final int FULLSCREEN_USER_SWITCHER = 3;
+
+
+    public static String toShortString(int x) {
+        switch (x) {
+            case SHADE:
+                return "SHD";
+            case SHADE_LOCKED:
+                return "SHD_LCK";
+            case KEYGUARD:
+                return "KGRD";
+            case FULLSCREEN_USER_SWITCHER:
+                return "FS_USRSW";
+            default:
+                return "bad_value_" + x;
+        }
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/TransformableView.java b/packages/SystemUI/src/com/android/systemui/statusbar/TransformableView.java
index 009eed7..dd7c4c7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/TransformableView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/TransformableView.java
@@ -27,6 +27,7 @@
     int TRANSFORMING_VIEW_TEXT = 2;
     int TRANSFORMING_VIEW_IMAGE = 3;
     int TRANSFORMING_VIEW_PROGRESS = 4;
+    int TRANSFORMING_VIEW_ACTIONS = 5;
 
     /**
      * Get the current state of a view in a transform animation
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ViewTransformationHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/ViewTransformationHelper.java
index bf05d1d..66f945e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ViewTransformationHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ViewTransformationHelper.java
@@ -76,26 +76,26 @@
         });
         mViewTransformationAnimation.setInterpolator(Interpolators.LINEAR);
         mViewTransformationAnimation.setDuration(StackStateAnimator.ANIMATION_DURATION_STANDARD);
-        if (endRunnable != null) {
-            mViewTransformationAnimation.addListener(new AnimatorListenerAdapter() {
-                public boolean mCancelled;
+        mViewTransformationAnimation.addListener(new AnimatorListenerAdapter() {
+            public boolean mCancelled;
 
-                @Override
-                public void onAnimationEnd(Animator animation) {
-                    endRunnable.run();
-                    if (!mCancelled) {
-                        setVisible(false);
-                    } else {
-                        abortTransformations();
+            @Override
+            public void onAnimationEnd(Animator animation) {
+                if (!mCancelled) {
+                    if (endRunnable != null) {
+                        endRunnable.run();
                     }
+                    setVisible(false);
+                } else {
+                    abortTransformations();
                 }
+            }
 
-                @Override
-                public void onAnimationCancel(Animator animation) {
-                    mCancelled = true;
-                }
-            });
-        }
+            @Override
+            public void onAnimationCancel(Animator animation) {
+                mCancelled = true;
+            }
+        });
         mViewTransformationAnimation.start();
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/car/CarNavigationBarController.java b/packages/SystemUI/src/com/android/systemui/statusbar/car/CarNavigationBarController.java
index 8a93c5b..bb43899 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/car/CarNavigationBarController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/car/CarNavigationBarController.java
@@ -71,7 +71,6 @@
     private List<CarNavigationButton> mNavButtons = new ArrayList<CarNavigationButton>();
 
     private int mCurrentFacetIndex;
-    private String mCurrentPackageName;
     private SparseBooleanArray mFacetHasMultipleAppsCache = new SparseBooleanArray();
 
     public CarNavigationBarController(Context context,
@@ -84,7 +83,6 @@
     }
 
     public void taskChanged(String packageName) {
-        mCurrentPackageName = packageName;
         // If the package name belongs to a filter, then highlight appropriate button in
         // the navigation bar.
         if (mFacetPackageMap.containsKey(packageName)) {
@@ -298,12 +296,6 @@
             return;
         }
 
-        // Don't launch the lens picker if it's already running and the
-        // user clicks the same facet
-        if (packageName.equals(mCurrentPackageName) && index == mCurrentFacetIndex) {
-            return;
-        }
-
         intent.putExtra(EXTRA_FACET_CATEGORIES, mFacetCategories.get(index));
         intent.putExtra(EXTRA_FACET_PACKAGES, mFacetPackages.get(index));
         // The facet is identified by the index in which it was added to the nav bar.
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 aa001ed..49e4ba8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationCustomViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationCustomViewWrapper.java
@@ -16,8 +16,19 @@
 
 package com.android.systemui.statusbar.notification;
 
+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;
 import com.android.systemui.ViewInvertHelper;
 import com.android.systemui.statusbar.phone.NotificationPanelView;
 
@@ -27,6 +38,11 @@
 public class NotificationCustomViewWrapper extends NotificationViewWrapper {
 
     private final ViewInvertHelper mInvertHelper;
+    private final Paint mGreyPaint = new Paint();
+    private int mBackgroundColor = 0;
+    private static final int CUSTOM_BACKGROUND_TAG = R.id.custom_background_color;
+    private boolean mShouldInvertDark;
+    private boolean mShowingLegacyBackground;
 
     protected NotificationCustomViewWrapper(View view) {
         super(view);
@@ -35,14 +51,50 @@
 
     @Override
     public void setDark(boolean dark, boolean fade, long delay) {
-        if (dark == mDark) {
+        if (dark == mDark && mDarkInitialized) {
             return;
         }
         super.setDark(dark, fade, delay);
-        if (fade) {
-            mInvertHelper.fade(dark, delay);
+        if (!mShowingLegacyBackground && mShouldInvertDark) {
+            if (fade) {
+                mInvertHelper.fade(dark, delay);
+            } else {
+                mInvertHelper.update(dark);
+            }
         } else {
-            mInvertHelper.update(dark);
+            mView.setLayerType(dark ? View.LAYER_TYPE_HARDWARE : View.LAYER_TYPE_NONE, null);
+            if (fade) {
+                fadeGrayscale(dark, delay);
+            } else {
+                updateGrayscale(dark);
+            }
+        }
+    }
+
+    protected void fadeGrayscale(final boolean dark, long delay) {
+        startIntensityAnimation(new ValueAnimator.AnimatorUpdateListener() {
+            @Override
+            public void onAnimationUpdate(ValueAnimator animation) {
+                updateGrayscaleMatrix((float) animation.getAnimatedValue());
+                mGreyPaint.setColorFilter(new ColorMatrixColorFilter(mGrayscaleColorMatrix));
+                mView.setLayerPaint(mGreyPaint);
+            }
+        }, dark, delay, new AnimatorListenerAdapter() {
+            @Override
+            public void onAnimationEnd(Animator animation) {
+                if (!dark) {
+                    mView.setLayerType(View.LAYER_TYPE_NONE, null);
+                }
+            }
+        });
+    }
+
+    protected void updateGrayscale(boolean dark) {
+        if (dark) {
+            updateGrayscaleMatrix(1f);
+            mGreyPaint.setColorFilter(
+                    new ColorMatrixColorFilter(mGrayscaleColorMatrix));
+            mView.setLayerPaint(mGreyPaint);
         }
     }
 
@@ -51,4 +103,35 @@
         super.setVisible(visible);
         mView.setAlpha(visible ? 1.0f : 0.0f);
     }
+
+    @Override
+    public void notifyContentUpdated(StatusBarNotification notification) {
+        super.notifyContentUpdated(notification);
+        Drawable background = mView.getBackground();
+        mBackgroundColor = 0;
+        if (background instanceof ColorDrawable) {
+            mBackgroundColor = ((ColorDrawable) background).getColor();
+            mView.setBackground(null);
+            mView.setTag(CUSTOM_BACKGROUND_TAG, mBackgroundColor);
+        } else if (mView.getTag(CUSTOM_BACKGROUND_TAG) != null) {
+            mBackgroundColor = (int) mView.getTag(CUSTOM_BACKGROUND_TAG);
+        }
+        mShouldInvertDark = mBackgroundColor == 0 || isColorLight(mBackgroundColor);
+    }
+
+    private boolean isColorLight(int backgroundColor) {
+        return Color.alpha(backgroundColor) == 0
+                || ColorUtils.calculateLuminance(backgroundColor) > 0.5;
+    }
+
+    @Override
+    public int getCustomBackgroundColor() {
+        return mBackgroundColor;
+    }
+
+    @Override
+    public void setShowingLegacyBackground(boolean showing) {
+        super.setShowingLegacyBackground(showing);
+        mShowingLegacyBackground = showing;
+    }
 }
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 000f957..b201d8f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationHeaderViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationHeaderViewWrapper.java
@@ -47,7 +47,6 @@
  */
 public class NotificationHeaderViewWrapper extends NotificationViewWrapper {
 
-    private final ColorMatrix mGrayscaleColorMatrix = new ColorMatrix();
     private final PorterDuffColorFilter mIconColorFilter = new PorterDuffColorFilter(
             0, PorterDuff.Mode.SRC_ATOP);
     private final int mIconDarkAlpha;
@@ -148,7 +147,7 @@
 
     @Override
     public void setDark(boolean dark, boolean fade, long delay) {
-        if (dark == mDark) {
+        if (dark == mDark && mDarkInitialized) {
             return;
         }
         super.setDark(dark, fade, delay);
@@ -178,21 +177,6 @@
         }
     }
 
-    protected void startIntensityAnimation(ValueAnimator.AnimatorUpdateListener updateListener,
-            boolean dark, long delay, Animator.AnimatorListener listener) {
-        float startIntensity = dark ? 0f : 1f;
-        float endIntensity = dark ? 1f : 0f;
-        ValueAnimator animator = ValueAnimator.ofFloat(startIntensity, endIntensity);
-        animator.addUpdateListener(updateListener);
-        animator.setDuration(NotificationPanelView.DOZE_ANIMATION_DURATION);
-        animator.setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN);
-        animator.setStartDelay(delay);
-        if (listener != null) {
-            animator.addListener(listener);
-        }
-        animator.start();
-    }
-
     private void fadeIconColorFilter(final ImageView target, boolean dark, long delay) {
         startIntensityAnimation(new ValueAnimator.AnimatorUpdateListener() {
             @Override
@@ -264,10 +248,6 @@
         mNotificationHeader.setOnClickListener(expandable ? onClickListener : null);
     }
 
-    private void updateGrayscaleMatrix(float intensity) {
-        mGrayscaleColorMatrix.setSaturation(1 - intensity);
-    }
-
     private static int interpolateColor(int source, int target, float t) {
         int aSource = Color.alpha(source);
         int rSource = Color.red(source);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationMediaTemplateViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationMediaTemplateViewWrapper.java
new file mode 100644
index 0000000..30698e1
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationMediaTemplateViewWrapper.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.statusbar.notification;
+
+import android.content.Context;
+import android.service.notification.StatusBarNotification;
+import android.view.View;
+
+import com.android.systemui.statusbar.TransformableView;
+
+/**
+ * Wraps a notification containing a media template
+ */
+public class NotificationMediaTemplateViewWrapper extends NotificationTemplateViewWrapper {
+
+    protected NotificationMediaTemplateViewWrapper(Context ctx, View view) {
+        super(ctx, view);
+    }
+
+    View mActions;
+
+    private void resolveViews(StatusBarNotification notification) {
+        mActions = mView.findViewById(com.android.internal.R.id.media_actions);
+    }
+
+    @Override
+    public void notifyContentUpdated(StatusBarNotification notification) {
+        // 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);
+    }
+
+    @Override
+    protected void updateTransformedTypes() {
+        // This also clears the existing types
+        super.updateTransformedTypes();
+        if (mActions != null) {
+            mTransformationHelper.addTransformedView(TransformableView.TRANSFORMING_VIEW_TEXT,
+                    mActions);
+        }
+    }
+}
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 fd4eca8..78e23fc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationTemplateViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationTemplateViewWrapper.java
@@ -163,7 +163,7 @@
 
     @Override
     public void setDark(boolean dark, boolean fade, long delay) {
-        if (dark == mDark) {
+        if (dark == mDark && mDarkInitialized) {
             return;
         }
         super.setDark(dark, fade, delay);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationUtils.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationUtils.java
index 4738657..6ef61ec 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationUtils.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationUtils.java
@@ -16,6 +16,7 @@
 
 package com.android.systemui.statusbar.notification;
 
+import android.graphics.Color;
 import android.widget.ImageView;
 
 import com.android.internal.util.NotificationColorUtil;
@@ -38,4 +39,12 @@
     public static float interpolate(float start, float end, float amount) {
         return start * (1.0f - amount) + end * amount;
     }
+
+    public static int interpolateColors(int startColor, int endColor, float amount) {
+        return Color.argb(
+                (int) interpolate(Color.alpha(startColor), Color.alpha(endColor), amount),
+                (int) interpolate(Color.red(startColor), Color.red(endColor), amount),
+                (int) interpolate(Color.green(startColor), Color.green(endColor), amount),
+                (int) interpolate(Color.blue(startColor), Color.blue(endColor), amount));
+    }
 }
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 d3503e7..ebff69d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationViewWrapper.java
@@ -16,13 +16,19 @@
 
 package com.android.systemui.statusbar.notification;
 
+import android.animation.Animator;
+import android.animation.ValueAnimator;
 import android.content.Context;
+import android.graphics.ColorMatrix;
 import android.service.notification.StatusBarNotification;
 import android.view.NotificationHeaderView;
 import android.view.View;
 
+import com.android.systemui.Interpolators;
 import com.android.systemui.statusbar.CrossFadeHelper;
+import com.android.systemui.statusbar.NotificationContentView;
 import com.android.systemui.statusbar.TransformableView;
+import com.android.systemui.statusbar.phone.NotificationPanelView;
 
 /**
  * Wraps the actual notification content view; used to implement behaviors which are different for
@@ -30,8 +36,10 @@
  */
 public abstract class NotificationViewWrapper implements TransformableView {
 
+    protected final ColorMatrix mGrayscaleColorMatrix = new ColorMatrix();
     protected final View mView;
     protected boolean mDark;
+    protected boolean mDarkInitialized = false;
 
     public static NotificationViewWrapper wrap(Context ctx, View v) {
         if (v.getId() == com.android.internal.R.id.status_bar_latest_event_content) {
@@ -39,6 +47,8 @@
                 return new NotificationBigPictureTemplateViewWrapper(ctx, v);
             } else if ("bigText".equals(v.getTag())) {
                 return new NotificationBigTextTemplateViewWrapper(ctx, v);
+            } else if ("media".equals(v.getTag()) || "bigMediaNarrow".equals(v.getTag())) {
+                return new NotificationMediaTemplateViewWrapper(ctx, v);
             }
             return new NotificationTemplateViewWrapper(ctx, v);
         } else if (v instanceof NotificationHeaderView) {
@@ -61,6 +71,7 @@
      */
     public void setDark(boolean dark, boolean fade, long delay) {
         mDark = dark;
+        mDarkInitialized = true;
     }
 
     /**
@@ -68,9 +79,29 @@
      * @param notification
      */
     public void notifyContentUpdated(StatusBarNotification notification) {
-        mDark = false;
+        mDarkInitialized = false;
     };
 
+
+    protected void startIntensityAnimation(ValueAnimator.AnimatorUpdateListener updateListener,
+            boolean dark, long delay, Animator.AnimatorListener listener) {
+        float startIntensity = dark ? 0f : 1f;
+        float endIntensity = dark ? 1f : 0f;
+        ValueAnimator animator = ValueAnimator.ofFloat(startIntensity, endIntensity);
+        animator.addUpdateListener(updateListener);
+        animator.setDuration(NotificationPanelView.DOZE_ANIMATION_DURATION);
+        animator.setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN);
+        animator.setStartDelay(delay);
+        if (listener != null) {
+            animator.addListener(listener);
+        }
+        animator.start();
+    }
+
+    protected void updateGrayscaleMatrix(float intensity) {
+        mGrayscaleColorMatrix.setSaturation(1 - intensity);
+    }
+
     /**
      * Update the appearance of the expand button.
      *
@@ -118,4 +149,11 @@
         mView.animate().cancel();
         mView.setVisibility(visible ? View.VISIBLE : View.INVISIBLE);
     }
+
+    public int getCustomBackgroundColor() {
+        return 0;
+    }
+
+    public void setShowingLegacyBackground(boolean showing) {
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/TextViewTransformState.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/TextViewTransformState.java
index 5ab441d..20dbc4a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/TextViewTransformState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/TextViewTransformState.java
@@ -16,6 +16,7 @@
 
 package com.android.systemui.statusbar.notification;
 
+import android.text.Layout;
 import android.text.TextUtils;
 import android.util.Pools;
 import android.view.View;
@@ -28,14 +29,13 @@
 
     private static Pools.SimplePool<TextViewTransformState> sInstancePool
             = new Pools.SimplePool<>(40);
-    private CharSequence mText;
+    private TextView mText;
 
     @Override
     public void initFrom(View view) {
         super.initFrom(view);
         if (view instanceof TextView) {
-            TextView txt = (TextView) view;
-            mText = txt.getText();
+            mText = (TextView) view;
         }
     }
 
@@ -43,11 +43,28 @@
     protected boolean sameAs(TransformState otherState) {
         if (otherState instanceof TextViewTransformState) {
             TextViewTransformState otherTvs = (TextViewTransformState) otherState;
-            return TextUtils.equals(otherTvs.mText, mText);
+            if(TextUtils.equals(otherTvs.mText.getText(), mText.getText())) {
+                int ownEllipsized = getEllipsisCount();
+                int otherEllipsized = otherTvs.getEllipsisCount();
+                return ownEllipsized == otherEllipsized
+                        && mText.getHeight() == otherTvs.mText.getHeight();
+            }
         }
         return super.sameAs(otherState);
     }
 
+    private int getEllipsisCount() {
+        Layout l = mText.getLayout();
+        if (l != null) {
+            int lines = l.getLineCount();
+            if (lines > 0) {
+                // we only care about the first line
+                return l.getEllipsisCount(0);
+            }
+        }
+        return 0;
+    }
+
     public static TextViewTransformState obtain() {
         TextViewTransformState instance = sInstancePool.acquire();
         if (instance != null) {
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 b742479..6d0fbb15 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoTileManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoTileManager.java
@@ -24,6 +24,7 @@
 import com.android.systemui.statusbar.policy.DataSaverController.Listener;
 import com.android.systemui.statusbar.policy.HotspotController;
 import com.android.systemui.statusbar.policy.HotspotController.Callback;
+import com.android.systemui.statusbar.policy.NightModeController;
 
 /**
  * Manages which tiles should be automatically added to QS.
@@ -66,12 +67,33 @@
         if (!Prefs.getBoolean(context, Key.QS_WORK_ADDED, false)) {
             host.getManagedProfileController().addCallback(mProfileCallback);
         }
+        if (!Prefs.getBoolean(context, Key.QS_NIGHT_ADDED, false)) {
+            host.getNightModeController().addListener(mNightModeListener);
+        }
     }
 
     public void destroy() {
         // TODO: Remove any registered listeners.
     }
 
+    private final NightModeController.Listener mNightModeListener =
+            new NightModeController.Listener() {
+        @Override
+        public void onNightModeChanged() {
+            mHost.addTile("night");
+            Prefs.putBoolean(mContext, Key.QS_NIGHT_ADDED, true);
+            mHandler.post(new Runnable() {
+                @Override
+                public void run() {
+                    mHost.getNightModeController().removeListener(mNightModeListener);
+                }
+            });
+        }
+
+        @Override
+        public void onTwilightAutoChanged() { }
+    };
+
     private final ManagedProfileController.Callback mProfileCallback =
             new ManagedProfileController.Callback() {
                 @Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BarTransitions.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BarTransitions.java
index 5796edb..ed71e57 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BarTransitions.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BarTransitions.java
@@ -22,8 +22,12 @@
 import android.graphics.Canvas;
 import android.graphics.Color;
 import android.graphics.ColorFilter;
+import android.graphics.Paint;
 import android.graphics.PixelFormat;
+import android.graphics.PorterDuff;
+import android.graphics.PorterDuffColorFilter;
 import android.graphics.Rect;
+import android.graphics.PorterDuff.Mode;
 import android.graphics.drawable.Drawable;
 import android.os.SystemClock;
 import android.util.Log;
@@ -55,6 +59,7 @@
     private final BarBackgroundDrawable mBarBackground;
 
     private int mMode;
+    private boolean mAlwaysOpaque = false;
 
     public BarTransitions(View view, int gradientResourceId) {
         mTag = "BarTransitions." + view.getClass().getSimpleName();
@@ -69,13 +74,25 @@
         return mMode;
     }
 
+    /**
+     * @param alwaysOpaque if {@code true}, the bar's background will always be opaque, regardless
+     *         of what mode it is currently set to.
+     */
+    public void setAlwaysOpaque(boolean alwaysOpaque) {
+        mAlwaysOpaque = alwaysOpaque;
+    }
+
+    public boolean isAlwaysOpaque() {
+        // Low-end devices do not support translucent modes, fallback to opaque
+        return !HIGH_END || mAlwaysOpaque;
+    }
+
     public void transitionTo(int mode, boolean animate) {
-        // low-end devices do not support translucent modes, fallback to opaque
-        if (!HIGH_END && (mode == MODE_SEMI_TRANSPARENT || mode == MODE_TRANSLUCENT
+        if (isAlwaysOpaque() && (mode == MODE_SEMI_TRANSPARENT || mode == MODE_TRANSLUCENT
                 || mode == MODE_TRANSPARENT)) {
             mode = MODE_OPAQUE;
         }
-        if (!HIGH_END && (mode == MODE_LIGHTS_OUT_TRANSPARENT)) {
+        if (isAlwaysOpaque() && (mode == MODE_LIGHTS_OUT_TRANSPARENT)) {
             mode = MODE_LIGHTS_OUT;
         }
         if (mMode == mode) return;
@@ -131,10 +148,13 @@
 
         private int mGradientAlpha;
         private int mColor;
+        private PorterDuffColorFilter mTintFilter;
+        private Paint mPaint = new Paint();
 
         private int mGradientAlphaStart;
         private int mColorStart;
 
+
         public BarBackgroundDrawable(Context context, int gradientResourceId) {
             final Resources res = context.getResources();
             if (DEBUG_COLORS) {
@@ -163,6 +183,26 @@
         }
 
         @Override
+        public void setTint(int color) {
+            if (mTintFilter == null) {
+                mTintFilter = new PorterDuffColorFilter(color, PorterDuff.Mode.SRC_IN);
+            } else {
+                mTintFilter.setColor(color);
+            }
+            invalidateSelf();
+        }
+
+        @Override
+        public void setTintMode(Mode tintMode) {
+            if (mTintFilter == null) {
+                mTintFilter = new PorterDuffColorFilter(0, tintMode);
+            } else {
+                mTintFilter.setMode(tintMode);
+            }
+            invalidateSelf();
+        }
+
+        @Override
         protected void onBoundsChange(Rect bounds) {
             super.onBoundsChange(bounds);
             mGradient.setBounds(bounds);
@@ -208,6 +248,7 @@
             } else {
                 targetColor = mOpaque;
             }
+
             if (!mAnimating) {
                 mColor = targetColor;
                 mGradientAlpha = targetGradientAlpha;
@@ -234,7 +275,11 @@
                 mGradient.draw(canvas);
             }
             if (Color.alpha(mColor) > 0) {
-                canvas.drawColor(mColor);
+                mPaint.setColor(mColor);
+                if (mTintFilter != null) {
+                    mPaint.setColorFilter(mTintFilter);
+                }
+                canvas.drawPaint(mPaint);
             }
             if (mAnimating) {
                 invalidateSelf();  // keep going
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BaseStatusBarHeader.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BaseStatusBarHeader.java
index eade2a8..6e1c862 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BaseStatusBarHeader.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BaseStatusBarHeader.java
@@ -19,7 +19,6 @@
 import android.content.Context;
 import android.util.AttributeSet;
 import android.widget.RelativeLayout;
-
 import com.android.systemui.qs.QSPanel;
 import com.android.systemui.statusbar.policy.BatteryController;
 import com.android.systemui.statusbar.policy.NetworkControllerImpl;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenWallpaper.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenWallpaper.java
index 5b4a3f0..65e7973 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenWallpaper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenWallpaper.java
@@ -105,7 +105,6 @@
                 if (mSelectedUser != null && mSelectedUser.getIdentifier() != mCurrentUserId) {
                     // When selected user is different from the current user, show the selected
                     // user's static wallpaper.
-                    mWallpaperManager.forgetLoadedWallpaper();
                     mCache = mWallpaperManager.getBitmapAsUser(mSelectedUser.getIdentifier());
                 } else {
                     // When there is no selected user, or it's same as the current user, show the
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 05ae41b..e5e3caf 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -42,6 +42,8 @@
 import com.android.internal.logging.MetricsLogger;
 import com.android.keyguard.KeyguardStatusView;
 import com.android.systemui.DejankUtils;
+import com.android.systemui.DensityContainer;
+import com.android.systemui.DensityContainer.InflateListener;
 import com.android.systemui.EventLogConstants;
 import com.android.systemui.EventLogTags;
 import com.android.systemui.Interpolators;
@@ -63,7 +65,7 @@
 import java.util.List;
 
 public class NotificationPanelView extends PanelView implements
-        ExpandableView.OnHeightChangedListener, ObservableScrollView.Listener,
+        ExpandableView.OnHeightChangedListener,
         View.OnClickListener, NotificationStackScrollLayout.OnOverscrollTopChangedListener,
         KeyguardAffordanceHelper.Callback, NotificationStackScrollLayout.OnEmptySpaceClickListener,
         HeadsUpManager.OnHeadsUpChangedListener {
@@ -90,6 +92,7 @@
     private KeyguardUserSwitcher mKeyguardUserSwitcher;
     private KeyguardStatusBarView mKeyguardStatusBar;
     protected QSContainer mQsContainer;
+    private DensityContainer mQsDensityContainer;
     private KeyguardStatusView mKeyguardStatusView;
     private TextView mClockView;
     private View mReserveNotificationSpace;
@@ -215,8 +218,15 @@
         super.onFinishInflate();
         mKeyguardStatusBar = (KeyguardStatusBarView) findViewById(R.id.keyguard_header);
         mKeyguardStatusView = (KeyguardStatusView) findViewById(R.id.keyguard_status_view);
-        mQsContainer = (QSContainer) findViewById(R.id.quick_settings_container);
-        mQsContainer.getHeader().setOnClickListener(this);
+        mQsDensityContainer = (DensityContainer) findViewById(R.id.qs_density_container);
+        mQsDensityContainer.addInflateListener(new InflateListener() {
+            @Override
+            public void onInflated(View v) {
+                mQsContainer = (QSContainer) v.findViewById(R.id.quick_settings_container);
+                mQsContainer.setPanelView(NotificationPanelView.this);
+                mQsContainer.getHeader().setOnClickListener(NotificationPanelView.this);
+            }
+        });
         mClockView = (TextView) findViewById(R.id.clock_view);
         mNotificationContainerParent = (NotificationsQuickSettingsContainer)
                 findViewById(R.id.notification_container_parent);
@@ -239,7 +249,7 @@
                 final int height = bottom - top;
                 final int oldHeight = oldBottom - oldTop;
                 if (height != oldHeight) {
-                    onScrollChanged();
+                    onQsHeightChanged();
                 }
             }
         });
@@ -267,11 +277,12 @@
     public void updateResources() {
         int panelWidth = getResources().getDimensionPixelSize(R.dimen.notification_panel_width);
         int panelGravity = getResources().getInteger(R.integer.notification_panel_layout_gravity);
-        FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) mQsContainer.getLayoutParams();
+        FrameLayout.LayoutParams lp =
+                (FrameLayout.LayoutParams) mQsDensityContainer.getLayoutParams();
         if (lp.width != panelWidth) {
             lp.width = panelWidth;
             lp.gravity = panelGravity;
-            mQsContainer.setLayoutParams(lp);
+            mQsDensityContainer.setLayoutParams(lp);
             mQsContainer.post(mUpdateHeader);
         }
 
@@ -539,7 +550,7 @@
 
     @Override
     public boolean onInterceptTouchEvent(MotionEvent event) {
-        if (mBlockTouches) {
+        if (mBlockTouches || mQsContainer.isCustomizing()) {
             return false;
         }
         initDownStates(event);
@@ -699,7 +710,7 @@
 
     @Override
     public boolean onTouchEvent(MotionEvent event) {
-        if (mBlockTouches) {
+        if (mBlockTouches || mQsContainer.isCustomizing()) {
             return false;
         }
         initDownStates(event);
@@ -898,18 +909,6 @@
     }
 
     @Override
-    public void onOverscrolled(float lastTouchX, float lastTouchY, int amount) {
-        if (mIntercepting && shouldQuickSettingsIntercept(lastTouchX, lastTouchY,
-                -1 /* yDiff: Not relevant here */)) {
-            mQsTracking = true;
-            onQsExpansionStarted(amount);
-            mInitialHeightOnTouch = mQsExpansionHeight;
-            mInitialTouchY = mLastTouchY;
-            mInitialTouchX = mLastTouchX;
-        }
-    }
-
-    @Override
     public void onOverscrollTopChanged(float amount, boolean isRubberbanded) {
         cancelQsAnimation();
         if (!mQsExpansionEnabled) {
@@ -1389,7 +1388,7 @@
                 // In Shade, interpolate linearly such that QS is closed whenever panel height is
                 // minimum QS expansion + minStackHeight
                 float panelHeightQsCollapsed = mNotificationStackScroller.getIntrinsicPadding()
-                        + mNotificationStackScroller.getMinStackHeight();
+                        + mNotificationStackScroller.getLayoutMinHeight();
                 float panelHeightQsExpanded = calculatePanelHeightQsExpanded();
                 t = (expandedHeight - panelHeightQsCollapsed)
                         / (panelHeightQsExpanded - panelHeightQsCollapsed);
@@ -1445,7 +1444,7 @@
                 && mShadeEmpty) {
             notificationHeight = mNotificationStackScroller.getEmptyShadeViewHeight()
                     + mNotificationStackScroller.getBottomStackPeekSize()
-                    + mNotificationStackScroller.getCollapseSecondCardPadding();
+                    + mNotificationStackScroller.getBottomStackSlowDownHeight();
         }
         int maxQsHeight = mQsMaxExpansionHeight;
 
@@ -1460,7 +1459,7 @@
                 + notificationHeight;
         if (totalHeight > mNotificationStackScroller.getHeight()) {
             float fullyCollapsedHeight = maxQsHeight
-                    + mNotificationStackScroller.getMinStackHeight();
+                    + mNotificationStackScroller.getLayoutMinHeight();
             totalHeight = Math.max(fullyCollapsedHeight, mNotificationStackScroller.getHeight());
         }
         return (int) totalHeight;
@@ -1477,7 +1476,7 @@
     private float getFadeoutAlpha() {
         float alpha = (getNotificationsTopY() + mNotificationStackScroller.getFirstItemMinHeight())
                 / (mQsMinExpansionHeight + mNotificationStackScroller.getBottomStackPeekSize()
-                - mNotificationStackScroller.getCollapseSecondCardPadding());
+                - mNotificationStackScroller.getBottomStackSlowDownHeight());
         alpha = Math.max(0, Math.min(alpha, 1));
         alpha = (float) Math.pow(alpha, 0.75);
         return alpha;
@@ -1711,9 +1710,10 @@
     public void onReset(ExpandableView view) {
     }
 
-    @Override
-    public void onScrollChanged() {
+    public void onQsHeightChanged() {
+        mQsMaxExpansionHeight = mQsContainer.getDesiredHeight();
         if (mQsExpanded) {
+            mQsExpansionHeight = mQsMaxExpansionHeight;
             requestScrollerTopPaddingUpdate(false /* animate */);
             requestPanelHeightUpdate();
         }
@@ -2211,7 +2211,7 @@
 
     protected void setVerticalPanelTranslation(float translation) {
         mNotificationStackScroller.setTranslationX(translation);
-        mQsContainer.setTranslationX(translation);
+        mQsDensityContainer.setTranslationX(translation);
     }
 
     protected void updateStackHeight(float stackHeight) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationsQuickSettingsContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationsQuickSettingsContainer.java
index 7cc720d..f0df706 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationsQuickSettingsContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationsQuickSettingsContainer.java
@@ -24,21 +24,24 @@
 import android.view.ViewStub;
 import android.view.WindowInsets;
 import android.widget.FrameLayout;
-
+import com.android.systemui.DensityContainer;
 import com.android.systemui.R;
+import com.android.systemui.qs.QSContainer;
+import com.android.systemui.qs.customize.QSCustomizer;
 
 /**
  * The container with notification stack scroller and quick settings inside.
  */
 public class NotificationsQuickSettingsContainer extends FrameLayout
-        implements ViewStub.OnInflateListener {
+        implements ViewStub.OnInflateListener, DensityContainer.InflateListener {
 
-    private View mQsContainer;
+    private DensityContainer mQsContainer;
     private View mUserSwitcher;
     private View mStackScroller;
     private View mKeyguardStatusBar;
     private boolean mInflated;
     private boolean mQsExpanded;
+    private boolean mCustomizerAnimating;
 
     public NotificationsQuickSettingsContainer(Context context, AttributeSet attrs) {
         super(context, attrs);
@@ -47,7 +50,8 @@
     @Override
     protected void onFinishInflate() {
         super.onFinishInflate();
-        mQsContainer = findViewById(R.id.quick_settings_container);
+        mQsContainer = (DensityContainer) findViewById(R.id.qs_density_container);
+        mQsContainer.addInflateListener(this);
         mStackScroller = findViewById(R.id.notification_stack_scroller);
         mKeyguardStatusBar = findViewById(R.id.keyguard_header);
         ViewStub userSwitcher = (ViewStub) findViewById(R.id.keyguard_user_switcher);
@@ -80,8 +84,9 @@
         boolean userSwitcherVisible = mInflated && mUserSwitcher.getVisibility() == View.VISIBLE;
         boolean statusBarVisible = mKeyguardStatusBar.getVisibility() == View.VISIBLE;
 
-        View stackQsTop = mQsExpanded ? mStackScroller : mQsContainer;
-        View stackQsBottom = !mQsExpanded ? mStackScroller : mQsContainer;
+        final boolean qsBottom = mQsExpanded && !mCustomizerAnimating;
+        View stackQsTop = qsBottom ? mStackScroller : mQsContainer;
+        View stackQsBottom = !qsBottom ? mStackScroller : mQsContainer;
         // Invert the order of the scroll view and user switcher such that the notifications receive
         // touches first but the panel gets drawn above.
         if (child == mQsContainer) {
@@ -117,10 +122,23 @@
         }
     }
 
+    @Override
+    public void onInflated(View v) {
+        QSCustomizer customizer = ((QSContainer) v).getCustomizer();
+        customizer.setContainer(this);
+    }
+
     public void setQsExpanded(boolean expanded) {
         if (mQsExpanded != expanded) {
             mQsExpanded = expanded;
             invalidate();
         }
     }
+
+    public void setCustomizerAnimating(boolean isAnimating) {
+        if (mCustomizerAnimating != isAnimating) {
+            mCustomizerAnimating = isAnimating;
+            invalidate();
+        }
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
index ac714e7..906bd0f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -23,7 +23,6 @@
 import android.app.ActivityManager;
 import android.app.ActivityManagerNative;
 import android.app.IActivityManager;
-import android.app.IWallpaperManagerCallback;
 import android.app.Notification;
 import android.app.PendingIntent;
 import android.app.StatusBarManager;
@@ -104,6 +103,8 @@
 import com.android.keyguard.ViewMediatorCallback;
 import com.android.systemui.BatteryMeterView;
 import com.android.systemui.DemoMode;
+import com.android.systemui.DensityContainer;
+import com.android.systemui.DensityContainer.InflateListener;
 import com.android.systemui.EventLogConstants;
 import com.android.systemui.EventLogTags;
 import com.android.systemui.Interpolators;
@@ -111,6 +112,7 @@
 import com.android.systemui.R;
 import com.android.systemui.SystemUIFactory;
 import com.android.systemui.assist.AssistManager;
+import com.android.systemui.classifier.FalsingLog;
 import com.android.systemui.classifier.FalsingManager;
 import com.android.systemui.doze.DozeHost;
 import com.android.systemui.doze.DozeLog;
@@ -771,15 +773,24 @@
         ScrimView scrimInFront = (ScrimView) mStatusBarWindow.findViewById(R.id.scrim_in_front);
         View headsUpScrim = mStatusBarWindow.findViewById(R.id.heads_up_scrim);
         mScrimController = SystemUIFactory.getInstance().createScrimController(
-                scrimBehind, scrimInFront, headsUpScrim, mScrimSrcModeEnabled);
+                scrimBehind, scrimInFront, headsUpScrim);
+        if (mScrimSrcModeEnabled) {
+            Runnable runnable = new Runnable() {
+                @Override
+                public void run() {
+                    boolean asSrc = mBackdrop.getVisibility() != View.VISIBLE;
+                    mScrimController.setDrawBehindAsSrc(asSrc);
+                    mStackScroller.setDrawBackgroundAsSrc(asSrc);
+                }
+            };
+            mBackdrop.setOnVisibilityChangedRunnable(runnable);
+            runnable.run();
+        }
         mHeadsUpManager.addListener(mScrimController);
         mStackScroller.setScrimController(mScrimController);
-        mScrimController.setBackDropView(mBackdrop);
         mStatusBarView.setScrimController(mScrimController);
         mDozeScrimController = new DozeScrimController(mScrimController, context);
 
-        mHeader = (BaseStatusBarHeader) mStatusBarWindow.findViewById(R.id.header);
-        mHeader.setActivityStarter(this);
         mKeyguardStatusBar = (KeyguardStatusBarView) mStatusBarWindow.findViewById(R.id.keyguard_header);
         mKeyguardStatusView = mStatusBarWindow.findViewById(R.id.keyguard_status_view);
         mKeyguardBottomArea =
@@ -839,12 +850,6 @@
 
         initSignalCluster(mStatusBarView);
         initSignalCluster(mKeyguardStatusBar);
-        initSignalCluster(mHeader);
-
-        final boolean isAPhone = mNetworkController.hasVoiceCallingFeature();
-        if (isAPhone) {
-            mNetworkController.addEmergencyListener(mHeader);
-        }
 
         mFlashlightController = new FlashlightController(mContext);
         mKeyguardBottomArea.setFlashlightController(mFlashlightController);
@@ -863,39 +868,40 @@
         }
 
         // Set up the quick settings tile panel
-        mQSPanel = (QSPanel) mStatusBarWindow.findViewById(R.id.quick_settings_panel);
-        if (mQSPanel != null) {
+        DensityContainer container = (DensityContainer) mStatusBarWindow.findViewById(
+                R.id.qs_density_container);
+        if (container != null) {
             final QSTileHost qsh = new QSTileHost(mContext, this,
                     mBluetoothController, mLocationController, mRotationLockController,
                     mNetworkController, mZenModeController, mHotspotController,
                     mCastController, mFlashlightController,
                     mUserSwitcherController, mUserInfoController, mKeyguardMonitor,
-                    mSecurityController, mBatteryController, mIconController);
-            mQSPanel.setTiles(qsh.getTiles());
+                    mSecurityController, mBatteryController, mIconController,
+                    mNextAlarmController);
             mBrightnessMirrorController = new BrightnessMirrorController(mStatusBarWindow);
-            mQSPanel.setBrightnessMirror(mBrightnessMirrorController);
-            QSContainer qsContainer = (QSContainer) mStatusBarWindow.findViewById(
-                    R.id.quick_settings_container);
-            qsContainer.setHost(qsh);
-            qsh.addCallback(new QSTileHost.Callback() {
+            container.addInflateListener(new InflateListener() {
                 @Override
-                public void onTilesChanged() {
-                    mQSPanel.setTiles(qsh.getTiles());
+                public void onInflated(View v) {
+                    QSContainer qsContainer = (QSContainer) v.findViewById(
+                            R.id.quick_settings_container);
+                    qsContainer.setHost(qsh);
+                    mQSPanel = qsContainer.getQsPanel();
+                    mQSPanel.setBrightnessMirror(mBrightnessMirrorController);
+                    mHeader = qsContainer.getHeader();
+                    initSignalCluster(mHeader);
+                    mHeader.setActivityStarter(PhoneStatusBar.this);
                 }
             });
         }
 
         // User info. Trigger first load.
-        mHeader.setUserInfoController(mUserInfoController);
         mKeyguardStatusBar.setUserInfoController(mUserInfoController);
         mKeyguardStatusBar.setUserSwitcherController(mUserSwitcherController);
         mUserInfoController.reloadUserInfo();
 
-        mHeader.setBatteryController(mBatteryController);
         ((BatteryMeterView) mStatusBarView.findViewById(R.id.battery)).setBatteryController(
                 mBatteryController);
         mKeyguardStatusBar.setBatteryController(mBatteryController);
-        mHeader.setNextAlarmController(mNextAlarmController);
 
         PowerManager pm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
         mBroadcastReceiver.onReceive(mContext,
@@ -1001,13 +1007,12 @@
         SignalClusterView signalCluster =
                 (SignalClusterView) containerView.findViewById(R.id.signal_cluster);
         if (signalCluster != null) {
-            mNetworkController.addSignalCallback(signalCluster);
             signalCluster.setSecurityController(mSecurityController);
             signalCluster.setNetworkController(mNetworkController);
         }
     }
 
-    private void clearAllNotifications() {
+    public void clearAllNotifications() {
 
         // animate-swipe all dismissable notifications, then animate the shade closed
         int numChildren = mStackScroller.getChildCount();
@@ -1144,9 +1149,10 @@
 
         @Override
         public boolean onLongClick(View v) {
-            if (mRecents == null) {
+            if (mRecents == null || !ActivityManager.supportsMultiWindow()) {
                 return false;
             }
+
             boolean initiallyDocked = WindowManagerProxy.getInstance().getDockSide()
                     == WindowManager.DOCKED_INVALID;
             boolean dockedAtEnd = toggleSplitScreenMode();
@@ -1167,13 +1173,8 @@
         }
         int dockSide = WindowManagerProxy.getInstance().getDockSide();
         if (dockSide == WindowManager.DOCKED_INVALID) {
-            Point realSize = new Point();
-            mContext.getSystemService(DisplayManager.class).getDisplay(Display.DEFAULT_DISPLAY)
-                    .getRealSize(realSize);
-            Rect initialBounds= new Rect(0, 0, realSize.x, realSize.y);
             return mRecents.dockTopTask(NavigationBarGestureHelper.DRAG_MODE_NONE,
-                    ActivityManager.DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT,
-                    initialBounds);
+                    ActivityManager.DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT, null);
         } else {
             EventBus.getDefault().send(new UndockingTaskEvent());
             return false;
@@ -1319,6 +1320,12 @@
                 if (DEBUG) {
                     Log.d(TAG, "No Fullscreen intent: suppressed by DND: " + notification.getKey());
                 }
+            } else if (mNotificationData.getImportance(notification.getKey())
+                    < NotificationListenerService.Ranking.IMPORTANCE_MAX) {
+                if (DEBUG) {
+                    Log.d(TAG, "No Fullscreen intent: not important enough: "
+                            + notification.getKey());
+                }
             } else {
                 // Stop screensaver if the notification has a full-screen intent.
                 // (like an incoming phone call)
@@ -1467,6 +1474,9 @@
             mStackScroller.removeView(remove);
             mStackScroller.setChildTransferInProgress(false);
         }
+
+        removeNotificationChildren();
+
         for (int i=0; i<toShow.size(); i++) {
             View v = toShow.get(i);
             if (v.getParent() == null) {
@@ -1474,6 +1484,8 @@
             }
         }
 
+        addNotificationChildrenAndSort();
+
         // So after all this work notifications still aren't sorted correctly.
         // Let's do that now by advancing through toShow and mStackScroller in
         // lock-step, making sure mStackScroller matches what we see in toShow.
@@ -1495,9 +1507,6 @@
 
         }
 
-        // lets handle the child notifications now
-        updateNotificationShadeForChildren();
-
         // clear the map again for the next usage
         mTmpChildOrderMap.clear();
 
@@ -1523,34 +1532,7 @@
                 && !ONLY_CORE_APPS);
     }
 
-    private void updateNotificationShadeForChildren() {
-        // First let's remove all children which don't belong in the parents
-        ArrayList<ExpandableNotificationRow> toRemove = new ArrayList<>();
-        for (int i = 0; i < mStackScroller.getChildCount(); i++) {
-            View view = mStackScroller.getChildAt(i);
-            if (!(view instanceof ExpandableNotificationRow)) {
-                // We don't care about non-notification views.
-                continue;
-            }
-
-            ExpandableNotificationRow parent = (ExpandableNotificationRow) view;
-            List<ExpandableNotificationRow> children = parent.getNotificationChildren();
-            List<ExpandableNotificationRow> orderedChildren = mTmpChildOrderMap.get(parent);
-
-            if (children != null) {
-                toRemove.clear();
-                for (ExpandableNotificationRow childRow : children) {
-                    if (orderedChildren == null || !orderedChildren.contains(childRow)) {
-                        toRemove.add(childRow);
-                    }
-                }
-                for (ExpandableNotificationRow remove : toRemove) {
-                    parent.removeChildNotification(remove);
-                    mStackScroller.notifyGroupChildRemoved(remove);
-                }
-            }
-        }
-
+    private void addNotificationChildrenAndSort() {
         // Let's now add all notification children which are missing
         boolean orderChanged = false;
         for (int i = 0; i < mStackScroller.getChildCount(); i++) {
@@ -1581,6 +1563,39 @@
         }
     }
 
+    private void removeNotificationChildren() {
+        // First let's remove all children which don't belong in the parents
+        ArrayList<ExpandableNotificationRow> toRemove = new ArrayList<>();
+        for (int i = 0; i < mStackScroller.getChildCount(); i++) {
+            View view = mStackScroller.getChildAt(i);
+            if (!(view instanceof ExpandableNotificationRow)) {
+                // We don't care about non-notification views.
+                continue;
+            }
+
+            ExpandableNotificationRow parent = (ExpandableNotificationRow) view;
+            List<ExpandableNotificationRow> children = parent.getNotificationChildren();
+            List<ExpandableNotificationRow> orderedChildren = mTmpChildOrderMap.get(parent);
+
+            if (children != null) {
+                toRemove.clear();
+                for (ExpandableNotificationRow childRow : children) {
+                    if (orderedChildren == null || !orderedChildren.contains(childRow)) {
+                        toRemove.add(childRow);
+                    }
+                }
+                for (ExpandableNotificationRow remove : toRemove) {
+                    parent.removeChildNotification(remove);
+                    if (mNotificationData.get(remove.getStatusBarNotification().getKey()) == null) {
+                        // We only want to add an animation if the view is completely removed
+                        // otherwise it's just a transfer
+                        mStackScroller.notifyGroupChildRemoved(remove);
+                    }
+                }
+            }
+        }
+    }
+
     @Override
     public void addQsTile(ComponentName tile) {
         mQSPanel.getHost().addTile(tile);
@@ -1597,8 +1612,7 @@
     }
 
     private boolean packageHasVisibilityOverride(String key) {
-        return mNotificationData.getVisibilityOverride(key)
-                != NotificationListenerService.Ranking.VISIBILITY_NO_OVERRIDE;
+        return mNotificationData.getVisibilityOverride(key) == Notification.VISIBILITY_PRIVATE;
     }
 
     private void updateClearAll() {
@@ -1933,6 +1947,7 @@
 
                     // We are unlocking directly - no animation!
                     mBackdrop.setVisibility(View.GONE);
+                    mBackdropBack.setImageDrawable(null);
                 } else {
                     mBackdrop.animate()
                             // Never let the alpha become zero - otherwise the RenderNode
@@ -1948,7 +1963,7 @@
                                 public void run() {
                                     mBackdrop.setVisibility(View.GONE);
                                     mBackdropFront.animate().cancel();
-                                    mBackdropBack.animate().cancel();
+                                    mBackdropBack.setImageDrawable(null);
                                     mHandler.post(mHideBackdropFront);
                                 }
                             });
@@ -2246,6 +2261,10 @@
         mStatusBarWindowManager.setPanelExpanded(isExpanded);
     }
 
+    public void onScreenTurnedOff() {
+        mFalsingManager.onScreenOff();
+    }
+
     /**
      * All changes to the status bar and notifications funnel through here and are batched.
      */
@@ -2949,18 +2968,15 @@
             KeyguardUpdateMonitor.getInstance(mContext).dump(fd, pw, args);
         }
 
+        FalsingManager.getInstance(mContext).dump(pw);
+        FalsingLog.dump(pw);
+
         pw.println("SharedPreferences:");
         for (Map.Entry<String, ?> entry : Prefs.getAll(mContext).entrySet()) {
             pw.print("  "); pw.print(entry.getKey()); pw.print("="); pw.println(entry.getValue());
         }
     }
 
-    private String hunStateToString(Entry entry) {
-        if (entry == null) return "null";
-        if (entry.notification == null) return "corrupt";
-        return entry.notification.getPackageName();
-    }
-
     private static void dumpBarTransitions(PrintWriter pw, String var, BarTransitions transitions) {
         pw.print("  "); pw.print(var); pw.print(".BarTransitions.mMode=");
         pw.println(BarTransitions.modeToString(transitions.getMode()));
@@ -3122,7 +3138,7 @@
         }
     };
 
-    private void resetUserExpandedStates() {
+    public void resetUserExpandedStates() {
         ArrayList<Entry> activeNotifications = mNotificationData.getActiveNotifications();
         final int notificationCount = activeNotifications.size();
         for (int i = 0; i < notificationCount; i++) {
@@ -3556,7 +3572,7 @@
     }
 
     @Override
-    protected boolean isPanelFullyCollapsed() {
+    public boolean isPanelFullyCollapsed() {
         return mNotificationPanel.isFullyCollapsed();
     }
 
@@ -4169,7 +4185,6 @@
         mDeviceInteractive = false;
         mWakeUpComingFromTouch = false;
         mWakeUpTouchLocation = null;
-        mFalsingManager.onScreenOff();
         mStackScroller.setAnimationsEnabled(false);
         updateVisibleToUser();
         if (mLaunchCameraOnFinishedGoingToSleep) {
@@ -4476,7 +4491,20 @@
         }
 
         private void handlePulseWhileDozing(@NonNull PulseCallback callback, int reason) {
-            mDozeScrimController.pulse(callback, reason);
+            mDozeScrimController.pulse(new PulseCallback() {
+
+                @Override
+                public void onPulseStarted() {
+                    callback.onPulseStarted();
+                    mStackScroller.setPulsing(true);
+                }
+
+                @Override
+                public void onPulseFinished() {
+                    callback.onPulseFinished();
+                    mStackScroller.setPulsing(false);
+                }
+            }, reason);
         }
 
         private void handleStopDozing() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java
index 80afb9a..5dcd393 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java
@@ -57,6 +57,7 @@
 import com.android.systemui.statusbar.policy.BatteryController;
 import com.android.systemui.statusbar.policy.BluetoothController;
 import com.android.systemui.statusbar.policy.CastController;
+import com.android.systemui.statusbar.policy.NextAlarmController;
 import com.android.systemui.statusbar.policy.NightModeController;
 import com.android.systemui.statusbar.policy.FlashlightController;
 import com.android.systemui.statusbar.policy.HotspotController;
@@ -111,16 +112,19 @@
     private final NightModeController mNightModeController;
     private final AutoTileManager mAutoTiles;
     private final ManagedProfileController mProfileController;
+    private final NextAlarmController mNextAlarmController;
     private View mHeader;
+    private int mCurrentUser;
 
     public QSTileHost(Context context, PhoneStatusBar statusBar,
-                      BluetoothController bluetooth, LocationController location,
-                      RotationLockController rotation, NetworkController network,
-                      ZenModeController zen, HotspotController hotspot,
-                      CastController cast, FlashlightController flashlight,
-                      UserSwitcherController userSwitcher, UserInfoController userInfo,
-                      KeyguardMonitor keyguard, SecurityController security,
-                      BatteryController battery, StatusBarIconController iconController) {
+            BluetoothController bluetooth, LocationController location,
+            RotationLockController rotation, NetworkController network,
+            ZenModeController zen, HotspotController hotspot,
+            CastController cast, FlashlightController flashlight,
+            UserSwitcherController userSwitcher, UserInfoController userInfo,
+            KeyguardMonitor keyguard, SecurityController security,
+            BatteryController battery, StatusBarIconController iconController,
+            NextAlarmController nextAlarmController) {
         mContext = context;
         mStatusBar = statusBar;
         mBluetooth = bluetooth;
@@ -137,6 +141,7 @@
         mSecurity = security;
         mBattery = battery;
         mIconController = iconController;
+        mNextAlarmController = nextAlarmController;
         mNightModeController = new NightModeController(mContext, true);
         mProfileController = new ManagedProfileController(this);
 
@@ -152,6 +157,10 @@
         mAutoTiles = new AutoTileManager(context, this);
     }
 
+    public NextAlarmController getNextAlarmController() {
+        return mNextAlarmController;
+    }
+
     public void setHeaderView(View view) {
         mHeader = view;
     }
@@ -171,6 +180,11 @@
     }
 
     @Override
+    public void removeCallback(Callback callback) {
+        mCallbacks.remove(callback);
+    }
+
+    @Override
     public Collection<QSTile<?>> getTiles() {
         return mTiles.values();
     }
@@ -307,7 +321,8 @@
         }
         if (DEBUG) Log.d(TAG, "Recreating tiles");
         final List<String> tileSpecs = loadTileSpecs(mContext, newValue);
-        if (tileSpecs.equals(mTileSpecs)) return;
+        int currentUser = ActivityManager.getCurrentUser();
+        if (tileSpecs.equals(mTileSpecs) && currentUser == mCurrentUser) return;
         for (Map.Entry<String, QSTile<?>> tile : mTiles.entrySet()) {
             if (!tileSpecs.contains(tile.getKey())) {
                 if (DEBUG) Log.d(TAG, "Destroying tile: " + tile.getKey());
@@ -316,15 +331,16 @@
         }
         final LinkedHashMap<String, QSTile<?>> newTiles = new LinkedHashMap<>();
         for (String tileSpec : tileSpecs) {
-            if (mTiles.containsKey(tileSpec)) {
-                QSTile<?> tile = mTiles.get(tileSpec);
+            QSTile<?> tile = mTiles.get(tileSpec);
+            if (tile != null && (!(tile instanceof CustomTile)
+                    || ((CustomTile) tile).getUser() == currentUser)) {
                 if (DEBUG) Log.d(TAG, "Adding " + tile);
                 tile.removeCallbacks();
                 newTiles.put(tileSpec, tile);
             } else {
                 if (DEBUG) Log.d(TAG, "Creating tile: " + tileSpec);
                 try {
-                    QSTile<?> tile = createTile(tileSpec);
+                    tile = createTile(tileSpec);
                     if (tile != null && tile.isAvailable()) {
                         tile.setTileSpec(tileSpec);
                         newTiles.put(tileSpec, tile);
@@ -334,6 +350,7 @@
                 }
             }
         }
+        mCurrentUser = currentUser;
         mTileSpecs.clear();
         mTileSpecs.addAll(tileSpecs);
         mTiles.clear();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStatusBarHeader.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStatusBarHeader.java
index cf5531f..b29c807 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStatusBarHeader.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStatusBarHeader.java
@@ -35,18 +35,17 @@
 import com.android.systemui.R;
 import com.android.systemui.qs.QSAnimator;
 import com.android.systemui.qs.QSPanel;
-import com.android.systemui.qs.QSTile;
 import com.android.systemui.qs.QuickQSPanel;
 import com.android.systemui.qs.TouchAnimator;
-import com.android.systemui.qs.TouchAnimator.Listener;
 import com.android.systemui.statusbar.policy.BatteryController;
 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, Listener {
+        NextAlarmChangeCallback, OnClickListener {
 
     private static final String TAG = "QuickStatusBarHeader";
 
@@ -91,6 +90,7 @@
     private TouchAnimator mAlarmTranslation;
     private TouchAnimator mSettingsAlpha;
     private float mExpansionAmount;
+    private QSTileHost mHost;
 
     public QuickStatusBarHeader(Context context, AttributeSet attrs) {
         super(context, attrs);
@@ -157,7 +157,6 @@
         mAnimator = new TouchAnimator.Builder()
                 .addFloat(mSettingsContainer, "translationY", -mGearTranslation, 0)
                 .addFloat(mMultiUserSwitch, "translationY", -mGearTranslation, 0)
-                .setListener(this)
                 .build();
         mSecondHalfAnimator = new TouchAnimator.Builder()
                 .addFloat(mSettingsButton, "rotation", -180, 0)
@@ -225,17 +224,11 @@
     }
 
     @Override
-    public void onAnimationAtStart() {
-    }
-
-    @Override
-    public void onAnimationAtEnd() {
-        mHeaderQsPanel.setVisibility(View.INVISIBLE);
-    }
-
-    @Override
-    public void onAnimationStarted() {
-        mHeaderQsPanel.setVisibility(View.VISIBLE);
+    protected void onDetachedFromWindow() {
+        setListening(false);
+        mHost.getUserInfoController().remListener(mUserListener);
+        mHost.getNetworkController().removeEmergencyListener(this);
+        super.onDetachedFromWindow();
     }
 
     private void updateAlarmVisibilities() {
@@ -300,17 +293,18 @@
     }
 
     public void setupHost(final QSTileHost host) {
+        mHost = host;
         host.setHeaderView(this);
         mHeaderQsPanel.setQSPanelAndHeader(mQsPanel, this);
-        mHeaderQsPanel.setHost(host);
-        mHeaderQsPanel.setMaxTiles(5);
-        mHeaderQsPanel.setTiles(host.getTiles());
-        host.addCallback(new QSTile.Host.Callback() {
-            @Override
-            public void onTilesChanged() {
-                mHeaderQsPanel.setTiles(host.getTiles());
-            }
-        });
+        mHeaderQsPanel.setHost(host, null /* No customization in header */);
+        setUserInfoController(host.getUserInfoController());
+        setBatteryController(host.getBatteryController());
+        setNextAlarmController(host.getNextAlarmController());
+
+        final boolean isAPhone = mHost.getNetworkController().hasVoiceCallingFeature();
+        if (isAPhone) {
+            mHost.getNetworkController().addEmergencyListener(this);
+        }
     }
 
     @Override
@@ -356,12 +350,7 @@
 
     @Override
     public void setUserInfoController(UserInfoController userInfoController) {
-        userInfoController.addListener(new UserInfoController.OnUserInfoChangedListener() {
-            @Override
-            public void onUserInfoChanged(String name, Drawable picture) {
-                mMultiUserAvatar.setImageDrawable(picture);
-            }
-        });
+        userInfoController.addListener(mUserListener);
     }
 
     @Override
@@ -374,4 +363,11 @@
             }
         }
     }
+
+    private final OnUserInfoChangedListener mUserListener = new OnUserInfoChangedListener() {
+        @Override
+        public void onUserInfoChanged(String name, Drawable picture) {
+            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 fe76ae7..3eda320 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
@@ -30,7 +30,6 @@
 import android.view.animation.PathInterpolator;
 
 import com.android.systemui.R;
-import com.android.systemui.statusbar.BackDropView;
 import com.android.systemui.statusbar.ExpandableNotificationRow;
 import com.android.systemui.statusbar.NotificationData;
 import com.android.systemui.statusbar.ScrimView;
@@ -46,7 +45,6 @@
     public static final long ANIMATION_DURATION = 220;
     public static final Interpolator KEYGUARD_FADE_OUT_INTERPOLATOR
             = new PathInterpolator(0f, 0, 0.7f, 1f);
-
     private static final float SCRIM_BEHIND_ALPHA = 0.62f;
     private static final float SCRIM_BEHIND_ALPHA_KEYGUARD = 0.45f;
     private static final float SCRIM_BEHIND_ALPHA_UNLOCKING = 0.2f;
@@ -61,6 +59,10 @@
     private final UnlockMethodCache mUnlockMethodCache;
     private final View mHeadsUpScrim;
 
+    private float mScrimBehindAlpha = SCRIM_BEHIND_ALPHA;
+    private float mScrimBehindAlphaKeyguard = SCRIM_BEHIND_ALPHA_KEYGUARD;
+    private float mScrimBehindAlphaUnlocking = SCRIM_BEHIND_ALPHA_UNLOCKING;
+
     protected boolean mKeyguardShowing;
     private float mFraction;
 
@@ -75,8 +77,6 @@
     private long mAnimationDelay;
     private Runnable mOnAnimationFinished;
     private final Interpolator mInterpolator = new DecelerateInterpolator();
-    private BackDropView mBackDropView;
-    private boolean mScrimSrcEnabled;
     private boolean mDozing;
     private float mDozeInFrontAlpha;
     private float mDozeBehindAlpha;
@@ -89,15 +89,14 @@
     private boolean mForceHideScrims;
     private boolean mSkipFirstFrame;
     private boolean mDontAnimateBouncerChanges;
+    private boolean mKeyguardFadingOutInProgress;
 
-    public ScrimController(ScrimView scrimBehind, ScrimView scrimInFront, View headsUpScrim,
-            boolean scrimSrcEnabled) {
+    public ScrimController(ScrimView scrimBehind, ScrimView scrimInFront, View headsUpScrim) {
         mScrimBehind = scrimBehind;
         mScrimInFront = scrimInFront;
         mHeadsUpScrim = headsUpScrim;
         final Context context = scrimBehind.getContext();
         mUnlockMethodCache = UnlockMethodCache.getInstance(context);
-        mScrimSrcEnabled = scrimSrcEnabled;
         updateHeadsUpScrim(false);
     }
 
@@ -106,6 +105,19 @@
         scheduleUpdate();
     }
 
+    public void setShowScrimBehind(boolean show) {
+        if (show) {
+            mScrimBehindAlpha = SCRIM_BEHIND_ALPHA;
+            mScrimBehindAlphaKeyguard = SCRIM_BEHIND_ALPHA_KEYGUARD;
+            mScrimBehindAlphaUnlocking = SCRIM_BEHIND_ALPHA_UNLOCKING;
+        } else {
+            mScrimBehindAlpha = 0;
+            mScrimBehindAlphaKeyguard = 0;
+            mScrimBehindAlphaUnlocking = 0;
+        }
+        scheduleUpdate();
+    }
+
     public void onTrackingStarted() {
         mExpanding = true;
         mDarkenWhileDragging = !mUnlockMethodCache.canSkipBouncer();
@@ -234,7 +246,7 @@
             fraction = (float) Math.pow(fraction, 0.8f);
             behindFraction = (float) Math.pow(behindFraction, 0.8f);
             setScrimInFrontColor(fraction * SCRIM_IN_FRONT_ALPHA);
-            setScrimBehindColor(behindFraction * SCRIM_BEHIND_ALPHA_KEYGUARD);
+            setScrimBehindColor(behindFraction * mScrimBehindAlphaKeyguard);
         } else if (mBouncerShowing) {
             setScrimInFrontColor(SCRIM_IN_FRONT_ALPHA);
             setScrimBehindColor(0f);
@@ -242,8 +254,8 @@
             float fraction = Math.max(0, Math.min(mFraction, 1));
             setScrimInFrontColor(0f);
             setScrimBehindColor(fraction
-                    * (SCRIM_BEHIND_ALPHA_KEYGUARD - SCRIM_BEHIND_ALPHA_UNLOCKING)
-                    + SCRIM_BEHIND_ALPHA_UNLOCKING);
+                    * (mScrimBehindAlphaKeyguard - mScrimBehindAlphaUnlocking)
+                    + mScrimBehindAlphaUnlocking);
         }
     }
 
@@ -256,7 +268,7 @@
         } else {
             // woo, special effects
             final float k = (float)(1f-0.5f*(1f-Math.cos(3.14159f * Math.pow(1f-frac, 2f))));
-            setScrimBehindColor(k * SCRIM_BEHIND_ALPHA);
+            setScrimBehindColor(k * mScrimBehindAlpha);
         }
     }
 
@@ -331,12 +343,16 @@
                 if (mOnAnimationFinished != null) {
                     mOnAnimationFinished.run();
                     mOnAnimationFinished = null;
+                    mKeyguardFadingOutInProgress = false;
                 }
                 scrim.setTag(TAG_KEY_ANIM, null);
                 scrim.setTag(TAG_KEY_ANIM_TARGET, null);
             }
         });
         anim.start();
+        if (mAnimateKeyguardFadingOut) {
+            mKeyguardFadingOutInProgress = true;
+        }
         if (mSkipFirstFrame) {
             anim.setCurrentPlayTime(16);
         }
@@ -371,6 +387,7 @@
                 && mOnAnimationFinished != null) {
             mOnAnimationFinished.run();
             mOnAnimationFinished = null;
+            mKeyguardFadingOutInProgress = false;
         }
     }
 
@@ -378,19 +395,7 @@
         return scrim.getTag(TAG_KEY_ANIM) != null;
     }
 
-    public void setBackDropView(BackDropView backDropView) {
-        mBackDropView = backDropView;
-        mBackDropView.setOnVisibilityChangedRunnable(new Runnable() {
-            @Override
-            public void run() {
-                updateScrimBehindDrawingMode();
-            }
-        });
-        updateScrimBehindDrawingMode();
-    }
-
-    private void updateScrimBehindDrawingMode() {
-        boolean asSrc = mBackDropView.getVisibility() != View.VISIBLE && mScrimSrcEnabled;
+    public void setDrawBehindAsSrc(boolean asSrc) {
         mScrimBehind.setDrawAsSrc(asSrc);
     }
 
@@ -423,6 +428,10 @@
     }
 
     private void updateScrim(boolean animate, View scrim, float alpha, float currentAlpha) {
+        if (mKeyguardFadingOutInProgress) {
+            return;
+        }
+
         ValueAnimator previousAnimator = StackStateAnimator.getChildTag(scrim,
                 TAG_KEY_ANIM);
         float animEndValue = -1;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java
index 3e3b169..a051973 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java
@@ -39,7 +39,6 @@
 import android.widget.Switch;
 import android.widget.TextView;
 import android.widget.Toast;
-
 import com.android.keyguard.KeyguardStatusView;
 import com.android.systemui.BatteryMeterView;
 import com.android.systemui.FontSizeUtils;
@@ -48,7 +47,7 @@
 import com.android.systemui.qs.QSTile;
 import com.android.systemui.qs.QSTile.DetailAdapter;
 import com.android.systemui.statusbar.policy.BatteryController;
-import com.android.systemui.statusbar.policy.NetworkControllerImpl.EmergencyListener;
+import com.android.systemui.statusbar.policy.NetworkController.EmergencyListener;
 import com.android.systemui.statusbar.policy.NextAlarmController;
 import com.android.systemui.statusbar.policy.UserInfoController;
 import com.android.systemui.tuner.TunerService;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
index 0e84f733..2ba1562 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -212,6 +212,7 @@
 
     public void onScreenTurnedOff() {
         mScreenTurnedOn = false;
+        mPhoneStatusBar.onScreenTurnedOff();
     }
 
     public void notifyDeviceWakeUpRequested() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java
index fcaf050..77ece93 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java
@@ -173,7 +173,7 @@
     private void applyInputFeatures(State state) {
         if (state.isKeyguardShowingAndNotOccluded()
                 && state.statusBarState == StatusBarState.KEYGUARD
-                && !state.qsExpanded) {
+                && !state.qsExpanded && !state.forceUserActivity) {
             mLpChanged.inputFeatures |=
                     WindowManager.LayoutParams.INPUT_FEATURE_DISABLE_USER_ACTIVITY;
         } else {
@@ -265,6 +265,11 @@
         apply(mCurrentState);
     }
 
+    public void setForceUserActivity(boolean forceUserActivity) {
+        mCurrentState.forceUserActivity = forceUserActivity;
+        apply(mCurrentState);
+    }
+
     public void setHeadsUpShowing(boolean showing) {
         mCurrentState.headsUpShowing = showing;
         apply(mCurrentState);
@@ -332,6 +337,7 @@
         boolean forceStatusBarVisible;
         boolean forceCollapsed;
         boolean forceDozeBrightness;
+        boolean forceUserActivity;
 
         /**
          * The {@link BaseStatusBar} state from the status bar.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/CallbackHandler.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/CallbackHandler.java
index e618cb8..3142ddf 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/CallbackHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/CallbackHandler.java
@@ -19,11 +19,10 @@
 import android.os.Looper;
 import android.os.Message;
 import android.telephony.SubscriptionInfo;
-
 import com.android.internal.annotations.VisibleForTesting;
+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.NetworkControllerImpl.EmergencyListener;
 
 import java.util.ArrayList;
 import java.util.List;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/EthernetSignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/EthernetSignalController.java
index bd36462..159bd41 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/EthernetSignalController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/EthernetSignalController.java
@@ -19,6 +19,7 @@
 import android.net.NetworkCapabilities;
 
 import com.android.systemui.statusbar.policy.NetworkController.IconState;
+import com.android.systemui.statusbar.policy.NetworkController.SignalCallback;
 
 import java.util.BitSet;
 
@@ -46,12 +47,12 @@
     }
 
     @Override
-    public void notifyListeners() {
+    public void notifyListeners(SignalCallback callback) {
         boolean ethernetVisible = mCurrentState.connected;
         String contentDescription = getStringIfExists(getContentDescription());
 
         // TODO: wire up data transfer using WifiSignalPoller.
-        mCallbackHandler.setEthernetIndicators(new IconState(ethernetVisible, getCurrentIconId(),
+        callback.setEthernetIndicators(new IconState(ethernetVisible, getCurrentIconId(),
                 contentDescription));
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/FlashlightController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/FlashlightController.java
index 29a8f67..9a21a1e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/FlashlightController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/FlashlightController.java
@@ -93,6 +93,10 @@
         }
     }
 
+    public boolean hasFlashlight() {
+        return mCameraId != null;
+    }
+
     public synchronized boolean isEnabled() {
         return mFlashlightEnabled;
     }
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 8fd4d9c..80dcfb6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
@@ -34,6 +34,7 @@
 import com.android.internal.telephony.cdma.EriInfo;
 import com.android.systemui.R;
 import com.android.systemui.statusbar.policy.NetworkController.IconState;
+import com.android.systemui.statusbar.policy.NetworkController.SignalCallback;
 import com.android.systemui.statusbar.policy.NetworkControllerImpl.Config;
 import com.android.systemui.statusbar.policy.NetworkControllerImpl.SubscriptionDefaults;
 
@@ -198,7 +199,7 @@
     }
 
     @Override
-    public void notifyListeners() {
+    public void notifyListeners(SignalCallback callback) {
         MobileIconGroup icons = getIcons();
 
         String contentDescription = getStringIfExists(getContentDescription());
@@ -231,7 +232,7 @@
                 || mCurrentState.iconGroup == TelephonyIcons.ROAMING
                 || mCurrentState.iconGroup == TelephonyIcons.DATA_DISABLED;
         int typeIcon = showDataIcon ? icons.mDataType : 0;
-        mCallbackHandler.setMobileDataIndicators(statusIcon, qsIcon, typeIcon, qsTypeIcon,
+        callback.setMobileDataIndicators(statusIcon, qsIcon, typeIcon, qsTypeIcon,
                 activityIn, activityOut, dataContentDescription, description, icons.mIsWide,
                 mSubscriptionInfo.getSubscriptionId());
     }
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 93c7322..348e0b0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
@@ -19,7 +19,6 @@
 import android.content.Context;
 import android.content.Intent;
 import android.telephony.SubscriptionInfo;
-
 import com.android.settingslib.net.DataUsageController;
 import com.android.settingslib.wifi.AccessPoint;
 
@@ -36,6 +35,11 @@
     DataUsageController getMobileDataController();
     DataSaverController getDataSaverController();
 
+    boolean hasVoiceCallingFeature();
+
+    void addEmergencyListener(EmergencyListener listener);
+    void removeEmergencyListener(EmergencyListener listener);
+
     public interface SignalCallback {
         void setWifiIndicators(boolean enabled, IconState statusIcon, IconState qsIcon,
                 boolean activityIn, boolean activityOut, String description);
@@ -53,6 +57,10 @@
         void setMobileDataEnabled(boolean enabled);
     }
 
+    public interface EmergencyListener {
+        void setEmergencyCallsOnly(boolean emergencyOnly);
+    }
+
     public static class IconState {
         public final boolean visible;
         public final int icon;
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 eecf8c2..40eb71d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
@@ -252,6 +252,10 @@
         mCallbackHandler.setEmergencyCallsOnly(isEmergencyOnly());
     }
 
+    public void removeEmergencyListener(EmergencyListener listener) {
+        mCallbackHandler.setListening(listener, false);
+    }
+
     public boolean hasMobileDataFeature() {
         return mHasMobileDataFeature;
     }
@@ -318,16 +322,16 @@
     }
 
     public void addSignalCallback(SignalCallback cb) {
-        mCallbackHandler.setListening(cb, true);
-        mCallbackHandler.setSubs(mCurrentSubscriptions);
-        mCallbackHandler.setIsAirplaneMode(new IconState(mAirplaneMode,
+        cb.setSubs(mCurrentSubscriptions);
+        cb.setIsAirplaneMode(new IconState(mAirplaneMode,
                 TelephonyIcons.FLIGHT_MODE_ICON, R.string.accessibility_airplane_mode, mContext));
-        mCallbackHandler.setNoSims(mHasNoSims);
-        mWifiSignalController.notifyListeners();
-        mEthernetSignalController.notifyListeners();
+        cb.setNoSims(mHasNoSims);
+        mWifiSignalController.notifyListeners(cb);
+        mEthernetSignalController.notifyListeners(cb);
         for (MobileSignalController mobileSignalController : mMobileSignalControllers.values()) {
-            mobileSignalController.notifyListeners();
+            mobileSignalController.notifyListeners(cb);
         }
+        mCallbackHandler.setListening(cb, true);
     }
 
     @Override
@@ -812,10 +816,6 @@
         }
     };
 
-    public interface EmergencyListener {
-        void setEmergencyCallsOnly(boolean emergencyOnly);
-    }
-
     public static class SubscriptionDefaults {
         public int getDefaultVoiceSubId() {
             return SubscriptionManager.getDefaultVoiceSubscriptionId();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NightModeController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NightModeController.java
index 0b1911b..4611ef9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NightModeController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NightModeController.java
@@ -14,17 +14,13 @@
 
 package com.android.systemui.statusbar.policy;
 
-import libcore.util.Objects;
-
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.opengl.Matrix;
-import android.provider.Settings;
 import android.provider.Settings.Secure;
 import android.util.MathUtils;
-
 import com.android.systemui.tuner.TunerService;
 
 import java.util.ArrayList;
@@ -189,8 +185,8 @@
     }
 
     private void updateNightMode(Intent intent) {
-        mIsNight = intent.getBooleanExtra(EXTRA_IS_NIGHT, false);
-        mAmount = intent.getFloatExtra(EXTRA_AMOUNT, 0);
+        mIsNight = intent != null && intent.getBooleanExtra(EXTRA_IS_NIGHT, false);
+        mAmount = intent != null ? intent.getFloatExtra(EXTRA_AMOUNT, 0) : 0;
     }
 
     private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java
index c6659d1..29b0f4b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java
@@ -155,8 +155,21 @@
     }
 
     @Override
+    protected void onAttachedToWindow() {
+        super.onAttachedToWindow();
+        if (mEntry.row.isChangingPosition()) {
+            if (getVisibility() == VISIBLE && mEditText.isFocusable()) {
+                mEditText.requestFocus();
+            }
+        }
+    }
+
+    @Override
     protected void onDetachedFromWindow() {
         super.onDetachedFromWindow();
+        if (mEntry.row.isChangingPosition()) {
+            return;
+        }
         mController.removeRemoteInput(mEntry);
     }
 
@@ -229,6 +242,9 @@
         }
 
         private void defocusIfNeeded() {
+            if (mDefocusListener.mEntry.row.isChangingPosition()) {
+                return;
+            }
             if (isFocusable() && isEnabled()) {
                 setInnerFocusable(false);
                 if (mDefocusListener != null) {
@@ -248,9 +264,11 @@
         }
 
         @Override
-        protected void onFocusLost() {
-            super.onFocusLost();
-            defocusIfNeeded();
+        protected void onFocusChanged(boolean focused, int direction, Rect previouslyFocusedRect) {
+            super.onFocusChanged(focused, direction, previouslyFocusedRect);
+            if (!focused) {
+                defocusIfNeeded();
+            }
         }
 
         @Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SignalController.java
index c954d08..4cfd1c7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SignalController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SignalController.java
@@ -18,6 +18,7 @@
 import android.content.Context;
 import android.text.format.DateFormat;
 import android.util.Log;
+import com.android.systemui.statusbar.policy.NetworkController.SignalCallback;
 
 import java.io.PrintWriter;
 import java.util.BitSet;
@@ -48,7 +49,7 @@
     // is aware of current state.
     protected final NetworkControllerImpl mNetworkController;
 
-    protected final CallbackHandler mCallbackHandler;
+    private final CallbackHandler mCallbackHandler;
 
     // Save the previous HISTORY_SIZE states for logging.
     private final State[] mHistory;
@@ -198,12 +199,16 @@
         }
     }
 
+    public final void notifyListeners() {
+        notifyListeners(mCallbackHandler);
+    }
+
     /**
      * Trigger callbacks based on current state.  The callbacks should be completely
      * based on current state, and only need to be called in the scenario where
      * mCurrentState != mLastState.
      */
-    public abstract void notifyListeners();
+    public abstract void notifyListeners(SignalCallback callback);
 
     /**
      * Generate a blank T.
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 53fd446..cedc3c7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
@@ -37,6 +37,8 @@
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.provider.Settings;
+import android.telephony.PhoneStateListener;
+import android.telephony.TelephonyManager;
 import android.util.Log;
 import android.util.SparseArray;
 import android.util.SparseBooleanArray;
@@ -99,7 +101,6 @@
     private boolean mSimpleUserSwitcher;
     private boolean mAddUsersWhenLocked;
     private boolean mPauseRefreshUsers;
-    private boolean mAllowUserSwitchingWhenSystemUserLocked;
     private SparseBooleanArray mForcePictureLoadForUserId = new SparseBooleanArray(2);
 
     public UserSwitcherController(Context context, KeyguardMonitor keyguardMonitor,
@@ -140,6 +141,7 @@
         mSettingsObserver.onChange(false);
 
         keyguardMonitor.addCallback(mCallback);
+        listenForCallState();
 
         refreshUsers(UserHandle.USER_NULL);
     }
@@ -186,8 +188,7 @@
                 }
                 ArrayList<UserRecord> records = new ArrayList<>(infos.size());
                 int currentId = ActivityManager.getCurrentUser();
-                boolean allowUserSwitching = mAllowUserSwitchingWhenSystemUserLocked
-                        || mUserManager.isUserUnlocked(UserHandle.SYSTEM);
+                boolean canSwitchUsers = mUserManager.canSwitchUsers();
                 UserInfo currentUserInfo = null;
                 UserRecord guestRecord = null;
                 int avatarSize = mContext.getResources()
@@ -198,12 +199,14 @@
                     if (isCurrent) {
                         currentUserInfo = info;
                     }
-                    boolean switchToEnabled = allowUserSwitching || isCurrent;
+                    boolean switchToEnabled = canSwitchUsers || isCurrent;
                     if (info.isEnabled()) {
                         if (info.isGuest()) {
+                            // Tapping guest icon triggers remove and a user switch therefore
+                            // the icon shouldn't be enabled even if the user is current
                             guestRecord = new UserRecord(info, null /* picture */,
                                     true /* isGuest */, isCurrent, false /* isAddUser */,
-                                    false /* isRestricted */, switchToEnabled);
+                                    false /* isRestricted */, canSwitchUsers);
                         } else if (info.supportsSwitchToByUser()) {
                             Bitmap picture = bitmaps.get(info.id);
                             if (picture == null) {
@@ -240,7 +243,7 @@
                         if (canCreateGuest) {
                             guestRecord = new UserRecord(null /* info */, null /* picture */,
                                     true /* isGuest */, false /* isCurrent */,
-                                    false /* isAddUser */, createIsRestricted, allowUserSwitching);
+                                    false /* isAddUser */, createIsRestricted, canSwitchUsers);
                             checkIfAddUserDisallowedByAdminOnly(guestRecord);
                             records.add(guestRecord);
                         }
@@ -253,7 +256,7 @@
                 if (!mSimpleUserSwitcher && canCreateUser) {
                     UserRecord addUserRecord = new UserRecord(null /* info */, null /* picture */,
                             false /* isGuest */, false /* isCurrent */, true /* isAddUser */,
-                            createIsRestricted, allowUserSwitching);
+                            createIsRestricted, canSwitchUsers);
                     checkIfAddUserDisallowedByAdminOnly(addUserRecord);
                     records.add(addUserRecord);
                 }
@@ -417,6 +420,24 @@
         mUserManager.removeUser(id);
     }
 
+    private void listenForCallState() {
+        TelephonyManager.from(mContext).listen(new PhoneStateListener() {
+            private int mCallState;
+            @Override
+            public void onCallStateChanged(int state, String incomingNumber) {
+                if (mCallState == state) return;
+                if (DEBUG) Log.v(TAG, "Call state changed: " + state);
+                mCallState = state;
+                int currentUserId = ActivityManager.getCurrentUser();
+                UserInfo userInfo = mUserManager.getUserInfo(currentUserId);
+                if (userInfo != null && userInfo.isGuest()) {
+                    showGuestNotification(currentUserId);
+                }
+                refreshUsers(UserHandle.USER_NULL);
+            }
+        }, PhoneStateListener.LISTEN_CALL_STATE);
+    }
+
     private BroadcastReceiver mReceiver = new BroadcastReceiver() {
         @Override
         public void onReceive(Context context, Intent intent) {
@@ -488,25 +509,6 @@
             }
         }
 
-        private void showGuestNotification(int guestUserId) {
-            PendingIntent removeGuestPI = PendingIntent.getBroadcastAsUser(mContext,
-                    0, new Intent(ACTION_REMOVE_GUEST), 0, UserHandle.SYSTEM);
-            Notification notification = new Notification.Builder(mContext)
-                    .setVisibility(Notification.VISIBILITY_SECRET)
-                    .setPriority(Notification.PRIORITY_MIN)
-                    .setSmallIcon(R.drawable.ic_person)
-                    .setContentTitle(mContext.getString(R.string.guest_notification_title))
-                    .setContentText(mContext.getString(R.string.guest_notification_text))
-                    .setContentIntent(removeGuestPI)
-                    .setShowWhen(false)
-                    .addAction(R.drawable.ic_delete,
-                            mContext.getString(R.string.guest_notification_remove_action),
-                            removeGuestPI)
-                    .build();
-            NotificationManager.from(mContext).notifyAsUser(TAG_REMOVE_GUEST, ID_REMOVE_GUEST,
-                    notification, new UserHandle(guestUserId));
-        }
-
         private void showLogoutNotification(int userId) {
             PendingIntent logoutPI = PendingIntent.getBroadcastAsUser(mContext,
                     0, new Intent(ACTION_LOGOUT_USER), 0, UserHandle.SYSTEM);
@@ -528,6 +530,28 @@
         }
     };
 
+    private void showGuestNotification(int guestUserId) {
+        boolean canSwitchUsers = mUserManager.canSwitchUsers();
+        // Disable 'Remove guest' action if cannot switch users right now
+        PendingIntent removeGuestPI = canSwitchUsers ? PendingIntent.getBroadcastAsUser(mContext,
+                0, new Intent(ACTION_REMOVE_GUEST), 0, UserHandle.SYSTEM) : null;
+
+        Notification notification = new Notification.Builder(mContext)
+                .setVisibility(Notification.VISIBILITY_SECRET)
+                .setPriority(Notification.PRIORITY_MIN)
+                .setSmallIcon(R.drawable.ic_person)
+                .setContentTitle(mContext.getString(R.string.guest_notification_title))
+                .setContentText(mContext.getString(R.string.guest_notification_text))
+                .setContentIntent(removeGuestPI)
+                .setShowWhen(false)
+                .addAction(R.drawable.ic_delete,
+                        mContext.getString(R.string.guest_notification_remove_action),
+                        removeGuestPI)
+                .build();
+        NotificationManager.from(mContext).notifyAsUser(TAG_REMOVE_GUEST, ID_REMOVE_GUEST,
+                notification, new UserHandle(guestUserId));
+    }
+
     private final Runnable mUnpauseRefreshUsers = new Runnable() {
         @Override
         public void run() {
@@ -543,9 +567,6 @@
                     SIMPLE_USER_SWITCHER_GLOBAL_SETTING, 0) != 0;
             mAddUsersWhenLocked = Settings.Global.getInt(mContext.getContentResolver(),
                     Settings.Global.ADD_USERS_WHEN_LOCKED, 0) != 0;
-            mAllowUserSwitchingWhenSystemUserLocked = Settings.Global.getInt(
-                    mContext.getContentResolver(),
-                    Settings.Global.ALLOW_USER_SWITCHING_WHEN_SYSTEM_USER_LOCKED, 0) != 0;
             refreshUsers(UserHandle.USER_NULL);
         };
     };
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 cc98eb6..a6ed04f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiSignalController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiSignalController.java
@@ -28,6 +28,7 @@
 import com.android.internal.util.AsyncChannel;
 import com.android.settingslib.wifi.WifiStatusTracker;
 import com.android.systemui.statusbar.policy.NetworkController.IconState;
+import com.android.systemui.statusbar.policy.NetworkController.SignalCallback;
 
 import java.util.Objects;
 
@@ -72,7 +73,7 @@
     }
 
     @Override
-    public void notifyListeners() {
+    public void notifyListeners(SignalCallback callback) {
         // only show wifi in the cluster if connected or if wifi-only
         boolean wifiVisible = mCurrentState.enabled
                 && (mCurrentState.connected || !mHasMobileData);
@@ -83,7 +84,7 @@
         IconState statusIcon = new IconState(wifiVisible, getCurrentIconId(), contentDescription);
         IconState qsIcon = new IconState(mCurrentState.connected, getQsCurrentIconId(),
                 contentDescription);
-        mCallbackHandler.setWifiIndicators(mCurrentState.enabled, statusIcon, qsIcon,
+        callback.setWifiIndicators(mCurrentState.enabled, statusIcon, qsIcon,
                 ssidPresent && mCurrentState.activityIn, ssidPresent && mCurrentState.activityOut,
                 wifiDesc);
     }
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 030c8b7..676ff2e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationChildrenContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationChildrenContainer.java
@@ -96,7 +96,8 @@
                 com.android.internal.R.dimen.notification_content_margin_top);
         mNotificatonTopPadding = getResources().getDimensionPixelSize(
                 R.dimen.notification_children_container_top_padding);
-        mCollapsedBottompadding = 11.5f * getResources().getDisplayMetrics().density;
+        mCollapsedBottompadding = getResources().getDimensionPixelSize(
+                com.android.internal.R.dimen.notification_content_margin_bottom);
     }
 
     @Override
@@ -167,6 +168,7 @@
         int newIndex = childIndex < 0 ? mChildren.size() : childIndex;
         mChildren.add(newIndex, row);
         addView(row);
+        row.setUserLocked(mUserLocked);
 
         View divider = inflateDivider();
         addView(divider);
@@ -191,6 +193,7 @@
         });
 
         row.setSystemChildExpanded(false);
+        row.setUserLocked(false);
         updateGroupOverflow();
     }
 
@@ -262,10 +265,14 @@
     }
 
     private void updateExpansionStates() {
-        // Let's make the first child expanded if the parent is
-        for (int i = 0; i < mChildren.size(); i++) {
+        if (mChildrenExpanded || mUserLocked) {
+            // we don't modify it the group is expanded or if we are expanding it
+            return;
+        }
+        int size = mChildren.size();
+        for (int i = 0; i < size; i++) {
             ExpandableNotificationRow child = mChildren.get(i);
-            child.setSystemChildExpanded(false);
+            child.setSystemChildExpanded(i == 0 && size == 1);
         }
     }
 
@@ -489,6 +496,7 @@
 
     public void setChildrenExpanded(boolean childrenExpanded) {
         mChildrenExpanded = childrenExpanded;
+        updateExpansionStates();
     }
 
     public void setNotificationParent(ExpandableNotificationRow parent) {
@@ -504,7 +512,7 @@
                 break;
             }
             ExpandableNotificationRow child = mChildren.get(i);
-            float childHeight = child.isExpanded()
+            float childHeight = child.isExpanded(true /* allowOnKeyguard */)
                     ? child.getMaxExpandHeight()
                     : child.getShowingLayout().getMinHeight(true /* likeGroupExpanded */);
             maxContentHeight += childHeight;
@@ -525,7 +533,7 @@
         int childCount = mChildren.size();
         for (int i = 0; i < childCount; i++) {
             ExpandableNotificationRow child = mChildren.get(i);
-            float childHeight = child.isExpanded()
+            float childHeight = child.isExpanded(true /* allowOnKeyguard */)
                     ? child.getMaxExpandHeight()
                     : child.getShowingLayout().getMinHeight(true /* likeGroupExpanded */);
             float singleLineHeight = child.getShowingLayout().getMinHeight(
@@ -566,8 +574,28 @@
         return getIntrinsicHeight(NUMBER_OF_CHILDREN_WHEN_COLLAPSED);
     }
 
-    public int getMinExpandHeight() {
-        return getIntrinsicHeight(getMaxAllowedVisibleChildren(true /* forceCollapsed */));
+    public int getMinExpandHeight(boolean onKeyguard) {
+        int maxAllowedVisibleChildren = onKeyguard ? NUMBER_OF_CHILDREN_WHEN_COLLAPSED
+                : getMaxAllowedVisibleChildren(true /* forceCollapsed */);
+        int minExpandHeight = mNotificationHeaderHeight;
+        int visibleChildren = 0;
+        boolean firstChild = true;
+        int childCount = mChildren.size();
+        for (int i = 0; i < childCount; i++) {
+            if (visibleChildren >= maxAllowedVisibleChildren) {
+                break;
+            }
+            if (!firstChild) {
+                minExpandHeight += mChildPadding;
+            } else {
+                firstChild = false;
+            }
+            ExpandableNotificationRow child = mChildren.get(i);
+            minExpandHeight += child.getMinHeight();
+            visibleChildren++;
+        }
+        minExpandHeight += mCollapsedBottompadding;
+        return minExpandHeight;
     }
 
     public void setDark(boolean dark, boolean fade, long delay) {
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 340ebb4..4cb0dea 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
@@ -18,7 +18,6 @@
 
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
-import android.animation.AnimatorSet;
 import android.animation.ObjectAnimator;
 import android.animation.PropertyValuesHolder;
 import android.animation.TimeAnimator;
@@ -48,6 +47,8 @@
 import android.view.animation.Interpolator;
 import android.widget.OverScroller;
 
+import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.MetricsProto.MetricsEvent;
 import com.android.systemui.ExpandHelper;
 import com.android.systemui.Interpolators;
 import com.android.systemui.R;
@@ -322,6 +323,8 @@
             }
         }
     };
+    private PorterDuffXfermode mSrcMode = new PorterDuffXfermode(PorterDuff.Mode.SRC);
+    private boolean mPulsing;
 
     public NotificationStackScrollLayout(Context context) {
         this(context, null);
@@ -357,17 +360,23 @@
             mDebugPaint.setStyle(Paint.Style.STROKE);
         }
         mFalsingManager = FalsingManager.getInstance(context);
-        mBackgroundPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC));
     }
 
     @Override
-    public void onGearTouched(ExpandableNotificationRow row) {
+    public void onGearTouched(ExpandableNotificationRow row, int x, int y) {
         if (mLongPressListener != null) {
-            mLongPressListener.onLongPress(row, 0, 0);
+            MetricsLogger.action(mContext, MetricsEvent.ACTION_TOUCH_GEAR,
+                    row.getStatusBarNotification().getPackageName());
+            mLongPressListener.onLongPress(row, x, y);
         }
     }
 
     @Override
+    public void onSettingsIconRowReset(NotificationSettingsIconRow row) {
+        mSwipeHelper.setSnappedToGear(false);
+    }
+
+    @Override
     protected void onDraw(Canvas canvas) {
         canvas.drawRect(0, mCurrentBounds.top, getWidth(), mCurrentBounds.bottom, mBackgroundPaint);
         if (DEBUG) {
@@ -418,12 +427,14 @@
                 .getDimensionPixelSize(R.dimen.notification_divider_height));
         mIncreasedPaddingBetweenElements = context.getResources()
                 .getDimensionPixelSize(R.dimen.notification_divider_height_increased);
-
         mBottomStackSlowDownHeight = mStackScrollAlgorithm.getBottomStackSlowDownLength();
         mMinTopOverScrollToEscape = getResources().getDimensionPixelSize(
                 R.dimen.min_top_overscroll_to_qs);
-        mCollapseSecondCardPadding = getResources().getDimensionPixelSize(
-                R.dimen.notification_collapse_second_card_padding);
+    }
+
+    public void setDrawBackgroundAsSrc(boolean asSrc) {
+        mBackgroundPaint.setXfermode(asSrc ? mSrcMode : null);
+        invalidate();
     }
 
     private void notifyHeightChangeListener(ExpandableView view) {
@@ -509,14 +520,6 @@
     }
 
     /**
-     * @return whether the height of the layout needs to be adapted, in order to ensure that the
-     *         last child is not in the bottom stack.
-     */
-    private boolean needsHeightAdaption() {
-        return getNotGoneChildCount() > 1;
-    }
-
-    /**
      * Updates the children views according to the stack scroll algorithm. Call this whenever
      * modifications to {@link #mOwnScrollY} are performed to reflect it in the view layout.
      */
@@ -599,7 +602,7 @@
         mLastSetStackHeight = height;
         setIsExpanded(height > 0.0f);
         int newStackHeight = (int) height;
-        int minStackHeight = getMinStackHeight();
+        int minStackHeight = getLayoutMinHeight();
         int stackHeight;
         float paddingOffset;
         boolean trackingHeadsUp = mTrackingHeadsUp || mHeadsUpManager.hasPinnedHeadsUp();
@@ -612,20 +615,7 @@
             stackHeight = newStackHeight;
         } else {
             int translationY;
-            if (!trackingHeadsUp) {
-                // We did not reach the position yet where we actually start growing,
-                // so we translate the stack upwards.
-                translationY = (newStackHeight - minStackHeight);
-                // A slight parallax effect is introduced in order for the stack to catch up with
-                // the top card.
-                float partiallyThere = (newStackHeight - mTopPadding - mTopPaddingOverflow)
-                        / minStackHeight;
-                partiallyThere = Math.max(0, partiallyThere);
-                translationY += (1 - partiallyThere) * (mBottomStackPeekSize +
-                        mCollapseSecondCardPadding);
-            } else {
-                translationY = (int) (height - normalUnfoldPositionStart);
-            }
+            translationY = newStackHeight - normalUnfoldPositionStart;
             paddingOffset = translationY - mTopPadding;
             stackHeight = (int) (height - (translationY - mTopPadding));
         }
@@ -668,8 +658,8 @@
         return mBottomStackPeekSize;
     }
 
-    public int getCollapseSecondCardPadding() {
-        return mCollapseSecondCardPadding;
+    public int getBottomStackSlowDownHeight() {
+        return mBottomStackSlowDownHeight;
     }
 
     public void setLongPressListener(SwipeHelper.LongPressListener listener) {
@@ -732,10 +722,15 @@
             mDragAnimPendingChildren.remove(animView);
         }
 
-        if (targetLeft == 0 && mCurrIconRow != null) {
-            mCurrIconRow.resetState();
-            if (mGearExposedView != null && mGearExposedView == mTranslatingParentView) {
-                mGearExposedView = null;
+        if (mCurrIconRow != null) {
+            if (targetLeft == 0) {
+                mCurrIconRow.resetState();
+                mCurrIconRow = null;
+                if (mGearExposedView != null && mGearExposedView == mTranslatingParentView) {
+                    mGearExposedView = null;
+                }
+            } else {
+                mSwipeHelper.setSnappedToGear(true);
             }
         }
     }
@@ -793,12 +788,15 @@
         if (child instanceof ExpandableNotificationRow) {
             ExpandableNotificationRow row = (ExpandableNotificationRow) child;
             ExpandableNotificationRow parent = row.getNotificationParent();
-            if (mGearExposedView != null && parent != null
-                    && parent.areChildrenExpanded() && mGearExposedView == parent) {
+            if (parent != null && parent.areChildrenExpanded()
+                    && (mGearExposedView == parent
+                        || (parent.getNotificationChildren().size() == 1
+                                && parent.isClearable()))) {
                 // In this case the group is expanded and showing the gear for the
                 // group, further interaction should apply to the group, not any
-                // child notifications so we use the parent of the child.
-                child = row.getNotificationParent();
+                // child notifications so we use the parent of the child. We also do the same
+                // if we only have a single child.
+                child = parent;
             }
         }
         return child;
@@ -876,7 +874,7 @@
     public boolean canChildBeExpanded(View v) {
         return v instanceof ExpandableNotificationRow
                 && ((ExpandableNotificationRow) v).isExpandable()
-                && !((ExpandableNotificationRow) v).isHeadsUp();
+                && (mIsExpanded || !((ExpandableNotificationRow) v).isPinned());
     }
 
     public void setUserExpandedChild(View v, boolean userExpanded) {
@@ -1850,7 +1848,7 @@
             boolean ignoreIntrinsicPadding) {
         float start = qsHeight;
         float stackHeight = getHeight() - start;
-        int minStackHeight = getMinStackHeight();
+        int minStackHeight = getLayoutMinHeight();
         if (stackHeight <= minStackHeight) {
             float overflow = minStackHeight - stackHeight;
             stackHeight = minStackHeight;
@@ -1864,11 +1862,16 @@
         setStackHeight(mLastSetStackHeight);
     }
 
-    public int getMinStackHeight() {
+    public int getLayoutMinHeight() {
         final ExpandableView firstChild = getFirstChildNotGone();
-        final int firstChildMinHeight = firstChild != null ? firstChild.getMinHeight()
+        int firstChildMinHeight = firstChild != null
+                ? firstChild.getIntrinsicHeight()
                 : mCollapsedSize;
-        return firstChildMinHeight + mBottomStackPeekSize + mCollapseSecondCardPadding;
+        if (mOwnScrollY > 0) {
+            firstChildMinHeight = Math.max(firstChildMinHeight - mOwnScrollY, mCollapsedSize);
+        }
+        return Math.min(firstChildMinHeight + mBottomStackPeekSize + mBottomStackSlowDownHeight,
+                mMaxLayoutHeight - mTopPadding);
     }
 
     public float getTopPaddingOverflow() {
@@ -1880,7 +1883,7 @@
         final int firstChildMinHeight = firstChild != null ? (int) firstChild.getMinHeight()
                 : mCollapsedSize;
         return mIntrinsicPadding + firstChildMinHeight + mBottomStackPeekSize
-                + mCollapseSecondCardPadding;
+                + mBottomStackSlowDownHeight;
     }
 
     private int clampPadding(int desiredPadding) {
@@ -1994,7 +1997,6 @@
     }
 
     private void onViewRemovedInternal(View child) {
-        mStackScrollAlgorithm.notifyChildrenChanged(this);
         if (mChangePositionInProgress) {
             // This is only a position change, don't do anything special
             return;
@@ -2175,7 +2177,6 @@
 
     private void onViewAddedInternal(View child) {
         updateHideSensitiveForChild(child);
-        mStackScrollAlgorithm.notifyChildrenChanged(this);
         ((ExpandableView) child).setOnHeightChangedListener(this);
         generateAddAnimation(child, false /* fromMoreCard */);
         updateAnimationState(child);
@@ -2203,7 +2204,7 @@
     }
 
     private void updateNotificationAnimationStates() {
-        boolean running = mAnimationsEnabled;
+        boolean running = mAnimationsEnabled || mPulsing;
         int childCount = getChildCount();
         for (int i = 0; i < childCount; i++) {
             View child = getChildAt(i);
@@ -2213,7 +2214,8 @@
     }
 
     private void updateAnimationState(View child) {
-        updateAnimationState(mAnimationsEnabled && (mIsExpanded || isPinnedHeadsUp(child)), child);
+        updateAnimationState((mAnimationsEnabled || mPulsing)
+                && (mIsExpanded || isPinnedHeadsUp(child)), child);
     }
 
 
@@ -2259,8 +2261,10 @@
         int currentIndex = indexOfChild(child);
         if (child != null && child.getParent() == this && currentIndex != newIndex) {
             mChangePositionInProgress = true;
+            ((ExpandableView)child).setChangingPosition(true);
             removeView(child);
             addView(child, newIndex);
+            ((ExpandableView)child).setChangingPosition(false);
             mChangePositionInProgress = false;
             if (mIsExpanded && mAnimationsEnabled && child.getVisibility() != View.GONE) {
                 mChildrenChangingPositions.add(child);
@@ -2643,12 +2647,8 @@
     }
 
     public int getEmptyBottomMargin() {
-        int emptyMargin = mMaxLayoutHeight - mContentHeight - mBottomStackPeekSize;
-        if (needsHeightAdaption()) {
-            emptyMargin -= mBottomStackSlowDownHeight;
-        } else {
-            emptyMargin -= mCollapseSecondCardPadding;
-        }
+        int emptyMargin = mMaxLayoutHeight - mContentHeight - mBottomStackPeekSize
+                - mBottomStackSlowDownHeight;
         return Math.max(emptyMargin, 0);
     }
 
@@ -2659,14 +2659,13 @@
 
     public void onExpansionStarted() {
         mIsExpansionChanging = true;
-        mStackScrollAlgorithm.onExpansionStarted(mCurrentStackScrollState);
     }
 
     public void onExpansionStopped() {
         mIsExpansionChanging = false;
-        mStackScrollAlgorithm.onExpansionStopped();
         if (!mIsExpanded) {
             mOwnScrollY = 0;
+            mPhoneStatusBar.resetUserExpandedStates();
 
             // lets make sure nothing is in the overlay anymore
             getOverlay().clear();
@@ -2732,7 +2731,6 @@
         if (mIsExpanded && mAnimationsEnabled) {
             mRequestViewResizeAnimationOnLayout = true;
         }
-        mStackScrollAlgorithm.onReset(view);
         updateAnimationState(view);
         updateChronometerForChild(view);
     }
@@ -3163,15 +3161,7 @@
     }
 
     public int getDismissViewHeight() {
-        int height = mDismissView.getHeight() + mPaddingBetweenElements;
-
-        // Hack: Accommodate for additional distance when we only have one notification and the
-        // dismiss all button.
-        if (getNotGoneChildCount() == 2 && getLastChildNotGone() == mDismissView
-                && getFirstChildNotGone() instanceof ActivatableNotificationView) {
-            height += mCollapseSecondCardPadding;
-        }
-        return height;
+        return mDismissView.getHeight() + mPaddingBetweenElements;
     }
 
     public int getEmptyShadeViewHeight() {
@@ -3346,6 +3336,11 @@
         return mIsExpanded;
     }
 
+    public void setPulsing(boolean pulsing) {
+        mPulsing = pulsing;
+        updateNotificationAnimationStates();
+    }
+
     /**
      * A listener that is notified when some child locations might have changed.
      */
@@ -3393,16 +3388,11 @@
     }
 
     private class NotificationSwipeHelper extends SwipeHelper {
-        private static final int MOVE_STATE_LEFT = -1;
-        private static final int MOVE_STATE_UNDEFINED = 0;
-        private static final int MOVE_STATE_RIGHT = 1;
-
         private static final long GEAR_SHOW_DELAY = 60;
-
-        private ArrayList<View> mTranslatingViews = new ArrayList<>();
         private CheckForDrag mCheckForDrag;
         private Handler mHandler;
-        private int mMoveState = MOVE_STATE_UNDEFINED;
+        private boolean mGearSnappedTo;
+        private boolean mGearSnappedOnLeft;
 
         public NotificationSwipeHelper(int swipeDirection, Callback callback, Context context) {
             super(swipeDirection, callback, context);
@@ -3415,7 +3405,12 @@
             mTranslatingParentView = currView;
 
             // Reset check for drag gesture
+            cancelCheckForDrag();
+            if (mCurrIconRow != null) {
+                mCurrIconRow.setSnapping(false);
+            }
             mCheckForDrag = null;
+            mCurrIconRow = null;
 
             // Slide back any notifications that might be showing a gear
             resetExposedGearView();
@@ -3424,80 +3419,138 @@
                 // Set the listener for the current row's gear
                 mCurrIconRow = ((ExpandableNotificationRow) currView).getSettingsRow();
                 mCurrIconRow.setGearListener(NotificationStackScrollLayout.this);
-
-                // And the translating children
-                mTranslatingViews = ((ExpandableNotificationRow) currView).getContentViews();
             }
-            mMoveState = MOVE_STATE_UNDEFINED;
         }
 
         @Override
         public void onMoveUpdate(View view, float translation, float delta) {
-            final int newMoveState = (delta < 0) ? MOVE_STATE_RIGHT : MOVE_STATE_LEFT;
-            if (mMoveState != MOVE_STATE_UNDEFINED && mMoveState != newMoveState) {
-                // Changed directions, make sure we check for drag again.
-                mCheckForDrag = null;
-            }
-            mMoveState = newMoveState;
+            if (mCurrIconRow != null) {
+                mCurrIconRow.setSnapping(false); // If we're moving, we're not snapping.
 
-            if (view instanceof ExpandableNotificationRow) {
-                ((ExpandableNotificationRow) view).setTranslationForOutline(translation);
-                if (!isPinnedHeadsUp(view)) {
-                    // Only show the gear if we're not a heads up view.
-                    checkForDrag();
-                    if (mCurrIconRow != null) {
-                        mCurrIconRow.updateSettingsIcons(translation, getSize(view));
+                // If the gear is visible and the movement is towards it it's not a location change.
+                boolean onLeft = mGearSnappedTo ? mGearSnappedOnLeft : mCurrIconRow.isIconOnLeft();
+                boolean locationChange = isTowardsGear(translation, onLeft)
+                        ? false : mCurrIconRow.isIconLocationChange(translation);
+                if (locationChange) {
+                    // Don't consider it "snapped" if location has changed.
+                    setSnappedToGear(false);
+
+                    // Changed directions, make sure we check to fade in icon again.
+                    if (!mHandler.hasCallbacks(mCheckForDrag)) {
+                        // No check scheduled, set null to schedule a new one.
+                        mCheckForDrag = null;
+                    } else {
+                        // Check scheduled, reset alpha and update location; check will fade it in
+                        mCurrIconRow.setGearAlpha(0f);
+                        mCurrIconRow.setIconLocation(translation > 0 /* onLeft */);
                     }
                 }
             }
+
+            final boolean gutsExposed = (view instanceof ExpandableNotificationRow)
+                    && ((ExpandableNotificationRow) view).areGutsExposed();
+
+            if (!isPinnedHeadsUp(view) && !gutsExposed) {
+                // Only show the gear if we're not a heads up view and guts aren't exposed.
+                checkForDrag();
+            }
         }
 
         @Override
         public void dismissChild(final View view, float velocity) {
-            cancelCheckForDrag();
             super.dismissChild(view, velocity);
+            cancelCheckForDrag();
+            setSnappedToGear(false);
         }
 
         @Override
         public void snapChild(final View animView, final float targetLeft, float velocity) {
+            super.snapChild(animView, targetLeft, velocity);
+            if (targetLeft == 0) {
+                cancelCheckForDrag();
+                setSnappedToGear(false);
+            }
+        }
+
+
+        @Override
+        public boolean handleUpEvent(MotionEvent ev, View animView, float velocity,
+                float translation) {
+            if (mCurrIconRow == null) {
+                cancelCheckForDrag();
+                return false; // Let SwipeHelper handle it.
+            }
+
+            boolean gestureTowardsGear = isTowardsGear(velocity, mCurrIconRow.isIconOnLeft());
+            boolean gestureFastEnough = Math.abs(velocity) > getEscapeVelocity();
+
+            if (mGearSnappedTo && mCurrIconRow.isVisible()) {
+                if (mGearSnappedOnLeft == mCurrIconRow.isIconOnLeft()) {
+                    boolean coveringGear =
+                            Math.abs(getTranslation(animView)) <= getSpaceForGear(animView) * 0.6f;
+                    if (gestureTowardsGear || coveringGear) {
+                        // Gesture is towards or covering the gear
+                        snapChild(animView, 0 /* leftTarget */, velocity);
+                    } else if (isDismissGesture(ev)) {
+                        // Gesture is a dismiss that's not towards the gear
+                        dismissChild(animView, swipedFastEnough() ? velocity : 0f);
+                    } else {
+                        // Didn't move enough to dismiss or cover, snap to the gear
+                        snapToGear(animView, velocity);
+                    }
+                } else if ((!gestureFastEnough && swipedEnoughToShowGear(animView))
+                        || (gestureTowardsGear && !swipedFarEnough())) {
+                    // The gear has been snapped to previously, however, the gear is now on the
+                    // other side. If gesture is towards gear and not too far snap to the gear.
+                    snapToGear(animView, velocity);
+                } else {
+                    dismissOrSnapBack(animView, velocity, ev);
+                }
+            } else if ((!gestureFastEnough && swipedEnoughToShowGear(animView))
+                    || gestureTowardsGear) {
+                // Gear has not been snapped to previously and this is gear revealing gesture
+                snapToGear(animView, velocity);
+            } else {
+                dismissOrSnapBack(animView, velocity, ev);
+            }
+            return true;
+        }
+
+        private void dismissOrSnapBack(View animView, float velocity, MotionEvent ev) {
+            if (isDismissGesture(ev)) {
+                dismissChild(animView, swipedFastEnough() ? velocity : 0f);
+            } else {
+                snapChild(animView, 0 /* leftTarget */, velocity);
+            }
+        }
+
+        private void snapToGear(View animView, float velocity) {
+            final float snapBackThreshold = getSpaceForGear(animView);
+            final float target = mCurrIconRow.isIconOnLeft() ? snapBackThreshold
+                    : -snapBackThreshold;
+            mGearExposedView = mTranslatingParentView;
+            if (mGearDisplayedListener != null
+                    && (animView instanceof ExpandableNotificationRow)) {
+                mGearDisplayedListener.onGearDisplayed((ExpandableNotificationRow) animView);
+            }
+            if (mCurrIconRow != null) {
+                mCurrIconRow.setSnapping(true);
+                setSnappedToGear(true);
+            }
+            super.snapChild(animView, target, velocity);
+        }
+
+        private boolean swipedEnoughToShowGear(View animView) {
             final float snapBackThreshold = getSpaceForGear(animView);
             final float translation = getTranslation(animView);
             final boolean fromLeft = translation > 0;
             final float absTrans = Math.abs(translation);
             final float notiThreshold = getSize(mTranslatingParentView) * 0.4f;
 
-            boolean pastGear = (fromLeft && translation >= snapBackThreshold * 0.4f
-                    && translation <= notiThreshold) ||
-                    (!fromLeft && absTrans >= snapBackThreshold * 0.4f
-                            && absTrans <= notiThreshold);
-
-            if (pastGear && !isPinnedHeadsUp(animView)) {
-                // bouncity
-                final float target = fromLeft ? snapBackThreshold : -snapBackThreshold;
-                mGearExposedView = mTranslatingParentView;
-                if (mGearDisplayedListener != null
-                        && (animView instanceof ExpandableNotificationRow)) {
-                    mGearDisplayedListener.onGearDisplayed((ExpandableNotificationRow) animView);
-                }
-                super.snapChild(animView, target, velocity);
-            } else {
-                super.snapChild(animView, 0, velocity);
-            }
-        }
-
-        @Override
-        public void onTranslationUpdate(View animView, float value, boolean canBeDismissed) {
-            if (mDismissAllInProgress) {
-                // When dismissing all, we translate the entire view instead.
-                super.onTranslationUpdate(animView, value, canBeDismissed);
-                return;
-            }
-            if (animView instanceof ExpandableNotificationRow) {
-                ((ExpandableNotificationRow) animView).setTranslationForOutline(value);
-            }
-            if (mCurrIconRow != null) {
-                mCurrIconRow.updateSettingsIcons(value, getSize(animView));
-            }
+            // If the notification can't be dismissed then how far it can move is
+            // restricted -- reduce the distance it needs to move in this case.
+            final float multiplier = canChildBeDismissed(animView) ? 0.4f : 0.2f;
+            return absTrans >= snapBackThreshold * 0.4f && absTrans <= notiThreshold;
         }
 
         @Override
@@ -3506,18 +3559,11 @@
             if (mDismissAllInProgress) {
                 // When dismissing all, we translate the entire view instead.
                 return super.getViewTranslationAnimator(v, target, listener);
+            } else if (v instanceof ExpandableNotificationRow) {
+                return ((ExpandableNotificationRow) v).getTranslateViewAnimator(target, listener);
+            } else {
+                return super.getViewTranslationAnimator(v, target, listener);
             }
-            ArrayList<Animator> animators = new ArrayList<Animator>();
-            for (int i = 0; i < mTranslatingViews.size(); i++) {
-                ObjectAnimator anim = createTranslationAnimation(mTranslatingViews.get(i), target);
-                animators.add(anim);
-                if (i == 0 && listener != null) {
-                    anim.addUpdateListener(listener);
-                }
-            }
-            AnimatorSet set = new AnimatorSet();
-            set.playTogether(animators);
-            return set;
         }
 
         @Override
@@ -3525,13 +3571,8 @@
             if (mDismissAllInProgress) {
                 // When dismissing all, we translate the entire view instead.
                 super.setTranslation(v, translate);
-                return;
-            }
-            // Translate the group of views
-            for (int i = 0; i < mTranslatingViews.size(); i++) {
-                if (mTranslatingViews.get(i) != null) {
-                    super.setTranslation(mTranslatingViews.get(i), translate);
-                }
+            } else {
+                ((ExpandableView) v).setTranslation(translate);
             }
         }
 
@@ -3540,14 +3581,29 @@
             if (mDismissAllInProgress) {
                 // When dismissing all, we translate the entire view instead.
                 return super.getTranslation(v);
+            } else {
+                return ((ExpandableView) v).getTranslation();
             }
-            // All of the views in the list should have same translation, just use first one.
-            if (mTranslatingViews.size() > 0) {
-                return super.getTranslation(mTranslatingViews.get(0));
-            }
-            return 0;
         }
 
+        /**
+         * Returns whether the gesture is towards the gear location or not.
+         */
+        private boolean isTowardsGear(float velocity, boolean onLeft) {
+            if (mCurrIconRow == null) {
+                return false;
+            }
+            return mCurrIconRow.isVisible()
+                    && ((onLeft && velocity <= 0) || (!onLeft && velocity >= 0));
+        }
+
+        /**
+         * Indicates the the gear has been snapped to.
+         */
+        private void setSnappedToGear(boolean snapped) {
+            mGearSnappedOnLeft = (mCurrIconRow != null) ? mCurrIconRow.isIconOnLeft() : false;
+            mGearSnappedTo = snapped && mCurrIconRow != null;
+        }
 
         /**
          * Returns the horizontal space in pixels required to display the gear behind a
@@ -3561,7 +3617,7 @@
         }
 
         private void checkForDrag() {
-            if (mCheckForDrag == null) {
+            if (mCheckForDrag == null || !mHandler.hasCallbacks(mCheckForDrag)) {
                 mCheckForDrag = new CheckForDrag();
                 mHandler.postDelayed(mCheckForDrag, GEAR_SHOW_DELAY);
             }
@@ -3572,7 +3628,6 @@
                 mCurrIconRow.cancelFadeAnimator();
             }
             mHandler.removeCallbacks(mCheckForDrag);
-            mCheckForDrag = null;
         }
 
         private final class CheckForDrag implements Runnable {
@@ -3582,14 +3637,13 @@
                 final float absTransX = Math.abs(translation);
                 final float bounceBackToGearWidth = getSpaceForGear(mTranslatingParentView);
                 final float notiThreshold = getSize(mTranslatingParentView) * 0.4f;
-                if (mCurrIconRow != null && absTransX >= bounceBackToGearWidth * 0.4
+                if ((mCurrIconRow != null && (!mCurrIconRow.isVisible()
+                        || mCurrIconRow.isIconLocationChange(translation)))
+                        && absTransX >= bounceBackToGearWidth * 0.4
                         && absTransX < notiThreshold) {
-                    // Show icon
+                    // Fade in the gear
                     mCurrIconRow.fadeInSettings(translation > 0 /* fromLeft */, translation,
                             notiThreshold);
-                } else {
-                    // Allow more to be posted if this wasn't a drag.
-                    mCheckForDrag = null;
                 }
             }
         }
@@ -3602,27 +3656,12 @@
 
             final View prevGearExposedView = mGearExposedView;
             mGearExposedView = null;
-
-            AnimatorListenerAdapter listener = new AnimatorListenerAdapter() {
-                public void onAnimationEnd(Animator animator) {
-                    if (prevGearExposedView instanceof ExpandableNotificationRow) {
-                        ((ExpandableNotificationRow) prevGearExposedView).getSettingsRow()
-                                .resetState();
-                    }
-                }
-            };
-            AnimatorUpdateListener updateListener = new AnimatorUpdateListener() {
-                @Override
-                public void onAnimationUpdate(ValueAnimator animation) {
-                    if (prevGearExposedView instanceof ExpandableNotificationRow) {
-                        ((ExpandableNotificationRow) prevGearExposedView)
-                                .setTranslationForOutline((float) animation.getAnimatedValue());
-                    }
-                }
-            };
-            Animator set = getViewTranslationAnimator(prevGearExposedView, 0, updateListener);
-            set.addListener(listener);
-            set.start();
+            mGearSnappedTo = false;
+            Animator anim = getViewTranslationAnimator(prevGearExposedView,
+                    0 /* leftTarget */, null /* updateListener */);
+            if (anim != null) {
+                anim.start();
+            }
         }
     }
 
@@ -3693,7 +3732,6 @@
 
                 // ANIMATION_TYPE_DIMMED
                 new AnimationFilter()
-                        .animateY()
                         .animateDimmed(),
 
                 // ANIMATION_TYPE_CHANGE_POSITION
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
index eea923f..4c94fe9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
@@ -52,13 +52,8 @@
     private StackIndentationFunctor mBottomStackIndentationFunctor;
 
     private StackScrollAlgorithmState mTempAlgorithmState = new StackScrollAlgorithmState();
-    private boolean mIsExpansionChanging;
-    private int mFirstChildMaxHeight;
     private boolean mIsExpanded;
-    private ExpandableView mFirstChildWhileExpanding;
-    private boolean mExpandedOnStart;
     private int mBottomStackSlowDownLength;
-    private int mCollapseSecondCardPadding;
 
     public StackScrollAlgorithm(Context context) {
         initView(context);
@@ -86,8 +81,6 @@
         mZBasicHeight = (MAX_ITEMS_IN_BOTTOM_STACK + 1) * mZDistanceBetweenElements;
         mBottomStackSlowDownLength = context.getResources()
                 .getDimensionPixelSize(R.dimen.bottom_stack_slow_down_length);
-        mCollapseSecondCardPadding = context.getResources().getDimensionPixelSize(
-                R.dimen.notification_collapse_second_card_padding);
         mBottomStackIndentationFunctor = new PiecewiseLinearIndentationFunctor(
                 MAX_ITEMS_IN_BOTTOM_STACK,
                 mBottomStackPeekSize,
@@ -508,7 +501,7 @@
             int childHeight, int minHeight, AmbientState ambientState) {
 
         int bottomStackStart = ambientState.getInnerHeight()
-                - mBottomStackPeekSize - mCollapseSecondCardPadding;
+                - mBottomStackPeekSize - mBottomStackSlowDownLength;
         int childStart = bottomStackStart - childHeight;
         if (childStart < childViewState.yTranslation) {
             float newHeight = bottomStackStart - childViewState.yTranslation;
@@ -595,12 +588,9 @@
 
             // The starting position of the bottom stack peek
             int bottomPeekStart = ambientState.getInnerHeight() - mBottomStackPeekSize -
-                    mCollapseSecondCardPadding + ambientState.getScrollY();
+                    mBottomStackSlowDownLength + ambientState.getScrollY();
             // Collapse and expand the first child while the shade is being expanded
-            float maxHeight = mIsExpansionChanging && child == mFirstChildWhileExpanding
-                    ? mFirstChildMaxHeight
-                    : childHeight;
-            childViewState.height = (int) Math.max(Math.min(bottomPeekStart, maxHeight),
+        childViewState.height = (int) Math.max(Math.min(bottomPeekStart, (float) childHeight),
                     child.getMinHeight());
     }
 
@@ -656,55 +646,6 @@
         }
     }
 
-    public void onExpansionStarted(StackScrollState currentState) {
-        mIsExpansionChanging = true;
-        mExpandedOnStart = mIsExpanded;
-        ViewGroup hostView = currentState.getHostView();
-        updateFirstChildHeightWhileExpanding(hostView);
-    }
-
-    private void updateFirstChildHeightWhileExpanding(ViewGroup hostView) {
-        mFirstChildWhileExpanding = (ExpandableView) findFirstVisibleChild(hostView);
-        if (mFirstChildWhileExpanding != null) {
-            if (mExpandedOnStart) {
-
-                // We are collapsing the shade, so the first child can get as most as high as the
-                // current height or the end value of the animation.
-                mFirstChildMaxHeight = StackStateAnimator.getFinalActualHeight(
-                        mFirstChildWhileExpanding);
-            } else {
-                updateFirstChildMaxSizeToMaxHeight();
-            }
-        } else {
-            mFirstChildMaxHeight = 0;
-        }
-    }
-
-    private void updateFirstChildMaxSizeToMaxHeight() {
-        // We are expanding the shade, expand it to its full height.
-        if (!isMaxSizeInitialized(mFirstChildWhileExpanding)) {
-
-            // This child was not layouted yet, wait for a layout pass
-            mFirstChildWhileExpanding
-                    .addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
-                        @Override
-                        public void onLayoutChange(View v, int left, int top, int right,
-                                int bottom, int oldLeft, int oldTop, int oldRight,
-                                int oldBottom) {
-                            if (mFirstChildWhileExpanding != null) {
-                                mFirstChildMaxHeight = getMaxAllowedChildHeight(
-                                        mFirstChildWhileExpanding);
-                            } else {
-                                mFirstChildMaxHeight = 0;
-                            }
-                            v.removeOnLayoutChangeListener(this);
-                        }
-                    });
-        } else {
-            mFirstChildMaxHeight = getMaxAllowedChildHeight(mFirstChildWhileExpanding);
-        }
-    }
-
     private boolean isMaxSizeInitialized(ExpandableView child) {
         if (child instanceof ExpandableNotificationRow) {
             ExpandableNotificationRow row = (ExpandableNotificationRow) child;
@@ -724,32 +665,10 @@
         return null;
     }
 
-    public void onExpansionStopped() {
-        mIsExpansionChanging = false;
-        mFirstChildWhileExpanding = null;
-    }
-
     public void setIsExpanded(boolean isExpanded) {
         this.mIsExpanded = isExpanded;
     }
 
-    public void notifyChildrenChanged(final NotificationStackScrollLayout hostView) {
-        if (mIsExpansionChanging) {
-            hostView.post(new Runnable() {
-                @Override
-                public void run() {
-                    updateFirstChildHeightWhileExpanding(hostView);
-                }
-            });
-        }
-    }
-
-    public void onReset(ExpandableView view) {
-        if (view.equals(mFirstChildWhileExpanding)) {
-            updateFirstChildMaxSizeToMaxHeight();
-        }
-    }
-
     class StackScrollAlgorithmState {
 
         /**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java
index 0ed6ef8..2524e1a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java
@@ -125,7 +125,7 @@
     }
 
     @Override
-    protected boolean isPanelFullyCollapsed() {
+    public boolean isPanelFullyCollapsed() {
         return false;
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/NightModeTile.java b/packages/SystemUI/src/com/android/systemui/tuner/NightModeTile.java
index 61135bd..26e1d46 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/NightModeTile.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/NightModeTile.java
@@ -20,6 +20,8 @@
 import android.provider.Settings;
 
 import com.android.internal.logging.MetricsProto.MetricsEvent;
+import com.android.systemui.Prefs;
+import com.android.systemui.Prefs.Key;
 import com.android.systemui.R;
 import com.android.systemui.qs.QSTile;
 import com.android.systemui.statusbar.policy.NightModeController;
@@ -46,6 +48,12 @@
     }
 
     @Override
+    public boolean isAvailable() {
+        return Prefs.getBoolean(mContext, Key.QS_NIGHT_ADDED, false)
+                && TunerService.isTunerEnabled(mContext);
+    }
+
+    @Override
     public void setListening(boolean listening) {
         if (listening) {
             mNightModeController.addListener(this);
diff --git a/packages/SystemUI/src/com/android/systemui/tv/pip/PipManager.java b/packages/SystemUI/src/com/android/systemui/tv/pip/PipManager.java
index 0925638..ff7ea27 100644
--- a/packages/SystemUI/src/com/android/systemui/tv/pip/PipManager.java
+++ b/packages/SystemUI/src/com/android/systemui/tv/pip/PipManager.java
@@ -23,14 +23,18 @@
 import android.app.IActivityManager;
 import android.app.ITaskStackListener;
 import android.content.BroadcastReceiver;
+import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.content.res.Resources;
 import android.graphics.Rect;
+import android.media.session.MediaController;
+import android.media.session.MediaSessionManager;
 import android.os.Debug;
 import android.os.Handler;
 import android.os.RemoteException;
+import android.os.SystemProperties;
 import android.util.Log;
 
 import com.android.systemui.Prefs;
@@ -48,7 +52,8 @@
 public class PipManager {
     private static final String TAG = "PipManager";
     private static final boolean DEBUG = false;
-    private static final boolean DEBUG_FORCE_ONBOARDING = false;
+    private static final boolean DEBUG_FORCE_ONBOARDING =
+            SystemProperties.getBoolean("debug.tv.pip_force_onboarding", false);
 
     private static PipManager sPipManager;
 
@@ -63,12 +68,16 @@
 
     public static final int SUSPEND_PIP_RESIZE_REASON_WAITING_FOR_MENU_ACTIVITY_FINISH = 0x1;
     public static final int SUSPEND_PIP_RESIZE_REASON_WAITING_FOR_OVERLAY_ACTIVITY_FINISH = 0x2;
+
+    private static final int CLOSE_PIP_WHEN_MEDIA_SESSION_GONE_TIMEOUT_MS = 3000;
+
     private int mSuspendPipResizingReason;
 
     private static final float SCALE_FACTOR = 1.1f;
 
     private Context mContext;
     private IActivityManager mActivityManager;
+    private MediaSessionManager mMediaSessionManager;
     private int mState = STATE_NO_PIP;
     private final Handler mHandler = new Handler();
     private List<Listener> mListeners = new ArrayList<>();
@@ -79,6 +88,8 @@
     private Rect mRecentsFocusedPipBounds;
     private boolean mInitialized;
     private int mPipTaskId = TASK_ID_NO_PIP;
+    private ComponentName mPipComponentName;
+    private MediaController mPipMediaController;
     private boolean mOnboardingShown;
 
     private boolean mIsRecentsShown;
@@ -100,10 +111,15 @@
             }
             if (DEBUG) Log.d(TAG, "PINNED_STACK:" + stackInfo);
             mPipTaskId = stackInfo.taskIds[stackInfo.taskIds.length - 1];
+            mPipComponentName = ComponentName.unflattenFromString(
+                    stackInfo.taskNames[stackInfo.taskNames.length - 1]);
             // Set state to overlay so we show it when the pinned stack animation ends.
             mState = STATE_PIP_OVERLAY;
             mCurrentPipBounds = mPipBounds;
             launchPipOnboardingActivityIfNeeded();
+            mMediaSessionManager.addOnActiveSessionsChangedListener(
+                    mActiveMediaSessionListener, null);
+            updateMediaController(mMediaSessionManager.getActiveSessions(null));
         }
     };
     private final Runnable mOnTaskStackChanged = new Runnable() {
@@ -159,6 +175,12 @@
             resizePinnedStack(mState);
         }
     };
+    private final Runnable mClosePipRunnable = new Runnable() {
+        @Override
+        public void run() {
+            closePip();
+        }
+    };
 
     private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
         @Override
@@ -176,6 +198,13 @@
 
         }
     };
+    private final MediaSessionManager.OnActiveSessionsChangedListener mActiveMediaSessionListener =
+            new MediaSessionManager.OnActiveSessionsChangedListener() {
+                @Override
+                public void onActiveSessionsChanged(List<MediaController> controllers) {
+                    updateMediaController(controllers);
+                }
+            };
 
     private PipManager() { }
 
@@ -215,6 +244,9 @@
         mContext.registerReceiver(mBroadcastReceiver, intentFilter);
         mOnboardingShown = Prefs.getBoolean(
                 mContext, TV_PICTURE_IN_PICTURE_ONBOARDING_SHOWN, false);
+
+        mMediaSessionManager =
+                (MediaSessionManager) mContext.getSystemService(Context.MEDIA_SESSION_SERVICE);
     }
 
     /**
@@ -248,6 +280,8 @@
     private void closePipInternal(boolean removePipStack) {
         mState = STATE_NO_PIP;
         mPipTaskId = TASK_ID_NO_PIP;
+        mPipMediaController = null;
+        mMediaSessionManager.removeOnActiveSessionsChangedListener(mActiveMediaSessionListener);
         if (removePipStack) {
             try {
                 mActivityManager.removeStack(PINNED_STACK_ID);
@@ -258,6 +292,7 @@
         for (int i = mListeners.size() - 1; i >= 0; --i) {
             mListeners.get(i).onPipActivityClosed();
         }
+        mHandler.removeCallbacks(mClosePipRunnable);
     }
 
     /**
@@ -502,6 +537,40 @@
         }
     }
 
+    private void updateMediaController(List<MediaController> controllers) {
+        MediaController mediaController = null;
+        if (controllers != null && mState != STATE_NO_PIP && mPipComponentName != null) {
+            for (int i = controllers.size() - 1; i >= 0; i--) {
+                MediaController controller = controllers.get(i);
+                // We assumes that an app with PIPable activity
+                // keeps the single instance of media controller especially when PIP is on.
+                if (controller.getPackageName().equals(mPipComponentName.getPackageName())) {
+                    mediaController = controller;
+                    break;
+                }
+            }
+        }
+        if (mPipMediaController != mediaController) {
+            mPipMediaController = mediaController;
+            for (int i = mListeners.size() - 1; i >= 0; i--) {
+                mListeners.get(i).onMediaControllerChanged();
+            }
+            if (mPipMediaController == null) {
+                mHandler.postDelayed(mClosePipRunnable,
+                        CLOSE_PIP_WHEN_MEDIA_SESSION_GONE_TIMEOUT_MS);
+            } else {
+                mHandler.removeCallbacks(mClosePipRunnable);
+            }
+        }
+    }
+
+    /**
+     * Gets the {@link android.media.session.MediaController} for the PIPed activity.
+     */
+    MediaController getMediaController() {
+        return mPipMediaController;
+    }
+
     private class TaskStackListener extends ITaskStackListener.Stub {
         @Override
         public void onTaskStackChanged() throws RemoteException {
@@ -542,6 +611,8 @@
         void onMoveToFullscreen();
         /** Invoked when we are above to start resizing the Pip. */
         void onPipResizeAboutToStart();
+        /** Invoked when the MediaController on PIPed activity is changed. */
+        void onMediaControllerChanged();
     }
 
     /**
diff --git a/packages/SystemUI/src/com/android/systemui/tv/pip/PipMenuActivity.java b/packages/SystemUI/src/com/android/systemui/tv/pip/PipMenuActivity.java
index 4171dbc..285dfd1 100644
--- a/packages/SystemUI/src/com/android/systemui/tv/pip/PipMenuActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/tv/pip/PipMenuActivity.java
@@ -18,39 +18,59 @@
 
 import android.app.Activity;
 import android.media.session.MediaController;
+import android.media.session.PlaybackState;
 import android.os.Bundle;
 import android.view.View;
+import android.widget.ImageView;
+import android.widget.TextView;
 
 import com.android.systemui.R;
+import com.android.systemui.SystemUI;
+import com.android.systemui.SystemUIApplication;
+import com.android.systemui.recents.Recents;
+
+import static android.content.pm.PackageManager.FEATURE_LEANBACK;
+import static android.content.pm.PackageManager.FEATURE_PICTURE_IN_PICTURE;
+import static android.media.session.PlaybackState.ACTION_PAUSE;
+import static android.media.session.PlaybackState.ACTION_PLAY;
 
 /**
  * Activity to show the PIP menu to control PIP.
  */
 public class PipMenuActivity extends Activity implements PipManager.Listener {
     private static final String TAG = "PipMenuActivity";
-    private static final boolean DEBUG = false;
 
     private final PipManager mPipManager = PipManager.getInstance();
     private MediaController mMediaController;
 
     private View mFullButtonView;
     private View mFullDescriptionView;
-    private View mPlayPauseButtonView;
-    private View mPlayPauseDescriptionView;
+    private View mPlayPauseView;
+    private ImageView mPlayPauseButtonImageView;
+    private TextView mPlayPauseDescriptionTextView;
     private View mCloseButtonView;
     private View mCloseDescriptionView;
+    private boolean mPipMovedToFullscreen;
+
+    private MediaController.Callback mMediaControllerCallback = new MediaController.Callback() {
+        @Override
+        public void onPlaybackStateChanged(PlaybackState state) {
+            updatePlayPauseView(state);
+        }
+    };
 
     @Override
     protected void onCreate(Bundle bundle) {
         super.onCreate(bundle);
         setContentView(R.layout.tv_pip_menu);
         mPipManager.addListener(this);
-        mFullButtonView = findViewById(R.id.full);
+        mFullButtonView = findViewById(R.id.full_button);
         mFullDescriptionView = findViewById(R.id.full_desc);
         mFullButtonView.setOnClickListener(new View.OnClickListener() {
             @Override
             public void onClick(View v) {
                 mPipManager.movePipToFullscreen();
+                mPipMovedToFullscreen = true;
                 finish();
             }
         });
@@ -61,22 +81,33 @@
             }
         });
 
-        mPlayPauseButtonView = findViewById(R.id.play_pause);
-        mPlayPauseDescriptionView = findViewById(R.id.play_pause_desc);
-        mPlayPauseButtonView.setOnClickListener(new View.OnClickListener() {
+        mPlayPauseView = findViewById(R.id.play_pause);
+        mPlayPauseButtonImageView = (ImageView) findViewById(R.id.play_pause_button);
+        mPlayPauseDescriptionTextView = (TextView) findViewById(R.id.play_pause_desc);
+        mPlayPauseButtonImageView.setOnClickListener(new View.OnClickListener() {
             @Override
             public void onClick(View v) {
-                // TODO: Implement play/pause.
+                if (mMediaController == null || mMediaController.getPlaybackState() == null) {
+                    return;
+                }
+                long actions = mMediaController.getPlaybackState().getActions();
+                int state = mMediaController.getPlaybackState().getState();
+                if (((actions & ACTION_PLAY) != 0) && !isPlaying(state)) {
+                    mMediaController.getTransportControls().play();
+                } else if ((actions & ACTION_PAUSE) != 0 && isPlaying(state)) {
+                    mMediaController.getTransportControls().pause();
+                }
+                // View will be updated later in {@link mMediaControllerCallback}
             }
         });
-        mPlayPauseButtonView.setOnFocusChangeListener(new View.OnFocusChangeListener() {
+        mPlayPauseButtonImageView.setOnFocusChangeListener(new View.OnFocusChangeListener() {
             @Override
             public void onFocusChange(View v, boolean hasFocus) {
-                mPlayPauseDescriptionView.setVisibility(hasFocus ? View.VISIBLE : View.INVISIBLE);
+                mPlayPauseDescriptionTextView.setVisibility(hasFocus ? View.VISIBLE : View.INVISIBLE);
             }
         });
 
-        mCloseButtonView = findViewById(R.id.close);
+        mCloseButtonView = findViewById(R.id.close_button);
         mCloseDescriptionView = findViewById(R.id.close_desc);
         mCloseButtonView.setOnClickListener(new View.OnClickListener() {
             @Override
@@ -91,11 +122,71 @@
                 mCloseDescriptionView.setVisibility(hasFocus ? View.VISIBLE : View.INVISIBLE);
             }
         });
+        updateMediaController();
+    }
+
+    private void updateMediaController() {
+        MediaController newController = mPipManager.getMediaController();
+        if (mMediaController == newController) {
+            return;
+        }
+        if (mMediaController != null) {
+            mMediaController.unregisterCallback(mMediaControllerCallback);
+        }
+        mMediaController = newController;
+        if (mMediaController != null) {
+            mMediaController.registerCallback(mMediaControllerCallback);
+            updatePlayPauseView(mMediaController.getPlaybackState());
+        } else {
+            updatePlayPauseView(null);
+        }
+    }
+
+    private void updatePlayPauseView(PlaybackState playbackState) {
+        if (playbackState != null
+                && (playbackState.getActions() & (ACTION_PLAY | ACTION_PAUSE)) != 0) {
+            mPlayPauseView.setVisibility(View.VISIBLE);
+            if (isPlaying(playbackState.getState())) {
+                mPlayPauseButtonImageView.setImageResource(R.drawable.tv_pip_pause_button);
+                mPlayPauseDescriptionTextView.setText(R.string.pip_pause);
+            } else {
+                mPlayPauseButtonImageView.setImageResource(R.drawable.tv_pip_play_button);
+                mPlayPauseDescriptionTextView.setText(R.string.pip_play);
+            }
+        } else {
+            mPlayPauseView.setVisibility(View.GONE);
+        }
+    }
+
+    private boolean isPlaying(int state) {
+        return state == PlaybackState.STATE_BUFFERING
+                || state == PlaybackState.STATE_CONNECTING
+                || state == PlaybackState.STATE_PLAYING
+                || state == PlaybackState.STATE_FAST_FORWARDING
+                || state == PlaybackState.STATE_REWINDING
+                || state == PlaybackState.STATE_SKIPPING_TO_PREVIOUS
+                || state == PlaybackState.STATE_SKIPPING_TO_NEXT;
+    }
+
+    private void restorePipAndFinish() {
+        if (!mPipMovedToFullscreen) {
+            mPipManager.resizePinnedStack(PipManager.STATE_PIP_OVERLAY);
+        }
+        finish();
+    }
+
+    @Override
+    public void onPause() {
+        super.onPause();
+        restorePipAndFinish();
     }
 
     @Override
     protected void onDestroy() {
         super.onDestroy();
+        if (mMediaController != null) {
+            mMediaController.unregisterCallback(mMediaControllerCallback);
+        }
         mPipManager.removeListener(this);
         mPipManager.resumePipResizing(
                 PipManager.SUSPEND_PIP_RESIZE_REASON_WAITING_FOR_MENU_ACTIVITY_FINISH);
@@ -103,8 +194,7 @@
 
     @Override
     public void onBackPressed() {
-        mPipManager.resizePinnedStack(PipManager.STATE_PIP_OVERLAY);
-        finish();
+        restorePipAndFinish();
     }
 
     @Override
@@ -121,9 +211,28 @@
     }
 
     @Override
+    public void onMediaControllerChanged() {
+        updateMediaController();
+    }
+
+    @Override
     public void onPipResizeAboutToStart() {
         finish();
         mPipManager.suspendPipResizing(
                 PipManager.SUSPEND_PIP_RESIZE_REASON_WAITING_FOR_MENU_ACTIVITY_FINISH);
     }
+
+    @Override
+    public void finish() {
+        super.finish();
+        if (mPipManager.isRecentsShown() && !mPipMovedToFullscreen) {
+            SystemUI[] services = ((SystemUIApplication) getApplication()).getServices();
+            for (int i = services.length - 1; i >= 0; i--) {
+                if (services[i] instanceof Recents) {
+                    ((Recents) services[i]).showRecents(false, null);
+                    break;
+                }
+            }
+        }
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/tv/pip/PipOnboardingActivity.java b/packages/SystemUI/src/com/android/systemui/tv/pip/PipOnboardingActivity.java
index e5c07d2..ad45625b 100644
--- a/packages/SystemUI/src/com/android/systemui/tv/pip/PipOnboardingActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/tv/pip/PipOnboardingActivity.java
@@ -82,6 +82,8 @@
     }
 
     @Override
-    public void onPipResizeAboutToStart() {
-    }
+    public void onPipResizeAboutToStart() { }
+
+    @Override
+    public void onMediaControllerChanged() { }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/tv/pip/PipOverlayActivity.java b/packages/SystemUI/src/com/android/systemui/tv/pip/PipOverlayActivity.java
index cfeab6d..95d655c 100644
--- a/packages/SystemUI/src/com/android/systemui/tv/pip/PipOverlayActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/tv/pip/PipOverlayActivity.java
@@ -103,4 +103,8 @@
         mPipManager.suspendPipResizing(
                 PipManager.SUSPEND_PIP_RESIZE_REASON_WAITING_FOR_OVERLAY_ACTIVITY_FINISH);
     }
+
+    @Override
+    public void onMediaControllerChanged() {
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/volume/ZenFooter.java b/packages/SystemUI/src/com/android/systemui/volume/ZenFooter.java
index c06b63b..005767f 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/ZenFooter.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/ZenFooter.java
@@ -131,7 +131,7 @@
 
         final boolean isForever = mConfig != null && mConfig.manualRule != null
                 && mConfig.manualRule.conditionId == null;
-        final String line2 =
+        final CharSequence line2 =
                 isForever ? mContext.getString(com.android.internal.R.string.zen_mode_forever_dnd)
                 : ZenModeConfig.getConditionSummary(mContext, mConfig, mController.getCurrentUser(),
                         true /*shortVersion*/);
diff --git a/packages/SystemUI/tests/AndroidManifest.xml b/packages/SystemUI/tests/AndroidManifest.xml
index 2825601..5389c804 100644
--- a/packages/SystemUI/tests/AndroidManifest.xml
+++ b/packages/SystemUI/tests/AndroidManifest.xml
@@ -20,6 +20,8 @@
     <uses-permission android:name="android.permission.INJECT_EVENTS" />
     <uses-permission android:name="android.permission.READ_PHONE_STATE" />
     <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS" />
+    <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL" />
+    <uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS" />
     <uses-permission android:name="android.permission.MANAGE_USERS" />
 
     <application>
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/TouchAnimatorTests.java b/packages/SystemUI/tests/src/com/android/systemui/qs/TouchAnimatorTests.java
new file mode 100644
index 0000000..1d81fd4
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/TouchAnimatorTests.java
@@ -0,0 +1,188 @@
+/*
+ * 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;
+
+import android.view.View;
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.qs.TouchAnimator.Listener;
+import org.mockito.Mockito;
+
+public class TouchAnimatorTests extends SysuiTestCase {
+
+    private Listener mTouchListener;
+    private View mTestView;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        mTestView = new View(getContext());
+        mTouchListener = Mockito.mock(Listener.class);
+    }
+
+    public void testSetValueFloat() {
+        TouchAnimator animator = new TouchAnimator.Builder()
+                .addFloat(mTestView, "x", 0, 50)
+                .build();
+
+        animator.setPosition(0);
+        assertEquals(0f, mTestView.getX());
+
+        animator.setPosition(.5f);
+        assertEquals(25f, mTestView.getX());
+
+        animator.setPosition(1);
+        assertEquals(50f, mTestView.getX());
+    }
+
+    public void testSetValueInt() {
+        TouchAnimator animator = new TouchAnimator.Builder()
+                .addInt(mTestView, "top", 0, 50)
+                .build();
+
+        animator.setPosition(0);
+        assertEquals(0, mTestView.getTop());
+
+        animator.setPosition(.5f);
+        assertEquals(25, mTestView.getTop());
+
+        animator.setPosition(1);
+        assertEquals(50, mTestView.getTop());
+    }
+
+    public void testStartDelay() {
+        TouchAnimator animator = new TouchAnimator.Builder()
+                .addFloat(mTestView, "x", 0, 50)
+                .setStartDelay(.5f)
+                .build();
+
+        animator.setPosition(0);
+        assertEquals(0f, mTestView.getX());
+
+        animator.setPosition(.5f);
+        assertEquals(0f, mTestView.getX());
+
+        animator.setPosition(.75f);
+        assertEquals(25f, mTestView.getX());
+
+        animator.setPosition(1);
+        assertEquals(50f, mTestView.getX());
+    }
+
+    public void testEndDelay() {
+        TouchAnimator animator = new TouchAnimator.Builder()
+                .addFloat(mTestView, "x", 0, 50)
+                .setEndDelay(.5f)
+                .build();
+
+        animator.setPosition(0);
+        assertEquals(0f, mTestView.getX());
+
+        animator.setPosition(.25f);
+        assertEquals(25f, mTestView.getX());
+
+        animator.setPosition(.5f);
+        assertEquals(50f, mTestView.getX());
+
+        animator.setPosition(1);
+        assertEquals(50f, mTestView.getX());
+    }
+
+    public void testOnAnimationAtStartCallback() {
+        TouchAnimator animator = new TouchAnimator.Builder()
+                .setListener(mTouchListener)
+                .build();
+
+        // Called on init.
+        animator.setPosition(0);
+        verifyOnAnimationAtStart(1);
+
+        // Not called from same state.
+        animator.setPosition(0);
+        verifyOnAnimationAtStart(1);
+
+        // Called after starting and moving back to start.
+        animator.setPosition(.5f);
+        animator.setPosition(0);
+        verifyOnAnimationAtStart(2);
+
+        // Called when move from end to end.
+        animator.setPosition(1);
+        animator.setPosition(0);
+        verifyOnAnimationAtStart(3);
+    }
+
+    public void testOnAnimationAtEndCallback() {
+        TouchAnimator animator = new TouchAnimator.Builder()
+                .setListener(mTouchListener)
+                .build();
+
+        // Called on init.
+        animator.setPosition(1);
+        verifyOnAnimationAtEnd(1);
+
+        // Not called from same state.
+        animator.setPosition(1);
+        verifyOnAnimationAtEnd(1);
+
+        // Called after starting and moving back to end.
+        animator.setPosition(.5f);
+        animator.setPosition(1);
+        verifyOnAnimationAtEnd(2);
+
+        // Called when move from end to end.
+        animator.setPosition(0);
+        animator.setPosition(1);
+        verifyOnAnimationAtEnd(3);
+    }
+
+    public void testOnAnimationStartedCallback() {
+        TouchAnimator animator = new TouchAnimator.Builder()
+                .setListener(mTouchListener)
+                .build();
+
+        // Called on init.
+        animator.setPosition(.5f);
+        verifyOnAnimationStarted(1);
+
+        // Not called from same state.
+        animator.setPosition(.6f);
+        verifyOnAnimationStarted(1);
+
+        // Called after going to end then moving again.
+        animator.setPosition(1);
+        animator.setPosition(.5f);
+        verifyOnAnimationStarted(2);
+
+        // Called after moving to start then moving again.
+        animator.setPosition(0);
+        animator.setPosition(.5f);
+        verifyOnAnimationStarted(3);
+    }
+
+    // TODO: Add test for interpolator.
+
+    private void verifyOnAnimationAtStart(int times) {
+        Mockito.verify(mTouchListener, Mockito.times(times)).onAnimationAtStart();
+    }
+
+    private void verifyOnAnimationAtEnd(int times) {
+        Mockito.verify(mTouchListener, Mockito.times(times)).onAnimationAtEnd();
+    }
+
+    private void verifyOnAnimationStarted(int times) {
+        Mockito.verify(mTouchListener, Mockito.times(times)).onAnimationStarted();
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServicesTests.java b/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServicesTests.java
index c4ca039..01514646b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServicesTests.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServicesTests.java
@@ -19,6 +19,9 @@
 import android.os.Looper;
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.statusbar.phone.QSTileHost;
+import com.android.systemui.statusbar.policy.DataSaverController;
+import com.android.systemui.statusbar.policy.HotspotController;
+import com.android.systemui.statusbar.policy.NetworkController;
 import org.mockito.ArgumentCaptor;
 import org.mockito.Mockito;
 
@@ -34,8 +37,13 @@
     protected void setUp() throws Exception {
         super.setUp();
         mManagers = new ArrayList<>();
-        QSTileHost host = new QSTileHost(mContext, null, null, null, null, null, null, null, null,
-                null, null, null, null, null, null, null);
+        final NetworkController networkController = Mockito.mock(NetworkController.class);
+        Mockito.when(networkController.getDataSaverController()).thenReturn(
+                Mockito.mock(DataSaverController.class));
+        QSTileHost host = new QSTileHost(mContext, null, null, null, null,
+                networkController, null,
+                Mockito.mock(HotspotController.class), null,
+                null, null, null, null, null, null, null, null);
         mTileService = new TestTileServices(host, Looper.myLooper());
     }
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/CallbackHandlerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/CallbackHandlerTest.java
index 00b8de2..19cb243 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/CallbackHandlerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/CallbackHandlerTest.java
@@ -19,12 +19,10 @@
 import android.telephony.SubscriptionInfo;
 import android.test.AndroidTestCase;
 import android.test.suitebuilder.annotation.SmallTest;
-
 import com.android.systemui.R;
+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.NetworkControllerImpl.EmergencyListener;
-
 import org.mockito.ArgumentCaptor;
 import org.mockito.Mock;
 import org.mockito.Mockito;
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 5cf3767..60d33fa 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
@@ -16,9 +16,6 @@
 
 package com.android.systemui.statusbar.policy;
 
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
 import android.content.Intent;
 import android.net.ConnectivityManager;
 import android.net.NetworkCapabilities;
@@ -31,14 +28,13 @@
 import android.telephony.SubscriptionManager;
 import android.telephony.TelephonyManager;
 import android.util.Log;
-
 import com.android.internal.telephony.cdma.EriInfo;
 import com.android.settingslib.net.DataUsageController;
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.statusbar.policy.NetworkController.IconState;
+import com.android.systemui.statusbar.policy.NetworkController.SignalCallback;
 import com.android.systemui.statusbar.policy.NetworkControllerImpl.Config;
 import com.android.systemui.statusbar.policy.NetworkControllerImpl.SubscriptionDefaults;
-
 import org.mockito.ArgumentCaptor;
 import org.mockito.Mockito;
 
@@ -47,6 +43,9 @@
 import java.util.ArrayList;
 import java.util.List;
 
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
 public class NetworkControllerBaseTest extends SysuiTestCase {
     private static final String TAG = "NetworkControllerBaseTest";
     protected static final int DEFAULT_LEVEL = 2;
@@ -102,13 +101,14 @@
 
         // Trigger blank callbacks to always get the current state (some tests don't trigger
         // changes from default state).
-        mNetworkController.addSignalCallback(null);
+        mNetworkController.addSignalCallback(mock(SignalCallback.class));
         mNetworkController.addEmergencyListener(null);
     }
 
     protected void setupNetworkController() {
         // For now just pretend to be the data sim, so we can test that too.
         mSubId = SubscriptionManager.DEFAULT_SUBSCRIPTION_ID;
+        when(mMockTm.getDataEnabled(mSubId)).thenReturn(true);
         setDefaultSubId(mSubId);
         setSubscriptions(mSubId);
         mMobileSignalController = mNetworkController.mMobileSignalControllers.get(mSubId);
diff --git a/proto/src/metrics_constants.proto b/proto/src/metrics_constants.proto
index 568edab..d36a1d7 100644
--- a/proto/src/metrics_constants.proto
+++ b/proto/src/metrics_constants.proto
@@ -24,334 +24,1734 @@
 
   // Known visual elements: views or controls.
   enum View {
+    // Unknown view
     VIEW_UNKNOWN = 0;
+
+    // OBSOLETE
     MAIN_SETTINGS = 1;
+
+    // OPEN: Settings > Accessibility
+    // CATEGORY: SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.26
     ACCESSIBILITY = 2;
+
+    // OPEN: Settings > Accessibility > Captions
+    // CATEGORY: SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.26
     ACCESSIBILITY_CAPTION_PROPERTIES = 3;
+
+    // OPEN: Settings > Accessibility > [Service]
+    // CATEGORY: SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.26
     ACCESSIBILITY_SERVICE = 4;
+
+    // OPEN: Settings > Accessibility > Color correction
+    // CATEGORY: SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.26
     ACCESSIBILITY_TOGGLE_DALTONIZER = 5;
+
+    // OPEN: Settings > Accessibility > Accessibility shortcut
+    // CATEGORY: SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.26
     ACCESSIBILITY_TOGGLE_GLOBAL_GESTURE = 6;
+
+    // OPEN: Settings > Accessibility > Magnification gestures
+    // CATEGORY: SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.26
     ACCESSIBILITY_TOGGLE_SCREEN_MAGNIFICATION = 7;
+
+    // OPEN: Settings > Accounts
+    // CATEGORY: SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.26
     ACCOUNT = 8;
+
+    // OPEN: Settings > Accounts > [Single Account Sync Settings]
+    // CATEGORY: SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.26
     ACCOUNTS_ACCOUNT_SYNC = 9;
+
+    // OPEN: Settings > Accounts > Add an account
+    // CATEGORY: SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.26
     ACCOUNTS_CHOOSE_ACCOUNT_ACTIVITY = 10;
+
+    // OPEN: Settings > Accounts > [List of accounts when more than one]
+    // CATEGORY: SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.26
     ACCOUNTS_MANAGE_ACCOUNTS = 11;
+
+    // OPEN: Settings > Cellular network settings > APNs
+    // CATEGORY: SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.26
     APN = 12;
+
+    // OPEN: Settings > More > Cellular network settings > APNs > [Edit APN]
+    // CATEGORY: SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.26
     APN_EDITOR = 13;
+
+    // OBSOLETE
     APP_OPS_DETAILS = 14;
+
+    // OBSOLETE
     APP_OPS_SUMMARY = 15;
+
+    // OBSOLETE
     APPLICATION = 16;
+
+    // OPEN: Settings > Apps > Configure apps > App links > [App]
+    // CATEGORY: SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.26
     APPLICATIONS_APP_LAUNCH = 17;
+
+    // OBSOLETE
     APPLICATIONS_APP_PERMISSION = 18;
+
+    // OPEN: Settings > Internal storage > Apps storage > [App]
+    // CATEGORY: SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.26
     APPLICATIONS_APP_STORAGE = 19;
+
+    // OPEN: Settings > Apps > [App info]
+    // CATEGORY: SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.26
     APPLICATIONS_INSTALLED_APP_DETAILS = 20;
+
+    // OPEN: Settings > Memory > App usage > [App Memory usage]
+    // CATEGORY: SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.26
     APPLICATIONS_PROCESS_STATS_DETAIL = 21;
+
+    // OBSOLETE
     APPLICATIONS_PROCESS_STATS_MEM_DETAIL = 22;
+
+    // OPEN: Settings > Memory > App usage
+    // CATEGORY: SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.26
     APPLICATIONS_PROCESS_STATS_UI = 23;
+
+    // OPEN: Settings > Bluetooth
+    // CATEGORY: SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.26
     BLUETOOTH = 24;
+
+    // OPEN: Choose Bluetooth device (ex: when sharing)
+    // CATEGORY: SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.26
     BLUETOOTH_DEVICE_PICKER = 25;
+
+    // OBSOLETE
     BLUETOOTH_DEVICE_PROFILES = 26;
+
+    // OPEN: Settings > Security > Choose screen lock
+    // CATEGORY: SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.26
     CHOOSE_LOCK_GENERIC = 27;
+
+    // OPEN: Settings > Security > Choose screen lock > Choose your password
+    // CATEGORY: SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.26
     CHOOSE_LOCK_PASSWORD = 28;
+
+    // OPEN: Settings > Security > Choose screen lock > Choose your pattern
+    // CATEGORY: SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.26
     CHOOSE_LOCK_PATTERN = 29;
+
+    // OPEN: Settings > Security > Choose screen lock > Confirm your password
+    // CATEGORY: SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.26
     CONFIRM_LOCK_PASSWORD = 30;
+
+    // OPEN: Settings > Security > Choose screen lock > Confirm your pattern
+    // CATEGORY: SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.26
     CONFIRM_LOCK_PATTERN = 31;
+
+    // OPEN: Settings > Security > Encrypt phone
+    // CATEGORY: SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.26
     CRYPT_KEEPER = 32;
+
+    // OPEN: Settings > Security > Encrypt phone > Confirm
+    // CATEGORY: SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.26
     CRYPT_KEEPER_CONFIRM = 33;
+
+    // OPEN: Settings > Search results
+    // CATEGORY: SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.26
     DASHBOARD_SEARCH_RESULTS = 34;
+
+    // OPEN: Settings (Root page)
+    // CATEGORY: SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.26
     DASHBOARD_SUMMARY = 35;
+
+    // OBSOLETE
     DATA_USAGE = 36;
+
+    // OPEN: Settings > Data usage
+    // CATEGORY: SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.26
     DATA_USAGE_SUMMARY = 37;
+
+    // OPEN: Settings > Date & time
+    // CATEGORY: SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.26
     DATE_TIME = 38;
+
+    // OPEN: Settings > Developer options
+    // CATEGORY: SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.26
     DEVELOPMENT = 39;
+
+    // OPEN: Settings > About phone
+    // CATEGORY: SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.26
     DEVICEINFO = 40;
+
+    // OPEN: Settings > About phone > Status > IMEI information
+    // CATEGORY: SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.26
     DEVICEINFO_IMEI_INFORMATION = 41;
+
+    // OPEN: Settings > Internal storage
+    // CATEGORY: SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.26
     DEVICEINFO_STORAGE = 42;
+
+    // OPEN: Settings > About phone > Status > SIM status
+    // CATEGORY: SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.26
     DEVICEINFO_SIM_STATUS = 43;
+
+    // OPEN: Settings > About phone > Status
+    // CATEGORY: SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.26
     DEVICEINFO_STATUS = 44;
+
+    // OBSOLETE
     DEVICEINFO_USB = 45;
+
+    // OPEN: Settings > Display
+    // CATEGORY: SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.26
     DISPLAY = 46;
+
+    // OPEN: Settings > Display > Daydream
+    // CATEGORY: SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.26
     DREAM = 47;
+
+    // OPEN: Settings > Security > Screen lock > Secure start-up
+    // CATEGORY: SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.26
     ENCRYPTION = 48;
+
+    // OPEN: Settings > Security > Nexus Imprint
+    // CATEGORY: SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.26
     FINGERPRINT = 49;
+
+    // OBSOLETE
     FINGERPRINT_ENROLL = 50;
+
+    // OPEN: Settings > Battery > History details
+    // CATEGORY: SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.26
     FUELGAUGE_BATTERY_HISTORY_DETAIL = 51;
+
+    // OPEN: Settings > Battery > Battery saver
+    // CATEGORY: SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.26
     FUELGAUGE_BATTERY_SAVER = 52;
+
+    // OPEN: Settings > Battery > [App Use details]
+    // CATEGORY: SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.26
     FUELGAUGE_POWER_USAGE_DETAIL = 53;
+
+    // OPEN: Settings > Battery
+    // CATEGORY: SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.26
     FUELGAUGE_POWER_USAGE_SUMMARY = 54;
+
+    // OPEN: Settings > Home
+    // CATEGORY: SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.26
     HOME = 55;
+
+    // OPEN: Settings > Security > SIM card lock settings
+    // CATEGORY: SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.26
     ICC_LOCK = 56;
+
+    // OPEN: Settings > Language & input
+    // CATEGORY: SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.26
     INPUTMETHOD_LANGUAGE = 57;
+
+    // OPEN: Settings > Language & input > Physical keyboard
+    // CATEGORY: SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.26
     INPUTMETHOD_KEYBOARD = 58;
+
+    // OPEN: Settings > Language & input > Spell checker
+    // CATEGORY: SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.26
     INPUTMETHOD_SPELL_CHECKERS = 59;
+
+    // OBSOLETE
     INPUTMETHOD_SUBTYPE_ENABLER = 60;
+
+    // OPEN: Settings > Language & input > Personal dictionary
+    // CATEGORY: SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.26
     INPUTMETHOD_USER_DICTIONARY = 61;
+
+    // OPEN: Settings > Language & input > Add word
+    // CATEGORY: SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.26
     INPUTMETHOD_USER_DICTIONARY_ADD_WORD = 62;
+
+    // OPEN: Settings > Location
+    // CATEGORY: SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.26
     LOCATION = 63;
+
+    // OPEN: Settings > Location > Location mode
+    // CATEGORY: SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.26
     LOCATION_MODE = 64;
+
+    // OPEN: Settings > Apps
+    // CATEGORY: SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.26
     MANAGE_APPLICATIONS = 65;
+
+    // OPEN: Settings > Backup & reset > Factory data reset
+    // CATEGORY: SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.26
     MASTER_CLEAR = 66;
+
+    // OPEN: Settings > Backup & reset > Factory data reset > Confirm
+    // CATEGORY: SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.26
     MASTER_CLEAR_CONFIRM = 67;
+
+    // OPEN: Settings > Data usage > Network restrictions
+    // CATEGORY: SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.26
     NET_DATA_USAGE_METERED = 68;
+
+    // OPEN: Settings > More > Android Beam
+    // CATEGORY: SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.26
     NFC_BEAM = 69;
+
+    // OPEN: Settings > Tap & pay
+    // CATEGORY: SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.26
     NFC_PAYMENT = 70;
+
+    // OPEN: Settings > Sound & notification
+    // CATEGORY: SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.26
     NOTIFICATION = 71;
+
+    // OPEN: Settings > Sound & notification > App notifications > [App]
+    // CATEGORY: SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.26
     NOTIFICATION_APP_NOTIFICATION = 72;
+
+    // OPEN: Settings > Sound & notification > Other sounds
+    // CATEGORY: SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.26
     NOTIFICATION_OTHER_SOUND = 73;
+
+    // OBSOLETE
     NOTIFICATION_REDACTION = 74;
+
+    // OPEN: Settings Widget > Notification log
+    // CATEGORY: SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.26
     NOTIFICATION_STATION = 75;
+
+    // OPEN: Settings > Sound & notification > Do not disturb
+    // CATEGORY: SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.26
     NOTIFICATION_ZEN_MODE = 76;
+
+    // OPEN: OBSOLETE
     OWNER_INFO = 77;
+
+    // OPEN: Print job notification > Print job settings
+    // CATEGORY: SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.26
     PRINT_JOB_SETTINGS = 78;
+
+    // OPEN: Settings > Printing > [Print Service]
+    // CATEGORY: SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.26
     PRINT_SERVICE_SETTINGS = 79;
+
+    // OPEN: Settings > Printing
+    // CATEGORY: SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.26
     PRINT_SETTINGS = 80;
+
+    // OPEN: Settings > Backup & reset
+    // CATEGORY: SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.26
     PRIVACY = 81;
+
+    //OBSOLETE
     PROXY_SELECTOR = 82;
+
+    // OPEN: Settings > Backup & reset > Network settings reset
+    // CATEGORY: SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.26
     RESET_NETWORK = 83;
+
+    // OPEN: Settings > Backup & reset > Network settings reset > Confirm
+    // CATEGORY: SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.26
     RESET_NETWORK_CONFIRM = 84;
+
+    // OPEN: Settings > Developer Options > Running Services
+    // CATEGORY: SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.26
     RUNNING_SERVICE_DETAILS = 85;
+
+    // OPEN: Settings > Security > Screen pinning
+    // CATEGORY: SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.26
     SCREEN_PINNING = 86;
+
+    // OPEN: Settings > Security
+    // CATEGORY: SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.26
     SECURITY = 87;
+
+    // OPEN: Settings > SIM cards
+    // CATEGORY: SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.26
     SIM = 88;
+
+    // OBSOLETE
     TESTING = 89;
+
+    // OPEN: Settings > More > Tethering & portable hotspot
+    // CATEGORY: SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.26
     TETHER = 90;
+
+    // OPEN: Settings > Security > Trust agents
+    // CATEGORY: SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.26
     TRUST_AGENT = 91;
+
+    // OPEN: Settings > Security > Trusted credentials
+    // CATEGORY: SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.26
     TRUSTED_CREDENTIALS = 92;
+
+    // OPEN: Settings > Language & input > TTS output > [Engine] > Settings
+    // CATEGORY: SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.26
     TTS_ENGINE_SETTINGS = 93;
+
+    // OPEN: Settings > Language & input > Text-to-speech output
+    // CATEGORY: SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.26
     TTS_TEXT_TO_SPEECH = 94;
+
+    // OPEN: Settings > Security > Apps with usage access
+    // CATEGORY: SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.26
     USAGE_ACCESS = 95;
+
+    // OPEN: Settings > Users
+    // CATEGORY: SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.26
     USER = 96;
+
+    // OPEN: Settings > Users > [Restricted profile app & content access]
+    // CATEGORY: SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.26
     USERS_APP_RESTRICTIONS = 97;
+
+    // OPEN: Settings > Users > [User settings]
+    // CATEGORY: SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.26
     USER_DETAILS = 98;
+
+    // OBSOLETE
     VOICE_INPUT = 99;
+
+    // OPEN: Settings > More > VPN
+    // CATEGORY: SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.26
     VPN = 100;
+
+    // OPEN: Settings > Display > Choose wallpaper from
+    // CATEGORY: SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.26
     WALLPAPER_TYPE = 101;
+
+    // OPEN: Settings > Display > Cast
+    // CATEGORY: SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.26
     WFD_WIFI_DISPLAY = 102;
+
+    // OPEN: Settings > Wi-Fi
+    // CATEGORY: SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.26
     WIFI = 103;
+
+    // OPEN: Settings > Wi-Fi > Advanced Wi-Fi
+    // CATEGORY: SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.26
     WIFI_ADVANCED = 104;
+
+    // OPEN: Settings > More > Wi-Fi Calling
+    // CATEGORY: SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.26
     WIFI_CALLING = 105;
+
+    // OPEN: Settings > Wi-Fi > Saved networks
+    // CATEGORY: SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.26
     WIFI_SAVED_ACCESS_POINTS = 106;
+
+    // OBSOLETE
     WIFI_APITEST = 107;
+
+    // OBSOLETE
     WIFI_INFO = 108;
+
+    // OPEN: Settings > Wi-Fi > Advanced Wi-Fi > Wi-Fi Direct
+    // CATEGORY: SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.26
     WIFI_P2P = 109;
+
+    // OPEN: Settings > More
+    // CATEGORY: SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.26
     WIRELESS = 110;
+
+    // OPEN: Quick Settings Panel
+    // CATEGORY: QUICK_SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.26
     QS_PANEL = 111;
+
+    // OPEN: QS Airplane mode tile shown
+    // ACTION: QS Airplane mode tile tapped
+    //  SUBTYPE: 0 is off, 1 is on
+    // CATEGORY: QUICK_SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.46
     QS_AIRPLANEMODE = 112;
+
+    // OPEN: QS Bluetooth tile shown
+    // ACTION: QS Bluetooth tile tapped
+    //  SUBTYPE: 0 is off, 1 is on
+    // CATEGORY: QUICK_SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.46
     QS_BLUETOOTH = 113;
+
+    // OPEN: QS Cast tile shown
+    // ACTION: QS Cast tile tapped
+    // CATEGORY: QUICK_SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.46
     QS_CAST = 114;
+
+    // OPEN: QS Cellular tile shown
+    // ACTION: QS Cellular tile tapped
+    // CATEGORY: QUICK_SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.46
     QS_CELLULAR = 115;
+
+    // OPEN: QS Color inversion tile shown
+    // ACTION: QS Color inversion tile tapped
+    //  SUBTYPE: 0 is off, 1 is on
+    // CATEGORY: QUICK_SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.46
     QS_COLORINVERSION = 116;
+
+    // OPEN: QS Cellular tile > Cellular detail panel
+    // CATEGORY: QUICK_SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.46
     QS_DATAUSAGEDETAIL = 117;
+
+    // OPEN: QS Do not disturb tile shown
+    // ACTION: QS Do not disturb tile tapped
+    //  SUBTYPE: 0 is off, 1 is on
+    // CATEGORY: QUICK_SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.46
     QS_DND = 118;
+
+    // OPEN: QS Flashlight tile shown
+    // ACTION: QS Flashlight tile tapped
+    //  SUBTYPE: 0 is off, 1 is on
+    // CATEGORY: QUICK_SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.46
     QS_FLASHLIGHT = 119;
+
+    // OPEN: QS Hotspot tile shown
+    // ACTION: QS Hotspot tile tapped
+    //  SUBTYPE: 0 is off, 1 is on
+    // CATEGORY: QUICK_SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.46
     QS_HOTSPOT = 120;
+
+    // OPEN: QS 3P tile shown
+    // ACTION: QS 3P tile tapped
+    // CATEGORY: QUICK_SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.46
     QS_INTENT = 121;
+
+    // OPEN: QS Location tile shown
+    // ACTION: QS Location tile tapped
+    //  SUBTYPE: 0 is off, 1 is on
+    // CATEGORY: QUICK_SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.46
     QS_LOCATION = 122;
+
+    // OPEN: QS Rotation tile shown
+    // ACTION: QS Rotation tile tapped
+    //  SUBTYPE: 0 is off, 1 is on
+    // CATEGORY: QUICK_SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.46
     QS_ROTATIONLOCK = 123;
+
+    // OBSOLETE
     QS_USERDETAILITE = 124;
+
+    // OPEN: QS User list panel
+    // CATEGORY: QUICK_SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.46
     QS_USERDETAIL = 125;
+
+    // OPEN: QS WiFi tile shown
+    // ACTION: QS WiFi tile tapped
+    //  SUBTYPE: 0 is off, 1 is on
+    // CATEGORY: QUICK_SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.46
     QS_WIFI = 126;
+
+    // OPEN: Notification Panel (including lockscreen)
+    // CATEGORY: NOTIFICATION
+    // OS: 5.1.1
+    // GMS: 7.5.26
     NOTIFICATION_PANEL = 127;
+
+    // OPEN: Notification in panel became visible.
+    //   PACKAGE: App that posted the notification.
+    // ACTION: Notification is tapped.
+    //   PACKAGE: App that posted the notification
+    // DETAIL: Notification is expanded by user.
+    //   PACKAGE: App that posted the notification
+    // DISMISS: Notification is dismissed.
+    //   PACKAGE: App that posted the notification
+    //   SUBTYPE: Dismiss reason from NotificationManagerService.java
+    // CATEGORY: NOTIFICATION
+    // OS: 5.1.1
+    // GMS: 7.5.26
     NOTIFICATION_ITEM = 128;
+
+    // ACTION: User tapped notification action
+    //   PACKAGE: App that posted the notification
+    //   SUBTYPE: Index of action on notification
+    // CATEGORY: NOTIFICATION
+    // OS: 5.0
+    // GMS: 7.5.26
     NOTIFICATION_ITEM_ACTION = 129;
+
+    // OPEN: Settings > Apps > Configure apps > App permissions
+    // CATEGORY: SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.26
     APPLICATIONS_ADVANCED = 130;
+
+    // OPEN: Settings > Location > Scanning
+    // CATEGORY: SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.26
     LOCATION_SCANNING = 131;
+
+    // OBSOLETE
     MANAGE_APPLICATIONS_ALL = 132;
+
+    // OPEN: Settings > Sound & notification > App notifications
+    // CATEGORY: SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.26
     MANAGE_APPLICATIONS_NOTIFICATIONS = 133;
+
+    // ACTION: Settings > Wi-Fi > Overflow > Add Network
+    // CATEGORY: SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.26
     ACTION_WIFI_ADD_NETWORK = 134;
+
+    // ACTION: Settings > Wi-Fi > [Long press network] > Connect to network
+    // CATEGORY: SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.26
     ACTION_WIFI_CONNECT = 135;
+
+    // ACTION: Settings > Wi-Fi > Overflow > Refresh
+    // CATEGORY: SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.26
     ACTION_WIFI_FORCE_SCAN = 136;
+
+    // ACTION: Settings > Wi-Fi > [Long press network] > Forget network
+    // CATEGORY: SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.26
     ACTION_WIFI_FORGET = 137;
+
+    // ACTION: Settings > Wi-Fi > Toggle off
+    // CATEGORY: SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.26
     ACTION_WIFI_OFF = 138;
+
+    // ACTION: Settings > Wi-Fi > Toggle on
+    // CATEGORY: SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.26
     ACTION_WIFI_ON = 139;
+
+    // OBSOLETE
     MANAGE_PERMISSIONS = 140;
+
+    // OPEN: Settings > Sound & notification > DND > Priority only allows
+    // CATEGORY: SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.26
     NOTIFICATION_ZEN_MODE_PRIORITY = 141;
+
+    // OPEN: Settings > Sound & notification > DND > Automatic rules
+    // CATEGORY: SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.26
     NOTIFICATION_ZEN_MODE_AUTOMATION = 142;
+
+    // OPEN: Settings > Apps > Configure apps > App links
+    // CATEGORY: SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.26
     MANAGE_DOMAIN_URLS = 143;
+
+    // OPEN: Settings > Sound & notification > DND > [Time based rule]
+    // CATEGORY: SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.26
     NOTIFICATION_ZEN_MODE_SCHEDULE_RULE = 144;
+
+    // OPEN: Settings > Sound & notification > DND > [External rule]
+    // CATEGORY: SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.26
     NOTIFICATION_ZEN_MODE_EXTERNAL_RULE = 145;
+
+    // OPEN: Settings > Sound & notification > DND > [Event rule]
+    // CATEGORY: SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.26
     NOTIFICATION_ZEN_MODE_EVENT_RULE = 146;
+
+    // ACTION: App notification settings > Block Notifications
+    // CATEGORY: SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.26
     ACTION_BAN_APP_NOTES = 147;
+
+    // ACTION: Notification shade > Dismiss all button
+    // CATEGORY: NOTIFICATION
+    // OS: 6.0
+    // GMS: 7.5.26
     ACTION_DISMISS_ALL_NOTES = 148;
+
+    // OPEN: QS Do Not Disturb detail panel
+    // CATEGORY: QUICK_SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.26
     QS_DND_DETAILS = 149;
+
+    // OPEN: QS Bluetooth detail panel
+    // CATEGORY: QUICK_SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.26
     QS_BLUETOOTH_DETAILS = 150;
+
+    // OPEN: QS Cast detail panel
+    // CATEGORY: QUICK_SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.26
     QS_CAST_DETAILS = 151;
+
+    // OPEN: QS Wi-Fi detail panel
+    // CATEGORY: QUICK_SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.26
     QS_WIFI_DETAILS = 152;
+
+    // ACTION: QS Wi-Fi detail panel > Wi-Fi toggle
+    //   SUBTYPE: 0 is off, 1 is on
+    // CATEGORY: QUICK_SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.26
     QS_WIFI_TOGGLE = 153;
+
+    // ACTION: QS Bluetooth detail panel > Bluetooth toggle
+    //   SUBTYPE: 0 is off, 1 is on
+    // CATEGORY: QUICK_SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.26
     QS_BLUETOOTH_TOGGLE = 154;
+
+    // ACTION: QS Cellular detail panel > Cellular toggle
+    //   SUBTYPE: 0 is off, 1 is on
+    // CATEGORY: QUICK_SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.26
     QS_CELLULAR_TOGGLE = 155;
+
+    // ACTION: QS User list panel > Select different user
+    // CATEGORY: QUICK_SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.26
     QS_SWITCH_USER = 156;
+
+    // ACTION: QS Cast detail panel > Select cast device
+    // CATEGORY: QUICK_SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.26
     QS_CAST_SELECT = 157;
+
+    // ACTION: QS Cast detail panel > Disconnect cast device
+    // CATEGORY: QUICK_SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.26
     QS_CAST_DISCONNECT = 158;
+
+    // ACTION: Settings > Bluetooth > Toggle
+    //   SUBTYPE: 0 is off, 1 is on
+    // CATEGORY: SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.26
     ACTION_BLUETOOTH_TOGGLE = 159;
+
+    // ACTION: Settings > Bluetooth > Overflow > Refresh
+    // CATEGORY: SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.26
     ACTION_BLUETOOTH_SCAN = 160;
+
+    // ACTION: Settings > Bluetooth > Overflow > Rename this device
+    // CATEGORY: SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.26
     ACTION_BLUETOOTH_RENAME = 161;
+
+    // ACTION: Settings > Bluetooth > Overflow > Show received files
+    // CATEGORY: SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.26
     ACTION_BLUETOOTH_FILES = 162;
+
+    // ACTION: QS DND details panel > Increase / Decrease exit time
+    //   SUBTYPE: true is increase, false is decrease
+    // CATEGORY: QUICK_SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.26
     QS_DND_TIME = 163;
+
+    // ACTION: QS DND details panel > [Exit condition]
+    // CATEGORY: QUICK_SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.26
     QS_DND_CONDITION_SELECT = 164;
+
+    // ACTION: QS DND details panel > [DND mode]
+    //  SUBTYPE: 1 is priority, 2 is silence, 3 is alarms only
+    // CATEGORY: QUICK_SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.26
     QS_DND_ZEN_SELECT = 165;
+
+    // ACTION: QS DND detail panel > DND toggle
+    //   SUBTYPE: 0 is off, 1 is on
+    // CATEGORY: QUICK_SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.26
     QS_DND_TOGGLE = 166;
+
+    // ACTION: DND Settings > Priority only allows > Reminder toggle
+    //   SUBTYPE: 0 is off, 1 is on
+    // CATEGORY: SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.26
     ACTION_ZEN_ALLOW_REMINDERS = 167;
+
+    // ACTION: DND Settings > Priority only allows > Event toggle
+    //   SUBTYPE: 0 is off, 1 is on
+    // CATEGORY: SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.26
     ACTION_ZEN_ALLOW_EVENTS = 168;
+
+    // ACTION: DND Settings > Priority only allows > Messages
+    //   SUBTYPE: 0 is off, 1 is on
+    // CATEGORY: SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.26
     ACTION_ZEN_ALLOW_MESSAGES = 169;
+
+    // ACTION: DND Settings > Priority only allows > Calls
+    //   SUBTYPE: 0 is off, 1 is on
+    // CATEGORY: SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.26
     ACTION_ZEN_ALLOW_CALLS = 170;
+
+    // ACTION: DND Settings > Priority only allows > Repeat callers toggle
+    //   SUBTYPE: 0 is off, 1 is on
+    // CATEGORY: SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.26
     ACTION_ZEN_ALLOW_REPEAT_CALLS = 171;
+
+    // ACTION: DND Settings > Automatic rules > Add rule
+    // CATEGORY: SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.26
     ACTION_ZEN_ADD_RULE = 172;
+
+    // ACTION: DND Settings > Automatic rules > Add rule > OK
+    // CATEGORY: SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.26
     ACTION_ZEN_ADD_RULE_OK = 173;
+
+    // ACTION: DND Settings > Automatic rules > [Rule] > Delete rule
+    // CATEGORY: SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.26
     ACTION_ZEN_DELETE_RULE = 174;
+
+    // ACTION: DND Settings > Automatic rules > [Rule] > Delete rule > Delete
+    // CATEGORY: SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.26
     ACTION_ZEN_DELETE_RULE_OK = 175;
+
+    // ACTION: DND Settings > Automatic rules > [Rule] > Toggle
+    //   SUBTYPE: 0 is off, 1 is on
+    // CATEGORY: SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.26
     ACTION_ZEN_ENABLE_RULE = 176;
+
+    // ACTION: Settings > More > Airplane mode toggle
+    //   SUBTYPE: 0 is off, 1 is on
+    // CATEGORY: SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.26
     ACTION_AIRPLANE_TOGGLE = 177;
+
+    // ACTION: Settings > Data usage > Cellular data toggle
+    //   SUBTYPE: 0 is off, 1 is on
+    // CATEGORY: SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.26
     ACTION_CELL_DATA_TOGGLE = 178;
+
+    // OPEN: Settings > Sound & notification > Notification access
+    // CATEGORY: SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.26
     NOTIFICATION_ACCESS = 179;
+
+    // OPEN: Settings > Sound & notification > Do Not Disturb access
+    // CATEGORY: SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.26
     NOTIFICATION_ZEN_MODE_ACCESS = 180;
+
+    // OPEN: Settings > Apps > Configure apps > Default Apps
+    // CATEGORY: SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.26
     APPLICATIONS_DEFAULT_APPS = 181;
+
+    // OPEN: Settings > Internal storage > Apps storage
+    // CATEGORY: SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.26
     APPLICATIONS_STORAGE_APPS = 182;
+
+    // OPEN: Settings > Security > Usage access
+    // CATEGORY: SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.26
     APPLICATIONS_USAGE_ACCESS_DETAIL = 183;
+
+    // OPEN: Settings > Battery > Battery optimization
+    // CATEGORY: SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.26
     APPLICATIONS_HIGH_POWER_APPS = 184;
+
+    // OBSOLETE
     FUELGAUGE_HIGH_POWER_DETAILS = 185;
+
+    // ACTION: Lockscreen > Unlock gesture
+    // CATEGORY: GLOBAL_SYSTEM_UI
+    // OS: 5.1.1
+    // GMS: 7.8.22
     ACTION_LS_UNLOCK = 186;
+
+    // ACTION: Lockscreen > Pull shade open
+    // CATEGORY: GLOBAL_SYSTEM_UI
+    // OS: 5.1.1
+    // GMS: 7.8.22
     ACTION_LS_SHADE = 187;
+
+    // ACTION: Lockscreen > Tap on lock, shows hint
+    // CATEGORY: GLOBAL_SYSTEM_UI
+    // OS: 5.1.1
+    // GMS: 7.8.22
     ACTION_LS_HINT = 188;
+
+    // ACTION: Lockscreen > Camera
+    // CATEGORY: GLOBAL_SYSTEM_UI
+    // OS: 5.1.1
+    // GMS: 7.8.22
     ACTION_LS_CAMERA = 189;
+
+    // ACTION: Lockscreen > Dialer
+    // CATEGORY: GLOBAL_SYSTEM_UI
+    // OS: 5.1.1
+    // GMS: 7.8.22
     ACTION_LS_DIALER = 190;
+
+    // ACTION: Lockscreen > Tap on lock, locks phone
+    // CATEGORY: GLOBAL_SYSTEM_UI
+    // OS: 5.1.1
+    // GMS: 7.8.22
     ACTION_LS_LOCK = 191;
+
+    // ACTION: Lockscreen > Tap on notification, false touch rejection
+    // CATEGORY: GLOBAL_SYSTEM_UI
+    // OS: 5.1.1
+    // GMS: 7.8.22
     ACTION_LS_NOTE = 192;
+
+    // ACTION: Lockscreen > Swipe down to open quick settings
+    // CATEGORY: GLOBAL_SYSTEM_UI
+    // OS: 6.0
+    // GMS: 7.8.22
     ACTION_LS_QS = 193;
+
+    // ACTION: Swipe down to open quick settings when unlocked
+    // CATEGORY: GLOBAL_SYSTEM_UI
+    // OS: 6.0
+    // GMS: 7.8.22
     ACTION_SHADE_QS_PULL = 194;
+
+    // ACTION: Notification shade > Tap to open quick settings
+    // CATEGORY: GLOBAL_SYSTEM_UI
+    // OS: 6.0
+    // GMS: 7.8.22
     ACTION_SHADE_QS_TAP = 195;
+
+    // OPEN: Lockscreen
+    //   SUBTYPE: 0 is unsecure, 1 is secured by password / pattern / PIN
+    // CATEGORY: GLOBAL_SYSTEM_UI
+    // OS: 5.1.1
+    // GMS: 7.8.22
     LOCKSCREEN = 196;
+
+    // OPEN: Lockscreen > Screen to enter password / pattern / PIN
+    // CATEGORY: GLOBAL_SYSTEM_UI
+    // OS: 5.1.1
+    // GMS: 7.8.22
     BOUNCER = 197;
+
+    // OPEN: Screen turned on
+    //   SUBTYPE: 2 is user action
+    // CATEGORY: GLOBAL_SYSTEM_UI
+    // OS: 5.1.1
+    // GMS: 7.8.22
     SCREEN = 198;
+
+    // OPEN: Notification caused sound, vibration, and/or LED blink
+    //   SUBTYPE: 1 is buzz, 2 is beep, blink is 4, or'd together
+    // CATEGORY: NOTIFICATION
+    // OS: 5.1.1
+    // GMS: 7.8.53
     NOTIFICATION_ALERT = 199;
+
+    // ACTION: Lockscreen > Emergency Call button
+    // CATEGORY: GLOBAL_SYSTEM_UI
+    // OS: 5.1.1
+    // GMS: 7.5.26
     ACTION_EMERGENCY_CALL = 200;
+
+    // OPEN: Settings > Apps > Configure > Default apps > Assist & voice input
+    // CATEGORY: SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.26
     APPLICATIONS_MANAGE_ASSIST = 201;
+
+    // OPEN: Settings > Memory
+    // CATEGORY: SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.26
     PROCESS_STATS_SUMMARY = 202;
+
+    // ACTION: Settings > Display > When device is rotated
+    // CATEGORY: SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.26
     ACTION_ROTATION_LOCK = 203;
+
+    // ACTION: Long press on notification to view controls
+    // CATEGORY: NOTIFICATION
+    // OS: 6.0
+    // GMS: 7.5.26
     ACTION_NOTE_CONTROLS = 204;
+
+    // ACTION: Notificatoin controls > Info button
+    // CATEGORY: NOTIFICATION
+    // OS: 6.0
+    // GMS: 7.5.26
     ACTION_NOTE_INFO = 205;
+
+    // ACTION: Notification controls > Settings button
+    // CATEGORY: NOTIFICATION
+    // OS: 6.0
+    // GMS: 7.5.26
     ACTION_APP_NOTE_SETTINGS = 206;
+
+    // OPEN: Volume Dialog (with hardware buttons)
+    // CATEGORY: GLOBAL_SYSTEM_UI
+    // OS: 6.0
+    // GMS: 7.5.26
     VOLUME_DIALOG = 207;
+
+    // OPEN: Volume dialog > Expanded volume dialog (multiple sliders)
+    // CATEGORY: GLOBAL_SYSTEM_UI
+    // OS: 6.0
+    // GMS: 7.5.26
     VOLUME_DIALOG_DETAILS = 208;
+
+    // ACTION: Volume dialog > Adjust volume slider
+    //   SUBTYPE: volume level (0-7)
+    // CATEGORY: GLOBAL_SYSTEM_UI
+    // OS: 6.0
+    // GMS: 7.5.26
     ACTION_VOLUME_SLIDER = 209;
+
+    // ACTION: Volume dialog > Select non-active stream
+    //   SUBTYPE: stream (defined in AudioSystem.java)
+    // CATEGORY: GLOBAL_SYSTEM_UI
+    // OS: 6.0
+    // GMS: 7.5.26
     ACTION_VOLUME_STREAM = 210;
+
+    // ACTION: Adjust volume with hardware key
+    //   SUBTYPE: volume level (0-7)
+    // CATEGORY: GLOBAL_SYSTEM_UI
+    // OS: 6.0
+    // GMS: 7.5.26
     ACTION_VOLUME_KEY = 211;
+
+    // ACTION: Volume dialog > Mute a stream by tapping icon
+    //   SUBTYPE: mute is 1, audible is 2
+    // CATEGORY: GLOBAL_SYSTEM_UI
+    // OS: 6.0
+    // GMS: 7.5.26
     ACTION_VOLUME_ICON = 212;
+
+    // ACTION: Volume dialog > Change ringer mode by tapping icon
+    //   SUBTYPE: 2 is audible, 3 is vibrate
+    // CATEGORY: GLOBAL_SYSTEM_UI
+    // OS: 6.0
+    // GMS: 7.5.26
     ACTION_RINGER_MODE = 213;
+
+    // ACTION: Chooser shown (share target, file open, etc.)
+    // CATEGORY: GLOBAL_SYSTEM_UI
+    // OS: 6.0
+    // GMS: 7.5.26
     ACTION_ACTIVITY_CHOOSER_SHOWN = 214;
+
+    // ACTION: Chooser > User taps an app target
+    //   SUBTYPE: Index of target
+    // CATEGORY: GLOBAL_SYSTEM_UI
+    // OS: 6.0
+    // GMS: 7.5.26
     ACTION_ACTIVITY_CHOOSER_PICKED_APP_TARGET = 215;
+
+    // ACTION: Chooser > User taps a service target
+    //   SUBTYPE: Index of target
+    // CATEGORY: GLOBAL_SYSTEM_UI
+    // OS: 6.0
+    // GMS: 7.5.26
     ACTION_ACTIVITY_CHOOSER_PICKED_SERVICE_TARGET = 216;
+
+    // ACTION: Chooser > User taps a standard target
+    //   SUBTYPE: Index of target
+    // CATEGORY: GLOBAL_SYSTEM_UI
+    // OS: 6.0
+    // GMS: 7.5.26
     ACTION_ACTIVITY_CHOOSER_PICKED_STANDARD_TARGET = 217;
+
+    // ACTION: QS Brightness Slider (with auto brightness disabled)
+    //   SUBTYPE: slider value
+    // CATEGORY: QUICK_SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.26
     ACTION_BRIGHTNESS = 218;
+
+    // ACTION: QS Brightness Slider (with auto brightness enabled)
+    //   SUBTYPE: slider value
+    // CATEGORY: QUICK_SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.26
     ACTION_BRIGHTNESS_AUTO = 219;
+
+    // OPEN: Settings > Display > Brightness Slider
+    // CATEGORY: SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.26
     BRIGHTNESS_DIALOG = 220;
+
+    // OPEN: Settings > Apps > Configure Apps > Draw over other apps
+    // CATEGORY: SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.26
     SYSTEM_ALERT_WINDOW_APPS = 221;
+
+    // OPEN: Display has entered dream mode
+    // CATEGORY: GLOBAL_SYSTEM_UI
+    // OS: 6.0
+    // GMS: 7.5.26
     DREAMING = 222;
+
+    // OPEN: Display has entered ambient notification mode
+    // CATEGORY: GLOBAL_SYSTEM_UI
+    // OS: 6.0
+    // GMS: 7.5.26
     DOZING = 223;
+
+    // OPEN: Overview
+    // CATEGORY: GLOBAL_SYSTEM_UI
+    // OS: 6.0
+    // GMS: 7.5.26
     OVERVIEW_ACTIVITY = 224;
+
+    // OPEN: Settings > About phone > Legal information
+    // CATEGORY: SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.26
     ABOUT_LEGAL_SETTINGS = 225;
+
+    // OPEN: Settings > Search > Perform search
+    // CATEGORY: SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.26
     ACTION_SEARCH_RESULTS = 226;
+
+    // OPEN: Settings > System UI Tuner
+    // CATEGORY: SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.26
     TUNER = 227;
+
+    // OPEN: Settings > System UI Tuner > Quick Settings
+    // CATEGORY: SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.26
     TUNER_QS = 228;
+
+    // OPEN: Settings > System UI Tuner > Demo mode
+    // CATEGORY: SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.26
     TUNER_DEMO_MODE = 229;
+
+    // ACTION: Settings > System UI Tuner > Quick Settings > Move tile
+    //   PACKAGE: Tile
+    // CATEGORY: SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.26
     TUNER_QS_REORDER = 230;
+
+    // ACTION: Settings > System UI Tuner > Quick Settings > Add tile
+    //   PACKAGE: Tile
+    // CATEGORY: SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.26
     TUNER_QS_ADD = 231;
+
+    // ACTION: Settings > System UI Tuner > Quick Settings > Remove tile
+    //   PACKAGE: Tile
+    // CATEGORY: SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.26
     TUNER_QS_REMOVE = 232;
+
+    // ACTION: Settings > System UI Tuner > Status bar > Enable icon
+    //   PACKAGE: Icon
+    // CATEGORY: SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.26
     TUNER_STATUS_BAR_ENABLE = 233;
+
+    // ACTION: Settings > System UI Tuner > Status bar > Disable icon
+    //   PACKAGE: Icon
+    // CATEGORY: SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.26
     TUNER_STATUS_BAR_DISABLE = 234;
+
+    // ACTION: Settings > System UI Tuner > Demo mode > Enable demo mode
+    //   SUBTYPE: false is disabled, true is enabled
+    // CATEGORY: SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.26
     TUNER_DEMO_MODE_ENABLED = 235;
+
+    // ACTION: Settings > System UI Tuner > Demo mode > Show demo mode
+    //   SUBTYPE: false is disabled, true is enabled
+    // CATEGORY: SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.26
     TUNER_DEMO_MODE_ON = 236;
+
+    // ACTION: Settings > System UI Tuner > Show embedded battery percentage
+    //   SUBTYPE: 0 is disabled, 1 is enabled
+    // CATEGORY: SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.26
     TUNER_BATTERY_PERCENTAGE = 237;
+
+    // OPEN: Settings > Developer options > Inactive apps
+    // CATEGORY: SETTINGS
+    // OS: 6.0
+    // GMS: 7.5.26
     FUELGAUGE_INACTIVE_APPS = 238;
+
+    // ACTION: Long press home to bring up assistant
+    // CATEGORY: GLOBAL_SYSTEM_UI
+    // OS: 6.0
+    // GMS: 7.5.26
     ACTION_ASSIST_LONG_PRESS = 239;
+
+    // OPEN: Settings > Security > Nexus Imprint > Add Fingerprint
+    // CATEGORY: SETTINGS
+    // OS: 6.0
+    // GMS: 7.8.99
     FINGERPRINT_ENROLLING = 240;
+
+    // OPEN: Fingerprint Enroll > Find Sensor
+    // CATEGORY: SETTINGS
+    // OS: 6.0
+    // GMS: 7.8.99
     FINGERPRINT_FIND_SENSOR = 241;
+
+    // OPEN: Fingerprint Enroll > Fingerprint Enrolled!
+    // CATEGORY: SETTINGS
+    // OS: 6.0
+    // GMS: 7.8.99
     FINGERPRINT_ENROLL_FINISH = 242;
+
+    // OPEN: Fingerprint Enroll introduction
+    // CATEGORY: SETTINGS
+    // OS: 6.0
+    // GMS: 7.8.99
     FINGERPRINT_ENROLL_INTRO = 243;
+
+    // OPEN: Fingerprint Enroll onboarding
+    // CATEGORY: SETTINGS
+    // OS: 6.0
+    // GMS: 7.8.99
     FINGERPRINT_ENROLL_ONBOARD = 244;
+
+    // OPEN: Fingerprint Enroll > Let's Start!
+    // CATEGORY: SETTINGS
+    // OS: 6.0
+    // GMS: 7.8.99
     FINGERPRINT_ENROLL_SIDECAR = 245;
+
+    // OPEN: Fingerprint Enroll SUW > Let's Start!
+    // CATEGORY: SETTINGS
+    // OS: 6.0
+    // GMS: 7.8.99
     FINGERPRINT_ENROLLING_SETUP = 246;
+
+    // OPEN: Fingerprint Enroll SUW > Find Sensor
+    // CATEGORY: SETTINGS
+    // OS: 6.0
+    // GMS: 7.8.99
     FINGERPRINT_FIND_SENSOR_SETUP = 247;
+
+    // OPEN: Fingerprint Enroll SUW > Fingerprint Enrolled!
+    // CATEGORY: SETTINGS
+    // OS: 6.0
+    // GMS: 7.8.99
     FINGERPRINT_ENROLL_FINISH_SETUP = 248;
+
+    // OPEN: Fingerprint Enroll SUW introduction
+    // CATEGORY: SETTINGS
+    // OS: 6.0
+    // GMS: 7.8.99
     FINGERPRINT_ENROLL_INTRO_SETUP = 249;
+
+    // OPEN: Fingerprint Enroll SUW onboarding
+    // CATEGORY: SETTINGS
+    // OS: 6.0
+    // GMS: 7.8.99
     FINGERPRINT_ENROLL_ONBOARD_SETUP = 250;
+
+    // ACTION: Add fingerprint > Enroll fingerprint
+    // CATEGORY: SETTINGS
+    // OS: 6.0
+    // GMS: 7.8.99
     ACTION_FINGERPRINT_ENROLL = 251;
+
+    // ACTION: Authenticate using fingerprint
+    // CATEGORY: SETTINGS
+    // OS: 6.0
+    // GMS: 7.8.99
     ACTION_FINGERPRINT_AUTH = 252;
+
+    // ACTION: Settings > Security > Nexus Imprint > [Fingerprint] > Delete
+    // CATEGORY: SETTINGS
+    // OS: 6.0
+    // GMS: 7.8.99
     ACTION_FINGERPRINT_DELETE = 253;
+
+    // ACTION: Settings > Security > Nexus Imprint > [Fingerprint] > Rename
+    // CATEGORY: SETTINGS
+    // OS: 6.0
+    // GMS: 7.8.99
     ACTION_FINGERPRINT_RENAME = 254;
+
+    // ACTION: Double tap camera shortcut
+    // CATEGORY: GLOBAL_SYSTEM_UI
+    // OS: 6.0
+    // GMS: 7.8.99
     ACTION_DOUBLE_TAP_POWER_CAMERA_GESTURE = 255;
+
+    // ACTION: Double twist camera shortcut
+    // CATEGORY: GLOBAL_SYSTEM_UI
+    // OS: 6.0
+    // GMS: 7.8.99
     ACTION_WIGGLE_CAMERA_GESTURE = 256;
+
+    // OPEN: QS Work Mode tile shown
+    // ACTION: QS Work Mode tile tapped
+    //   SUBTYPE: 0 is off, 1 is on
+    // CATEGORY: QUICK_SETTINGS
+    // OS: N
+    // GMS: 7.8.99
     QS_WORKMODE = 257;
+
+    // OPEN: Settings > Developer Options > Background Check
+    // CATEGORY: SETTINGS
+    // OS: N
+    // GMS: 7.8.99
     BACKGROUND_CHECK_SUMMARY = 258;
+
+    // OPEN: QS Lock tile shown
+    // ACTION: QS Lock tile tapped
+    //   SUBTYPE: 0 is off, 1 is on
+    // CATEGORY: QUICK_SETTINGS
+    // OS: N
+    // GMS: 7.8.99
     QS_LOCK_TILE = 259;
+
+    // OPEN: QS User Tile shown
+    // CATEGORY: QUICK_SETTINGS
+    // OS: N
+    // GMS: 7.8.99
     QS_USER_TILE = 260;
+
+    // OPEN: QS Battery tile shown
+    // CATEGORY: QUICK_SETTINGS
+    // OS: N
+    // GMS: 7.8.99
     QS_BATTERY_TILE = 261;
+
+    // OPEN: Settings > Sound > Do not disturb > Visual interruptions
+    // CATEGORY: SETTINGS
+    // OS: N
+    // GMS: 7.8.99
     NOTIFICATION_ZEN_MODE_VISUAL_INTERRUPTIONS = 262;
+
+    // ACTION: Visual interruptions > No screen interuptions toggle
+    //   SUBTYPE: 0 is off, 1 is on
+    // CATEGORY: SETTINGS
+    // OS: N
+    // GMS: 7.8.99
     ACTION_ZEN_ALLOW_WHEN_SCREEN_OFF = 263;
-    // Dead
+
+    // ACTION: Visual interruptions > No notification light toggle
+    //   SUBTYPE: 0 is off, 1 is on
+    // CATEGORY: SETTINGS
+    // OS: N
+    // GMS: 7.8.99
     ACTION_ZEN_ALLOW_LIGHTS = 264;
+
+    // OPEN: Settings > Notifications > [App] > Topic Notifications
+    // CATEGORY: SETTINGS
+    // OS: N
+    // GMS: 7.8.99
     NOTIFICATION_TOPIC_NOTIFICATION = 265;
+
+    // ACTION: Settings > Apps > Default Apps > Select different SMS app
+    //   PACKAGE: Selected SMS app
+    // CATEGORY: SETTINGS
+    // OS: N
+    // GMS: 7.8.99
     ACTION_DEFAULT_SMS_APP_CHANGED = 266;
+
+    // OPEN: QS Color modification tile shown
+    // ACTION: QS Color modification tile tapped
+    //   SUBTYPE: 0 is off, 1 is on
+    // CATEGORY: QUICK_SETTINGS
+    // OS: N
+    // GMS: 7.8.99
     QS_COLOR_MATRIX = 267;
+
+    // OPEN: QS Custom tile shown
+    // ACTION: QS Work Mode tile tapped
+    // CATEGORY: QUICK_SETTINGS
+    // OS: N
+    // GMS: 7.8.99
     QS_CUSTOM = 268;
+
+    // ACTION: Visual interruptions > Never turn off the screen toggle
+    //   SUBTYPE: 0 is off, 1 is on
+    // CATEGORY: SETTINGS
+    // OS: N
+    // GMS: 7.8.99
     ACTION_ZEN_ALLOW_WHEN_SCREEN_ON = 269;
 
-    // Logged when the user docks a window from recents by
-    // longpressing a task and dragging it to the dock area.
+    // ACTION: Overview > Long-press task, drag to enter split-screen
+    // CATEGORY: GLOBAL_SYSTEM_UI
+    // OS: N
+    // GMS: 7.8.99
     ACTION_WINDOW_DOCK_DRAG_DROP = 270;
 
-    // Logged when the user docks a fullscreen window by long pressing
-    // recents which also opens recents on the lower/right side.
+    // ACTION: In App > Long-press Overview button to enter split-screen
+    // CATEGORY: GLOBAL_SYSTEM_UI
+    // OS: N
+    // GMS: 7.8.99
     ACTION_WINDOW_DOCK_LONGPRESS = 271;
 
-    // Logged when the user docks a window by dragging from the navbar
-    // which also opens recents on the lower/right side.
+    // ACTION: In App > Swipe Overview button to enter split-screen
+    // CATEGORY: GLOBAL_SYSTEM_UI
+    // OS: N
+    // GMS: 7.8.99
     ACTION_WINDOW_DOCK_SWIPE = 272;
 
-    // Logged when the user launches a profile-specific app and we
-    // intercept it with the confirm credentials UI.
+    // ACTION: Launch profile-specific app > Confirm credentials
+    // CATEGORY: GLOBAL_SYSTEM_UI
+    // OS: N
+    // GMS: 7.8.99
     PROFILE_CHALLENGE = 273;
 
+    // OPEN: QS Battery detail panel
+    // CATEGORY: GLOBAL_SYSTEM_UI
+    // OS: N
+    // GMS: 7.8.99
     QS_BATTERY_DETAIL = 274;
 
-    // Logged when the user goes into the overview history.
+    // OPEN: Overview > History
+    // CATEGORY: GLOBAL_SYSTEM_UI
+    // OS: N
+    // GMS: 7.8.99
     OVERVIEW_HISTORY = 275;
 
-    // Logged when the user pages through overview.
-    OVERVIEW_PAGE = 276;
+    // ACTION: Overview > Page by tapping Overview button
+    // CATEGORY: GLOBAL_SYSTEM_UI
+    // OS: N
+    // GMS: 7.8.99
+    ACTION_OVERVIEW_PAGE = 276;
 
-    // Logged when the user launches a task from overview.
-    OVERVIEW_SELECT = 277;
+    // ACTION: Overview > Select app
+    // CATEGORY: GLOBAL_SYSTEM_UI
+    // OS: N
+    // GMS: 7.8.99
+    ACTION_OVERVIEW_SELECT = 277;
 
-    // Logged when the user views the emergency info.
+    // ACTION: View emergency info
+    // CATEGORY: GLOBAL_SYSTEM_UI
+    // OS: N
+    // GMS: 7.8.99
     ACTION_VIEW_EMERGENCY_INFO = 278;
 
-    // Logged when the user views the edit emergency info activity.
+    // ACTION: Edit emergency info activity
+    // CATEGORY: SETTINGS
+    // OS: N
+    // GMS: 7.8.99
     ACTION_EDIT_EMERGENCY_INFO = 279;
 
-    // Logged when the user edits an emergency info field.
+    // ACTION: Edit emergency info field
+    // CATEGORY: SETTINGS
+    // OS: N
+    // GMS: 7.8.99
     ACTION_EDIT_EMERGENCY_INFO_FIELD = 280;
 
-    // Logged when the user adds a new emergency contact.
+    // ACTION: Add emergency contact
+    // CATEGORY: SETTINGS
+    // OS: N
+    // GMS: 7.8.99
     ACTION_ADD_EMERGENCY_CONTACT = 281;
 
-    // Logged when the user deletes an emergency contact.
+    // ACTION: Delete emergency contact
+    // CATEGORY: SETTINGS
+    // OS: N
+    // GMS: 7.8.99
     ACTION_DELETE_EMERGENCY_CONTACT = 282;
 
-    // Logged when the user calls an emergency contact.
+    // ACTION: Call emergency contact
+    // CATEGORY: SETTINGS
+    // OS: N
+    // GMS: 7.8.99
     ACTION_CALL_EMERGENCY_CONTACT = 283;
 
-    // QS Tile for Data Saver.
+    // OPEN: QS Data Saver tile shown
+    // ACTION: QS Data Saver tile tapped
+    // CATEGORY: QUICK_SETTINGS
     QS_DATA_SAVER = 284;
 
     // OPEN: Settings > Security > User credentials
     // CATEGORY: Settings
-    // OS: 6.1
+    // OS: N
     // GMS: 7.8.99
     USER_CREDENTIALS = 285;
 
-    // Logged when the user undocks a previously docked window by long pressing recents while in
-    // docked mode.
+    // ACTION: In App (splitscreen) > Long-press Overview to exit split-screen
+    // CATEGORY: GLOBAL_SYSTEM_UI
+    // OS: N
+    // GMS: 7.8.99
     ACTION_WINDOW_UNDOCK_LONGPRESS = 286;
 
     // Logged when the user scrolls through overview manually
@@ -370,43 +1770,84 @@
     // indicate the user lowered the importance; positive means they increased it.
     ACTION_SAVE_IMPORTANCE = 291;
 
-    // Interactive bug report initiated from power menu.
+    // ACTION: Long-press power button, then tap "Take bug report" option.
+    // CATEGORY: GLOBAL_SYSTEM_UI
+    // OS: N
+    // GMS: 7.8.99
     ACTION_BUGREPORT_FROM_POWER_MENU_INTERACTIVE = 292;
 
-    // Full bug report initiated from power menu.
+    // ACTION: Long-press power button, then long-press "Take bug report" option.
+    // CATEGORY: GLOBAL_SYSTEM_UI
+    // OS: N
+    // GMS: 7.8.99
     ACTION_BUGREPORT_FROM_POWER_MENU_FULL = 293;
 
+    // ACTION: Settings -> Developer Options -> Take bug report -> Interactive report
+    // CATEGORY: SETTINGS
+    // OS: N
+    // GMS: 7.8.99
     // Interactive bug report initiated from Settings.
     ACTION_BUGREPORT_FROM_SETTINGS_INTERACTIVE = 294;
 
-    // Full bug report initiated from Settings.
+    // ACTION: Settings -> Developer Options -> Take bug report -> Full report
+    // CATEGORY: SETTINGS
+    // OS: N
+    // GMS: 7.8.99
+    // Interactive bug report initiated from Settings.
     ACTION_BUGREPORT_FROM_SETTINGS_FULL = 295;
 
-    // Bug report canceled using system notification.
+    // ACTION: User tapped notification action to cancel a bug report
+    // CATEGORY: NOTIFICATION
+    // OS: N
+    // GMS: 7.8.99
     ACTION_BUGREPORT_NOTIFICATION_ACTION_CANCEL = 296;
 
-    // Bug report details screen open using system notification.
+    // ACTION: User tapped notification action to launch bug report details screen
+    // CATEGORY: NOTIFICATION
+    // OS: N
+    // GMS: 7.8.99
     ACTION_BUGREPORT_NOTIFICATION_ACTION_DETAILS = 297;
 
-    // Additional Bug report screen shot taken using system notification.
+    // ACTION: User tapped notification action to take adition screenshot on bug report
+    // CATEGORY: NOTIFICATION
+    // OS: N
+    // GMS: 7.8.99
     ACTION_BUGREPORT_NOTIFICATION_ACTION_SCREENSHOT = 298;
 
-    // Bug report shared by user using system notification.
+    // ACTION: User tapped notification to share bug report
+    // CATEGORY: NOTIFICATION
+    // OS: N
+    // GMS: 7.8.99
     ACTION_BUGREPORT_NOTIFICATION_ACTION_SHARE = 299;
 
-    // User changed bug report name using the details screen.
+    // ACTION: User changed bug report name using the details screen
+    // CATEGORY: GLOBAL_SYSTEM_UI
+    // OS: N
+    // GMS: 7.8.99
     ACTION_BUGREPORT_DETAILS_NAME_CHANGED = 300;
 
-    // User changed bug report title using the details screen.
+    // ACTION: User changed bug report title using the details screen
+    // CATEGORY: GLOBAL_SYSTEM_UI
+    // OS: N
+    // GMS: 7.8.99
     ACTION_BUGREPORT_DETAILS_TITLE_CHANGED = 301;
 
-    // User changed bug report description using the details screen.
+    // ACTION: User changed bug report description using the details screen
+    // CATEGORY: GLOBAL_SYSTEM_UI
+    // OS: N
+    // GMS: 7.8.99
     ACTION_BUGREPORT_DETAILS_DESCRIPTION_CHANGED = 302;
 
-    // Changes made on bug report details screen were saved by user.
+    // ACTION: User tapped Save in the bug report details screen.
+    // CATEGORY: GLOBAL_SYSTEM_UI
+    // OS: N
+    // GMS: 7.8.99
     ACTION_BUGREPORT_DETAILS_SAVED = 303;
 
-    // Changes made on bug report details screen were canceled by user.
+    // ACTION: User tapped Cancel in the bug report details screen.
+    // CATEGORY: GLOBAL_SYSTEM_UI
+    // OS: N
+    // GMS: 7.8.99
     ACTION_BUGREPORT_DETAILS_CANCELED = 304;
 
     // Tuner: Open/close calibrate dialog.
@@ -450,5 +1891,112 @@
 
     // Logged when a user double taps the overview button to launch the previous task
     OVERVIEW_LAUNCH_PREVIOUS_TASK = 318;
+
+    // Logged when we execute an app transition. This indicates the total delay from startActivity
+    // until the app transition is starting to animate, in milliseconds.
+    APP_TRANSITION_DELAY_MS = 319;
+
+    // Logged when we execute an app transition. This indicates the reason why the transition
+    // started. Must be one of ActivityManagerInternal.APP_TRANSITION_* reasons.
+    APP_TRANSITION_REASON = 320;
+
+    // Logged when we execute an app transition and we drew a starting window. This indicates the
+    // delay from startActivity until the starting window was drawn.
+    APP_TRANSITION_STARTING_WINDOW_DELAY_MS = 321;
+
+    // Logged when we execute an app transition and all windows of the app got drawn. This indicates
+    // the delay from startActivity until all windows have been drawn.
+    APP_TRANSITION_WINDOWS_DRAWN_DELAY_MS = 322;
+
+    // Logged when we execute an app transition. This indicates the component name of the current
+    // transition.
+    APP_TRANSITION_COMPONENT_NAME = 323;
+
+    // Logged when we execute an app transition. This indicates whether the process was already
+    // running.
+    APP_TRANSITION_PROCESS_RUNNING = 324;
+
+    // Logged when we execute an app transition. This indicates the device uptime in seconds when
+    // the transition was executed.
+    APP_TRANSITION_DEVICE_UPTIME_SECONDS = 325;
+
+    // User granted access to the request folder; action takes an integer
+    // representing the folder's index on Environment.STANDARD_DIRECTORIES
+    ACTION_SCOPED_DIRECTORY_ACCESS_GRANTED_BY_FOLDER = 326;
+
+    // User denied access to the request folder; action takes an integer
+    // representing the folder's index on Environment.STANDARD_DIRECTORIES
+    ACTION_SCOPED_DIRECTORY_ACCESS_DENIED_BY_FOLDER = 327;
+
+    // User granted access to the request folder; action pass package name
+    // of calling package.
+    ACTION_SCOPED_DIRECTORY_ACCESS_GRANTED_BY_PACKAGE = 328;
+
+    // User denied access to the request folder; action pass package name
+    // of calling package.
+    ACTION_SCOPED_DIRECTORY_ACCESS_DENIED_BY_PACKAGE = 329;
+
+    // App requested access to a directory it has already been granted
+    // access before; action takes an integer representing the folder's
+    // index on Environment.STANDARD_DIRECTORIES
+    ACTION_SCOPED_DIRECTORY_ACCESS_ALREADY_GRANTED_BY_FOLDER = 330;
+
+    // App requested access to a directory it has already been granted
+    // access before; action pass package name of calling package.
+    ACTION_SCOPED_DIRECTORY_ACCESS_ALREADY_GRANTED_BY_PACKAGE = 331;
+
+    // Logged when the user slides a notification and
+    // reveals the gear beneath it.
+    ACTION_REVEAL_GEAR = 332;
+
+    // Logged when the user taps on the gear beneath
+    // a notification.
+    ACTION_TOUCH_GEAR = 333;
+
+    // Logs that the user has edited the enabled VR listeners.
+    VR_MANAGE_LISTENERS = 334;
+
+    // Settings -> Accessibility -> Click after pointer stops moving
+    ACCESSIBILITY_TOGGLE_AUTOCLICK = 335;
+    // Settings -> Sound
+    SOUND = 336;
+    // Settings -> Notifications -> Gear
+    CONFIGURE_NOTIFICATION = 337;
+    // Settings -> Wi-Fi -> Gear
+    CONFIGURE_WIFI = 338;
+    // Settings -> Display -> Display size
+    DISPLAY_SCREEN_ZOOM = 339;
+    // Settings -> Display -> Font size
+    ACCESSIBILITY_FONT_SIZE = 340;
+    // Settings -> Data usage -> Cellular/Wi-Fi data usage
+    DATA_USAGE_LIST = 341;
+    // Settings -> Data usage -> Billing cycle or DATA_USAGE_LIST -> Gear
+    BILLING_CYCLE = 342;
+    // DATA_USAGE_LIST -> Any item or App info -> Data usage
+    APP_DATA_USAGE = 343;
+    // Settings -> Language & input -> Language
+    USER_LOCALE_LIST = 344;
+    // Settings -> Language & input -> Virtual keyboard
+    VIRTUAL_KEYBOARDS = 345;
+    // Settings -> Language & input -> Physical keyboard
+    PHYSICAL_KEYBOARDS = 346;
+    // Settings -> Language & input -> Virtual keyboard -> Add a virtual keyboard
+    ENABLE_VIRTUAL_KEYBOARDS = 347;
+    // Settings -> Data usage -> Data Saver
+    DATA_SAVER_SUMMARY = 348;
+    // Settings -> Data usage -> Data Saver -> Unrestricted data access
+    DATA_USAGE_UNRESTRICTED_ACCESS = 349;
+
+    // Used for generic logging of Settings Preference Persistence, should not be used
+    // outside SharedPreferencesLogger.
+    ACTION_GENERIC_PACKAGE = 350;
+    // Settings -> Apps -> Gear -> Special access
+    SPECIAL_ACCESS = 351;
+
+    // Logs that the user docks window via shortcut key.
+    WINDOW_DOCK_SHORTCUTS = 352;
+
+    // Add new aosp constants above this line.
+    // END OF AOSP CONSTANTS
   }
 }
diff --git a/rs/java/android/renderscript/Allocation.java b/rs/java/android/renderscript/Allocation.java
index 8c78a3a..fc92966 100644
--- a/rs/java/android/renderscript/Allocation.java
+++ b/rs/java/android/renderscript/Allocation.java
@@ -115,7 +115,7 @@
 
         if (cmp == Short.TYPE) {
             if (checkType) {
-                validateIsInt16();
+                validateIsInt16OrFloat16();
                 return mType.mElement.mType;
             }
             return Element.DataType.SIGNED_16;
@@ -402,9 +402,10 @@
             "32 bit integer source does not match allocation type " + mType.mElement.mType);
     }
 
-    private void validateIsInt16() {
+    private void validateIsInt16OrFloat16() {
         if ((mType.mElement.mType == Element.DataType.SIGNED_16) ||
-            (mType.mElement.mType == Element.DataType.UNSIGNED_16)) {
+            (mType.mElement.mType == Element.DataType.UNSIGNED_16) ||
+            (mType.mElement.mType == Element.DataType.FLOAT_16)) {
             return;
         }
         throw new RSIllegalArgumentException(
@@ -751,7 +752,7 @@
      * @param d the source data array
      */
     public void copyFrom(short[] d) {
-        validateIsInt16();
+        validateIsInt16OrFloat16();
         copyFromUnchecked(d, Element.DataType.SIGNED_16, d.length);
     }
 
@@ -1060,7 +1061,7 @@
      * @param d the source data array
      */
     public void copy1DRangeFrom(int off, int count, short[] d) {
-        validateIsInt16();
+        validateIsInt16OrFloat16();
         copy1DRangeFromUnchecked(off, count, d, Element.DataType.SIGNED_16, d.length);
     }
 
@@ -1204,7 +1205,7 @@
      * @param data to be placed into the Allocation
      */
     public void copy2DRangeFrom(int xoff, int yoff, int w, int h, short[] data) {
-        validateIsInt16();
+        validateIsInt16OrFloat16();
         copy2DRangeFromUnchecked(xoff, yoff, w, h, data,
                                  Element.DataType.SIGNED_16, data.length);
     }
@@ -1473,7 +1474,7 @@
      * @param d The array to be set from the Allocation.
      */
     public void copyTo(short[] d) {
-        validateIsInt16();
+        validateIsInt16OrFloat16();
         copyTo(d, Element.DataType.SIGNED_16, d.length);
     }
 
@@ -1693,7 +1694,7 @@
      * @param d the source data array
      */
     public void copy1DRangeTo(int off, int count, short[] d) {
-        validateIsInt16();
+        validateIsInt16OrFloat16();
         copy1DRangeToUnchecked(off, count, d, Element.DataType.SIGNED_16, d.length);
     }
 
@@ -1794,7 +1795,7 @@
      * @param data Dest Array to be copied into
      */
     public void copy2DRangeTo(int xoff, int yoff, int w, int h, short[] data) {
-        validateIsInt16();
+        validateIsInt16OrFloat16();
         copy2DRangeToUnchecked(xoff, yoff, w, h, data,
                                Element.DataType.SIGNED_16, data.length);
     }
diff --git a/rs/jni/android_renderscript_RenderScript.cpp b/rs/jni/android_renderscript_RenderScript.cpp
index 3bef19e..4e667c6 100644
--- a/rs/jni/android_renderscript_RenderScript.cpp
+++ b/rs/jni/android_renderscript_RenderScript.cpp
@@ -151,6 +151,7 @@
         return;                                                                         \
     case RS_TYPE_SIGNED_16:                                                             \
     case RS_TYPE_UNSIGNED_16:                                                           \
+    case RS_TYPE_FLOAT_16:                                                              \
         len = _env->GetArrayLength((jshortArray)data);                                  \
         ptr = _env->GetShortArrayElements((jshortArray)data, flag);                     \
         if (ptr == nullptr) {                                                           \
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityGestureDetector.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityGestureDetector.java
index ad70853..3ac81f6 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityGestureDetector.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityGestureDetector.java
@@ -37,7 +37,8 @@
 
 /**
  * This class handles gesture detection for the Touch Explorer.  It collects
- * touch events, and sends events to mListener as gestures are recognized.
+ * touch events and determines when they match a gesture, as well as when they
+ * won't match a gesture.  These state changes are then surfaced to mListener.
  */
 class AccessibilityGestureDetector extends GestureDetector.SimpleOnGestureListener {
 
@@ -46,12 +47,66 @@
     // Tag for logging received events.
     private static final String LOG_TAG = "AccessibilityGestureDetector";
 
+    /**
+     * Listener functions are called as a result of onMoveEvent().  The current
+     * MotionEvent in the context of these functions is the event passed into
+     * onMotionEvent.
+     */
     public interface Listener {
-        public void onDoubleTapAndHold(MotionEvent event, int policyFlags);
-        public boolean onDoubleTap(MotionEvent event, int policyFlags);
-        public boolean onGestureCompleted(int gestureId);
-        public void onGestureStarted();
-        public void onGestureCancelled(MotionEvent event, int policyFlags);
+        /**
+         * Called when the user has performed a double tap and then held down
+         * the second tap.
+         *
+         * @param event The most recent MotionEvent received.
+         * @param policyFlags The policy flags of the most recent event.
+         */
+        void onDoubleTapAndHold(MotionEvent event, int policyFlags);
+
+        /**
+         * Called when the user touches the screen on the second tap of a double
+         * tap.
+         *
+         * @return true if the event is consumed, else false
+         */
+        boolean onDoubleTapStarted();
+
+        /**
+         * Called when the user lifts their finger on the second tap of a double
+         * tap.
+         *
+         * @param event The most recent MotionEvent received.
+         * @param policyFlags The policy flags of the most recent event.
+         *
+         * @return true if the event is consumed, else false
+         */
+        boolean onDoubleTap(MotionEvent event, int policyFlags);
+
+        /**
+         * Called when the system has decided the event stream is a gesture.
+         *
+         * @return true if the event is consumed, else false
+         */
+        boolean onGestureStarted();
+
+        /**
+         * Called when an event stream is recognized as a gesture.
+         *
+         * @param gestureId ID of the gesture that was recognized.
+         *
+         * @return true if the event is consumed, else false
+         */
+        boolean onGestureCompleted(int gestureId);
+
+        /**
+         * Called when the system has decided an event stream doesn't match any
+         * known gesture.
+         *
+         * @param event The most recent MotionEvent received.
+         * @param policyFlags The policy flags of the most recent event.
+         *
+         * @return true if the event is consumed, else false
+         */
+        public boolean onGestureCancelled(MotionEvent event, int policyFlags);
     }
 
     private final Listener mListener;
@@ -121,9 +176,9 @@
     // movement when gesturing, and touch exploring.  Based on user testing,
     // all gestures started with the initial movement taking less than 100ms.
     // When touch exploring, the first movement almost always takes longer than
-    // 200ms.  From this data, 150ms seems the best value to decide what
+    // 200ms.  From this data, 200ms seems the best value to decide what
     // kind of interaction it is.
-    private static final long CANCEL_ON_PAUSE_THRESHOLD_NOT_STARTED_MS = 150;
+    private static final long CANCEL_ON_PAUSE_THRESHOLD_NOT_STARTED_MS = 200;
 
     // Time threshold used to determine if a gesture should be cancelled.  If
     // the finger pauses for longer than this delay, the ongoing gesture is
@@ -145,6 +200,18 @@
                 context.getResources().getDisplayMetrics()) * GESTURE_CONFIRM_MM;
     }
 
+    /**
+     * Handle a motion event.  If an action is completed, the appropriate
+     * callback on mListener is called, and the return value of the callback is
+     * passed to the caller.
+     *
+     * @param event The raw motion event.  It's important that this be the raw
+     * event, before any transformations have been applied, so that measurements
+     * can be made in physical units.
+     * @param policyFlags Policy flags for the event.
+     *
+     * @return true if the event is consumed, else false
+     */
     public boolean onMotionEvent(MotionEvent event, int policyFlags) {
         final float x = event.getX();
         final float y = event.getY();
@@ -183,7 +250,7 @@
                         // the event.
                         if (!mGestureStarted) {
                             mGestureStarted = true;
-                            mListener.onGestureStarted();
+                            return mListener.onGestureStarted();
                         }
                     } else {
                         final long timeDelta = time - mBaseTime;
@@ -195,8 +262,7 @@
                         // timeout, cancel gesture detection.
                         if (timeDelta > threshold) {
                             cancelGesture();
-                            mListener.onGestureCancelled(event, policyFlags);
-                            return false;
+                            return mListener.onGestureCancelled(event, policyFlags);
                         }
                     }
 
@@ -211,16 +277,13 @@
                 break;
 
             case MotionEvent.ACTION_UP:
-                if (maybeFinishDoubleTap(event, policyFlags)) {
-                    return true;
+                if (mDoubleTapDetected) {
+                    return finishDoubleTap(event, policyFlags);
                 }
                 if (mGestureStarted) {
                     mStrokeBuffer.add(new GesturePoint(x, y, time));
 
-                    if (!recognizeGesture()) {
-                        mListener.onGestureCancelled(event, policyFlags);
-                    }
-                    return true;
+                    return recognizeGesture(event, policyFlags);
                 }
                 break;
 
@@ -244,8 +307,8 @@
             case MotionEvent.ACTION_POINTER_UP:
                 // If we're detecting taps on the second finger, see if we
                 // should finish the double tap.
-                if (mSecondFingerDoubleTap && maybeFinishDoubleTap(event, policyFlags)) {
-                    return true;
+                if (mSecondFingerDoubleTap && mDoubleTapDetected) {
+                    return finishDoubleTap(event, policyFlags);
                 }
                 break;
 
@@ -308,7 +371,7 @@
         // The processing of the double tap is deferred until the finger is
         // lifted, so that we can detect a long press on the second tap.
         mDoubleTapDetected = true;
-        return true;
+        return mListener.onDoubleTapStarted();
     }
 
     private void maybeSendLongPress(MotionEvent event, int policyFlags) {
@@ -321,11 +384,7 @@
         mListener.onDoubleTapAndHold(event, policyFlags);
     }
 
-    private boolean maybeFinishDoubleTap(MotionEvent event, int policyFlags) {
-        if (!mDoubleTapDetected) {
-            return false;
-        }
-
+    private boolean finishDoubleTap(MotionEvent event, int policyFlags) {
         clear();
 
         return mListener.onDoubleTap(event, policyFlags);
@@ -337,7 +396,7 @@
         mStrokeBuffer.clear();
     }
 
-    private boolean recognizeGesture() {
+    private boolean recognizeGesture(MotionEvent event, int policyFlags) {
         Gesture gesture = new Gesture();
         gesture.addStroke(new GestureStroke(mStrokeBuffer));
 
@@ -351,16 +410,14 @@
                 }
                 try {
                     final int gestureId = Integer.parseInt(bestPrediction.name);
-                    if (mListener.onGestureCompleted(gestureId)) {
-                        return true;
-                    }
+                    return mListener.onGestureCompleted(gestureId);
                 } catch (NumberFormatException nfe) {
                     Slog.w(LOG_TAG, "Non numeric gesture id:" + bestPrediction.name);
                 }
             }
         }
 
-        return false;
+        return mListener.onGestureCancelled(event, policyFlags);
     }
 
     private MotionEvent mapSecondPointerToFirstPointer(MotionEvent event) {
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
index 2b682c5..b4b40ae 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -655,10 +655,9 @@
             userState.mUiAutomationServiceOwner = owner;
             userState.mUiAutomationServiceClient = serviceClient;
             userState.mUiAutomationFlags = flags;
-            userState.mIsAccessibilityEnabled = true;
             userState.mInstalledServices.add(accessibilityServiceInfo);
             if ((flags & UiAutomation.FLAG_DONT_SUPPRESS_ACCESSIBILITY_SERVICES) == 0) {
-                // Set the temporary state.
+                // Set the temporary state, and use it instead of settings
                 userState.mIsTouchExplorationEnabled = false;
                 userState.mIsEnhancedWebAccessibilityEnabled = false;
                 userState.mIsDisplayMagnificationEnabled = false;
@@ -709,7 +708,6 @@
                 return;
             }
 
-            userState.mIsAccessibilityEnabled = true;
             userState.mIsTouchExplorationEnabled = touchExplorationEnabled;
             userState.mIsEnhancedWebAccessibilityEnabled = false;
             userState.mIsDisplayMagnificationEnabled = false;
@@ -1245,17 +1243,17 @@
         }
     }
 
-    private void manageServicesLocked(UserState userState) {
+    private void updateServicesLocked(UserState userState) {
         Map<ComponentName, Service> componentNameToServiceMap =
                 userState.mComponentNameToServiceMap;
         boolean isUnlocked = mContext.getSystemService(UserManager.class)
                 .isUserUnlocked(userState.mUserId);
-        boolean isEnabled = userState.mIsAccessibilityEnabled;
 
         for (int i = 0, count = userState.mInstalledServices.size(); i < count; i++) {
             AccessibilityServiceInfo installedService = userState.mInstalledServices.get(i);
             ComponentName componentName = ComponentName.unflattenFromString(
                     installedService.getId());
+
             Service service = componentNameToServiceMap.get(componentName);
 
             // Ignore non-encryption-aware services until user is unlocked
@@ -1264,45 +1262,25 @@
                 continue;
             }
 
-            if (isEnabled) {
-                // Wait for the binding if it is in process.
-                if (userState.mBindingServices.contains(componentName)) {
+            // Wait for the binding if it is in process.
+            if (userState.mBindingServices.contains(componentName)) {
+                continue;
+            }
+            if (userState.mEnabledServices.contains(componentName)) {
+                if (service == null) {
+                    service = new Service(userState.mUserId, componentName, installedService);
+                } else if (userState.mBoundServices.contains(service)) {
                     continue;
                 }
-                if (userState.mEnabledServices.contains(componentName)) {
-                    if (service == null) {
-                        service = new Service(userState.mUserId, componentName, installedService);
-                    } else if (userState.mBoundServices.contains(service)) {
-                        continue;
-                    }
-                    service.bindLocked();
-                } else {
-                    if (service != null) {
-                        service.unbindLocked();
-                    }
-                }
+                service.bindLocked();
             } else {
                 if (service != null) {
                     service.unbindLocked();
-                } else {
-                    userState.mBindingServices.remove(componentName);
                 }
             }
         }
 
-        // No enabled installed services => disable accessibility to avoid
-        // sending accessibility events with no recipient across processes.
-        if (isEnabled && isUnlocked && userState.mBoundServices.isEmpty()
-                && userState.mBindingServices.isEmpty()) {
-            userState.mIsAccessibilityEnabled = false;
-            final long identity = Binder.clearCallingIdentity();
-            try {
-                Settings.Secure.putIntForUser(mContext.getContentResolver(),
-                        Settings.Secure.ACCESSIBILITY_ENABLED, 0, userState.mUserId);
-            } finally {
-                Binder.restoreCallingIdentity(identity);
-            }
-        }
+        updateAccessibilityEnabledSetting(userState);
     }
 
     private void scheduleUpdateClientsIfNeededLocked(UserState userState) {
@@ -1329,7 +1307,8 @@
                 flags |= AccessibilityInputFilter.FLAG_FEATURE_SCREEN_MAGNIFIER;
             }
             // Touch exploration without accessibility makes no sense.
-            if (userState.mIsAccessibilityEnabled && userState.mIsTouchExplorationEnabled) {
+            if (userState.isHandlingAccessibilityEvents()
+                    && userState.mIsTouchExplorationEnabled) {
                 flags |= AccessibilityInputFilter.FLAG_FEATURE_TOUCH_EXPLORATION;
             }
             if (userState.mIsFilterKeyEventsEnabled) {
@@ -1468,25 +1447,17 @@
     }
 
     private void updateWindowsForAccessibilityCallbackLocked(UserState userState) {
-        if (userState.mIsAccessibilityEnabled) {
-            // We observe windows for accessibility only if there is at least
-            // one bound service that can retrieve window content that specified
-            // it is interested in accessing such windows. For services that are
-            // binding we do an update pass after each bind event, so we run this
-            // code and register the callback if needed.
-            boolean boundServiceCanRetrieveInteractiveWindows = false;
+        // We observe windows for accessibility only if there is at least
+        // one bound service that can retrieve window content that specified
+        // it is interested in accessing such windows. For services that are
+        // binding we do an update pass after each bind event, so we run this
+        // code and register the callback if needed.
 
-            List<Service> boundServices = userState.mBoundServices;
-            final int boundServiceCount = boundServices.size();
-            for (int i = 0; i < boundServiceCount; i++) {
-                Service boundService = boundServices.get(i);
-                if (boundService.canRetrieveInteractiveWindowsLocked()) {
-                    boundServiceCanRetrieveInteractiveWindows = true;
-                    break;
-                }
-            }
-
-            if (boundServiceCanRetrieveInteractiveWindows) {
+        List<Service> boundServices = userState.mBoundServices;
+        final int boundServiceCount = boundServices.size();
+        for (int i = 0; i < boundServiceCount; i++) {
+            Service boundService = boundServices.get(i);
+            if (boundService.canRetrieveInteractiveWindowsLocked()) {
                 if (mWindowsForAccessibilityCallback == null) {
                     mWindowsForAccessibilityCallback = new WindowsForAccessibilityCallback();
                     mWindowManagerService.setWindowsForAccessibilityCallback(
@@ -1554,37 +1525,30 @@
         userState.mIsFilterKeyEventsEnabled = false;
     }
 
-    private void updateServicesLocked(UserState userState) {
-        if (userState.mIsAccessibilityEnabled) {
-            manageServicesLocked(userState);
-        } else {
-            unbindAllServicesLocked(userState);
-        }
-    }
-
     private boolean readConfigurationForUserStateLocked(UserState userState) {
-        boolean somthingChanged = readAccessibilityEnabledSettingLocked(userState);
-        somthingChanged |= readInstalledAccessibilityServiceLocked(userState);
-        somthingChanged |= readEnabledAccessibilityServicesLocked(userState);
-        somthingChanged |= readTouchExplorationGrantedAccessibilityServicesLocked(userState);
-        somthingChanged |= readTouchExplorationEnabledSettingLocked(userState);
-        somthingChanged |= readHighTextContrastEnabledSettingLocked(userState);
-        somthingChanged |= readEnhancedWebAccessibilityEnabledChangedLocked(userState);
-        somthingChanged |= readDisplayMagnificationEnabledSettingLocked(userState);
-        somthingChanged |= readAutoclickEnabledSettingLocked(userState);
-        somthingChanged |= readDisplayColorAdjustmentSettingsLocked(userState);
-        return somthingChanged;
+        boolean somethingChanged = readInstalledAccessibilityServiceLocked(userState);
+        somethingChanged |= readEnabledAccessibilityServicesLocked(userState);
+        somethingChanged |= readTouchExplorationGrantedAccessibilityServicesLocked(userState);
+        somethingChanged |= readTouchExplorationEnabledSettingLocked(userState);
+        somethingChanged |= readHighTextContrastEnabledSettingLocked(userState);
+        somethingChanged |= readEnhancedWebAccessibilityEnabledChangedLocked(userState);
+        somethingChanged |= readDisplayMagnificationEnabledSettingLocked(userState);
+        somethingChanged |= readAutoclickEnabledSettingLocked(userState);
+        somethingChanged |= readDisplayColorAdjustmentSettingsLocked(userState);
+
+        return somethingChanged;
     }
 
-    private boolean readAccessibilityEnabledSettingLocked(UserState userState) {
-        final boolean accessibilityEnabled = Settings.Secure.getIntForUser(
-               mContext.getContentResolver(),
-               Settings.Secure.ACCESSIBILITY_ENABLED, 0, userState.mUserId) == 1;
-        if (accessibilityEnabled != userState.mIsAccessibilityEnabled) {
-            userState.mIsAccessibilityEnabled = accessibilityEnabled;
-            return true;
+    private void updateAccessibilityEnabledSetting(UserState userState) {
+        final long identity = Binder.clearCallingIdentity();
+        try {
+            Settings.Secure.putIntForUser(mContext.getContentResolver(),
+                    Settings.Secure.ACCESSIBILITY_ENABLED,
+                    userState.isHandlingAccessibilityEvents() ? 0 : 1,
+                    userState.mUserId);
+        } finally {
+            Binder.restoreCallingIdentity(identity);
         }
-        return false;
     }
 
     private boolean readTouchExplorationEnabledSettingLocked(UserState userState) {
@@ -1768,14 +1732,14 @@
     private void updateMagnificationLocked(UserState userState) {
         final int userId = userState.mUserId;
         if (userId == mCurrentUserId && mMagnificationController != null) {
-            if (userHasMagnificationServicesLocked(userState)) {
+            if (userState.mIsDisplayMagnificationEnabled ||
+                    userHasMagnificationServicesLocked(userState)) {
                 mMagnificationController.setUserId(userState.mUserId);
             } else {
                 // If the user no longer has any magnification-controlling
                 // services and is not using magnification gestures, then
                 // reset the state to normal.
-                if (!userState.mIsDisplayMagnificationEnabled
-                        && mMagnificationController.resetIfNeeded(true)) {
+                if (mMagnificationController.resetIfNeeded(true)) {
                     // Animations are still running, so wait until we receive a
                     // callback verifying that we've reset magnification.
                     mUnregisterMagnificationOnReset = true;
@@ -1809,7 +1773,7 @@
             // Check whether any Accessibility Services are still enabled and, if not, remove flag
             // requesting no soft keyboard
             final boolean accessibilityRequestingNoIme = userState.mSoftKeyboardShowMode == 1;
-            if (accessibilityRequestingNoIme && !userState.mIsAccessibilityEnabled) {
+            if (accessibilityRequestingNoIme && !userState.isHandlingAccessibilityEvents()) {
                 // No active Accessibility Services can be requesting the soft keyboard to be hidden
                 Settings.Secure.putIntForUser(mContext.getContentResolver(),
                         Settings.Secure.ACCESSIBILITY_SOFT_KEYBOARD_MODE,
@@ -1853,7 +1817,6 @@
                 UserState userState = mUserStates.valueAt(i);
                 pw.append("User state[attributes:{id=" + userState.mUserId);
                 pw.append(", currentUser=" + (userState.mUserId == mCurrentUserId));
-                pw.append(", accessibilityEnabled=" + userState.mIsAccessibilityEnabled);
                 pw.append(", touchExplorationEnabled=" + userState.mIsTouchExplorationEnabled);
                 pw.append(", displayMagnificationEnabled="
                         + userState.mIsDisplayMagnificationEnabled);
@@ -2003,7 +1966,7 @@
         private void announceNewUserIfNeeded() {
             synchronized (mLock) {
                 UserState userState = getCurrentUserStateLocked();
-                if (userState.mIsAccessibilityEnabled) {
+                if (userState.isHandlingAccessibilityEvents()) {
                     UserManager userManager = (UserManager) mContext.getSystemService(
                             Context.USER_SERVICE);
                     String message = mContext.getString(R.string.user_switched,
@@ -3473,7 +3436,8 @@
                 case WindowManager.LayoutParams.TYPE_SYSTEM_ALERT:
                 case WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG:
                 case WindowManager.LayoutParams.TYPE_SYSTEM_ERROR:
-                case WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY: {
+                case WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY:
+                case WindowManager.LayoutParams.TYPE_SCREENSHOT: {
                     return AccessibilityWindowInfo.TYPE_SYSTEM;
                 }
 
@@ -4061,7 +4025,6 @@
 
         public int mSoftKeyboardShowMode = 0;
 
-        public boolean mIsAccessibilityEnabled;
         public boolean mIsTouchExplorationEnabled;
         public boolean mIsTextHighContrastEnabled;
         public boolean mIsEnhancedWebAccessibilityEnabled;
@@ -4096,11 +4059,11 @@
 
         public int getClientState() {
             int clientState = 0;
-            if (mIsAccessibilityEnabled) {
+            if (isHandlingAccessibilityEvents()) {
                 clientState |= AccessibilityManager.STATE_FLAG_ACCESSIBILITY_ENABLED;
             }
             // Touch exploration relies on enabled accessibility.
-            if (mIsAccessibilityEnabled && mIsTouchExplorationEnabled) {
+            if (isHandlingAccessibilityEvents() && mIsTouchExplorationEnabled) {
                 clientState |= AccessibilityManager.STATE_FLAG_TOUCH_EXPLORATION_ENABLED;
             }
             if (mIsTextHighContrastEnabled) {
@@ -4109,6 +4072,10 @@
             return clientState;
         }
 
+        public boolean isHandlingAccessibilityEvents() {
+            return !mBoundServices.isEmpty() || !mBoundServices.isEmpty();
+        }
+
         public void onSwitchToAnotherUser() {
             // Clear UI test automation state.
             if (mUiAutomationService != null) {
@@ -4128,7 +4095,6 @@
             // Clear state persisted in settings.
             mEnabledServices.clear();
             mTouchExplorationGrantedServices.clear();
-            mIsAccessibilityEnabled = false;
             mIsTouchExplorationEnabled = false;
             mIsEnhancedWebAccessibilityEnabled = false;
             mIsDisplayMagnificationEnabled = false;
@@ -4155,9 +4121,6 @@
 
     private final class AccessibilityContentObserver extends ContentObserver {
 
-        private final Uri mAccessibilityEnabledUri = Settings.Secure.getUriFor(
-                Settings.Secure.ACCESSIBILITY_ENABLED);
-
         private final Uri mTouchExplorationEnabledUri = Settings.Secure.getUriFor(
                 Settings.Secure.TOUCH_EXPLORATION_ENABLED);
 
@@ -4199,8 +4162,6 @@
         }
 
         public void register(ContentResolver contentResolver) {
-            contentResolver.registerContentObserver(mAccessibilityEnabledUri,
-                    false, this, UserHandle.USER_ALL);
             contentResolver.registerContentObserver(mTouchExplorationEnabledUri,
                     false, this, UserHandle.USER_ALL);
             contentResolver.registerContentObserver(mDisplayMagnificationEnabledUri,
@@ -4240,11 +4201,7 @@
                     return;
                 }
 
-                if (mAccessibilityEnabledUri.equals(uri)) {
-                    if (readAccessibilityEnabledSettingLocked(userState)) {
-                        onUserStateChangedLocked(userState);
-                    }
-                } else if (mTouchExplorationEnabledUri.equals(uri)) {
+                if (mTouchExplorationEnabledUri.equals(uri)) {
                     if (readTouchExplorationEnabledSettingLocked(userState)) {
                         onUserStateChangedLocked(userState);
                     }
diff --git a/services/accessibility/java/com/android/server/accessibility/TouchExplorer.java b/services/accessibility/java/com/android/server/accessibility/TouchExplorer.java
index 3ecff40..cd8b792 100644
--- a/services/accessibility/java/com/android/server/accessibility/TouchExplorer.java
+++ b/services/accessibility/java/com/android/server/accessibility/TouchExplorer.java
@@ -390,6 +390,11 @@
     }
 
     @Override
+    public boolean onDoubleTapStarted() {
+        return true;
+    }
+
+    @Override
     public boolean onDoubleTap(MotionEvent event, int policyFlags) {
         // Ignore the event if we aren't touch exploring.
         if (mCurrentState != STATE_TOUCH_EXPLORING) {
@@ -437,6 +442,20 @@
     }
 
     @Override
+    public boolean onGestureStarted() {
+      // We have to perform gesture detection, so
+      // clear the current state and try to detect.
+      mCurrentState = STATE_GESTURE_DETECTING;
+      mSendHoverEnterAndMoveDelayed.cancel();
+      mSendHoverExitDelayed.cancel();
+      mExitGestureDetectionModeDelayed.post();
+      // Send accessibility event to announce the start
+      // of gesture recognition.
+      sendAccessibilityEvent(AccessibilityEvent.TYPE_GESTURE_DETECTION_START);
+      return false;
+    }
+
+    @Override
     public boolean onGestureCompleted(int gestureId) {
         if (mCurrentState != STATE_GESTURE_DETECTING) {
             return false;
@@ -450,36 +469,26 @@
     }
 
     @Override
-    public void onGestureStarted() {
-      // We have to perform gesture detection, so
-      // clear the current state and try to detect.
-      mCurrentState = STATE_GESTURE_DETECTING;
-      mSendHoverEnterAndMoveDelayed.cancel();
-      mSendHoverExitDelayed.cancel();
-      mExitGestureDetectionModeDelayed.post();
-      // Send accessibility event to announce the start
-      // of gesture recognition.
-      sendAccessibilityEvent(AccessibilityEvent.TYPE_GESTURE_DETECTION_START);
-    }
+    public boolean onGestureCancelled(MotionEvent event, int policyFlags) {
+        if (mCurrentState == STATE_GESTURE_DETECTING) {
+            endGestureDetection();
+            return true;
+        } else if (mCurrentState == STATE_TOUCH_EXPLORING) {
+            // If the finger is still moving, pass the event on.
+            if (event.getActionMasked() == MotionEvent.ACTION_MOVE) {
+                final int pointerId = mReceivedPointerTracker.getPrimaryPointerId();
+                final int pointerIdBits = (1 << pointerId);
 
-    @Override
-    public void onGestureCancelled(MotionEvent event, int policyFlags) {
-      if (mCurrentState == STATE_GESTURE_DETECTING) {
-          endGestureDetection();
-      } else if (mCurrentState == STATE_TOUCH_EXPLORING) {
-          // If the finger is still moving, pass the event on.
-          if (event.getActionMasked() == MotionEvent.ACTION_MOVE) {
-              final int pointerId = mReceivedPointerTracker.getPrimaryPointerId();
-              final int pointerIdBits = (1 << pointerId);
-
-              // We have just decided that the user is touch,
-              // exploring so start sending events.
-              mSendHoverEnterAndMoveDelayed.addEvent(event);
-              mSendHoverEnterAndMoveDelayed.forceSendAndRemove();
-              mSendHoverExitDelayed.cancel();
-              sendMotionEvent(event, MotionEvent.ACTION_HOVER_MOVE, pointerIdBits, policyFlags);
-          }
-      }
+                // We have just decided that the user is touch,
+                // exploring so start sending events.
+                mSendHoverEnterAndMoveDelayed.addEvent(event);
+                mSendHoverEnterAndMoveDelayed.forceSendAndRemove();
+                mSendHoverExitDelayed.cancel();
+                sendMotionEvent(event, MotionEvent.ACTION_HOVER_MOVE, pointerIdBits, policyFlags);
+                return true;
+            }
+        }
+        return false;
     }
 
     /**
diff --git a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
index f537d18..3659a40 100644
--- a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
+++ b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
@@ -16,9 +16,14 @@
 
 package com.android.server.appwidget;
 
+import static android.content.Context.KEYGUARD_SERVICE;
+import static android.content.Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS;
+import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
+
 import android.app.AlarmManager;
 import android.app.AppGlobals;
 import android.app.AppOpsManager;
+import android.app.KeyguardManager;
 import android.app.PendingIntent;
 import android.app.admin.DevicePolicyManagerInternal;
 import android.app.admin.DevicePolicyManagerInternal.OnCrossProfileWidgetProvidersChangeListener;
@@ -72,10 +77,12 @@
 import android.util.TypedValue;
 import android.util.Xml;
 import android.view.Display;
+import android.view.View;
 import android.view.WindowManager;
 import android.widget.RemoteViews;
 
 import com.android.internal.R;
+import com.android.internal.app.UnlaunchableAppActivity;
 import com.android.internal.appwidget.IAppWidgetHost;
 import com.android.internal.appwidget.IAppWidgetService;
 import com.android.internal.os.BackgroundThread;
@@ -146,7 +153,7 @@
             final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL);
 
             if (DEBUG) {
-                Slog.i(TAG, "Received broadcast: " + action);
+                Slog.i(TAG, "Received broadcast: " + action + " on user " + userId);
             }
 
             if (Intent.ACTION_CONFIGURATION_CHANGED.equals(action)) {
@@ -156,10 +163,10 @@
             } else if (Intent.ACTION_USER_STOPPED.equals(action)) {
                 onUserStopped(userId);
             } else if (Intent.ACTION_USER_SWITCHED.equals(action)) {
-                reloadWidgetsMaskedStateForUser(userId);
+                reloadWidgetsMaskedStateForGroup(userId);
             } else if (Intent.ACTION_MANAGED_PROFILE_AVAILABILITY_CHANGED.equals(action)) {
                 synchronized (mLock) {
-                    reloadWidgetProfileUnavailableMaskedStateLocked(userId);
+                    reloadWidgetsMaskedState(userId);
                 }
             } else if (Intent.ACTION_PACKAGES_SUSPENDED.equals(action)) {
                 String[] packages = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
@@ -202,6 +209,7 @@
     private final AlarmManager mAlarmManager;
     private final UserManager mUserManager;
     private final AppOpsManager mAppOpsManager;
+    private final KeyguardManager mKeyguardManager;
 
     private final SecurityPolicy mSecurityPolicy;
 
@@ -223,6 +231,7 @@
         mAlarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);
         mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
         mAppOpsManager = (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE);
+        mKeyguardManager = (KeyguardManager) mContext.getSystemService(KEYGUARD_SERVICE);
         mSaveStateHandler = BackgroundThread.getHandler();
         mCallbackHandler = new CallbackHandler(mContext.getMainLooper());
         mBackupRestoreController = new BackupRestoreController();
@@ -436,48 +445,51 @@
     /**
      * Reload all widgets' masked state for the given user and its associated profiles, including
      * due to user not being available and package suspension.
+     * userId must be the group parent.
      */
-    private void reloadWidgetsMaskedStateForUser(int userId) {
-        if (!mUserManager.isUserUnlocked(userId) ||
-                isProfileWithLockedParent(userId)) {
+    private void reloadWidgetsMaskedStateForGroup(int userId) {
+        if (!mUserManager.isUserUnlocked(userId)) {
             return;
         }
         synchronized (mLock) {
-            reloadWidgetPackageSuspensionMaskedStateLocked(userId);
+            reloadWidgetsMaskedState(userId);
             List<UserInfo> profiles = mUserManager.getEnabledProfiles(userId);
             if (profiles != null) {
                 for (int i = 0; i < profiles.size(); i++) {
                     UserInfo user  = profiles.get(i);
-                    reloadWidgetProfileUnavailableMaskedStateLocked(user.id);
-                    reloadWidgetPackageSuspensionMaskedStateLocked(user.id);
+                    reloadWidgetsMaskedState(user.id);
                 }
             }
         }
     }
 
-    /**
-     * Mask/unmask widgets in the given profile, depending on the quiet state
-     * or locked state of the profile.
-     */
-    private void reloadWidgetProfileUnavailableMaskedStateLocked(int profileId) {
+    private void reloadWidgetsMaskedState(int userId) {
         final long identity = Binder.clearCallingIdentity();
         try {
-            if (!isProfileWithUnlockedParent(profileId)) {
-                return;
-            }
-            UserInfo user  = mUserManager.getUserInfo(profileId);
-            boolean shouldMask = user.isQuietModeEnabled() ||
-                    !mUserManager.isUserUnlocked(user.getUserHandle());
+            UserInfo user  = mUserManager.getUserInfo(userId);
+
+            boolean lockedProfile = !mUserManager.isUserUnlocked(userId);
+            boolean quietProfile = user.isQuietModeEnabled();
             final int N = mProviders.size();
             for (int i = 0; i < N; i++) {
                 Provider provider = mProviders.get(i);
                 int providerUserId = provider.getUserId();
-                if (providerUserId != profileId) {
+                if (providerUserId != userId) {
                     continue;
                 }
-                if (provider.setMaskedByProfileUnavailabledLocked(shouldMask)) {
+
+                boolean changed = provider.setMaskedByLockedProfileLocked(lockedProfile);
+                changed |= provider.setMaskedByQuietProfileLocked(quietProfile);
+                try {
+                    boolean suspended = mPackageManager.isPackageSuspendedForUser(
+                            provider.info.provider.getPackageName(), provider.getUserId());
+                    changed |= provider.setMaskedBySuspendedPackageLocked(suspended);
+                } catch (RemoteException e) {
+                    Slog.e(TAG, "Failed to query application info", e);
+                }
+                if (changed) {
                     if (provider.isMaskedLocked()) {
-                        maskWidgetsViewsLocked(provider);
+                        maskWidgetsViewsLocked(provider, null);
                     } else {
                         unmaskWidgetsViewsLocked(provider);
                     }
@@ -489,33 +501,6 @@
     }
 
     /**
-     * Reload widget's masked state due to package suspension state.
-     */
-    private void reloadWidgetPackageSuspensionMaskedStateLocked(int profileId) {
-        final int N = mProviders.size();
-        for (int i = 0; i < N; i++) {
-            Provider provider = mProviders.get(i);
-            int providerUserId = provider.getUserId();
-            if (providerUserId != profileId) {
-                continue;
-            }
-            try {
-                boolean suspended = mPackageManager.isPackageSuspendedForUser(
-                        provider.info.provider.getPackageName(), provider.getUserId());
-                if (provider.setMaskedBySuspendedPackageLocked(suspended)) {
-                    if (provider.isMaskedLocked()) {
-                        maskWidgetsViewsLocked(provider);
-                    } else {
-                        unmaskWidgetsViewsLocked(provider);
-                    }
-                }
-            } catch (RemoteException e) {
-                Slog.e(TAG, "Failed to query application info", e);
-            }
-        }
-    }
-
-    /**
      * Incrementally update the masked state due to package suspension state.
      */
     private void updateWidgetPackageSuspensionMaskedState(String[] packagesArray, boolean suspended,
@@ -535,7 +520,7 @@
                 }
                 if (provider.setMaskedBySuspendedPackageLocked(suspended)) {
                     if (provider.isMaskedLocked()) {
-                        maskWidgetsViewsLocked(provider);
+                        maskWidgetsViewsLocked(provider, null);
                     } else {
                         unmaskWidgetsViewsLocked(provider);
                     }
@@ -544,14 +529,13 @@
         }
     }
 
-    private Bitmap createMaskedWidgetBitmap(Provider provider) {
+    private Bitmap createMaskedWidgetBitmap(String providerPackage, int providerUserId) {
         final long identity = Binder.clearCallingIdentity();
         try {
             // Load the unbadged application icon and pass it to the widget to appear on
             // the masked view.
-            final String providerPackage = provider.info.provider.getPackageName();
             Context userContext = mContext.createPackageContextAsUser(providerPackage, 0,
-                    UserHandle.of(provider.getUserId()));
+                    UserHandle.of(providerUserId));
             PackageManager pm = userContext.getPackageManager();
             Drawable icon = pm.getApplicationInfo(providerPackage, 0).loadUnbadgedIcon(pm);
             // Create a bitmap of the icon which is what the widget's remoteview requires.
@@ -566,18 +550,73 @@
         }
     }
 
-    private void maskWidgetsViewsLocked(Provider provider) {
-        Bitmap iconBitmap = createMaskedWidgetBitmap(provider);
+    private RemoteViews createMaskedWidgetRemoteViews(Bitmap icon, boolean showBadge,
+            PendingIntent onClickIntent) {
+        RemoteViews views = new RemoteViews(mContext.getPackageName(),
+                R.layout.work_widget_mask_view);
+        if (icon != null) {
+            views.setImageViewBitmap(R.id.work_widget_app_icon, icon);
+        }
+        if (!showBadge) {
+            views.setViewVisibility(R.id.work_widget_badge_icon, View.INVISIBLE);
+        }
+        if (onClickIntent != null) {
+            views.setOnClickPendingIntent(R.id.work_widget_mask_frame, onClickIntent);
+        }
+        return views;
+    }
+
+    /**
+     * Mask the target widget belonging to the specified provider, or all active widgets
+     * of the provider if target widget == null.
+     */
+    private void maskWidgetsViewsLocked(Provider provider, Widget targetWidget) {
+        final int widgetCount = provider.widgets.size();
+        if (widgetCount == 0) {
+            return;
+        }
+        final String providerPackage = provider.info.provider.getPackageName();
+        final int providerUserId = provider.getUserId();
+        Bitmap iconBitmap = createMaskedWidgetBitmap(providerPackage, providerUserId);
         if (iconBitmap == null) {
             return;
         }
+        final boolean showBadge;
+        final Intent onClickIntent;
+        if (provider.maskedBySuspendedPackage) {
+            final long identity = Binder.clearCallingIdentity();
+            try {
+                UserInfo userInfo = mUserManager.getUserInfo(providerUserId);
+                showBadge = userInfo.isManagedProfile();
+                onClickIntent = UnlaunchableAppActivity.createPackageSuspendedDialogIntent(
+                        providerPackage, providerUserId);
+            } finally {
+                Binder.restoreCallingIdentity(identity);
+            }
+        } else if (provider.maskedByQuietProfile) {
+            showBadge = true;
+            onClickIntent = UnlaunchableAppActivity.createInQuietModeDialogIntent(
+                    providerUserId);
+        } else /* provider.maskedByLockedProfile */ {
+            showBadge = true;
+            onClickIntent = mKeyguardManager.createConfirmDeviceCredentialIntent(null, null,
+                    providerUserId);
+            if (onClickIntent != null) {
+                onClickIntent.setFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
+            }
+        }
 
-        final int widgetCount = provider.widgets.size();
         for (int j = 0; j < widgetCount; j++) {
             Widget widget = provider.widgets.get(j);
-            if (widget.replaceWithMaskedViewsLocked(mContext, iconBitmap)) {
-                scheduleNotifyUpdateAppWidgetLocked(widget,
-                        widget.getEffectiveViewsLocked());
+            if (targetWidget != null && targetWidget != widget) continue;
+            PendingIntent intent = null;
+            if (onClickIntent != null) {
+                intent = PendingIntent.getActivity(mContext, widget.appWidgetId,
+                        onClickIntent, PendingIntent.FLAG_UPDATE_CURRENT);
+            }
+            RemoteViews views = createMaskedWidgetRemoteViews(iconBitmap, showBadge, intent);
+            if (widget.replaceWithMaskedViewsLocked(views)) {
+                scheduleNotifyUpdateAppWidgetLocked(widget, widget.getEffectiveViewsLocked());
             }
         }
     }
@@ -587,8 +626,7 @@
         for (int j = 0; j < widgetCount; j++) {
             Widget widget = provider.widgets.get(j);
             if (widget.clearMaskedViewsLocked()) {
-                scheduleNotifyUpdateAppWidgetLocked(widget,
-                        widget.getEffectiveViewsLocked());
+                scheduleNotifyUpdateAppWidgetLocked(widget, widget.getEffectiveViewsLocked());
             }
         }
     }
@@ -2458,7 +2496,7 @@
 
             return mPackageManager.queryIntentReceivers(intent,
                     intent.resolveTypeIfNeeded(mContext.getContentResolver()),
-                    flags, userId);
+                    flags, userId).getList();
         } catch (RemoteException re) {
             return Collections.emptyList();
         } finally {
@@ -2472,7 +2510,7 @@
         }
         synchronized (mLock) {
             ensureGroupStateLoadedLocked(userId);
-            reloadWidgetsMaskedStateForUser(userId);
+            reloadWidgetsMaskedStateForGroup(mSecurityPolicy.getGroupParent(userId));
 
             final int N = mProviders.size();
             for (int i = 0; i < N; i++) {
@@ -2614,10 +2652,7 @@
         // If we are adding a widget it might be for a provider that
         // is currently masked, if so mask the widget.
         if (widget.provider.isMaskedLocked()) {
-            Bitmap bitmap = createMaskedWidgetBitmap(widget.provider);
-            if (bitmap != null) {
-                widget.replaceWithMaskedViewsLocked(mContext, bitmap);
-            }
+            maskWidgetsViewsLocked(widget.provider, widget);
         } else {
             widget.clearMaskedViewsLocked();
         }
@@ -3014,7 +3049,6 @@
 
     private void onUserStopped(int userId) {
         synchronized (mLock) {
-            boolean providersChanged = false;
             boolean crossProfileWidgetsChanged = false;
 
             // Remove widgets that have both host and provider in the user.
@@ -3050,16 +3084,8 @@
                 }
             }
 
-            // Remove the providers and notify hosts in other profiles.
-            final int providerCount = mProviders.size();
-            for (int i = providerCount - 1; i >= 0; i--) {
-                Provider provider = mProviders.get(i);
-                if (provider.getUserId() == userId) {
-                    crossProfileWidgetsChanged |= !provider.widgets.isEmpty();
-                    providersChanged = true;
-                    deleteProviderLocked(provider);
-                }
-            }
+            // Leave the providers present as hosts will show the widgets
+            // masked while the user is stopped.
 
             // Remove grants for this user.
             final int grantCount = mPackagesWithBindWidgetPermission.size();
@@ -3082,11 +3108,6 @@
                 mNextAppWidgetIds.removeAt(nextIdIndex);
             }
 
-            // Announce removed provider changes to all hosts in the group.
-            if (providersChanged) {
-                scheduleNotifyGroupHostsForProvidersChangedLocked(userId);
-            }
-
             // Save state if removing a profile changed the group state.
             // Nothing will be saved if the group parent was removed.
             if (crossProfileWidgetsChanged) {
@@ -3624,7 +3645,8 @@
         PendingIntent broadcast;
         boolean zombie; // if we're in safe mode, don't prune this just because nobody references it
 
-        boolean maskedByProfileUnavailable;
+        boolean maskedByLockedProfile;
+        boolean maskedByQuietProfile;
         boolean maskedBySuspendedPackage;
 
         int tag = TAG_UNDEFINED; // for use while saving state (the index)
@@ -3656,22 +3678,29 @@
             return "Provider{" + id + (zombie ? " Z" : "") + '}';
         }
 
-        // returns true if the provider's masked state is changed as a result
-        public boolean setMaskedByProfileUnavailabledLocked(boolean masked) {
-            boolean oldMaskedState = isMaskedLocked();
-            maskedByProfileUnavailable = masked;
-            return isMaskedLocked() != oldMaskedState;
+        // returns true if it's different from previous state.
+        public boolean setMaskedByQuietProfileLocked(boolean masked) {
+            boolean oldState = maskedByQuietProfile;
+            maskedByQuietProfile = masked;
+            return masked != oldState;
         }
 
-        // returns true if the provider's masked state is changed as a result
+        // returns true if it's different from previous state.
+        public boolean setMaskedByLockedProfileLocked(boolean masked) {
+            boolean oldState = maskedByLockedProfile;
+            maskedByLockedProfile = masked;
+            return masked != oldState;
+        }
+
+        // returns true if it's different from previous state.
         public boolean setMaskedBySuspendedPackageLocked(boolean masked) {
-            boolean oldMaskedState = isMaskedLocked();
+            boolean oldState = maskedBySuspendedPackage;
             maskedBySuspendedPackage = masked;
-            return isMaskedLocked() != oldMaskedState;
+            return masked != oldState;
         }
 
         public boolean isMaskedLocked() {
-            return maskedByProfileUnavailable || maskedBySuspendedPackage;
+            return maskedByQuietProfile || maskedByLockedProfile || maskedBySuspendedPackage;
         }
     }
 
@@ -3828,14 +3857,8 @@
             return "AppWidgetId{" + appWidgetId + ':' + host + ':' + provider + '}';
         }
 
-        private boolean replaceWithMaskedViewsLocked(Context context, Bitmap icon) {
-            if (maskedViews != null) {
-                return false;
-            }
-            maskedViews = new RemoteViews(context.getPackageName(), R.layout.work_widget_mask_view);
-            if (icon != null) {
-                maskedViews.setImageViewBitmap(R.id.work_widget_app_icon, icon);
-            }
+        private boolean replaceWithMaskedViewsLocked(RemoteViews views) {
+            maskedViews = views;
             return true;
         }
 
diff --git a/services/backup/java/com/android/server/backup/BackupManagerService.java b/services/backup/java/com/android/server/backup/BackupManagerService.java
index e32d89c..cd4d107d 100644
--- a/services/backup/java/com/android/server/backup/BackupManagerService.java
+++ b/services/backup/java/com/android/server/backup/BackupManagerService.java
@@ -171,6 +171,10 @@
     static final boolean MORE_DEBUG = false;
     static final boolean DEBUG_SCHEDULING = MORE_DEBUG || true;
 
+    // File containing backup-enabled state.  Contains a single byte;
+    // nonzero == enabled.  File missing or contains a zero byte == disabled.
+    static final String BACKUP_ENABLE_FILE = "backup_enabled";
+
     // System-private key used for backing up an app's widget state.  Must
     // begin with U+FFxx by convention (we reserve all keys starting
     // with U+FF00 or higher for system use).
@@ -354,11 +358,30 @@
             if (userId == UserHandle.USER_SYSTEM) {
                 sInstance.initialize(userId);
 
-                ContentResolver r = sInstance.mContext.getContentResolver();
-                boolean areEnabled = Settings.Secure.getIntForUser(r,
-                        Settings.Secure.BACKUP_ENABLED, 0, userId) != 0;
+                // Migrate legacy setting
+                if (!backupSettingMigrated(userId)) {
+                    if (DEBUG) {
+                        Slog.i(TAG, "Backup enable apparently not migrated");
+                    }
+                    final ContentResolver r = sInstance.mContext.getContentResolver();
+                    final int enableState = Settings.Secure.getIntForUser(r,
+                            Settings.Secure.BACKUP_ENABLED, -1, userId);
+                    if (enableState >= 0) {
+                        if (DEBUG) {
+                            Slog.i(TAG, "Migrating enable state " + (enableState != 0));
+                        }
+                        writeBackupEnableState(enableState != 0, userId);
+                        Settings.Secure.putStringForUser(r,
+                                Settings.Secure.BACKUP_ENABLED, null, userId);
+                    } else {
+                        if (DEBUG) {
+                            Slog.i(TAG, "Backup not yet configured; retaining null enable state");
+                        }
+                    }
+                }
+
                 try {
-                    sInstance.setBackupEnabled(areEnabled);
+                    sInstance.setBackupEnabled(readBackupEnableState(userId));
                 } catch (RemoteException e) {
                     // can't happen; it's a local object
                 }
@@ -3472,9 +3495,8 @@
             // The agent was running with a stub Application object, so shut it down.
             // !!! We hardcode the confirmation UI's package name here rather than use a
             //     manifest flag!  TODO something less direct.
-            if (app.uid != Process.SYSTEM_UID
-                    && !app.packageName.equals("com.android.backupconfirm")
-                    && app.uid != Process.PHONE_UID) {
+            if (app.uid >= Process.FIRST_APPLICATION_UID
+                    && !app.packageName.equals("com.android.backupconfirm")) {
                 if (MORE_DEBUG) Slog.d(TAG, "Killing agent host process");
                 mActivityManager.killApplicationProcess(app.processName, app.uid);
             } else {
@@ -6858,7 +6880,7 @@
                     // The agent was running with a stub Application object, so shut it down.
                     // !!! We hardcode the confirmation UI's package name here rather than use a
                     //     manifest flag!  TODO something less direct.
-                    if (app.uid != Process.SYSTEM_UID
+                    if (app.uid >= Process.FIRST_APPLICATION_UID
                             && !app.packageName.equals("com.android.backupconfirm")) {
                         if (DEBUG) Slog.d(TAG, "Killing host process");
                         mActivityManager.killApplicationProcess(app.processName, app.uid);
@@ -8602,13 +8624,15 @@
                     // it is explicitly not killed following that operation.
                     //
                     // We execute this kill when these conditions hold:
-                    //    1. the app did not request its own restore (mTargetPackage == null), and either
-                    //    2a. the app is a full-data target (TYPE_FULL_STREAM) or
+                    //    1. it's not a system-uid process,
+                    //    2. the app did not request its own restore (mTargetPackage == null), and either
+                    //    3a. the app is a full-data target (TYPE_FULL_STREAM) or
                     //     b. the app does not state android:killAfterRestore="false" in its manifest
                     final int appFlags = mCurrentPackage.applicationInfo.flags;
                     final boolean killAfterRestore =
-                            (mRestoreDescription.getDataType() == RestoreDescription.TYPE_FULL_STREAM)
-                            || ((appFlags & ApplicationInfo.FLAG_KILL_AFTER_RESTORE) != 0);
+                            (mCurrentPackage.applicationInfo.uid >= Process.FIRST_APPLICATION_UID)
+                            && ((mRestoreDescription.getDataType() == RestoreDescription.TYPE_FULL_STREAM)
+                                    || ((appFlags & ApplicationInfo.FLAG_KILL_AFTER_RESTORE) != 0));
 
                     if (mTargetPackage == null && killAfterRestore) {
                         if (DEBUG) Slog.d(TAG, "Restore complete, killing host process of "
@@ -9314,6 +9338,58 @@
         }
     }
 
+    private static boolean backupSettingMigrated(int userId) {
+        File base = new File(Environment.getDataDirectory(), "backup");
+        File enableFile = new File(base, BACKUP_ENABLE_FILE);
+        return enableFile.exists();
+    }
+
+    private static boolean readBackupEnableState(int userId) {
+        File base = new File(Environment.getDataDirectory(), "backup");
+        File enableFile = new File(base, BACKUP_ENABLE_FILE);
+        if (enableFile.exists()) {
+            try (FileInputStream fin = new FileInputStream(enableFile)) {
+                int state = fin.read();
+                return state != 0;
+            } catch (IOException e) {
+                // can't read the file; fall through to assume disabled
+                Slog.e(TAG, "Cannot read enable state; assuming disabled");
+            }
+        } else {
+            if (DEBUG) {
+                Slog.i(TAG, "isBackupEnabled() => false due to absent settings file");
+            }
+        }
+        return false;
+    }
+
+    private static void writeBackupEnableState(boolean enable, int userId) {
+        File base = new File(Environment.getDataDirectory(), "backup");
+        File enableFile = new File(base, BACKUP_ENABLE_FILE);
+        File stage = new File(base, BACKUP_ENABLE_FILE + "-stage");
+        FileOutputStream fout = null;
+        try {
+            fout = new FileOutputStream(stage);
+            fout.write(enable ? 1 : 0);
+            fout.close();
+            stage.renameTo(enableFile);
+            // will be synced immediately by the try-with-resources call to close()
+        } catch (IOException|RuntimeException e) {
+            // Whoops; looks like we're doomed.  Roll everything out, disabled,
+            // including the legacy state.
+            Slog.e(TAG, "Unable to record backup enable state; reverting to disabled: "
+                    + e.getMessage());
+
+            final ContentResolver r = sInstance.mContext.getContentResolver();
+            Settings.Secure.putStringForUser(r,
+                    Settings.Secure.BACKUP_ENABLED, null, userId);
+            enableFile.delete();
+            stage.delete();
+        } finally {
+            IoUtils.closeQuietly(fout);
+        }
+    }
+
     // Enable/disable backups
     public void setBackupEnabled(boolean enable) {
         mContext.enforceCallingOrSelfPermission(android.Manifest.permission.BACKUP,
@@ -9325,8 +9401,7 @@
         try {
             boolean wasEnabled = mEnabled;
             synchronized (this) {
-                Settings.Secure.putInt(mContext.getContentResolver(),
-                        Settings.Secure.BACKUP_ENABLED, enable ? 1 : 0);
+                writeBackupEnableState(enable, UserHandle.USER_SYSTEM);
                 mEnabled = enable;
             }
 
diff --git a/services/core/java/com/android/server/AlarmManagerService.java b/services/core/java/com/android/server/AlarmManagerService.java
index 4667172..c5a210c 100644
--- a/services/core/java/com/android/server/AlarmManagerService.java
+++ b/services/core/java/com/android/server/AlarmManagerService.java
@@ -150,6 +150,12 @@
     int mNumTimeChanged;
 
     /**
+     * The current set of user whitelisted apps for device idle mode, meaning these are allowed
+     * to freely schedule alarms.
+     */
+    int[] mDeviceIdleUserWhitelist = new int[0];
+
+    /**
      * For each uid, this is the last time we dispatched an "allow while idle" alarm,
      * used to determine the earliest we can dispatch the next such alarm.
      */
@@ -936,6 +942,7 @@
         }
 
         publishBinderService(Context.ALARM_SERVICE, mService);
+        publishLocalService(LocalService.class, new LocalService());
     }
 
     @Override
@@ -1251,14 +1258,6 @@
                 flags &= ~AlarmManager.FLAG_IDLE_UNTIL;
             }
 
-            // If the caller is a core system component, and not calling to do work on behalf
-            // of someone else, then always set ALLOW_WHILE_IDLE_UNRESTRICTED.  This means we
-            // will allow these alarms to go off as normal even while idle, with no timing
-            // restrictions.
-            if (callingUid < Process.FIRST_APPLICATION_UID && workSource == null) {
-                flags |= AlarmManager.FLAG_ALLOW_WHILE_IDLE_UNRESTRICTED;
-            }
-
             // If this is an exact time alarm, then it can't be batched with other alarms.
             if (windowLength == AlarmManager.WINDOW_EXACT) {
                 flags |= AlarmManager.FLAG_STANDALONE;
@@ -1268,6 +1267,16 @@
             // use it to wake early from idle if needed.
             if (alarmClock != null) {
                 flags |= AlarmManager.FLAG_WAKE_FROM_IDLE | AlarmManager.FLAG_STANDALONE;
+
+            // If the caller is a core system component or on the user's whitelist, and not calling
+            // to do work on behalf of someone else, then always set ALLOW_WHILE_IDLE_UNRESTRICTED.
+            // This means we will allow these alarms to go off as normal even while idle, with no
+            // timing restrictions.
+            } else if (workSource == null && (callingUid < Process.FIRST_APPLICATION_UID
+                    || Arrays.binarySearch(mDeviceIdleUserWhitelist,
+                            UserHandle.getAppId(callingUid)) >= 0)) {
+                flags |= AlarmManager.FLAG_ALLOW_WHILE_IDLE_UNRESTRICTED;
+                flags &= ~AlarmManager.FLAG_ALLOW_WHILE_IDLE;
             }
 
             setImpl(type, triggerAtTime, windowLength, interval, operation, directReceiver,
@@ -1344,6 +1353,12 @@
         }
     };
 
+    public final class LocalService {
+        public void setDeviceIdleUserWhitelist(int[] appids) {
+            setDeviceIdleUserWhitelistImpl(appids);
+        }
+    }
+
     void dumpImpl(PrintWriter pw) {
         synchronized (mLock) {
             pw.println("Current Alarm Manager state:");
@@ -1386,6 +1401,7 @@
             pw.print("  Next wakeup: "); TimeUtils.formatDuration(mNextWakeup, nowELAPSED, pw);
                     pw.print(" = "); pw.println(sdf.format(new Date(nextWakeupRTC)));
             pw.print("  Num time change events: "); pw.println(mNumTimeChanged);
+            pw.println("  mDeviceIdleUserWhitelist=" + Arrays.toString(mDeviceIdleUserWhitelist));
 
             pw.println();
             pw.println("  Next alarm clock information: ");
@@ -1678,6 +1694,12 @@
         }
     }
 
+    void setDeviceIdleUserWhitelistImpl(int[] appids) {
+        synchronized (mLock) {
+            mDeviceIdleUserWhitelist = appids;
+        }
+    }
+
     AlarmManager.AlarmClockInfo getNextAlarmClockImpl(int userId) {
         synchronized (mLock) {
             return mNextAlarmClockForUser.get(userId);
diff --git a/services/core/java/com/android/server/BluetoothManagerService.java b/services/core/java/com/android/server/BluetoothManagerService.java
index 8cfeb74..e241a4a 100644
--- a/services/core/java/com/android/server/BluetoothManagerService.java
+++ b/services/core/java/com/android/server/BluetoothManagerService.java
@@ -19,7 +19,6 @@
 import android.Manifest;
 import android.app.ActivityManager;
 import android.bluetooth.BluetoothAdapter;
-import android.bluetooth.BluetoothDevice;
 import android.bluetooth.BluetoothProfile;
 import android.bluetooth.IBluetooth;
 import android.bluetooth.IBluetoothCallback;
@@ -44,7 +43,6 @@
 import android.os.IBinder;
 import android.os.Looper;
 import android.os.Message;
-import android.os.ParcelFileDescriptor;
 import android.os.Process;
 import android.os.RemoteCallbackList;
 import android.os.RemoteException;
@@ -53,10 +51,9 @@
 import android.os.UserManager;
 import android.provider.Settings;
 import android.provider.Settings.SettingNotFoundException;
-import android.util.Log;
+import android.util.Slog;
 
 import java.io.FileDescriptor;
-import java.io.IOException;
 import java.io.PrintWriter;
 import java.util.HashMap;
 import java.util.Map;
@@ -92,14 +89,15 @@
     private static final int MESSAGE_BLUETOOTH_SERVICE_CONNECTED = 40;
     private static final int MESSAGE_BLUETOOTH_SERVICE_DISCONNECTED = 41;
     private static final int MESSAGE_RESTART_BLUETOOTH_SERVICE = 42;
-    private static final int MESSAGE_BLUETOOTH_STATE_CHANGE=60;
-    private static final int MESSAGE_TIMEOUT_BIND =100;
-    private static final int MESSAGE_TIMEOUT_UNBIND =101;
+    private static final int MESSAGE_BLUETOOTH_STATE_CHANGE = 60;
+    private static final int MESSAGE_TIMEOUT_BIND = 100;
+    private static final int MESSAGE_TIMEOUT_UNBIND = 101;
     private static final int MESSAGE_USER_SWITCHED = 300;
+    private static final int MESSAGE_USER_UNLOCKED = 301;
     private static final int MESSAGE_ADD_PROXY_DELAYED = 400;
     private static final int MESSAGE_BIND_PROFILE_SERVICE = 401;
-    private static final int MAX_SAVE_RETRIES=3;
-    private static final int MAX_ERROR_RESTART_RETRIES=6;
+    private static final int MAX_SAVE_RETRIES = 3;
+    private static final int MAX_ERROR_RESTART_RETRIES = 6;
 
     // Bluetooth persisted setting is off
     private static final int BLUETOOTH_OFF=0;
@@ -176,7 +174,7 @@
             String action = intent.getAction();
             if (BluetoothAdapter.ACTION_LOCAL_NAME_CHANGED.equals(action)) {
                 String newName = intent.getStringExtra(BluetoothAdapter.EXTRA_LOCAL_NAME);
-                if (DBG) Log.d(TAG, "Bluetooth Adapter name changed to " + newName);
+                if (DBG) Slog.d(TAG, "Bluetooth Adapter name changed to " + newName);
                 if (newName != null) {
                     storeNameAndAddress(newName, null);
                 }
@@ -195,10 +193,10 @@
                         try {
                             st = mBluetooth.getState();
                         } catch (RemoteException e) {
-                            Log.e(TAG,"Unable to call getState", e);
+                            Slog.e(TAG,"Unable to call getState", e);
                         }
                     }
-                    Log.d(TAG, "state" + st);
+                    Slog.d(TAG, "state" + st);
 
                     if (isAirplaneModeOn()) {
                         // Clear registered LE apps to force shut-off
@@ -214,16 +212,16 @@
                                     mEnableExternal = false;
                                 }
                             } catch(RemoteException e) {
-                                Log.e(TAG,"Unable to call onBrEdrDown", e);
+                                Slog.e(TAG,"Unable to call onBrEdrDown", e);
                             }
                         } else if (st == BluetoothAdapter.STATE_ON){
                             // disable without persisting the setting
-                            Log.d(TAG, "Calling disable");
+                            Slog.d(TAG, "Calling disable");
                             sendDisableMsg();
                         }
                     } else if (mEnableExternal) {
                         // enable without persisting the setting
-                        Log.d(TAG, "Calling enable");
+                        Slog.d(TAG, "Calling enable");
                         sendEnableMsg(mQuietEnableExternal);
                     }
                 }
@@ -267,7 +265,7 @@
                     PackageManager.MATCH_SYSTEM_ONLY, UserHandle.USER_SYSTEM);
         } catch (PackageManager.NameNotFoundException e) {
             // Some platforms, such as wearables do not have a system ui.
-            Log.w(TAG, "Unable to resolve SystemUI's UID.", e);
+            Slog.w(TAG, "Unable to resolve SystemUI's UID.", e);
         }
         mSystemUiUid = sysUiUid;
     }
@@ -320,17 +318,17 @@
      * in the local cache
      */
     private void loadStoredNameAndAddress() {
-        if (DBG) Log.d(TAG, "Loading stored name and address");
+        if (DBG) Slog.d(TAG, "Loading stored name and address");
         if (mContext.getResources().getBoolean
             (com.android.internal.R.bool.config_bluetooth_address_validation) &&
              Settings.Secure.getInt(mContentResolver, SECURE_SETTINGS_BLUETOOTH_ADDR_VALID, 0) == 0) {
             // if the valid flag is not set, don't load the address and name
-            if (DBG) Log.d(TAG, "invalid bluetooth name and address stored");
+            if (DBG) Slog.d(TAG, "invalid bluetooth name and address stored");
             return;
         }
         mName = Settings.Secure.getString(mContentResolver, SECURE_SETTINGS_BLUETOOTH_NAME);
         mAddress = Settings.Secure.getString(mContentResolver, SECURE_SETTINGS_BLUETOOTH_ADDRESS);
-        if (DBG) Log.d(TAG, "Stored bluetooth Name=" + mName + ",Address=" + mAddress);
+        if (DBG) Slog.d(TAG, "Stored bluetooth Name=" + mName + ",Address=" + mAddress);
     }
 
     /**
@@ -343,14 +341,14 @@
         if (name != null) {
             Settings.Secure.putString(mContentResolver, SECURE_SETTINGS_BLUETOOTH_NAME, name);
             mName = name;
-            if (DBG) Log.d(TAG,"Stored Bluetooth name: " +
+            if (DBG) Slog.d(TAG,"Stored Bluetooth name: " +
                 Settings.Secure.getString(mContentResolver,SECURE_SETTINGS_BLUETOOTH_NAME));
         }
 
         if (address != null) {
             Settings.Secure.putString(mContentResolver, SECURE_SETTINGS_BLUETOOTH_ADDRESS, address);
             mAddress=address;
-            if (DBG)  Log.d(TAG,"Stored Bluetoothaddress: " +
+            if (DBG)  Slog.d(TAG,"Stored Bluetoothaddress: " +
                 Settings.Secure.getString(mContentResolver,SECURE_SETTINGS_BLUETOOTH_ADDRESS));
         }
 
@@ -361,7 +359,7 @@
 
     public IBluetooth registerAdapter(IBluetoothManagerCallback callback){
         if (callback == null) {
-            Log.w(TAG, "Callback is null in registerAdapter");
+            Slog.w(TAG, "Callback is null in registerAdapter");
             return null;
         }
         Message msg = mHandler.obtainMessage(MESSAGE_REGISTER_ADAPTER);
@@ -374,7 +372,7 @@
 
     public void unregisterAdapter(IBluetoothManagerCallback callback) {
         if (callback == null) {
-            Log.w(TAG, "Callback is null in unregisterAdapter");
+            Slog.w(TAG, "Callback is null in unregisterAdapter");
             return;
         }
         mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM,
@@ -403,7 +401,7 @@
     public boolean isEnabled() {
         if ((Binder.getCallingUid() != Process.SYSTEM_UID) &&
             (!checkIfCallerIsForegroundUser())) {
-            Log.w(TAG,"isEnabled(): not allowed for non-active and non system user");
+            Slog.w(TAG,"isEnabled(): not allowed for non-active and non system user");
             return false;
         }
 
@@ -411,7 +409,7 @@
             try {
                 return (mBluetooth != null && mBluetooth.isEnabled());
             } catch (RemoteException e) {
-                Log.e(TAG, "isEnabled()", e);
+                Slog.e(TAG, "isEnabled()", e);
             }
         }
         return false;
@@ -419,17 +417,17 @@
 
     class ClientDeathRecipient implements IBinder.DeathRecipient {
         public void binderDied() {
-            if (DBG) Log.d(TAG, "Binder is dead -  unregister Ble App");
+            if (DBG) Slog.d(TAG, "Binder is dead -  unregister Ble App");
             if (mBleAppCount > 0) --mBleAppCount;
 
             if (mBleAppCount == 0) {
-                if (DBG) Log.d(TAG, "Disabling LE only mode after application crash");
+                if (DBG) Slog.d(TAG, "Disabling LE only mode after application crash");
                 try {
                     if (mBluetooth != null) {
                         mBluetooth.onBrEdrDown();
                     }
                 } catch(RemoteException e) {
-                     Log.e(TAG,"Unable to call onBrEdrDown", e);
+                     Slog.e(TAG,"Unable to call onBrEdrDown", e);
                 }
             }
         }
@@ -459,7 +457,7 @@
                     try {
                         if (mBluetooth != null) mBluetooth.onBrEdrDown();
                     } catch (RemoteException e) {
-                        Log.e(TAG, "error when disabling bluetooth", e);
+                        Slog.e(TAG, "error when disabling bluetooth", e);
                     }
                 }
             }
@@ -474,11 +472,11 @@
     private void disableBleScanMode() {
         try {
             if (mBluetooth != null && (mBluetooth.getState() != BluetoothAdapter.STATE_ON)) {
-                if (DBG) Log.d(TAG, "Reseting the mEnable flag for clean disable");
+                if (DBG) Slog.d(TAG, "Reseting the mEnable flag for clean disable");
                 mEnable = false;
             }
         } catch (RemoteException e) {
-            Log.e(TAG, "getState()", e);
+            Slog.e(TAG, "getState()", e);
         }
     }
 
@@ -496,7 +494,7 @@
                 synchronized (this) {
                     ++mBleAppCount;
                 }
-                if (DBG) Log.d(TAG, "Registered for death Notification");
+                if (DBG) Slog.d(TAG, "Registered for death Notification");
             }
 
         } else  {
@@ -508,10 +506,10 @@
                 synchronized (this) {
                     if (mBleAppCount > 0) --mBleAppCount;
                 }
-                if (DBG) Log.d(TAG, "Unregistered for death Notification");
+                if (DBG) Slog.d(TAG, "Unregistered for death Notification");
             }
         }
-        if (DBG) Log.d(TAG, "Updated BleAppCount" + mBleAppCount);
+        if (DBG) Slog.d(TAG, "Updated BleAppCount" + mBleAppCount);
         if (mBleAppCount == 0 && mEnable) {
             disableBleScanMode();
         }
@@ -528,7 +526,7 @@
 
     /** @hide*/
     public boolean isBleAppPresent() {
-        if (DBG) Log.d(TAG, "isBleAppPresent() count: " + mBleAppCount);
+        if (DBG) Slog.d(TAG, "isBleAppPresent() count: " + mBleAppCount);
         return (mBleAppCount > 0);
     }
 
@@ -536,7 +534,7 @@
      * Action taken when GattService is turned off
      */
     private void onBluetoothGattServiceUp() {
-        if (DBG) Log.d(TAG,"BluetoothGatt Service is Up");
+        if (DBG) Slog.d(TAG,"BluetoothGatt Service is Up");
         try{
             if (isBleAppPresent() == false && mBluetooth != null
                   && mBluetooth.getState() == BluetoothAdapter.STATE_BLE_ON) {
@@ -548,7 +546,7 @@
                 Binder.restoreCallingIdentity(callingIdentity);
             }
         } catch(RemoteException e) {
-                Log.e(TAG,"Unable to call onServiceUp", e);
+                Slog.e(TAG,"Unable to call onServiceUp", e);
         }
     }
 
@@ -557,10 +555,10 @@
      * and turn off all service and stack if no LE app needs it
      */
     private void sendBrEdrDownCallback() {
-        if (DBG) Log.d(TAG,"Calling sendBrEdrDownCallback callbacks");
+        if (DBG) Slog.d(TAG,"Calling sendBrEdrDownCallback callbacks");
 
         if(mBluetooth == null) {
-            Log.w(TAG, "Bluetooth handle is null");
+            Slog.w(TAG, "Bluetooth handle is null");
             return;
         }
 
@@ -568,14 +566,14 @@
             try {
                 mBluetooth.onBrEdrDown();
             } catch(RemoteException e) {
-                Log.e(TAG, "Call to onBrEdrDown() failed.", e);
+                Slog.e(TAG, "Call to onBrEdrDown() failed.", e);
             }
         } else {
             // Need to stay at BLE ON. Disconnect all Gatt connections
             try{
                 mBluetoothGatt.unregAll();
             } catch(RemoteException e) {
-                Log.e(TAG, "Unable to disconnect all apps.", e);
+                Slog.e(TAG, "Unable to disconnect all apps.", e);
             }
         }
     }
@@ -586,7 +584,7 @@
                                                 "Need BLUETOOTH ADMIN permission");
 
         if (DBG) {
-            Log.d(TAG,"enableNoAutoConnect():  mBluetooth =" + mBluetooth +
+            Slog.d(TAG,"enableNoAutoConnect():  mBluetooth =" + mBluetooth +
                     " mBinding = " + mBinding);
         }
         int callingAppId = UserHandle.getAppId(Binder.getCallingUid());
@@ -606,14 +604,14 @@
     public boolean enable() {
         if ((Binder.getCallingUid() != Process.SYSTEM_UID) &&
             (!checkIfCallerIsForegroundUser())) {
-            Log.w(TAG,"enable(): not allowed for non-active and non system user");
+            Slog.w(TAG,"enable(): not allowed for non-active and non system user");
             return false;
         }
 
         mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
                                                 "Need BLUETOOTH ADMIN permission");
         if (DBG) {
-            Log.d(TAG,"enable():  mBluetooth =" + mBluetooth +
+            Slog.d(TAG,"enable():  mBluetooth =" + mBluetooth +
                     " mBinding = " + mBinding);
         }
 
@@ -623,7 +621,7 @@
             // waive WRITE_SECURE_SETTINGS permission check
             sendEnableMsg(false);
         }
-        if (DBG) Log.d(TAG, "enable returning");
+        if (DBG) Slog.d(TAG, "enable returning");
         return true;
     }
 
@@ -633,12 +631,12 @@
 
         if ((Binder.getCallingUid() != Process.SYSTEM_UID) &&
             (!checkIfCallerIsForegroundUser())) {
-            Log.w(TAG,"disable(): not allowed for non-active and non system user");
+            Slog.w(TAG,"disable(): not allowed for non-active and non system user");
             return false;
         }
 
         if (DBG) {
-            Log.d(TAG,"disable(): mBluetooth = " + mBluetooth +
+            Slog.d(TAG,"disable(): mBluetooth = " + mBluetooth +
                 " mBinding = " + mBinding);
         }
 
@@ -657,7 +655,7 @@
 
     public void unbindAndFinish() {
         if (DBG) {
-            Log.d(TAG,"unbindAndFinish(): " + mBluetooth +
+            Slog.d(TAG,"unbindAndFinish(): " + mBluetooth +
                 " mBinding = " + mBinding);
         }
 
@@ -669,10 +667,10 @@
                 try {
                     mBluetooth.unregisterCallback(mBluetoothCallback);
                 } catch (RemoteException re) {
-                    Log.e(TAG, "Unable to unregister BluetoothCallback",re);
+                    Slog.e(TAG, "Unable to unregister BluetoothCallback",re);
                 }
 
-                if (DBG) Log.d(TAG, "Sending unbind request.");
+                if (DBG) Slog.d(TAG, "Sending unbind request.");
                 mBluetoothBinder = null;
                 mBluetooth = null;
                 //Unbind
@@ -696,7 +694,7 @@
             IBluetoothProfileServiceConnection proxy) {
         if (!mEnable) {
             if (DBG) {
-                Log.d(TAG, "Trying to bind to profile: " + bluetoothProfile +
+                Slog.d(TAG, "Trying to bind to profile: " + bluetoothProfile +
                         ", while Bluetooth was disabled");
             }
             return false;
@@ -705,7 +703,7 @@
             ProfileServiceConnections psc = mProfileServices.get(new Integer(bluetoothProfile));
             if (psc == null) {
                 if (DBG) {
-                    Log.d(TAG, "Creating new ProfileServiceConnections object for"
+                    Slog.d(TAG, "Creating new ProfileServiceConnections object for"
                             + " profile: " + bluetoothProfile);
                 }
 
@@ -746,7 +744,7 @@
                 try {
                     mContext.unbindService(psc);
                 } catch (IllegalArgumentException e) {
-                    Log.e(TAG, "Unable to unbind service with intent: " + psc.mIntent, e);
+                    Slog.e(TAG, "Unable to unbind service with intent: " + psc.mIntent, e);
                 }
                 psc.removeAllProxies();
             }
@@ -759,9 +757,9 @@
      * PHASE_SYSTEM_SERVICES_READY.
      */
     public void handleOnBootPhase() {
-        if (DBG) Log.d(TAG, "Bluetooth boot completed");
+        if (DBG) Slog.d(TAG, "Bluetooth boot completed");
         if (mEnableExternal && isBluetoothPersistedStateOnBluetooth()) {
-            if (DBG) Log.d(TAG, "Auto-enabling Bluetooth.");
+            if (DBG) Slog.d(TAG, "Auto-enabling Bluetooth.");
             sendEnableMsg(mQuietEnableExternal);
         }
     }
@@ -770,8 +768,16 @@
      * Called when switching to a different foreground user.
      */
     public void handleOnSwitchUser(int userHandle) {
-        if (DBG) Log.d(TAG, "Bluetooth user switched");
-        mHandler.sendMessage(mHandler.obtainMessage(MESSAGE_USER_SWITCHED, userHandle, 0));
+        if (DBG) Slog.d(TAG, "User " + userHandle + " switched");
+        mHandler.obtainMessage(MESSAGE_USER_SWITCHED, userHandle, 0).sendToTarget();
+    }
+
+    /**
+     * Called when user is unlocked.
+     */
+    public void handleOnUnlockUser(int userHandle) {
+        if (DBG) Slog.d(TAG, "User " + userHandle + " unlocked");
+        mHandler.obtainMessage(MESSAGE_USER_UNLOCKED, userHandle, 0).sendToTarget();
     }
 
     /**
@@ -801,7 +807,7 @@
                 mHandler.sendMessageDelayed(msg, TIMEOUT_BIND_MS);
                 return true;
             }
-            Log.w(TAG, "Unable to bind with intent: " + mIntent);
+            Slog.w(TAG, "Unable to bind with intent: " + mIntent);
             return false;
         }
 
@@ -811,7 +817,7 @@
                 try{
                     proxy.onServiceConnected(mClassName, mService);
                 } catch (RemoteException e) {
-                    Log.e(TAG, "Unable to connect to proxy", e);
+                    Slog.e(TAG, "Unable to connect to proxy", e);
                 }
             } else {
                 if (!mHandler.hasMessages(MESSAGE_BIND_PROFILE_SERVICE, this)) {
@@ -828,11 +834,11 @@
                     try {
                         proxy.onServiceDisconnected(mClassName);
                     } catch (RemoteException e) {
-                        Log.e(TAG, "Unable to disconnect proxy", e);
+                        Slog.e(TAG, "Unable to disconnect proxy", e);
                     }
                 }
             } else {
-                Log.w(TAG, "Trying to remove a null proxy");
+                Slog.w(TAG, "Trying to remove a null proxy");
             }
         }
 
@@ -850,11 +856,11 @@
             try {
                 mService.linkToDeath(this, 0);
             } catch (RemoteException e) {
-                Log.e(TAG, "Unable to linkToDeath", e);
+                Slog.e(TAG, "Unable to linkToDeath", e);
             }
 
             if (mInvokingProxyCallbacks) {
-                Log.e(TAG, "Proxy callbacks already in progress.");
+                Slog.e(TAG, "Proxy callbacks already in progress.");
                 return;
             }
             mInvokingProxyCallbacks = true;
@@ -865,7 +871,7 @@
                     try {
                         mProxies.getBroadcastItem(i).onServiceConnected(className, service);
                     } catch (RemoteException e) {
-                        Log.e(TAG, "Unable to connect to proxy", e);
+                        Slog.e(TAG, "Unable to connect to proxy", e);
                     }
                 }
             } finally {
@@ -882,7 +888,7 @@
             mClassName = null;
 
             if (mInvokingProxyCallbacks) {
-                Log.e(TAG, "Proxy callbacks already in progress.");
+                Slog.e(TAG, "Proxy callbacks already in progress.");
                 return;
             }
             mInvokingProxyCallbacks = true;
@@ -893,7 +899,7 @@
                     try {
                         mProxies.getBroadcastItem(i).onServiceDisconnected(className);
                     } catch (RemoteException e) {
-                        Log.e(TAG, "Unable to disconnect from proxy", e);
+                        Slog.e(TAG, "Unable to disconnect from proxy", e);
                     }
                 }
             } finally {
@@ -905,7 +911,7 @@
         @Override
         public void binderDied() {
             if (DBG) {
-                Log.w(TAG, "Profile service for profile: " + mClassName
+                Slog.w(TAG, "Profile service for profile: " + mClassName
                         + " died.");
             }
             onServiceDisconnected(mClassName);
@@ -919,12 +925,12 @@
     private void sendBluetoothStateCallback(boolean isUp) {
         try {
             int n = mStateChangeCallbacks.beginBroadcast();
-            if (DBG) Log.d(TAG,"Broadcasting onBluetoothStateChange("+isUp+") to " + n + " receivers.");
+            if (DBG) Slog.d(TAG,"Broadcasting onBluetoothStateChange("+isUp+") to " + n + " receivers.");
             for (int i=0; i <n;i++) {
                 try {
                     mStateChangeCallbacks.getBroadcastItem(i).onBluetoothStateChange(isUp);
                 } catch (RemoteException e) {
-                    Log.e(TAG, "Unable to call onBluetoothStateChange() on callback #" + i , e);
+                    Slog.e(TAG, "Unable to call onBluetoothStateChange() on callback #" + i , e);
                 }
             }
         } finally {
@@ -936,15 +942,15 @@
      * Inform BluetoothAdapter instances that Adapter service is up
      */
     private void sendBluetoothServiceUpCallback() {
-        if (DBG) Log.d(TAG,"Calling onBluetoothServiceUp callbacks");
+        if (DBG) Slog.d(TAG,"Calling onBluetoothServiceUp callbacks");
         try {
             int n = mCallbacks.beginBroadcast();
-            Log.d(TAG,"Broadcasting onBluetoothServiceUp() to " + n + " receivers.");
+            Slog.d(TAG,"Broadcasting onBluetoothServiceUp() to " + n + " receivers.");
             for (int i=0; i <n;i++) {
                 try {
                     mCallbacks.getBroadcastItem(i).onBluetoothServiceUp(mBluetooth);
                 }  catch (RemoteException e) {
-                    Log.e(TAG, "Unable to call onBluetoothServiceUp() on callback #" + i, e);
+                    Slog.e(TAG, "Unable to call onBluetoothServiceUp() on callback #" + i, e);
                 }
             }
         } finally {
@@ -955,15 +961,15 @@
      * Inform BluetoothAdapter instances that Adapter service is down
      */
     private void sendBluetoothServiceDownCallback() {
-        if (DBG) Log.d(TAG,"Calling onBluetoothServiceDown callbacks");
+        if (DBG) Slog.d(TAG,"Calling onBluetoothServiceDown callbacks");
         try {
             int n = mCallbacks.beginBroadcast();
-            Log.d(TAG,"Broadcasting onBluetoothServiceDown() to " + n + " receivers.");
+            Slog.d(TAG,"Broadcasting onBluetoothServiceDown() to " + n + " receivers.");
             for (int i=0; i <n;i++) {
                 try {
                     mCallbacks.getBroadcastItem(i).onBluetoothServiceDown();
                 }  catch (RemoteException e) {
-                    Log.e(TAG, "Unable to call onBluetoothServiceDown() on callback #" + i, e);
+                    Slog.e(TAG, "Unable to call onBluetoothServiceDown() on callback #" + i, e);
                 }
             }
         } finally {
@@ -977,7 +983,7 @@
 
         if ((Binder.getCallingUid() != Process.SYSTEM_UID) &&
                 (!checkIfCallerIsForegroundUser())) {
-            Log.w(TAG,"getAddress(): not allowed for non-active and non system user");
+            Slog.w(TAG,"getAddress(): not allowed for non-active and non system user");
             return null;
         }
 
@@ -991,7 +997,7 @@
                 try {
                     return mBluetooth.getAddress();
                 } catch (RemoteException e) {
-                    Log.e(TAG, "getAddress(): Unable to retrieve address remotely..Returning cached address",e);
+                    Slog.e(TAG, "getAddress(): Unable to retrieve address remotely..Returning cached address",e);
                 }
             }
         }
@@ -1007,7 +1013,7 @@
 
         if ((Binder.getCallingUid() != Process.SYSTEM_UID) &&
             (!checkIfCallerIsForegroundUser())) {
-            Log.w(TAG,"getName(): not allowed for non-active and non system user");
+            Slog.w(TAG,"getName(): not allowed for non-active and non system user");
             return null;
         }
 
@@ -1016,7 +1022,7 @@
                 try {
                     return mBluetooth.getName();
                 } catch (RemoteException e) {
-                    Log.e(TAG, "getName(): Unable to retrieve name remotely..Returning cached name",e);
+                    Slog.e(TAG, "getName(): Unable to retrieve name remotely..Returning cached name",e);
                 }
             }
         }
@@ -1028,7 +1034,7 @@
 
     private class BluetoothServiceConnection implements ServiceConnection {
         public void onServiceConnected(ComponentName className, IBinder service) {
-            if (DBG) Log.d(TAG, "BluetoothServiceConnection: " + className.getClassName());
+            if (DBG) Slog.d(TAG, "BluetoothServiceConnection: " + className.getClassName());
             Message msg = mHandler.obtainMessage(MESSAGE_BLUETOOTH_SERVICE_CONNECTED);
             // TBD if (className.getClassName().equals(IBluetooth.class.getName())) {
             if (className.getClassName().equals("com.android.bluetooth.btservice.AdapterService")) {
@@ -1037,7 +1043,7 @@
             } else if (className.getClassName().equals("com.android.bluetooth.gatt.GattService")) {
                 msg.arg1 = SERVICE_IBLUETOOTHGATT;
             } else {
-                Log.e(TAG, "Unknown service connected: " + className.getClassName());
+                Slog.e(TAG, "Unknown service connected: " + className.getClassName());
                 return;
             }
             msg.obj = service;
@@ -1046,7 +1052,7 @@
 
         public void onServiceDisconnected(ComponentName className) {
             // Called if we unexpected disconnected.
-            if (DBG) Log.d(TAG, "BluetoothServiceConnection, disconnected: " +
+            if (DBG) Slog.d(TAG, "BluetoothServiceConnection, disconnected: " +
                            className.getClassName());
             Message msg = mHandler.obtainMessage(MESSAGE_BLUETOOTH_SERVICE_DISCONNECTED);
             if (className.getClassName().equals("com.android.bluetooth.btservice.AdapterService")) {
@@ -1054,7 +1060,7 @@
             } else if (className.getClassName().equals("com.android.bluetooth.gatt.GattService")) {
                 msg.arg1 = SERVICE_IBLUETOOTHGATT;
             } else {
-                Log.e(TAG, "Unknown service disconnected: " + className.getClassName());
+                Slog.e(TAG, "Unknown service disconnected: " + className.getClassName());
                 return;
             }
             mHandler.sendMessage(msg);
@@ -1070,11 +1076,11 @@
 
         @Override
         public void handleMessage(Message msg) {
-            if (DBG) Log.d (TAG, "Message: " + msg.what);
+            if (DBG) Slog.d (TAG, "Message: " + msg.what);
             switch (msg.what) {
                 case MESSAGE_ENABLE:
                     if (DBG) {
-                        Log.d(TAG, "MESSAGE_ENABLE: mBluetooth = " + mBluetooth);
+                        Slog.d(TAG, "MESSAGE_ENABLE: mBluetooth = " + mBluetooth);
                     }
                     mHandler.removeMessages(MESSAGE_RESTART_BLUETOOTH_SERVICE);
                     mEnable = true;
@@ -1098,14 +1104,14 @@
                 {
                     IBluetoothManagerCallback callback = (IBluetoothManagerCallback) msg.obj;
                     boolean added = mCallbacks.register(callback);
-                    Log.d(TAG,"Added callback: " +  (callback == null? "null": callback)  +":" +added );
+                    Slog.d(TAG,"Added callback: " +  (callback == null? "null": callback)  +":" +added );
                 }
                     break;
                 case MESSAGE_UNREGISTER_ADAPTER:
                 {
                     IBluetoothManagerCallback callback = (IBluetoothManagerCallback) msg.obj;
                     boolean removed = mCallbacks.unregister(callback);
-                    Log.d(TAG,"Removed callback: " +  (callback == null? "null": callback)  +":" + removed);
+                    Slog.d(TAG,"Removed callback: " +  (callback == null? "null": callback)  +":" + removed);
                     break;
                 }
                 case MESSAGE_REGISTER_STATE_CHANGE_CALLBACK:
@@ -1148,7 +1154,7 @@
                 }
                 case MESSAGE_BLUETOOTH_SERVICE_CONNECTED:
                 {
-                    if (DBG) Log.d(TAG,"MESSAGE_BLUETOOTH_SERVICE_CONNECTED: " + msg.arg1);
+                    if (DBG) Slog.d(TAG,"MESSAGE_BLUETOOTH_SERVICE_CONNECTED: " + msg.arg1);
 
                     IBinder service = (IBinder) msg.obj;
                     synchronized(mConnection) {
@@ -1169,17 +1175,17 @@
                             boolean enableHciSnoopLog = (Settings.Secure.getInt(mContentResolver,
                                 Settings.Secure.BLUETOOTH_HCI_LOG, 0) == 1);
                             if (!mBluetooth.configHciSnoopLog(enableHciSnoopLog)) {
-                                Log.e(TAG,"IBluetooth.configHciSnoopLog return false");
+                                Slog.e(TAG,"IBluetooth.configHciSnoopLog return false");
                             }
                         } catch (RemoteException e) {
-                            Log.e(TAG,"Unable to call configHciSnoopLog", e);
+                            Slog.e(TAG,"Unable to call configHciSnoopLog", e);
                         }
 
                         //Register callback object
                         try {
                             mBluetooth.registerCallback(mBluetoothCallback);
                         } catch (RemoteException re) {
-                            Log.e(TAG, "Unable to register BluetoothCallback",re);
+                            Slog.e(TAG, "Unable to register BluetoothCallback",re);
                         }
                         //Inform BluetoothAdapter instances that service is up
                         sendBluetoothServiceUpCallback();
@@ -1188,17 +1194,17 @@
                         try {
                             if (mQuietEnable == false) {
                                 if(!mBluetooth.enable()) {
-                                    Log.e(TAG,"IBluetooth.enable() returned false");
+                                    Slog.e(TAG,"IBluetooth.enable() returned false");
                                 }
                             }
                             else
                             {
                                 if(!mBluetooth.enableNoAutoConnect()) {
-                                    Log.e(TAG,"IBluetooth.enableNoAutoConnect() returned false");
+                                    Slog.e(TAG,"IBluetooth.enableNoAutoConnect() returned false");
                                 }
                             }
                         } catch (RemoteException e) {
-                            Log.e(TAG,"Unable to call enable()",e);
+                            Slog.e(TAG,"Unable to call enable()",e);
                         }
                     }
 
@@ -1210,7 +1216,7 @@
                     break;
                 }
                 case MESSAGE_TIMEOUT_BIND: {
-                    Log.e(TAG, "MESSAGE_TIMEOUT_BIND");
+                    Slog.e(TAG, "MESSAGE_TIMEOUT_BIND");
                     synchronized(mConnection) {
                         mBinding = false;
                     }
@@ -1220,7 +1226,7 @@
                 {
                     int prevState = msg.arg1;
                     int newState = msg.arg2;
-                    if (DBG) Log.d(TAG, "MESSAGE_BLUETOOTH_STATE_CHANGE: prevState = " + prevState + ", newState=" + newState);
+                    if (DBG) Slog.d(TAG, "MESSAGE_BLUETOOTH_STATE_CHANGE: prevState = " + prevState + ", newState=" + newState);
                     mState = newState;
                     bluetoothStateChangeHandler(prevState, newState);
                     // handle error state transition case from TURNING_ON to OFF
@@ -1239,7 +1245,7 @@
                         newState == BluetoothAdapter.STATE_BLE_ON) {
                         // bluetooth is working, reset the counter
                         if (mErrorRecoveryRetryCounter != 0) {
-                            Log.w(TAG, "bluetooth is recovered from error");
+                            Slog.w(TAG, "bluetooth is recovered from error");
                             mErrorRecoveryRetryCounter = 0;
                         }
                     }
@@ -1247,7 +1253,7 @@
                 }
                 case MESSAGE_BLUETOOTH_SERVICE_DISCONNECTED:
                 {
-                    Log.e(TAG, "MESSAGE_BLUETOOTH_SERVICE_DISCONNECTED: " + msg.arg1);
+                    Slog.e(TAG, "MESSAGE_BLUETOOTH_SERVICE_DISCONNECTED: " + msg.arg1);
                     synchronized(mConnection) {
                         if (msg.arg1 == SERVICE_IBLUETOOTH) {
                             // if service is unbinded already, do nothing and return
@@ -1257,7 +1263,7 @@
                             mBluetoothGatt = null;
                             break;
                         } else {
-                            Log.e(TAG, "Bad msg.arg1: " + msg.arg1);
+                            Slog.e(TAG, "Bad msg.arg1: " + msg.arg1);
                             break;
                         }
                     }
@@ -1292,7 +1298,7 @@
                 }
                 case MESSAGE_RESTART_BLUETOOTH_SERVICE:
                 {
-                    Log.d(TAG, "MESSAGE_RESTART_BLUETOOTH_SERVICE:"
+                    Slog.d(TAG, "MESSAGE_RESTART_BLUETOOTH_SERVICE:"
                         +" Restart IBluetooth service");
                     /* Enable without persisting the setting as
                      it doesnt change when IBluetooth
@@ -1304,19 +1310,17 @@
 
                 case MESSAGE_TIMEOUT_UNBIND:
                 {
-                    Log.e(TAG, "MESSAGE_TIMEOUT_UNBIND");
+                    Slog.e(TAG, "MESSAGE_TIMEOUT_UNBIND");
                     synchronized(mConnection) {
                         mUnbinding = false;
                     }
                     break;
                 }
 
-                case MESSAGE_USER_SWITCHED:
-                {
-                    if (DBG) {
-                        Log.d(TAG, "MESSAGE_USER_SWITCHED");
-                    }
+                case MESSAGE_USER_SWITCHED: {
+                    if (DBG) Slog.d(TAG, "MESSAGE_USER_SWITCHED");
                     mHandler.removeMessages(MESSAGE_USER_SWITCHED);
+
                     /* disable and enable BT when detect a user switch */
                     if (mEnable && mBluetooth != null) {
                         synchronized (mConnection) {
@@ -1325,7 +1329,7 @@
                                 try {
                                     mBluetooth.unregisterCallback(mBluetoothCallback);
                                 } catch (RemoteException re) {
-                                    Log.e(TAG, "Unable to unregister",re);
+                                    Slog.e(TAG, "Unable to unregister",re);
                                 }
                             }
                         }
@@ -1379,11 +1383,25 @@
                         // delay sending MESSAGE_USER_SWITCHED
                         mHandler.sendMessageDelayed(userMsg, USER_SWITCHED_TIME_MS);
                         if (DBG) {
-                            Log.d(TAG, "delay MESSAGE_USER_SWITCHED " + userMsg.arg2);
+                            Slog.d(TAG, "delay MESSAGE_USER_SWITCHED " + userMsg.arg2);
                         }
                     }
                     break;
                 }
+                case MESSAGE_USER_UNLOCKED: {
+                    if (DBG) Slog.d(TAG, "MESSAGE_USER_UNLOCKED");
+                    mHandler.removeMessages(MESSAGE_USER_SWITCHED);
+
+                    synchronized (mConnection) {
+                        if (mEnable && !mBinding && (mBluetooth == null)) {
+                            // We should be connected, but we gave up for some
+                            // reason; maybe the Bluetooth service wasn't encryption
+                            // aware, so try binding again.
+                            if (DBG) Slog.d(TAG, "Enabled but not bound; retrying after unlock");
+                            handleEnable(mQuietEnable);
+                        }
+                    }
+                }
             }
         }
     }
@@ -1408,16 +1426,16 @@
                 try {
                     if (!mQuietEnable) {
                         if(!mBluetooth.enable()) {
-                            Log.e(TAG,"IBluetooth.enable() returned false");
+                            Slog.e(TAG,"IBluetooth.enable() returned false");
                         }
                     }
                     else {
                         if(!mBluetooth.enableNoAutoConnect()) {
-                            Log.e(TAG,"IBluetooth.enableNoAutoConnect() returned false");
+                            Slog.e(TAG,"IBluetooth.enableNoAutoConnect() returned false");
                         }
                     }
                 } catch (RemoteException e) {
-                    Log.e(TAG,"Unable to call enable()",e);
+                    Slog.e(TAG,"Unable to call enable()",e);
                 }
             }
         }
@@ -1427,7 +1445,7 @@
         ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0);
         intent.setComponent(comp);
         if (comp == null || !mContext.bindServiceAsUser(intent, conn, flags, user)) {
-            Log.e(TAG, "Fail to bind to: " + intent);
+            Slog.e(TAG, "Fail to bind to: " + intent);
             return false;
         }
         return true;
@@ -1436,14 +1454,14 @@
     private void handleDisable() {
         synchronized(mConnection) {
             if (mBluetooth != null) {
-                if (DBG) Log.d(TAG,"Sending off request.");
+                if (DBG) Slog.d(TAG,"Sending off request.");
 
                 try {
                     if(!mBluetooth.disable()) {
-                        Log.e(TAG,"IBluetooth.disable() returned false");
+                        Slog.e(TAG,"IBluetooth.disable() returned false");
                     }
                 } catch (RemoteException e) {
-                    Log.e(TAG,"Unable to call disable()",e);
+                    Slog.e(TAG,"Unable to call disable()",e);
                 }
             }
         }
@@ -1466,7 +1484,7 @@
                     callingAppId == Process.NFC_UID ||
                     callingAppId == mSystemUiUid;
             if (DBG) {
-                Log.d(TAG, "checkIfCallerIsForegroundUser: valid=" + valid
+                Slog.d(TAG, "checkIfCallerIsForegroundUser: valid=" + valid
                     + " callingUser=" + callingUser
                     + " parentUser=" + parentUser
                     + " foregroundUser=" + foregroundUser);
@@ -1478,7 +1496,7 @@
     }
 
     private void sendBleStateChanged(int prevState, int newState) {
-        if (DBG) Log.d(TAG,"BLE State Change Intent: " + prevState + " -> " + newState);
+        if (DBG) Slog.d(TAG,"BLE State Change Intent: " + prevState + " -> " + newState);
         // Send broadcast message to everyone else
         Intent intent = new Intent(BluetoothAdapter.ACTION_BLE_STATE_CHANGED);
         intent.putExtra(BluetoothAdapter.EXTRA_PREVIOUS_STATE, prevState);
@@ -1498,9 +1516,9 @@
 
                 if (newState == BluetoothAdapter.STATE_OFF) {
                     // If Bluetooth is off, send service down event to proxy objects, and unbind
-                    if (DBG) Log.d(TAG, "Bluetooth is complete turn off");
+                    if (DBG) Slog.d(TAG, "Bluetooth is complete turn off");
                     if (canUnbindBluetoothService()) {
-                        if (DBG) Log.d(TAG, "Good to unbind!");
+                        if (DBG) Slog.d(TAG, "Good to unbind!");
                         sendBluetoothServiceDownCallback();
                         unbindAndFinish();
                         sendBleStateChanged(prevState, newState);
@@ -1510,12 +1528,12 @@
 
                 } else if (!intermediate_off) {
                     // connect to GattService
-                    if (DBG) Log.d(TAG, "Bluetooth is in LE only mode");
+                    if (DBG) Slog.d(TAG, "Bluetooth is in LE only mode");
                     if (mBluetoothGatt != null) {
-                        if (DBG) Log.d(TAG, "Calling BluetoothGattServiceUp");
+                        if (DBG) Slog.d(TAG, "Calling BluetoothGattServiceUp");
                         onBluetoothGattServiceUp();
                     } else {
-                        if (DBG) Log.d(TAG, "Binding Bluetooth GATT service");
+                        if (DBG) Slog.d(TAG, "Binding Bluetooth GATT service");
                         if (mContext.getPackageManager().hasSystemFeature(
                                                         PackageManager.FEATURE_BLUETOOTH_LE)) {
                             Intent i = new Intent(IBluetoothGatt.class.getName());
@@ -1527,7 +1545,7 @@
                     isStandardBroadcast = false;
 
                 } else if (intermediate_off){
-                    if (DBG) Log.d(TAG, "Intermediate off, back to LE only mode");
+                    if (DBG) Slog.d(TAG, "Intermediate off, back to LE only mode");
                     // For LE only mode, broadcast as is
                     sendBleStateChanged(prevState, newState);
                     sendBluetoothStateCallback(false); // BT is OFF for general users
@@ -1583,7 +1601,7 @@
                         if (mBluetooth.getState() != BluetoothAdapter.STATE_ON) return true;
                     }
                 } catch (RemoteException e) {
-                    Log.e(TAG, "getState()", e);
+                    Slog.e(TAG, "getState()", e);
                     break;
                 }
             }
@@ -1594,7 +1612,7 @@
             }
             i++;
         }
-        Log.e(TAG,"waitForOnOff time out");
+        Slog.e(TAG,"waitForOnOff time out");
         return false;
     }
 
@@ -1619,21 +1637,21 @@
                 if (mHandler.hasMessages(MESSAGE_BLUETOOTH_STATE_CHANGE)) return false;
                 return (mBluetooth.getState() == BluetoothAdapter.STATE_OFF);
             } catch (RemoteException e) {
-                Log.e(TAG, "getState()", e);
+                Slog.e(TAG, "getState()", e);
             }
         }
         return false;
     }
 
     private void recoverBluetoothServiceFromError() {
-        Log.e(TAG,"recoverBluetoothServiceFromError");
+        Slog.e(TAG,"recoverBluetoothServiceFromError");
         synchronized (mConnection) {
             if (mBluetooth != null) {
                 //Unregister callback object
                 try {
                     mBluetooth.unregisterCallback(mBluetoothCallback);
                 } catch (RemoteException re) {
-                    Log.e(TAG, "Unable to unregister",re);
+                    Slog.e(TAG, "Unable to unregister",re);
                 }
             }
         }
diff --git a/services/core/java/com/android/server/BluetoothService.java b/services/core/java/com/android/server/BluetoothService.java
index 019d03d..1bf4e3a 100644
--- a/services/core/java/com/android/server/BluetoothService.java
+++ b/services/core/java/com/android/server/BluetoothService.java
@@ -18,10 +18,8 @@
 
 import android.bluetooth.BluetoothAdapter;
 import android.content.Context;
-import android.util.Log;
 
 class BluetoothService extends SystemService {
-    private static final String TAG = "BluetoothService";
     private BluetoothManagerService mBluetoothManagerService;
 
     public BluetoothService(Context context) {
@@ -36,17 +34,20 @@
     @Override
     public void onBootPhase(int phase) {
         if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY) {
-            Log.d(TAG, "onBootPhase: PHASE_SYSTEM_SERVICES_READY");
-            publishBinderService(BluetoothAdapter.BLUETOOTH_MANAGER_SERVICE, mBluetoothManagerService);
+            publishBinderService(BluetoothAdapter.BLUETOOTH_MANAGER_SERVICE,
+                    mBluetoothManagerService);
         } else if (phase == SystemService.PHASE_ACTIVITY_MANAGER_READY) {
-            Log.d(TAG, "onBootPhase: PHASE_ACTIVITY_MANAGER_READY");
             mBluetoothManagerService.handleOnBootPhase();
         }
     }
 
     @Override
     public void onSwitchUser(int userHandle) {
-        Log.d(TAG, "onSwitchUser: switching to user " + userHandle);
         mBluetoothManagerService.handleOnSwitchUser(userHandle);
     }
+
+    @Override
+    public void onUnlockUser(int userHandle) {
+        mBluetoothManagerService.handleOnUnlockUser(userHandle);
+    }
 }
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 4300920..86040c2 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -125,6 +125,7 @@
 import com.android.server.connectivity.NetworkMonitor;
 import com.android.server.connectivity.PacManager;
 import com.android.server.connectivity.PermissionMonitor;
+import com.android.server.connectivity.ApfFilter;
 import com.android.server.connectivity.Tethering;
 import com.android.server.connectivity.Vpn;
 import com.android.server.net.BaseNetworkObserver;
@@ -163,7 +164,7 @@
         implements PendingIntent.OnFinished {
     private static final String TAG = "ConnectivityService";
 
-    private static final boolean DBG = true;
+    private static final boolean DBG = false;
     private static final boolean VDBG = false;
 
     private static final boolean LOGD_RULES = false;
@@ -353,6 +354,13 @@
      */
     private static final int EVENT_REGISTER_NETWORK_LISTENER_WITH_INTENT = 31;
 
+    /**
+     * used to push APF program to NetworkAgent
+     * replyTo = NetworkAgent message handler
+     * obj = byte[] of APF program
+     */
+    private static final int EVENT_PUSH_APF_PROGRAM_TO_NETWORK = 32;
+
     /** Handler thread used for both of the handlers below. */
     @VisibleForTesting
     protected final HandlerThread mHandlerThread;
@@ -447,7 +455,7 @@
      */
     private class LegacyTypeTracker {
 
-        private static final boolean DBG = true;
+        private static final boolean DBG = false;
         private static final boolean VDBG = false;
         private static final String TAG = "CSLegacyTypeTracker";
 
@@ -750,7 +758,7 @@
         intentFilter.addAction(Intent.ACTION_USER_STOPPING);
         intentFilter.addAction(Intent.ACTION_USER_ADDED);
         intentFilter.addAction(Intent.ACTION_USER_REMOVED);
-        intentFilter.addAction(Intent.ACTION_USER_PRESENT);
+        intentFilter.addAction(Intent.ACTION_USER_UNLOCKED);
         mContext.registerReceiverAsUser(
                 mUserIntentReceiver, UserHandle.ALL, intentFilter, null, null);
 
@@ -2190,6 +2198,7 @@
             mKeepaliveTracker.handleStopAllKeepalives(nai,
                     ConnectivityManager.PacketKeepalive.ERROR_INVALID_NETWORK);
             nai.networkMonitor.sendMessage(NetworkMonitor.CMD_NETWORK_DISCONNECTED);
+            if (nai.apfFilter != null) nai.apfFilter.shutdown();
             mNetworkAgentInfos.remove(msg.replyTo);
             updateClat(null, nai.linkProperties, nai);
             synchronized (mNetworkForNetId) {
@@ -2404,6 +2413,13 @@
                 accept ? 1 : 0, always ? 1: 0, network));
     }
 
+    public void pushApfProgramToNetwork(NetworkAgentInfo nai, byte[] program) {
+        enforceConnectivityInternalPermission();
+        Message msg = mHandler.obtainMessage(EVENT_PUSH_APF_PROGRAM_TO_NETWORK, program);
+        msg.replyTo = nai.messenger;
+        mHandler.sendMessage(msg);
+    }
+
     private void handleSetAcceptUnvalidated(Network network, boolean accept, boolean always) {
         if (DBG) log("handleSetAcceptUnvalidated network=" + network +
                 " accept=" + accept + " always=" + always);
@@ -2553,6 +2569,16 @@
                     handleMobileDataAlwaysOn();
                     break;
                 }
+                case EVENT_PUSH_APF_PROGRAM_TO_NETWORK: {
+                    NetworkAgentInfo nai = mNetworkAgentInfos.get(msg.replyTo);
+                    if (nai == null) {
+                        loge("EVENT_PUSH_APF_PROGRAM_TO_NETWORK from unknown NetworkAgent");
+                    } else {
+                         nai.asyncChannel.sendMessage(NetworkAgent.CMD_PUSH_APF_PROGRAM,
+                                 (byte[]) msg.obj);
+                    }
+                    break;
+                }
                 // Sent by KeepaliveTracker to process an app request on the state machine thread.
                 case NetworkAgent.CMD_START_PACKET_KEEPALIVE: {
                     mKeepaliveTracker.handleStartKeepalive(msg);
@@ -3633,7 +3659,7 @@
         }
     }
 
-    private void onUserPresent(int userId) {
+    private void onUserUnlocked(int userId) {
         // User present may be sent because of an unlock, which might mean an unlocked keystore.
         if (mUserManager.getUserInfo(userId).isPrimary() && LockdownVpnTracker.isEnabled()) {
             updateLockdownVpn();
@@ -3657,8 +3683,8 @@
                 onUserAdded(userId);
             } else if (Intent.ACTION_USER_REMOVED.equals(action)) {
                 onUserRemoved(userId);
-            } else if (Intent.ACTION_USER_PRESENT.equals(action)) {
-                onUserPresent(userId);
+            } else if (Intent.ACTION_USER_UNLOCKED.equals(action)) {
+                onUserUnlocked(userId);
             }
         }
     };
@@ -4068,6 +4094,9 @@
         if (networkAgent.clatd != null) {
             networkAgent.clatd.fixupLinkProperties(oldLp);
         }
+        if (networkAgent.apfFilter != null) {
+            networkAgent.apfFilter.updateFilter();
+        }
 
         updateInterfaces(newLp, oldLp, netId);
         updateMtu(newLp, oldLp);
diff --git a/services/core/java/com/android/server/DeviceIdleController.java b/services/core/java/com/android/server/DeviceIdleController.java
index 62fa7d5..7bf4b56 100644
--- a/services/core/java/com/android/server/DeviceIdleController.java
+++ b/services/core/java/com/android/server/DeviceIdleController.java
@@ -120,6 +120,7 @@
     private AlarmManager mAlarmManager;
     private IBatteryStats mBatteryStats;
     private PowerManagerInternal mLocalPowerManager;
+    private AlarmManagerService.LocalService mLocalAlarmManager;
     private INetworkPolicyManager mNetworkPolicyManager;
     private DisplayManager mDisplayManager;
     private SensorManager mSensorManager;
@@ -269,6 +270,17 @@
     private int[] mPowerSaveWhitelistAllAppIdArray = new int[0];
 
     /**
+     * App IDs that have been white-listed by the user to opt out of power save restrictions.
+     */
+    private final SparseBooleanArray mPowerSaveWhitelistUserAppIds = new SparseBooleanArray();
+
+    /**
+     * Current app IDs that are in the user power save white list.  This array can
+     * be shared with others because it will not be modified once set.
+     */
+    private int[] mPowerSaveWhitelistUserAppIdArray = new int[0];
+
+    /**
      * List of end times for UIDs that are temporarily marked as being allowed to access
      * the network and acquire wakelocks. Times are in milliseconds.
      */
@@ -964,6 +976,10 @@
             return getSystemPowerWhitelistInternal();
         }
 
+        @Override public String[] getUserPowerWhitelist() {
+            return getUserPowerWhitelistInternal();
+        }
+
         @Override public String[] getFullPowerWhitelistExceptIdle() {
             return getFullPowerWhitelistExceptIdleInternal();
         }
@@ -980,6 +996,10 @@
             return getAppIdWhitelistInternal();
         }
 
+        @Override public int[] getAppIdUserWhitelist() {
+            return getAppIdUserWhitelistInternal();
+        }
+
         @Override public int[] getAppIdTempWhitelist() {
             return getAppIdTempWhitelistInternal();
         }
@@ -1161,6 +1181,7 @@
                 mAlarmManager = (AlarmManager) getContext().getSystemService(Context.ALARM_SERVICE);
                 mBatteryStats = BatteryStatsService.getService();
                 mLocalPowerManager = getLocalService(PowerManagerInternal.class);
+                mLocalAlarmManager = getLocalService(AlarmManagerService.LocalService.class);
                 mNetworkPolicyManager = INetworkPolicyManager.Stub.asInterface(
                         ServiceManager.getService(Context.NETWORK_POLICY_SERVICE));
                 mDisplayManager = (DisplayManager) getContext().getSystemService(
@@ -1227,6 +1248,7 @@
                 getContext().registerReceiver(mReceiver, filter);
 
                 mLocalPowerManager.setDeviceIdleWhitelist(mPowerSaveWhitelistAllAppIdArray);
+                mLocalAlarmManager.setDeviceIdleUserWhitelist(mPowerSaveWhitelistUserAppIdArray);
 
                 mDisplayManager.registerDisplayListener(mDisplayListener, null);
                 updateDisplayLocked();
@@ -1291,6 +1313,17 @@
         }
     }
 
+    public String[] getUserPowerWhitelistInternal() {
+        synchronized (this) {
+            int size = mPowerSaveWhitelistUserApps.size();
+            String[] apps = new String[size];
+            for (int i = 0; i < mPowerSaveWhitelistUserApps.size(); i++) {
+                apps[i] = mPowerSaveWhitelistUserApps.keyAt(i);
+            }
+            return apps;
+        }
+    }
+
     public String[] getFullPowerWhitelistExceptIdleInternal() {
         synchronized (this) {
             int size = mPowerSaveWhitelistAppsExceptIdle.size() + mPowerSaveWhitelistUserApps.size();
@@ -1351,6 +1384,12 @@
         }
     }
 
+    public int[] getAppIdUserWhitelistInternal() {
+        synchronized (this) {
+            return mPowerSaveWhitelistUserAppIdArray;
+        }
+    }
+
     public int[] getAppIdTempWhitelistInternal() {
         synchronized (this) {
             return mTempWhitelistAppIdArray;
@@ -1993,11 +2032,15 @@
     private static int[] buildAppIdArray(ArrayMap<String, Integer> systemApps,
             ArrayMap<String, Integer> userApps, SparseBooleanArray outAppIds) {
         outAppIds.clear();
-        for (int i=0; i<systemApps.size(); i++) {
-            outAppIds.put(systemApps.valueAt(i), true);
+        if (systemApps != null) {
+            for (int i = 0; i < systemApps.size(); i++) {
+                outAppIds.put(systemApps.valueAt(i), true);
+            }
         }
-        for (int i=0; i<userApps.size(); i++) {
-            outAppIds.put(userApps.valueAt(i), true);
+        if (userApps != null) {
+            for (int i = 0; i < userApps.size(); i++) {
+                outAppIds.put(userApps.valueAt(i), true);
+            }
         }
         int size = outAppIds.size();
         int[] appids = new int[size];
@@ -2012,6 +2055,8 @@
                 mPowerSaveWhitelistUserApps, mPowerSaveWhitelistExceptIdleAppIds);
         mPowerSaveWhitelistAllAppIdArray = buildAppIdArray(mPowerSaveWhitelistApps,
                 mPowerSaveWhitelistUserApps, mPowerSaveWhitelistAllAppIds);
+        mPowerSaveWhitelistUserAppIdArray = buildAppIdArray(null,
+                mPowerSaveWhitelistUserApps, mPowerSaveWhitelistUserAppIds);
         if (mLocalPowerManager != null) {
             if (DEBUG) {
                 Slog.d(TAG, "Setting wakelock whitelist to "
@@ -2019,6 +2064,13 @@
             }
             mLocalPowerManager.setDeviceIdleWhitelist(mPowerSaveWhitelistAllAppIdArray);
         }
+        if (mLocalAlarmManager != null) {
+            if (DEBUG) {
+                Slog.d(TAG, "Setting alarm whitelist to "
+                        + Arrays.toString(mPowerSaveWhitelistUserAppIdArray));
+            }
+            mLocalAlarmManager.setDeviceIdleUserWhitelist(mPowerSaveWhitelistUserAppIdArray);
+        }
     }
 
     private void updateTempWhitelistAppIdsLocked() {
@@ -2536,6 +2588,15 @@
                     pw.println();
                 }
             }
+            size = mPowerSaveWhitelistUserAppIds.size();
+            if (size > 0) {
+                pw.println("  Whitelist user app ids:");
+                for (int i = 0; i < size; i++) {
+                    pw.print("    ");
+                    pw.print(mPowerSaveWhitelistUserAppIds.keyAt(i));
+                    pw.println();
+                }
+            }
             size = mPowerSaveWhitelistAllAppIds.size();
             if (size > 0) {
                 pw.println("  Whitelist all app ids:");
diff --git a/services/core/java/com/android/server/DiskStatsService.java b/services/core/java/com/android/server/DiskStatsService.java
index 9313148..8ca675a 100644
--- a/services/core/java/com/android/server/DiskStatsService.java
+++ b/services/core/java/com/android/server/DiskStatsService.java
@@ -80,7 +80,7 @@
         reportFreeSpace(Environment.getDownloadCacheDirectory(), "Cache", pw);
         reportFreeSpace(new File("/system"), "System", pw);
 
-        if (StorageManager.isNativeFileBasedEncryptionEnabled()) {
+        if (StorageManager.isFileEncryptedNativeOnly()) {
             pw.println("File-based Encryption: true");
         }
 
diff --git a/services/core/java/com/android/server/InputMethodManagerService.java b/services/core/java/com/android/server/InputMethodManagerService.java
index 63c9822..9b8f2d2 100644
--- a/services/core/java/com/android/server/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/InputMethodManagerService.java
@@ -39,6 +39,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.UserIdInt;
 import android.app.ActivityManagerNative;
 import android.app.AlertDialog;
 import android.app.AppGlobals;
@@ -47,7 +48,6 @@
 import android.app.Notification;
 import android.app.NotificationManager;
 import android.app.PendingIntent;
-import android.app.SynchronousUserSwitchObserver;
 import android.content.BroadcastReceiver;
 import android.content.ComponentName;
 import android.content.ContentResolver;
@@ -465,7 +465,7 @@
             super(handler);
         }
 
-        public void registerContentObserverLocked(int userId) {
+        public void registerContentObserverLocked(@UserIdInt int userId) {
             if (mRegistered && mUserId == userId) {
                 return;
             }
@@ -774,7 +774,16 @@
         }
 
         @Override
+        public void onSwitchUser(@UserIdInt int userHandle) {
+            // Called on the system server's main looper thread.
+            // TODO: Dispatch this to a worker thread as needed.
+            mService.onSwitchUser(userHandle);
+        }
+
+        @Override
         public void onBootPhase(int phase) {
+            // Called on the system server's main looper thread.
+            // TODO: Dispatch this to a worker thread as needed.
             if (phase == SystemService.PHASE_ACTIVITY_MANAGER_READY) {
                 StatusBarManagerService statusBarService = (StatusBarManagerService) ServiceManager
                         .getService(Context.STATUS_BAR_SERVICE);
@@ -783,12 +792,14 @@
         }
 
         @Override
-        public void onUnlockUser(int userHandle) {
+        public void onUnlockUser(@UserIdInt int userHandle) {
+            // Called on the system server's main looper thread.
+            // TODO: Dispatch this to a worker thread as needed.
             mService.onUnlockUser(userHandle);
         }
     }
 
-    public void onUnlockUser(int userId) {
+    void onUnlockUser(@UserIdInt int userId) {
         synchronized(mMethodMap) {
             final int currentUserId = mSettings.getCurrentUserId();
             if (DEBUG) {
@@ -804,6 +815,12 @@
         }
     }
 
+    void onSwitchUser(@UserIdInt int userId) {
+        synchronized (mMethodMap) {
+            switchUserLocked(userId);
+        }
+    }
+
     public InputMethodManagerService(Context context) {
         mIPackageManager = AppGlobals.getPackageManager();
         mContext = context;
@@ -852,25 +869,6 @@
         mNotificationShown = false;
         int userId = 0;
         try {
-            ActivityManagerNative.getDefault().registerUserSwitchObserver(
-                    new SynchronousUserSwitchObserver() {
-                        @Override
-                        public void onUserSwitching(int newUserId)
-                                throws RemoteException {
-                            synchronized(mMethodMap) {
-                                switchUserLocked(newUserId);
-                            }
-                        }
-
-                        @Override
-                        public void onUserSwitchComplete(int newUserId) throws RemoteException {
-                        }
-
-                        @Override
-                        public void onForegroundProfileSwitch(int newProfileId) {
-                            // Ignore.
-                        }
-                    });
             userId = ActivityManagerNative.getDefault().getCurrentUser().id;
         } catch (RemoteException e) {
             Slog.w(TAG, "Couldn't get current user ID; guessing it's 0", e);
@@ -1960,14 +1958,6 @@
             throw new IllegalArgumentException("Unknown id: " + id);
         }
 
-        if (mCurClient != null && mCurAttribute != null) {
-            // We have already made sure that the package name belongs to the application's UID.
-            // No further UID check is required.
-            if (SystemConfig.getInstance().getFixedImeApps().contains(mCurAttribute.packageName)) {
-                return;
-            }
-        }
-
         // See if we need to notify a subtype change within the same IME.
         if (id.equals(mCurMethodId)) {
             final int subtypeCount = info.getSubtypeCount();
@@ -3598,6 +3588,7 @@
         private static final String ATTR_IME_SUBTYPE_MODE = "imeSubtypeMode";
         private static final String ATTR_IME_SUBTYPE_EXTRA_VALUE = "imeSubtypeExtraValue";
         private static final String ATTR_IS_AUXILIARY = "isAuxiliary";
+        private static final String ATTR_IS_ASCII_CAPABLE = "isAsciiCapable";
         private final AtomicFile mAdditionalInputMethodSubtypeFile;
         private final HashMap<String, InputMethodInfo> mMethodMap;
         private final HashMap<String, List<InputMethodSubtype>> mAdditionalSubtypesMap =
@@ -3694,6 +3685,8 @@
                         out.attribute(null, ATTR_IME_SUBTYPE_EXTRA_VALUE, subtype.getExtraValue());
                         out.attribute(null, ATTR_IS_AUXILIARY,
                                 String.valueOf(subtype.isAuxiliary() ? 1 : 0));
+                        out.attribute(null, ATTR_IS_ASCII_CAPABLE,
+                                String.valueOf(subtype.isAsciiCapable() ? 1 : 0));
                         out.endTag(null, NODE_SUBTYPE);
                     }
                     out.endTag(null, NODE_IMI);
@@ -3759,6 +3752,8 @@
                                 parser.getAttributeValue(null, ATTR_IME_SUBTYPE_EXTRA_VALUE);
                         final boolean isAuxiliary = "1".equals(String.valueOf(
                                 parser.getAttributeValue(null, ATTR_IS_AUXILIARY)));
+                        final boolean isAsciiCapable = "1".equals(String.valueOf(
+                                parser.getAttributeValue(null, ATTR_IS_ASCII_CAPABLE)));
                         final InputMethodSubtype subtype = new InputMethodSubtypeBuilder()
                                 .setSubtypeNameResId(label)
                                 .setSubtypeIconResId(icon)
@@ -3767,6 +3762,7 @@
                                 .setSubtypeMode(imeSubtypeMode)
                                 .setSubtypeExtraValue(imeSubtypeExtraValue)
                                 .setIsAuxiliary(isAuxiliary)
+                                .setIsAsciiCapable(isAsciiCapable)
                                 .build();
                         tempSubtypesArray.add(subtype);
                     }
diff --git a/services/core/java/com/android/server/LockGuard.java b/services/core/java/com/android/server/LockGuard.java
new file mode 100644
index 0000000..3a381ae
--- /dev/null
+++ b/services/core/java/com/android/server/LockGuard.java
@@ -0,0 +1,149 @@
+/*
+ * 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;
+
+import android.util.ArrayMap;
+import android.util.ArraySet;
+import android.util.Slog;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+
+/**
+ * LockGuard is a mechanism to help detect lock inversions inside the system
+ * server. It works by requiring each lock acquisition site to follow this
+ * pattern:
+ *
+ * <pre>
+ * synchronized (LockGuard.guard(lock)) {
+ * }
+ * </pre>
+ *
+ * <pre>
+ * $ find services/ -name "*.java" -exec sed -i -r \
+ *     's/synchronized.?\((.+?)\)/synchronized \(com.android.server.LockGuard.guard\(\1\)\)/' {} \;
+ * </pre>
+ *
+ * The {@link #guard(Object)} method internally verifies that all locking is
+ * done in a consistent order, and will log if any inversion is detected. For
+ * example, if the calling thread is trying to acquire the
+ * {@code ActivityManager} lock while holding the {@code PackageManager} lock,
+ * it will yell.
+ * <p>
+ * This class requires no prior knowledge of locks or their ordering; it derives
+ * all of this data at runtime. However, this means the overhead is
+ * <em>substantial</em> and it should not be enabled by default. For example,
+ * here are some benchmarked timings:
+ * <ul>
+ * <li>An unguarded synchronized block takes 40ns.
+ * <li>A guarded synchronized block takes 50ns when disabled.
+ * <li>A guarded synchronized block takes 460ns per lock checked when enabled.
+ * </ul>
+ */
+public class LockGuard {
+    private static final String TAG = "LockGuard";
+
+    private static ArrayMap<Object, LockInfo> sKnown = new ArrayMap<>(0, true);
+
+    private static class LockInfo {
+        /** Friendly label to describe this lock */
+        public String label;
+
+        /** Child locks that can be acquired while this lock is already held */
+        public ArraySet<Object> children = new ArraySet<>(0, true);
+    }
+
+    private static LockInfo findOrCreateLockInfo(Object lock) {
+        LockInfo info = sKnown.get(lock);
+        if (info == null) {
+            info = new LockInfo();
+            info.label = "0x" + Integer.toHexString(System.identityHashCode(lock)) + " ["
+                    + new Throwable().getStackTrace()[2].toString() + "]";
+            sKnown.put(lock, info);
+        }
+        return info;
+    }
+
+    /**
+     * Check if the calling thread is holding any locks in an inverted order.
+     *
+     * @param lock The lock the calling thread is attempting to acquire.
+     */
+    public static Object guard(Object lock) {
+        // If we already hold this lock, ignore
+        if (lock == null || Thread.holdsLock(lock)) return lock;
+
+        // Check to see if we're already holding any child locks
+        boolean triggered = false;
+        final LockInfo info = findOrCreateLockInfo(lock);
+        for (int i = 0; i < info.children.size(); i++) {
+            final Object child = info.children.valueAt(i);
+            if (child == null) continue;
+
+            if (Thread.holdsLock(child)) {
+                Slog.w(TAG, "Calling thread " + Thread.currentThread().getName() + " is holding "
+                      + lockToString(child) + " while trying to acquire "
+                      + lockToString(lock), new Throwable());
+                triggered = true;
+            }
+        }
+
+        if (!triggered) {
+            // If no trouble found above, record this lock as being a valid
+            // child of all locks currently being held
+            for (int i = 0; i < sKnown.size(); i++) {
+                final Object test = sKnown.keyAt(i);
+                if (test == null || test == lock) continue;
+
+                if (Thread.holdsLock(test)) {
+                    sKnown.valueAt(i).children.add(lock);
+                }
+            }
+        }
+
+        return lock;
+    }
+
+    /**
+     * Report the given lock with a well-known label.
+     */
+    public static void installLock(Object lock, String label) {
+        final LockInfo info = findOrCreateLockInfo(lock);
+        info.label = label;
+    }
+
+    private static String lockToString(Object lock) {
+        final LockInfo info = sKnown.get(lock);
+        if (info != null) {
+            return info.label;
+        } else {
+            return "0x" + Integer.toHexString(System.identityHashCode(lock));
+        }
+    }
+
+    public static void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+        for (int i = 0; i < sKnown.size(); i++) {
+            final Object lock = sKnown.keyAt(i);
+            final LockInfo info = sKnown.valueAt(i);
+            pw.println("Lock " + lockToString(lock) + ":");
+            for (int j = 0; j < info.children.size(); j++) {
+                pw.println("  Child " + lockToString(info.children.valueAt(j)));
+            }
+            pw.println();
+        }
+    }
+}
diff --git a/services/core/java/com/android/server/LockSettingsService.java b/services/core/java/com/android/server/LockSettingsService.java
index c318140..6fb0671 100644
--- a/services/core/java/com/android/server/LockSettingsService.java
+++ b/services/core/java/com/android/server/LockSettingsService.java
@@ -345,9 +345,9 @@
                     final int userId = users.get(user).id;
                     final String OWNER_INFO = Secure.LOCK_SCREEN_OWNER_INFO;
                     String ownerInfo = Settings.Secure.getStringForUser(cr, OWNER_INFO, userId);
-                    if (ownerInfo != null) {
+                    if (!TextUtils.isEmpty(ownerInfo)) {
                         setString(OWNER_INFO, ownerInfo, userId);
-                        Settings.Secure.putStringForUser(cr, ownerInfo, "", userId);
+                        Settings.Secure.putStringForUser(cr, OWNER_INFO, "", userId);
                     }
 
                     // Migrate owner info enabled.  Note there was a bug where older platforms only
@@ -545,9 +545,23 @@
         final UserManager um = (UserManager) mContext.getSystemService(USER_SERVICE);
         final KeyStore ks = KeyStore.getInstance();
 
-        final List<UserInfo> profiles = um.getProfiles(userHandle);
-        for (UserInfo pi : profiles) {
-            ks.onUserPasswordChanged(pi.id, password);
+        if (um.getUserInfo(userHandle).isManagedProfile()) {
+            if (mLockPatternUtils.isSeparateProfileChallengeEnabled(userHandle)) {
+                ks.onUserPasswordChanged(userHandle, password);
+            } else {
+                throw new RuntimeException("Can't set keystore password on a profile that "
+                        + "doesn't have a profile challenge.");
+            }
+        } else {
+            final List<UserInfo> profiles = um.getProfiles(userHandle);
+            for (UserInfo pi : profiles) {
+                // Change password on the given user and all its profiles that don't have
+                // their own profile challenge enabled.
+                if (pi.id == userHandle || (pi.isManagedProfile()
+                        && !mLockPatternUtils.isSeparateProfileChallengeEnabled(pi.id))) {
+                    ks.onUserPasswordChanged(pi.id, password);
+                }
+            }
         }
     }
 
@@ -555,9 +569,23 @@
         final UserManager um = (UserManager) mContext.getSystemService(USER_SERVICE);
         final KeyStore ks = KeyStore.getInstance();
 
-        final List<UserInfo> profiles = um.getProfiles(userHandle);
-        for (UserInfo pi : profiles) {
-            ks.unlock(pi.id, password);
+        if (um.getUserInfo(userHandle).isManagedProfile()) {
+            if (mLockPatternUtils.isSeparateProfileChallengeEnabled(userHandle)) {
+                ks.unlock(userHandle, password);
+            } else {
+                throw new RuntimeException("Can't unlock a profile explicitly if it "
+                        + "doesn't have a profile challenge.");
+            }
+        } else {
+            final List<UserInfo> profiles = um.getProfiles(userHandle);
+            for (UserInfo pi : profiles) {
+                // Unlock the given user and all its profiles that don't have
+                // their own profile challenge enabled.
+                if (pi.id == userHandle || (pi.isManagedProfile()
+                        && !mLockPatternUtils.isSeparateProfileChallengeEnabled(pi.id))) {
+                    ks.unlock(pi.id, password);
+                }
+            }
         }
     }
 
diff --git a/services/core/java/com/android/server/MountService.java b/services/core/java/com/android/server/MountService.java
index 53923ba..4536e04 100644
--- a/services/core/java/com/android/server/MountService.java
+++ b/services/core/java/com/android/server/MountService.java
@@ -839,11 +839,11 @@
         Slog.d(TAG, "Thinking about init, mSystemReady=" + mSystemReady
                 + ", mDaemonConnected=" + mDaemonConnected);
         if (mSystemReady && mDaemonConnected
-                && !StorageManager.isNativeFileBasedEncryptionEnabled()) {
+                && !StorageManager.isFileEncryptedNativeOnly()) {
             // When booting a device without native support, make sure that our
             // user directories are locked or unlocked based on the current
             // emulation status.
-            final boolean initLocked = StorageManager.isEmulatedFileBasedEncryptionEnabled();
+            final boolean initLocked = StorageManager.isFileEncryptedEmulatedOnly();
             Slog.d(TAG, "Setting up emulation state, initlocked=" + initLocked);
             final List<UserInfo> users = mContext.getSystemService(UserManager.class).getUsers();
             for (UserInfo user : users) {
@@ -1940,16 +1940,21 @@
         waitForReady();
 
         if ((mask & StorageManager.DEBUG_EMULATE_FBE) != 0) {
-            if (StorageManager.isNativeFileBasedEncryptionEnabled()) {
+            if (StorageManager.isFileEncryptedNativeOnly()) {
                 throw new IllegalStateException(
                         "Emulation not available on device with native FBE");
             }
 
-            final boolean emulateFbe = (flags & StorageManager.DEBUG_EMULATE_FBE) != 0;
-            SystemProperties.set(StorageManager.PROP_EMULATE_FBE, Boolean.toString(emulateFbe));
+            final long token = Binder.clearCallingIdentity();
+            try {
+                final boolean emulateFbe = (flags & StorageManager.DEBUG_EMULATE_FBE) != 0;
+                SystemProperties.set(StorageManager.PROP_EMULATE_FBE, Boolean.toString(emulateFbe));
 
-            // Perform hard reboot to kick policy into place
-            mContext.getSystemService(PowerManager.class).reboot(null);
+                // Perform hard reboot to kick policy into place
+                mContext.getSystemService(PowerManager.class).reboot(null);
+            } finally {
+                Binder.restoreCallingIdentity(token);
+            }
         }
 
         if ((mask & StorageManager.DEBUG_FORCE_ADOPTABLE) != 0) {
@@ -2806,7 +2811,7 @@
 
     @Override
     public boolean isUserKeyUnlocked(int userId) {
-        if (StorageManager.isFileBasedEncryptionEnabled()) {
+        if (StorageManager.isFileEncryptedNativeOrEmulated()) {
             synchronized (mLock) {
                 return ArrayUtils.contains(mLocalUnlockedUsers, userId);
             }
diff --git a/services/core/java/com/android/server/NetworkManagementService.java b/services/core/java/com/android/server/NetworkManagementService.java
index 799d0bd..329f716 100644
--- a/services/core/java/com/android/server/NetworkManagementService.java
+++ b/services/core/java/com/android/server/NetworkManagementService.java
@@ -22,8 +22,10 @@
 import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_DOZABLE;
 import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_DOZABLE;
 import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_NONE;
+import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_POWERSAVE;
 import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_STANDBY;
 import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NONE;
+import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_POWERSAVE;
 import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_STANDBY;
 import static android.net.NetworkPolicyManager.FIREWALL_RULE_DEFAULT;
 import static android.net.NetworkPolicyManager.FIREWALL_TYPE_BLACKLIST;
@@ -43,7 +45,6 @@
 import static com.android.server.NetworkManagementService.NetdResponseCode.TetheringStatsListResult;
 import static com.android.server.NetworkManagementService.NetdResponseCode.TtyListResult;
 import static com.android.server.NetworkManagementSocketTagger.PROP_QTAGUID_ENABLED;
-
 import android.annotation.NonNull;
 import android.app.ActivityManagerNative;
 import android.content.Context;
@@ -226,6 +227,12 @@
      */
     @GuardedBy("mQuotaLock")
     private SparseIntArray mUidFirewallDozableRules = new SparseIntArray();
+    /**
+     * Set of UIDs that are to be blocked/allowed by firewall controller.  This set of Ids matches
+     * to device on power-save mode.
+     */
+    @GuardedBy("mQuotaLock")
+    private SparseIntArray mUidFirewallPowerSaveRules = new SparseIntArray();
     /** Set of states for the child firewall chains. True if the chain is active. */
     @GuardedBy("mQuotaLock")
     final SparseBooleanArray mFirewallChainStates = new SparseBooleanArray();
@@ -286,8 +293,8 @@
         Watchdog.getInstance().addMonitor(this);
     }
 
-    static NetworkManagementService create(Context context,
-            String socket) throws InterruptedException {
+    static NetworkManagementService create(Context context, String socket)
+            throws InterruptedException {
         final NetworkManagementService service = new NetworkManagementService(context, socket);
         final CountDownLatch connectedSignal = service.mConnectedSignal;
         if (DBG) Slog.d(TAG, "Creating NetworkManagementService");
@@ -303,8 +310,15 @@
     }
 
     public void systemReady() {
-        prepareNativeDaemon();
-        if (DBG) Slog.d(TAG, "Prepared");
+        if (DBG) {
+            final long start = System.currentTimeMillis();
+            prepareNativeDaemon();
+            final long delta = System.currentTimeMillis() - start;
+            Slog.d(TAG, "Prepared in " + delta + "ms");
+            return;
+        } else {
+            prepareNativeDaemon();
+        }
     }
 
     private IBatteryStats getBatteryStats() {
@@ -339,8 +353,7 @@
             for (int i = 0; i < length; i++) {
                 try {
                     mObservers.getBroadcastItem(i).interfaceStatusChanged(iface, up);
-                } catch (RemoteException e) {
-                } catch (RuntimeException e) {
+                } catch (RemoteException | RuntimeException e) {
                 }
             }
         } finally {
@@ -358,8 +371,7 @@
             for (int i = 0; i < length; i++) {
                 try {
                     mObservers.getBroadcastItem(i).interfaceLinkStateChanged(iface, up);
-                } catch (RemoteException e) {
-                } catch (RuntimeException e) {
+                } catch (RemoteException | RuntimeException e) {
                 }
             }
         } finally {
@@ -376,8 +388,7 @@
             for (int i = 0; i < length; i++) {
                 try {
                     mObservers.getBroadcastItem(i).interfaceAdded(iface);
-                } catch (RemoteException e) {
-                } catch (RuntimeException e) {
+                } catch (RemoteException | RuntimeException e) {
                 }
             }
         } finally {
@@ -399,8 +410,7 @@
             for (int i = 0; i < length; i++) {
                 try {
                     mObservers.getBroadcastItem(i).interfaceRemoved(iface);
-                } catch (RemoteException e) {
-                } catch (RuntimeException e) {
+                } catch (RemoteException | RuntimeException e) {
                 }
             }
         } finally {
@@ -417,8 +427,7 @@
             for (int i = 0; i < length; i++) {
                 try {
                     mObservers.getBroadcastItem(i).limitReached(limitName, iface);
-                } catch (RemoteException e) {
-                } catch (RuntimeException e) {
+                } catch (RemoteException | RuntimeException e) {
                 }
             }
         } finally {
@@ -476,8 +485,7 @@
                     try {
                         mObservers.getBroadcastItem(i).interfaceClassDataActivityChanged(
                                 Integer.toString(type), isActive, tsNanos);
-                    } catch (RemoteException e) {
-                    } catch (RuntimeException e) {
+                    } catch (RemoteException | RuntimeException e) {
                     }
                 }
             } finally {
@@ -520,7 +528,7 @@
                 Log.wtf(TAG, "problem enabling bandwidth controls", e);
             }
         } else {
-            Slog.d(TAG, "not enabling bandwidth control");
+            Slog.i(TAG, "not enabling bandwidth control");
         }
 
         SystemProperties.set(PROP_QTAGUID_ENABLED, mBandwidthControlEnabled ? "1" : "0");
@@ -543,7 +551,7 @@
         synchronized (mQuotaLock) {
             int size = mActiveQuotas.size();
             if (size > 0) {
-                Slog.d(TAG, "Pushing " + size + " active quota rules");
+                if (DBG) Slog.d(TAG, "Pushing " + size + " active quota rules");
                 final HashMap<String, Long> activeQuotas = mActiveQuotas;
                 mActiveQuotas = Maps.newHashMap();
                 for (Map.Entry<String, Long> entry : activeQuotas.entrySet()) {
@@ -553,7 +561,7 @@
 
             size = mActiveAlerts.size();
             if (size > 0) {
-                Slog.d(TAG, "Pushing " + size + " active alert rules");
+                if (DBG) Slog.d(TAG, "Pushing " + size + " active alert rules");
                 final HashMap<String, Long> activeAlerts = mActiveAlerts;
                 mActiveAlerts = Maps.newHashMap();
                 for (Map.Entry<String, Long> entry : activeAlerts.entrySet()) {
@@ -563,7 +571,7 @@
 
             size = mUidRejectOnQuota.size();
             if (size > 0) {
-                Slog.d(TAG, "Pushing " + size + " active UID rules");
+                if (DBG) Slog.d(TAG, "Pushing " + size + " active UID rules");
                 final SparseBooleanArray uidRejectOnQuota = mUidRejectOnQuota;
                 mUidRejectOnQuota = new SparseBooleanArray();
                 for (int i = 0; i < uidRejectOnQuota.size(); i++) {
@@ -573,7 +581,7 @@
 
             size = mUidCleartextPolicy.size();
             if (size > 0) {
-                Slog.d(TAG, "Pushing " + size + " active UID cleartext policies");
+                if (DBG) Slog.d(TAG, "Pushing " + size + " active UID cleartext policies");
                 final SparseIntArray local = mUidCleartextPolicy;
                 mUidCleartextPolicy = new SparseIntArray();
                 for (int i = 0; i < local.size(); i++) {
@@ -585,7 +593,7 @@
 
             size = mUidFirewallRules.size();
             if (size > 0) {
-                Slog.d(TAG, "Pushing " + size + " active firewall UID rules");
+                if (DBG) Slog.d(TAG, "Pushing " + size + " active firewall UID rules");
                 final SparseIntArray uidFirewallRules = mUidFirewallRules;
                 mUidFirewallRules = new SparseIntArray();
                 for (int i = 0; i < uidFirewallRules.size(); i++) {
@@ -596,7 +604,7 @@
 
             size = mUidFirewallStandbyRules.size();
             if (size > 0) {
-                Slog.d(TAG, "Pushing " + size + " active firewall standby UID rules");
+                if (DBG) Slog.d(TAG, "Pushing " + size + " active firewall standby UID rules");
                 final SparseIntArray uidFirewallRules = mUidFirewallStandbyRules;
                 mUidFirewallStandbyRules = new SparseIntArray();
                 for (int i = 0; i < uidFirewallRules.size(); i++) {
@@ -610,7 +618,7 @@
 
             size = mUidFirewallDozableRules.size();
             if (size > 0) {
-                Slog.d(TAG, "Pushing " + size + " active firewall dozable UID rules");
+                if (DBG) Slog.d(TAG, "Pushing " + size + " active firewall dozable UID rules");
                 final SparseIntArray uidFirewallRules = mUidFirewallDozableRules;
                 mUidFirewallDozableRules = new SparseIntArray();
                 for (int i = 0; i < uidFirewallRules.size(); i++) {
@@ -621,6 +629,20 @@
             if (mFirewallChainStates.get(FIREWALL_CHAIN_DOZABLE)) {
                 setFirewallChainEnabled(FIREWALL_CHAIN_DOZABLE, true);
             }
+
+            size = mUidFirewallPowerSaveRules.size();
+            if (size > 0) {
+                Slog.d(TAG, "Pushing " + size + " active firewall powersave UID rules");
+                final SparseIntArray uidFirewallRules = mUidFirewallPowerSaveRules;
+                mUidFirewallPowerSaveRules = new SparseIntArray();
+                for (int i = 0; i < uidFirewallRules.size(); i++) {
+                    setFirewallUidRuleInternal(FIREWALL_CHAIN_POWERSAVE, uidFirewallRules.keyAt(i),
+                            uidFirewallRules.valueAt(i));
+                }
+            }
+            if (mFirewallChainStates.get(FIREWALL_CHAIN_POWERSAVE)) {
+                setFirewallChainEnabled(FIREWALL_CHAIN_POWERSAVE, true);
+            }
         }
     }
 
@@ -633,8 +655,7 @@
             for (int i = 0; i < length; i++) {
                 try {
                     mObservers.getBroadcastItem(i).addressUpdated(iface, address);
-                } catch (RemoteException e) {
-                } catch (RuntimeException e) {
+                } catch (RemoteException | RuntimeException e) {
                 }
             }
         } finally {
@@ -651,8 +672,7 @@
             for (int i = 0; i < length; i++) {
                 try {
                     mObservers.getBroadcastItem(i).addressRemoved(iface, address);
-                } catch (RemoteException e) {
-                } catch (RuntimeException e) {
+                } catch (RemoteException | RuntimeException e) {
                 }
             }
         } finally {
@@ -670,8 +690,7 @@
                 try {
                     mObservers.getBroadcastItem(i).interfaceDnsServerInfo(iface, lifetime,
                         addresses);
-                } catch (RemoteException e) {
-                } catch (RuntimeException e) {
+                } catch (RemoteException | RuntimeException e) {
                 }
             }
         } finally {
@@ -692,8 +711,7 @@
                     } else {
                         mObservers.getBroadcastItem(i).routeRemoved(route);
                     }
-                } catch (RemoteException e) {
-                } catch (RuntimeException e) {
+                } catch (RemoteException | RuntimeException e) {
                 }
             }
         } finally {
@@ -1210,7 +1228,7 @@
         // TODO: remove from aidl if nobody calls externally
         mContext.enforceCallingOrSelfPermission(SHUTDOWN, TAG);
 
-        Slog.d(TAG, "Shutting down");
+        Slog.i(TAG, "Shutting down");
     }
 
     @Override
@@ -2023,6 +2041,9 @@
                     case FIREWALL_CHAIN_DOZABLE:
                         chainName = FIREWALL_CHAIN_NAME_DOZABLE;
                         break;
+                    case FIREWALL_CHAIN_POWERSAVE:
+                        chainName = FIREWALL_CHAIN_NAME_POWERSAVE;
+                        break;
                     default:
                         throw new IllegalArgumentException("Bad child chain: " + chain);
                 }
@@ -2039,6 +2060,8 @@
                 return FIREWALL_TYPE_BLACKLIST;
             case FIREWALL_CHAIN_DOZABLE:
                 return FIREWALL_TYPE_WHITELIST;
+            case FIREWALL_CHAIN_POWERSAVE:
+                return FIREWALL_TYPE_WHITELIST;
             default:
                 return isFirewallEnabled() ? FIREWALL_TYPE_WHITELIST : FIREWALL_TYPE_BLACKLIST;
         }
@@ -2138,6 +2161,8 @@
                 return mUidFirewallStandbyRules;
             case FIREWALL_CHAIN_DOZABLE:
                 return mUidFirewallDozableRules;
+            case FIREWALL_CHAIN_POWERSAVE:
+                return mUidFirewallPowerSaveRules;
             case FIREWALL_CHAIN_NONE:
                 return mUidFirewallRules;
             default:
@@ -2151,6 +2176,8 @@
                 return FIREWALL_CHAIN_NAME_STANDBY;
             case FIREWALL_CHAIN_DOZABLE:
                 return FIREWALL_CHAIN_NAME_DOZABLE;
+            case FIREWALL_CHAIN_POWERSAVE:
+                return FIREWALL_CHAIN_NAME_POWERSAVE;
             case FIREWALL_CHAIN_NONE:
                 return FIREWALL_CHAIN_NAME_NONE;
             default:
@@ -2225,8 +2252,7 @@
             for (int i = 0; i < length; i++) {
                 try {
                     mNetworkActivityListeners.getBroadcastItem(i).onNetworkActive();
-                } catch (RemoteException e) {
-                } catch (RuntimeException e) {
+                } catch (RemoteException | RuntimeException e) {
                 }
             }
         } finally {
@@ -2271,43 +2297,25 @@
         }
 
         synchronized (mUidFirewallRules) {
-            pw.print("UID firewall rule: [");
-            final int size = mUidFirewallRules.size();
-            for (int i = 0; i < size; i++) {
-                pw.print(mUidFirewallRules.keyAt(i));
-                pw.print(":");
-                pw.print(mUidFirewallRules.valueAt(i));
-                if (i < size - 1) pw.print(",");
-            }
-            pw.println("]");
+            dumpUidFirewallRule(pw, "", mUidFirewallRules);
         }
 
         pw.println("UID firewall standby chain enabled: " +
                 mFirewallChainStates.get(FIREWALL_CHAIN_STANDBY));
         synchronized (mUidFirewallStandbyRules) {
-            pw.print("UID firewall standby rule: [");
-            final int size = mUidFirewallStandbyRules.size();
-            for (int i = 0; i < size; i++) {
-                pw.print(mUidFirewallStandbyRules.keyAt(i));
-                pw.print(":");
-                pw.print(mUidFirewallStandbyRules.valueAt(i));
-                if (i < size - 1) pw.print(",");
-            }
-            pw.println("]");
+            dumpUidFirewallRule(pw, FIREWALL_CHAIN_NAME_STANDBY, mUidFirewallStandbyRules);
         }
 
         pw.println("UID firewall dozable chain enabled: " +
                 mFirewallChainStates.get(FIREWALL_CHAIN_DOZABLE));
         synchronized (mUidFirewallDozableRules) {
-            pw.print("UID firewall dozable rule: [");
-            final int size = mUidFirewallDozableRules.size();
-            for (int i = 0; i < size; i++) {
-                pw.print(mUidFirewallDozableRules.keyAt(i));
-                pw.print(":");
-                pw.print(mUidFirewallDozableRules.valueAt(i));
-                if (i < size - 1) pw.print(",");
-            }
-            pw.println("]");
+            dumpUidFirewallRule(pw, FIREWALL_CHAIN_NAME_DOZABLE, mUidFirewallDozableRules);
+        }
+
+        pw.println("UID firewall powersave chain enabled: " +
+                mFirewallChainStates.get(FIREWALL_CHAIN_POWERSAVE));
+        synchronized (mUidFirewallPowerSaveRules) {
+            dumpUidFirewallRule(pw, FIREWALL_CHAIN_NAME_POWERSAVE, mUidFirewallPowerSaveRules);
         }
 
         synchronized (mIdleTimerLock) {
@@ -2324,6 +2332,20 @@
         pw.print("Firewall enabled: "); pw.println(mFirewallEnabled);
     }
 
+    private void dumpUidFirewallRule(PrintWriter pw, String name, SparseIntArray rules) {
+        pw.print("UID firewall");
+        pw.print(name);
+        pw.print(" rule: [");
+        final int size = rules.size();
+        for (int i = 0; i < size; i++) {
+            pw.print(rules.keyAt(i));
+            pw.print(":");
+            pw.print(rules.valueAt(i));
+            if (i < size - 1) pw.print(",");
+        }
+        pw.println("]");
+    }
+
     @Override
     public void createPhysicalNetwork(int netId, String permission) {
         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
diff --git a/services/core/java/com/android/server/NetworkTimeUpdateService.java b/services/core/java/com/android/server/NetworkTimeUpdateService.java
index 3f0664d..b64c65d 100644
--- a/services/core/java/com/android/server/NetworkTimeUpdateService.java
+++ b/services/core/java/com/android/server/NetworkTimeUpdateService.java
@@ -23,8 +23,10 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
+import android.content.pm.PackageManager;
 import android.database.ContentObserver;
 import android.net.ConnectivityManager;
+import android.os.Binder;
 import android.os.Handler;
 import android.os.HandlerThread;
 import android.os.Looper;
@@ -34,10 +36,14 @@
 import android.provider.Settings;
 import android.util.Log;
 import android.util.NtpTrustedTime;
+import android.util.TimeUtils;
 import android.util.TrustedTime;
 
 import com.android.internal.telephony.TelephonyIntents;
 
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+
 /**
  * Monitors the network time and updates the system time if it is out of sync
  * and there hasn't been any NITZ update from the carrier recently.
@@ -48,7 +54,7 @@
  * available.
  * </p>
  */
-public class NetworkTimeUpdateService {
+public class NetworkTimeUpdateService extends Binder {
 
     private static final String TAG = "NetworkTimeUpdateService";
     private static final boolean DBG = false;
@@ -59,6 +65,8 @@
 
     private static final String ACTION_POLL =
             "com.android.server.NetworkTimeUpdateService.action.POLL";
+
+    private static final int NETWORK_CHANGE_EVENT_DELAY_MS = 1000;
     private static int POLL_REQUEST = 0;
 
     private static final long NOT_SET = -1;
@@ -245,6 +253,7 @@
         @Override
         public void onReceive(Context context, Intent intent) {
             String action = intent.getAction();
+            if (DBG) Log.d(TAG, "Received " + action);
             if (TelephonyIntents.ACTION_NETWORK_SET_TIME.equals(action)) {
                 mNitzTimeSetTime = SystemClock.elapsedRealtime();
             } else if (TelephonyIntents.ACTION_NETWORK_SET_TIMEZONE.equals(action)) {
@@ -260,8 +269,11 @@
         public void onReceive(Context context, Intent intent) {
             String action = intent.getAction();
             if (ConnectivityManager.CONNECTIVITY_ACTION.equals(action)) {
+                if (DBG) Log.d(TAG, "Received CONNECTIVITY_ACTION ");
                 // Don't bother checking if we have connectivity, NtpTrustedTime does that for us.
-                mHandler.obtainMessage(EVENT_NETWORK_CHANGED).sendToTarget();
+                Message message = mHandler.obtainMessage(EVENT_NETWORK_CHANGED);
+                // Send with a short delay to make sure the network is ready for use
+                mHandler.sendMessageDelayed(message, NETWORK_CHANGE_EVENT_DELAY_MS);
             }
         }
     };
@@ -308,4 +320,28 @@
             mHandler.obtainMessage(mMsg).sendToTarget();
         }
     }
+
+    @Override
+    protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
+                != PackageManager.PERMISSION_GRANTED) {
+            pw.println("Permission Denial: can't dump NetworkTimeUpdateService from from pid="
+                    + Binder.getCallingPid()
+                    + ", uid=" + Binder.getCallingUid()
+                    + " without permission "
+                    + android.Manifest.permission.DUMP);
+            return;
+        }
+        pw.print("PollingIntervalMs: ");
+        TimeUtils.formatDuration(mPollingIntervalMs, pw);
+        pw.print("\nPollingIntervalShorterMs: ");
+        TimeUtils.formatDuration(mPollingIntervalShorterMs, pw);
+        pw.println("\nTryAgainTimesMax: " + mTryAgainTimesMax);
+        pw.print("TimeErrorThresholdMs: ");
+        TimeUtils.formatDuration(mTimeErrorThresholdMs, pw);
+        pw.println("\nTryAgainCounter: " + mTryAgainCounter);
+        pw.print("LastNtpFetchTime: ");
+        TimeUtils.formatDuration(mLastNtpFetchTime, pw);
+        pw.println();
+    }
 }
diff --git a/services/core/java/com/android/server/NsdService.java b/services/core/java/com/android/server/NsdService.java
index f4c6225..11aef17 100644
--- a/services/core/java/com/android/server/NsdService.java
+++ b/services/core/java/com/android/server/NsdService.java
@@ -58,7 +58,7 @@
     private static final String TAG = "NsdService";
     private static final String MDNS_TAG = "mDnsConnector";
 
-    private static final boolean DBG = true;
+    private static final boolean DBG = false;
 
     private Context mContext;
     private ContentResolver mContentResolver;
diff --git a/services/core/java/com/android/server/RecoverySystemService.java b/services/core/java/com/android/server/RecoverySystemService.java
index d237fe7..d284d07 100644
--- a/services/core/java/com/android/server/RecoverySystemService.java
+++ b/services/core/java/com/android/server/RecoverySystemService.java
@@ -17,6 +17,8 @@
 package com.android.server;
 
 import android.content.Context;
+import android.net.LocalSocket;
+import android.net.LocalSocketAddress;
 import android.os.IRecoverySystem;
 import android.os.IRecoverySystemProgressListener;
 import android.os.RecoverySystem;
@@ -26,9 +28,11 @@
 import android.system.Os;
 import android.util.Slog;
 
-import java.io.BufferedReader;
+import libcore.io.IoUtils;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
 import java.io.File;
-import java.io.FileReader;
 import java.io.FileWriter;
 import java.io.IOException;
 
@@ -43,10 +47,10 @@
     private static final String TAG = "RecoverySystemService";
     private static final boolean DEBUG = false;
 
-    // A pipe file to monitor the uncrypt progress.
-    private static final String UNCRYPT_STATUS_FILE = "/cache/recovery/uncrypt_status";
-    // Temporary command file to communicate between the system server and uncrypt.
-    private static final String COMMAND_FILE = "/cache/recovery/command";
+    // The socket at /dev/socket/uncrypt to communicate with uncrypt.
+    private static final String UNCRYPT_SOCKET = "uncrypt";
+
+    private static final int SOCKET_CONNECTION_MAX_RETRY = 30;
 
     private Context mContext;
 
@@ -79,60 +83,63 @@
                 return false;
             }
 
-            // Create the status pipe file to communicate with uncrypt.
-            new File(UNCRYPT_STATUS_FILE).delete();
-            try {
-                Os.mkfifo(UNCRYPT_STATUS_FILE, 0600);
-            } catch (ErrnoException e) {
-                Slog.e(TAG, "ErrnoException when creating named pipe \"" + UNCRYPT_STATUS_FILE +
-                        "\": " + e.getMessage());
-                return false;
-            }
-
             // Trigger uncrypt via init.
             SystemProperties.set("ctl.start", "uncrypt");
 
-            // Read the status from the pipe.
-            try (BufferedReader reader = new BufferedReader(new FileReader(UNCRYPT_STATUS_FILE))) {
+            // Connect to the uncrypt service socket.
+            LocalSocket socket = connectService();
+            if (socket == null) {
+                Slog.e(TAG, "Failed to connect to uncrypt socket");
+                return false;
+            }
+
+            // Read the status from the socket.
+            try (DataInputStream dis = new DataInputStream(socket.getInputStream());
+                    DataOutputStream dos = new DataOutputStream(socket.getOutputStream())) {
                 int lastStatus = Integer.MIN_VALUE;
                 while (true) {
-                    String str = reader.readLine();
-                    try {
-                        int status = Integer.parseInt(str);
+                    int status = dis.readInt();
+                    // Avoid flooding the log with the same message.
+                    if (status == lastStatus && lastStatus != Integer.MIN_VALUE) {
+                        continue;
+                    }
+                    lastStatus = status;
 
-                        // Avoid flooding the log with the same message.
-                        if (status == lastStatus && lastStatus != Integer.MIN_VALUE) {
-                            continue;
-                        }
-                        lastStatus = status;
-
-                        if (status >= 0 && status <= 100) {
-                            // Update status
-                            Slog.i(TAG, "uncrypt read status: " + status);
-                            if (listener != null) {
-                                try {
-                                    listener.onProgress(status);
-                                } catch (RemoteException unused) {
-                                    Slog.w(TAG, "RemoteException when posting progress");
-                                }
+                    if (status >= 0 && status <= 100) {
+                        // Update status
+                        Slog.i(TAG, "uncrypt read status: " + status);
+                        if (listener != null) {
+                            try {
+                                listener.onProgress(status);
+                            } catch (RemoteException unused) {
+                                Slog.w(TAG, "RemoteException when posting progress");
                             }
-                            if (status == 100) {
-                                Slog.i(TAG, "uncrypt successfully finished.");
-                                break;
-                            }
-                        } else {
-                            // Error in /system/bin/uncrypt.
-                            Slog.e(TAG, "uncrypt failed with status: " + status);
-                            return false;
                         }
-                    } catch (NumberFormatException unused) {
-                        Slog.e(TAG, "uncrypt invalid status received: " + str);
+                        if (status == 100) {
+                            Slog.i(TAG, "uncrypt successfully finished.");
+                            // Ack receipt of the final status code. uncrypt
+                            // waits for the ack so the socket won't be
+                            // destroyed before we receive the code.
+                            dos.writeInt(0);
+                            dos.flush();
+                            break;
+                        }
+                    } else {
+                        // Error in /system/bin/uncrypt.
+                        Slog.e(TAG, "uncrypt failed with status: " + status);
+                        // Ack receipt of the final status code. uncrypt waits
+                        // for the ack so the socket won't be destroyed before
+                        // we receive the code.
+                        dos.writeInt(0);
+                        dos.flush();
                         return false;
                     }
                 }
-            } catch (IOException unused) {
-                Slog.e(TAG, "IOException when reading \"" + UNCRYPT_STATUS_FILE + "\".");
+            } catch (IOException e) {
+                Slog.e(TAG, "IOException when reading status: " + e);
                 return false;
+            } finally {
+                IoUtils.closeQuietly(socket);
             }
 
             return true;
@@ -150,29 +157,35 @@
             return setupOrClearBcb(true, command);
         }
 
-        private boolean setupOrClearBcb(boolean isSetup, String command) {
-            mContext.enforceCallingOrSelfPermission(android.Manifest.permission.RECOVERY, null);
-
-            if (isSetup) {
-                // Set up the command file to be read by uncrypt.
-                try (FileWriter commandFile = new FileWriter(COMMAND_FILE)) {
-                    commandFile.write(command + "\n");
-                } catch (IOException e) {
-                    Slog.e(TAG, "IOException when writing \"" + COMMAND_FILE +
-                            "\": " + e.getMessage());
-                    return false;
+        private LocalSocket connectService() {
+            LocalSocket socket = new LocalSocket();
+            boolean done = false;
+            // The uncrypt socket will be created by init upon receiving the
+            // service request. It may not be ready by this point. So we will
+            // keep retrying until success or reaching timeout.
+            for (int retry = 0; retry < SOCKET_CONNECTION_MAX_RETRY; retry++) {
+                try {
+                    socket.connect(new LocalSocketAddress(UNCRYPT_SOCKET,
+                            LocalSocketAddress.Namespace.RESERVED));
+                    done = true;
+                    break;
+                } catch (IOException unused) {
+                    try {
+                        Thread.sleep(1000);
+                    } catch (InterruptedException e) {
+                        Slog.w(TAG, "Interrupted: " + e);
+                    }
                 }
             }
-
-            // Create the status pipe file to communicate with uncrypt.
-            new File(UNCRYPT_STATUS_FILE).delete();
-            try {
-                Os.mkfifo(UNCRYPT_STATUS_FILE, 0600);
-            } catch (ErrnoException e) {
-                Slog.e(TAG, "ErrnoException when creating named pipe \"" +
-                        UNCRYPT_STATUS_FILE + "\": " + e.getMessage());
-                return false;
+            if (!done) {
+                Slog.e(TAG, "Timed out connecting to uncrypt socket");
+                return null;
             }
+            return socket;
+        }
+
+        private boolean setupOrClearBcb(boolean isSetup, String command) {
+            mContext.enforceCallingOrSelfPermission(android.Manifest.permission.RECOVERY, null);
 
             if (isSetup) {
                 SystemProperties.set("ctl.start", "setup-bcb");
@@ -180,34 +193,45 @@
                 SystemProperties.set("ctl.start", "clear-bcb");
             }
 
-            // Read the status from the pipe.
-            try (BufferedReader reader = new BufferedReader(new FileReader(UNCRYPT_STATUS_FILE))) {
-                while (true) {
-                    String str = reader.readLine();
-                    try {
-                        int status = Integer.parseInt(str);
-
-                        if (status == 100) {
-                            Slog.i(TAG, "uncrypt " + (isSetup ? "setup" : "clear") +
-                                    " bcb successfully finished.");
-                            break;
-                        } else {
-                            // Error in /system/bin/uncrypt.
-                            Slog.e(TAG, "uncrypt failed with status: " + status);
-                            return false;
-                        }
-                    } catch (NumberFormatException unused) {
-                        Slog.e(TAG, "uncrypt invalid status received: " + str);
-                        return false;
-                    }
-                }
-            } catch (IOException unused) {
-                Slog.e(TAG, "IOException when reading \"" + UNCRYPT_STATUS_FILE + "\".");
+            // Connect to the uncrypt service socket.
+            LocalSocket socket = connectService();
+            if (socket == null) {
+                Slog.e(TAG, "Failed to connect to uncrypt socket");
                 return false;
             }
 
-            // Delete the command file as we don't need it anymore.
-            new File(COMMAND_FILE).delete();
+            try (DataInputStream dis = new DataInputStream(socket.getInputStream());
+                    DataOutputStream dos = new DataOutputStream(socket.getOutputStream())) {
+                // Send the BCB commands if it's to setup BCB.
+                if (isSetup) {
+                    dos.writeInt(command.length());
+                    dos.writeBytes(command);
+                    dos.flush();
+                }
+
+                // Read the status from the socket.
+                int status = dis.readInt();
+
+                // Ack receipt of the status code. uncrypt waits for the ack so
+                // the socket won't be destroyed before we receive the code.
+                dos.writeInt(0);
+                dos.flush();
+
+                if (status == 100) {
+                    Slog.i(TAG, "uncrypt " + (isSetup ? "setup" : "clear") +
+                            " bcb successfully finished.");
+                } else {
+                    // Error in /system/bin/uncrypt.
+                    Slog.e(TAG, "uncrypt failed with status: " + status);
+                    return false;
+                }
+            } catch (IOException e) {
+                Slog.e(TAG, "IOException when getting output stream: " + e);
+                return false;
+            } finally {
+                IoUtils.closeQuietly(socket);
+            }
+
             return true;
         }
     }
diff --git a/services/core/java/com/android/server/SystemConfig.java b/services/core/java/com/android/server/SystemConfig.java
index 7bdd3e2..30e0ceb 100644
--- a/services/core/java/com/android/server/SystemConfig.java
+++ b/services/core/java/com/android/server/SystemConfig.java
@@ -101,8 +101,9 @@
     // background while in power save mode, as read from the configuration files.
     final ArraySet<String> mAllowInPowerSave = new ArraySet<>();
 
-    // These are the app package names that should not allow IME switching.
-    final ArraySet<String> mFixedImeApps = new ArraySet<>();
+    // These are the packages that are white-listed to be able to run in the
+    // background while in data-usage save mode, as read from the configuration files.
+    final ArraySet<String> mAllowInDataUsageSave = new ArraySet<>();
 
     // These are the package names of apps which should be in the 'always'
     // URL-handling state upon factory reset.
@@ -151,8 +152,8 @@
         return mAllowInPowerSave;
     }
 
-    public ArraySet<String> getFixedImeApps() {
-        return mFixedImeApps;
+    public ArraySet<String> getAllowInDataUsageSave() {
+        return mAllowInDataUsageSave;
     }
 
     public ArraySet<String> getLinkedApps() {
@@ -392,13 +393,13 @@
                     XmlUtils.skipCurrentTag(parser);
                     continue;
 
-                } else if ("fixed-ime-app".equals(name) && allowAll) {
+                } else if ("allow-in-data-usage-save".equals(name) && allowAll) {
                     String pkgname = parser.getAttributeValue(null, "package");
                     if (pkgname == null) {
-                        Slog.w(TAG, "<fixed-ime-app> without package in " + permFile + " at "
-                                + parser.getPositionDescription());
+                        Slog.w(TAG, "<allow-in-data-usage-save> without package in " + permFile
+                                + " at " + parser.getPositionDescription());
                     } else {
-                        mFixedImeApps.add(pkgname);
+                        mAllowInDataUsageSave.add(pkgname);
                     }
                     XmlUtils.skipCurrentTag(parser);
                     continue;
@@ -445,7 +446,7 @@
 
         // Some devices can be field-converted to FBE, so offer to splice in
         // those features if not already defined by the static config
-        if (StorageManager.isNativeFileBasedEncryptionEnabled()) {
+        if (StorageManager.isFileEncryptedNativeOnly()) {
             addFeature(PackageManager.FEATURE_FILE_BASED_ENCRYPTION, 0);
             addFeature(PackageManager.FEATURE_SECURELY_REMOVES_USERS, 0);
         }
diff --git a/services/core/java/com/android/server/TextServicesManagerService.java b/services/core/java/com/android/server/TextServicesManagerService.java
index c4b4cbe..306e933 100644
--- a/services/core/java/com/android/server/TextServicesManagerService.java
+++ b/services/core/java/com/android/server/TextServicesManagerService.java
@@ -27,9 +27,10 @@
 
 import org.xmlpull.v1.XmlPullParserException;
 
+import android.annotation.NonNull;
+import android.annotation.UserIdInt;
 import android.app.ActivityManagerNative;
 import android.app.AppGlobals;
-import android.app.SynchronousUserSwitchObserver;
 import android.content.BroadcastReceiver;
 import android.content.ComponentName;
 import android.content.ContentResolver;
@@ -76,16 +77,72 @@
     private final Context mContext;
     private boolean mSystemReady;
     private final TextServicesMonitor mMonitor;
-    private final HashMap<String, SpellCheckerInfo> mSpellCheckerMap =
-            new HashMap<String, SpellCheckerInfo>();
-    private final ArrayList<SpellCheckerInfo> mSpellCheckerList = new ArrayList<SpellCheckerInfo>();
-    private final HashMap<String, SpellCheckerBindGroup> mSpellCheckerBindGroups =
-            new HashMap<String, SpellCheckerBindGroup>();
+    private final HashMap<String, SpellCheckerInfo> mSpellCheckerMap = new HashMap<>();
+    private final ArrayList<SpellCheckerInfo> mSpellCheckerList = new ArrayList<>();
+    private final HashMap<String, SpellCheckerBindGroup> mSpellCheckerBindGroups = new HashMap<>();
     private final TextServicesSettings mSettings;
+    @NonNull
+    private final UserManager mUserManager;
 
-    public void systemRunning() {
-        if (!mSystemReady) {
-            mSystemReady = true;
+    public static final class Lifecycle extends SystemService {
+        private TextServicesManagerService mService;
+
+        public Lifecycle(Context context) {
+            super(context);
+            mService = new TextServicesManagerService(context);
+        }
+
+        @Override
+        public void onStart() {
+            publishBinderService(Context.TEXT_SERVICES_MANAGER_SERVICE, mService);
+        }
+
+        @Override
+        public void onSwitchUser(@UserIdInt int userHandle) {
+            // Called on the system server's main looper thread.
+            // TODO: Dispatch this to a worker thread as needed.
+            mService.onSwitchUser(userHandle);
+        }
+
+        @Override
+        public void onBootPhase(int phase) {
+            // Called on the system server's main looper thread.
+            // TODO: Dispatch this to a worker thread as needed.
+            if (phase == SystemService.PHASE_ACTIVITY_MANAGER_READY) {
+                mService.systemRunning();
+            }
+        }
+
+        @Override
+        public void onUnlockUser(@UserIdInt int userHandle) {
+            // Called on the system server's main looper thread.
+            // TODO: Dispatch this to a worker thread as needed.
+            mService.onUnlockUser(userHandle);
+        }
+    }
+
+    void systemRunning() {
+        synchronized (mSpellCheckerMap) {
+            if (!mSystemReady) {
+                mSystemReady = true;
+                resetInternalState(mSettings.getCurrentUserId());
+            }
+        }
+    }
+
+    void onSwitchUser(@UserIdInt int userId) {
+        synchronized (mSpellCheckerMap) {
+            resetInternalState(userId);
+        }
+    }
+
+    void onUnlockUser(@UserIdInt int userId) {
+        synchronized(mSpellCheckerMap) {
+            final int currentUserId = mSettings.getCurrentUserId();
+            if (userId != currentUserId) {
+                return;
+            }
+            resetInternalState(currentUserId);
         }
     }
 
@@ -93,6 +150,8 @@
         mSystemReady = false;
         mContext = context;
 
+        mUserManager = mContext.getSystemService(UserManager.class);
+
         final IntentFilter broadcastFilter = new IntentFilter();
         broadcastFilter.addAction(Intent.ACTION_USER_ADDED);
         broadcastFilter.addAction(Intent.ACTION_USER_REMOVED);
@@ -100,38 +159,25 @@
 
         int userId = UserHandle.USER_SYSTEM;
         try {
-            ActivityManagerNative.getDefault().registerUserSwitchObserver(
-                    new SynchronousUserSwitchObserver() {
-                        @Override
-                        public void onUserSwitching(int newUserId) throws RemoteException {
-                            synchronized(mSpellCheckerMap) {
-                                switchUserLocked(newUserId);
-                            }
-                        }
-
-                        @Override
-                        public void onUserSwitchComplete(int newUserId) throws RemoteException {
-                        }
-
-                        @Override
-                        public void onForegroundProfileSwitch(int newProfileId) {
-                            // Ignore.
-                        }
-                    });
             userId = ActivityManagerNative.getDefault().getCurrentUser().id;
         } catch (RemoteException e) {
             Slog.w(TAG, "Couldn't get current user ID; guessing it's 0", e);
         }
         mMonitor = new TextServicesMonitor();
         mMonitor.register(context, null, true);
-        mSettings = new TextServicesSettings(context.getContentResolver(), userId);
+        final boolean useCopyOnWriteSettings =
+                !mSystemReady || !mUserManager.isUserUnlocked(userId);
+        mSettings = new TextServicesSettings(context.getContentResolver(), userId,
+                useCopyOnWriteSettings);
 
-        // "switchUserLocked" initializes the states for the foreground user
-        switchUserLocked(userId);
+        // "resetInternalState" initializes the states for the foreground user
+        resetInternalState(userId);
     }
 
-    private void switchUserLocked(int userId) {
-        mSettings.setCurrentUserId(userId);
+    private void resetInternalState(@UserIdInt int userId) {
+        final boolean useCopyOnWriteSettings =
+                !mSystemReady || !mUserManager.isUserUnlocked(userId);
+        mSettings.switchCurrentUser(userId, useCopyOnWriteSettings);
         updateCurrentProfileIds();
         unbindServiceLocked();
         buildSpellCheckerMapLocked(mContext, mSpellCheckerList, mSpellCheckerMap, mSettings);
@@ -148,8 +194,7 @@
     }
 
     void updateCurrentProfileIds() {
-        List<UserInfo> profiles =
-                UserManager.get(mContext).getProfiles(mSettings.getCurrentUserId());
+        final List<UserInfo> profiles = mUserManager.getProfiles(mSettings.getCurrentUserId());
         int[] currentProfileIds = new int[profiles.size()]; // profiles will not be null
         for (int i = 0; i < currentProfileIds.length; i++) {
             currentProfileIds[i] = profiles.get(i).id;
@@ -214,6 +259,9 @@
         list.clear();
         map.clear();
         final PackageManager pm = context.getPackageManager();
+        // Note: We do not specify PackageManager.MATCH_ENCRYPTION_* flags here because the default
+        // behavior of PackageManager is exactly what we want.  It by default picks up appropriate
+        // services depending on the unlock state for the specified user.
         final List<ResolveInfo> services = pm.queryIntentServicesAsUser(
                 new Intent(SpellCheckerService.SERVICE_INTERFACE), PackageManager.GET_META_DATA,
                 settings.getCurrentUserId());
@@ -615,8 +663,7 @@
             Slog.d(TAG, "FinishSpellCheckerService");
         }
         synchronized(mSpellCheckerMap) {
-            final ArrayList<SpellCheckerBindGroup> removeList =
-                    new ArrayList<SpellCheckerBindGroup>();
+            final ArrayList<SpellCheckerBindGroup> removeList = new ArrayList<>();
             for (SpellCheckerBindGroup group : mSpellCheckerBindGroups.values()) {
                 if (group == null) continue;
                 // Use removeList to avoid modifying mSpellCheckerBindGroups in this loop.
@@ -757,50 +804,36 @@
 
         synchronized(mSpellCheckerMap) {
             pw.println("Current Text Services Manager state:");
-            pw.println("  Spell Checker Map:");
-            for (Map.Entry<String, SpellCheckerInfo> ent : mSpellCheckerMap.entrySet()) {
-                pw.print("    "); pw.print(ent.getKey()); pw.println(":");
-                SpellCheckerInfo info = ent.getValue();
-                pw.print("      "); pw.print("id="); pw.println(info.getId());
-                pw.print("      "); pw.print("comp=");
-                        pw.println(info.getComponent().toShortString());
-                int NS = info.getSubtypeCount();
-                for (int i=0; i<NS; i++) {
-                    SpellCheckerSubtype st = info.getSubtypeAt(i);
-                    pw.print("      "); pw.print("Subtype #"); pw.print(i); pw.println(":");
-                    pw.print("        "); pw.print("locale="); pw.println(st.getLocale());
-                    pw.print("        "); pw.print("extraValue=");
-                            pw.println(st.getExtraValue());
-                }
+            pw.println("  Spell Checkers:");
+            int spellCheckerIndex = 0;
+            for (final SpellCheckerInfo info : mSpellCheckerMap.values()) {
+                pw.println("  Spell Checker #" + spellCheckerIndex);
+                info.dump(pw, "    ");
+                ++spellCheckerIndex;
             }
             pw.println("");
             pw.println("  Spell Checker Bind Groups:");
-            for (Map.Entry<String, SpellCheckerBindGroup> ent
+            for (final Map.Entry<String, SpellCheckerBindGroup> ent
                     : mSpellCheckerBindGroups.entrySet()) {
-                SpellCheckerBindGroup grp = ent.getValue();
-                pw.print("    "); pw.print(ent.getKey()); pw.print(" ");
-                        pw.print(grp); pw.println(":");
-                pw.print("      "); pw.print("mInternalConnection=");
-                        pw.println(grp.mInternalConnection);
-                pw.print("      "); pw.print("mSpellChecker=");
-                        pw.println(grp.mSpellChecker);
-                pw.print("      "); pw.print("mBound="); pw.print(grp.mBound);
-                        pw.print(" mConnected="); pw.println(grp.mConnected);
-                int NL = grp.mListeners.size();
-                for (int i=0; i<NL; i++) {
-                    InternalDeathRecipient listener = grp.mListeners.get(i);
-                    pw.print("      "); pw.print("Listener #"); pw.print(i); pw.println(":");
-                    pw.print("        "); pw.print("mTsListener=");
-                            pw.println(listener.mTsListener);
-                    pw.print("        "); pw.print("mScListener=");
-                            pw.println(listener.mScListener);
-                    pw.print("        "); pw.print("mGroup=");
-                            pw.println(listener.mGroup);
-                    pw.print("        "); pw.print("mScLocale=");
-                            pw.print(listener.mScLocale);
-                            pw.print(" mUid="); pw.println(listener.mUid);
+                final SpellCheckerBindGroup grp = ent.getValue();
+                pw.println("    " + ent.getKey() + " " + grp + ":");
+                pw.println("      " + "mInternalConnection=" + grp.mInternalConnection);
+                pw.println("      " + "mSpellChecker=" + grp.mSpellChecker);
+                pw.println("      " + "mBound=" + grp.mBound + " mConnected=" + grp.mConnected);
+                final int N = grp.mListeners.size();
+                for (int i = 0; i < N; i++) {
+                    final InternalDeathRecipient listener = grp.mListeners.get(i);
+                    pw.println("      " + "Listener #" + i + ":");
+                    pw.println("        " + "mTsListener=" + listener.mTsListener);
+                    pw.println("        " + "mScListener=" + listener.mScListener);
+                    pw.println("        " + "mGroup=" + listener.mGroup);
+                    pw.println("        " + "mScLocale=" + listener.mScLocale
+                            + " mUid=" + listener.mUid);
                 }
             }
+            pw.println("");
+            pw.println("  mSettings:");
+            mSettings.dumpLocked(pw, "    ");
         }
     }
 
@@ -811,7 +844,7 @@
         private final String TAG = SpellCheckerBindGroup.class.getSimpleName();
         private final InternalServiceConnection mInternalConnection;
         private final CopyOnWriteArrayList<InternalDeathRecipient> mListeners =
-                new CopyOnWriteArrayList<InternalDeathRecipient>();
+                new CopyOnWriteArrayList<>();
         public boolean mBound;
         public ISpellCheckerService mSpellChecker;
         public boolean mConnected;
@@ -885,8 +918,7 @@
             }
             synchronized(mSpellCheckerMap) {
                 final int size = mListeners.size();
-                final ArrayList<InternalDeathRecipient> removeList =
-                        new ArrayList<InternalDeathRecipient>();
+                final ArrayList<InternalDeathRecipient> removeList = new ArrayList<>();
                 for (int i = 0; i < size; ++i) {
                     final InternalDeathRecipient tempRecipient = mListeners.get(i);
                     if(tempRecipient.hasSpellCheckerListener(listener)) {
@@ -1015,23 +1047,85 @@
 
     private static class TextServicesSettings {
         private final ContentResolver mResolver;
+        @UserIdInt
         private int mCurrentUserId;
         @GuardedBy("mLock")
         private int[] mCurrentProfileIds = new int[0];
         private Object mLock = new Object();
 
-        public TextServicesSettings(ContentResolver resolver, int userId) {
+        /**
+         * On-memory data store to emulate when {@link #mCopyOnWrite} is {@code true}.
+         */
+        private final HashMap<String, String> mCopyOnWriteDataStore = new HashMap<>();
+        private boolean mCopyOnWrite = false;
+
+        public TextServicesSettings(ContentResolver resolver, @UserIdInt int userId,
+                boolean copyOnWrite) {
             mResolver = resolver;
-            mCurrentUserId = userId;
+            switchCurrentUser(userId, copyOnWrite);
         }
 
-        public void setCurrentUserId(int userId) {
+        /**
+         * Must be called when the current user is changed.
+         *
+         * @param userId The user ID.
+         * @param copyOnWrite If {@code true}, for each settings key
+         * (e.g. {@link Settings.Secure#SELECTED_SPELL_CHECKER}) we use the actual settings on the
+         * {@link Settings.Secure} until we do the first write operation.
+         */
+        public void switchCurrentUser(@UserIdInt int userId, boolean copyOnWrite) {
             if (DBG) {
                 Slog.d(TAG, "--- Swtich the current user from " + mCurrentUserId + " to "
                         + userId + ", new ime = " + getSelectedSpellChecker());
             }
+            if (mCurrentUserId != userId || mCopyOnWrite != copyOnWrite) {
+                mCopyOnWriteDataStore.clear();
+                // TODO: mCurrentProfileIds should be cleared here.
+            }
             // TSMS settings are kept per user, so keep track of current user
             mCurrentUserId = userId;
+            mCopyOnWrite = copyOnWrite;
+            // TODO: mCurrentProfileIds should be updated here.
+        }
+
+        private void putString(final String key, final String str) {
+            if (mCopyOnWrite) {
+                mCopyOnWriteDataStore.put(key, str);
+            } else {
+                Settings.Secure.putStringForUser(mResolver, key, str, mCurrentUserId);
+            }
+        }
+
+        private String getString(final String key) {
+            if (mCopyOnWrite && mCopyOnWriteDataStore.containsKey(key)) {
+                final String result = mCopyOnWriteDataStore.get(key);
+                return result != null ? result : "";
+            }
+            return Settings.Secure.getStringForUser(mResolver, key, mCurrentUserId);
+        }
+
+        private void putInt(final String key, final int value) {
+            if (mCopyOnWrite) {
+                mCopyOnWriteDataStore.put(key, String.valueOf(value));
+            } else {
+                Settings.Secure.putIntForUser(mResolver, key, value, mCurrentUserId);
+            }
+        }
+
+        private int getInt(final String key, final int defaultValue) {
+            if (mCopyOnWrite && mCopyOnWriteDataStore.containsKey(key)) {
+                final String result = mCopyOnWriteDataStore.get(key);
+                return result != null ? Integer.valueOf(result) : 0;
+            }
+            return Settings.Secure.getIntForUser(mResolver, key, defaultValue, mCurrentUserId);
+        }
+
+        private void putBoolean(final String key, final boolean value) {
+            putInt(key, value ? 1 : 0);
+        }
+
+        private boolean getBoolean(final String key, final boolean defaultValue) {
+            return getInt(key, defaultValue ? 1 : 0) == 1;
         }
 
         public void setCurrentProfileIds(int[] currentProfileIds) {
@@ -1040,7 +1134,7 @@
             }
         }
 
-        public boolean isCurrentProfile(int userId) {
+        public boolean isCurrentProfile(@UserIdInt int userId) {
             synchronized (mLock) {
                 if (userId == mCurrentUserId) return true;
                 for (int i = 0; i < mCurrentProfileIds.length; i++) {
@@ -1050,39 +1144,39 @@
             }
         }
 
+        @UserIdInt
         public int getCurrentUserId() {
             return mCurrentUserId;
         }
 
         public void putSelectedSpellChecker(String sciId) {
-            Settings.Secure.putStringForUser(mResolver,
-                    Settings.Secure.SELECTED_SPELL_CHECKER, sciId, mCurrentUserId);
+            putString(Settings.Secure.SELECTED_SPELL_CHECKER, sciId);
         }
 
         public void putSelectedSpellCheckerSubtype(int hashCode) {
-            Settings.Secure.putStringForUser(mResolver,
-                    Settings.Secure.SELECTED_SPELL_CHECKER_SUBTYPE, String.valueOf(hashCode),
-                    mCurrentUserId);
+            putString(Settings.Secure.SELECTED_SPELL_CHECKER_SUBTYPE, String.valueOf(hashCode));
         }
 
         public void setSpellCheckerEnabled(boolean enabled) {
-            Settings.Secure.putIntForUser(mResolver,
-                    Settings.Secure.SPELL_CHECKER_ENABLED, enabled ? 1 : 0, mCurrentUserId);
+            putBoolean(Settings.Secure.SPELL_CHECKER_ENABLED, enabled);
         }
 
         public String getSelectedSpellChecker() {
-            return Settings.Secure.getStringForUser(mResolver,
-                    Settings.Secure.SELECTED_SPELL_CHECKER, mCurrentUserId);
+            return getString(Settings.Secure.SELECTED_SPELL_CHECKER);
         }
 
         public String getSelectedSpellCheckerSubtype() {
-            return Settings.Secure.getStringForUser(mResolver,
-                    Settings.Secure.SELECTED_SPELL_CHECKER_SUBTYPE, mCurrentUserId);
+            return getString(Settings.Secure.SELECTED_SPELL_CHECKER_SUBTYPE);
         }
 
         public boolean isSpellCheckerEnabled() {
-            return Settings.Secure.getIntForUser(mResolver,
-                    Settings.Secure.SPELL_CHECKER_ENABLED, 1, mCurrentUserId) == 1;
+            return getBoolean(Settings.Secure.SPELL_CHECKER_ENABLED, true);
+        }
+
+        public void dumpLocked(final PrintWriter pw, final String prefix) {
+            pw.println(prefix + "mCurrentUserId=" + mCurrentUserId);
+            pw.println(prefix + "mCurrentProfileIds=" + Arrays.toString(mCurrentProfileIds));
+            pw.println(prefix + "mCopyOnWrite=" + mCopyOnWrite);
         }
     }
 
diff --git a/services/core/java/com/android/server/Watchdog.java b/services/core/java/com/android/server/Watchdog.java
index 772a15c..11888ff 100644
--- a/services/core/java/com/android/server/Watchdog.java
+++ b/services/core/java/com/android/server/Watchdog.java
@@ -64,6 +64,7 @@
 
     // Which native processes to dump into dropbox's stack traces
     public static final String[] NATIVE_STACKS_OF_INTEREST = new String[] {
+        "/system/bin/audioserver",
         "/system/bin/mediaserver",
         "/system/bin/sdcard",
         "/system/bin/surfaceflinger"
diff --git a/services/core/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java
index caeb0c6..a63faf1 100644
--- a/services/core/java/com/android/server/accounts/AccountManagerService.java
+++ b/services/core/java/com/android/server/accounts/AccountManagerService.java
@@ -101,9 +101,12 @@
 import java.util.Date;
 import java.util.HashMap;
 import java.util.HashSet;
+import java.util.Iterator;
 import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
 import java.util.concurrent.atomic.AtomicInteger;
 import java.util.concurrent.atomic.AtomicReference;
 
@@ -122,7 +125,7 @@
     private static final String TAG = "AccountManagerService";
 
     private static final String DATABASE_NAME = "accounts.db";
-    private static final int DATABASE_VERSION = 8;
+    private static final int DATABASE_VERSION = 9;
 
     private static final int MAX_DEBUG_DB_SIZE = 64;
 
@@ -200,6 +203,11 @@
             EXTRAS_ACCOUNTS_ID + "=(select _id FROM accounts WHERE name=? AND type=?)";
     private static final String[] COLUMNS_EXTRAS_KEY_AND_VALUE = {EXTRAS_KEY, EXTRAS_VALUE};
 
+    private static final String META_KEY_FOR_AUTHENTICATOR_UID_FOR_TYPE_PREFIX =
+            "auth_uid_for_type:";
+    private static final String META_KEY_DELIMITER = ":";
+    private static final String SELECTION_META_BY_AUTHENTICATOR_TYPE = META_KEY + " LIKE ?";
+
     private final LinkedHashMap<String, Session> mSessions = new LinkedHashMap<String, Session>();
     private final AtomicInteger mNotificationIds = new AtomicInteger(1);
 
@@ -376,15 +384,69 @@
             mAuthenticatorCache.invalidateCache(accounts.userId);
         }
 
-        final HashSet<AuthenticatorDescription> knownAuth = Sets.newHashSet();
+        final HashMap<String, Integer> knownAuth = new HashMap<>();
         for (RegisteredServicesCache.ServiceInfo<AuthenticatorDescription> service :
                 mAuthenticatorCache.getAllServices(accounts.userId)) {
-            knownAuth.add(service.type);
+            knownAuth.put(service.type.type, service.uid);
         }
 
         synchronized (accounts.cacheLock) {
             final SQLiteDatabase db = accounts.openHelper.getWritableDatabase();
             boolean accountDeleted = false;
+
+            // Get a list of stored authenticator type and UID
+            Cursor metaCursor = db.query(
+                    TABLE_META,
+                    new String[] {META_KEY, META_VALUE},
+                    SELECTION_META_BY_AUTHENTICATOR_TYPE,
+                    new String[] {META_KEY_FOR_AUTHENTICATOR_UID_FOR_TYPE_PREFIX + "%"},
+                    null /* groupBy */,
+                    null /* having */,
+                    META_KEY);
+            // Create a list of authenticator type whose previous uid no longer exists
+            HashSet<String> obsoleteAuthType = Sets.newHashSet();
+            try {
+                while (metaCursor.moveToNext()) {
+                    String type = TextUtils.split(metaCursor.getString(0), META_KEY_DELIMITER)[1];
+                    String uid = metaCursor.getString(1);
+                    if (TextUtils.isEmpty(type) || TextUtils.isEmpty(uid)) {
+                        // Should never happen.
+                        Slog.e(TAG, "Auth type empty: " + TextUtils.isEmpty(type)
+                                + ", uid empty: " + TextUtils.isEmpty(uid));
+                        continue;
+                    }
+                    Integer knownUid = knownAuth.get(type);
+                    if (knownUid != null && uid.equals(knownUid.toString())) {
+                        // Remove it from the knownAuth list if it's unchanged.
+                        knownAuth.remove(type);
+                    } else {
+                        // Only add it to the list if it no longer exists or uid different
+                        obsoleteAuthType.add(type);
+                        // And delete it from the TABLE_META
+                        db.delete(
+                                TABLE_META,
+                                META_KEY + "=? AND " + META_VALUE + "=?",
+                                new String[] {
+                                        META_KEY_FOR_AUTHENTICATOR_UID_FOR_TYPE_PREFIX + type,
+                                        uid}
+                                );
+                    }
+                }
+            } finally {
+                metaCursor.close();
+            }
+
+            // Add the newly registered authenticator to TABLE_META
+            Iterator<Entry<String, Integer>> iterator = knownAuth.entrySet().iterator();
+            while (iterator.hasNext()) {
+                Entry<String, Integer> entry = iterator.next();
+                ContentValues values = new ContentValues();
+                values.put(META_KEY,
+                        META_KEY_FOR_AUTHENTICATOR_UID_FOR_TYPE_PREFIX + entry.getKey());
+                values.put(META_VALUE, entry.getValue());
+                db.insert(TABLE_META, null, values);
+            }
+
             Cursor cursor = db.query(TABLE_ACCOUNTS,
                     new String[]{ACCOUNTS_ID, ACCOUNTS_TYPE, ACCOUNTS_NAME},
                     null, null, null, null, ACCOUNTS_ID);
@@ -397,9 +459,9 @@
                     final String accountType = cursor.getString(1);
                     final String accountName = cursor.getString(2);
 
-                    if (!knownAuth.contains(AuthenticatorDescription.newKey(accountType))) {
+                    if (obsoleteAuthType.contains(accountType)) {
                         Slog.w(TAG, "deleting account " + accountName + " because type "
-                                + accountType + " no longer has a registered authenticator");
+                                + accountType + "'s registered authenticator no longer exist.");
                         db.delete(TABLE_ACCOUNTS, ACCOUNTS_ID + "=" + accountId, null);
                         accountDeleted = true;
 
@@ -440,6 +502,18 @@
         }
     }
 
+    private static HashMap<String, Integer> getAuthenticatorTypeAndUIDForUser(
+            Context context,
+            int userId) {
+        AccountAuthenticatorCache authCache = new AccountAuthenticatorCache(context);
+        HashMap<String, Integer> knownAuth = new HashMap<>();
+        for (RegisteredServicesCache.ServiceInfo<AuthenticatorDescription> service : authCache
+                .getAllServices(userId)) {
+            knownAuth.put(service.type.type, service.uid);
+        }
+        return knownAuth;
+    }
+
     private UserAccounts getUserAccountsForCaller() {
         return getUserAccounts(UserHandle.getCallingUserId());
     }
@@ -3963,8 +4037,13 @@
 
     static class DatabaseHelper extends SQLiteOpenHelper {
 
+        private final Context mContext;
+        private final int mUserId;
+
         public DatabaseHelper(Context context, int userId) {
             super(context, AccountManagerService.getDatabaseName(userId), null, DATABASE_VERSION);
+            mContext = context;
+            mUserId = userId;
         }
 
         /**
@@ -4053,6 +4132,20 @@
                     +   "," + GRANTS_GRANTEE_UID + "))");
         }
 
+        private void populateMetaTableWithAuthTypeAndUID(
+                SQLiteDatabase db,
+                Map<String, Integer> authTypeAndUIDMap) {
+            Iterator<Entry<String, Integer>> iterator = authTypeAndUIDMap.entrySet().iterator();
+            while (iterator.hasNext()) {
+                Entry<String, Integer> entry = iterator.next();
+                ContentValues values = new ContentValues();
+                values.put(META_KEY,
+                        META_KEY_FOR_AUTHENTICATOR_UID_FOR_TYPE_PREFIX + entry.getKey());
+                values.put(META_VALUE, entry.getValue());
+                db.insert(TABLE_META, null, values);
+            }
+        }
+
         @Override
         public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
             Log.e(TAG, "upgrade from version " + oldVersion + " to version " + newVersion);
@@ -4096,6 +4189,13 @@
                 oldVersion++;
             }
 
+            if (oldVersion == 8) {
+                populateMetaTableWithAuthTypeAndUID(
+                        db,
+                        AccountManagerService.getAuthenticatorTypeAndUIDForUser(mContext, mUserId));
+                oldVersion++;
+            }
+
             if (oldVersion != newVersion) {
                 Log.e(TAG, "failed to upgrade version " + oldVersion + " to version " + newVersion);
             }
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index 8c0ec78..63a0e87 100755
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -319,7 +319,7 @@
                         + " (pid=" + Binder.getCallingPid()
                         + ") when starting service " + service);
             }
-            callerFg = callerApp.setSchedGroup != Process.THREAD_GROUP_BG_NONINTERACTIVE;
+            callerFg = callerApp.setSchedGroup != ProcessList.SCHED_GROUP_BACKGROUND;
         } else {
             callerFg = true;
         }
@@ -831,7 +831,7 @@
                     "BIND_TREAT_LIKE_ACTIVITY");
         }
 
-        final boolean callerFg = callerApp.setSchedGroup != Process.THREAD_GROUP_BG_NONINTERACTIVE;
+        final boolean callerFg = callerApp.setSchedGroup != ProcessList.SCHED_GROUP_BACKGROUND;
         final boolean isBindExternal = (flags & Context.BIND_EXTERNAL_SERVICE) != 0;
 
         ServiceLookupResult res =
@@ -1138,7 +1138,7 @@
                         for (int i=b.apps.size()-1; i>=0; i--) {
                             ProcessRecord client = b.apps.valueAt(i).client;
                             if (client != null && client.setSchedGroup
-                                    != Process.THREAD_GROUP_BG_NONINTERACTIVE) {
+                                    != ProcessList.SCHED_GROUP_BACKGROUND) {
                                 inFg = true;
                                 break;
                             }
diff --git a/services/core/java/com/android/server/am/ActivityManagerDebugConfig.java b/services/core/java/com/android/server/am/ActivityManagerDebugConfig.java
index 4f0d4d9..f2bf4f9 100644
--- a/services/core/java/com/android/server/am/ActivityManagerDebugConfig.java
+++ b/services/core/java/com/android/server/am/ActivityManagerDebugConfig.java
@@ -46,6 +46,7 @@
 
     // Available log categories in the activity manager package.
     static final boolean DEBUG_ADD_REMOVE = DEBUG_ALL_ACTIVITIES || false;
+    static final boolean DEBUG_ANR = false;
     static final boolean DEBUG_APP = DEBUG_ALL_ACTIVITIES || false;
     static final boolean DEBUG_BACKUP = DEBUG_ALL || false;
     static final boolean DEBUG_BROADCAST = DEBUG_ALL || false;
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index e3a0b5c..07f668b 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -45,6 +45,7 @@
 import com.android.server.DeviceIdleController;
 import com.android.server.IntentResolver;
 import com.android.server.LocalServices;
+import com.android.server.LockGuard;
 import com.android.server.ServiceThread;
 import com.android.server.SystemService;
 import com.android.server.SystemServiceManager;
@@ -100,6 +101,8 @@
 import android.app.PendingIntent;
 import android.app.ProfilerInfo;
 import android.app.admin.DevicePolicyManager;
+import android.app.admin.DevicePolicyManagerInternal;
+import android.app.admin.IDevicePolicyManager;
 import android.app.assist.AssistContent;
 import android.app.assist.AssistStructure;
 import android.app.backup.IBackupManager;
@@ -283,6 +286,7 @@
 import static com.android.internal.util.XmlUtils.writeIntAttribute;
 import static com.android.internal.util.XmlUtils.writeLongAttribute;
 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_ALL;
+import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_ANR;
 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_BACKUP;
 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_BROADCAST;
 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_BROADCAST_BACKGROUND;
@@ -348,6 +352,11 @@
 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.wm.AppTransition.TRANSIT_ACTIVITY_OPEN;
+import static com.android.server.wm.AppTransition.TRANSIT_ACTIVITY_RELAUNCH;
+import static com.android.server.wm.AppTransition.TRANSIT_TASK_IN_PLACE;
+import static com.android.server.wm.AppTransition.TRANSIT_TASK_OPEN;
+import static com.android.server.wm.AppTransition.TRANSIT_TASK_TO_FRONT;
 import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT;
 import static org.xmlpull.v1.XmlPullParser.START_TAG;
 
@@ -533,9 +542,11 @@
     final ActivityStarter mActivityStarter;
 
     /** Task stack change listeners. */
-    private RemoteCallbackList<ITaskStackListener> mTaskStackListeners =
+    private final RemoteCallbackList<ITaskStackListener> mTaskStackListeners =
             new RemoteCallbackList<ITaskStackListener>();
 
+    final InstrumentationReporter mInstrumentationReporter = new InstrumentationReporter();
+
     public IntentFirewall mIntentFirewall;
 
     // Whether we should show our dialogs (ANR, crash, etc) or just perform their
@@ -1293,10 +1304,12 @@
     boolean mAlwaysFinishActivities = false;
     boolean mLenientBackgroundCheck = false;
     boolean mForceResizableActivities;
+    boolean mSupportsMultiWindow;
     boolean mSupportsFreeformWindowManagement;
     boolean mSupportsPictureInPicture;
     Rect mDefaultPinnedStackBounds;
     IActivityController mController = null;
+    boolean mControllerIsAMonkey = false;
     String mProfileApp = null;
     ProcessRecord mProfileProc = null;
     String mProfileFile;
@@ -1371,7 +1384,6 @@
     int mProcessLimitOverride = -1;
 
     WindowManagerService mWindowManager;
-
     final ActivityThread mSystemThread;
 
     private final class AppDeathRecipient implements IBinder.DeathRecipient {
@@ -1894,7 +1906,12 @@
             case SYSTEM_USER_UNLOCK_MSG: {
                 final int userId = msg.arg1;
                 mSystemServiceManager.unlockUser(userId);
-                mRecentTasks.loadUserRecentsLocked(userId);
+                synchronized (ActivityManagerService.this) {
+                    mRecentTasks.loadUserRecentsLocked(userId);
+                }
+                if (userId == UserHandle.USER_SYSTEM) {
+                    startPersistentApps(PackageManager.MATCH_ENCRYPTION_UNAWARE);
+                }
                 installEncryptionUnawareProviders(userId);
                 break;
             }
@@ -2148,15 +2165,20 @@
             } break;
             case VR_MODE_CHANGE_MSG: {
                 VrManagerInternal vrService = LocalServices.getService(VrManagerInternal.class);
-                final boolean vrMode = msg.arg1 != 0;
-                vrService.setVrMode(vrMode);
-
-                if (mInVrMode != vrMode) {
-                    synchronized (ActivityManagerService.this) {
+                final ActivityRecord r = (ActivityRecord) msg.obj;
+                boolean vrMode;
+                ComponentName requestedPackage;
+                int userId;
+                synchronized (ActivityManagerService.this) {
+                    vrMode = r.requestedVrComponent != null;
+                    requestedPackage = r.requestedVrComponent;
+                    userId = r.userId;
+                    if (mInVrMode != vrMode) {
                         mInVrMode = vrMode;
                         mShowDialogs = shouldShowDialogs(mConfiguration, mInVrMode);
                     }
                 }
+                vrService.setVrMode(vrMode, requestedPackage, userId);
             } break;
             }
         }
@@ -2487,7 +2509,6 @@
         mActivityStarter = new ActivityStarter(this, mStackSupervisor);
         mRecentTasks = new RecentTasks(this, mStackSupervisor);
 
-
         mProcessCpuThread = new Thread("CpuTracker") {
             @Override
             public void run() {
@@ -2930,7 +2951,7 @@
 
     final void applyUpdateVrModeLocked(ActivityRecord r) {
         mHandler.sendMessage(
-                mHandler.obtainMessage(VR_MODE_CHANGE_MSG, (r.isVrActivity) ? 1 : 0, 0));
+                mHandler.obtainMessage(VR_MODE_CHANGE_MSG, 0, 0, r));
     }
 
     final void showAskCompatModeDialogLocked(ActivityRecord r) {
@@ -3246,9 +3267,9 @@
 
     boolean isNextTransitionForward() {
         int transit = mWindowManager.getPendingAppTransition();
-        return transit == AppTransition.TRANSIT_ACTIVITY_OPEN
-                || transit == AppTransition.TRANSIT_TASK_OPEN
-                || transit == AppTransition.TRANSIT_TASK_TO_FRONT;
+        return transit == TRANSIT_ACTIVITY_OPEN
+                || transit == TRANSIT_TASK_OPEN
+                || transit == TRANSIT_TASK_TO_FRONT;
     }
 
     int startIsolatedProcess(String entryPoint, String[] entryPointArgs,
@@ -4369,7 +4390,7 @@
                     AppGlobals.getPackageManager().queryIntentActivities(
                             intent, r.resolvedType,
                             PackageManager.MATCH_DEFAULT_ONLY | STOCK_PM_FLAGS,
-                            UserHandle.getCallingUserId());
+                            UserHandle.getCallingUserId()).getList();
 
                 // Look for the original activity in the list...
                 final int N = resolves != null ? resolves.size() : 0;
@@ -5087,8 +5108,13 @@
                     int num = firstPids.size();
                     for (int i = 0; i < num; i++) {
                         synchronized (observer) {
+                            if (DEBUG_ANR) Slog.d(TAG, "Collecting stacks for pid "
+                                    + firstPids.get(i));
+                            final long sime = SystemClock.elapsedRealtime();
                             Process.sendSignal(firstPids.get(i), Process.SIGNAL_QUIT);
-                            observer.wait(200);  // Wait for write-close, give up after 200msec
+                            observer.wait(1000);  // Wait for write-close, give up after 1 sec
+                            if (DEBUG_ANR) Slog.d(TAG, "Done with pid " + firstPids.get(i)
+                                    + " in " + (SystemClock.elapsedRealtime()-sime) + "ms");
                         }
                     }
                 } catch (InterruptedException e) {
@@ -5101,7 +5127,11 @@
                 int[] pids = Process.getPidsForCommands(nativeProcs);
                 if (pids != null) {
                     for (int pid : pids) {
+                        if (DEBUG_ANR) Slog.d(TAG, "Collecting stacks for native pid " + pid);
+                        final long sime = SystemClock.elapsedRealtime();
                         Debug.dumpNativeBacktraceToFile(pid, tracesPath);
+                        if (DEBUG_ANR) Slog.d(TAG, "Done with native pid " + pid
+                                + " in " + (SystemClock.elapsedRealtime()-sime) + "ms");
                     }
                 }
             }
@@ -5128,13 +5158,20 @@
                         numProcs++;
                         try {
                             synchronized (observer) {
+                                if (DEBUG_ANR) Slog.d(TAG, "Collecting stacks for extra pid "
+                                        + stats.pid);
+                                final long stime = SystemClock.elapsedRealtime();
                                 Process.sendSignal(stats.pid, Process.SIGNAL_QUIT);
-                                observer.wait(200);  // Wait for write-close, give up after 200msec
+                                observer.wait(1000);  // Wait for write-close, give up after 1 sec
+                                if (DEBUG_ANR) Slog.d(TAG, "Done with extra pid " + stats.pid
+                                        + " in " + (SystemClock.elapsedRealtime()-stime) + "ms");
                             }
                         } catch (InterruptedException e) {
                             Slog.wtf(TAG, e);
                         }
-
+                    } else if (DEBUG_ANR) {
+                        Slog.d(TAG, "Skipping next CPU consuming process, not a java proc: "
+                                + stats.pid);
                     }
                 }
             }
@@ -5240,13 +5277,17 @@
     public boolean clearApplicationUserData(final String packageName,
             final IPackageDataObserver observer, int userId) {
         enforceNotIsolatedCaller("clearApplicationUserData");
-        if (packageName != null && packageName.equals(mDeviceOwnerName)) {
-            throw new SecurityException("Clearing DeviceOwner data is forbidden.");
-        }
         int uid = Binder.getCallingUid();
         int pid = Binder.getCallingPid();
         userId = mUserController.handleIncomingUser(pid, uid, userId, false,
                 ALLOW_FULL_ONLY, "clearApplicationUserData", null);
+
+        final DevicePolicyManagerInternal dpmi = LocalServices
+                .getService(DevicePolicyManagerInternal.class);
+        if (dpmi != null && dpmi.hasDeviceOwnerOrProfileOwner(packageName, userId)) {
+            throw new SecurityException("Cannot clear data for a device owner or a profile owner");
+        }
+
         long callingId = Binder.clearCallingIdentity();
         try {
             IPackageManager pm = AppGlobals.getPackageManager();
@@ -5356,17 +5397,6 @@
 
     @Override
     public void killAllBackgroundProcesses() {
-        killAllBackgroundProcesses(-1);
-    }
-
-    /**
-     * Kills all background processes with targetSdkVersion below the specified
-     * target SDK version.
-     *
-     * @param targetSdkVersion the target SDK version below which to kill
-     *                         processes, or {@code -1} to kill all processes
-     */
-    private void killAllBackgroundProcesses(int targetSdkVersion) {
         if (checkCallingPermission(android.Manifest.permission.KILL_BACKGROUND_PROCESSES)
                 != PackageManager.PERMISSION_GRANTED) {
             final String msg = "Permission Denial: killAllBackgroundProcesses() from pid="
@@ -5390,10 +5420,6 @@
                             // We don't kill persistent processes.
                             continue;
                         }
-                        if (targetSdkVersion > 0
-                                && app.info.targetSdkVersion >= targetSdkVersion) {
-                            continue;
-                        }
                         if (app.removed) {
                             procs.add(app);
                         } else if (app.setAdj >= ProcessList.CACHED_APP_MIN_ADJ) {
@@ -5418,6 +5444,55 @@
         }
     }
 
+    /**
+     * Kills all background processes, except those matching any of the
+     * specified properties.
+     *
+     * @param minTargetSdk the target SDK version at or above which to preserve
+     *                     processes, or {@code -1} to ignore the target SDK
+     * @param maxProcState the process state at or below which to preserve
+     *                     processes, or {@code -1} to ignore the process state
+     */
+    private void killAllBackgroundProcessesExcept(int minTargetSdk, int maxProcState) {
+        if (checkCallingPermission(android.Manifest.permission.KILL_BACKGROUND_PROCESSES)
+                != PackageManager.PERMISSION_GRANTED) {
+            final String msg = "Permission Denial: killAllBackgroundProcessesExcept() from pid="
+                    + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid()
+                    + " requires " + android.Manifest.permission.KILL_BACKGROUND_PROCESSES;
+            Slog.w(TAG, msg);
+            throw new SecurityException(msg);
+        }
+
+        final long callingId = Binder.clearCallingIdentity();
+        try {
+            synchronized (this) {
+                final ArrayList<ProcessRecord> procs = new ArrayList<>();
+                final int NP = mProcessNames.getMap().size();
+                for (int ip = 0; ip < NP; ip++) {
+                    final SparseArray<ProcessRecord> apps = mProcessNames.getMap().valueAt(ip);
+                    final int NA = apps.size();
+                    for (int ia = 0; ia < NA; ia++) {
+                        final ProcessRecord app = apps.valueAt(ia);
+                        if (app.removed) {
+                            procs.add(app);
+                        } else if ((minTargetSdk < 0 || app.info.targetSdkVersion < minTargetSdk)
+                                && (maxProcState < 0 || app.setProcState > maxProcState)) {
+                            app.removed = true;
+                            procs.add(app);
+                        }
+                    }
+                }
+
+                final int N = procs.size();
+                for (int i = 0; i < N; i++) {
+                    removeProcessLocked(procs.get(i), false, true, "kill all background except");
+                }
+            }
+        } finally {
+            Binder.restoreCallingIdentity(callingId);
+        }
+    }
+
     @Override
     public void forceStopPackage(final String packageName, int userId) {
         if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
@@ -6174,7 +6249,7 @@
 
         app.makeActive(thread, mProcessStats);
         app.curAdj = app.setAdj = ProcessList.INVALID_ADJ;
-        app.curSchedGroup = app.setSchedGroup = Process.THREAD_GROUP_DEFAULT;
+        app.curSchedGroup = app.setSchedGroup = ProcessList.SCHED_GROUP_DEFAULT;
         app.forcingToForeground = null;
         updateProcessForegroundLocked(app, false, false);
         app.hasShownUi = false;
@@ -6232,9 +6307,10 @@
             // If the app is being launched for restore or full backup, set it up specially
             boolean isRestrictedBackupMode = false;
             if (mBackupTarget != null && mBackupAppName.equals(processName)) {
-                isRestrictedBackupMode = (mBackupTarget.backupMode == BackupRecord.RESTORE)
-                        || (mBackupTarget.backupMode == BackupRecord.RESTORE_FULL)
-                        || (mBackupTarget.backupMode == BackupRecord.BACKUP_FULL);
+                isRestrictedBackupMode = mBackupTarget.appInfo.uid >= Process.FIRST_APPLICATION_UID
+                        && ((mBackupTarget.backupMode == BackupRecord.RESTORE)
+                                || (mBackupTarget.backupMode == BackupRecord.RESTORE_FULL)
+                                || (mBackupTarget.backupMode == BackupRecord.BACKUP_FULL));
             }
 
             notifyPackageUse(app.instrumentationInfo != null
@@ -6588,7 +6664,7 @@
         synchronized(this) {
             ActivityStack stack = ActivityRecord.getStackLocked(token);
             if (stack != null) {
-                ActivityRecord.activityResumedLocked(token);
+                stack.activityResumedLocked(token);
             }
         }
         Binder.restoreCallingIdentity(origId);
@@ -6985,6 +7061,8 @@
 
     @Override
     public Intent getIntentForIntentSender(IIntentSender pendingResult) {
+        enforceCallingPermission(Manifest.permission.GET_INTENT_SENDER_INTENT,
+                "getIntentForIntentSender()");
         if (!(pendingResult instanceof PendingIntentRecord)) {
             return null;
         }
@@ -9029,7 +9107,8 @@
                     preserveWindow = false;
                 }
 
-                mStackSupervisor.resizeTaskLocked(task, bounds, resizeMode, preserveWindow);
+                mStackSupervisor.resizeTaskLocked(task, bounds, resizeMode, preserveWindow,
+                        false /* deferResume */);
             }
         } finally {
             Binder.restoreCallingIdentity(ident);
@@ -9094,7 +9173,7 @@
             throw new IllegalArgumentException("Expected in-place ActivityOption " +
                     "with valid animation");
         }
-        mWindowManager.prepareAppTransition(AppTransition.TRANSIT_TASK_IN_PLACE, false);
+        mWindowManager.prepareAppTransition(TRANSIT_TASK_IN_PLACE, false);
         mWindowManager.overridePendingAppTransitionInPlace(opts.getPackageName(),
                 opts.getCustomInPlaceResId());
         mWindowManager.executeAppTransition();
@@ -9163,7 +9242,7 @@
         // Kill the running processes.
         for (int i = 0; i < procsToKill.size(); i++) {
             ProcessRecord pr = procsToKill.get(i);
-            if (pr.setSchedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE
+            if (pr.setSchedGroup == ProcessList.SCHED_GROUP_BACKGROUND
                     && pr.curReceiver == null) {
                 pr.kill("remove task", true);
             } else {
@@ -9473,6 +9552,55 @@
         }
     }
 
+    @Override
+    public void swapDockedAndFullscreenStack() throws RemoteException {
+        enforceCallingPermission(MANAGE_ACTIVITY_STACKS, "swapDockedAndFullscreenStack()");
+        synchronized (this) {
+            long ident = Binder.clearCallingIdentity();
+            try {
+                final ActivityStack fullscreenStack = mStackSupervisor.getStack(
+                        FULLSCREEN_WORKSPACE_STACK_ID);
+                final TaskRecord topTask = fullscreenStack != null ? fullscreenStack.topTask()
+                        : null;
+                final ActivityStack dockedStack = mStackSupervisor.getStack(DOCKED_STACK_ID);
+                final ArrayList<TaskRecord> tasks = dockedStack != null ? dockedStack.getAllTasks()
+                        : null;
+                if (topTask == null || tasks == null || tasks.size() == 0) {
+                    Slog.w(TAG,
+                            "Unable to swap tasks, either docked or fullscreen stack is empty.");
+                    return;
+                }
+
+                // 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 */);
+                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 */);
+                }
+
+                // 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();
+
+                mWindowManager.executeAppTransition();
+            } finally {
+                Binder.restoreCallingIdentity(ident);
+            }
+        }
+    }
+
     /**
      * Moves the input task to the docked stack.
      *
@@ -9488,7 +9616,7 @@
      *                      docked stack. Pass {@code null} to use default bounds.
      */
     @Override
-    public void moveTaskToDockedStack(int taskId, int createMode, boolean toTop, boolean animate,
+    public boolean moveTaskToDockedStack(int taskId, int createMode, boolean toTop, boolean animate,
             Rect initialBounds) {
         enforceCallingPermission(MANAGE_ACTIVITY_STACKS, "moveTaskToDockedStack()");
         synchronized (this) {
@@ -9497,7 +9625,8 @@
                 if (DEBUG_STACK) Slog.d(TAG_STACK, "moveTaskToDockedStack: moving task=" + taskId
                         + " to createMode=" + createMode + " toTop=" + toTop);
                 mWindowManager.setDockedStackCreateState(createMode, initialBounds);
-                mStackSupervisor.moveTaskToStackLocked(taskId, DOCKED_STACK_ID, toTop, !FORCE_FOCUS,
+                return mStackSupervisor.moveTaskToStackLocked(
+                        taskId, DOCKED_STACK_ID, toTop, !FORCE_FOCUS,
                         "moveTaskToDockedStack", animate);
             } finally {
                 Binder.restoreCallingIdentity(ident);
@@ -9576,6 +9705,20 @@
     }
 
     @Override
+    public void resizePinnedStack(Rect pinnedBounds, Rect tempPinnedTaskBounds) {
+        enforceCallingPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS,
+                "resizePinnedStack()");
+        final long ident = Binder.clearCallingIdentity();
+        try {
+            synchronized (this) {
+                mStackSupervisor.resizePinnedStackLocked(pinnedBounds, tempPinnedTaskBounds);
+            }
+        } finally {
+            Binder.restoreCallingIdentity(ident);
+        }
+    }
+
+    @Override
     public void positionTaskInStack(int taskId, int stackId, int position) {
         enforceCallingPermission(MANAGE_ACTIVITY_STACKS, "positionTaskInStack()");
         if (stackId == HOME_STACK_ID) {
@@ -9829,11 +9972,11 @@
     private final List<ProviderInfo> generateApplicationProvidersLocked(ProcessRecord app) {
         List<ProviderInfo> providers = null;
         try {
-            ParceledListSlice<ProviderInfo> slice = AppGlobals.getPackageManager()
+            providers = AppGlobals.getPackageManager()
                     .queryContentProviders(app.processName, app.uid,
                             STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS
-                                    | MATCH_DEBUG_TRIAGED_MISSING);
-            providers = slice != null ? slice.getList() : null;
+                                    | MATCH_DEBUG_TRIAGED_MISSING)
+                    .getList();
         } catch (RemoteException ex) {
         }
         if (DEBUG_MU) Slog.v(TAG_MU,
@@ -10423,7 +10566,7 @@
                 cpi.packageName, r.userId)) {
 
             final boolean callerForeground = r != null ? r.setSchedGroup
-                    != Process.THREAD_GROUP_BG_NONINTERACTIVE : true;
+                    != ProcessList.SCHED_GROUP_BACKGROUND : true;
 
             // Show a permission review UI only for starting from a foreground app
             if (!callerForeground) {
@@ -10743,12 +10886,13 @@
             return;
         }
 
-        final long token = Binder.clearCallingIdentity();
-        try {
-            mAppErrors.appNotResponding(host, null, null, false, "ContentProvider not responding");
-        } finally {
-            Binder.restoreCallingIdentity(token);
-        }
+        mHandler.post(new Runnable() {
+            @Override
+            public void run() {
+                mAppErrors.appNotResponding(host, null, null, false,
+                        "ContentProvider not responding");
+            }
+        });
     }
 
     public final void installSystemProviders() {
@@ -10777,12 +10921,29 @@
         //mUsageStatsService.monitorPackages();
     }
 
+    private void startPersistentApps(int matchFlags) {
+        if (mFactoryTest == FactoryTest.FACTORY_TEST_LOW_LEVEL) return;
+
+        synchronized (this) {
+            try {
+                final List<ApplicationInfo> apps = AppGlobals.getPackageManager()
+                        .getPersistentApplications(STOCK_PM_FLAGS | matchFlags).getList();
+                for (ApplicationInfo app : apps) {
+                    if (!"android".equals(app.packageName)) {
+                        addAppLocked(app, false, null /* ABI override */);
+                    }
+                }
+            } catch (RemoteException ex) {
+            }
+        }
+    }
+
     /**
      * When a user is unlocked, we need to install encryption-unaware providers
      * belonging to any running apps.
      */
     private void installEncryptionUnawareProviders(int userId) {
-        if (!StorageManager.isFileBasedEncryptionEnabled()) {
+        if (!StorageManager.isFileEncryptedNativeOrEmulated()) {
             // TODO: eventually pivot this back to look at current user state,
             // similar to the comment in UserManager.isUserUnlocked(), but for
             // now, if we started apps when "unlocked" then unaware providers
@@ -10793,8 +10954,7 @@
         // We're only interested in providers that are encryption unaware, and
         // we don't care about uninstalled apps, since there's no way they're
         // running at this point.
-        final int matchFlags = GET_PROVIDERS | MATCH_ENCRYPTION_UNAWARE
-                | MATCH_DEBUG_TRIAGED_MISSING;
+        final int matchFlags = GET_PROVIDERS | MATCH_ENCRYPTION_UNAWARE;
 
         synchronized (this) {
             final int NP = mProcessNames.getMap().size();
@@ -11425,11 +11585,12 @@
     }
 
     @Override
-    public void setActivityController(IActivityController controller) {
+    public void setActivityController(IActivityController controller, boolean imAMonkey) {
         enforceCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER,
                 "setActivityController()");
         synchronized (this) {
             mController = controller;
+            mControllerIsAMonkey = imAMonkey;
             Watchdog.getInstance().setActivityController(controller);
         }
     }
@@ -11456,7 +11617,7 @@
     public boolean isUserAMonkey() {
         synchronized (this) {
             // If there is a controller also implies the user is a monkey.
-            return (mUserIsMonkey || mController != null);
+            return (mUserIsMonkey || (mController != null && mControllerIsAMonkey));
         }
     }
 
@@ -11933,25 +12094,51 @@
     }
 
     @Override
-    public void setVrMode(IBinder token, boolean enabled) {
+    public int setVrMode(IBinder token, boolean enabled, ComponentName packageName) {
         if (!mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_VR_MODE)) {
             throw new UnsupportedOperationException("VR mode not supported on this device!");
         }
 
+        final VrManagerInternal vrService = LocalServices.getService(VrManagerInternal.class);
+
+        ActivityRecord r;
+        synchronized (this) {
+            r = ActivityRecord.isInStackLocked(token);
+        }
+
+        if (r == null) {
+            throw new IllegalArgumentException();
+        }
+
+        int err;
+        if ((err = vrService.hasVrPackage(packageName, r.userId)) !=
+                VrManagerInternal.NO_ERROR) {
+            return err;
+        }
+
         synchronized(this) {
-            final ActivityRecord r = ActivityRecord.isInStackLocked(token);
-            if (r == null) {
-                throw new IllegalArgumentException();
-            }
-            r.isVrActivity = enabled;
+            r.requestedVrComponent = (enabled) ? packageName : null;
 
             // Update associated state if this activity is currently focused
             if (r == mFocusedActivity) {
                 applyUpdateVrModeLocked(r);
             }
+            return 0;
         }
     }
 
+    @Override
+    public boolean isVrModePackageEnabled(ComponentName packageName) {
+        if (!mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_VR_MODE)) {
+            throw new UnsupportedOperationException("VR mode not supported on this device!");
+        }
+
+        final VrManagerInternal vrService = LocalServices.getService(VrManagerInternal.class);
+
+        return vrService.hasVrPackage(packageName, UserHandle.getCallingUserId()) ==
+                VrManagerInternal.NO_ERROR;
+    }
+
     public boolean isTopActivityImmersive() {
         enforceNotIsolatedCaller("startActivity");
         synchronized (this) {
@@ -12314,6 +12501,7 @@
         final boolean supportsPictureInPicture =
                 mContext.getPackageManager().hasSystemFeature(FEATURE_PICTURE_IN_PICTURE);
 
+        final boolean supportsMultiWindow = ActivityManager.supportsMultiWindow();
         final String debugApp = Settings.Global.getString(resolver, DEBUG_APP);
         final boolean waitForDebugger = Settings.Global.getInt(resolver, WAIT_FOR_DEBUGGER, 0) != 0;
         final boolean alwaysFinishActivities =
@@ -12340,8 +12528,15 @@
             mLenientBackgroundCheck = lenientBackgroundCheck;
             mForceResizableActivities = forceResizable;
             mWindowManager.setForceResizableTasks(mForceResizableActivities);
-            mSupportsFreeformWindowManagement = freeformWindowManagement || forceResizable;
-            mSupportsPictureInPicture = supportsPictureInPicture || forceResizable;
+            if (supportsMultiWindow || forceResizable) {
+                mSupportsMultiWindow = true;
+                mSupportsFreeformWindowManagement = freeformWindowManagement || forceResizable;
+                mSupportsPictureInPicture = supportsPictureInPicture || forceResizable;
+            } else {
+                mSupportsMultiWindow = false;
+                mSupportsFreeformWindowManagement = false;
+                mSupportsPictureInPicture = false;
+            }
             // This happens before any activities are started, so we can
             // change mConfiguration in-place.
             updateConfigurationLocked(configuration, null, true);
@@ -12509,7 +12704,7 @@
         List<ResolveInfo> ris = null;
         try {
             ris = AppGlobals.getPackageManager().queryIntentReceivers(
-                    intent, null, MATCH_SYSTEM_ONLY, UserHandle.USER_SYSTEM);
+                    intent, null, MATCH_SYSTEM_ONLY, UserHandle.USER_SYSTEM).getList();
         } catch (RemoteException e) {
         }
         if (ris == null) {
@@ -12679,26 +12874,9 @@
         mSystemServiceManager.startUser(currentUserId);
 
         synchronized (this) {
-            if (mFactoryTest != FactoryTest.FACTORY_TEST_LOW_LEVEL) {
-                try {
-                    List apps = AppGlobals.getPackageManager().
-                        getPersistentApplications(STOCK_PM_FLAGS);
-                    if (apps != null) {
-                        int N = apps.size();
-                        int i;
-                        for (i=0; i<N; i++) {
-                            ApplicationInfo info
-                                = (ApplicationInfo)apps.get(i);
-                            if (info != null &&
-                                    !info.packageName.equals("android")) {
-                                addAppLocked(info, false, null /* ABI override */);
-                            }
-                        }
-                    }
-                } catch (RemoteException ex) {
-                    // pm is in same process, this will never happen.
-                }
-            }
+            // Only start up encryption-aware persistent apps; once user is
+            // unlocked we'll come back around and start unaware apps
+            startPersistentApps(PackageManager.MATCH_ENCRYPTION_AWARE);
 
             // Start up initial activity.
             mBooting = true;
@@ -12710,7 +12888,7 @@
                             PackageManager.COMPONENT_ENABLED_STATE_ENABLED, 0,
                             UserHandle.USER_SYSTEM);
                 } catch (RemoteException e) {
-                    e.rethrowAsRuntimeException();
+                    throw e.rethrowAsRuntimeException();
                 }
             }
             startHomeActivityLocked(currentUserId, "systemReady");
@@ -13395,6 +13573,14 @@
     }
 
     @Override
+    public int getMemoryTrimLevel() {
+        enforceNotIsolatedCaller("getMyMemoryState");
+        synchronized (this) {
+            return mLastMemoryLevel;
+        }
+    }
+
+    @Override
     public void onShellCommand(FileDescriptor in, FileDescriptor out,
             FileDescriptor err, String[] args, ResultReceiver resultReceiver) {
         (new ActivityManagerShellCommand(this, false)).exec(
@@ -13575,6 +13761,8 @@
                 synchronized (this) {
                     mServices.dumpServicesLocked(fd, pw, args, opti, true, dumpClient, dumpPackage);
                 }
+            } else if ("locks".equals(cmd)) {
+                LockGuard.dump(fd, pw, args);
             } else {
                 // Dumping a single activity?
                 if (!dumpActivity(fd, pw, cmd, args, opti, dumpAll)) {
@@ -14117,10 +14305,13 @@
             }
         }
         if (dumpPackage == null) {
-            if (mAlwaysFinishActivities || mLenientBackgroundCheck || mController != null) {
+            if (mAlwaysFinishActivities || mLenientBackgroundCheck) {
                 pw.println("  mAlwaysFinishActivities=" + mAlwaysFinishActivities
-                        + " mLenientBackgroundCheck=" + mLenientBackgroundCheck
-                        + " mController=" + mController);
+                        + " mLenientBackgroundCheck=" + mLenientBackgroundCheck);
+            }
+            if (mController != null) {
+                pw.println("  mController=" + mController
+                        + " mControllerIsAMonkey=" + mControllerIsAMonkey);
             }
             if (dumpAll) {
                 pw.println("  Total persistent processes: " + numPers);
@@ -14718,13 +14909,13 @@
             String oomAdj = ProcessList.makeOomAdjString(r.setAdj);
             char schedGroup;
             switch (r.setSchedGroup) {
-                case Process.THREAD_GROUP_BG_NONINTERACTIVE:
+                case ProcessList.SCHED_GROUP_BACKGROUND:
                     schedGroup = 'B';
                     break;
-                case Process.THREAD_GROUP_DEFAULT:
+                case ProcessList.SCHED_GROUP_DEFAULT:
                     schedGroup = 'F';
                     break;
-                case Process.THREAD_GROUP_TOP_APP:
+                case ProcessList.SCHED_GROUP_TOP_APP:
                     schedGroup = 'T';
                     break;
                 default:
@@ -15144,6 +15335,7 @@
         boolean dumpFullDetails = false;
         boolean dumpDalvik = false;
         boolean dumpSummaryOnly = false;
+        boolean dumpUnreachable = false;
         boolean oomOnly = false;
         boolean isCompact = false;
         boolean localOnly = false;
@@ -15172,6 +15364,8 @@
                 dumpSummaryOnly = true;
             } else if ("-S".equals(opt)) {
                 dumpSwapPss = true;
+            } else if ("--unreachable".equals(opt)) {
+                dumpUnreachable = true;
             } else if ("--oom".equals(opt)) {
                 oomOnly = true;
             } else if ("--local".equals(opt)) {
@@ -15333,7 +15527,7 @@
                         try {
                             pw.flush();
                             thread.dumpMemInfo(fd, mi, isCheckinRequest, dumpFullDetails,
-                                    dumpDalvik, dumpSummaryOnly, innerArgs);
+                                    dumpDalvik, dumpSummaryOnly, dumpUnreachable, innerArgs);
                         } catch (RemoteException e) {
                             if (!isCheckinRequest) {
                                 pw.println("Got RemoteException!");
@@ -16859,7 +17053,7 @@
                     continue;
                 }
                 List<ResolveInfo> newReceivers = AppGlobals.getPackageManager()
-                        .queryIntentReceivers(intent, resolvedType, pmFlags, user);
+                        .queryIntentReceivers(intent, resolvedType, pmFlags, user).getList();
                 if (user != UserHandle.USER_SYSTEM && newReceivers != null) {
                     // If this is not the system user, we need to check for
                     // any receivers that should be filtered out.
@@ -17129,10 +17323,11 @@
                             String ssp;
                             if (data != null && (ssp=data.getSchemeSpecificPart()) != null) {
                                 boolean removed = Intent.ACTION_PACKAGE_REMOVED.equals(action);
-                                boolean fullUninstall = removed &&
-                                        !intent.getBooleanExtra(Intent.EXTRA_REPLACING, false);
+                                final boolean replacing =
+                                        intent.getBooleanExtra(Intent.EXTRA_REPLACING, false);
                                 final boolean killProcess =
                                         !intent.getBooleanExtra(Intent.EXTRA_DONT_KILL_APP, false);
+                                final boolean fullUninstall = removed && !replacing;
                                 if (killProcess) {
                                     forceStopPackageLocked(ssp, UserHandle.getAppId(
                                             intent.getIntExtra(Intent.EXTRA_UID, -1)),
@@ -17140,7 +17335,10 @@
                                             removed ? "pkg removed" : "pkg changed");
                                 }
                                 if (removed) {
-                                    sendPackageBroadcastLocked(IApplicationThread.PACKAGE_REMOVED,
+                                    final int cmd = killProcess
+                                            ? IApplicationThread.PACKAGE_REMOVED
+                                            : IApplicationThread.PACKAGE_REMOVED_DONT_KILL;
+                                    sendPackageBroadcastLocked(cmd,
                                             new String[] {ssp}, userId);
                                     if (fullUninstall) {
                                         mAppOpsService.packageRemoved(
@@ -17175,7 +17373,23 @@
                             break;
                     }
                     break;
+                case Intent.ACTION_PACKAGE_REPLACED:
+                {
+                    final Uri data = intent.getData();
+                    final String ssp;
+                    if (data != null && (ssp = data.getSchemeSpecificPart()) != null) {
+                        final ApplicationInfo aInfo =
+                                getPackageManagerInternalLocked().getApplicationInfo(
+                                        ssp,
+                                        userId);
+                        mStackSupervisor.updateActivityApplicationInfoLocked(aInfo);
+                        sendPackageBroadcastLocked(IApplicationThread.PACKAGE_REPLACED,
+                                new String[] {ssp}, userId);
+                    }
+                    break;
+                }
                 case Intent.ACTION_PACKAGE_ADDED:
+                {
                     // Special case for adding a package: by default turn on compatibility mode.
                     Uri data = intent.getData();
                     String ssp;
@@ -17193,6 +17407,7 @@
                         }
                     }
                     break;
+                }
                 case Intent.ACTION_TIMEZONE_CHANGED:
                     // If this is the time zone changed action, queue up a message that will reset
                     // the timezone of all currently running processes. This message will get
@@ -17638,17 +17853,17 @@
             } catch (RemoteException e) {
             }
             if (ii == null) {
-                reportStartInstrumentationFailure(watcher, className,
+                reportStartInstrumentationFailureLocked(watcher, className,
                         "Unable to find instrumentation info for: " + className);
                 return false;
             }
             if (ai == null) {
-                reportStartInstrumentationFailure(watcher, className,
+                reportStartInstrumentationFailureLocked(watcher, className,
                         "Unable to find instrumentation target package: " + ii.targetPackage);
                 return false;
             }
             if (!ai.hasCode()) {
-                reportStartInstrumentationFailure(watcher, className,
+                reportStartInstrumentationFailureLocked(watcher, className,
                         "Instrumentation target has no code: " + ii.targetPackage);
                 return false;
             }
@@ -17663,7 +17878,7 @@
                         + " not allowed because package " + ii.packageName
                         + " does not have a signature matching the target "
                         + ii.targetPackage;
-                reportStartInstrumentationFailure(watcher, className, msg);
+                reportStartInstrumentationFailureLocked(watcher, className, msg);
                 throw new SecurityException(msg);
             }
 
@@ -17694,31 +17909,21 @@
      * @param cn The component name of the instrumentation.
      * @param report The error report.
      */
-    private void reportStartInstrumentationFailure(IInstrumentationWatcher watcher,
+    private void reportStartInstrumentationFailureLocked(IInstrumentationWatcher watcher,
             ComponentName cn, String report) {
         Slog.w(TAG, report);
-        try {
-            if (watcher != null) {
-                Bundle results = new Bundle();
-                results.putString(Instrumentation.REPORT_KEY_IDENTIFIER, "ActivityManagerService");
-                results.putString("Error", report);
-                watcher.instrumentationStatus(cn, -1, results);
-            }
-        } catch (RemoteException e) {
-            Slog.w(TAG, e);
+        if (watcher != null) {
+            Bundle results = new Bundle();
+            results.putString(Instrumentation.REPORT_KEY_IDENTIFIER, "ActivityManagerService");
+            results.putString("Error", report);
+            mInstrumentationReporter.reportStatus(watcher, cn, -1, results);
         }
     }
 
     void finishInstrumentationLocked(ProcessRecord app, int resultCode, Bundle results) {
         if (app.instrumentationWatcher != null) {
-            try {
-                // NOTE:  IInstrumentationWatcher *must* be oneway here
-                app.instrumentationWatcher.instrumentationFinished(
-                    app.instrumentationClass,
-                    resultCode,
-                    results);
-            } catch (RemoteException e) {
-            }
+            mInstrumentationReporter.reportFinished(app.instrumentationWatcher,
+                    app.instrumentationClass, resultCode, results);
         }
 
         // Can't call out of the system process with a lock held, so post a message.
@@ -18034,7 +18239,8 @@
 
                 final boolean isDensityChange = (changes & ActivityInfo.CONFIG_DENSITY) != 0;
                 if (isDensityChange) {
-                    killAllBackgroundProcesses(Build.VERSION_CODES.N);
+                    killAllBackgroundProcessesExcept(Build.VERSION_CODES.N,
+                            ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE);
                 }
 
                 for (int i=mLruProcesses.size()-1; i>=0; i--) {
@@ -18255,7 +18461,7 @@
 
         if (app.thread == null) {
             app.adjSeq = mAdjSeq;
-            app.curSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
+            app.curSchedGroup = ProcessList.SCHED_GROUP_BACKGROUND;
             app.curProcState = ActivityManager.PROCESS_STATE_CACHED_EMPTY;
             return (app.curAdj=app.curRawAdj=ProcessList.CACHED_APP_MAX_ADJ);
         }
@@ -18275,7 +18481,7 @@
             app.adjSeq = mAdjSeq;
             app.curRawAdj = app.maxAdj;
             app.foregroundActivities = false;
-            app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
+            app.curSchedGroup = ProcessList.SCHED_GROUP_DEFAULT;
             app.curProcState = ActivityManager.PROCESS_STATE_PERSISTENT;
             // System processes can do UI, and when they do we want to have
             // them trim their memory after the user leaves the UI.  To
@@ -18312,14 +18518,14 @@
         if (app == TOP_APP) {
             // The last app on the list is the foreground app.
             adj = ProcessList.FOREGROUND_APP_ADJ;
-            schedGroup = Process.THREAD_GROUP_TOP_APP;
+            schedGroup = ProcessList.SCHED_GROUP_TOP_APP;
             app.adjType = "top-activity";
             foregroundActivities = true;
             procState = PROCESS_STATE_CUR_TOP;
         } else if (app.instrumentationClass != null) {
             // Don't want to kill running instrumentation.
             adj = ProcessList.FOREGROUND_APP_ADJ;
-            schedGroup = Process.THREAD_GROUP_DEFAULT;
+            schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
             app.adjType = "instrumentation";
             procState = ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE;
         } else if ((queue = isReceivingBroadcast(app)) != null) {
@@ -18329,7 +18535,7 @@
             // broadcast as reflected by which queue it's active in.
             adj = ProcessList.FOREGROUND_APP_ADJ;
             schedGroup = (queue == mFgBroadcastQueue)
-                    ? Process.THREAD_GROUP_DEFAULT : Process.THREAD_GROUP_BG_NONINTERACTIVE;
+                    ? ProcessList.SCHED_GROUP_DEFAULT : ProcessList.SCHED_GROUP_BACKGROUND;
             app.adjType = "broadcast";
             procState = ActivityManager.PROCESS_STATE_RECEIVER;
         } else if (app.executingServices.size() > 0) {
@@ -18337,13 +18543,13 @@
             // counts as being in the foreground.
             adj = ProcessList.FOREGROUND_APP_ADJ;
             schedGroup = app.execServicesFg ?
-                    Process.THREAD_GROUP_DEFAULT : Process.THREAD_GROUP_BG_NONINTERACTIVE;
+                    ProcessList.SCHED_GROUP_DEFAULT : ProcessList.SCHED_GROUP_BACKGROUND;
             app.adjType = "exec-service";
             procState = ActivityManager.PROCESS_STATE_SERVICE;
             //Slog.i(TAG, "EXEC " + (app.execServicesFg ? "FG" : "BG") + ": " + app);
         } else {
             // As far as we know the process is empty.  We may change our mind later.
-            schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
+            schedGroup = ProcessList.SCHED_GROUP_BACKGROUND;
             // At this point we don't actually know the adjustment.  Use the cached adj
             // value that the caller wants us to.
             adj = cachedAdj;
@@ -18372,7 +18578,7 @@
                     if (procState > PROCESS_STATE_CUR_TOP) {
                         procState = PROCESS_STATE_CUR_TOP;
                     }
-                    schedGroup = Process.THREAD_GROUP_DEFAULT;
+                    schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
                     app.cached = false;
                     app.empty = false;
                     foregroundActivities = true;
@@ -18391,7 +18597,7 @@
                     if (procState > PROCESS_STATE_CUR_TOP) {
                         procState = PROCESS_STATE_CUR_TOP;
                     }
-                    schedGroup = Process.THREAD_GROUP_DEFAULT;
+                    schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
                     app.cached = false;
                     app.empty = false;
                     foregroundActivities = true;
@@ -18435,7 +18641,7 @@
                 procState = ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE;
                 app.cached = false;
                 app.adjType = "fg-service";
-                schedGroup = Process.THREAD_GROUP_DEFAULT;
+                schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
             } else if (app.forcingToForeground != null) {
                 // The user is aware of this app, so make it visible.
                 adj = ProcessList.PERCEPTIBLE_APP_ADJ;
@@ -18443,7 +18649,7 @@
                 app.cached = false;
                 app.adjType = "force-fg";
                 app.adjSource = app.forcingToForeground;
-                schedGroup = Process.THREAD_GROUP_DEFAULT;
+                schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
             }
         }
 
@@ -18451,7 +18657,7 @@
             if (adj > ProcessList.HEAVY_WEIGHT_APP_ADJ) {
                 // We don't want to kill the current heavy-weight process.
                 adj = ProcessList.HEAVY_WEIGHT_APP_ADJ;
-                schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
+                schedGroup = ProcessList.SCHED_GROUP_BACKGROUND;
                 app.cached = false;
                 app.adjType = "heavy";
             }
@@ -18465,7 +18671,7 @@
                 // This process is hosting what we currently consider to be the
                 // home app, so we don't want to let it go into the background.
                 adj = ProcessList.HOME_APP_ADJ;
-                schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
+                schedGroup = ProcessList.SCHED_GROUP_BACKGROUND;
                 app.cached = false;
                 app.adjType = "home";
             }
@@ -18480,7 +18686,7 @@
                 // We want to try to keep it around more aggressively, to give
                 // a good experience around switching between two apps.
                 adj = ProcessList.PREVIOUS_APP_ADJ;
-                schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
+                schedGroup = ProcessList.SCHED_GROUP_BACKGROUND;
                 app.cached = false;
                 app.adjType = "previous";
             }
@@ -18520,7 +18726,7 @@
 
         for (int is = app.services.size()-1;
                 is >= 0 && (adj > ProcessList.FOREGROUND_APP_ADJ
-                        || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE
+                        || schedGroup == ProcessList.SCHED_GROUP_BACKGROUND
                         || procState > ActivityManager.PROCESS_STATE_TOP);
                 is--) {
             ServiceRecord s = app.services.valueAt(is);
@@ -18558,13 +18764,13 @@
             }
             for (int conni = s.connections.size()-1;
                     conni >= 0 && (adj > ProcessList.FOREGROUND_APP_ADJ
-                            || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE
+                            || schedGroup == ProcessList.SCHED_GROUP_BACKGROUND
                             || procState > ActivityManager.PROCESS_STATE_TOP);
                     conni--) {
                 ArrayList<ConnectionRecord> clist = s.connections.valueAt(conni);
                 for (int i = 0;
                         i < clist.size() && (adj > ProcessList.FOREGROUND_APP_ADJ
-                                || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE
+                                || schedGroup == ProcessList.SCHED_GROUP_BACKGROUND
                                 || procState > ActivityManager.PROCESS_STATE_TOP);
                         i++) {
                     // XXX should compute this based on the max of
@@ -18656,7 +18862,7 @@
                                 if ((cr.flags&Context.BIND_IMPORTANT) != 0) {
                                     schedGroup = client.curSchedGroup;
                                 } else {
-                                    schedGroup = Process.THREAD_GROUP_DEFAULT;
+                                    schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
                                 }
                             }
                             if (clientProcState <= ActivityManager.PROCESS_STATE_TOP) {
@@ -18726,9 +18932,9 @@
                             adj = ProcessList.FOREGROUND_APP_ADJ;
                             if ((cr.flags&Context.BIND_NOT_FOREGROUND) == 0) {
                                 if ((cr.flags&Context.BIND_IMPORTANT) != 0) {
-                                    schedGroup = Process.THREAD_GROUP_TOP_APP;
+                                    schedGroup = ProcessList.SCHED_GROUP_TOP_APP;
                                 } else {
-                                    schedGroup = Process.THREAD_GROUP_DEFAULT;
+                                    schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
                                 }
                             }
                             app.cached = false;
@@ -18746,13 +18952,13 @@
 
         for (int provi = app.pubProviders.size()-1;
                 provi >= 0 && (adj > ProcessList.FOREGROUND_APP_ADJ
-                        || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE
+                        || schedGroup == ProcessList.SCHED_GROUP_BACKGROUND
                         || procState > ActivityManager.PROCESS_STATE_TOP);
                 provi--) {
             ContentProviderRecord cpr = app.pubProviders.valueAt(provi);
             for (int i = cpr.connections.size()-1;
                     i >= 0 && (adj > ProcessList.FOREGROUND_APP_ADJ
-                            || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE
+                            || schedGroup == ProcessList.SCHED_GROUP_BACKGROUND
                             || procState > ActivityManager.PROCESS_STATE_TOP);
                     i--) {
                 ContentProviderConnection conn = cpr.connections.get(i);
@@ -18810,7 +19016,7 @@
                     procState = clientProcState;
                 }
                 if (client.curSchedGroup > schedGroup) {
-                    schedGroup = Process.THREAD_GROUP_DEFAULT;
+                    schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
                 }
             }
             // If the provider has external (non-framework) process
@@ -18819,7 +19025,7 @@
             if (cpr.hasExternalProcessHandles()) {
                 if (adj > ProcessList.FOREGROUND_APP_ADJ) {
                     adj = ProcessList.FOREGROUND_APP_ADJ;
-                    schedGroup = Process.THREAD_GROUP_DEFAULT;
+                    schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
                     app.cached = false;
                     app.adjType = "provider";
                     app.adjTarget = cpr.name;
@@ -18833,7 +19039,7 @@
         if (app.lastProviderTime > 0 && (app.lastProviderTime+CONTENT_PROVIDER_RETAIN_TIME) > now) {
             if (adj > ProcessList.PREVIOUS_APP_ADJ) {
                 adj = ProcessList.PREVIOUS_APP_ADJ;
-                schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
+                schedGroup = ProcessList.SCHED_GROUP_BACKGROUND;
                 app.cached = false;
                 app.adjType = "provider";
             }
@@ -18912,7 +19118,7 @@
         if (adj > app.maxAdj) {
             adj = app.maxAdj;
             if (app.maxAdj <= ProcessList.PERCEPTIBLE_APP_ADJ) {
-                schedGroup = Process.THREAD_GROUP_DEFAULT;
+                schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
             }
         }
 
@@ -19328,17 +19534,29 @@
         if (app.setSchedGroup != app.curSchedGroup) {
             app.setSchedGroup = app.curSchedGroup;
             if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(TAG_OOM_ADJ,
-                    "Setting process group of " + app.processName
+                    "Setting sched group of " + app.processName
                     + " to " + app.curSchedGroup);
             if (app.waitingToKill != null && app.curReceiver == null
-                    && app.setSchedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE) {
+                    && app.setSchedGroup == ProcessList.SCHED_GROUP_BACKGROUND) {
                 app.kill(app.waitingToKill, true);
                 success = false;
             } else {
+                int processGroup;
+                switch (app.curSchedGroup) {
+                    case ProcessList.SCHED_GROUP_BACKGROUND:
+                        processGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
+                        break;
+                    case ProcessList.SCHED_GROUP_TOP_APP:
+                        processGroup = Process.THREAD_GROUP_TOP_APP;
+                        break;
+                    default:
+                        processGroup = Process.THREAD_GROUP_DEFAULT;
+                        break;
+                }
                 if (true) {
                     long oldId = Binder.clearCallingIdentity();
                     try {
-                        Process.setProcessGroup(app.pid, app.curSchedGroup);
+                        Process.setProcessGroup(app.pid, processGroup);
                     } catch (Exception e) {
                         Slog.w(TAG, "Failed setting process group of " + app.pid
                                 + " to " + app.curSchedGroup);
@@ -19349,7 +19567,7 @@
                 } else {
                     if (app.thread != null) {
                         try {
-                            app.thread.setSchedulingGroup(app.curSchedGroup);
+                            app.thread.setSchedulingGroup(processGroup);
                         } catch (RemoteException e) {
                         }
                     }
@@ -20757,6 +20975,20 @@
                         voiceSession, voiceInteractor);
             }
         }
+
+        @Override
+        public void notifyStartingWindowDrawn() {
+            synchronized (ActivityManagerService.this) {
+                mStackSupervisor.mActivityMetricsLogger.notifyStartingWindowDrawn();
+            }
+        }
+
+        @Override
+        public void notifyAppTransitionStarting(int reason) {
+            synchronized (ActivityManagerService.this) {
+                mStackSupervisor.mActivityMetricsLogger.notifyTransitionStarting(reason);
+            }
+        }
     }
 
     private final class SleepTokenImpl extends SleepToken {
diff --git a/services/core/java/com/android/server/am/ActivityMetricsLogger.java b/services/core/java/com/android/server/am/ActivityMetricsLogger.java
index ffb2fc4..43e1bdf 100644
--- a/services/core/java/com/android/server/am/ActivityMetricsLogger.java
+++ b/services/core/java/com/android/server/am/ActivityMetricsLogger.java
@@ -7,11 +7,13 @@
 import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
 import static com.android.server.am.ActivityStack.STACK_INVISIBLE;
 
+import android.annotation.Nullable;
 import android.app.ActivityManager.StackId;
 import android.content.Context;
 import android.os.SystemClock;
 
 import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.MetricsProto.MetricsEvent;
 
 /**
  * Handles logging into Tron.
@@ -24,6 +26,8 @@
     private static final int WINDOW_STATE_FREEFORM = 2;
     private static final int WINDOW_STATE_INVALID = -1;
 
+    private static final long INVALID_START_TIME = -1;
+
     // Preallocated strings we are sending to tron, so we don't have to allocate a new one every
     // time we log.
     private static final String[] TRON_WINDOW_STATE_VARZ_STRINGS = {
@@ -34,6 +38,11 @@
     private final ActivityStackSupervisor mSupervisor;
     private final Context mContext;
 
+    private long mCurrentTransitionStartTime = INVALID_START_TIME;
+    private boolean mLoggedWindowsDrawn;
+    private boolean mLoggedStartingWindowDrawn;
+    private boolean mLoggedTransitionStarting;
+
     ActivityMetricsLogger(ActivityStackSupervisor supervisor, Context context) {
         mLastLogTimeSecs = SystemClock.elapsedRealtime() / 1000;
         mSupervisor = supervisor;
@@ -52,7 +61,7 @@
         mLastLogTimeSecs = now;
 
         ActivityStack stack = mSupervisor.getStack(DOCKED_STACK_ID);
-        if (stack != null && stack.getStackVisibilityLocked() != STACK_INVISIBLE) {
+        if (stack != null && stack.getStackVisibilityLocked(null) != STACK_INVISIBLE) {
             mWindowState = WINDOW_STATE_SIDE_BY_SIDE;
             return;
         }
@@ -73,4 +82,101 @@
             throw new IllegalStateException("Unknown stack=" + stack);
         }
     }
+
+    /**
+     * Notifies the tracker at the earliest possible point when we are starting to launch an
+     * activity.
+     */
+    void notifyActivityLaunching() {
+        mCurrentTransitionStartTime = System.currentTimeMillis();
+    }
+
+    /**
+     * Notifies the tracker the the activity is actually launching.
+     *
+     * @param resultCode one of the ActivityManager.START_* flags, indicating the result of the
+     *                   launch
+     * @param componentName the component name of the activity being launched
+     * @param processRunning whether the process that will contains the activity is already running
+     */
+    void notifyActivityLaunched(int resultCode, @Nullable String componentName,
+            boolean processRunning) {
+
+        if (resultCode < 0 || componentName == null) {
+
+            // Failed to launch, don't track anything.
+            reset();
+            return;
+        }
+
+        MetricsLogger.action(mContext, MetricsEvent.APP_TRANSITION_COMPONENT_NAME,
+                componentName);
+        MetricsLogger.action(mContext, MetricsEvent.APP_TRANSITION_PROCESS_RUNNING,
+                processRunning);
+        MetricsLogger.action(mContext, MetricsEvent.APP_TRANSITION_DEVICE_UPTIME_SECONDS,
+                (int) (SystemClock.uptimeMillis() / 1000));
+    }
+
+    /**
+     * Notifies the tracker that all windows of the app have been drawn.
+     */
+    void notifyWindowsDrawn() {
+        if (!isTransitionActive() || mLoggedWindowsDrawn) {
+            return;
+        }
+        MetricsLogger.action(mContext, MetricsEvent.APP_TRANSITION_WINDOWS_DRAWN_DELAY_MS,
+                calculateCurrentDelay());
+        mLoggedWindowsDrawn = true;
+        if (mLoggedTransitionStarting) {
+            reset();
+        }
+    }
+
+    /**
+     * Notifies the tracker that the starting window was drawn.
+     */
+    void notifyStartingWindowDrawn() {
+        if (!isTransitionActive() || mLoggedStartingWindowDrawn) {
+            return;
+        }
+        mLoggedStartingWindowDrawn = true;
+        MetricsLogger.action(mContext, MetricsEvent.APP_TRANSITION_STARTING_WINDOW_DELAY_MS,
+                calculateCurrentDelay());
+    }
+
+    /**
+     * Notifies the tracker that the app transition is starting.
+     *
+     * @param reason The reason why we started it. Must be on of
+     *               ActivityManagerInternal.APP_TRANSITION_* reasons.
+     */
+    void notifyTransitionStarting(int reason) {
+        if (!isTransitionActive() || mLoggedTransitionStarting) {
+            return;
+        }
+        MetricsLogger.action(mContext, MetricsEvent.APP_TRANSITION_REASON, reason);
+        MetricsLogger.action(mContext, MetricsEvent.APP_TRANSITION_DELAY_MS,
+                calculateCurrentDelay());
+        mLoggedTransitionStarting = true;
+        if (mLoggedWindowsDrawn) {
+            reset();
+        }
+    }
+
+    private boolean isTransitionActive() {
+        return mCurrentTransitionStartTime != INVALID_START_TIME;
+    }
+
+    private void reset() {
+        mCurrentTransitionStartTime = INVALID_START_TIME;
+        mLoggedWindowsDrawn = false;
+        mLoggedTransitionStarting = false;
+        mLoggedStartingWindowDrawn = false;
+    }
+
+    private int calculateCurrentDelay() {
+
+        // Shouldn't take more than 25 days to launch an app, so int is fine here.
+        return (int) (System.currentTimeMillis() - mCurrentTransitionStartTime);
+    }
 }
diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java
index 32ca5bf..5219827 100755
--- a/services/core/java/com/android/server/am/ActivityRecord.java
+++ b/services/core/java/com/android/server/am/ActivityRecord.java
@@ -76,6 +76,7 @@
 import java.io.PrintWriter;
 import java.lang.ref.WeakReference;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.HashSet;
 import java.util.Objects;
 
@@ -122,7 +123,7 @@
     final boolean stateNotNeeded; // As per ActivityInfo.flags
     boolean fullscreen; // covers the full screen?
     final boolean noDisplay;  // activity is not displayed?
-    final boolean componentSpecified;  // did caller specifiy an explicit component?
+    final boolean componentSpecified;  // did caller specify an explicit component?
     final boolean rootVoiceInteraction;  // was this the root activity of a voice interaction?
 
     static final int APPLICATION_ACTIVITY_TYPE = 0;
@@ -189,14 +190,19 @@
     boolean forceNewConfig; // force re-create with new config next time
     int launchCount;        // count of launches since last state
     long lastLaunchTime;    // time of last launch of this activity
-    boolean isVrActivity;   // is the activity running in VR mode?
+    ComponentName requestedVrComponent; // the requested component for handling VR mode.
     ArrayList<ActivityContainer> mChildContainers = new ArrayList<>();
 
     String stringName;      // for caching of toString().
 
     private boolean inHistory;  // are we in the history stack?
     final ActivityStackSupervisor mStackSupervisor;
-    boolean mStartingWindowShown = false;
+
+    static final int STARTING_WINDOW_NOT_SHOWN = 0;
+    static final int STARTING_WINDOW_SHOWN = 1;
+    static final int STARTING_WINDOW_REMOVED = 2;
+    int mStartingWindowState = STARTING_WINDOW_NOT_SHOWN;
+
     boolean mUpdateTaskThumbnailWhenHidden;
     ActivityContainer mInitialActivityContainer;
 
@@ -214,6 +220,19 @@
     boolean pendingVoiceInteractionStart;   // Waiting for activity-invoked voice session
     IVoiceInteractionSession voiceSession;  // Voice interaction session for this activity
 
+    private static String startingWindowStateToString(int state) {
+        switch (state) {
+            case STARTING_WINDOW_NOT_SHOWN:
+                return "STARTING_WINDOW_NOT_SHOWN";
+            case STARTING_WINDOW_SHOWN:
+                return "STARTING_WINDOW_SHOWN";
+            case STARTING_WINDOW_REMOVED:
+                return "STARTING_WINDOW_REMOVED";
+            default:
+                return "unknown state=" + state;
+        }
+    }
+
     void dump(PrintWriter pw, String prefix) {
         final long now = SystemClock.uptimeMillis();
         pw.print(prefix); pw.print("packageName="); pw.print(packageName);
@@ -234,6 +253,10 @@
                 pw.print(prefix); pw.print("resDir="); pw.println(appInfo.publicSourceDir);
             }
             pw.print(prefix); pw.print("dataDir="); pw.println(appInfo.dataDir);
+            if (appInfo.splitSourceDirs != null) {
+                pw.print(prefix); pw.print("splitDir=");
+                        pw.println(Arrays.toString(appInfo.splitSourceDirs));
+            }
         }
         pw.print(prefix); pw.print("stateNotNeeded="); pw.print(stateNotNeeded);
                 pw.print(" componentSpecified="); pw.print(componentSpecified);
@@ -320,8 +343,9 @@
                 pw.print(" inHistory="); pw.print(inHistory);
                 pw.print(" visible="); pw.print(visible);
                 pw.print(" sleeping="); pw.print(sleeping);
-                pw.print(" idle="); pw.println(idle);
-                pw.print(" mStartingWindowShown="); pw.println(mStartingWindowShown);
+                pw.print(" idle="); pw.print(idle);
+                pw.print(" mStartingWindowState=");
+                pw.println(startingWindowStateToString(mStartingWindowState));
         pw.print(prefix); pw.print("fullscreen="); pw.print(fullscreen);
                 pw.print(" noDisplay="); pw.print(noDisplay);
                 pw.print(" immersive="); pw.print(immersive);
@@ -330,7 +354,11 @@
                 pw.print(" forceNewConfig="); pw.println(forceNewConfig);
         pw.print(prefix); pw.print("mActivityType=");
                 pw.println(activityTypeToString(mActivityType));
-        pw.print(prefix); pw.print("vrMode="); pw.println(isVrActivity);
+        if (requestedVrComponent != null) {
+            pw.print(prefix);
+            pw.print("requestedVrComponent=");
+            pw.println(requestedVrComponent);
+        }
         if (displayStartTime != 0 || startTime != 0) {
             pw.print(prefix); pw.print("displayStartTime=");
                     if (displayStartTime == 0) pw.print("0");
@@ -694,7 +722,6 @@
             }
 
             immersive = (aInfo.flags & ActivityInfo.FLAG_IMMERSIVE) != 0;
-            isVrActivity = (aInfo.flags & ActivityInfo.FLAG_ENABLE_VR_MODE) != 0;
         } else {
             realActivity = null;
             taskAffinity = null;
@@ -706,7 +733,6 @@
             noDisplay = false;
             mActivityType = APPLICATION_ACTIVITY_TYPE;
             immersive = false;
-            isVrActivity = false;
         }
     }
 
@@ -1167,6 +1193,7 @@
     }
 
     void windowsDrawnLocked() {
+        mStackSupervisor.mActivityMetricsLogger.notifyWindowsDrawn();
         if (displayStartTime != 0) {
             reportLaunchTimeLocked(SystemClock.uptimeMillis());
         }
@@ -1250,13 +1277,6 @@
         }
     }
 
-    static void activityResumedLocked(IBinder token) {
-        final ActivityRecord r = ActivityRecord.forTokenLocked(token);
-        if (DEBUG_SAVED_STATE) Slog.i(TAG_STATES, "Resumed activity; dropping state of: " + r);
-        r.icicle = null;
-        r.haveState = false;
-    }
-
     static int getTaskForActivityLocked(IBinder token, boolean onlyRoot) {
         final ActivityRecord r = ActivityRecord.forTokenLocked(token);
         if (r == null) {
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index ec37667..09542cb 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -20,6 +20,7 @@
 import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_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.INVALID_STACK_ID;
 import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
 import static android.content.pm.ActivityInfo.CONFIG_ORIENTATION;
 import static android.content.pm.ActivityInfo.CONFIG_SCREEN_LAYOUT;
@@ -34,6 +35,8 @@
 import static com.android.server.am.ActivityRecord.HOME_ACTIVITY_TYPE;
 import static com.android.server.am.ActivityRecord.APPLICATION_ACTIVITY_TYPE;
 
+import static com.android.server.am.ActivityRecord.STARTING_WINDOW_REMOVED;
+import static com.android.server.am.ActivityRecord.STARTING_WINDOW_SHOWN;
 import static com.android.server.am.ActivityStackSupervisor.FindTaskResult;
 import static com.android.server.am.ActivityStackSupervisor.MOVING;
 import static com.android.server.am.ActivityStackSupervisor.PRESERVE_WINDOWS;
@@ -63,7 +66,7 @@
 import android.content.ComponentName;
 import android.content.Intent;
 import android.content.pm.ActivityInfo;
-import android.content.pm.PackageManager;
+import android.content.pm.ApplicationInfo;
 import android.content.res.Configuration;
 import android.graphics.Bitmap;
 import android.net.Uri;
@@ -183,7 +186,7 @@
      * The back history of all previous (and possibly still
      * running) activities.  It contains #TaskRecord objects.
      */
-    private ArrayList<TaskRecord> mTaskHistory = new ArrayList<>();
+    private final ArrayList<TaskRecord> mTaskHistory = new ArrayList<>();
 
     /**
      * Used for validating app tokens with window manager.
@@ -412,6 +415,12 @@
             mTaskPositioner.reset();
         }
         mWindowManager.detachStack(mStackId);
+        if (mStackId == DOCKED_STACK_ID) {
+            // If we removed a docked stack we want to resize it so it resizes all other stacks
+            // in the system to fullscreen.
+            mStackSupervisor.resizeDockedStackLocked(
+                    null, null, null, null, null, PRESERVE_WINDOWS);
+        }
     }
 
     public void getDisplaySize(Point out) {
@@ -838,6 +847,18 @@
         }
     }
 
+    void updateActivityApplicationInfoLocked(ApplicationInfo aInfo) {
+        final String packageName = aInfo.packageName;
+        for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
+            final List<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities;
+            for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
+                if (packageName.equals(activities.get(activityNdx).packageName)) {
+                    activities.get(activityNdx).info.applicationInfo = aInfo;
+                }
+            }
+        }
+    }
+
     /**
      * @return true if something must be done before going to sleep.
      */
@@ -1074,6 +1095,13 @@
         mStackSupervisor.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
     }
 
+    final void activityResumedLocked(IBinder token) {
+        final ActivityRecord r = ActivityRecord.forTokenLocked(token);
+        if (DEBUG_SAVED_STATE) Slog.i(TAG_STATES, "Resumed activity; dropping state of: " + r);
+        r.icicle = null;
+        r.haveState = false;
+    }
+
     final void activityStoppedLocked(ActivityRecord r, Bundle icicle,
             PersistableBundle persistentState, CharSequence description) {
         if (r.state != ActivityState.STOPPING) {
@@ -1100,7 +1128,7 @@
             r.stopped = true;
             r.state = ActivityState.STOPPED;
 
-            mWindowManager.notifyAppStopped(r.appToken);
+            mWindowManager.notifyAppStopped(r.appToken, true);
 
             if (getVisibleBehindActivity() == r) {
                 mStackSupervisor.requestVisibleBehindLocked(r, false);
@@ -1353,7 +1381,7 @@
             for (int i = stacks.size() - 1; i >= 0; --i) {
                 ActivityStack stack = stacks.get(i);
                 if (stack != this && stack.isFocusable()
-                        && stack.getStackVisibilityLocked() != STACK_INVISIBLE) {
+                        && stack.getStackVisibilityLocked(null) != STACK_INVISIBLE) {
                     return stack;
                 }
             }
@@ -1372,22 +1400,42 @@
         return false;
     }
 
-    private boolean hasTranslucentActivity(ActivityStack stack) {
-        final ArrayList<TaskRecord> tasks = stack.getAllTasks();
-        for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) {
-            final TaskRecord task = tasks.get(taskNdx);
+    /**
+     * Returns true if the stack is translucent and can have other contents visible behind it if
+     * needed. A stack is considered translucent if it don't contain a visible or
+     * starting (about to be visible) activity that is fullscreen (opaque).
+     * @param starting The currently starting activity or null if there is none.
+     * @param stackBehindId The id of the stack directly behind this one.
+     */
+    private boolean isStackTranslucent(ActivityRecord starting, int stackBehindId) {
+        for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
+            final TaskRecord task = mTaskHistory.get(taskNdx);
             final ArrayList<ActivityRecord> activities = task.mActivities;
             for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
                 final ActivityRecord r = activities.get(activityNdx);
 
-                // Conditions for an activity to obscure the stack we're
-                // examining:
-                // 1. Not Finishing AND Visible AND:
-                // 2. Either:
-                // - Full Screen Activity OR
-                // - On top of Home and our stack is NOT home
-                if (!r.finishing && r.visible && (r.fullscreen ||
-                        (!isHomeStack() && r.frontOfTask && task.isOverHomeStack()))) {
+                if (r.finishing) {
+                    // We don't factor in finishing activities when determining translucency since
+                    // they will be gone soon.
+                    continue;
+                }
+
+                if (!r.visible && r != starting) {
+                    // Also ignore invisible activities that are not the currently starting
+                    // activity (about to be visible).
+                    continue;
+                }
+
+                if (r.fullscreen) {
+                    // Stack isn't translucent if it has at least one fullscreen activity
+                    // that is visible.
+                    return false;
+                }
+
+                if (!isHomeStack() && r.frontOfTask
+                        && task.isOverHomeStack() && stackBehindId != HOME_STACK_ID) {
+                    // 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 stack.
                     return false;
                 }
             }
@@ -1398,8 +1446,9 @@
     /**
      * Returns stack's visibility: {@link #STACK_INVISIBLE}, {@link #STACK_VISIBLE} or
      * {@link #STACK_VISIBLE_ACTIVITY_BEHIND}.
+     * @param starting The currently starting activity or null if there is none.
      */
-    int getStackVisibilityLocked() {
+    int getStackVisibilityLocked(ActivityRecord starting) {
         if (!isAttached()) {
             return STACK_INVISIBLE;
         }
@@ -1442,30 +1491,33 @@
                     : STACK_INVISIBLE;
         }
 
-        // Find the first stack below focused stack that actually got something visible.
-        int belowFocusedIndex = mStacks.indexOf(focusedStack) - 1;
-        while (belowFocusedIndex >= 0 &&
-                mStacks.get(belowFocusedIndex).topRunningActivityLocked() == null) {
-            belowFocusedIndex--;
+        // Find the first stack behind focused stack that actually got something visible.
+        int stackBehindFocusedIndex = mStacks.indexOf(focusedStack) - 1;
+        while (stackBehindFocusedIndex >= 0 &&
+                mStacks.get(stackBehindFocusedIndex).topRunningActivityLocked() == null) {
+            stackBehindFocusedIndex--;
         }
         if ((focusedStackId == DOCKED_STACK_ID || focusedStackId == PINNED_STACK_ID)
-                && stackIndex == belowFocusedIndex) {
+                && stackIndex == stackBehindFocusedIndex) {
             // Stacks directly behind the docked or pinned stack are always visible.
             return STACK_VISIBLE;
         }
 
+        final int stackBehindFocusedId = (stackBehindFocusedIndex >= 0)
+                ? mStacks.get(stackBehindFocusedIndex).mStackId : INVALID_STACK_ID;
+
         if (focusedStackId == FULLSCREEN_WORKSPACE_STACK_ID
-                && hasTranslucentActivity(focusedStack)) {
+                && focusedStack.isStackTranslucent(starting, stackBehindFocusedId)) {
             // Stacks behind the fullscreen stack with a translucent activity are always
             // visible so they can act as a backdrop to the translucent activity.
             // For example, dialog activities
-            if (stackIndex == belowFocusedIndex) {
+            if (stackIndex == stackBehindFocusedIndex) {
                 return STACK_VISIBLE;
             }
-            if (belowFocusedIndex >= 0) {
-                final ActivityStack stack = mStacks.get(belowFocusedIndex);
-                if ((stack.mStackId == DOCKED_STACK_ID || stack.mStackId == PINNED_STACK_ID)
-                        && stackIndex == (belowFocusedIndex - 1)) {
+            if (stackBehindFocusedIndex >= 0) {
+                if ((stackBehindFocusedId == DOCKED_STACK_ID
+                        || stackBehindFocusedId == PINNED_STACK_ID)
+                        && stackIndex == (stackBehindFocusedIndex - 1)) {
                     // The stack behind the docked or pinned stack is also visible so we can have a
                     // complete backdrop to the translucent activity when the docked stack is up.
                     return STACK_VISIBLE;
@@ -1490,7 +1542,7 @@
                 return STACK_INVISIBLE;
             }
 
-            if (!hasTranslucentActivity(stack)) {
+            if (!stack.isStackTranslucent(starting, INVALID_STACK_ID)) {
                 return STACK_INVISIBLE;
             }
         }
@@ -1528,7 +1580,7 @@
         // If the top activity is not fullscreen, then we need to
         // make sure any activities under it are now visible.
         boolean aboveTop = top != null;
-        final int stackVisibility = getStackVisibilityLocked();
+        final int stackVisibility = getStackVisibilityLocked(starting);
         final boolean stackInvisible = stackVisibility != STACK_VISIBLE;
         final boolean stackVisibleBehind = stackVisibility == STACK_VISIBLE_ACTIVITY_BEHIND;
         boolean behindFullscreenActivity = stackInvisible;
@@ -1757,6 +1809,12 @@
             r.app.pendingUiClean = true;
             r.app.thread.scheduleWindowVisibility(r.appToken, true);
             r.stopFreezingScreenLocked(false);
+
+            // The activity may be waiting for stop, but that is no longer
+            // appropriate for it.
+            mStackSupervisor.mStoppingActivities.remove(r);
+            mStackSupervisor.mGoingToSleepActivities.remove(r);
+            mStackSupervisor.mWaitingVisibleActivities.remove(r);
         } catch (Exception e) {
             // Just skip on any failure; we'll make it
             // visible when it next restarts.
@@ -1845,10 +1903,11 @@
                     continue;
                 }
 
-                if (r.state == ActivityState.INITIALIZING && r.mStartingWindowShown) {
+                if (r.state == ActivityState.INITIALIZING
+                        && r.mStartingWindowState == STARTING_WINDOW_SHOWN) {
                     if (DEBUG_VISIBILITY) Slog.w(TAG_VISIBILITY,
                             "Found orphaned starting window " + r);
-                    r.mStartingWindowShown = false;
+                    r.mStartingWindowState = STARTING_WINDOW_REMOVED;
                     mWindowManager.removeAppStartingWindow(r.appToken);
                 }
             }
@@ -2231,6 +2290,10 @@
                     next.app.thread.scheduleNewIntent(next.newIntents, next.appToken);
                 }
 
+                // Well the app will no longer be stopped.
+                // Clear app token stopped state in window manager if needed.
+                mWindowManager.notifyAppStopped(next.appToken, false);
+
                 EventLog.writeEvent(EventLogTags.AM_RESUME_ACTIVITY, next.userId,
                         System.identityHashCode(next), next.task.taskId, next.shortComponentName);
 
@@ -2263,7 +2326,7 @@
                             mService.compatibilityInfoForPackageLocked(next.info.applicationInfo),
                             next.nonLocalizedLabel, next.labelRes, next.icon, next.logo,
                             next.windowFlags, null, true);
-                    next.mStartingWindowShown = true;
+                    next.mStartingWindowState = STARTING_WINDOW_SHOWN;
                 }
                 mStackSupervisor.startSpecificActivityLocked(next, true, false);
                 if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
@@ -2296,7 +2359,7 @@
                             next.nonLocalizedLabel,
                             next.labelRes, next.icon, next.logo, next.windowFlags,
                             null, true);
-                    next.mStartingWindowShown = true;
+                    next.mStartingWindowState = STARTING_WINDOW_SHOWN;
                 }
                 if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Restarting: " + next);
             }
@@ -2529,7 +2592,7 @@
                                 r.info.applicationInfo), r.nonLocalizedLabel,
                         r.labelRes, r.icon, r.logo, r.windowFlags,
                         prev != null ? prev.appToken : null, showStartingIcon);
-                r.mStartingWindowShown = true;
+                r.mStartingWindowState = STARTING_WINDOW_SHOWN;
             }
         } else {
             // If this is the first activity, don't do any fancy animations,
@@ -3003,6 +3066,8 @@
                 if (!r.visible) {
                     mWindowManager.setAppVisibility(r.appToken, false);
                 }
+                EventLogTags.writeAmStopActivity(
+                        r.userId, System.identityHashCode(r), r.shortComponentName);
                 r.app.thread.scheduleStopActivity(r.appToken, r.visible, r.configChangeFlags);
                 if (mService.isSleepingOrShuttingDown()) {
                     r.setSleeping(true);
@@ -3784,7 +3849,8 @@
     void releaseBackgroundResources(ActivityRecord r) {
         if (hasVisibleBehindActivity() &&
                 !mHandler.hasMessages(RELEASE_BACKGROUND_RESOURCES_TIMEOUT_MSG)) {
-            if (r == topRunningActivityLocked() && getStackVisibilityLocked() == STACK_VISIBLE) {
+            if (r == topRunningActivityLocked()
+                    && getStackVisibilityLocked(null) == STACK_VISIBLE) {
                 // Don't release the top activity if it has requested to run behind the next
                 // activity and the stack is currently visible.
                 return;
@@ -4408,10 +4474,10 @@
                     "Moving to " + (andResume ? "RESUMED" : "PAUSED") + " Relaunching " + r
                     + " callers=" + Debug.getCallers(6));
             r.forceNewConfig = false;
+            mStackSupervisor.activityRelaunchingLocked(r);
             r.app.thread.scheduleRelaunchActivity(r.appToken, results, newIntents, changes,
                     !andResume, new Configuration(mService.mConfiguration),
                     new Configuration(r.task.mOverrideConfig), preserveWindow);
-            mStackSupervisor.activityRelaunchingLocked(r);
             // Note: don't need to call pauseIfSleepingLocked() here, because
             // the caller will only pass in 'andResume' if this activity is
             // currently resumed, which implies we aren't sleeping.
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index af5f6b3..d364d85 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -406,7 +406,7 @@
     // Whether tasks have moved and we need to rank the tasks before next OOM scoring
     private boolean mTaskLayersChanged = true;
 
-    private final ActivityMetricsLogger mActivityMetricsLogger;
+    final ActivityMetricsLogger mActivityMetricsLogger;
 
     private final ResizeDockedStackTimeout mResizeDockedStackTimeout;
 
@@ -1700,6 +1700,15 @@
         return false;
     }
 
+    void updateActivityApplicationInfoLocked(ApplicationInfo aInfo) {
+        for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
+            final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
+            for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
+                stacks.get(stackNdx).updateActivityApplicationInfoLocked(aInfo);
+            }
+        }
+    }
+
     TaskRecord finishTopRunningActivityLocked(ProcessRecord app, String reason) {
         TaskRecord finishedTask = null;
         ActivityStack focusedStack = getFocusedStack();
@@ -2034,7 +2043,27 @@
                 || tempOtherTaskInsetBounds != null);
     }
 
-    boolean resizeTaskLocked(TaskRecord task, Rect bounds, int resizeMode, boolean preserveWindow) {
+    void resizePinnedStackLocked(Rect pinnedBounds, Rect tempPinnedTaskBounds) {
+        final ActivityStack stack = getStack(PINNED_STACK_ID);
+        if (stack == null) {
+            Slog.w(TAG, "resizePinnedStackLocked: pinned stack not found");
+            return;
+        }
+        Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "am.resizePinnedStack");
+        mWindowManager.deferSurfaceLayout();
+        try {
+            ActivityRecord r = stack.topRunningActivityLocked();
+            resizeStackUncheckedLocked(stack, pinnedBounds, tempPinnedTaskBounds,
+                    null);
+            ensureConfigurationAndResume(stack, r, false);
+        } finally {
+            mWindowManager.continueSurfaceLayout();
+            Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
+        }
+    }
+
+    boolean resizeTaskLocked(TaskRecord task, Rect bounds, int resizeMode, boolean preserveWindow,
+            boolean deferResume) {
         if (!task.isResizeable()) {
             Slog.w(TAG, "resizeTask: task " + task + " not resizeable.");
             return true;
@@ -2077,10 +2106,14 @@
             if (r != null) {
                 final ActivityStack stack = task.stack;
                 kept = stack.ensureActivityConfigurationLocked(r, 0, preserveWindow);
-                // All other activities must be made visible with their correct configuration.
-                ensureActivitiesVisibleLocked(r, 0, !PRESERVE_WINDOWS);
-                if (!kept) {
-                    resumeFocusedStackTopActivityLocked();
+
+                if (!deferResume) {
+
+                    // All other activities must be made visible with their correct configuration.
+                    ensureActivitiesVisibleLocked(r, 0, !PRESERVE_WINDOWS);
+                    if (!kept) {
+                        resumeFocusedStackTopActivityLocked();
+                    }
                 }
             }
         }
@@ -2174,6 +2207,12 @@
      */
     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.getTopActivity();
         final ActivityStack prevStack = task.stack;
         final boolean wasFocused = isFocusedStack(prevStack) && (topRunningActivityLocked() == r);
@@ -2184,9 +2223,7 @@
         final boolean wasFront = isFrontStack(prevStack)
                 && (prevStack.topRunningActivityLocked() == r);
 
-        final int resizeMode = task.mResizeMode;
-
-        if (stackId == DOCKED_STACK_ID && resizeMode == RESIZE_MODE_UNRESIZEABLE) {
+        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
@@ -2213,18 +2250,24 @@
         return stack;
     }
 
-    void moveTaskToStackLocked(int taskId, int stackId, boolean toTop, boolean forceFocus,
+    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;
+            return false;
         }
 
         if (task.stack != null && task.stack.mStackId == stackId) {
             // You are already in the right stack silly...
             Slog.i(TAG, "moveTaskToStack: taskId=" + taskId + " already in stackId=" + stackId);
-            return;
+            return true;
         }
 
         if (stackId == FREEFORM_WORKSPACE_STACK_ID && !mService.mSupportsFreeformWindowManagement) {
@@ -2265,16 +2308,19 @@
 
             // Make sure the task has the appropriate bounds/size for the stack it is in.
             if (stackId == FULLSCREEN_WORKSPACE_STACK_ID && task.mBounds != null) {
-                kept = resizeTaskLocked(task, stack.mBounds, RESIZE_MODE_SYSTEM, !mightReplaceWindow);
+                kept = resizeTaskLocked(task, 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 = resizeTaskLocked(task, bounds, RESIZE_MODE_FORCED, !mightReplaceWindow);
+                kept = resizeTaskLocked(task, bounds, RESIZE_MODE_FORCED, !mightReplaceWindow,
+                        deferResume);
             } else if (stackId == DOCKED_STACK_ID || stackId == PINNED_STACK_ID) {
-                kept = resizeTaskLocked(task, stack.mBounds, RESIZE_MODE_SYSTEM, !mightReplaceWindow);
+                kept = resizeTaskLocked(task, stack.mBounds, RESIZE_MODE_SYSTEM,
+                        !mightReplaceWindow, deferResume);
             }
         } finally {
             mWindowManager.continueSurfaceLayout();
@@ -2287,12 +2333,17 @@
             mWindowManager.scheduleClearReplacingWindowIfNeeded(topActivity.appToken, !kept);
         }
 
-        // 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();
+        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();
+        }
 
         showNonResizeableDockToastIfNeeded(task, preferredLaunchStackId, stackId);
+
+        return (preferredLaunchStackId == stackId);
     }
 
     boolean moveTopStackActivityToPinnedStackLocked(int stackId, Rect bounds) {
@@ -2338,6 +2389,11 @@
             if (task.mActivities.size() == 1) {
                 // There is only one activity in the task. So, we can just move the task over to
                 // the stack without re-parenting the activity in a different task.
+                if (task.getTaskToReturnTo() == HOME_ACTIVITY_TYPE) {
+                    // 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);
             } else {
diff --git a/services/core/java/com/android/server/am/ActivityStarter.java b/services/core/java/com/android/server/am/ActivityStarter.java
index 9c7eb95..83ad2a7 100644
--- a/services/core/java/com/android/server/am/ActivityStarter.java
+++ b/services/core/java/com/android/server/am/ActivityStarter.java
@@ -593,6 +593,7 @@
         if (intent != null && intent.hasFileDescriptors()) {
             throw new IllegalArgumentException("File descriptors passed in Intent");
         }
+        mSupervisor.mActivityMetricsLogger.notifyActivityLaunching();
         boolean componentSpecified = intent.getComponent() != null;
 
         // Save a copy in case ephemeral needs it
@@ -722,11 +723,13 @@
                 }
             }
 
+            final ActivityRecord[] outRecord = new ActivityRecord[1];
             int res = startActivityLocked(caller, intent, ephemeralIntent, resolvedType,
                     aInfo, rInfo, voiceSession, voiceInteractor,
                     resultTo, resultWho, requestCode, callingPid,
                     callingUid, callingPackage, realCallingPid, realCallingUid, startFlags,
-                    options, ignoreTargetSecurity, componentSpecified, null, container, inTask);
+                    options, ignoreTargetSecurity, componentSpecified, outRecord, container,
+                    inTask);
 
             Binder.restoreCallingIdentity(origId);
 
@@ -773,6 +776,13 @@
                 }
             }
 
+            final String componentName = outRecord[0] != null ? outRecord[0].shortComponentName
+                    : null;
+            final boolean processRunning = outRecord[0] != null &&
+                    mService.mProcessNames.get(outRecord[0].processName,
+                            outRecord[0].appInfo.uid) != null;
+            mSupervisor.mActivityMetricsLogger.notifyActivityLaunched(res, componentName,
+                    processRunning);
             return res;
         }
     }
@@ -1406,7 +1416,7 @@
                 }
                 intentActivity.deliverNewIntentLocked(mCallingUid, mStartActivity.intent,
                         mStartActivity.launchedFromPackage);
-            } else if (!mStartActivity.intent.filterEquals(intentActivity.intent)) {
+            } else if (!intentActivity.task.isSameIntentResolution(mStartActivity)) {
                 // In this case we are launching the root activity of the task, but with a
                 // different intent. We should start a new instance on top.
                 mAddingToTask = true;
@@ -1747,7 +1757,7 @@
             // and if yes, we will launch into that stack. If not, we just put the new
             // activity into parent's stack, because we can't find a better place.
             final ActivityStack stack = mSupervisor.getStack(DOCKED_STACK_ID);
-            if (stack != null && stack.getStackVisibilityLocked() == STACK_INVISIBLE) {
+            if (stack != null && stack.getStackVisibilityLocked(r) == STACK_INVISIBLE) {
                 // There is a docked stack, but it isn't visible, so we can't launch into that.
                 return null;
             } else {
@@ -1762,12 +1772,13 @@
             return false;
         }
 
-        if (stackId == DOCKED_STACK_ID && r.canGoInDockedStack()) {
-            return true;
+        if (stackId != FULLSCREEN_WORKSPACE_STACK_ID
+                && (!mService.mSupportsMultiWindow || !r.isResizeableOrForced())) {
+            return false;
         }
 
-        if (stackId != FULLSCREEN_WORKSPACE_STACK_ID && !r.isResizeableOrForced()) {
-            return false;
+        if (stackId == DOCKED_STACK_ID && r.canGoInDockedStack()) {
+            return true;
         }
 
         if (stackId == FREEFORM_WORKSPACE_STACK_ID && !mService.mSupportsFreeformWindowManagement) {
diff --git a/services/core/java/com/android/server/am/AppErrorDialog.java b/services/core/java/com/android/server/am/AppErrorDialog.java
index 86cdbcc..ddfab4d 100644
--- a/services/core/java/com/android/server/am/AppErrorDialog.java
+++ b/services/core/java/com/android/server/am/AppErrorDialog.java
@@ -25,6 +25,7 @@
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.Message;
+import android.text.BidiFormatter;
 import android.util.Slog;
 import android.view.LayoutInflater;
 import android.view.View;
@@ -68,18 +69,21 @@
         mProc = data.proc;
         mResult = data.result;
         mRepeating = data.repeating;
+        BidiFormatter bidi = BidiFormatter.getInstance();
+
         if ((mProc.pkgList.size() == 1) &&
                 (mName = context.getPackageManager().getApplicationLabel(mProc.info)) != null) {
             setTitle(res.getString(
                     mRepeating ? com.android.internal.R.string.aerr_application_repeated
                             : com.android.internal.R.string.aerr_application,
-                    mName.toString(), mProc.info.processName));
+                    bidi.unicodeWrap(mName.toString()),
+                    bidi.unicodeWrap(mProc.info.processName)));
         } else {
             mName = mProc.processName;
             setTitle(res.getString(
                     mRepeating ? com.android.internal.R.string.aerr_process_repeated
                             : com.android.internal.R.string.aerr_process,
-                    mName.toString()));
+                    bidi.unicodeWrap(mName.toString())));
         }
 
         setCancelable(false);
diff --git a/services/core/java/com/android/server/am/AppErrors.java b/services/core/java/com/android/server/am/AppErrors.java
index 055935d..6cd7561 100644
--- a/services/core/java/com/android/server/am/AppErrors.java
+++ b/services/core/java/com/android/server/am/AppErrors.java
@@ -61,6 +61,7 @@
 import java.util.concurrent.Semaphore;
 
 import static com.android.server.Watchdog.NATIVE_STACKS_OF_INTEREST;
+import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_ANR;
 import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
 import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
 import static com.android.server.am.ActivityManagerService.MY_PID;
@@ -806,8 +807,10 @@
                     if (pid > 0 && pid != app.pid && pid != parentPid && pid != MY_PID) {
                         if (r.persistent) {
                             firstPids.add(pid);
+                            if (DEBUG_ANR) Slog.i(TAG, "Adding persistent proc: " + r);
                         } else {
                             lastPids.put(pid, Boolean.TRUE);
+                            if (DEBUG_ANR) Slog.i(TAG, "Adding ANR proc: " + r);
                         }
                     }
                 }
diff --git a/services/core/java/com/android/server/am/AppNotRespondingDialog.java b/services/core/java/com/android/server/am/AppNotRespondingDialog.java
index 6d1d9f3..c6befd7 100644
--- a/services/core/java/com/android/server/am/AppNotRespondingDialog.java
+++ b/services/core/java/com/android/server/am/AppNotRespondingDialog.java
@@ -27,6 +27,7 @@
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.Message;
+import android.text.BidiFormatter;
 import android.util.Slog;
 import android.view.LayoutInflater;
 import android.view.View;
@@ -84,9 +85,11 @@
             }
         }
 
+        BidiFormatter bidi = BidiFormatter.getInstance();
+
         setTitle(name2 != null
-                ? res.getString(resid, name1.toString(), name2.toString())
-                : res.getString(resid, name1.toString()));
+                ? res.getString(resid, bidi.unicodeWrap(name1.toString()), bidi.unicodeWrap(name2.toString()))
+                : res.getString(resid, bidi.unicodeWrap(name1.toString())));
 
         if (aboveSystem) {
             getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ERROR);
diff --git a/services/core/java/com/android/server/am/BatteryStatsService.java b/services/core/java/com/android/server/am/BatteryStatsService.java
index 28882de..71a1f97 100644
--- a/services/core/java/com/android/server/am/BatteryStatsService.java
+++ b/services/core/java/com/android/server/am/BatteryStatsService.java
@@ -32,6 +32,7 @@
 import android.os.Parcel;
 import android.os.ParcelFileDescriptor;
 import android.os.ParcelFormatException;
+import android.os.PowerManager;
 import android.os.PowerManagerInternal;
 import android.os.Process;
 import android.os.RemoteException;
@@ -39,6 +40,9 @@
 import android.os.SystemClock;
 import android.os.UserHandle;
 import android.os.WorkSource;
+import android.os.health.HealthStatsParceler;
+import android.os.health.HealthStatsWriter;
+import android.os.health.UidHealthStats;
 import android.telephony.DataConnectionRealTimeInfo;
 import android.telephony.ModemActivityInfo;
 import android.telephony.SignalStrength;
@@ -65,7 +69,9 @@
 import java.nio.charset.CharsetDecoder;
 import java.nio.charset.CodingErrorAction;
 import java.nio.charset.StandardCharsets;
+import java.util.Arrays;
 import java.util.List;
+import java.util.Map;
 
 /**
  * All information we are collecting about things that can happen that impact
@@ -1419,4 +1425,88 @@
             }
         }
     }
+
+    /**
+     * Gets a snapshot of the system health for a particular uid.
+     */
+    @Override
+    public HealthStatsParceler takeUidSnapshot(int requestUid) {
+        if (requestUid != Binder.getCallingUid()) {
+            mContext.enforceCallingOrSelfPermission(
+                    android.Manifest.permission.BATTERY_STATS, null);
+        }
+        long ident = Binder.clearCallingIdentity();
+        try {
+            updateExternalStats("get-health-stats-for-uid",
+                    BatteryStatsImpl.ExternalStatsSync.UPDATE_ALL);
+            synchronized (mStats) {
+                return getHealthStatsForUidLocked(requestUid);
+            }
+        } catch (Exception ex) {
+            Slog.d(TAG, "Crashed while writing for takeUidSnapshot(" + requestUid + ")", ex);
+            throw ex;
+        } finally {
+            Binder.restoreCallingIdentity(ident);
+        }
+    }
+
+    /**
+     * Gets a snapshot of the system health for a number of uids.
+     */
+    @Override
+    public HealthStatsParceler[] takeUidSnapshots(int[] requestUids) {
+        if (!onlyCaller(requestUids)) {
+            mContext.enforceCallingOrSelfPermission(
+                    android.Manifest.permission.BATTERY_STATS, null);
+        }
+        long ident = Binder.clearCallingIdentity();
+        int i=-1;
+        try {
+            updateExternalStats("get-health-stats-for-uids",
+                    BatteryStatsImpl.ExternalStatsSync.UPDATE_ALL);
+            synchronized (mStats) {
+                final int N = requestUids.length;
+                final HealthStatsParceler[] results = new HealthStatsParceler[N];
+                for (i=0; i<N; i++) {
+                    results[i] = getHealthStatsForUidLocked(requestUids[i]);
+                }
+                return results;
+            }
+        } catch (Exception ex) {
+            Slog.d(TAG, "Crashed while writing for takeUidSnapshots("
+                    + Arrays.toString(requestUids) + ") i=" + i, ex);
+            throw ex;
+        } finally {
+            Binder.restoreCallingIdentity(ident);
+        }
+    }
+
+    /**
+     * Returns whether the Binder.getCallingUid is the only thing in requestUids.
+     */
+    private static boolean onlyCaller(int[] requestUids) {
+        final int caller = Binder.getCallingUid();
+        final int N = requestUids.length;
+        for (int i=0; i<N; i++) {
+            if (requestUids[i] != caller) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    /**
+     * Gets a HealthStatsParceler for the given uid. You should probably call
+     * updateExternalStats first.
+     */
+    HealthStatsParceler getHealthStatsForUidLocked(int requestUid) {
+        final HealthStatsBatteryStatsWriter writer = new HealthStatsBatteryStatsWriter();
+        final HealthStatsWriter uidWriter = new HealthStatsWriter(UidHealthStats.CONSTANTS);
+        final BatteryStats.Uid uid = mStats.getUidStats().get(requestUid);
+        if (uid != null) {
+            writer.writeUid(uidWriter, mStats, uid);
+        }
+        return new HealthStatsParceler(uidWriter);
+    }
+
 }
diff --git a/services/core/java/com/android/server/am/BroadcastQueue.java b/services/core/java/com/android/server/am/BroadcastQueue.java
index 37b0af1..45e3a76 100644
--- a/services/core/java/com/android/server/am/BroadcastQueue.java
+++ b/services/core/java/com/android/server/am/BroadcastQueue.java
@@ -654,7 +654,7 @@
         }
 
         final boolean callerForeground = receiverRecord.callerApp != null
-                ? receiverRecord.callerApp.setSchedGroup != Process.THREAD_GROUP_BG_NONINTERACTIVE
+                ? receiverRecord.callerApp.setSchedGroup != ProcessList.SCHED_GROUP_BACKGROUND
                 : true;
 
         // Show a permission review UI only for explicit broadcast from a foreground app
diff --git a/services/core/java/com/android/server/am/EventLogTags.logtags b/services/core/java/com/android/server/am/EventLogTags.logtags
index f2e8d09..2329b2f 100644
--- a/services/core/java/com/android/server/am/EventLogTags.logtags
+++ b/services/core/java/com/android/server/am/EventLogTags.logtags
@@ -54,9 +54,9 @@
 # An activity has been relaunched:
 30020 am_relaunch_activity (User|1|5),(Token|1|5),(Task ID|1|5),(Component Name|3)
 # The activity's onPause has been called.
-30021 am_on_paused_called (User|1|5),(Component Name|3)
+30021 am_on_paused_called (User|1|5),(Component Name|3),(Reason|3)
 # The activity's onResume has been called.
-30022 am_on_resume_called (User|1|5),(Component Name|3)
+30022 am_on_resume_called (User|1|5),(Component Name|3),(Reason|3)
 # Kill a process to reclaim memory.
 30023 am_kill (User|1|5),(PID|1|5),(Process Name|3),(OomAdj|1|5),(Reason|3)
 # Discard an undelivered serialized broadcast (timeout/ANR/crash)
@@ -103,3 +103,8 @@
 30046 am_meminfo (Cached|2|2),(Free|2|2),(Zram|2|2),(Kernel|2|2),(Native|2|2)
 # Report collection of memory used by a process
 30047 am_pss (Pid|1|5),(UID|1|5),(Process Name|3),(Pss|2|2),(Uss|2|2),(SwapPss|2|2)
+
+# Attempting to stop an activity
+30048 am_stop_activity (User|1|5),(Token|1|5),(Component Name|3)
+# The activity's onStop has been called.
+30049 am_on_stop_called (User|1|5),(Component Name|3),(Reason|3)
diff --git a/services/core/java/com/android/server/am/HealthStatsBatteryStatsWriter.java b/services/core/java/com/android/server/am/HealthStatsBatteryStatsWriter.java
new file mode 100644
index 0000000..39c6ce6
--- /dev/null
+++ b/services/core/java/com/android/server/am/HealthStatsBatteryStatsWriter.java
@@ -0,0 +1,473 @@
+/*
+ * 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.am;
+
+import android.os.BatteryStats;
+import static android.os.BatteryStats.STATS_SINCE_UNPLUGGED;
+import android.os.PowerManager;
+import android.os.SystemClock;
+import android.os.health.HealthKeys;
+import android.os.health.HealthStatsParceler;
+import android.os.health.HealthStatsWriter;
+import android.os.health.PackageHealthStats;
+import android.os.health.ProcessHealthStats;
+import android.os.health.PidHealthStats;
+import android.os.health.ServiceHealthStats;
+import android.os.health.TimerStat;
+import android.os.health.UidHealthStats;
+import android.util.SparseArray;
+
+import java.util.Map;
+
+public class HealthStatsBatteryStatsWriter {
+
+    private final long mNowRealtime;
+    private final long mNowUptime;
+
+    public HealthStatsBatteryStatsWriter() {
+        mNowRealtime = SystemClock.elapsedRealtime();
+        mNowUptime = SystemClock.uptimeMillis();
+    }
+
+    /**
+     * Writes the contents of a BatteryStats.Uid into a HealthStatsWriter.
+     */
+    public void writeUid(HealthStatsWriter uidWriter, BatteryStats bs, BatteryStats.Uid uid) {
+        int N;
+        BatteryStats.Timer timer;
+        SparseArray<? extends BatteryStats.Uid.Sensor> sensors;
+        SparseArray<? extends BatteryStats.Uid.Pid> pids;
+        BatteryStats.ControllerActivityCounter controller;
+        long sum;
+
+        //
+        // It's a little odd for these first four to be here but it's not the end of the
+        // world. It would be easy enough to duplicate them somewhere else if this API
+        // grows.
+        //
+
+        // MEASUREMENT_REALTIME_BATTERY_MS
+        uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_REALTIME_BATTERY_MS,
+                bs.computeBatteryRealtime(mNowRealtime*1000, STATS_SINCE_UNPLUGGED)/1000);
+
+        // MEASUREMENT_UPTIME_BATTERY_MS
+        uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_UPTIME_BATTERY_MS,
+                bs.computeBatteryUptime(mNowUptime*1000, STATS_SINCE_UNPLUGGED)/1000);
+
+        // MEASUREMENT_REALTIME_SCREEN_OFF_BATTERY_MS
+        uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_REALTIME_SCREEN_OFF_BATTERY_MS,
+                bs.computeBatteryScreenOffRealtime(mNowRealtime*1000, STATS_SINCE_UNPLUGGED)/1000);
+
+        // MEASUREMENT_UPTIME_SCREEN_OFF_BATTERY_MS
+        uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_UPTIME_SCREEN_OFF_BATTERY_MS,
+                bs.computeBatteryScreenOffUptime(mNowUptime*1000, STATS_SINCE_UNPLUGGED)/1000);
+
+        //
+        // Now on to the real per-uid stats...
+        //
+
+        for (final Map.Entry<String,? extends BatteryStats.Uid.Wakelock> entry:
+                uid.getWakelockStats().entrySet()) {
+            final String key = entry.getKey();
+            final BatteryStats.Uid.Wakelock wakelock = entry.getValue();
+
+            // TIMERS_WAKELOCKS_FULL
+            timer = wakelock.getWakeTime(BatteryStats.WAKE_TYPE_FULL);
+            addTimers(uidWriter, UidHealthStats.TIMERS_WAKELOCKS_FULL, key, timer);
+
+            // TIMERS_WAKELOCKS_PARTIAL
+            timer = wakelock.getWakeTime(BatteryStats.WAKE_TYPE_PARTIAL);
+            addTimers(uidWriter, UidHealthStats.TIMERS_WAKELOCKS_PARTIAL, key, timer);
+            
+            // TIMERS_WAKELOCKS_WINDOW
+            timer = wakelock.getWakeTime(BatteryStats.WAKE_TYPE_WINDOW);
+            addTimers(uidWriter, UidHealthStats.TIMERS_WAKELOCKS_WINDOW, key, timer);
+            
+            // TIMERS_WAKELOCKS_DRAW
+            timer = wakelock.getWakeTime(BatteryStats.WAKE_TYPE_DRAW);
+            addTimers(uidWriter, UidHealthStats.TIMERS_WAKELOCKS_DRAW, key, timer);
+        }
+        
+        // TIMERS_SYNCS
+        for (final Map.Entry<String,? extends BatteryStats.Timer> entry:
+                uid.getSyncStats().entrySet()) {
+            addTimers(uidWriter, UidHealthStats.TIMERS_SYNCS, entry.getKey(), entry.getValue());
+        }
+
+        // TIMERS_JOBS
+        for (final Map.Entry<String,? extends BatteryStats.Timer> entry:
+                uid.getJobStats().entrySet()) {
+            addTimers(uidWriter, UidHealthStats.TIMERS_JOBS, entry.getKey(), entry.getValue());
+        }
+
+        // TIMERS_SENSORS
+        sensors = uid.getSensorStats();
+        N = sensors.size();
+        for (int i=0; i<N; i++) {
+            int sensorId = sensors.keyAt(i);
+            // Battery Stats stores the GPS sensors with a bogus key in this API. Pull it out
+            // as a separate metric here so as to not expose that in the API.
+            if (sensorId == BatteryStats.Uid.Sensor.GPS) {
+                addTimer(uidWriter, UidHealthStats.TIMER_GPS_SENSOR, sensors.valueAt(i).getSensorTime());
+            } else {
+                addTimers(uidWriter, UidHealthStats.TIMERS_SENSORS, Integer.toString(sensorId),
+                        sensors.valueAt(i).getSensorTime());
+            }
+        }
+
+        // STATS_PIDS
+        pids = uid.getPidStats();
+        N = sensors.size();
+        for (int i=0; i<N; i++) {
+            final HealthStatsWriter writer = new HealthStatsWriter(PidHealthStats.CONSTANTS);
+            writePid(writer, pids.valueAt(i));
+            uidWriter.addStats(UidHealthStats.STATS_PIDS, Integer.toString(pids.keyAt(i)), writer);
+        }
+
+        // STATS_PROCESSES
+        for (final Map.Entry<String,? extends BatteryStats.Uid.Proc> entry:
+                uid.getProcessStats().entrySet()) {
+            final HealthStatsWriter writer = new HealthStatsWriter(ProcessHealthStats.CONSTANTS);
+            writeProc(writer, entry.getValue());
+            uidWriter.addStats(UidHealthStats.STATS_PROCESSES, entry.getKey(), writer);
+        }
+
+        // STATS_PACKAGES
+        for (final Map.Entry<String,? extends BatteryStats.Uid.Pkg> entry:
+                uid.getPackageStats().entrySet()) {
+            final HealthStatsWriter writer = new HealthStatsWriter(PackageHealthStats.CONSTANTS);
+            writePkg(writer, entry.getValue());
+            uidWriter.addStats(UidHealthStats.STATS_PACKAGES, entry.getKey(), writer);
+        }
+
+        controller = uid.getWifiControllerActivity();
+        if (controller != null) {
+            // MEASUREMENT_WIFI_IDLE_MS
+            uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_WIFI_IDLE_MS,
+                    controller.getIdleTimeCounter().getCountLocked(STATS_SINCE_UNPLUGGED));
+            // MEASUREMENT_WIFI_RX_MS
+            uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_WIFI_RX_MS,
+                    controller.getRxTimeCounter().getCountLocked(STATS_SINCE_UNPLUGGED));
+            // MEASUREMENT_WIFI_TX_MS
+            sum = 0;
+            for (final BatteryStats.LongCounter counter: controller.getTxTimeCounters()) {
+                sum += counter.getCountLocked(STATS_SINCE_UNPLUGGED);
+            }
+            uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_WIFI_TX_MS, sum);
+            // MEASUREMENT_WIFI_POWER_MAMS
+            uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_WIFI_POWER_MAMS,
+                    controller.getPowerCounter().getCountLocked(STATS_SINCE_UNPLUGGED));
+        }
+
+        controller = uid.getBluetoothControllerActivity();
+        if (controller != null) {
+            // MEASUREMENT_BLUETOOTH_IDLE_MS
+            uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_BLUETOOTH_IDLE_MS,
+                    controller.getIdleTimeCounter().getCountLocked(STATS_SINCE_UNPLUGGED));
+            // MEASUREMENT_BLUETOOTH_RX_MS
+            uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_BLUETOOTH_RX_MS,
+                    controller.getRxTimeCounter().getCountLocked(STATS_SINCE_UNPLUGGED));
+            // MEASUREMENT_BLUETOOTH_TX_MS
+            sum = 0;
+            for (final BatteryStats.LongCounter counter: controller.getTxTimeCounters()) {
+                sum += counter.getCountLocked(STATS_SINCE_UNPLUGGED);
+            }
+            uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_BLUETOOTH_TX_MS, sum);
+            // MEASUREMENT_BLUETOOTH_POWER_MAMS
+            uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_BLUETOOTH_POWER_MAMS,
+                    controller.getPowerCounter().getCountLocked(STATS_SINCE_UNPLUGGED));
+        }
+
+        controller = uid.getModemControllerActivity();
+        if (controller != null) {
+            // MEASUREMENT_MOBILE_IDLE_MS
+            uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_MOBILE_IDLE_MS,
+                    controller.getIdleTimeCounter().getCountLocked(STATS_SINCE_UNPLUGGED));
+            // MEASUREMENT_MOBILE_RX_MS
+            uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_MOBILE_RX_MS,
+                    controller.getRxTimeCounter().getCountLocked(STATS_SINCE_UNPLUGGED));
+            // MEASUREMENT_MOBILE_TX_MS
+            sum = 0;
+            for (final BatteryStats.LongCounter counter: controller.getTxTimeCounters()) {
+                sum += counter.getCountLocked(STATS_SINCE_UNPLUGGED);
+            }
+            uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_MOBILE_TX_MS, sum);
+            // MEASUREMENT_MOBILE_POWER_MAMS
+            uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_MOBILE_POWER_MAMS,
+                    controller.getPowerCounter().getCountLocked(STATS_SINCE_UNPLUGGED));
+        }
+
+        // MEASUREMENT_WIFI_RUNNING_MS
+        uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_WIFI_RUNNING_MS,
+                uid.getWifiRunningTime(mNowRealtime, STATS_SINCE_UNPLUGGED));
+
+        // MEASUREMENT_WIFI_FULL_LOCK_MS
+        uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_WIFI_FULL_LOCK_MS,
+                uid.getFullWifiLockTime(mNowRealtime, STATS_SINCE_UNPLUGGED));
+
+        // TIMER_WIFI_SCAN
+        uidWriter.addTimer(UidHealthStats.TIMER_WIFI_SCAN,
+                uid.getWifiScanCount(STATS_SINCE_UNPLUGGED),
+                uid.getWifiScanTime(mNowRealtime, STATS_SINCE_UNPLUGGED));
+
+        // MEASUREMENT_WIFI_MULTICAST_MS
+        uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_WIFI_MULTICAST_MS,
+                uid.getWifiMulticastTime(mNowRealtime, STATS_SINCE_UNPLUGGED));
+
+        // TIMER_AUDIO
+        addTimer(uidWriter, UidHealthStats.TIMER_AUDIO, uid.getAudioTurnedOnTimer());
+
+        // TIMER_VIDEO
+        addTimer(uidWriter, UidHealthStats.TIMER_VIDEO, uid.getVideoTurnedOnTimer());
+
+        // TIMER_FLASHLIGHT
+        addTimer(uidWriter, UidHealthStats.TIMER_FLASHLIGHT, uid.getFlashlightTurnedOnTimer());
+
+        // TIMER_CAMERA
+        addTimer(uidWriter, UidHealthStats.TIMER_CAMERA, uid.getCameraTurnedOnTimer());
+
+        // TIMER_FOREGROUND_ACTIVITY
+        addTimer(uidWriter, UidHealthStats.TIMER_FOREGROUND_ACTIVITY, uid.getForegroundActivityTimer());
+
+        // TIMER_BLUETOOTH_SCAN
+        addTimer(uidWriter, UidHealthStats.TIMER_BLUETOOTH_SCAN, uid.getBluetoothScanTimer());
+
+        // TIMER_PROCESS_STATE_TOP_MS
+        addTimer(uidWriter, UidHealthStats.TIMER_PROCESS_STATE_TOP_MS,
+                uid.getProcessStateTimer(BatteryStats.Uid.PROCESS_STATE_TOP));
+
+        // TIMER_PROCESS_STATE_FOREGROUND_SERVICE_MS
+        addTimer(uidWriter, UidHealthStats.TIMER_PROCESS_STATE_FOREGROUND_SERVICE_MS,
+                uid.getProcessStateTimer(BatteryStats.Uid.PROCESS_STATE_FOREGROUND_SERVICE));
+
+        // TIMER_PROCESS_STATE_TOP_SLEEPING_MS
+        addTimer(uidWriter, UidHealthStats.TIMER_PROCESS_STATE_TOP_SLEEPING_MS,
+                uid.getProcessStateTimer(BatteryStats.Uid.PROCESS_STATE_TOP_SLEEPING));
+
+        // TIMER_PROCESS_STATE_FOREGROUND_MS
+        addTimer(uidWriter, UidHealthStats.TIMER_PROCESS_STATE_FOREGROUND_MS,
+                uid.getProcessStateTimer(BatteryStats.Uid.PROCESS_STATE_FOREGROUND));
+
+        // TIMER_PROCESS_STATE_BACKGROUND_MS
+        addTimer(uidWriter, UidHealthStats.TIMER_PROCESS_STATE_BACKGROUND_MS,
+                uid.getProcessStateTimer(BatteryStats.Uid.PROCESS_STATE_BACKGROUND));
+
+        // TIMER_PROCESS_STATE_CACHED_MS
+        addTimer(uidWriter, UidHealthStats.TIMER_PROCESS_STATE_CACHED_MS,
+                uid.getProcessStateTimer(BatteryStats.Uid.PROCESS_STATE_CACHED));
+
+        // TIMER_VIBRATOR
+        addTimer(uidWriter, UidHealthStats.TIMER_VIBRATOR, uid.getVibratorOnTimer());
+
+        // MEASUREMENT_OTHER_USER_ACTIVITY_COUNT
+        uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_OTHER_USER_ACTIVITY_COUNT,
+                uid.getUserActivityCount(PowerManager.USER_ACTIVITY_EVENT_OTHER,
+                    STATS_SINCE_UNPLUGGED));
+
+        // MEASUREMENT_BUTTON_USER_ACTIVITY_COUNT
+        uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_BUTTON_USER_ACTIVITY_COUNT,
+                uid.getUserActivityCount(PowerManager.USER_ACTIVITY_EVENT_BUTTON,
+                    STATS_SINCE_UNPLUGGED));
+
+        // MEASUREMENT_TOUCH_USER_ACTIVITY_COUNT
+        uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_TOUCH_USER_ACTIVITY_COUNT,
+                uid.getUserActivityCount(PowerManager.USER_ACTIVITY_EVENT_TOUCH,
+                    STATS_SINCE_UNPLUGGED));
+
+        // MEASUREMENT_MOBILE_RX_BYTES
+        uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_MOBILE_RX_BYTES,
+                uid.getNetworkActivityBytes(BatteryStats.NETWORK_MOBILE_RX_DATA,
+                    STATS_SINCE_UNPLUGGED));
+
+        // MEASUREMENT_MOBILE_TX_BYTES
+        uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_MOBILE_TX_BYTES,
+                uid.getNetworkActivityBytes(BatteryStats.NETWORK_MOBILE_TX_DATA,
+                    STATS_SINCE_UNPLUGGED));
+
+        // MEASUREMENT_WIFI_RX_BYTES
+        uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_WIFI_RX_BYTES,
+                uid.getNetworkActivityBytes(BatteryStats.NETWORK_WIFI_RX_DATA,
+                    STATS_SINCE_UNPLUGGED));
+
+        // MEASUREMENT_WIFI_TX_BYTES
+        uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_WIFI_TX_BYTES,
+                uid.getNetworkActivityBytes(BatteryStats.NETWORK_WIFI_TX_DATA,
+                    STATS_SINCE_UNPLUGGED));
+
+        // MEASUREMENT_BLUETOOTH_RX_BYTES
+        uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_BLUETOOTH_RX_BYTES,
+                uid.getNetworkActivityBytes(BatteryStats.NETWORK_BT_RX_DATA,
+                    STATS_SINCE_UNPLUGGED));
+
+        // MEASUREMENT_BLUETOOTH_TX_BYTES
+        uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_BLUETOOTH_TX_BYTES,
+                uid.getNetworkActivityBytes(BatteryStats.NETWORK_BT_TX_DATA,
+                    STATS_SINCE_UNPLUGGED));
+
+        // MEASUREMENT_MOBILE_RX_PACKETS
+        uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_MOBILE_RX_PACKETS,
+                uid.getNetworkActivityPackets(BatteryStats.NETWORK_MOBILE_RX_DATA,
+                    STATS_SINCE_UNPLUGGED));
+
+        // MEASUREMENT_MOBILE_TX_PACKETS
+        uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_MOBILE_TX_PACKETS,
+                uid.getNetworkActivityPackets(BatteryStats.NETWORK_MOBILE_TX_DATA,
+                    STATS_SINCE_UNPLUGGED));
+
+        // MEASUREMENT_WIFI_RX_PACKETS
+        uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_WIFI_RX_PACKETS,
+                uid.getNetworkActivityPackets(BatteryStats.NETWORK_WIFI_RX_DATA,
+                    STATS_SINCE_UNPLUGGED));
+
+        // MEASUREMENT_WIFI_TX_PACKETS
+        uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_WIFI_TX_PACKETS,
+                uid.getNetworkActivityPackets(BatteryStats.NETWORK_WIFI_TX_DATA,
+                    STATS_SINCE_UNPLUGGED));
+
+        // MEASUREMENT_BLUETOOTH_RX_PACKETS
+        uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_BLUETOOTH_RX_PACKETS,
+                uid.getNetworkActivityPackets(BatteryStats.NETWORK_BT_RX_DATA,
+                    STATS_SINCE_UNPLUGGED));
+
+        // MEASUREMENT_BLUETOOTH_TX_PACKETS
+        uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_BLUETOOTH_TX_PACKETS,
+                uid.getNetworkActivityPackets(BatteryStats.NETWORK_BT_TX_DATA,
+                    STATS_SINCE_UNPLUGGED));
+
+        // TIMER_MOBILE_RADIO_ACTIVE
+        uidWriter.addTimer(UidHealthStats.TIMER_MOBILE_RADIO_ACTIVE,
+                uid.getMobileRadioActiveCount(STATS_SINCE_UNPLUGGED),
+                uid.getMobileRadioActiveTime(STATS_SINCE_UNPLUGGED));
+
+        // MEASUREMENT_USER_CPU_TIME_US
+        uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_USER_CPU_TIME_US,
+                uid.getUserCpuTimeUs(STATS_SINCE_UNPLUGGED));
+
+        // MEASUREMENT_SYSTEM_CPU_TIME_US
+        uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_SYSTEM_CPU_TIME_US,
+                uid.getSystemCpuTimeUs(STATS_SINCE_UNPLUGGED));
+
+        // MEASUREMENT_CPU_POWER_MAUS
+        uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_CPU_POWER_MAUS,
+                uid.getCpuPowerMaUs(STATS_SINCE_UNPLUGGED));
+    }
+
+    /**
+     * Writes the contents of a BatteryStats.Uid.Pid into a HealthStatsWriter.
+     */
+    public void writePid(HealthStatsWriter pidWriter, BatteryStats.Uid.Pid pid) {
+        if (pid == null) {
+            return;
+        }
+
+        // MEASUREMENT_WAKE_NESTING_COUNT
+        pidWriter.addMeasurement(PidHealthStats.MEASUREMENT_WAKE_NESTING_COUNT, pid.mWakeNesting);
+
+        // MEASUREMENT_WAKE_SUM_MS
+        pidWriter.addMeasurement(PidHealthStats.MEASUREMENT_WAKE_SUM_MS, pid.mWakeSumMs);
+
+        // MEASUREMENT_WAKE_START_MS
+        pidWriter.addMeasurement(PidHealthStats.MEASUREMENT_WAKE_SUM_MS, pid.mWakeStartMs);
+    }
+
+    /**
+     * Writes the contents of a BatteryStats.Uid.Proc into a HealthStatsWriter.
+     */
+    public void writeProc(HealthStatsWriter procWriter, BatteryStats.Uid.Proc proc) {
+        // MEASUREMENT_USER_TIME_MS
+        procWriter.addMeasurement(ProcessHealthStats.MEASUREMENT_USER_TIME_MS,
+                proc.getUserTime(STATS_SINCE_UNPLUGGED));
+
+        // MEASUREMENT_SYSTEM_TIME_MS
+        procWriter.addMeasurement(ProcessHealthStats.MEASUREMENT_SYSTEM_TIME_MS,
+                proc.getSystemTime(STATS_SINCE_UNPLUGGED));
+
+        // MEASUREMENT_STARTS_COUNT
+        procWriter.addMeasurement(ProcessHealthStats.MEASUREMENT_STARTS_COUNT,
+                proc.getStarts(STATS_SINCE_UNPLUGGED));
+
+        // MEASUREMENT_CRASHES_COUNT
+        procWriter.addMeasurement(ProcessHealthStats.MEASUREMENT_CRASHES_COUNT,
+                proc.getNumCrashes(STATS_SINCE_UNPLUGGED));
+
+        // MEASUREMENT_ANR_COUNT
+        procWriter.addMeasurement(ProcessHealthStats.MEASUREMENT_ANR_COUNT,
+                proc.getNumAnrs(STATS_SINCE_UNPLUGGED));
+
+        // MEASUREMENT_FOREGROUND_MS
+        procWriter.addMeasurement(ProcessHealthStats.MEASUREMENT_FOREGROUND_MS,
+                proc.getForegroundTime(STATS_SINCE_UNPLUGGED));
+    }
+
+    /**
+     * Writes the contents of a BatteryStats.Uid.Pkg into a HealthStatsWriter.
+     */
+    public void writePkg(HealthStatsWriter pkgWriter, BatteryStats.Uid.Pkg pkg) {
+        // STATS_SERVICES
+        for (final Map.Entry<String,? extends BatteryStats.Uid.Pkg.Serv> entry:
+                pkg.getServiceStats().entrySet()) {
+            final HealthStatsWriter writer = new HealthStatsWriter(ServiceHealthStats.CONSTANTS);
+            writeServ(writer, entry.getValue());
+            pkgWriter.addStats(PackageHealthStats.STATS_SERVICES, entry.getKey(), writer);
+        }
+
+        // MEASUREMENTS_WAKEUP_ALARMS_COUNT
+        for (final Map.Entry<String,? extends BatteryStats.Counter> entry:
+                pkg.getWakeupAlarmStats().entrySet()) {
+            final BatteryStats.Counter counter = entry.getValue();
+            if (counter != null) {
+                pkgWriter.addMeasurements(PackageHealthStats.MEASUREMENTS_WAKEUP_ALARMS_COUNT,
+                        entry.getKey(), counter.getCountLocked(STATS_SINCE_UNPLUGGED));
+            }
+        }
+    }
+
+    /**
+     * Writes the contents of a BatteryStats.Uid.Pkg.Serv into a HealthStatsWriter.
+     */
+    public void writeServ(HealthStatsWriter servWriter, BatteryStats.Uid.Pkg.Serv serv) {
+        // MEASUREMENT_START_SERVICE_COUNT
+        servWriter.addMeasurement(ServiceHealthStats.MEASUREMENT_START_SERVICE_COUNT,
+                serv.getStarts(STATS_SINCE_UNPLUGGED));
+
+        // MEASUREMENT_LAUNCH_COUNT
+        servWriter.addMeasurement(ServiceHealthStats.MEASUREMENT_LAUNCH_COUNT,
+                serv.getLaunches(STATS_SINCE_UNPLUGGED));
+    }
+
+    /**
+     * Adds a BatteryStats.Timer into a HealthStatsWriter. Safe to pass a null timer.
+     */
+    private void addTimer(HealthStatsWriter writer, int key, BatteryStats.Timer timer) {
+        if (timer != null) {
+            writer.addTimer(key, timer.getCountLocked(STATS_SINCE_UNPLUGGED),
+                    timer.getTotalTimeLocked(mNowRealtime, STATS_SINCE_UNPLUGGED));
+        }
+    }
+
+    /**
+     * Adds a named BatteryStats.Timer into a HealthStatsWriter. Safe to pass a null timer.
+     */
+    private void addTimers(HealthStatsWriter writer, int key, String name,
+            BatteryStats.Timer timer) {
+        if (timer != null) {
+            writer.addTimers(key, name, new TimerStat(timer.getCountLocked(STATS_SINCE_UNPLUGGED),
+                    timer.getTotalTimeLocked(mNowRealtime, STATS_SINCE_UNPLUGGED)));
+        }
+    }
+}
+
diff --git a/services/core/java/com/android/server/am/InstrumentationReporter.java b/services/core/java/com/android/server/am/InstrumentationReporter.java
new file mode 100644
index 0000000..fdbb73e
--- /dev/null
+++ b/services/core/java/com/android/server/am/InstrumentationReporter.java
@@ -0,0 +1,144 @@
+/*
+ * 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.am;
+
+import android.app.IInstrumentationWatcher;
+import android.content.ComponentName;
+import android.os.Bundle;
+import android.os.Process;
+import android.os.RemoteException;
+import android.util.Slog;
+
+import java.util.ArrayList;
+
+public class InstrumentationReporter {
+    static final boolean DEBUG = false;
+    static final String TAG = ActivityManagerDebugConfig.TAG_AM;
+
+    static final int REPORT_TYPE_STATUS = 0;
+    static final int REPORT_TYPE_FINISHED = 1;
+
+    final Object mLock = new Object();
+    ArrayList<Report> mPendingReports;
+    Thread mThread;
+
+    final class MyThread extends Thread {
+        public MyThread() {
+            super("InstrumentationReporter");
+            if (DEBUG) Slog.d(TAG, "Starting InstrumentationReporter: " + this);
+        }
+
+        @Override
+        public void run() {
+            Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT);
+            boolean waited = false;
+            while (true) {
+                ArrayList<Report> reports;
+                synchronized (mLock) {
+                    reports = mPendingReports;
+                    mPendingReports = null;
+                    if (reports == null || reports.isEmpty()) {
+                        if (!waited) {
+                            // Sleep for a little bit, to avoid thrashing through threads.
+                            try {
+                                mLock.wait(10000); // 10 seconds
+                            } catch (InterruptedException e) {
+                            }
+                            waited = true;
+                            continue;
+                        } else {
+                            mThread = null;
+                            if (DEBUG) Slog.d(TAG, "Exiting InstrumentationReporter: " + this);
+                            return;
+                        }
+                    }
+                }
+
+                waited = false;
+
+                for (int i=0; i<reports.size(); i++) {
+                    final Report rep = reports.get(i);
+                    try {
+                        if (rep.mType == REPORT_TYPE_STATUS) {
+                            if (DEBUG) Slog.d(TAG, "Dispatch status to " + rep.mWatcher
+                                    + ": " + rep.mName.flattenToShortString()
+                                    + " code=" + rep.mResultCode + " result=" + rep.mResults);
+                            rep.mWatcher.instrumentationStatus(rep.mName, rep.mResultCode,
+                                    rep.mResults);
+                        } else {
+                            if (DEBUG) Slog.d(TAG, "Dispatch finished to " + rep.mWatcher
+                                    + ": " + rep.mName.flattenToShortString()
+                                    + " code=" + rep.mResultCode + " result=" + rep.mResults);
+                            rep.mWatcher.instrumentationFinished(rep.mName, rep.mResultCode,
+                                    rep.mResults);
+                        }
+                    } catch (RemoteException e) {
+                        Slog.i(TAG, "Failure reporting to instrumentation watcher: comp="
+                                + rep.mName + " results=" + rep.mResults);
+                    }
+                }
+            }
+        }
+    }
+
+    final class Report {
+        final int mType;
+        final IInstrumentationWatcher mWatcher;
+        final ComponentName mName;
+        final int mResultCode;
+        final Bundle mResults;
+
+        Report(int type, IInstrumentationWatcher watcher, ComponentName name, int resultCode,
+                Bundle results) {
+            mType = type;
+            mWatcher = watcher;
+            mName = name;
+            mResultCode = resultCode;
+            mResults = results;
+        }
+    }
+
+    public void reportStatus(IInstrumentationWatcher watcher, ComponentName name, int resultCode,
+            Bundle results) {
+        if (DEBUG) Slog.d(TAG, "Report status to " + watcher
+                + ": " + name.flattenToShortString()
+                + " code=" + resultCode + " result=" + results);
+        report(new Report(REPORT_TYPE_STATUS, watcher, name, resultCode, results));
+    }
+
+    public void reportFinished(IInstrumentationWatcher watcher, ComponentName name, int resultCode,
+            Bundle results) {
+        if (DEBUG) Slog.d(TAG, "Report finished to " + watcher
+                + ": " + name.flattenToShortString()
+                + " code=" + resultCode + " result=" + results);
+        report(new Report(REPORT_TYPE_FINISHED, watcher, name, resultCode, results));
+    }
+
+    private void report(Report report) {
+        synchronized (mLock) {
+            if (mThread == null) {
+                mThread = new MyThread();
+                mThread.start();
+            }
+            if (mPendingReports == null) {
+                mPendingReports = new ArrayList<>();
+            }
+            mPendingReports.add(report);
+            mLock.notifyAll();
+        }
+    }
+}
diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java
index b49370b..f073e5c 100644
--- a/services/core/java/com/android/server/am/ProcessList.java
+++ b/services/core/java/com/android/server/am/ProcessList.java
@@ -124,6 +124,13 @@
     // Memory pages are 4K.
     static final int PAGE_SIZE = 4*1024;
 
+    // Activity manager's version of Process.THREAD_GROUP_BG_NONINTERACTIVE
+    static final int SCHED_GROUP_BACKGROUND = 0;
+    // Activity manager's version of Process.THREAD_GROUP_DEFAULT
+    static final int SCHED_GROUP_DEFAULT = 1;
+    // Activity manager's version of Process.THREAD_GROUP_TOP_APP
+    static final int SCHED_GROUP_TOP_APP = 2;
+
     // The minimum number of cached apps we want to be able to keep around,
     // without empty apps being able to push them out of memory.
     static final int MIN_CACHED_APPS = 2;
diff --git a/services/core/java/com/android/server/am/TaskRecord.java b/services/core/java/com/android/server/am/TaskRecord.java
index 37a549a..4eae45c 100644
--- a/services/core/java/com/android/server/am/TaskRecord.java
+++ b/services/core/java/com/android/server/am/TaskRecord.java
@@ -40,6 +40,7 @@
 import android.os.ParcelFileDescriptor;
 import android.os.RemoteException;
 import android.os.UserHandle;
+import android.provider.Settings;
 import android.service.voice.IVoiceInteractionSession;
 import android.util.DisplayMetrics;
 import android.util.Slog;
@@ -74,6 +75,7 @@
 import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE;
 import static android.content.pm.ActivityInfo.RESIZE_MODE_UNRESIZEABLE;
 import static android.content.pm.ApplicationInfo.PRIVATE_FLAG_PRIVILEGED;
+import static android.provider.Settings.Secure.USER_SETUP_COMPLETE;
 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_ADD_REMOVE;
 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_LOCKTASK;
 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_RECENTS;
@@ -444,9 +446,9 @@
             // task as having a true root activity.
             rootWasReset = true;
         }
-
         userId = UserHandle.getUserId(info.applicationInfo.uid);
-        mUserSetupComplete = mService.mUserController.isUserSetupCompleteLocked(userId);
+        mUserSetupComplete = Settings.Secure.getIntForUser(mService.mContext.getContentResolver(),
+                USER_SETUP_COMPLETE, 0, userId) != 0;
         if ((info.flags & ActivityInfo.FLAG_AUTO_REMOVE_FROM_RECENTS) != 0) {
             // If the activity itself has requested auto-remove, then just always do it.
             autoRemoveRecents = true;
@@ -469,6 +471,19 @@
         setLockTaskAuth();
     }
 
+    /**
+     * Return true if the input activity has the same intent resolution as the intent this task
+     * record is based on (normally the root activity intent).
+     */
+    boolean isSameIntentResolution(ActivityRecord r) {
+        final Intent intent = new Intent(r.intent);
+        // Correct the activity intent for aliasing. The task record intent will always be based on
+        // the real activity that will be launched not the alias, so we need to use an intent with
+        // the component name pointing to the real activity not the alias in the activity record.
+        intent.setComponent(r.realActivity);
+        return this.intent.filterEquals(intent);
+    }
+
     void setTaskToReturnTo(int taskToReturnTo) {
         mTaskToReturnTo = (taskToReturnTo == RECENTS_ACTIVITY_TYPE)
                 ? HOME_ACTIVITY_TYPE : taskToReturnTo;
@@ -744,6 +759,14 @@
         if (r.isPersistable()) {
             mService.notifyTaskPersisterLocked(this, false);
         }
+
+        if (stack != null && stack.mStackId == PINNED_STACK_ID) {
+            // We normally notify listeners of task stack changes on pause, however pinned stack
+            // activities are normally in the paused state so no notification will be sent there
+            // before the activity is removed. We send it here so instead.
+            mService.notifyTaskStackChangedLocked();
+        }
+
         if (mActivities.isEmpty()) {
             return !mReuseTask;
         }
@@ -1319,8 +1342,13 @@
         if (bounds == null) {
             return;
         }
-        final int minimalSize = mMinimalSize == -1
-                ? mService.mStackSupervisor.mDefaultMinimalSizeOfResizeableTask : mMinimalSize;
+        int minimalSize = mMinimalSize;
+        // If the task has no requested minimal size, we'd like to enforce a minimal size
+        // so that the user can not render the task too small to manipulate. We don't need
+        // to do this for the pinned stack as the bounds are controlled by the system.
+        if (minimalSize == -1 && stack.mStackId != PINNED_STACK_ID) {
+            minimalSize = mService.mStackSupervisor.mDefaultMinimalSizeOfResizeableTask;
+        }
         final boolean adjustWidth = minimalSize > bounds.width();
         final boolean adjustHeight = minimalSize > bounds.height();
         if (!(adjustWidth || adjustHeight)) {
@@ -1557,6 +1585,7 @@
         pw.print(prefix); pw.print("userId="); pw.print(userId);
                 pw.print(" effectiveUid="); UserHandle.formatUid(pw, effectiveUid);
                 pw.print(" mCallingUid="); UserHandle.formatUid(pw, mCallingUid);
+                pw.print(" mUserSetupComplete="); pw.print(mUserSetupComplete);
                 pw.print(" mCallingPackage="); pw.println(mCallingPackage);
         if (affinity != null || rootAffinity != null) {
             pw.print(prefix); pw.print("affinity="); pw.print(affinity);
diff --git a/services/core/java/com/android/server/am/UserController.java b/services/core/java/com/android/server/am/UserController.java
index addffd3..59c2682 100644
--- a/services/core/java/com/android/server/am/UserController.java
+++ b/services/core/java/com/android/server/am/UserController.java
@@ -24,7 +24,6 @@
 import static android.app.ActivityManager.USER_OP_SUCCESS;
 import static android.content.Context.KEYGUARD_SERVICE;
 import static android.os.Process.SYSTEM_UID;
-import static android.provider.Settings.Secure.USER_SETUP_COMPLETE;
 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;
@@ -46,14 +45,11 @@
 import android.app.IStopUserCallback;
 import android.app.IUserSwitchObserver;
 import android.app.KeyguardManager;
-import android.content.ContentResolver;
 import android.content.Context;
 import android.content.IIntentReceiver;
 import android.content.Intent;
 import android.content.pm.PackageManager;
 import android.content.pm.UserInfo;
-import android.database.ContentObserver;
-import android.net.Uri;
 import android.os.BatteryStats;
 import android.os.Binder;
 import android.os.Bundle;
@@ -71,12 +67,10 @@
 import android.os.UserManagerInternal;
 import android.os.storage.IMountService;
 import android.os.storage.StorageManager;
-import android.provider.Settings;
 import android.util.IntArray;
 import android.util.Pair;
 import android.util.Slog;
 import android.util.SparseArray;
-import android.util.SparseBooleanArray;
 import android.util.SparseIntArray;
 
 import com.android.internal.R;
@@ -153,34 +147,6 @@
 
     private final LockPatternUtils mLockPatternUtils;
 
-    // Set of users who have completed the set-up process.
-    private final SparseBooleanArray mSetupCompletedUsers = new SparseBooleanArray();
-    private final UserSetupCompleteContentObserver mUserSetupCompleteContentObserver;
-
-    private class UserSetupCompleteContentObserver extends ContentObserver {
-        private final Uri mUserSetupComplete = Settings.Secure.getUriFor(USER_SETUP_COMPLETE);
-
-        public UserSetupCompleteContentObserver(Handler handler) {
-            super(handler);
-        }
-
-        void register(ContentResolver resolver) {
-            resolver.registerContentObserver(mUserSetupComplete, false, this, UserHandle.USER_ALL);
-            synchronized (mService) {
-                updateUserSetupCompleteLocked(UserHandle.USER_ALL);
-            }
-        }
-
-        @Override
-        public void onChange(boolean selfChange, Uri uri, int userId) {
-            if (mUserSetupComplete.equals(uri)) {
-                synchronized (mService) {
-                    updateUserSetupCompleteLocked(userId);
-                }
-            }
-        }
-    }
-
     UserController(ActivityManagerService service) {
         mService = service;
         mHandler = mService.mHandler;
@@ -190,7 +156,6 @@
         mUserLru.add(UserHandle.USER_SYSTEM);
         mLockPatternUtils = new LockPatternUtils(mService.mContext);
         updateStartedUserArrayLocked();
-        mUserSetupCompleteContentObserver = new UserSetupCompleteContentObserver(mHandler);
     }
 
     void finishUserSwitch(UserState uss) {
@@ -477,7 +442,6 @@
                 mStartedUsers.remove(userId);
                 mUserLru.remove(Integer.valueOf(userId));
                 updateStartedUserArrayLocked();
-                mSetupCompletedUsers.delete(userId);
 
                 mService.onUserStoppedLocked(userId);
                 // Clean up all state and processes associated with the user.
@@ -620,7 +584,7 @@
             }
         } else {
             Slog.w(TAG, "Mount service not published; guessing locked state based on property");
-            return !StorageManager.isFileBasedEncryptionEnabled();
+            return !StorageManager.isFileEncryptedNativeOrEmulated();
         }
     }
 
@@ -677,7 +641,6 @@
                 final Integer userIdInt = userId;
                 mUserLru.remove(userIdInt);
                 mUserLru.add(userIdInt);
-                updateUserSetupCompleteLocked(userId);
 
                 if (foreground) {
                     mCurrentUserId = userId;
@@ -892,22 +855,6 @@
         mUserSwitchObservers.finishBroadcast();
     }
 
-    void updateUserSetupCompleteLocked(int userId) {
-        final ContentResolver cr = mService.mContext.getContentResolver();
-        for (int i = mStartedUsers.size() - 1; i >= 0; i--) {
-            int startedUser = mStartedUsers.keyAt(i);
-            if (startedUser == userId || userId == UserHandle.USER_ALL) {
-                final boolean setupComplete =
-                        Settings.Secure.getIntForUser(cr, USER_SETUP_COMPLETE, 0, startedUser) != 0;
-                mSetupCompletedUsers.put(startedUser, setupComplete);
-            }
-        }
-    }
-
-    boolean isUserSetupCompleteLocked(int userId) {
-        return mSetupCompletedUsers.get(userId);
-    }
-
     private void stopBackgroundUsersIfEnforced(int oldUserId) {
         // Never stop system user
         if (oldUserId == UserHandle.USER_SYSTEM) {
@@ -1218,7 +1165,6 @@
 
     void onSystemReady() {
         updateCurrentProfileIdsLocked();
-        mUserSetupCompleteContentObserver.register(mService.mContext.getContentResolver());
     }
 
     /**
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index 548f563..d919737 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -58,7 +58,7 @@
 import android.media.AudioManager;
 import android.media.AudioManagerInternal;
 import android.media.AudioPort;
-import android.media.AudioRecordConfiguration;
+import android.media.AudioRecordingConfiguration;
 import android.media.AudioRoutesInfo;
 import android.media.IAudioFocusDispatcher;
 import android.media.IAudioRoutesObserver;
@@ -222,7 +222,6 @@
     private static final int MSG_UNMUTE_STREAM = 24;
     private static final int MSG_DYN_POLICY_MIX_STATE_UPDATE = 25;
     private static final int MSG_INDICATE_SYSTEM_READY = 26;
-    private static final int MSG_PERSIST_MASTER_MONO = 27;
     // start of messages handled under wakelock
     //   these messages can only be queued, i.e. sent with queueMsgUnderWakeLock(),
     //   and not with sendMsg(..., ..., SENDMSG_QUEUE, ...)
@@ -827,10 +826,7 @@
         }
 
         // Restore mono mode
-        final boolean masterMono = System.getIntForUser(
-                mContentResolver, System.MASTER_MONO,
-                0 /* default */, UserHandle.USER_CURRENT) == 1;
-        AudioSystem.setMasterMono(masterMono);
+        updateMasterMono(mContentResolver);
 
         // Restore ringer mode
         setRingerModeInt(getRingerModeInternal(), false);
@@ -853,6 +849,7 @@
             AudioSystem.setForceUse(AudioSystem.FOR_DOCK,
                     mDockAudioMediaEnabled ?
                             AudioSystem.FORCE_ANALOG_DOCK : AudioSystem.FORCE_NONE);
+            sendEncodedSurroundMode(mContentResolver);
         }
         if (mHdmiManager != null) {
             synchronized (mHdmiManager) {
@@ -1015,6 +1012,55 @@
                 0);
     }
 
+
+    private void updateMasterMono(ContentResolver cr)
+    {
+        final boolean masterMono = System.getIntForUser(
+                cr, System.MASTER_MONO, 0 /* default */, UserHandle.USER_CURRENT) == 1;
+        if (DEBUG_VOL) {
+            Log.d(TAG, String.format("Master mono %b", masterMono));
+        }
+        AudioSystem.setMasterMono(masterMono);
+    }
+
+    private void sendEncodedSurroundMode(ContentResolver cr)
+    {
+        int encodedSurroundMode = Settings.Global.getInt(
+                cr, Settings.Global.ENCODED_SURROUND_OUTPUT,
+                Settings.Global.ENCODED_SURROUND_OUTPUT_AUTO);
+        sendEncodedSurroundMode(encodedSurroundMode);
+    }
+
+    private void sendEncodedSurroundMode(int encodedSurroundMode)
+    {
+        // initialize to guaranteed bad value
+        int forceSetting = AudioSystem.NUM_FORCE_CONFIG;
+        switch (encodedSurroundMode) {
+            case Settings.Global.ENCODED_SURROUND_OUTPUT_AUTO:
+                forceSetting = AudioSystem.FORCE_NONE;
+                break;
+            case Settings.Global.ENCODED_SURROUND_OUTPUT_NEVER:
+                forceSetting = AudioSystem.FORCE_ENCODED_SURROUND_NEVER;
+                break;
+            case Settings.Global.ENCODED_SURROUND_OUTPUT_ALWAYS:
+                forceSetting = AudioSystem.FORCE_ENCODED_SURROUND_ALWAYS;
+                break;
+            default:
+                Log.e(TAG, "updateSurroundSoundSettings: illegal value "
+                        + encodedSurroundMode);
+                break;
+        }
+        if (forceSetting != AudioSystem.NUM_FORCE_CONFIG) {
+            sendMsg(mAudioHandler,
+                    MSG_SET_FORCE_USE,
+                    SENDMSG_QUEUE,
+                    AudioSystem.FOR_ENCODED_SURROUND,
+                    forceSetting,
+                    null,
+                    0);
+        }
+    }
+
     private void readPersistedSettings() {
         final ContentResolver cr = mContentResolver;
 
@@ -1056,6 +1102,7 @@
 
             updateRingerModeAffectedStreams();
             readDockAudioSettings(cr);
+            sendEncodedSurroundMode(cr);
         }
 
         mMuteAffectedStreams = System.getIntForUser(cr,
@@ -1091,13 +1138,7 @@
         }
         AudioSystem.muteMicrophone(microphoneMute);
 
-        final boolean masterMono = System.getIntForUser(
-                cr, System.MASTER_MONO, 0 /* default */, UserHandle.USER_CURRENT) == 1;
-        if (DEBUG_VOL) {
-            Log.d(TAG, String.format("Master mono %b, user=%d", masterMono, currentUser));
-        }
-        AudioSystem.setMasterMono(masterMono);
-        broadcastMasterMonoStatus(masterMono);
+        updateMasterMono(cr);
 
         // Each stream will read its own persisted settings
 
@@ -1855,52 +1896,6 @@
                 userId);
     }
 
-    /** @hide */
-    public boolean isMasterMono() {
-        return AudioSystem.getMasterMono();
-    }
-
-    /** @hide */
-    public void setMasterMono(boolean mono, String callingPackage, int userId) {
-        int callingUid = Binder.getCallingUid();
-        // If we are being called by the system check for user we are going to change
-        // so we handle user restrictions correctly.
-        if (callingUid == android.os.Process.SYSTEM_UID) {
-            callingUid = UserHandle.getUid(userId, UserHandle.getAppId(callingUid));
-        }
-
-        if (userId != UserHandle.getCallingUserId() &&
-                mContext.checkCallingOrSelfPermission(
-                        android.Manifest.permission.INTERACT_ACROSS_USERS_FULL)
-                != PackageManager.PERMISSION_GRANTED) {
-            return;
-        }
-        if (DEBUG_VOL) {
-            Log.d(TAG, String.format("Master mono %b, user=%d", mono, userId));
-        }
-
-        if (getCurrentUserId() == userId) {
-            if (mono != AudioSystem.getMasterMono()) {
-                AudioSystem.setMasterMono(mono);
-                // Post a persist master mono msg
-                sendMsg(mAudioHandler, MSG_PERSIST_MASTER_MONO, SENDMSG_REPLACE, mono ? 1
-                        : 0 /* value */, userId, null /* obj */, 0 /* delay */);
-                // notify apps and settings
-                broadcastMasterMonoStatus(mono);
-            }
-        } else {
-            // Post a persist master mono msg
-            sendMsg(mAudioHandler, MSG_PERSIST_MASTER_MONO, SENDMSG_REPLACE, mono ? 1
-                    : 0 /* value */, userId, null /* obj */, 0 /* delay */);
-        }
-    }
-
-    private void broadcastMasterMonoStatus(boolean mono) {
-        Intent intent = new Intent(AudioManager.MASTER_MONO_CHANGED_ACTION);
-        intent.putExtra(AudioManager.EXTRA_MASTER_MONO, mono);
-        sendBroadcastToAll(intent);
-    }
-
     /** @see AudioManager#getStreamVolume(int) */
     public int getStreamVolume(int streamType) {
         ensureValidStreamType(streamType);
@@ -4641,25 +4636,28 @@
                 case MSG_DYN_POLICY_MIX_STATE_UPDATE:
                     onDynPolicyMixStateUpdate((String) msg.obj, msg.arg1);
                     break;
-
-                case MSG_PERSIST_MASTER_MONO:
-                    Settings.System.putIntForUser(mContentResolver,
-                                                 Settings.System.MASTER_MONO,
-                                                 msg.arg1 /* value */,
-                                                 msg.arg2 /* userHandle */);
-                    break;
             }
         }
     }
 
     private class SettingsObserver extends ContentObserver {
 
+        private int mEncodedSurroundMode;
+
         SettingsObserver() {
             super(new Handler());
             mContentResolver.registerContentObserver(Settings.System.getUriFor(
                 Settings.System.MODE_RINGER_STREAMS_AFFECTED), false, this);
             mContentResolver.registerContentObserver(Settings.Global.getUriFor(
                 Settings.Global.DOCK_AUDIO_MEDIA_ENABLED), false, this);
+            mContentResolver.registerContentObserver(Settings.System.getUriFor(
+                    Settings.System.MASTER_MONO), false, this);
+
+            mEncodedSurroundMode = Settings.Global.getInt(
+                    mContentResolver, Settings.Global.ENCODED_SURROUND_OUTPUT,
+                    Settings.Global.ENCODED_SURROUND_OUTPUT_AUTO);
+            mContentResolver.registerContentObserver(Settings.Global.getUriFor(
+                    Settings.Global.ENCODED_SURROUND_OUTPUT), false, this);
         }
 
         @Override
@@ -4678,6 +4676,34 @@
                     setRingerModeInt(getRingerModeInternal(), false);
                 }
                 readDockAudioSettings(mContentResolver);
+                updateMasterMono(mContentResolver);
+                updateEncodedSurroundOutput();
+            }
+        }
+
+        private void updateEncodedSurroundOutput() {
+            int newSurroundMode = Settings.Global.getInt(
+                mContentResolver, Settings.Global.ENCODED_SURROUND_OUTPUT,
+                Settings.Global.ENCODED_SURROUND_OUTPUT_AUTO);
+            // Did it change?
+            if (mEncodedSurroundMode != newSurroundMode) {
+                // Send to AudioPolicyManager
+                sendEncodedSurroundMode(newSurroundMode);
+                synchronized(mConnectedDevices) {
+                    // Is HDMI connected?
+                    String key = makeDeviceListKey(AudioSystem.DEVICE_OUT_HDMI, "");
+                    DeviceListSpec deviceSpec = mConnectedDevices.get(key);
+                    if (deviceSpec != null) {
+                        // Toggle HDMI to retrigger broadcast with proper formats.
+                        setWiredDeviceConnectionState(AudioSystem.DEVICE_OUT_HDMI,
+                                AudioSystem.DEVICE_STATE_UNAVAILABLE, "", "",
+                                "android"); // disconnect
+                        setWiredDeviceConnectionState(AudioSystem.DEVICE_OUT_HDMI,
+                                AudioSystem.DEVICE_STATE_AVAILABLE, "", "",
+                                "android"); // reconnect
+                    }
+                }
+                mEncodedSurroundMode = newSurroundMode;
             }
         }
     }
@@ -6261,8 +6287,8 @@
         mRecordMonitor.unregisterRecordingCallback(rcdb);
     }
 
-    public AudioRecordConfiguration[] getActiveRecordConfigurations() {
-        return mRecordMonitor.getActiveRecordConfigurations();
+    public AudioRecordingConfiguration[] getActiveRecordingConfigurations() {
+        return mRecordMonitor.getActiveRecordingConfigurations();
     }
 
     //======================
@@ -6365,4 +6391,4 @@
             if (DEBUG_VOL) Log.d(TAG, "Reloaded controller service: " + this);
         }
     }
-}
\ No newline at end of file
+}
diff --git a/services/core/java/com/android/server/audio/RecordingActivityMonitor.java b/services/core/java/com/android/server/audio/RecordingActivityMonitor.java
index 4b0a142..7a085e1 100644
--- a/services/core/java/com/android/server/audio/RecordingActivityMonitor.java
+++ b/services/core/java/com/android/server/audio/RecordingActivityMonitor.java
@@ -18,7 +18,7 @@
 
 import android.media.AudioFormat;
 import android.media.AudioManager;
-import android.media.AudioRecordConfiguration;
+import android.media.AudioRecordingConfiguration;
 import android.media.AudioSystem;
 import android.media.IRecordingConfigDispatcher;
 import android.media.MediaRecorder;
@@ -39,8 +39,8 @@
 
     private ArrayList<RecMonitorClient> mClients = new ArrayList<RecMonitorClient>();
 
-    private HashMap<Integer, AudioRecordConfiguration> mRecordConfigs =
-            new HashMap<Integer, AudioRecordConfiguration>();
+    private HashMap<Integer, AudioRecordingConfiguration> mRecordConfigs =
+            new HashMap<Integer, AudioRecordingConfiguration>();
 
     RecordingActivityMonitor() {
         RecMonitorClient.sMonitor = this;
@@ -50,16 +50,19 @@
      * Implementation of android.media.AudioSystem.AudioRecordingCallback
      */
     public void onRecordingConfigurationChanged(int event, int session, int source,
-            int[] recordingFormat) {
+            int[] recordingInfo) {
         if (MediaRecorder.isSystemOnlyAudioSource(source)) {
             return;
         }
-        if (updateSnapshot(event, session, source, recordingFormat)) {
-            final Iterator<RecMonitorClient> clientIterator = mClients.iterator();
+        final AudioRecordingConfiguration[] configs =
+                updateSnapshot(event, session, source, recordingInfo);
+        if (configs != null){
             synchronized(mClients) {
+                final Iterator<RecMonitorClient> clientIterator = mClients.iterator();
                 while (clientIterator.hasNext()) {
                     try {
-                        clientIterator.next().mDispatcherCb.dispatchRecordingConfigChange();
+                        clientIterator.next().mDispatcherCb.dispatchRecordingConfigChange(
+                                configs);
                     } catch (RemoteException e) {
                         Log.w(TAG, "Could not call dispatchRecordingConfigChange() on client", e);
                     }
@@ -101,9 +104,9 @@
         }
     }
 
-    AudioRecordConfiguration[] getActiveRecordConfigurations() {
+    AudioRecordingConfiguration[] getActiveRecordingConfigurations() {
         synchronized(mRecordConfigs) {
-            return mRecordConfigs.values().toArray(new AudioRecordConfiguration[0]);
+            return mRecordConfigs.values().toArray(new AudioRecordingConfiguration[0]);
         }
     }
 
@@ -115,44 +118,65 @@
      * @param recordingFormat see
      *     {@link AudioSystem.AudioRecordingCallback#onRecordingConfigurationChanged(int, int, int, int[])}
      *     for the definition of the contents of the array
-     * @return true if the list of active recording sessions has been modified, false otherwise.
+     * @return null if the list of active recording sessions has not been modified, an array
+     *     with the current active configurations otherwise.
      */
-    private boolean updateSnapshot(int event, int session, int source, int[] recordingFormat) {
+    private AudioRecordingConfiguration[] updateSnapshot(int event, int session, int source,
+            int[] recordingInfo) {
+        final boolean configChanged;
+        final AudioRecordingConfiguration[] configs;
         synchronized(mRecordConfigs) {
             switch (event) {
             case AudioManager.RECORD_CONFIG_EVENT_STOP:
                 // return failure if an unknown recording session stopped
-                return (mRecordConfigs.remove(new Integer(session)) != null);
+                configChanged = (mRecordConfigs.remove(new Integer(session)) != null);
+                break;
             case AudioManager.RECORD_CONFIG_EVENT_START:
                 final AudioFormat clientFormat = new AudioFormat.Builder()
-                        .setEncoding(recordingFormat[0])
+                        .setEncoding(recordingInfo[0])
                         // FIXME this doesn't support index-based masks
-                        .setChannelMask(recordingFormat[1])
-                        .setSampleRate(recordingFormat[2])
+                        .setChannelMask(recordingInfo[1])
+                        .setSampleRate(recordingInfo[2])
                         .build();
                 final AudioFormat deviceFormat = new AudioFormat.Builder()
-                        .setEncoding(recordingFormat[3])
+                        .setEncoding(recordingInfo[3])
                         // FIXME this doesn't support index-based masks
-                        .setChannelMask(recordingFormat[4])
-                        .setSampleRate(recordingFormat[5])
+                        .setChannelMask(recordingInfo[4])
+                        .setSampleRate(recordingInfo[5])
                         .build();
-                if (mRecordConfigs.containsKey(new Integer(session))) {
-                    // start of session that's already tracked, not worth an update
-                    // TO DO in the future when tracking record format: there might be a record
-                    //       format change during a recording that requires reporting
-                    return false;
+                final int patchHandle = recordingInfo[6];
+                final Integer sessionKey = new Integer(session);
+                if (mRecordConfigs.containsKey(sessionKey)) {
+                    final AudioRecordingConfiguration updatedConfig =
+                            new AudioRecordingConfiguration(session, source,
+                                    clientFormat, deviceFormat, patchHandle);
+                    if (updatedConfig.equals(mRecordConfigs.get(sessionKey))) {
+                        configChanged = false;
+                    } else {
+                        // config exists but has been modified
+                        mRecordConfigs.remove(sessionKey);
+                        mRecordConfigs.put(sessionKey, updatedConfig);
+                        configChanged = true;
+                    }
                 } else {
-                    mRecordConfigs.put(new Integer(session),
-                            new AudioRecordConfiguration(session, source,
-                                    clientFormat, deviceFormat));
-                    return true;
+                    mRecordConfigs.put(sessionKey,
+                            new AudioRecordingConfiguration(session, source,
+                                    clientFormat, deviceFormat, patchHandle));
+                    configChanged = true;
                 }
+                break;
             default:
                 Log.e(TAG, String.format("Unknown event %d for session %d, source %d",
                         event, session, source));
-                return false;
+                configChanged = false;
+            }
+            if (configChanged) {
+                configs = mRecordConfigs.values().toArray(new AudioRecordingConfiguration[0]);
+            } else {
+                configs = null;
             }
         }
+        return configs;
     }
 
     /**
diff --git a/services/core/java/com/android/server/camera/CameraService.java b/services/core/java/com/android/server/camera/CameraService.java
index f82454a..cd8eb4e 100644
--- a/services/core/java/com/android/server/camera/CameraService.java
+++ b/services/core/java/com/android/server/camera/CameraService.java
@@ -60,10 +60,6 @@
 
     public static final String CAMERA_SERVICE_PROXY_BINDER_NAME = "media.camera.proxy";
 
-    // Event arguments to use with the camera service notifySystemEvent call:
-    public static final int NO_EVENT = 0; // NOOP
-    public static final int USER_SWITCHED = 1; // User changed, argument is the new user handle
-
     // State arguments to use with the notifyCameraState call from camera service:
     public static final int CAMERA_STATE_OPEN = 0;
     public static final int CAMERA_STATE_ACTIVE = 1;
@@ -224,7 +220,7 @@
         if (mEnabledCameraUsers == null || !mEnabledCameraUsers.equals(currentUserHandles)) {
             // Some user handles have been added or removed, update mediaserver.
             mEnabledCameraUsers = currentUserHandles;
-            notifyMediaserverLocked(USER_SWITCHED, currentUserHandles);
+            notifyMediaserverLocked(ICameraService.EVENT_USER_SWITCHED, currentUserHandles);
         }
     }
 
@@ -244,7 +240,7 @@
             if (mEnabledCameraUsers == null) {
                 return;
             }
-            if (notifyMediaserverLocked(USER_SWITCHED, mEnabledCameraUsers)) {
+            if (notifyMediaserverLocked(ICameraService.EVENT_USER_SWITCHED, mEnabledCameraUsers)) {
                 retries = 0;
             }
         }
diff --git a/services/core/java/com/android/server/connectivity/ApfFilter.java b/services/core/java/com/android/server/connectivity/ApfFilter.java
new file mode 100644
index 0000000..25c84e1
--- /dev/null
+++ b/services/core/java/com/android/server/connectivity/ApfFilter.java
@@ -0,0 +1,499 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.connectivity;
+
+import static android.system.OsConstants.*;
+
+import android.net.NetworkUtils;
+import android.net.apf.ApfGenerator;
+import android.net.apf.ApfGenerator.IllegalInstructionException;
+import android.net.apf.ApfGenerator.Register;
+import android.system.ErrnoException;
+import android.system.Os;
+import android.system.PacketSocketAddress;
+import android.util.Log;
+import android.util.Pair;
+
+import com.android.internal.util.HexDump;
+import com.android.server.ConnectivityService;
+
+import java.io.FileDescriptor;
+import java.io.IOException;
+import java.lang.Thread;
+import java.net.NetworkInterface;
+import java.net.SocketException;
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.Arrays;
+
+import libcore.io.IoBridge;
+
+/**
+ * For networks that support packet filtering via APF programs, {@code ApfFilter}
+ * listens for IPv6 ICMPv6 router advertisements (RAs) and generates APF programs to
+ * filter out redundant duplicate ones.
+ *
+ * @hide
+ */
+public class ApfFilter {
+    // Thread to listen for RAs.
+    private class ReceiveThread extends Thread {
+        private final byte[] mPacket = new byte[1514];
+        private final FileDescriptor mSocket;
+        private volatile boolean mStopped;
+
+        public ReceiveThread(FileDescriptor socket) {
+            mSocket = socket;
+        }
+
+        public void halt() {
+            mStopped = true;
+            try {
+                // Interrupts the read() call the thread is blocked in.
+                IoBridge.closeAndSignalBlockedThreads(mSocket);
+            } catch (IOException ignored) {}
+        }
+
+        @Override
+        public void run() {
+            log("begin monitoring");
+            while (!mStopped) {
+                try {
+                    int length = Os.read(mSocket, mPacket, 0, mPacket.length);
+                    processRa(mPacket, length);
+                } catch (IOException|ErrnoException e) {
+                    if (!mStopped) {
+                        Log.e(TAG, "Read error", e);
+                    }
+                }
+            }
+        }
+    }
+
+    private static final String TAG = "ApfFilter";
+
+    private final ConnectivityService mConnectivityService;
+    private final NetworkAgentInfo mNai;
+    private ReceiveThread mReceiveThread;
+    private String mIfaceName;
+    private long mUniqueCounter;
+
+    private ApfFilter(ConnectivityService connectivityService, NetworkAgentInfo nai) {
+        mConnectivityService = connectivityService;
+        mNai = nai;
+        maybeStartFilter();
+    }
+
+    private void log(String s) {
+        Log.d(TAG, "(" + mNai.network.netId + "): " + s);
+    }
+
+    private long getUniqueNumber() {
+        return mUniqueCounter++;
+    }
+
+    /**
+     * Attempt to start listening for RAs and, if RAs are received, generating and installing
+     * filters to ignore useless RAs.
+     */
+    private void maybeStartFilter() {
+        mIfaceName = mNai.linkProperties.getInterfaceName();
+        if (mIfaceName == null) return;
+        FileDescriptor socket;
+        try {
+            socket = Os.socket(AF_PACKET, SOCK_RAW, ETH_P_IPV6);
+            PacketSocketAddress addr = new PacketSocketAddress((short) ETH_P_IPV6,
+                    NetworkInterface.getByName(mIfaceName).getIndex());
+            Os.bind(socket, addr);
+            NetworkUtils.attachRaFilter(socket, mNai.networkMisc.apfPacketFormat);
+        } catch(SocketException|ErrnoException e) {
+            Log.e(TAG, "Error filtering raw socket", e);
+            return;
+        }
+        mReceiveThread = new ReceiveThread(socket);
+        mReceiveThread.start();
+    }
+
+    /**
+     * mNai's LinkProperties may have changed, take appropriate action.
+     */
+    public void updateFilter() {
+        // If we're not listening for RAs, try starting.
+        if (mReceiveThread == null) {
+            maybeStartFilter();
+        // If interface name has changed, restart.
+        } else if (!mIfaceName.equals(mNai.linkProperties.getInterfaceName())) {
+            shutdown();
+            maybeStartFilter();
+        }
+    }
+
+    // Returns seconds since Unix Epoch.
+    private static long curTime() {
+        return System.currentTimeMillis() / 1000L;
+    }
+
+    // A class to hold information about an RA.
+    private class Ra {
+        private static final int ETH_HEADER_LEN = 14;
+
+        private static final int IPV6_HEADER_LEN = 40;
+
+        // From RFC4861:
+        private static final int ICMP6_RA_HEADER_LEN = 16;
+        private static final int ICMP6_RA_OPTION_OFFSET =
+                ETH_HEADER_LEN + IPV6_HEADER_LEN + ICMP6_RA_HEADER_LEN;
+        private static final int ICMP6_RA_ROUTER_LIFETIME_OFFSET =
+                ETH_HEADER_LEN + IPV6_HEADER_LEN + 6;
+        private static final int ICMP6_RA_ROUTER_LIFETIME_LEN = 2;
+        // Prefix information option.
+        private static final int ICMP6_PREFIX_OPTION_TYPE = 3;
+        private static final int ICMP6_PREFIX_OPTION_LEN = 32;
+        private static final int ICMP6_PREFIX_OPTION_VALID_LIFETIME_OFFSET = 4;
+        private static final int ICMP6_PREFIX_OPTION_VALID_LIFETIME_LEN = 4;
+        private static final int ICMP6_PREFIX_OPTION_PREFERRED_LIFETIME_OFFSET = 8;
+        private static final int ICMP6_PREFIX_OPTION_PREFERRED_LIFETIME_LEN = 4;
+
+        // From RFC6106: Recursive DNS Server option
+        private static final int ICMP6_RDNSS_OPTION_TYPE = 25;
+        // From RFC6106: DNS Search List option
+        private static final int ICMP6_DNSSL_OPTION_TYPE = 31;
+
+        // From RFC4191: Route Information option
+        private static final int ICMP6_ROUTE_INFO_OPTION_TYPE = 24;
+        // Above three options all have the same format:
+        private static final int ICMP6_4_BYTE_LIFETIME_OFFSET = 4;
+        private static final int ICMP6_4_BYTE_LIFETIME_LEN = 4;
+
+        private final ByteBuffer mPacket;
+        // List of binary ranges that include the whole packet except the lifetimes.
+        // Pairs consist of offset and length.
+        private final ArrayList<Pair<Integer, Integer>> mNonLifetimes =
+                new ArrayList<Pair<Integer, Integer>>();
+        // Minimum lifetime in packet
+        long mMinLifetime;
+        // When the packet was last captured, in seconds since Unix Epoch
+        long mLastSeen;
+
+        /**
+         * Add a binary range of the packet that does not include a lifetime to mNonLifetimes.
+         * Assumes mPacket.position() is as far as we've parsed the packet.
+         * @param lastNonLifetimeStart offset within packet of where the last binary range of
+         *                             data not including a lifetime.
+         * @param lifetimeOffset offset from mPacket.position() to the next lifetime data.
+         * @param lifetimeLength length of the next lifetime data.
+         * @return offset within packet of where the next binary range of data not including
+         *         a lifetime.  This can be passed into the next invocation of this function
+         *         via {@code lastNonLifetimeStart}.
+         */
+        private int addNonLifetime(int lastNonLifetimeStart, int lifetimeOffset,
+                int lifetimeLength) {
+            lifetimeOffset += mPacket.position();
+            mNonLifetimes.add(new Pair<Integer, Integer>(lastNonLifetimeStart,
+                    lifetimeOffset - lastNonLifetimeStart));
+            return lifetimeOffset + lifetimeLength;
+        }
+
+        // Note that this parses RA and may throw IllegalArgumentException (from
+        // Buffer.position(int) ) or IndexOutOfBoundsException (from ByteBuffer.get(int) ) if
+        // parsing encounters something non-compliant with specifications.
+        Ra(byte[] packet, int length) {
+            mPacket = ByteBuffer.allocate(length).put(ByteBuffer.wrap(packet, 0, length));
+            mPacket.clear();
+            mLastSeen = curTime();
+
+            // Parse router lifetime
+            int lastNonLifetimeStart = addNonLifetime(0, ICMP6_RA_ROUTER_LIFETIME_OFFSET,
+                    ICMP6_RA_ROUTER_LIFETIME_LEN);
+            // Parse ICMP6 options
+            mPacket.position(ICMP6_RA_OPTION_OFFSET);
+            while (mPacket.hasRemaining()) {
+                int optionType = ((int)mPacket.get(mPacket.position())) & 0xff;
+                int optionLength = (((int)mPacket.get(mPacket.position() + 1)) & 0xff) * 8;
+                switch (optionType) {
+                    case ICMP6_PREFIX_OPTION_TYPE:
+                        // Parse valid lifetime
+                        lastNonLifetimeStart = addNonLifetime(lastNonLifetimeStart,
+                                ICMP6_PREFIX_OPTION_VALID_LIFETIME_OFFSET,
+                                ICMP6_PREFIX_OPTION_VALID_LIFETIME_LEN);
+                        // Parse preferred lifetime
+                        lastNonLifetimeStart = addNonLifetime(lastNonLifetimeStart,
+                                ICMP6_PREFIX_OPTION_PREFERRED_LIFETIME_OFFSET,
+                                ICMP6_PREFIX_OPTION_PREFERRED_LIFETIME_LEN);
+                        break;
+                    // These three options have the same lifetime offset and size, so process
+                    // together:
+                    case ICMP6_ROUTE_INFO_OPTION_TYPE:
+                    case ICMP6_RDNSS_OPTION_TYPE:
+                    case ICMP6_DNSSL_OPTION_TYPE:
+                        // Parse lifetime
+                        lastNonLifetimeStart = addNonLifetime(lastNonLifetimeStart,
+                                ICMP6_4_BYTE_LIFETIME_OFFSET,
+                                ICMP6_4_BYTE_LIFETIME_LEN);
+                        break;
+                    default:
+                        // RFC4861 section 4.2 dictates we ignore unknown options for fowards
+                        // compatibility.
+                        break;
+                }
+                mPacket.position(mPacket.position() + optionLength);
+            }
+            // Mark non-lifetime bytes since last lifetime.
+            addNonLifetime(lastNonLifetimeStart, 0, 0);
+            mMinLifetime = minLifetime(packet, length);
+        }
+
+        // Ignoring lifetimes (which may change) does {@code packet} match this RA?
+        boolean matches(byte[] packet, int length) {
+            if (length != mPacket.limit()) return false;
+            ByteBuffer a = ByteBuffer.wrap(packet);
+            ByteBuffer b = mPacket;
+            for (Pair<Integer, Integer> nonLifetime : mNonLifetimes) {
+                a.clear();
+                b.clear();
+                a.position(nonLifetime.first);
+                b.position(nonLifetime.first);
+                a.limit(nonLifetime.first + nonLifetime.second);
+                b.limit(nonLifetime.first + nonLifetime.second);
+                if (a.compareTo(b) != 0) return false;
+            }
+            return true;
+        }
+
+        // What is the minimum of all lifetimes within {@code packet} in seconds?
+        // Precondition: matches(packet, length) already returned true.
+        long minLifetime(byte[] packet, int length) {
+            long minLifetime = Long.MAX_VALUE;
+            // Wrap packet in ByteBuffer so we can read big-endian values easily
+            ByteBuffer byteBuffer = ByteBuffer.wrap(packet);
+            for (int i = 0; (i + 1) < mNonLifetimes.size(); i++) {
+                int offset = mNonLifetimes.get(i).first + mNonLifetimes.get(i).second;
+                int lifetimeLength = mNonLifetimes.get(i+1).first - offset;
+                long val;
+                switch (lifetimeLength) {
+                    case 2: val = byteBuffer.getShort(offset); break;
+                    case 4: val = byteBuffer.getInt(offset); break;
+                    default: throw new IllegalStateException("bogus lifetime size " + length);
+                }
+                // Mask to size, converting signed to unsigned
+                val &= (1L << (lifetimeLength * 8)) - 1;
+                minLifetime = Math.min(minLifetime, val);
+            }
+            return minLifetime;
+        }
+
+        // How many seconds does this RA's have to live, taking into account the fact
+        // that we might have seen it a while ago.
+        long currentLifetime() {
+            return mMinLifetime - (curTime() - mLastSeen);
+        }
+
+        boolean isExpired() {
+            return currentLifetime() < 0;
+        }
+
+        // Append a filter for this RA to {@code gen}. Jump to DROP_LABEL if it should be dropped.
+        // Jump to the next filter if packet doesn't match this RA.
+        long generateFilter(ApfGenerator gen) throws IllegalInstructionException {
+            String nextFilterLabel = "Ra" + getUniqueNumber();
+            // Skip if packet is not the right size
+            gen.addLoadFromMemory(Register.R0, gen.PACKET_SIZE_MEMORY_SLOT);
+            gen.addJumpIfR0NotEquals(mPacket.limit(), nextFilterLabel);
+            int filterLifetime = (int)(currentLifetime() / FRACTION_OF_LIFETIME_TO_FILTER);
+            // Skip filter if expired
+            gen.addLoadFromMemory(Register.R0, gen.FILTER_AGE_MEMORY_SLOT);
+            gen.addJumpIfR0GreaterThan(filterLifetime, nextFilterLabel);
+            for (int i = 0; i < mNonLifetimes.size(); i++) {
+                // Generate code to match the packet bytes
+                Pair<Integer, Integer> nonLifetime = mNonLifetimes.get(i);
+                gen.addLoadImmediate(Register.R0, nonLifetime.first);
+                gen.addJumpIfBytesNotEqual(Register.R0,
+                        Arrays.copyOfRange(mPacket.array(), nonLifetime.first,
+                                           nonLifetime.first + nonLifetime.second),
+                        nextFilterLabel);
+                // Generate code to test the lifetimes haven't gone down too far
+                if ((i + 1) < mNonLifetimes.size()) {
+                    Pair<Integer, Integer> nextNonLifetime = mNonLifetimes.get(i + 1);
+                    int offset = nonLifetime.first + nonLifetime.second;
+                    int length = nextNonLifetime.first - offset;
+                    switch (length) {
+                        case 4: gen.addLoad32(Register.R0, offset); break;
+                        case 2: gen.addLoad16(Register.R0, offset); break;
+                        default: throw new IllegalStateException("bogus lifetime size " + length);
+                    }
+                    gen.addJumpIfR0LessThan(filterLifetime, nextFilterLabel);
+                }
+            }
+            gen.addJump(gen.DROP_LABEL);
+            gen.defineLabel(nextFilterLabel);
+            return filterLifetime;
+        }
+    }
+
+    // Maximum number of RAs to filter for.
+    private static final int MAX_RAS = 10;
+    private ArrayList<Ra> mRas = new ArrayList<Ra>();
+
+    // There is always some marginal benefit to updating the installed APF program when an RA is
+    // seen because we can extend the program's lifetime slightly, but there is some cost to
+    // updating the program, so don't bother unless the program is going to expire soon. This
+    // constant defines "soon" in seconds.
+    private static final long MAX_PROGRAM_LIFETIME_WORTH_REFRESHING = 30;
+    // We don't want to filter an RA for it's whole lifetime as it'll be expired by the time we ever
+    // see a refresh.  Using half the lifetime might be a good idea except for the fact that
+    // packets may be dropped, so let's use 6.
+    private static final int FRACTION_OF_LIFETIME_TO_FILTER = 6;
+
+    // When did we last install a filter program? In seconds since Unix Epoch.
+    private long mLastTimeInstalledProgram;
+    // How long should the last installed filter program live for? In seconds.
+    private long mLastInstalledProgramMinLifetime;
+
+    private void installNewProgram() {
+        if (mRas.size() == 0) return;
+        final byte[] program;
+        long programMinLifetime = Long.MAX_VALUE;
+        try {
+            ApfGenerator gen = new ApfGenerator();
+            // This is guaranteed to return true because of the check in maybeInstall.
+            gen.setApfVersion(mNai.networkMisc.apfVersionSupported);
+            // Step 1: Determine how many RA filters we can fit in the program.
+            int ras = 0;
+            for (Ra ra : mRas) {
+                if (ra.isExpired()) continue;
+                ra.generateFilter(gen);
+                if (gen.programLengthOverEstimate() > mNai.networkMisc.maximumApfProgramSize) {
+                    // We went too far.  Use prior number of RAs in "ras".
+                    break;
+                } else {
+                    // Yay! this RA filter fits, increment "ras".
+                    ras++;
+                }
+            }
+            // Step 2: Generate RA filters
+            gen = new ApfGenerator();
+            // This is guaranteed to return true because of the check in maybeInstall.
+            gen.setApfVersion(mNai.networkMisc.apfVersionSupported);
+            for (Ra ra : mRas) {
+                if (ras-- == 0) break;
+                if (ra.isExpired()) continue;
+                programMinLifetime = Math.min(programMinLifetime, ra.generateFilter(gen));
+            }
+            // Execution will reach the end of the program if no filters match, which will pass the
+            // packet to the AP.
+            program = gen.generate();
+        } catch (IllegalInstructionException e) {
+            Log.e(TAG, "Program failed to generate: ", e);
+            return;
+        }
+        mLastTimeInstalledProgram = curTime();
+        mLastInstalledProgramMinLifetime = programMinLifetime;
+        hexDump("Installing filter: ", program, program.length);
+        mConnectivityService.pushApfProgramToNetwork(mNai, program);
+    }
+
+    // Install a new filter program if the last installed one will die soon.
+    private void maybeInstallNewProgram() {
+        if (mRas.size() == 0) return;
+        // If the current program doesn't expire for a while, don't bother updating.
+        long expiry = mLastTimeInstalledProgram + mLastInstalledProgramMinLifetime;
+        if (expiry < curTime() + MAX_PROGRAM_LIFETIME_WORTH_REFRESHING) {
+            installNewProgram();
+        }
+    }
+
+    private void hexDump(String msg, byte[] packet, int length) {
+        log(msg + HexDump.toHexString(packet, 0, length));
+    }
+
+    private void processRa(byte[] packet, int length) {
+        hexDump("Read packet = ", packet, length);
+
+        // Have we seen this RA before?
+        for (int i = 0; i < mRas.size(); i++) {
+            Ra ra = mRas.get(i);
+            if (ra.matches(packet, length)) {
+                log("matched RA");
+                // Update lifetimes.
+                ra.mLastSeen = curTime();
+                ra.mMinLifetime = ra.minLifetime(packet, length);
+
+                // Keep mRas in LRU order so as to prioritize generating filters for recently seen
+                // RAs. LRU prioritizes this because RA filters are generated in order from mRas
+                // until the filter program exceeds the maximum filter program size allowed by the
+                // chipset, so RAs appearing earlier in mRas are more likely to make it into the
+                // filter program.
+                // TODO: consider sorting the RAs in order of increasing expiry time as well.
+                // Swap to front of array.
+                mRas.add(0, mRas.remove(i));
+
+                maybeInstallNewProgram();
+                return;
+            }
+        }
+        // Purge expired RAs.
+        for (int i = 0; i < mRas.size();) {
+            if (mRas.get(i).isExpired()) {
+                log("expired RA");
+                mRas.remove(i);
+            } else {
+                i++;
+            }
+        }
+        // TODO: figure out how to proceed when we've received more then MAX_RAS RAs.
+        if (mRas.size() >= MAX_RAS) return;
+        try {
+            log("adding RA");
+            mRas.add(new Ra(packet, length));
+        } catch (Exception e) {
+            Log.e(TAG, "Error parsing RA: " + e);
+            return;
+        }
+        installNewProgram();
+    }
+
+    /**
+     * Install an {@link ApfFilter} on {@code nai} if {@code nai} supports packet
+     * filtering using APF programs.
+     */
+    public static void maybeInstall(ConnectivityService connectivityService, NetworkAgentInfo nai) {
+        if (nai.networkMisc == null) return;
+        if (nai.networkMisc.apfVersionSupported == 0) return;
+        if (nai.networkMisc.maximumApfProgramSize < 200) {
+            Log.e(TAG, "Uselessly small APF size limit: " + nai.networkMisc.maximumApfProgramSize);
+            return;
+        }
+        // For now only support generating programs for Ethernet frames. If this restriction is
+        // lifted:
+        //   1. the program generator will need its offsets adjusted.
+        //   2. the packet filter attached to our packet socket will need its offset adjusted.
+        if (nai.networkMisc.apfPacketFormat != ARPHRD_ETHER) return;
+        if (!new ApfGenerator().setApfVersion(nai.networkMisc.apfVersionSupported)) {
+            Log.e(TAG, "Unsupported APF version: " + nai.networkMisc.apfVersionSupported);
+            return;
+        }
+        nai.apfFilter = new ApfFilter(connectivityService, nai);
+    }
+
+    public void shutdown() {
+        if (mReceiveThread != null) {
+            log("shuting down");
+            mReceiveThread.halt();  // Also closes socket.
+            mReceiveThread = null;
+        }
+    }
+}
diff --git a/services/core/java/com/android/server/connectivity/KeepaliveTracker.java b/services/core/java/com/android/server/connectivity/KeepaliveTracker.java
index 90c9ddf..9e1f6b8 100644
--- a/services/core/java/com/android/server/connectivity/KeepaliveTracker.java
+++ b/services/core/java/com/android/server/connectivity/KeepaliveTracker.java
@@ -60,7 +60,7 @@
 public class KeepaliveTracker {
 
     private static final String TAG = "KeepaliveTracker";
-    private static final boolean DBG = true;
+    private static final boolean DBG = false;
 
     public static final String PERMISSION = android.Manifest.permission.PACKET_KEEPALIVE_OFFLOAD;
 
diff --git a/services/core/java/com/android/server/connectivity/Nat464Xlat.java b/services/core/java/com/android/server/connectivity/Nat464Xlat.java
index a9eaeee..b390884 100644
--- a/services/core/java/com/android/server/connectivity/Nat464Xlat.java
+++ b/services/core/java/com/android/server/connectivity/Nat464Xlat.java
@@ -16,13 +16,11 @@
 
 package com.android.server.connectivity;
 
-import static android.net.ConnectivityManager.TYPE_MOBILE;
-import static android.net.ConnectivityManager.TYPE_WIFI;
-
 import java.net.Inet4Address;
 
 import android.content.Context;
 import android.net.InterfaceConfiguration;
+import android.net.ConnectivityManager;
 import android.net.LinkAddress;
 import android.net.LinkProperties;
 import android.net.NetworkAgent;
@@ -34,6 +32,7 @@
 import android.util.Slog;
 
 import com.android.server.net.BaseNetworkObserver;
+import com.android.internal.util.ArrayUtils;
 
 /**
  * @hide
@@ -46,6 +45,13 @@
     // This must match the interface prefix in clatd.c.
     private static final String CLAT_PREFIX = "v4-";
 
+    // The network types we will start clatd on.
+    private static final int[] NETWORK_TYPES = {
+            ConnectivityManager.TYPE_MOBILE,
+            ConnectivityManager.TYPE_WIFI,
+            ConnectivityManager.TYPE_ETHERNET,
+    };
+
     private final INetworkManagementService mNMService;
 
     // ConnectivityService Handler for LinkProperties updates.
@@ -90,7 +96,7 @@
                 (nai.linkProperties != null) ? nai.linkProperties.hasIPv4Address() : false;
         // Only support clat on mobile and wifi for now, because these are the only IPv6-only
         // networks we can connect to.
-        return connected && !hasIPv4Address && (netType == TYPE_MOBILE || netType == TYPE_WIFI);
+        return connected && !hasIPv4Address && ArrayUtils.contains(NETWORK_TYPES, netType);
     }
 
     /**
@@ -221,7 +227,7 @@
     }
 
     private void maybeSetIpv6NdOffload(String iface, boolean on) {
-        if (mNetwork.networkInfo.getType() != TYPE_WIFI) {
+        if (mNetwork.networkInfo.getType() != ConnectivityManager.TYPE_WIFI) {
             return;
         }
         try {
diff --git a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java
index c5d38cb..b4c71c1 100644
--- a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java
+++ b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java
@@ -32,6 +32,7 @@
 import com.android.internal.util.AsyncChannel;
 import com.android.server.ConnectivityService;
 import com.android.server.connectivity.NetworkMonitor;
+import com.android.server.connectivity.ApfFilter;
 
 import java.util.ArrayList;
 import java.util.Comparator;
@@ -163,6 +164,8 @@
     // Used by ConnectivityService to keep track of 464xlat.
     public Nat464Xlat clatd;
 
+    public ApfFilter apfFilter;
+
     public NetworkAgentInfo(Messenger messenger, AsyncChannel ac, Network net, NetworkInfo info,
             LinkProperties lp, NetworkCapabilities nc, int score, Context context, Handler handler,
             NetworkMisc misc, NetworkRequest defaultRequest, ConnectivityService connService) {
@@ -175,6 +178,7 @@
         currentScore = score;
         networkMonitor = connService.createNetworkMonitor(context, handler, this, defaultRequest);
         networkMisc = misc;
+        apfFilter.maybeInstall(connService, this);
     }
 
     /**
diff --git a/services/core/java/com/android/server/connectivity/NetworkMonitor.java b/services/core/java/com/android/server/connectivity/NetworkMonitor.java
index 4504bdb..73da427 100644
--- a/services/core/java/com/android/server/connectivity/NetworkMonitor.java
+++ b/services/core/java/com/android/server/connectivity/NetworkMonitor.java
@@ -76,7 +76,7 @@
  * {@hide}
  */
 public class NetworkMonitor extends StateMachine {
-    private static final boolean DBG = true;
+    private static final boolean DBG = false;
     private static final String TAG = "NetworkMonitor";
     private static final String DEFAULT_SERVER = "connectivitycheck.gstatic.com";
     private static final int SOCKET_TIMEOUT_MS = 10000;
@@ -566,7 +566,7 @@
         @Override
         public void enter() {
             final String cmdName = ACTION_LINGER_EXPIRED + "." + mNetworkAgentInfo.network.netId;
-            mWakeupMessage = new WakeupMessage(mContext, getHandler(), cmdName, CMD_LINGER_EXPIRED);
+            mWakeupMessage = makeWakeupMessage(mContext, getHandler(), cmdName, CMD_LINGER_EXPIRED);
             long wakeupTime = SystemClock.elapsedRealtime() + mLingerDelayMs;
             mWakeupMessage.schedule(wakeupTime);
         }
@@ -823,4 +823,9 @@
         }
         DEFAULT_LINGER_DELAY_MS = time_ms;
     }
+
+    @VisibleForTesting
+    protected WakeupMessage makeWakeupMessage(Context c, Handler h, String s, int i) {
+        return new WakeupMessage(c, h, s, i);
+    }
 }
diff --git a/services/core/java/com/android/server/connectivity/PermissionMonitor.java b/services/core/java/com/android/server/connectivity/PermissionMonitor.java
index debda14..22cefd1 100644
--- a/services/core/java/com/android/server/connectivity/PermissionMonitor.java
+++ b/services/core/java/com/android/server/connectivity/PermissionMonitor.java
@@ -54,7 +54,7 @@
  */
 public class PermissionMonitor {
     private static final String TAG = "PermissionMonitor";
-    private static final boolean DBG = true;
+    private static final boolean DBG = false;
     private static final boolean SYSTEM = true;
     private static final boolean NETWORK = false;
 
diff --git a/services/core/java/com/android/server/connectivity/Tethering.java b/services/core/java/com/android/server/connectivity/Tethering.java
index 760b218..4eecc81 100644
--- a/services/core/java/com/android/server/connectivity/Tethering.java
+++ b/services/core/java/com/android/server/connectivity/Tethering.java
@@ -90,7 +90,7 @@
 
     private Context mContext;
     private final static String TAG = "Tethering";
-    private final static boolean DBG = true;
+    private final static boolean DBG = false;
     private final static boolean VDBG = false;
 
     // TODO - remove both of these - should be part of interface inspection/selection stuff
diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java
index f231f92..3b0b79a 100644
--- a/services/core/java/com/android/server/connectivity/Vpn.java
+++ b/services/core/java/com/android/server/connectivity/Vpn.java
@@ -718,7 +718,8 @@
     public void onUserAdded(int userHandle) {
         // If the user is restricted tie them to the parent user's VPN
         UserInfo user = UserManager.get(mContext).getUserInfo(userHandle);
-        if (user.isRestricted() && user.restrictedProfileParentId == mUserHandle) {
+        if (user.isRestricted() && user.restrictedProfileParentId == mUserHandle
+                && mVpnUsers != null) {
             synchronized(Vpn.this) {
                 try {
                     addVpnUserLocked(userHandle);
@@ -736,7 +737,8 @@
     public void onUserRemoved(int userHandle) {
         // clean up if restricted
         UserInfo user = UserManager.get(mContext).getUserInfo(userHandle);
-        if (user.isRestricted() && user.restrictedProfileParentId == mUserHandle) {
+        if (user.isRestricted() && user.restrictedProfileParentId == mUserHandle
+                && mVpnUsers != null) {
             synchronized(Vpn.this) {
                 try {
                     removeVpnUserLocked(userHandle);
diff --git a/services/core/java/com/android/server/content/SyncManager.java b/services/core/java/com/android/server/content/SyncManager.java
index 95a9875..e1d208e 100644
--- a/services/core/java/com/android/server/content/SyncManager.java
+++ b/services/core/java/com/android/server/content/SyncManager.java
@@ -192,6 +192,13 @@
      */
     private static final long SYNC_DELAY_ON_CONFLICT = 10*1000; // 10 seconds
 
+    /**
+     * Generate job ids in the range [MIN_SYNC_JOB_ID, MAX_SYNC_JOB_ID) to avoid conflicts with
+     * other jobs scheduled by the system process.
+     */
+    private static final int MIN_SYNC_JOB_ID = 100000;
+    private static final int MAX_SYNC_JOB_ID = 110000;
+
     private static final String SYNC_WAKE_LOCK_PREFIX = "*sync*/";
     private static final String HANDLE_SYNC_ALARM_WAKE_LOCK = "SyncManagerHandleSyncAlarm";
     private static final String SYNC_LOOP_WAKE_LOCK = "SyncLoopWakeLock";
@@ -249,7 +256,7 @@
         synchronized (mScheduledSyncs) {
             int newJobId;
             do {
-                newJobId = mRand.nextInt(Integer.MAX_VALUE);
+                newJobId = MIN_SYNC_JOB_ID + mRand.nextInt(MAX_SYNC_JOB_ID - MIN_SYNC_JOB_ID);
             } while (isJobIdInUseLockedH(newJobId));
             return newJobId;
         }
diff --git a/services/core/java/com/android/server/fingerprint/FingerprintService.java b/services/core/java/com/android/server/fingerprint/FingerprintService.java
index 5d81dae..7b134ca 100644
--- a/services/core/java/com/android/server/fingerprint/FingerprintService.java
+++ b/services/core/java/com/android/server/fingerprint/FingerprintService.java
@@ -905,13 +905,15 @@
 
             // Group ID is arbitrarily set to parent profile user ID. It just represents
             // the default fingerprints for the user.
-            final int effectiveGroupId = getEffectiveUserId(groupId);
+            if (!isCurrentUserOrProfile(groupId)) {
+                return;
+            }
 
             final boolean restricted = isRestricted();
             mHandler.post(new Runnable() {
                 @Override
                 public void run() {
-                    startEnrollment(token, cryptoClone, effectiveGroupId, receiver, flags, restricted);
+                    startEnrollment(token, cryptoClone, groupId, receiver, flags, restricted);
                 }
             });
         }
@@ -1011,15 +1013,14 @@
         @Override // Binder call
         public void rename(final int fingerId, final int groupId, final String name) {
             checkPermission(MANAGE_FINGERPRINT);
-
-            // Group ID is arbitrarily set to parent profile user ID. It just represents
-            // the default fingerprints for the user.
-            final int effectiveGroupId = getEffectiveUserId(groupId);
+            if (!isCurrentUserOrProfile(groupId)) {
+                return;
+            }
             mHandler.post(new Runnable() {
                 @Override
                 public void run() {
                     mFingerprintUtils.renameFingerprintForUser(mContext, fingerId,
-                            effectiveGroupId, name);
+                            groupId, name);
                 }
             });
         }
@@ -1029,9 +1030,11 @@
             if (!canUseFingerprint(opPackageName, false /* foregroundOnly */)) {
                 return Collections.emptyList();
             }
-            int effectiveUserId = getEffectiveUserId(userId);
+            if (!isCurrentUserOrProfile(userId)) {
+                return Collections.emptyList();
+            }
 
-            return FingerprintService.this.getEnrolledFingerprints(effectiveUserId);
+            return FingerprintService.this.getEnrolledFingerprints(userId);
         }
 
         @Override // Binder call
@@ -1040,8 +1043,10 @@
                 return false;
             }
 
-            int effectiveUserId  = getEffectiveUserId(userId);
-            return FingerprintService.this.hasEnrolledFingerprints(effectiveUserId);
+            if (!isCurrentUserOrProfile(userId)) {
+                return false;
+            }
+            return FingerprintService.this.hasEnrolledFingerprints(userId);
         }
 
         @Override // Binder call
diff --git a/services/core/java/com/android/server/job/JobSchedulerService.java b/services/core/java/com/android/server/job/JobSchedulerService.java
index 4bf77d3..d2b77aa 100644
--- a/services/core/java/com/android/server/job/JobSchedulerService.java
+++ b/services/core/java/com/android/server/job/JobSchedulerService.java
@@ -47,15 +47,18 @@
 import android.os.Message;
 import android.os.PowerManager;
 import android.os.RemoteException;
+import android.os.ResultReceiver;
 import android.os.ServiceManager;
 import android.os.SystemClock;
 import android.os.UserHandle;
 import android.util.Slog;
 import android.util.SparseArray;
+import android.util.SparseIntArray;
+import android.util.TimeUtils;
 
-import android.util.SparseBooleanArray;
 import com.android.internal.app.IBatteryStats;
 import com.android.internal.util.ArrayUtils;
+import com.android.internal.app.ProcessStats;
 import com.android.server.DeviceIdleController;
 import com.android.server.LocalServices;
 import com.android.server.job.JobStore.JobStatusFunctor;
@@ -87,11 +90,10 @@
     static final String TAG = "JobSchedulerService";
     public static final boolean DEBUG = false;
 
-    /** The number of concurrent jobs we run at one time. */
-    private static final int MAX_JOB_CONTEXTS_COUNT
-            = ActivityManager.isLowRamDeviceStatic() ? 3 : 6;
+    /** The maximum number of concurrent jobs we run at one time. */
+    private static final int MAX_JOB_CONTEXTS_COUNT = 8;
     /** Enforce a per-app limit on scheduled jobs? */
-    private static final boolean ENFORCE_MAX_JOBS = false;
+    private static final boolean ENFORCE_MAX_JOBS = true;
     /** The maximum number of jobs that we allow an unprivileged app to schedule */
     private static final int MAX_JOBS_PER_APP = 100;
 
@@ -171,9 +173,33 @@
     boolean mReportedActive;
 
     /**
+     * Current limit on the number of concurrent JobServiceContext entries we want to
+     * keep actively running a job.
+     */
+    int mMaxActiveJobs = MAX_JOB_CONTEXTS_COUNT - 2;
+
+    /**
      * Which uids are currently in the foreground.
      */
-    final SparseBooleanArray mForegroundUids = new SparseBooleanArray();
+    final SparseIntArray mUidPriorityOverride = new SparseIntArray();
+
+    // -- Pre-allocated temporaries only for use in assignJobsToContextsLocked --
+
+    /**
+     * This array essentially stores the state of mActiveServices array.
+     * The ith index stores the job present on the ith JobServiceContext.
+     * We manipulate this array until we arrive at what jobs should be running on
+     * what JobServiceContext.
+     */
+    JobStatus[] mTmpAssignContextIdToJobMap = new JobStatus[MAX_JOB_CONTEXTS_COUNT];
+    /**
+     * Indicates whether we need to act on this jobContext id
+     */
+    boolean[] mTmpAssignAct = new boolean[MAX_JOB_CONTEXTS_COUNT];
+    /**
+     * The uid whose jobs we would like to assign to a context.
+     */
+    int[] mTmpAssignPreferredUidForContext = new int[MAX_JOB_CONTEXTS_COUNT];
 
     /**
      * Cleans up outstanding jobs when a package is removed. Even if it's being replaced later we
@@ -376,19 +402,15 @@
 
     void updateUidState(int uid, int procState) {
         synchronized (mLock) {
-            boolean foreground = procState <= ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE;
-            boolean changed = false;
-            if (foreground) {
-                if (!mForegroundUids.get(uid)) {
-                    changed = true;
-                    mForegroundUids.put(uid, true);
-                }
+            if (procState == ActivityManager.PROCESS_STATE_TOP) {
+                // Only use this if we are exactly the top app.  All others can live
+                // with just the foreground priority.  This means that persistent processes
+                // can never be the top app priority...  that is fine.
+                mUidPriorityOverride.put(uid, JobInfo.PRIORITY_TOP_APP);
+            } else if (procState <= ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE) {
+                mUidPriorityOverride.put(uid, JobInfo.PRIORITY_FOREGROUND_APP);
             } else {
-                int index = mForegroundUids.indexOfKey(uid);
-                if (index >= 0) {
-                    mForegroundUids.removeAt(index);
-                    changed = true;
-                }
+                mUidPriorityOverride.delete(uid);
             }
         }
     }
@@ -1007,8 +1029,9 @@
         if (priority >= JobInfo.PRIORITY_FOREGROUND_APP) {
             return priority;
         }
-        if (mForegroundUids.get(job.getSourceUid())) {
-            return JobInfo.PRIORITY_FOREGROUND_APP;
+        int override = mUidPriorityOverride.get(job.getSourceUid(), 0);
+        if (override != 0) {
+            return override;
         }
         return priority;
     }
@@ -1024,24 +1047,44 @@
             Slog.d(TAG, printPendingQueue());
         }
 
-        // This array essentially stores the state of mActiveServices array.
-        // ith index stores the job present on the ith JobServiceContext.
-        // We manipulate this array until we arrive at what jobs should be running on
-        // what JobServiceContext.
-        JobStatus[] contextIdToJobMap = new JobStatus[MAX_JOB_CONTEXTS_COUNT];
-        // Indicates whether we need to act on this jobContext id
-        boolean[] act = new boolean[MAX_JOB_CONTEXTS_COUNT];
-        int[] preferredUidForContext = new int[MAX_JOB_CONTEXTS_COUNT];
-        for (int i=0; i<mActiveServices.size(); i++) {
-            contextIdToJobMap[i] = mActiveServices.get(i).getRunningJob();
-            preferredUidForContext[i] = mActiveServices.get(i).getPreferredUid();
+        int memLevel;
+        try {
+            memLevel = ActivityManagerNative.getDefault().getMemoryTrimLevel();
+        } catch (RemoteException e) {
+            memLevel = ProcessStats.ADJ_MEM_FACTOR_NORMAL;
+        }
+        switch (memLevel) {
+            case ProcessStats.ADJ_MEM_FACTOR_MODERATE:
+                mMaxActiveJobs = ((MAX_JOB_CONTEXTS_COUNT - 2) * 2) / 3;
+                break;
+            case ProcessStats.ADJ_MEM_FACTOR_LOW:
+                mMaxActiveJobs = (MAX_JOB_CONTEXTS_COUNT - 2) / 3;
+                break;
+            case ProcessStats.ADJ_MEM_FACTOR_CRITICAL:
+                mMaxActiveJobs = 1;
+                break;
+            default:
+                mMaxActiveJobs = MAX_JOB_CONTEXTS_COUNT - 2;
+                break;
+        }
+
+        JobStatus[] contextIdToJobMap = mTmpAssignContextIdToJobMap;
+        boolean[] act = mTmpAssignAct;
+        int[] preferredUidForContext = mTmpAssignPreferredUidForContext;
+        int numActive = 0;
+        for (int i=0; i<MAX_JOB_CONTEXTS_COUNT; i++) {
+            final JobServiceContext js = mActiveServices.get(i);
+            if ((contextIdToJobMap[i] = js.getRunningJob()) != null) {
+                numActive++;
+            }
+            act[i] = false;
+            preferredUidForContext[i] = js.getPreferredUid();
         }
         if (DEBUG) {
             Slog.d(TAG, printContextIdToJobMap(contextIdToJobMap, "running jobs initial"));
         }
-        Iterator<JobStatus> it = mPendingJobs.iterator();
-        while (it.hasNext()) {
-            JobStatus nextPending = it.next();
+        for (int i=0; i<mPendingJobs.size(); i++) {
+            JobStatus nextPending = mPendingJobs.get(i);
 
             // If job is already running, go to next job.
             int jobRunningContext = findJobContextIdFromMap(nextPending, contextIdToJobMap);
@@ -1049,24 +1092,30 @@
                 continue;
             }
 
-            nextPending.lastEvaluatedPriority = evaluateJobPriorityLocked(nextPending);
+            final int priority = evaluateJobPriorityLocked(nextPending);
+            nextPending.lastEvaluatedPriority = priority;
 
             // Find a context for nextPending. The context should be available OR
             // it should have lowest priority among all running jobs
             // (sharing the same Uid as nextPending)
             int minPriority = Integer.MAX_VALUE;
             int minPriorityContextId = -1;
-            for (int i=0; i<mActiveServices.size(); i++) {
-                JobStatus job = contextIdToJobMap[i];
-                int preferredUid = preferredUidForContext[i];
-                if (job == null && (preferredUid == nextPending.getUid() ||
-                        preferredUid == JobServiceContext.NO_PREFERRED_UID) ) {
-                    minPriorityContextId = i;
-                    break;
-                }
+            for (int j=0; j<MAX_JOB_CONTEXTS_COUNT; j++) {
+                JobStatus job = contextIdToJobMap[j];
+                int preferredUid = preferredUidForContext[j];
                 if (job == null) {
+                    if ((numActive < mMaxActiveJobs || priority >= JobInfo.PRIORITY_TOP_APP) &&
+                            (preferredUid == nextPending.getUid() ||
+                                    preferredUid == JobServiceContext.NO_PREFERRED_UID)) {
+                        // This slot is free, and we haven't yet hit the limit on
+                        // concurrent jobs...  we can just throw the job in to here.
+                        minPriorityContextId = j;
+                        numActive++;
+                        break;
+                    }
                     // No job on this context, but nextPending can't run here because
-                    // the context has a preferred Uid.
+                    // the context has a preferred Uid or we have reached the limit on
+                    // concurrent jobs.
                     continue;
                 }
                 if (job.getUid() != nextPending.getUid()) {
@@ -1077,7 +1126,7 @@
                 }
                 if (minPriority > nextPending.lastEvaluatedPriority) {
                     minPriority = nextPending.lastEvaluatedPriority;
-                    minPriorityContextId = i;
+                    minPriorityContextId = j;
                 }
             }
             if (minPriorityContextId != -1) {
@@ -1088,7 +1137,7 @@
         if (DEBUG) {
             Slog.d(TAG, printContextIdToJobMap(contextIdToJobMap, "running jobs final"));
         }
-        for (int i=0; i<mActiveServices.size(); i++) {
+        for (int i=0; i<MAX_JOB_CONTEXTS_COUNT; i++) {
             boolean preservePreferredUid = false;
             if (act[i]) {
                 JobStatus js = mActiveServices.get(i).getRunningJob();
@@ -1289,8 +1338,48 @@
                 Binder.restoreCallingIdentity(identityToken);
             }
         }
+
+        @Override
+        public void onShellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err,
+                String[] args, ResultReceiver resultReceiver) throws RemoteException {
+                (new JobSchedulerShellCommand(JobSchedulerService.this)).exec(
+                        this, in, out, err, args, resultReceiver);
+        }
     };
 
+    // Shell command infrastructure: run the given job immediately
+    int executeRunCommand(String pkgName, int userId, int jobId, boolean force) {
+        if (DEBUG) {
+            Slog.v(TAG, "executeRunCommand(): " + pkgName + "/" + userId
+                    + " " + jobId + " f=" + force);
+        }
+
+        try {
+            final int uid = AppGlobals.getPackageManager().getPackageUid(pkgName, 0, userId);
+            if (uid < 0) {
+                return JobSchedulerShellCommand.CMD_ERR_NO_PACKAGE;
+            }
+
+            synchronized (mLock) {
+                final JobStatus js = mJobs.getJobByUidAndJobId(uid, jobId);
+                if (js == null) {
+                    return JobSchedulerShellCommand.CMD_ERR_NO_JOB;
+                }
+
+                js.overrideState = (force) ? JobStatus.OVERRIDE_FULL : JobStatus.OVERRIDE_SOFT;
+                if (!js.isConstraintsSatisfied()) {
+                    js.overrideState = 0;
+                    return JobSchedulerShellCommand.CMD_ERR_CONSTRAINTS;
+                }
+
+                mHandler.obtainMessage(MSG_CHECK_JOB_GREEDY).sendToTarget();
+            }
+        } catch (RemoteException e) {
+            // can't happen
+        }
+        return 0;
+    }
+
     private String printContextIdToJobMap(JobStatus[] map, String initial) {
         StringBuilder s = new StringBuilder(initial + ": ");
         for (int i=0; i<map.length; i++) {
@@ -1329,7 +1418,7 @@
                     public void process(JobStatus job) {
                         pw.print("  Job #"); pw.print(index++); pw.print(": ");
                         pw.println(job.toShortString());
-                        job.dump(pw, "    ");
+                        job.dump(pw, "    ", true);
                         pw.print("    Ready: ");
                         pw.print(mHandler.isReadyToBeExecutedLocked(job));
                         pw.print(" (job=");
@@ -1351,9 +1440,10 @@
                 mControllers.get(i).dumpControllerStateLocked(pw);
             }
             pw.println();
-            pw.println("Foreground uids:");
-            for (int i=0; i<mForegroundUids.size(); i++) {
-                pw.print("  "); pw.println(UserHandle.formatUid(mForegroundUids.keyAt(i)));
+            pw.println("Uid priority overrides:");
+            for (int i=0; i< mUidPriorityOverride.size(); i++) {
+                pw.print("  "); pw.print(UserHandle.formatUid(mUidPriorityOverride.keyAt(i)));
+                pw.print(": "); pw.println(mUidPriorityOverride.valueAt(i));
             }
             pw.println();
             pw.println("Pending queue:");
@@ -1361,6 +1451,7 @@
                 JobStatus job = mPendingJobs.get(i);
                 pw.print("  Pending #"); pw.print(i); pw.print(": ");
                 pw.println(job.toShortString());
+                job.dump(pw, "    ", false);
                 int priority = evaluateJobPriorityLocked(job);
                 if (priority != JobInfo.PRIORITY_DEFAULT) {
                     pw.print("    Evaluated priority: "); pw.println(priority);
@@ -1371,20 +1462,21 @@
             pw.println("Active jobs:");
             for (int i=0; i<mActiveServices.size(); i++) {
                 JobServiceContext jsc = mActiveServices.get(i);
+                pw.print("  Slot #"); pw.print(i); pw.print(": ");
                 if (jsc.getRunningJob() == null) {
+                    pw.println("inactive");
                     continue;
                 } else {
-                    final long timeout = jsc.getTimeoutElapsed();
-                    pw.print("Running for: ");
-                    pw.print((now - jsc.getExecutionStartTimeElapsed())/1000);
-                    pw.print("s timeout=");
-                    pw.print(timeout);
-                    pw.print(" fromnow=");
-                    pw.println(timeout-now);
-                    jsc.getRunningJob().dump(pw, "  ");
+                    pw.println(jsc.getRunningJob().toShortString());
+                    pw.print("    Running for: ");
+                    TimeUtils.formatDuration(now - jsc.getExecutionStartTimeElapsed(), pw);
+                    pw.print(", timeout at: ");
+                    TimeUtils.formatDuration(jsc.getTimeoutElapsed() - now, pw);
+                    pw.println();
+                    jsc.getRunningJob().dump(pw, "    ", false);
                     int priority = evaluateJobPriorityLocked(jsc.getRunningJob());
                     if (priority != JobInfo.PRIORITY_DEFAULT) {
-                        pw.print("  Evaluated priority: "); pw.println(priority);
+                        pw.print("    Evaluated priority: "); pw.println(priority);
                     }
                 }
             }
@@ -1392,6 +1484,7 @@
             pw.print("mReadyToRock="); pw.println(mReadyToRock);
             pw.print("mDeviceIdleMode="); pw.println(mDeviceIdleMode);
             pw.print("mReportedActive="); pw.println(mReportedActive);
+            pw.print("mMaxActiveJobs="); pw.println(mMaxActiveJobs);
         }
         pw.println();
     }
diff --git a/services/core/java/com/android/server/job/JobSchedulerShellCommand.java b/services/core/java/com/android/server/job/JobSchedulerShellCommand.java
new file mode 100644
index 0000000..2d62c1c
--- /dev/null
+++ b/services/core/java/com/android/server/job/JobSchedulerShellCommand.java
@@ -0,0 +1,154 @@
+/*
+ * 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.job;
+
+import android.app.AppGlobals;
+import android.content.pm.IPackageManager;
+import android.content.pm.PackageManager;
+import android.os.Binder;
+import android.os.RemoteException;
+import android.os.ShellCommand;
+import android.os.UserHandle;
+
+import java.io.PrintWriter;
+
+public class JobSchedulerShellCommand extends ShellCommand {
+    public static final int CMD_ERR_NO_PACKAGE = -1000;
+    public static final int CMD_ERR_NO_JOB = -1001;
+    public static final int CMD_ERR_CONSTRAINTS = -1002;
+
+    JobSchedulerService mInternal;
+    IPackageManager mPM;
+
+    JobSchedulerShellCommand(JobSchedulerService service) {
+        mInternal = service;
+        mPM = AppGlobals.getPackageManager();
+    }
+
+    @Override
+    public int onCommand(String cmd) {
+        final PrintWriter pw = getOutPrintWriter();
+        try {
+            if ("run".equals(cmd)) {
+                return runJob();
+            } else {
+                return handleDefaultCommands(cmd);
+            }
+        } catch (Exception e) {
+            pw.println("Exception: " + e);
+        }
+        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
+        }
+
+        final PrintWriter pw = getOutPrintWriter();
+        boolean force = false;
+        int userId = UserHandle.USER_SYSTEM;
+
+        String opt;
+        while ((opt = getNextOption()) != null) {
+            switch (opt) {
+                case "-f":
+                case "--force":
+                    force = true;
+                    break;
+
+                case "-u":
+                case "--user":
+                    userId = Integer.parseInt(getNextArgRequired());
+                    break;
+
+                default:
+                    pw.println("Error: unknown option '" + opt + "'");
+                    return -1;
+            }
+        }
+
+        final String pkgName = getNextArgRequired();
+        final int jobId = Integer.parseInt(getNextArgRequired());
+
+        int ret = mInternal.executeRunCommand(pkgName, userId, jobId, force);
+        switch (ret) {
+            case CMD_ERR_NO_PACKAGE:
+                pw.print("Package not found: ");
+                pw.print(pkgName);
+                pw.print(" / user ");
+                pw.println(userId);
+                break;
+
+            case CMD_ERR_NO_JOB:
+                pw.print("Could not find job ");
+                pw.print(jobId);
+                pw.print(" in package ");
+                pw.print(pkgName);
+                pw.print(" / user ");
+                pw.println(userId);
+                break;
+
+            case CMD_ERR_CONSTRAINTS:
+                pw.print("Job ");
+                pw.print(jobId);
+                pw.print(" in package ");
+                pw.print(pkgName);
+                pw.print(" / user ");
+                pw.print(userId);
+                pw.println(" has functional constraints but --force not specified");
+                break;
+
+            default:
+                // success!
+                pw.print("Running job");
+                if (force) {
+                    pw.print(" [FORCED]");
+                }
+                pw.println();
+                break;
+        }
+        return ret;
+    }
+
+    @Override
+    public void onHelp() {
+        final PrintWriter pw = getOutPrintWriter();
+
+        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:");
+        pw.println("      -f or --force: run the job even if technical constraints such as");
+        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();
+    }
+
+}
diff --git a/services/core/java/com/android/server/job/JobStore.java b/services/core/java/com/android/server/job/JobStore.java
index 4268dab..9837a56 100644
--- a/services/core/java/com/android/server/job/JobStore.java
+++ b/services/core/java/com/android/server/job/JobStore.java
@@ -543,7 +543,7 @@
                 return null;
             }
 
-            final String sourcePackageName = parser.getAttributeValue(null, "sourcePackageName");
+            String sourcePackageName = parser.getAttributeValue(null, "sourcePackageName");
 
             final String sourceTag = parser.getAttributeValue(null, "sourceTag");
 
@@ -660,6 +660,18 @@
             jobBuilder.setExtras(extras);
             parser.nextTag(); // Consume </extras>
 
+            // Migrate sync jobs forward from earlier, incomplete representation
+            if ("android".equals(sourcePackageName)
+                    && extras != null
+                    && extras.getBoolean("SyncManagerJob", false)) {
+                sourcePackageName = extras.getString("owningPackage", sourcePackageName);
+                if (DEBUG) {
+                    Slog.i(TAG, "Fixing up sync job source package name from 'android' to '"
+                            + sourcePackageName + "'");
+                }
+            }
+
+            // And now we're done
             JobStatus js = new JobStatus(
                     jobBuilder.build(), uid, sourcePackageName, sourceUserId, sourceTag,
                     elapsedRuntimes.first, elapsedRuntimes.second);
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 e6fbc39..4a2c88c 100644
--- a/services/core/java/com/android/server/job/controllers/JobStatus.java
+++ b/services/core/java/com/android/server/job/controllers/JobStatus.java
@@ -55,6 +55,11 @@
     static final int CONSTRAINT_APP_NOT_IDLE = 1<<6;
     static final int CONSTRAINT_CONTENT_TRIGGER = 1<<7;
 
+    // Soft override: ignore constraints like time that don't affect API availability
+    public static final int OVERRIDE_SOFT = 1;
+    // Full override: ignore all constraints including API-affecting like connectivity
+    public static final int OVERRIDE_FULL = 2;
+
     final JobInfo job;
     /** Uid of the package requesting this job. */
     final int callingUid;
@@ -91,6 +96,9 @@
 
     public int lastEvaluatedPriority;
 
+    // Used by shell commands
+    public int overrideState = 0;
+
     /**
      * For use only by ContentObserverController: state it is maintaining about content URIs
      * being observed.
@@ -134,6 +142,10 @@
             sb.append(job.getService().getPackageName());
             sb.append('/');
             sb.append(this.sourceTag);
+            if (sourcePackageName != null) {
+                sb.append('/');
+                sb.append(this.sourcePackageName);
+            }
             this.batteryName = sb.toString();
         } else {
             this.batteryName = job.getService().flattenToShortString();
@@ -366,7 +378,7 @@
      */
     public boolean isReady() {
         // Deadline constraint trumps other constraints (except for periodic jobs where deadline
-        // (is an implementation detail. A periodic job should only run if it's constraints are
+        // is an implementation detail. A periodic job should only run if its constraints are
         // satisfied).
         // AppNotIdle implicit constraint trumps all!
         return (isConstraintsSatisfied()
@@ -380,12 +392,27 @@
             CONSTRAINT_CONNECTIVITY | CONSTRAINT_UNMETERED |
             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;
+
     /**
      * @return Whether the constraints set on this job are satisfied.
      */
     public boolean isConstraintsSatisfied() {
+        if (overrideState == OVERRIDE_FULL) {
+            // force override: the job is always runnable
+            return true;
+        }
+
         final int req = requiredConstraints & CONSTRAINTS_OF_INTEREST;
-        final int sat = satisfiedConstraints & CONSTRAINTS_OF_INTEREST;
+
+        int sat = satisfiedConstraints & CONSTRAINTS_OF_INTEREST;
+        if (overrideState == OVERRIDE_SOFT) {
+            // override: pretend all 'soft' requirements are satisfied
+            sat |= (requiredConstraints & SOFT_OVERRIDE_CONSTRAINTS);
+        }
+
         return (sat & req) == req;
     }
 
@@ -433,10 +460,10 @@
         sb.append(Integer.toHexString(System.identityHashCode(this)));
         sb.append(" jId=");
         sb.append(job.getId());
-        sb.append(" uid=");
+        sb.append(' ');
         UserHandle.formatUid(sb, callingUid);
         sb.append(' ');
-        sb.append(job.getService().flattenToShortString());
+        sb.append(batteryName);
         return sb.toString();
     }
 
@@ -468,75 +495,71 @@
     }
 
     // Dumpsys infrastructure
-    public void dump(PrintWriter pw, String prefix) {
+    public void dump(PrintWriter pw, String prefix, boolean full) {
         pw.print(prefix); UserHandle.formatUid(pw, callingUid);
         pw.print(" tag="); pw.println(tag);
         pw.print(prefix);
         pw.print("Source: uid="); UserHandle.formatUid(pw, getSourceUid());
         pw.print(" user="); pw.print(getSourceUserId());
         pw.print(" pkg="); pw.println(getSourcePackageName());
-        pw.print(prefix); pw.println("JobInfo:");
-        pw.print(prefix); pw.print("  Service: ");
-        pw.println(job.getService().flattenToShortString());
-        if (job.isPeriodic()) {
-            pw.print(prefix); pw.print("  PERIODIC: interval=");
-            TimeUtils.formatDuration(job.getIntervalMillis(), pw);
-            pw.print(" flex=");
-            TimeUtils.formatDuration(job.getFlexMillis(), pw);
-            pw.println();
-        }
-        if (job.isPersisted()) {
-            pw.print(prefix); pw.println("  PERSISTED");
-        }
-        if (job.getPriority() != 0) {
-            pw.print(prefix); pw.print("  Priority: ");
-            pw.println(job.getPriority());
-        }
-        pw.print(prefix); pw.print("  Requires: charging=");
-        pw.print(job.isRequireCharging());
-        pw.print(" deviceIdle=");
-        pw.println(job.isRequireDeviceIdle());
-        if (job.getTriggerContentUris() != null) {
-            pw.print(prefix); pw.println("  Trigger content URIs:");
-            for (int i=0; i<job.getTriggerContentUris().length; i++) {
-                JobInfo.TriggerContentUri trig = job.getTriggerContentUris()[i];
-                pw.print(prefix); pw.print("    ");
-                pw.print(Integer.toHexString(trig.getFlags()));
-                pw.print(' ' );
-                pw.println(trig.getUri());
+        if (full) {
+            pw.print(prefix); pw.println("JobInfo:"); pw.print(prefix);
+            pw.print("  Service: "); pw.println(job.getService().flattenToShortString());
+            if (job.isPeriodic()) {
+                pw.print(prefix); pw.print("  PERIODIC: interval=");
+                TimeUtils.formatDuration(job.getIntervalMillis(), pw);
+                pw.print(" flex="); TimeUtils.formatDuration(job.getFlexMillis(), pw);
+                pw.println();
             }
-        }
-        if (job.getNetworkType() != JobInfo.NETWORK_TYPE_NONE) {
-            pw.print(prefix); pw.print("  Network type: ");
-            pw.println(job.getNetworkType());
-        }
-        if (job.getMinLatencyMillis() != 0) {
-            pw.print(prefix); pw.print("  Minimum latency: ");
-            TimeUtils.formatDuration(job.getMinLatencyMillis(), pw);
+            if (job.isPersisted()) {
+                pw.print(prefix); pw.println("  PERSISTED");
+            }
+            if (job.getPriority() != 0) {
+                pw.print(prefix); pw.print("  Priority: "); pw.println(job.getPriority());
+            }
+            pw.print(prefix); pw.print("  Requires: charging=");
+            pw.print(job.isRequireCharging()); pw.print(" deviceIdle=");
+            pw.println(job.isRequireDeviceIdle());
+            if (job.getTriggerContentUris() != null) {
+                pw.print(prefix); pw.println("  Trigger content URIs:");
+                for (int i = 0; i < job.getTriggerContentUris().length; i++) {
+                    JobInfo.TriggerContentUri trig = job.getTriggerContentUris()[i];
+                    pw.print(prefix); pw.print("    ");
+                    pw.print(Integer.toHexString(trig.getFlags()));
+                    pw.print(' '); pw.println(trig.getUri());
+                }
+            }
+            if (job.getNetworkType() != JobInfo.NETWORK_TYPE_NONE) {
+                pw.print(prefix); pw.print("  Network type: "); pw.println(job.getNetworkType());
+            }
+            if (job.getMinLatencyMillis() != 0) {
+                pw.print(prefix); pw.print("  Minimum latency: ");
+                TimeUtils.formatDuration(job.getMinLatencyMillis(), pw);
+                pw.println();
+            }
+            if (job.getMaxExecutionDelayMillis() != 0) {
+                pw.print(prefix); pw.print("  Max execution delay: ");
+                TimeUtils.formatDuration(job.getMaxExecutionDelayMillis(), pw);
+                pw.println();
+            }
+            pw.print(prefix); pw.print("  Backoff: policy="); pw.print(job.getBackoffPolicy());
+            pw.print(" initial="); TimeUtils.formatDuration(job.getInitialBackoffMillis(), pw);
             pw.println();
-        }
-        if (job.getMaxExecutionDelayMillis() != 0) {
-            pw.print(prefix); pw.print("  Max execution delay: ");
-            TimeUtils.formatDuration(job.getMaxExecutionDelayMillis(), pw);
-            pw.println();
-        }
-        pw.print(prefix); pw.print("  Backoff: policy=");
-        pw.print(job.getBackoffPolicy());
-        pw.print(" initial=");
-        TimeUtils.formatDuration(job.getInitialBackoffMillis(), pw);
-        pw.println();
-        if (job.hasEarlyConstraint()) {
-            pw.print(prefix); pw.println("  Has early constraint");
-        }
-        if (job.hasLateConstraint()) {
-            pw.print(prefix); pw.println("  Has late constraint");
+            if (job.hasEarlyConstraint()) {
+                pw.print(prefix); pw.println("  Has early constraint");
+            }
+            if (job.hasLateConstraint()) {
+                pw.print(prefix); pw.println("  Has late constraint");
+            }
         }
         pw.print(prefix); pw.print("Required constraints:");
         dumpConstraints(pw, requiredConstraints);
         pw.println();
-        pw.print(prefix); pw.print("Satisfied constraints:");
-        dumpConstraints(pw, satisfiedConstraints);
-        pw.println();
+        if (full) {
+            pw.print(prefix); pw.print("Satisfied constraints:");
+            dumpConstraints(pw, satisfiedConstraints);
+            pw.println();
+        }
         if (changedAuthorities != null) {
             pw.print(prefix); pw.println("Changed authorities:");
             for (int i=0; i<changedAuthorities.size(); i++) {
diff --git a/services/core/java/com/android/server/location/GnssLocationProvider.java b/services/core/java/com/android/server/location/GnssLocationProvider.java
index ed68abe..e08fad4 100644
--- a/services/core/java/com/android/server/location/GnssLocationProvider.java
+++ b/services/core/java/com/android/server/location/GnssLocationProvider.java
@@ -1559,11 +1559,11 @@
      * called from native code to update SV info
      */
     private void reportSvStatus() {
-        int svCount = native_read_sv_status(mSvidWithFlags, mSnrs, mSvElevations, mSvAzimuths);
+        int svCount = native_read_sv_status(mSvidWithFlags, mCn0s, mSvElevations, mSvAzimuths);
         mListenerHelper.onSvStatusChanged(
                 svCount,
                 mSvidWithFlags,
-                mSnrs,
+                mCn0s,
                 mSvElevations,
                 mSvAzimuths);
 
@@ -1578,7 +1578,7 @@
             }
             if (VERBOSE) {
                 Log.v(TAG, "svid: " + (mSvidWithFlags[i] >> GnssStatus.SVID_SHIFT_WIDTH) +
-                        " snr: " + mSnrs[i]/10 +
+                        " cn0: " + mCn0s[i]/10 +
                         " elev: " + mSvElevations[i] +
                         " azimuth: " + mSvAzimuths[i] +
                         ((mSvidWithFlags[i] & GnssStatus.GNSS_SV_FLAGS_HAS_EPHEMERIS_DATA) == 0
@@ -2402,7 +2402,7 @@
 
     // preallocated arrays, to avoid memory allocation in reportStatus()
     private int mSvidWithFlags[] = new int[MAX_SVS];
-    private float mSnrs[] = new float[MAX_SVS];
+    private float mCn0s[] = new float[MAX_SVS];
     private float mSvElevations[] = new float[MAX_SVS];
     private float mSvAzimuths[] = new float[MAX_SVS];
     private int mSvCount;
@@ -2424,7 +2424,7 @@
     private native void native_delete_aiding_data(int flags);
     // returns number of SVs
     // mask[0] is ephemeris mask and mask[1] is almanac mask
-    private native int native_read_sv_status(int[] prnWithFlags, float[] snrs, float[] elevations,
+    private native int native_read_sv_status(int[] prnWithFlags, float[] cn0s, float[] elevations,
             float[] azimuths);
     private native int native_read_nmea(byte[] buffer, int bufferSize);
     private native void native_inject_location(double latitude, double longitude, float accuracy);
diff --git a/services/core/java/com/android/server/location/GnssMeasurementsProvider.java b/services/core/java/com/android/server/location/GnssMeasurementsProvider.java
index d9e8e91..734a8d4 100644
--- a/services/core/java/com/android/server/location/GnssMeasurementsProvider.java
+++ b/services/core/java/com/android/server/location/GnssMeasurementsProvider.java
@@ -72,7 +72,7 @@
                 status = GnssMeasurementsEvent.STATUS_NOT_SUPPORTED;
                 break;
             case RESULT_GPS_LOCATION_DISABLED:
-                status = GnssMeasurementsEvent.STATUS_GPS_LOCATION_DISABLED;
+                status = GnssMeasurementsEvent.STATUS_GNSS_LOCATION_DISABLED;
                 break;
             case RESULT_UNKNOWN:
                 return null;
diff --git a/services/core/java/com/android/server/location/GnssNavigationMessageProvider.java b/services/core/java/com/android/server/location/GnssNavigationMessageProvider.java
index 57bce4b..fdef31f 100644
--- a/services/core/java/com/android/server/location/GnssNavigationMessageProvider.java
+++ b/services/core/java/com/android/server/location/GnssNavigationMessageProvider.java
@@ -73,7 +73,8 @@
                 status = GnssNavigationMessageEvent.STATUS_NOT_SUPPORTED;
                 break;
             case RESULT_GPS_LOCATION_DISABLED:
-                status = GnssNavigationMessageEvent.STATUS_GPS_LOCATION_DISABLED;
+                status = GnssNavigationMessageEvent
+                        .STATUS_GNSS_LOCATION_DISABLED;
                 break;
             case RESULT_UNKNOWN:
                 return null;
diff --git a/services/core/java/com/android/server/location/GnssStatusListenerHelper.java b/services/core/java/com/android/server/location/GnssStatusListenerHelper.java
index 0b3111c..d471e45 100644
--- a/services/core/java/com/android/server/location/GnssStatusListenerHelper.java
+++ b/services/core/java/com/android/server/location/GnssStatusListenerHelper.java
@@ -75,7 +75,7 @@
     public void onSvStatusChanged(
             final int svCount,
             final int[] prnWithFlags,
-            final float[] snrs,
+            final float[] cn0s,
             final float[] elevations,
             final float[] azimuths) {
         Operation operation = new Operation() {
@@ -84,7 +84,7 @@
                 listener.onSvStatusChanged(
                         svCount,
                         prnWithFlags,
-                        snrs,
+                        cn0s,
                         elevations,
                         azimuths);
             }
diff --git a/services/core/java/com/android/server/net/IpConfigStore.java b/services/core/java/com/android/server/net/IpConfigStore.java
index 9f1435a..2807ec8 100644
--- a/services/core/java/com/android/server/net/IpConfigStore.java
+++ b/services/core/java/com/android/server/net/IpConfigStore.java
@@ -40,7 +40,7 @@
 
 public class IpConfigStore {
     private static final String TAG = "IpConfigStore";
-    private static final boolean DBG = true;
+    private static final boolean DBG = false;
 
     protected final DelayedDiskWrite mWriter;
 
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index fc40f9f..3acd2ca 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -28,6 +28,7 @@
 import static android.content.Intent.ACTION_USER_ADDED;
 import static android.content.Intent.ACTION_USER_REMOVED;
 import static android.content.Intent.EXTRA_UID;
+
 import static android.net.ConnectivityManager.CONNECTIVITY_ACTION;
 import static android.net.ConnectivityManager.TYPE_MOBILE;
 import static android.net.ConnectivityManager.TYPE_WIMAX;
@@ -41,6 +42,7 @@
 import static android.net.NetworkPolicy.WARNING_DISABLED;
 import static android.net.NetworkPolicyManager.EXTRA_NETWORK_TEMPLATE;
 import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_DOZABLE;
+import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_POWERSAVE;
 import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_STANDBY;
 import static android.net.NetworkPolicyManager.FIREWALL_RULE_ALLOW;
 import static android.net.NetworkPolicyManager.FIREWALL_RULE_DEFAULT;
@@ -67,6 +69,7 @@
 import static android.net.wifi.WifiManager.EXTRA_WIFI_CONFIGURATION;
 import static android.net.wifi.WifiManager.EXTRA_WIFI_INFO;
 import static android.text.format.DateUtils.DAY_IN_MILLIS;
+
 import static com.android.internal.util.ArrayUtils.appendInt;
 import static com.android.internal.util.Preconditions.checkNotNull;
 import static com.android.internal.util.XmlUtils.readBooleanAttribute;
@@ -165,6 +168,7 @@
 import com.android.server.DeviceIdleController;
 import com.android.server.EventLogTags;
 import com.android.server.LocalServices;
+import com.android.server.SystemConfig;
 import com.google.android.collect.Lists;
 
 import org.xmlpull.v1.XmlPullParser;
@@ -221,6 +225,7 @@
     private static final String TAG_APP_POLICY = "app-policy";
     private static final String TAG_WHITELIST = "whitelist";
     private static final String TAG_RESTRICT_BACKGROUND = "restrict-background";
+    private static final String TAG_REVOKED_RESTRICT_BACKGROUND = "revoked-restrict-background";
 
     private static final String ATTR_VERSION = "version";
     private static final String ATTR_RESTRICT_BACKGROUND = "restrictBackground";
@@ -291,6 +296,7 @@
 
     final SparseIntArray mUidFirewallStandbyRules = new SparseIntArray();
     final SparseIntArray mUidFirewallDozableRules = new SparseIntArray();
+    final SparseIntArray mUidFirewallPowerSaveRules = new SparseIntArray();
 
     /** Set of states for the child firewall chains. True if the chain is active. */
     final SparseBooleanArray mFirewallChainStates = new SparseBooleanArray();
@@ -316,6 +322,19 @@
      */
     private final SparseBooleanArray mRestrictBackgroundWhitelistUids = new SparseBooleanArray();
 
+    /**
+     * UIDs that have been initially white-listed by system to avoid restricted background.
+     */
+    private final SparseBooleanArray mDefaultRestrictBackgroundWhitelistUids =
+            new SparseBooleanArray();
+
+    /**
+     * UIDs that have been initially white-listed by system to avoid restricted background,
+     * but later revoked by user.
+     */
+    private final SparseBooleanArray mRestrictBackgroundWhitelistRevokedUids =
+            new SparseBooleanArray();
+
     /** Set of ifaces that are metered. */
     private ArraySet<String> mMeteredIfaces = new ArraySet<>();
     /** Set of over-limit templates that have been notified. */
@@ -412,6 +431,53 @@
         }
     }
 
+    /**
+     * Whitelists pre-defined apps for restrict background, but only if the user didn't already
+     * revoke the whitelist.
+     *
+     * @return whether any uid has been added to {@link #mRestrictBackgroundWhitelistUids}.
+     */
+    boolean addDefaultRestrictBackgroundWhitelistUids() {
+        final SystemConfig sysConfig = SystemConfig.getInstance();
+        final PackageManager pm = mContext.getPackageManager();
+        final List<UserInfo> users = mUserManager.getUsers();
+        final int numberUsers = users.size();
+
+        final ArraySet<String> allowDataUsage = sysConfig.getAllowInDataUsageSave();
+        boolean changed = false;
+        for (int i = 0; i < allowDataUsage.size(); i++) {
+            final String pkg = allowDataUsage.valueAt(i);
+            if (LOGD)
+                Slog.d(TAG, "checking restricted background whitelisting for package " + pkg);
+            final ApplicationInfo app;
+            try {
+                app = pm.getApplicationInfo(pkg, PackageManager.MATCH_SYSTEM_ONLY);
+            } catch (PackageManager.NameNotFoundException e) {
+                // Should not happen
+                Slog.wtf(TAG, "No ApplicationInfo for package " + pkg);
+                continue;
+            }
+            if (!app.isPrivilegedApp()) {
+                Slog.w(TAG, "getAllowInDataUsageSave() returned non-privileged app: " + pkg);
+                continue;
+            }
+            for (int j = 0; j < numberUsers; j++) {
+                final UserInfo user = users.get(i);
+                final int uid = UserHandle.getUid(user.id, app.uid);
+                mDefaultRestrictBackgroundWhitelistUids.append(uid, true);
+                if (LOGD) Slog.d(TAG, "revoked whistelist status for uid " + uid + ": "
+                        + mRestrictBackgroundWhitelistRevokedUids.get(uid));
+                if (!mRestrictBackgroundWhitelistRevokedUids.get(uid)) {
+                    Slog.i(TAG, "adding default package " + pkg + " (uid " + uid + " for user "
+                            + user.id + ") to restrict background whitelist");
+                    mRestrictBackgroundWhitelistUids.append(uid, true);
+                    changed = true;
+                }
+            }
+        }
+        return changed;
+    }
+
     void updatePowerSaveTempWhitelistLocked() {
         try {
             // Clear the states of the current whitelist
@@ -459,9 +525,11 @@
                     new PowerManagerInternal.LowPowerModeListener() {
                 @Override
                 public void onLowPowerModeChanged(boolean enabled) {
+                    if (LOGD) Slog.d(TAG, "onLowPowerModeChanged(" + enabled + ")");
                     synchronized (mRulesLock) {
                         if (mRestrictPower != enabled) {
                             mRestrictPower = enabled;
+                            updateRulesForRestrictPowerLocked();
                             updateRulesForGlobalChangeLocked(true);
                         }
                     }
@@ -473,6 +541,10 @@
             // read policy from disk
             readPolicyLocked();
 
+            if (addDefaultRestrictBackgroundWhitelistUids()) {
+                writePolicyLocked();
+            }
+
             updateRulesForGlobalChangeLocked(false);
             updateNotificationsLocked();
         }
@@ -1108,13 +1180,6 @@
             return;
         }
 
-        // If we are in restrict power mode, we want to treat all interfaces
-        // as metered, to restrict access to the network by uid.  However, we
-        // will not have a bandwidth limit.  Also only do this if restrict
-        // background data use is *not* enabled, since that takes precedence
-        // use over those networks can have a cost associated with it).
-        final boolean powerSave = mRestrictPower && !mRestrictBackground;
-
         // First, generate identities of all connected networks so we can
         // quickly compare them against all defined policies below.
         final ArrayList<Pair<String, NetworkIdentity>> connIdents = new ArrayList<>(states.length);
@@ -1126,9 +1191,6 @@
                 final String baseIface = state.linkProperties.getInterfaceName();
                 if (baseIface != null) {
                     connIdents.add(Pair.create(baseIface, ident));
-                    if (powerSave) {
-                        connIfaces.add(baseIface);
-                    }
                 }
 
                 // Stacked interfaces are considered to have same identity as
@@ -1138,9 +1200,6 @@
                     final String stackedIface = stackedLink.getInterfaceName();
                     if (stackedIface != null) {
                         connIdents.add(Pair.create(stackedIface, ident));
-                        if (powerSave) {
-                            connIfaces.add(stackedIface);
-                        }
                     }
                 }
             }
@@ -1187,8 +1246,7 @@
             }
 
             if (LOGD) {
-                Slog.d(TAG, "applying policy " + policy.toString() + " to ifaces "
-                        + Arrays.toString(ifaces));
+                Slog.d(TAG, "applying policy " + policy + " to ifaces " + Arrays.toString(ifaces));
             }
 
             final boolean hasWarning = policy.warningBytes != LIMIT_DISABLED;
@@ -1219,9 +1277,6 @@
                     removeInterfaceQuota(iface);
                     setInterfaceQuota(iface, quotaBytes);
                     newMeteredIfaces.add(iface);
-                    if (powerSave) {
-                        connIfaces.remove(iface);
-                    }
                 }
             }
 
@@ -1421,6 +1476,9 @@
                     } else if (TAG_RESTRICT_BACKGROUND.equals(tag) && insideWhitelist) {
                         final int uid = readIntAttribute(in, ATTR_UID);
                         mRestrictBackgroundWhitelistUids.put(uid, true);
+                    } else if (TAG_REVOKED_RESTRICT_BACKGROUND.equals(tag) && insideWhitelist) {
+                        final int uid = readIntAttribute(in, ATTR_UID);
+                        mRestrictBackgroundWhitelistRevokedUids.put(uid, true);
                     }
                 } else if (type == END_TAG) {
                     if (TAG_WHITELIST.equals(tag)) {
@@ -1519,7 +1577,7 @@
             out.startTag(null, TAG_WHITELIST);
 
             // restrict background whitelist
-            final int size = mRestrictBackgroundWhitelistUids.size();
+            int size = mRestrictBackgroundWhitelistUids.size();
             for (int i = 0; i < size; i++) {
                 final int uid = mRestrictBackgroundWhitelistUids.keyAt(i);
                 out.startTag(null, TAG_RESTRICT_BACKGROUND);
@@ -1527,6 +1585,15 @@
                 out.endTag(null, TAG_RESTRICT_BACKGROUND);
             }
 
+            // revoked restrict background whitelist
+            size = mRestrictBackgroundWhitelistRevokedUids.size();
+            for (int i = 0; i < size; i++) {
+                final int uid = mRestrictBackgroundWhitelistRevokedUids.keyAt(i);
+                out.startTag(null, TAG_REVOKED_RESTRICT_BACKGROUND);
+                writeIntAttribute(out, ATTR_UID, uid);
+                out.endTag(null, TAG_REVOKED_RESTRICT_BACKGROUND);
+            }
+
             out.endTag(null, TAG_WHITELIST);
 
             out.endDocument();
@@ -1552,7 +1619,7 @@
             try {
                 final int oldPolicy = mUidPolicy.get(uid, POLICY_NONE);
                 if (oldPolicy != policy) {
-                    setUidPolicyUncheckedLocked(uid, policy, true);
+                    setUidPolicyUncheckedLocked(uid, oldPolicy, policy, true);
                 }
             } finally {
                 Binder.restoreCallingIdentity(token);
@@ -1572,7 +1639,7 @@
             final int oldPolicy = mUidPolicy.get(uid, POLICY_NONE);
             policy |= oldPolicy;
             if (oldPolicy != policy) {
-                setUidPolicyUncheckedLocked(uid, policy, true);
+                setUidPolicyUncheckedLocked(uid, oldPolicy, policy, true);
             }
         }
     }
@@ -1589,11 +1656,22 @@
             final int oldPolicy = mUidPolicy.get(uid, POLICY_NONE);
             policy = oldPolicy & ~policy;
             if (oldPolicy != policy) {
-                setUidPolicyUncheckedLocked(uid, policy, true);
+                setUidPolicyUncheckedLocked(uid, oldPolicy, policy, true);
             }
         }
     }
 
+    private void setUidPolicyUncheckedLocked(int uid, int oldPolicy, int policy, boolean persist) {
+        setUidPolicyUncheckedLocked(uid, policy, persist);
+
+        // Checks if app was added or removed to the blacklist.
+        if ((oldPolicy == POLICY_NONE && policy == POLICY_REJECT_METERED_BACKGROUND)
+                || (oldPolicy == POLICY_REJECT_METERED_BACKGROUND && policy == POLICY_NONE)) {
+            mHandler.obtainMessage(MSG_RESTRICT_BACKGROUND_WHITELIST_CHANGED, uid, 0)
+                    .sendToTarget();
+        }
+    }
+
     private void setUidPolicyUncheckedLocked(int uid, int policy, boolean persist) {
         mUidPolicy.put(uid, policy);
 
@@ -1844,6 +1922,12 @@
             }
             Slog.i(TAG, "adding uid " + uid + " to restrict background whitelist");
             mRestrictBackgroundWhitelistUids.append(uid, true);
+            if (mDefaultRestrictBackgroundWhitelistUids.get(uid)
+                    && mRestrictBackgroundWhitelistRevokedUids.get(uid)) {
+                if (LOGD) Slog.d(TAG, "Removing uid " + uid
+                        + " from revoked restrict background whitelist");
+                mRestrictBackgroundWhitelistRevokedUids.delete(uid);
+            }
             changed = mRestrictBackground && !oldStatus;
             if (changed && hasInternetPermissions(uid)) {
                 setUidNetworkRules(uid, false);
@@ -1879,6 +1963,12 @@
         Slog.i(TAG, "removing uid " + uid + " from restrict background whitelist");
         final boolean changed = mRestrictBackground && oldStatus;
         mRestrictBackgroundWhitelistUids.delete(uid);
+        if (mDefaultRestrictBackgroundWhitelistUids.get(uid)
+                && !mRestrictBackgroundWhitelistRevokedUids.get(uid)) {
+            if (LOGD) Slog.d(TAG, "Adding uid " + uid
+                    + " to revoked restrict background whitelist");
+            mRestrictBackgroundWhitelistRevokedUids.append(uid, true);
+        }
         if (updateNow) {
             if (changed && hasInternetPermissions(uid)) {
                 setUidNetworkRules(uid, true);
@@ -1909,7 +1999,20 @@
     public int getRestrictBackgroundByCaller() {
         mContext.enforceCallingOrSelfPermission(ACCESS_NETWORK_STATE, TAG);
         final int uid = Binder.getCallingUid();
+
         synchronized (mRulesLock) {
+            // Must clear identity because getUidPolicy() is restricted to system.
+            final long token = Binder.clearCallingIdentity();
+            final int policy;
+            try {
+                policy = getUidPolicy(uid);
+            } finally {
+                Binder.restoreCallingIdentity(token);
+            }
+            if (policy == POLICY_REJECT_METERED_BACKGROUND) {
+                // App is blacklisted.
+                return RESTRICT_BACKGROUND_STATUS_ENABLED;
+            }
             if (!mRestrictBackground) {
                 return RESTRICT_BACKGROUND_STATUS_DISABLED;
             }
@@ -2125,6 +2228,30 @@
                 fout.decreaseIndent();
             }
 
+            size = mDefaultRestrictBackgroundWhitelistUids.size();
+            if (size > 0) {
+                fout.println("Default restrict background whitelist uids:");
+                fout.increaseIndent();
+                for (int i = 0; i < size; i++) {
+                    fout.print("UID=");
+                    fout.print(mDefaultRestrictBackgroundWhitelistUids.keyAt(i));
+                    fout.println();
+                }
+                fout.decreaseIndent();
+            }
+
+            size = mRestrictBackgroundWhitelistRevokedUids.size();
+            if (size > 0) {
+                fout.println("Default restrict background whitelist uids revoked by users:");
+                fout.increaseIndent();
+                for (int i = 0; i < size; i++) {
+                    fout.print("UID=");
+                    fout.print(mRestrictBackgroundWhitelistRevokedUids.keyAt(i));
+                    fout.println();
+                }
+                fout.decreaseIndent();
+            }
+
             final SparseBooleanArray knownUids = new SparseBooleanArray();
             collectKeys(mUidState, knownUids);
             collectKeys(mUidRules, knownUids);
@@ -2184,9 +2311,14 @@
             // state changed, push updated rules
             mUidState.put(uid, uidState);
             updateRulesForUidStateChangeLocked(uid, oldUidState, uidState);
-            if (mDeviceIdleMode && isProcStateAllowedWhileIdle(oldUidState)
-                    != isProcStateAllowedWhileIdle(uidState)) {
-                updateRuleForDeviceIdleLocked(uid);
+            if (isProcStateAllowedWhileIdleOrPowerSaveMode(oldUidState)
+                    != isProcStateAllowedWhileIdleOrPowerSaveMode(uidState) ) {
+                if (mDeviceIdleMode) {
+                    updateRuleForDeviceIdleLocked(uid);
+                }
+                if (mRestrictPower) {
+                    updateRulesForRestrictPowerLocked(uid);
+                }
             }
         }
     }
@@ -2202,6 +2334,9 @@
                 if (mDeviceIdleMode) {
                     updateRuleForDeviceIdleLocked(uid);
                 }
+                if (mRestrictPower) {
+                    updateRulesForRestrictPowerLocked(uid);
+                }
             }
         }
     }
@@ -2239,15 +2374,36 @@
         }
     }
 
-    static boolean isProcStateAllowedWhileIdle(int procState) {
+    static boolean isProcStateAllowedWhileIdleOrPowerSaveMode(int procState) {
         return procState <= ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE;
     }
 
+    void updateRulesForRestrictPowerLocked() {
+        updateRulesForWhitelistedPowerSaveLocked(mRestrictPower, FIREWALL_CHAIN_POWERSAVE,
+                mUidFirewallPowerSaveRules);
+    }
+
+    void updateRulesForRestrictPowerLocked(int uid) {
+        updateRulesForWhitelistedPowerSaveLocked(uid, mRestrictPower, FIREWALL_CHAIN_POWERSAVE);
+    }
+
     void updateRulesForDeviceIdleLocked() {
-        if (mDeviceIdleMode) {
-            // sync the whitelists before enable dozable chain.  We don't care about the rules if
+        updateRulesForWhitelistedPowerSaveLocked(mDeviceIdleMode, FIREWALL_CHAIN_DOZABLE,
+                mUidFirewallDozableRules);
+    }
+
+    void updateRuleForDeviceIdleLocked(int uid) {
+        updateRulesForWhitelistedPowerSaveLocked(uid, mDeviceIdleMode, FIREWALL_CHAIN_DOZABLE);
+    }
+
+    // NOTE: since both fw_dozable and fw_powersave uses the same map (mPowerSaveTempWhitelistAppIds)
+    // for whitelisting, we can reuse their logic in this method.
+    private void updateRulesForWhitelistedPowerSaveLocked(boolean enabled, int chain,
+            SparseIntArray rules) {
+        if (enabled) {
+            // Sync the whitelists before enabling the chain.  We don't care about the rules if
             // we are disabling the chain.
-            final SparseIntArray uidRules = mUidFirewallDozableRules;
+            final SparseIntArray uidRules = rules;
             uidRules.clear();
             final List<UserInfo> users = mUserManager.getUsers();
             for (int ui = users.size() - 1; ui >= 0; ui--) {
@@ -2266,24 +2422,26 @@
                 }
             }
             for (int i = mUidState.size() - 1; i >= 0; i--) {
-                if (isProcStateAllowedWhileIdle(mUidState.valueAt(i))) {
+                if (isProcStateAllowedWhileIdleOrPowerSaveMode(mUidState.valueAt(i))) {
                     uidRules.put(mUidState.keyAt(i), FIREWALL_RULE_ALLOW);
                 }
             }
-            setUidFirewallRules(FIREWALL_CHAIN_DOZABLE, uidRules);
+            setUidFirewallRules(chain, uidRules);
         }
 
-        enableFirewallChainLocked(FIREWALL_CHAIN_DOZABLE, mDeviceIdleMode);
+        enableFirewallChainLocked(chain, enabled);
     }
 
-    void updateRuleForDeviceIdleLocked(int uid) {
-        if (mDeviceIdleMode) {
+    // NOTE: since both fw_dozable and fw_powersave uses the same map (mPowerSaveTempWhitelistAppIds)
+    // for whitelisting, we can reuse their logic in this method.
+    private void updateRulesForWhitelistedPowerSaveLocked(int uid, boolean enabled, int chain) {
+        if (enabled) {
             int appId = UserHandle.getAppId(uid);
             if (mPowerSaveTempWhitelistAppIds.get(appId) || mPowerSaveWhitelistAppIds.get(appId)
-                    || isProcStateAllowedWhileIdle(mUidState.get(uid))) {
-                setUidFirewallRule(FIREWALL_CHAIN_DOZABLE, uid, FIREWALL_RULE_ALLOW);
+                    || isProcStateAllowedWhileIdleOrPowerSaveMode(mUidState.get(uid))) {
+                setUidFirewallRule(chain, uid, FIREWALL_RULE_ALLOW);
             } else {
-                setUidFirewallRule(FIREWALL_CHAIN_DOZABLE, uid, FIREWALL_RULE_DEFAULT);
+                setUidFirewallRule(chain, uid, FIREWALL_RULE_DEFAULT);
             }
         }
 
@@ -2339,10 +2497,14 @@
      * {@link #mRestrictPower}, or {@link #mDeviceIdleMode} value.
      */
     void updateRulesForGlobalChangeLocked(boolean restrictedNetworksChanged) {
+        long start;
+        if (LOGD) start = System.currentTimeMillis();
+
         final PackageManager pm = mContext.getPackageManager();
 
         updateRulesForDeviceIdleLocked();
         updateRulesForAppIdleLocked();
+        updateRulesForRestrictPowerLocked();
 
         // update rules for all installed applications
         final List<UserInfo> users = mUserManager.getUsers();
@@ -2350,8 +2512,12 @@
                 PackageManager.GET_UNINSTALLED_PACKAGES | PackageManager.GET_DISABLED_COMPONENTS
                         | PackageManager.MATCH_ENCRYPTION_AWARE_AND_UNAWARE);
 
-        for (UserInfo user : users) {
-            for (ApplicationInfo app : apps) {
+        final int usersSize = users.size();
+        final int appsSize = apps.size();
+        for (int i = 0; i < usersSize; i++) {
+            final UserInfo user = users.get(i);
+            for (int j = 0; j < appsSize; j++) {
+                final ApplicationInfo app = apps.get(j);
                 final int uid = UserHandle.getUid(user.id, app.uid);
                 updateRulesForUidLocked(uid);
             }
@@ -2366,16 +2532,23 @@
             normalizePoliciesLocked();
             updateNetworkRulesLocked();
         }
+        if (LOGD) {
+          final long delta = System.currentTimeMillis() - start;
+          Slog.d(TAG, "updateRulesForGlobalChangeLocked(" + restrictedNetworksChanged + ") took "
+                  + delta + "ms");
+        }
     }
 
     void updateRulesForTempWhitelistChangeLocked() {
         final List<UserInfo> users = mUserManager.getUsers();
-        for (UserInfo user : users) {
-            for (int i = mPowerSaveTempWhitelistAppIds.size() - 1; i >= 0; i--) {
-                int appId = mPowerSaveTempWhitelistAppIds.keyAt(i);
+        for (int i = 0; i < users.size(); i++) {
+            final UserInfo user = users.get(i);
+            for (int j = mPowerSaveTempWhitelistAppIds.size() - 1; j >= 0; j--) {
+                int appId = mPowerSaveTempWhitelistAppIds.keyAt(j);
                 int uid = UserHandle.getUid(user.id, appId);
                 updateRuleForAppIdleLocked(uid);
                 updateRuleForDeviceIdleLocked(uid);
+                updateRulesForRestrictPowerLocked(uid);
             }
         }
     }
@@ -2468,6 +2641,12 @@
             uidRules = RULE_REJECT_ALL;
         }
 
+        // Check powersave state, which is whitelist
+        if (mFirewallChainStates.get(FIREWALL_CHAIN_POWERSAVE)
+                && mUidFirewallPowerSaveRules.get(uid, FIREWALL_RULE_DEFAULT) != FIREWALL_RULE_ALLOW) {
+            uidRules = RULE_REJECT_ALL;
+        }
+
         // Check standby state, which is blacklist
         if (mFirewallChainStates.get(FIREWALL_CHAIN_STANDBY)
                 && mUidFirewallStandbyRules.get(uid, FIREWALL_RULE_DEFAULT) == FIREWALL_RULE_DENY) {
@@ -2695,6 +2874,8 @@
             mUidFirewallDozableRules.put(uid, rule);
         } else if (chain == FIREWALL_CHAIN_STANDBY) {
             mUidFirewallStandbyRules.put(uid, rule);
+        } else if (chain == FIREWALL_CHAIN_POWERSAVE) {
+            mUidFirewallPowerSaveRules.put(uid, rule);
         }
 
         try {
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerShellCommand.java b/services/core/java/com/android/server/net/NetworkPolicyManagerShellCommand.java
index a5dc008..9cfb590 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerShellCommand.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerShellCommand.java
@@ -16,12 +16,15 @@
 
 package com.android.server.net;
 
+import static android.net.NetworkPolicyManager.POLICY_NONE;
+import static android.net.NetworkPolicyManager.POLICY_REJECT_METERED_BACKGROUND;
 import static android.net.wifi.WifiInfo.removeDoubleQuotes;
 import static com.android.server.net.NetworkPolicyManagerService.newWifiPolicy;
 import static com.android.server.net.NetworkPolicyManagerService.TAG;
 
 import java.io.PrintWriter;
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
@@ -83,6 +86,8 @@
         pw.println("");
         pw.println("  add restrict-background-whitelist UID");
         pw.println("    Adds a UID to the whitelist for restrict background usage.");
+        pw.println("  add restrict-background-blacklist UID");
+        pw.println("    Adds a UID to the blacklist for restrict background usage.");
         pw.println("  get metered-network ID");
         pw.println("    Checks whether the given non-mobile network is metered or not.");
         pw.println("  get restrict-background");
@@ -93,8 +98,12 @@
         pw.println("    networks.");
         pw.println("  list restrict-background-whitelist");
         pw.println("    Lists UIDs that are whitelisted for restrict background usage.");
+        pw.println("  list restrict-background-blacklist");
+        pw.println("    Lists UIDs that are blacklisted for restrict background usage.");
         pw.println("  remove restrict-background-whitelist UID");
         pw.println("    Removes a UID from the whitelist for restrict background usage.");
+        pw.println("  remove restrict-background-blacklist UID");
+        pw.println("    Removes a UID from the blacklist for restrict background usage.");
         pw.println("  set metered-network ID BOOLEAN");
         pw.println("    Toggles whether the given non-mobile network is metered.");
         pw.println("  set restrict-background BOOLEAN");
@@ -147,6 +156,8 @@
                 return listMeteredWifiNetworks();
             case "restrict-background-whitelist":
                 return listRestrictBackgroundWhitelist();
+            case "restrict-background-blacklist":
+                return listRestrictBackgroundBlacklist();
         }
         pw.println("Error: unknown list type '" + type + "'");
         return -1;
@@ -162,6 +173,8 @@
         switch(type) {
             case "restrict-background-whitelist":
                 return addRestrictBackgroundWhitelist();
+            case "restrict-background-blacklist":
+                return addRestrictBackgroundBlacklist();
         }
         pw.println("Error: unknown add type '" + type + "'");
         return -1;
@@ -177,6 +190,8 @@
         switch(type) {
             case "restrict-background-whitelist":
                 return removeRestrictBackgroundWhitelist();
+            case "restrict-background-blacklist":
+                return removeRestrictBackgroundBlacklist();
         }
         pw.println("Error: unknown remove type '" + type + "'");
         return -1;
@@ -199,6 +214,24 @@
         return 0;
     }
 
+    private int listRestrictBackgroundBlacklist() throws RemoteException {
+        final PrintWriter pw = getOutPrintWriter();
+
+        final int[] uids = mInterface.getUidsWithPolicy(POLICY_REJECT_METERED_BACKGROUND);
+        pw.print("Restrict background blacklisted UIDs: ");
+        if (uids.length == 0) {
+            pw.println("none");
+        } else {
+            for (int i = 0; i < uids.length; i++) {
+                int uid = uids[i];
+                pw.print(uid);
+                pw.print(' ');
+            }
+        }
+        pw.println();
+        return 0;
+    }
+
     private int getRestrictBackground() throws RemoteException {
         final PrintWriter pw = getOutPrintWriter();
         pw.print("Restrict background status: ");
@@ -233,6 +266,24 @@
         return 0;
     }
 
+    private int addRestrictBackgroundBlacklist() throws RemoteException {
+        final int uid = getUidFromNextArg();
+        if (uid < 0) {
+            return uid;
+        }
+        mInterface.setUidPolicy(uid, POLICY_REJECT_METERED_BACKGROUND);
+        return 0;
+    }
+
+    private int removeRestrictBackgroundBlacklist() throws RemoteException {
+        final int uid = getUidFromNextArg();
+        if (uid < 0) {
+            return uid;
+        }
+        mInterface.setUidPolicy(uid, POLICY_NONE);
+        return 0;
+    }
+
     private int listMeteredWifiNetworks() throws RemoteException {
         final PrintWriter pw = getOutPrintWriter();
         final String arg = getNextArg();
@@ -314,9 +365,12 @@
     private List<NetworkPolicy> getWifiPolicies() throws RemoteException {
         // First gets a list of saved wi-fi networks.
         final List<WifiConfiguration> configs = mWifiManager.getConfiguredNetworks();
-        final Set<String> ssids = new HashSet<>(configs.size());
-        for (WifiConfiguration config : configs) {
-            ssids.add(removeDoubleQuotes(config.SSID));
+        final int size = configs != null ? configs.size() : 0;
+        final Set<String> ssids = new HashSet<>(size);
+        if (configs != null) {
+            for (WifiConfiguration config : configs) {
+                ssids.add(removeDoubleQuotes(config.SSID));
+            }
         }
 
         // Then gets the saved policies.
diff --git a/services/core/java/com/android/server/notification/ConditionProviders.java b/services/core/java/com/android/server/notification/ConditionProviders.java
index 9820a12..c19b51f 100644
--- a/services/core/java/com/android/server/notification/ConditionProviders.java
+++ b/services/core/java/com/android/server/notification/ConditionProviders.java
@@ -16,6 +16,7 @@
 
 package com.android.server.notification;
 
+import android.app.AutomaticZenRule;
 import android.content.ComponentName;
 import android.content.ContentResolver;
 import android.content.Context;
@@ -44,7 +45,6 @@
 
 public class ConditionProviders extends ManagedServices {
     private final ArrayList<ConditionRecord> mRecords = new ArrayList<>();
-    private final ArrayMap<IBinder, IConditionListener> mListeners = new ArrayMap<>();
     private final ArraySet<String> mSystemConditionProviderNames;
     private final ArraySet<SystemConditionProviderService> mSystemConditionProviders
             = new ArraySet<>();
@@ -103,12 +103,6 @@
                 }
             }
         }
-        if (filter == null) {
-            pw.print("    mListeners("); pw.print(mListeners.size()); pw.println("):");
-            for (int i = 0; i < mListeners.size(); i++) {
-                pw.print("      "); pw.println(mListeners.keyAt(i));
-            }
-        }
         pw.print("    mSystemConditionProviders: "); pw.println(mSystemConditionProviderNames);
         for (int i = 0; i < mSystemConditionProviders.size(); i++) {
             mSystemConditionProviders.valueAt(i).dump(pw, filter);
@@ -173,16 +167,12 @@
         }
     }
 
-    private Condition[] validateConditions(String pkg, Condition[] conditions) {
+    private Condition[] removeDuplicateConditions(String pkg, Condition[] conditions) {
         if (conditions == null || conditions.length == 0) return null;
         final int N = conditions.length;
         final ArrayMap<Uri, Condition> valid = new ArrayMap<Uri, Condition>(N);
         for (int i = 0; i < N; i++) {
             final Uri id = conditions[i].id;
-            if (!Condition.isValidId(id, pkg)) {
-                Slog.w(TAG, "Ignoring condition from " + pkg + " for invalid id: " + id);
-                continue;
-            }
             if (valid.containsKey(id)) {
                 Slog.w(TAG, "Ignoring condition from " + pkg + " for duplicate id: " + id);
                 continue;
@@ -219,16 +209,9 @@
         synchronized(mMutex) {
             if (DEBUG) Slog.d(TAG, "notifyConditions pkg=" + pkg + " info=" + info + " conditions="
                     + (conditions == null ? null : Arrays.asList(conditions)));
-            conditions = validateConditions(pkg, conditions);
+            conditions = removeDuplicateConditions(pkg, conditions);
             if (conditions == null || conditions.length == 0) return;
             final int N = conditions.length;
-            for (IConditionListener listener : mListeners.values()) {
-                try {
-                    listener.onConditionsReceived(conditions);
-                } catch (RemoteException e) {
-                    Slog.w(TAG, "Error sending conditions to listener " + listener, e);
-                }
-            }
             for (int i = 0; i < N; i++) {
                 final Condition c = conditions[i];
                 final ConditionRecord r = getRecordLocked(c.id, info.component, true /*create*/);
diff --git a/services/core/java/com/android/server/notification/EventConditionProvider.java b/services/core/java/com/android/server/notification/EventConditionProvider.java
index ab3cb83..b13fec1 100644
--- a/services/core/java/com/android/server/notification/EventConditionProvider.java
+++ b/services/core/java/com/android/server/notification/EventConditionProvider.java
@@ -26,7 +26,9 @@
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.net.Uri;
 import android.os.Handler;
+import android.os.HandlerThread;
 import android.os.Looper;
+import android.os.Process;
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.service.notification.Condition;
@@ -63,15 +65,18 @@
     private final ArraySet<Uri> mSubscriptions = new ArraySet<Uri>();
     private final SparseArray<CalendarTracker> mTrackers = new SparseArray<>();
     private final Handler mWorker;
+    private final HandlerThread mThread;
 
     private boolean mConnected;
     private boolean mRegistered;
     private boolean mBootComplete;  // don't hammer the calendar provider until boot completes.
     private long mNextAlarmTime;
 
-    public EventConditionProvider(Looper worker) {
+    public EventConditionProvider() {
         if (DEBUG) Slog.d(TAG, "new " + SIMPLE_NAME + "()");
-        mWorker = new Handler(worker);
+        mThread = new HandlerThread(TAG, Process.THREAD_PRIORITY_BACKGROUND);
+        mThread.start();
+        mWorker = new Handler(mThread.getLooper());
     }
 
     @Override
diff --git a/services/core/java/com/android/server/notification/ManagedServices.java b/services/core/java/com/android/server/notification/ManagedServices.java
index 0d6e3e5..6cf3940 100644
--- a/services/core/java/com/android/server/notification/ManagedServices.java
+++ b/services/core/java/com/android/server/notification/ManagedServices.java
@@ -16,6 +16,7 @@
 
 package com.android.server.notification;
 
+import android.annotation.NonNull;
 import android.app.ActivityManager;
 import android.app.PendingIntent;
 import android.content.BroadcastReceiver;
@@ -301,7 +302,9 @@
      * */
     public void registerGuestService(ManagedServiceInfo guest) {
         checkNotNull(guest.service);
-        checkType(guest.service);
+        if (!checkType(guest.service)) {
+            throw new IllegalArgumentException();
+        }
         if (registerServiceImpl(guest) != null) {
             onServiceAdded(guest);
         }
@@ -325,12 +328,16 @@
                     component.flattenToShortString());
         }
 
-        final int[] userIds = mUserProfiles.getCurrentProfileIds();
-        for (int userId : userIds) {
-            if (enabled) {
-                registerServiceLocked(component, userId);
-            } else {
-                unregisterServiceLocked(component, userId);
+
+        synchronized (mMutex) {
+            final int[] userIds = mUserProfiles.getCurrentProfileIds();
+
+            for (int userId : userIds) {
+                if (enabled) {
+                    registerServiceLocked(component, userId);
+                } else {
+                    unregisterServiceLocked(component, userId);
+                }
             }
         }
     }
@@ -450,7 +457,7 @@
         return queryPackageForServices(packageName, userId, null);
     }
 
-    protected Set<ComponentName> queryPackageForServices(String packageName, int userId,
+    public Set<ComponentName> queryPackageForServices(String packageName, int userId,
             String category) {
         Set<ComponentName> installed = new ArraySet<>();
         final PackageManager pm = mContext.getPackageManager();
@@ -633,7 +640,21 @@
         }
     }
 
+    /**
+     * Inject a system service into the management list.
+     */
+    public void registerSystemService(final ComponentName name, final int userid) {
+        synchronized (mMutex) {
+            registerServiceLocked(name, userid, true /* isSystem */);
+        }
+    }
+
     private void registerServiceLocked(final ComponentName name, final int userid) {
+        registerServiceLocked(name, userid, false /* isSystem */);
+    }
+
+    private void registerServiceLocked(final ComponentName name, final int userid,
+            final boolean isSystem) {
         if (DEBUG) Slog.v(TAG, "registerService: " + name + " u=" + userid);
 
         final String servicesBindingTag = name.toString() + "/" + userid;
@@ -691,7 +712,7 @@
                         try {
                             mService = asInterface(binder);
                             info = newServiceInfo(mService, name,
-                                userid, false /*isSystem*/, this, targetSdkVersion);
+                                userid, isSystem, this, targetSdkVersion);
                             binder.linkToDeath(info, 0);
                             added = mServices.add(info);
                         } catch (RemoteException e) {
@@ -887,6 +908,7 @@
                 return false;
             }
             if (this.userid == UserHandle.USER_ALL) return true;
+            if (this.userid == UserHandle.USER_SYSTEM) return true;
             if (nid == UserHandle.USER_ALL || nid == this.userid) return true;
             return supportsProfiles() && mUserProfiles.isCurrentProfile(nid);
         }
@@ -920,9 +942,9 @@
 
     public static class UserProfiles {
         // Profiles of the current user.
-        private final SparseArray<UserInfo> mCurrentProfiles = new SparseArray<UserInfo>();
+        private final SparseArray<UserInfo> mCurrentProfiles = new SparseArray<>();
 
-        public void updateCache(Context context) {
+        public void updateCache(@NonNull Context context) {
             UserManager userManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
             if (userManager != null) {
                 int currentUserId = ActivityManager.getCurrentUser();
@@ -954,12 +976,12 @@
         }
     }
 
-    protected static class Config {
-        String caption;
-        String serviceInterface;
-        String secureSettingName;
-        String bindPermission;
-        String settingsAction;
-        int clientLabel;
+    public static class Config {
+        public String caption;
+        public String serviceInterface;
+        public String secureSettingName;
+        public String bindPermission;
+        public String settingsAction;
+        public int clientLabel;
     }
 }
diff --git a/services/core/java/com/android/server/notification/NotificationComparator.java b/services/core/java/com/android/server/notification/NotificationComparator.java
index 5e4703d..7dff2c1 100644
--- a/services/core/java/com/android/server/notification/NotificationComparator.java
+++ b/services/core/java/com/android/server/notification/NotificationComparator.java
@@ -28,10 +28,11 @@
         final int leftImportance = left.getImportance();
         final int rightImportance = right.getImportance();
         if (leftImportance != rightImportance) {
-            // by priority, high to low
+            // by importance, high to low
             return -1 * Integer.compare(leftImportance, rightImportance);
         }
 
+        // Whether or not the notification can bypass DND.
         final int leftPackagePriority = left.getPackagePriority();
         final int rightPackagePriority = right.getPackagePriority();
         if (leftPackagePriority != rightPackagePriority) {
@@ -39,6 +40,13 @@
             return -1 * Integer.compare(leftPackagePriority, rightPackagePriority);
         }
 
+        final int leftPriority = left.sbn.getNotification().priority;
+        final int rightPriority = right.sbn.getNotification().priority;
+        if (leftPriority != rightPriority) {
+            // by priority, high to low
+            return -1 * Integer.compare(leftPriority, rightPriority);
+        }
+
         final float leftPeople = left.getContactAffinity();
         final float rightPeople = right.getContactAffinity();
         if (leftPeople != rightPeople) {
diff --git a/services/core/java/com/android/server/notification/NotificationIntrusivenessExtractor.java b/services/core/java/com/android/server/notification/NotificationIntrusivenessExtractor.java
index b57cc75..bcdeb66 100644
--- a/services/core/java/com/android/server/notification/NotificationIntrusivenessExtractor.java
+++ b/services/core/java/com/android/server/notification/NotificationIntrusivenessExtractor.java
@@ -23,7 +23,7 @@
 import android.util.Slog;
 
 /**
- * This {@link com.android.server.notification.NotificationSignalExtractor} noticies noisy
+ * This {@link com.android.server.notification.NotificationSignalExtractor} notices noisy
  * notifications and marks them to get a temporary ranking bump.
  */
 public class NotificationIntrusivenessExtractor implements NotificationSignalExtractor {
@@ -44,9 +44,15 @@
             return null;
         }
 
-        final Notification notification = record.getNotification();
-        if (record.getImportance() > NotificationListenerService.Ranking.IMPORTANCE_DEFAULT) {
-            record.setRecentlyIntrusive(true);
+        if (record.getImportance() >= NotificationListenerService.Ranking.IMPORTANCE_DEFAULT) {
+            final Notification notification = record.getNotification();
+            if ((notification.defaults & Notification.DEFAULT_VIBRATE) != 0 ||
+                    notification.vibrate != null ||
+                    (notification.defaults & Notification.DEFAULT_SOUND) != 0 ||
+                    notification.sound != null ||
+                    notification.fullScreenIntent != null) {
+                record.setRecentlyIntrusive(true);
+            }
         }
 
         return new RankingReconsideration(record.getKey(), HANG_TIME_MS) {
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index c337c573..516602e 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -16,27 +16,27 @@
 
 package com.android.server.notification;
 
-import static android.service.notification.NotificationAssistantService.REASON_APP_CANCEL;
-import static android.service.notification.NotificationAssistantService.REASON_APP_CANCEL_ALL;
-import static android.service.notification.NotificationAssistantService.REASON_DELEGATE_CANCEL;
-import static android.service.notification.NotificationAssistantService.REASON_DELEGATE_CANCEL_ALL;
-import static android.service.notification.NotificationAssistantService.REASON_DELEGATE_CLICK;
-import static android.service.notification.NotificationAssistantService.REASON_DELEGATE_ERROR;
-import static android.service.notification.NotificationAssistantService.REASON_GROUP_OPTIMIZATION;
-import static android.service.notification.NotificationAssistantService.REASON_GROUP_SUMMARY_CANCELED;
-import static android.service.notification.NotificationAssistantService.REASON_LISTENER_CANCEL;
-import static android.service.notification.NotificationAssistantService.REASON_LISTENER_CANCEL_ALL;
-import static android.service.notification.NotificationAssistantService.REASON_PACKAGE_BANNED;
-import static android.service.notification.NotificationAssistantService.REASON_PACKAGE_CHANGED;
-import static android.service.notification.NotificationAssistantService.REASON_PACKAGE_SUSPENDED;
-import static android.service.notification.NotificationAssistantService.REASON_PROFILE_TURNED_OFF;
-import static android.service.notification.NotificationAssistantService.REASON_USER_STOPPED;
+import static android.service.notification.NotificationRankerService.REASON_APP_CANCEL;
+import static android.service.notification.NotificationRankerService.REASON_APP_CANCEL_ALL;
+import static android.service.notification.NotificationRankerService.REASON_DELEGATE_CANCEL;
+import static android.service.notification.NotificationRankerService.REASON_DELEGATE_CANCEL_ALL;
+import static android.service.notification.NotificationRankerService.REASON_DELEGATE_CLICK;
+import static android.service.notification.NotificationRankerService.REASON_DELEGATE_ERROR;
+import static android.service.notification.NotificationRankerService.REASON_GROUP_OPTIMIZATION;
+import static android.service.notification.NotificationRankerService.REASON_GROUP_SUMMARY_CANCELED;
+import static android.service.notification.NotificationRankerService.REASON_LISTENER_CANCEL;
+import static android.service.notification.NotificationRankerService.REASON_LISTENER_CANCEL_ALL;
+import static android.service.notification.NotificationRankerService.REASON_PACKAGE_BANNED;
+import static android.service.notification.NotificationRankerService.REASON_PACKAGE_CHANGED;
+import static android.service.notification.NotificationRankerService.REASON_PACKAGE_SUSPENDED;
+import static android.service.notification.NotificationRankerService.REASON_PROFILE_TURNED_OFF;
+import static android.service.notification.NotificationRankerService.REASON_USER_STOPPED;
 import static android.service.notification.NotificationListenerService.HINT_HOST_DISABLE_EFFECTS;
 import static android.service.notification.NotificationListenerService.SUPPRESSED_EFFECT_SCREEN_OFF;
 import static android.service.notification.NotificationListenerService.SUPPRESSED_EFFECT_SCREEN_ON;
 import static android.service.notification.NotificationListenerService.TRIM_FULL;
 import static android.service.notification.NotificationListenerService.TRIM_LIGHT;
-import static android.service.notification.NotificationListenerService.Ranking.IMPORTANCE_HIGH;
+import static android.service.notification.NotificationListenerService.Ranking.IMPORTANCE_DEFAULT;
 import static android.service.notification.NotificationListenerService.Ranking.IMPORTANCE_NONE;
 import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT;
 import static org.xmlpull.v1.XmlPullParser.END_TAG;
@@ -100,7 +100,7 @@
 import android.service.notification.IConditionProvider;
 import android.service.notification.INotificationListener;
 import android.service.notification.IStatusBarNotificationHolder;
-import android.service.notification.NotificationAssistantService;
+import android.service.notification.NotificationRankerService;
 import android.service.notification.NotificationListenerService;
 import android.service.notification.NotificationRankingUpdate;
 import android.service.notification.StatusBarNotification;
@@ -128,10 +128,9 @@
 import com.android.server.lights.Light;
 import com.android.server.lights.LightsManager;
 import com.android.server.notification.ManagedServices.ManagedServiceInfo;
-import com.android.server.notification.ManagedServices.UserProfiles;
 import com.android.server.statusbar.StatusBarManagerInternal;
 import com.android.server.vr.VrManagerInternal;
-import com.android.server.vr.VrStateListener;
+import com.android.server.notification.ManagedServices.UserProfiles;
 
 import libcore.io.IoUtils;
 
@@ -161,6 +160,7 @@
 import java.util.List;
 import java.util.Map.Entry;
 import java.util.Objects;
+import java.util.Set;
 import java.util.concurrent.TimeUnit;
 
 /** {@hide} */
@@ -213,6 +213,7 @@
 
     /** notification_enqueue status value for an ignored notification. */
     private static final int EVENTLOG_ENQUEUE_STATUS_IGNORED = 2;
+    private String mRankerServicePackageName;
 
     private IActivityManager mAm;
     AudioManager mAudioManager;
@@ -220,14 +221,11 @@
     StatusBarManagerInternal mStatusBar;
     Vibrator mVibrator;
     private VrManagerInternal mVrManagerInternal;
-    private final NotificationVrListener mVrListener = new NotificationVrListener();
 
     final IBinder mForegroundToken = new Binder();
     private WorkerHandler mHandler;
     private final HandlerThread mRankingThread = new HandlerThread("ranker",
             Process.THREAD_PRIORITY_BACKGROUND);
-    private final HandlerThread mAssistantThread = new HandlerThread("assistant",
-            Process.THREAD_PRIORITY_BACKGROUND);
 
     private Light mNotificationLight;
     Light mAttentionLight;
@@ -293,14 +291,13 @@
 
     private final UserProfiles mUserProfiles = new UserProfiles();
     private NotificationListeners mListeners;
-    private NotificationAssistant mAssistant;
+    private NotificationRankers mRankerServices;
     private ConditionProviders mConditionProviders;
     private NotificationUsageStats mUsageStats;
 
     private static final int MY_UID = Process.myUid();
     private static final int MY_PID = Process.myPid();
     private RankingHandler mRankingHandler;
-    private Handler mAssistantHandler;
 
     private static class Archive {
         final int mBufferSize;
@@ -758,7 +755,7 @@
                     }
                 }
                 mListeners.onPackagesChanged(queryReplace, pkgList);
-                mAssistant.onPackagesChanged(queryReplace, pkgList);
+                mRankerServices.onPackagesChanged(queryReplace, pkgList);
                 mConditionProviders.onPackagesChanged(queryReplace, pkgList);
                 mRankingHelper.onPackagesChanged(queryReplace, pkgList);
             }
@@ -807,7 +804,7 @@
                 // Refresh managed services
                 mConditionProviders.onUserSwitched(user);
                 mListeners.onUserSwitched(user);
-                mAssistant.onUserSwitched(user);
+                mRankerServices.onUserSwitched(user);
                 mZenModeHelper.onUserSwitched(user);
             } else if (action.equals(Intent.ACTION_USER_ADDED)) {
                 mUserProfiles.updateCache(context);
@@ -818,7 +815,7 @@
                 final int user = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL);
                 mConditionProviders.onUserUnlocked(user);
                 mListeners.onUserUnlocked(user);
-                mAssistant.onUserUnlocked(user);
+                mRankerServices.onUserUnlocked(user);
                 mZenModeHelper.onUserUnlocked(user);
             }
         }
@@ -856,14 +853,6 @@
         }
     }
 
-    private final class NotificationVrListener extends VrStateListener {
-        @Override
-        public void onVrStateChanged(final boolean enabled) {
-            mListeners.setCategoryState(NotificationListenerService.CATEGORY_VR_NOTIFICATIONS,
-                enabled);
-        }
-    }
-
     private SettingsObserver mSettingsObserver;
     private ZenModeHelper mZenModeHelper;
 
@@ -900,9 +889,12 @@
         mVibrator = (Vibrator) getContext().getSystemService(Context.VIBRATOR_SERVICE);
         mAppUsageStats = LocalServices.getService(UsageStatsManagerInternal.class);
 
+        // This is the package that contains the AOSP framework update.
+        mRankerServicePackageName = getContext().getPackageManager()
+                .getServicesSystemSharedLibraryPackageName();
+
         mHandler = new WorkerHandler();
         mRankingThread.start();
-        mAssistantThread.start();
         String[] extractorNames;
         try {
             extractorNames = resources.getStringArray(R.array.config_notificationSignalExtractors);
@@ -911,7 +903,6 @@
         }
         mUsageStats = new NotificationUsageStats(getContext());
         mRankingHandler = new RankingHandlerWorker(mRankingThread.getLooper());
-        mAssistantHandler = new Handler(mAssistantThread.getLooper());
         mRankingHelper = new RankingHelper(getContext(),
                 mRankingHandler,
                 mUsageStats,
@@ -946,8 +937,26 @@
 
         importOldBlockDb();
 
+        // This is a MangedServices object that keeps track of the listeners.
         mListeners = new NotificationListeners();
-        mAssistant = new NotificationAssistant();
+
+        // This is a MangedServices object that keeps track of the ranker.
+        mRankerServices = new NotificationRankers();
+        // Find the updatable ranker and register it.
+        Set<ComponentName> rankerComponents = mRankerServices.queryPackageForServices(
+                mRankerServicePackageName, UserHandle.USER_SYSTEM, null);
+        Iterator<ComponentName> iterator = rankerComponents.iterator();
+        if (iterator.hasNext()) {
+            ComponentName rankerComponent = iterator.next();
+            if (iterator.hasNext()) {
+                Slog.e(TAG, "found multiple ranker services:" + rankerComponents);
+            } else {
+                mRankerServices.registerSystemService(rankerComponent, UserHandle.USER_SYSTEM);
+            }
+        } else {
+            Slog.w(TAG, "could not start ranker service: none found");
+        }
+
         mStatusBar = getLocalService(StatusBarManagerInternal.class);
         mStatusBar.setNotificationDelegate(mNotificationDelegate);
 
@@ -1064,14 +1073,13 @@
             mAudioManager = (AudioManager) getContext().getSystemService(Context.AUDIO_SERVICE);
             mAudioManagerInternal = getLocalService(AudioManagerInternal.class);
             mVrManagerInternal = getLocalService(VrManagerInternal.class);
-            mVrManagerInternal.registerListener(mVrListener);
             mZenModeHelper.onSystemReady();
         } else if (phase == SystemService.PHASE_THIRD_PARTY_APPS_CAN_START) {
             // This observer will force an update when observe is called, causing us to
             // bind to listener services.
             mSettingsObserver.observe();
             mListeners.onBootPhaseAppsCanStart();
-            mAssistant.onBootPhaseAppsCanStart();
+            mRankerServices.onBootPhaseAppsCanStart();
             mConditionProviders.onBootPhaseAppsCanStart();
         }
     }
@@ -1304,7 +1312,7 @@
         }
 
         @Override
-        public void setImportance(String pkg, int uid,  int importance) {
+        public void setImportance(String pkg, int uid, int importance) {
             enforceSystemOrSystemUI("Caller not system or systemui");
             setNotificationsEnabledForPackageImpl(pkg, uid,
                     importance != NotificationListenerService.Ranking.IMPORTANCE_NONE);
@@ -1320,7 +1328,7 @@
 
         @Override
         public int getImportance(String pkg, int uid) {
-            checkCallerIsSystem();
+            enforceSystemOrSystemUI("Caller not system or systemui");
             return mRankingHelper.getImportance(pkg, uid);
         }
 
@@ -1435,8 +1443,8 @@
          * Remove a listener binder directly
          */
         @Override
-        public void unregisterListener(INotificationListener listener, int userid) {
-            mListeners.unregisterService(listener, userid);
+        public void unregisterListener(INotificationListener token, int userid) {
+            mListeners.unregisterService(token, userid);
         }
 
         /**
@@ -1489,8 +1497,8 @@
             checkCallerIsSystemOrSameApp(component.getPackageName());
             long identity = Binder.clearCallingIdentity();
             try {
-                ManagedServices manager = mAssistant.isComponentEnabledForCurrentProfiles(component)
-                        ? mAssistant
+                ManagedServices manager = mRankerServices.isComponentEnabledForCurrentProfiles(component)
+                        ? mRankerServices
                         : mListeners;
                 manager.setComponentState(component, true);
             } finally {
@@ -1698,9 +1706,9 @@
         }
 
         @Override
-        public List<AutomaticZenRule> getAutomaticZenRules() throws RemoteException {
+        public List<ZenModeConfig.ZenRule> getZenRules() throws RemoteException {
             enforcePolicyAccess(Binder.getCallingUid(), "getAutomaticZenRules");
-            return mZenModeHelper.getAutomaticZenRules();
+            return mZenModeHelper.getZenRules();
         }
 
         @Override
@@ -1711,7 +1719,7 @@
         }
 
         @Override
-        public AutomaticZenRule addAutomaticZenRule(AutomaticZenRule automaticZenRule)
+        public String addAutomaticZenRule(AutomaticZenRule automaticZenRule)
                 throws RemoteException {
             Preconditions.checkNotNull(automaticZenRule, "automaticZenRule is null");
             Preconditions.checkNotNull(automaticZenRule.getName(), "Name is null");
@@ -1724,7 +1732,7 @@
         }
 
         @Override
-        public boolean updateAutomaticZenRule(AutomaticZenRule automaticZenRule)
+        public boolean updateAutomaticZenRule(String id, AutomaticZenRule automaticZenRule)
                 throws RemoteException {
             Preconditions.checkNotNull(automaticZenRule, "automaticZenRule is null");
             Preconditions.checkNotNull(automaticZenRule.getName(), "Name is null");
@@ -1732,7 +1740,7 @@
             Preconditions.checkNotNull(automaticZenRule.getConditionId(), "ConditionId is null");
             enforcePolicyAccess(Binder.getCallingUid(), "updateAutomaticZenRule");
 
-            return mZenModeHelper.updateAutomaticZenRule(automaticZenRule,
+            return mZenModeHelper.updateAutomaticZenRule(id, automaticZenRule,
                     "updateAutomaticZenRule");
         }
 
@@ -1983,7 +1991,7 @@
         }
 
         @Override
-        public void setImportanceFromAssistant(INotificationListener token, String key,
+        public void setImportanceFromRankerService(INotificationListener token, String key,
                 int importance, CharSequence explanation) throws RemoteException {
             if (importance == IMPORTANCE_NONE) {
                 throw new IllegalArgumentException("blocking not allowed: key=" + key);
@@ -1991,7 +1999,7 @@
             final long identity = Binder.clearCallingIdentity();
             try {
                 synchronized (mNotificationList) {
-                    mAssistant.checkServiceTokenLocked(token);
+                    mRankerServices.checkServiceTokenLocked(token);
                     NotificationRecord n = mNotificationsByKey.get(key);
                     n.setImportance(importance, explanation);
                     mRankingHandler.requestSort();
@@ -2141,8 +2149,9 @@
                     pw.print(listener.component);
                 }
                 pw.println(')');
-                pw.println("\n  Notification assistant:");
-                mAssistant.dump(pw, filter);
+                pw.println("\n  mRankerServicePackageName: " + mRankerServicePackageName);
+                pw.println("\n  Notification ranker services:");
+                mRankerServices.dump(pw, filter);
             }
             pw.println("\n  Policy access:");
             pw.print("    mPolicyAccess: "); pw.println(mPolicyAccess);
@@ -2369,9 +2378,9 @@
                     }
                 }
 
-                // tell the assistant about the notification
-                if (mAssistant.isEnabled()) {
-                    mAssistant.onNotificationEnqueued(r);
+                // tell the ranker service about the notification
+                if (mRankerServices.isEnabled()) {
+                    mRankerServices.onNotificationEnqueued(r);
                     // TODO delay the code below here for 100ms or until there is an answer
                 }
 
@@ -2524,7 +2533,7 @@
         final Notification notification = record.sbn.getNotification();
 
         // Should this notification make noise, vibe, or use the LED?
-        final boolean aboveThreshold = record.getImportance() >= IMPORTANCE_HIGH;
+        final boolean aboveThreshold = record.getImportance() >= IMPORTANCE_DEFAULT;
         final boolean canInterrupt = aboveThreshold && !record.isIntercepted();
         if (DBG || record.isIntercepted())
             Slog.v(TAG,
@@ -3488,21 +3497,21 @@
         }
     }
 
-    public class NotificationAssistant extends ManagedServices {
+    public class NotificationRankers extends ManagedServices {
 
-        public NotificationAssistant() {
+        public NotificationRankers() {
             super(getContext(), mHandler, mNotificationList, mUserProfiles);
         }
 
         @Override
         protected Config getConfig() {
             Config c = new Config();
-            c.caption = "notification assistant";
-            c.serviceInterface = NotificationAssistantService.SERVICE_INTERFACE;
-            c.secureSettingName = Settings.Secure.ENABLED_NOTIFICATION_ASSISTANT;
-            c.bindPermission = Manifest.permission.BIND_NOTIFICATION_ASSISTANT_SERVICE;
+            c.caption = "notification ranker service";
+            c.serviceInterface = NotificationRankerService.SERVICE_INTERFACE;
+            c.secureSettingName = null;
+            c.bindPermission = Manifest.permission.BIND_NOTIFICATION_RANKER_SERVICE;
             c.settingsAction = Settings.ACTION_MANAGE_DEFAULT_APPS_SETTINGS;
-            c.clientLabel = R.string.notification_assistant_binding_label;
+            c.clientLabel = R.string.notification_ranker_binding_label;
             return c;
         }
 
@@ -3530,10 +3539,10 @@
             final StatusBarNotification sbn = r.sbn;
             TrimCache trimCache = new TrimCache(sbn);
 
-            // mServices is the list inside ManagedServices of all the assistants,
+            // mServices is the list inside ManagedServices of all the rankers,
             // There should be only one, but it's a list, so while we enforce
             // singularity elsewhere, we keep it general here, to avoid surprises.
-            for (final ManagedServiceInfo info : NotificationAssistant.this.mServices) {
+            for (final ManagedServiceInfo info : NotificationRankers.this.mServices) {
                 boolean sbnVisible = isVisibleToListener(sbn, info);
                 if (!sbnVisible) {
                     continue;
@@ -3542,7 +3551,7 @@
                 final int importance = r.getImportance();
                 final boolean fromUser = r.isImportanceFromUser();
                 final StatusBarNotification sbnToPost =  trimCache.ForListener(info);
-                mAssistantHandler.post(new Runnable() {
+                mHandler.post(new Runnable() {
                     @Override
                     public void run() {
                         notifyEnqueued(info, sbnToPost, importance, fromUser);
@@ -3553,12 +3562,12 @@
 
         private void notifyEnqueued(final ManagedServiceInfo info,
                 final StatusBarNotification sbn, int importance, boolean fromUser) {
-            final INotificationListener assistant = (INotificationListener) info.service;
+            final INotificationListener ranker = (INotificationListener) info.service;
             StatusBarNotificationHolder sbnHolder = new StatusBarNotificationHolder(sbn);
             try {
-                assistant.onNotificationEnqueued(sbnHolder, importance, fromUser);
+                ranker.onNotificationEnqueued(sbnHolder, importance, fromUser);
             } catch (RemoteException ex) {
-                Log.e(TAG, "unable to notify assistant (enqueued): " + assistant, ex);
+                Log.e(TAG, "unable to notify ranker (enqueued): " + ranker, ex);
             }
         }
 
diff --git a/services/core/java/com/android/server/notification/NotificationRecord.java b/services/core/java/com/android/server/notification/NotificationRecord.java
index 6c5685d..fd893fa 100644
--- a/services/core/java/com/android/server/notification/NotificationRecord.java
+++ b/services/core/java/com/android/server/notification/NotificationRecord.java
@@ -15,6 +15,7 @@
  */
 package com.android.server.notification;
 
+import static android.service.notification.NotificationListenerService.Ranking.IMPORTANCE_MIN;
 import static android.service.notification.NotificationListenerService.Ranking.IMPORTANCE_UNSPECIFIED;
 import static android.service.notification.NotificationListenerService.Ranking.IMPORTANCE_DEFAULT;
 import static android.service.notification.NotificationListenerService.Ranking.IMPORTANCE_HIGH;
@@ -33,6 +34,8 @@
 import android.os.UserHandle;
 import android.service.notification.NotificationListenerService;
 import android.service.notification.StatusBarNotification;
+import android.util.Log;
+import android.util.Slog;
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.server.EventLogTags;
@@ -55,6 +58,8 @@
  * {@hide}
  */
 public final class NotificationRecord {
+    static final String TAG = "NotificationRecord";
+    static final boolean DBG = Log.isLoggable(TAG, Log.DEBUG);
     final StatusBarNotification sbn;
     final int mOriginalFlags;
     private final Context mContext;
@@ -123,6 +128,8 @@
 
         switch (n.priority) {
             case Notification.PRIORITY_MIN:
+                importance = IMPORTANCE_MIN;
+                break;
             case Notification.PRIORITY_LOW:
                 importance = IMPORTANCE_LOW;
                 break;
@@ -143,25 +150,15 @@
                 || n.sound != null
                 || n.vibrate != null;
         stats.isNoisy = isNoisy;
-        if (!isNoisy && importance > IMPORTANCE_DEFAULT) {
-            importance = IMPORTANCE_DEFAULT;
+
+        if (!isNoisy && importance > IMPORTANCE_LOW) {
+            importance = IMPORTANCE_LOW;
         }
 
-        try {
-            final ApplicationInfo applicationInfo =
-                    mContext.getPackageManager().getApplicationInfoAsUser(sbn.getPackageName(),
-                            0, sbn.getUser().getIdentifier());
-            if (applicationInfo.targetSdkVersion < Build.VERSION_CODES.N) {
-                if (isNoisy) {
-                    if (importance >= IMPORTANCE_HIGH) {
-                        importance = IMPORTANCE_MAX;
-                    } else {
-                        importance = IMPORTANCE_HIGH;
-                    }
-                }
+        if (isNoisy) {
+            if (importance < IMPORTANCE_DEFAULT) {
+                importance = IMPORTANCE_DEFAULT;
             }
-        } catch (NameNotFoundException e) {
-            // oh well.
         }
 
         if (n.fullScreenIntent != null) {
diff --git a/services/core/java/com/android/server/notification/NotificationUsageStats.java b/services/core/java/com/android/server/notification/NotificationUsageStats.java
index 0272850..538f951 100644
--- a/services/core/java/com/android/server/notification/NotificationUsageStats.java
+++ b/services/core/java/com/android/server/notification/NotificationUsageStats.java
@@ -597,8 +597,9 @@
 
     private static class ImportanceHistogram {
         // TODO define these somewhere else
-        private static final int NUM_IMPORTANCES = 5;
-        private static final String[] IMPORTANCE_NAMES = {"none", "low", "default", "high", "max"};
+        private static final int NUM_IMPORTANCES = 6;
+        private static final String[] IMPORTANCE_NAMES =
+                {"none", "min", "low", "default", "high", "max"};
         private final Context mContext;
         private final String[] mCounterNames;
         private final String mPrefix;
diff --git a/services/core/java/com/android/server/notification/ZenModeConditions.java b/services/core/java/com/android/server/notification/ZenModeConditions.java
index 9cdece5..0945065 100644
--- a/services/core/java/com/android/server/notification/ZenModeConditions.java
+++ b/services/core/java/com/android/server/notification/ZenModeConditions.java
@@ -50,7 +50,7 @@
             mConditionProviders.addSystemProvider(new ScheduleConditionProvider());
         }
         if (mConditionProviders.isSystemProviderEnabled(ZenModeConfig.EVENT_PATH)) {
-            mConditionProviders.addSystemProvider(new EventConditionProvider(helper.getLooper()));
+            mConditionProviders.addSystemProvider(new EventConditionProvider());
         }
         mConditionProviders.setCallback(this);
     }
diff --git a/services/core/java/com/android/server/notification/ZenModeHelper.java b/services/core/java/com/android/server/notification/ZenModeHelper.java
index 383c1ab..5c5c8f8 100644
--- a/services/core/java/com/android/server/notification/ZenModeHelper.java
+++ b/services/core/java/com/android/server/notification/ZenModeHelper.java
@@ -238,13 +238,13 @@
         return mZenMode;
     }
 
-    public List<AutomaticZenRule> getAutomaticZenRules() {
-        List<AutomaticZenRule> rules = new ArrayList<>();
+    public List<ZenRule> getZenRules() {
+        List<ZenRule> rules = new ArrayList<>();
         synchronized (mConfig) {
             if (mConfig == null) return rules;
             for (ZenRule rule : mConfig.automaticRules.values()) {
                 if (canManageAutomaticZenRule(rule)) {
-                    rules.add(createAutomaticZenRule(rule));
+                    rules.add(rule);
                 }
             }
         }
@@ -264,18 +264,18 @@
         return null;
     }
 
-    public AutomaticZenRule addAutomaticZenRule(AutomaticZenRule automaticZenRule, String reason) {
-        if (!TextUtils.isEmpty(automaticZenRule.getId())) {
-            throw new IllegalArgumentException("Rule already exists");
-        }
+    public String addAutomaticZenRule(AutomaticZenRule automaticZenRule, String reason) {
         if (!isSystemRule(automaticZenRule)) {
             ServiceInfo owner = getServiceInfo(automaticZenRule.getOwner());
             if (owner == null) {
                 throw new IllegalArgumentException("Owner is not a condition provider service");
             }
 
-            final int ruleInstanceLimit = owner.metaData.getInt(
-                    ConditionProviderService.META_DATA_RULE_INSTANCE_LIMIT, -1);
+            int ruleInstanceLimit = -1;
+            if (owner.metaData != null) {
+                ruleInstanceLimit = owner.metaData.getInt(
+                        ConditionProviderService.META_DATA_RULE_INSTANCE_LIMIT, -1);
+            }
             if (ruleInstanceLimit > 0 && ruleInstanceLimit
                     < (getCurrentInstanceCount(automaticZenRule.getOwner()) + 1)) {
                 throw new IllegalArgumentException("Rule instance limit exceeded");
@@ -293,14 +293,15 @@
             populateZenRule(automaticZenRule, rule, true);
             newConfig.automaticRules.put(rule.id, rule);
             if (setConfigLocked(newConfig, reason, true)) {
-                return createAutomaticZenRule(rule);
+                return rule.id;
             } else {
                 return null;
             }
         }
     }
 
-    public boolean updateAutomaticZenRule(AutomaticZenRule automaticZenRule, String reason) {
+    public boolean updateAutomaticZenRule(String ruleId, AutomaticZenRule automaticZenRule,
+            String reason) {
         ZenModeConfig newConfig;
         synchronized (mConfig) {
             if (mConfig == null) return false;
@@ -309,7 +310,6 @@
                         + " reason=" + reason);
             }
             newConfig = mConfig.copy();
-            final String ruleId = automaticZenRule.getId();
             ZenModeConfig.ZenRule rule;
             if (ruleId == null) {
                 throw new IllegalArgumentException("Rule doesn't exist");
@@ -437,7 +437,7 @@
     private AutomaticZenRule createAutomaticZenRule(ZenRule rule) {
         return new AutomaticZenRule(rule.name, rule.component, rule.conditionId,
                 NotificationManager.zenModeToInterruptionFilter(rule.zenMode), rule.enabled,
-                rule.id, rule.creationTime);
+                rule.creationTime);
     }
 
     public void setManualZenMode(int zenMode, Uri conditionId, String reason) {
diff --git a/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java b/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java
index 9a5a183..27c8293 100644
--- a/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java
+++ b/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java
@@ -31,6 +31,7 @@
 import android.net.Uri;
 import android.os.Build;
 import android.os.UserHandle;
+import android.print.PrintManager;
 import android.provider.CalendarContract;
 import android.provider.ContactsContract;
 import android.provider.MediaStore;
@@ -579,7 +580,7 @@
 
             // Print Spooler
             PackageParser.Package printSpoolerPackage = getSystemPackageLPr(
-                    "com.android.printspooler");
+                    PrintManager.PRINT_SPOOLER_PACKAGE_NAME);
             if (printSpoolerPackage != null
                     && doesPackageSupportRuntimePermissions(printSpoolerPackage)) {
                 grantRuntimePermissionsLPw(printSpoolerPackage, LOCATION_PERMISSIONS, true, userId);
@@ -714,7 +715,8 @@
     private PackageParser.Package getDefaultSystemHandlerServicePackageLPr(
             Intent intent, int userId) {
         List<ResolveInfo> handlers = mService.queryIntentServices(intent,
-                intent.resolveType(mService.mContext.getContentResolver()), DEFAULT_FLAGS, userId);
+                intent.resolveType(mService.mContext.getContentResolver()), DEFAULT_FLAGS, userId)
+                .getList();
         if (handlers == null) {
             return null;
         }
@@ -788,7 +790,7 @@
     }
 
     private void grantRuntimePermissionsLPw(PackageParser.Package pkg, Set<String> permissions,
-            boolean systemFixed, boolean overrideUserChoice,  int userId) {
+            boolean systemFixed, boolean isDefaultPhoneOrSms, int userId) {
         if (pkg.requestedPermissions.isEmpty()) {
             return;
         }
@@ -796,7 +798,13 @@
         List<String> requestedPermissions = pkg.requestedPermissions;
         Set<String> grantablePermissions = null;
 
-        if (pkg.isUpdatedSystemApp()) {
+        // If this is the default Phone or SMS app we grant permissions regardless
+        // whether the version on the system image declares the permission as used since
+        // selecting the app as the default Phone or SMS the user makes a deliberate
+        // choice to grant this app the permissions needed to function. For all other
+        // apps, (default grants on first boot and user creation) we don't grant default
+        // permissions if the version on the system image does not declare them.
+        if (!isDefaultPhoneOrSms && pkg.isUpdatedSystemApp()) {
             PackageSetting sysPs = mService.mSettings.getDisabledSystemPkgLPr(pkg.packageName);
             if (sysPs != null) {
                 if (sysPs.pkg.requestedPermissions.isEmpty()) {
@@ -828,7 +836,7 @@
                 // Unless the caller wants to override user choices. The override is
                 // to make sure we can grant the needed permission to the default
                 // sms and phone apps after the user chooses this in the UI.
-                if (flags == 0 || overrideUserChoice) {
+                if (flags == 0 || isDefaultPhoneOrSms) {
                     // Never clobber policy or system.
                     final int fixedFlags = PackageManager.FLAG_PERMISSION_SYSTEM_FIXED
                             | PackageManager.FLAG_PERMISSION_POLICY_FIXED;
diff --git a/services/core/java/com/android/server/pm/EphemeralApplicationRegistry.java b/services/core/java/com/android/server/pm/EphemeralApplicationRegistry.java
index 8786350..389e0a1 100644
--- a/services/core/java/com/android/server/pm/EphemeralApplicationRegistry.java
+++ b/services/core/java/com/android/server/pm/EphemeralApplicationRegistry.java
@@ -210,6 +210,9 @@
     }
 
     public void onPackageUninstalledLPw(PackageParser.Package pkg) {
+        if (pkg == null) {
+            return;
+        }
         PackageSetting ps = (PackageSetting) pkg.mExtras;
         if (ps == null) {
             return;
diff --git a/services/core/java/com/android/server/pm/Installer.java b/services/core/java/com/android/server/pm/Installer.java
index 1476e6e..206a143 100644
--- a/services/core/java/com/android/server/pm/Installer.java
+++ b/services/core/java/com/android/server/pm/Installer.java
@@ -166,6 +166,10 @@
         mInstaller.execute("rmpackagedir", packageDir);
     }
 
+    public void rmProfiles(String pkgName) throws InstallerException {
+        mInstaller.execute("rmprofiles", pkgName);
+    }
+
     public void createUserConfig(int userid) throws InstallerException {
         mInstaller.execute("mkuserconfig", userid);
     }
@@ -203,6 +207,11 @@
         mInstaller.execute("linkfile", relativePath, fromBase, toBase);
     }
 
+    public void moveAb(String apkPath, String instructionSet, String outputPath)
+            throws InstallerException {
+        mInstaller.execute("move_ab", apkPath, instructionSet, outputPath);
+    }
+
     private static void assertValidInstructionSet(String instructionSet)
             throws InstallerException {
         for (String abi : Build.SUPPORTED_ABIS) {
diff --git a/services/core/java/com/android/server/pm/LauncherAppsService.java b/services/core/java/com/android/server/pm/LauncherAppsService.java
index 8d75f60..b7cd318 100644
--- a/services/core/java/com/android/server/pm/LauncherAppsService.java
+++ b/services/core/java/com/android/server/pm/LauncherAppsService.java
@@ -16,6 +16,9 @@
 
 package com.android.server.pm;
 
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.UserIdInt;
 import android.app.AppGlobals;
 import android.content.ComponentName;
 import android.content.Context;
@@ -27,14 +30,19 @@
 import android.content.pm.IPackageManager;
 import android.content.pm.PackageInfo;
 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.ShortcutServiceInternal;
+import android.content.pm.ShortcutServiceInternal.ShortcutChangeListener;
 import android.content.pm.UserInfo;
 import android.graphics.Rect;
 import android.net.Uri;
 import android.os.Binder;
 import android.os.Bundle;
 import android.os.IInterface;
+import android.os.ParcelFileDescriptor;
 import android.os.RemoteCallbackList;
 import android.os.RemoteException;
 import android.os.UserHandle;
@@ -43,16 +51,18 @@
 import android.util.Log;
 import android.util.Slog;
 
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.content.PackageMonitor;
+import com.android.internal.util.Preconditions;
+import com.android.server.LocalServices;
 import com.android.server.SystemService;
 
 import java.util.List;
 
 /**
  * Service that manages requests and callbacks for launchers that support
- * managed profiles. 
+ * managed profiles.
  */
-
 public class LauncherAppsService extends SystemService {
 
     private final LauncherAppsImpl mLauncherAppsImpl;
@@ -67,21 +77,26 @@
         publishBinderService(Context.LAUNCHER_APPS_SERVICE, mLauncherAppsImpl);
     }
 
-    class LauncherAppsImpl extends ILauncherApps.Stub {
+    @VisibleForTesting
+    static class LauncherAppsImpl extends ILauncherApps.Stub {
         private static final boolean DEBUG = false;
         private static final String TAG = "LauncherAppsService";
         private final Context mContext;
         private final PackageManager mPm;
         private final UserManager mUm;
+        private final ShortcutServiceInternal mShortcutServiceInternal;
         private final PackageCallbackList<IOnAppsChangedListener> mListeners
                 = new PackageCallbackList<IOnAppsChangedListener>();
 
-        private MyPackageMonitor mPackageMonitor = new MyPackageMonitor();
+        private final MyPackageMonitor mPackageMonitor = new MyPackageMonitor();
 
         public LauncherAppsImpl(Context context) {
             mContext = context;
             mPm = mContext.getPackageManager();
             mUm = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
+            mShortcutServiceInternal = Preconditions.checkNotNull(
+                    LocalServices.getService(ShortcutServiceInternal.class));
+            mShortcutServiceInternal.addListener(mPackageMonitor);
         }
 
         /*
@@ -154,7 +169,8 @@
         /**
          * Checks if the caller is in the same group as the userToCheck.
          */
-        private void ensureInUserProfiles(UserHandle userToCheck, String message) {
+        @VisibleForTesting // We override it in unit tests
+        void ensureInUserProfiles(UserHandle userToCheck, String message) {
             final int callingUserId = UserHandle.getCallingUserId();
             final int targetUserId = userToCheck.getIdentifier();
 
@@ -174,6 +190,22 @@
             }
         }
 
+        @VisibleForTesting // We override it in unit tests
+        void verifyCallingPackage(String callingPackage) {
+            int packageUid = -1;
+            try {
+                packageUid = mPm.getPackageUidAsUser(callingPackage,
+                        PackageManager.MATCH_ENCRYPTION_AWARE_AND_UNAWARE
+                                | PackageManager.MATCH_UNINSTALLED_PACKAGES,
+                        UserHandle.getUserId(getCallingUid()));
+            } catch (NameNotFoundException e) {
+                Log.e(TAG, "Package not found: " + callingPackage);
+            }
+            if (packageUid != Binder.getCallingUid()) {
+                throw new SecurityException("Calling package name mismatch");
+            }
+        }
+
         /**
          * Checks if the user is enabled.
          */
@@ -264,6 +296,90 @@
             }
         }
 
+        private void enforceShortcutPermission(UserHandle user) {
+            ensureInUserProfiles(user, "Cannot start activity for unrelated profile " + user);
+            // STOPSHIP Implement it
+        }
+
+        @Override
+        public ParceledListSlice getShortcuts(String callingPackage, long changedSince,
+                String packageName, ComponentName componentName, int flags, UserHandle user)
+                throws RemoteException {
+            enforceShortcutPermission(user);
+            verifyCallingPackage(callingPackage);
+
+            return new ParceledListSlice<>(
+                    mShortcutServiceInternal.getShortcuts(callingPackage, changedSince, packageName,
+                    componentName, flags, user.getIdentifier()));
+        }
+
+        @Override
+        public ParceledListSlice getShortcutInfo(String callingPackage, String packageName,
+                List<String> ids, UserHandle user) throws RemoteException {
+            enforceShortcutPermission(user);
+            verifyCallingPackage(callingPackage);
+
+            return new ParceledListSlice<>(
+                    mShortcutServiceInternal.getShortcutInfo(callingPackage, packageName,
+                    ids, user.getIdentifier()));
+        }
+
+        @Override
+        public void pinShortcuts(String callingPackage, String packageName, List<String> ids,
+                UserHandle user) throws RemoteException {
+            enforceShortcutPermission(user);
+            verifyCallingPackage(callingPackage);
+
+            mShortcutServiceInternal.pinShortcuts(callingPackage, packageName,
+                    ids, user.getIdentifier());
+        }
+
+        @Override
+        public int getShortcutIconResId(String callingPackage, ShortcutInfo shortcut,
+                UserHandle user) {
+            enforceShortcutPermission(user);
+            verifyCallingPackage(callingPackage);
+
+            return mShortcutServiceInternal.getShortcutIconResId(callingPackage, shortcut,
+                    user.getIdentifier());
+        }
+
+        @Override
+        public ParcelFileDescriptor getShortcutIconFd(String callingPackage, ShortcutInfo shortcut,
+                UserHandle user) {
+            enforceShortcutPermission(user);
+            verifyCallingPackage(callingPackage);
+
+            return mShortcutServiceInternal.getShortcutIconFd(callingPackage, shortcut,
+                    user.getIdentifier());
+        }
+
+        @Override
+        public boolean startShortcut(String callingPackage, String packageName, String shortcutId,
+                Rect sourceBounds, Bundle startActivityOptions, UserHandle user)
+                throws RemoteException {
+            enforceShortcutPermission(user);
+            verifyCallingPackage(callingPackage);
+
+            final Intent intent = mShortcutServiceInternal.createShortcutIntent(callingPackage,
+                    packageName, shortcutId, user.getIdentifier());
+            if (intent == null) {
+                return false;
+            }
+            // Note the target activity doesn't have to be exported.
+
+            intent.setSourceBounds(sourceBounds);
+            prepareIntentForLaunch(intent, sourceBounds);
+
+            final long ident = Binder.clearCallingIdentity();
+            try {
+                mContext.startActivityAsUser(intent, startActivityOptions, user);
+            } finally {
+                Binder.restoreCallingIdentity(ident);
+            }
+            return true;
+        }
+
         @Override
         public boolean isActivityEnabled(ComponentName component, UserHandle user)
                 throws RemoteException {
@@ -293,9 +409,7 @@
 
             Intent launchIntent = new Intent(Intent.ACTION_MAIN);
             launchIntent.addCategory(Intent.CATEGORY_LAUNCHER);
-            launchIntent.setSourceBounds(sourceBounds);
-            launchIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
-                    | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
+            prepareIntentForLaunch(launchIntent, sourceBounds);
             launchIntent.setPackage(component.getPackageName());
 
             long ident = Binder.clearCallingIdentity();
@@ -332,6 +446,13 @@
             }
         }
 
+        private void prepareIntentForLaunch(@NonNull Intent launchIntent,
+                @Nullable Rect sourceBounds) {
+            launchIntent.setSourceBounds(sourceBounds);
+            launchIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
+                    | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
+        }
+
         @Override
         public void showAppDetailsAsUser(ComponentName component, Rect sourceBounds,
                 Bundle opts, UserHandle user) throws RemoteException {
@@ -355,7 +476,7 @@
         }
 
 
-        private class MyPackageMonitor extends PackageMonitor {
+        private class MyPackageMonitor extends PackageMonitor implements ShortcutChangeListener {
 
             /** Checks if user is a profile of or same as listeningUser.
               * and the user is enabled. */
@@ -390,6 +511,8 @@
                 }
             }
 
+            // TODO Simplify with lambdas.
+
             @Override
             public void onPackageAdded(String packageName, int uid) {
                 UserHandle user = new UserHandle(getChangingUserId());
@@ -523,6 +646,25 @@
                 super.onPackagesUnsuspended(packages);
             }
 
+            @Override
+            public void onShortcutChanged(@NonNull String packageName,
+                    @NonNull List<ShortcutInfo> shortcuts, @UserIdInt int userId) {
+                final UserHandle user = UserHandle.of(userId);
+
+                final int n = mListeners.beginBroadcast();
+                for (int i = 0; i < n; i++) {
+                    IOnAppsChangedListener listener = mListeners.getBroadcastItem(i);
+                    UserHandle listeningUser = (UserHandle) mListeners.getBroadcastCookie(i);
+                    if (!isEnabledProfileOf(user, listeningUser, "onShortcutChanged")) continue;
+                    try {
+                        listener.onShortcutChanged(user, packageName,
+                                new ParceledListSlice<>(shortcuts));
+                    } catch (RemoteException re) {
+                        Slog.d(TAG, "Callback failed ", re);
+                    }
+                }
+                mListeners.finishBroadcast();
+            }
         }
 
         class PackageCallbackList<T extends IInterface> extends RemoteCallbackList<T> {
diff --git a/services/core/java/com/android/server/pm/OtaDexoptService.java b/services/core/java/com/android/server/pm/OtaDexoptService.java
index 94b3b2d..67aeed1 100644
--- a/services/core/java/com/android/server/pm/OtaDexoptService.java
+++ b/services/core/java/com/android/server/pm/OtaDexoptService.java
@@ -16,36 +16,28 @@
 
 package com.android.server.pm;
 
-import android.app.AppGlobals;
+import static com.android.server.pm.Installer.DEXOPT_OTA;
+import static com.android.server.pm.InstructionSets.getAppDexInstructionSets;
+import static com.android.server.pm.InstructionSets.getDexCodeInstructionSets;
+
 import android.content.Context;
-import android.content.Intent;
 import android.content.pm.IOtaDexopt;
 import android.content.pm.PackageParser;
 import android.content.pm.PackageParser.Package;
-import android.content.pm.ResolveInfo;
 import android.os.Environment;
 import android.os.RemoteException;
 import android.os.ResultReceiver;
 import android.os.ServiceManager;
-import android.os.UserHandle;
 import android.os.storage.StorageManager;
-import android.util.ArraySet;
 import android.util.Log;
+import android.util.Slog;
 
-import dalvik.system.DexFile;
+import com.android.internal.os.InstallerConnection.InstallerException;
 
 import java.io.File;
 import java.io.FileDescriptor;
-import java.util.ArrayList;
 import java.util.Collection;
-import java.util.Date;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.LinkedList;
 import java.util.List;
-import java.util.Set;
-
-import static com.android.server.pm.Installer.DEXOPT_OTA;
 
 /**
  * A service for A/B OTA dexopting.
@@ -70,6 +62,9 @@
         // Use the package manager install and install lock here for the OTA dex optimizer.
         mPackageDexOptimizer = new OTADexoptPackageDexOptimizer(packageManagerService.mInstaller,
                 packageManagerService.mInstallLock, context);
+
+        // Now it's time to check whether we need to move any A/B artifacts.
+        moveAbArtifacts(packageManagerService.mInstaller);
     }
 
     public static OtaDexoptService main(Context context,
@@ -150,20 +145,50 @@
                 false /* extractOnly */);
     }
 
-    private ArraySet<String> getPackageNamesForIntent(Intent intent, int userId) {
-        List<ResolveInfo> ris = null;
-        try {
-            ris = AppGlobals.getPackageManager().queryIntentReceivers(
-                    intent, null, 0, userId);
-        } catch (RemoteException e) {
+    private void moveAbArtifacts(Installer installer) {
+        if (mDexoptPackages != null) {
+            throw new IllegalStateException("Should not be ota-dexopting when trying to move.");
         }
-        ArraySet<String> pkgNames = new ArraySet<String>(ris == null ? 0 : ris.size());
-        if (ris != null) {
-            for (ResolveInfo ri : ris) {
-                pkgNames.add(ri.activityInfo.packageName);
+
+        // Look into all packages.
+        Collection<PackageParser.Package> pkgs = mPackageManagerService.getPackages();
+        for (PackageParser.Package pkg : pkgs) {
+            if (pkg == null) {
+                continue;
+            }
+
+            // Does the package have code? If not, there won't be any artifacts.
+            if (!PackageDexOptimizer.canOptimizePackage(pkg)) {
+                continue;
+            }
+            if (pkg.codePath == null) {
+                Slog.w(TAG, "Package " + pkg + " can be optimized but has null codePath");
+                continue;
+            }
+
+            // If the path is in /system or /vendor, ignore. It will have been ota-dexopted into
+            // /data/ota and moved into the dalvik-cache already.
+            if (pkg.codePath.startsWith("/system") || pkg.codePath.startsWith("/vendor")) {
+                continue;
+            }
+
+            final String[] instructionSets = getAppDexInstructionSets(pkg.applicationInfo);
+            final List<String> paths = pkg.getAllCodePathsExcludingResourceOnly();
+            final String[] dexCodeInstructionSets = getDexCodeInstructionSets(instructionSets);
+            for (String dexCodeInstructionSet : dexCodeInstructionSets) {
+                for (String path : paths) {
+                    String oatDir = PackageDexOptimizer.getOatDir(new File(pkg.codePath)).
+                            getAbsolutePath();
+
+                    // TODO: Check first whether there is an artifact, to save the roundtrip time.
+
+                    try {
+                        installer.moveAb(path, dexCodeInstructionSet, oatDir);
+                    } catch (InstallerException e) {
+                    }
+                }
             }
         }
-        return pkgNames;
     }
 
     private static class OTADexoptPackageDexOptimizer extends
@@ -180,10 +205,5 @@
             return dexoptFlags | DEXOPT_OTA;
         }
 
-        @Override
-        protected void recordSuccessfulDexopt(Package pkg, String instructionSet) {
-            // Never record the dexopt, as it's in the B partition.
-        }
-
     }
 }
diff --git a/services/core/java/com/android/server/pm/PackageDexOptimizer.java b/services/core/java/com/android/server/pm/PackageDexOptimizer.java
index a3af561..561682c 100644
--- a/services/core/java/com/android/server/pm/PackageDexOptimizer.java
+++ b/services/core/java/com/android/server/pm/PackageDexOptimizer.java
@@ -21,6 +21,7 @@
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageParser;
 import android.content.pm.PackageParser.Package;
+import android.os.Environment;
 import android.os.PowerManager;
 import android.os.UserHandle;
 import android.os.WorkSource;
@@ -112,15 +113,6 @@
     }
 
     /**
-     * Determine whether the package should be skipped for the given instruction set. A return
-     * value of true means the package will be skipped. A return value of false means that the
-     * package will be further investigated, and potentially compiled.
-     */
-    protected boolean shouldSkipBasedOnISA(PackageParser.Package pkg, String instructionSet) {
-        return pkg.mDexOptPerformed.contains(instructionSet);
-    }
-
-    /**
      * Adjust the given dexopt-needed value. Can be overridden to influence the decision to
      * optimize or not (and in what way).
      */
@@ -135,13 +127,6 @@
         return dexoptFlags;
     }
 
-    /**
-     * Update the package status after a successful compilation.
-     */
-    protected void recordSuccessfulDexopt(PackageParser.Package pkg, String instructionSet) {
-        pkg.mDexOptPerformed.add(instructionSet);
-    }
-
     private int performDexOptLI(PackageParser.Package pkg, String[] targetInstructionSets,
             boolean useProfiles, boolean extractOnly) {
         final String[] instructionSets = targetInstructionSets != null ?
@@ -158,54 +143,63 @@
         boolean performedDexOpt = false;
         final String[] dexCodeInstructionSets = getDexCodeInstructionSets(instructionSets);
         for (String dexCodeInstructionSet : dexCodeInstructionSets) {
-            if (!useProfiles && shouldSkipBasedOnISA(pkg, dexCodeInstructionSet)) {
-                // Skip only if we do not use profiles since they might trigger a recompilation.
-                continue;
-            }
-
             for (String path : paths) {
+                if (useProfiles && isUsedByOtherApps(path)) {
+                    // We cannot use profile guided compilation if the apk was used by another app.
+                    useProfiles = false;
+                }
                 int dexoptNeeded;
 
                 try {
-                    dexoptNeeded = DexFile.getDexOptNeeded(path, pkg.packageName,
-                            dexCodeInstructionSet, /* defer */false);
+                    int compilationTypeMask = 0;
+                    if (extractOnly) {
+                        // For extract only, any type of compilation is good.
+                        compilationTypeMask = DexFile.COMPILATION_TYPE_FULL
+                            | DexFile.COMPILATION_TYPE_PROFILE_GUIDE
+                            | DexFile.COMPILATION_TYPE_EXTRACT_ONLY;
+                    } else {
+                        // Branch taken for profile guide and full compilation.
+                        // Profile guide compilation should only recompile a previous
+                        // profile compiled/extract only file and should not be attempted if the
+                        // apk is already fully compiled. So test against a full compilation type.
+                        compilationTypeMask = DexFile.COMPILATION_TYPE_FULL;
+                    }
+                    dexoptNeeded = DexFile.getDexOptNeeded(path,
+                            dexCodeInstructionSet, compilationTypeMask);
                 } catch (IOException ioe) {
                     Slog.w(TAG, "IOException reading apk: " + path, ioe);
                     return DEX_OPT_FAILED;
                 }
                 dexoptNeeded = adjustDexoptNeeded(dexoptNeeded);
 
-                if (dexoptNeeded == DexFile.NO_DEXOPT_NEEDED) {
-                    if (useProfiles) {
-                        // Profiles may trigger re-compilation. The final decision is taken in
-                        // installd.
-                        dexoptNeeded = DexFile.DEX2OAT_NEEDED;
-                    } else {
-                        // No dexopt needed and we don't use profiles. Nothing to do.
-                        continue;
-                    }
-                }
                 final String dexoptType;
                 String oatDir = null;
-                if (dexoptNeeded == DexFile.DEX2OAT_NEEDED) {
-                    dexoptType = "dex2oat";
-                    oatDir = createOatDirIfSupported(pkg, dexCodeInstructionSet);
-                } else if (dexoptNeeded == DexFile.PATCHOAT_NEEDED) {
-                    dexoptType = "patchoat";
-                } else if (dexoptNeeded == DexFile.SELF_PATCHOAT_NEEDED) {
-                    dexoptType = "self patchoat";
-                } else {
-                    throw new IllegalStateException("Invalid dexopt needed: " + dexoptNeeded);
+                switch (dexoptNeeded) {
+                    case DexFile.NO_DEXOPT_NEEDED:
+                        continue;
+                    case DexFile.DEX2OAT_NEEDED:
+                        dexoptType = "dex2oat";
+                        oatDir = createOatDirIfSupported(pkg, dexCodeInstructionSet);
+                        break;
+                    case DexFile.PATCHOAT_NEEDED:
+                        dexoptType = "patchoat";
+                        break;
+                    case DexFile.SELF_PATCHOAT_NEEDED:
+                        dexoptType = "self patchoat";
+                        break;
+                    default:
+                        throw new IllegalStateException("Invalid dexopt:" + dexoptNeeded);
                 }
 
-
                 Log.i(TAG, "Running dexopt (" + dexoptType + ") on: " + path + " pkg="
                         + pkg.applicationInfo.packageName + " isa=" + dexCodeInstructionSet
                         + " vmSafeMode=" + vmSafeMode + " debuggable=" + debuggable
                         + " extractOnly=" + extractOnly + " oatDir = " + oatDir);
                 final int sharedGid = UserHandle.getSharedAppGid(pkg.applicationInfo.uid);
+                // Profile guide compiled oat files should not be public.
+                final boolean isPublic = !pkg.isForwardLocked() && !useProfiles;
                 final int dexFlags = adjustDexoptFlags(
-                        (!pkg.isForwardLocked() ? DEXOPT_PUBLIC : 0)
+                        ( isPublic ? DEXOPT_PUBLIC : 0)
                         | (vmSafeMode ? DEXOPT_SAFEMODE : 0)
                         | (debuggable ? DEXOPT_DEBUGGABLE : 0)
                         | (extractOnly ? DEXOPT_EXTRACTONLY : 0)
@@ -219,15 +213,6 @@
                     Slog.w(TAG, "Failed to dexopt", e);
                 }
             }
-
-            if (!extractOnly) {
-                // At this point we haven't failed dexopt and we haven't deferred dexopt. We must
-                // either have either succeeded dexopt, or have had getDexOptNeeded tell us
-                // it isn't required. We therefore mark that this package doesn't need dexopt unless
-                // it's forced. performedDexOpt will tell us whether we performed dex-opt or skipped
-                // it.
-                recordSuccessfulDexopt(pkg, dexCodeInstructionSet);
-            }
         }
 
         // If we've gotten here, we're sure that no error occurred and that we haven't
@@ -275,6 +260,25 @@
         mSystemReady = true;
     }
 
+    private boolean isUsedByOtherApps(String apkPath) {
+        try {
+            apkPath = new File(apkPath).getCanonicalPath();
+        } catch (IOException e) {
+            // Log an error but continue without it.
+            Slog.w(TAG, "Failed to get canonical path", e);
+        }
+        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;
+    }
+
     /**
      * A specialized PackageDexOptimizer that overrides already-installed checks, forcing a
      * dexopt path.
@@ -291,12 +295,6 @@
         }
 
         @Override
-        protected boolean shouldSkipBasedOnISA(Package pkg, String instructionSet) {
-            // Forced compilation, never skip.
-            return false;
-        }
-
-        @Override
         protected int adjustDexoptNeeded(int dexoptNeeded) {
             // Ensure compilation, no matter the current state.
             // TODO: The return value is wrong when patchoat is needed.
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index b84ffa3..ef53905 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -34,6 +34,7 @@
 import android.content.pm.ApplicationInfo;
 import android.content.pm.IPackageInstallObserver2;
 import android.content.pm.IPackageInstallerSession;
+import android.content.pm.PackageInfo;
 import android.content.pm.PackageInstaller;
 import android.content.pm.PackageInstaller.SessionInfo;
 import android.content.pm.PackageInstaller.SessionParams;
@@ -58,6 +59,7 @@
 import android.system.Os;
 import android.system.OsConstants;
 import android.system.StructStat;
+import android.text.TextUtils;
 import android.util.ArraySet;
 import android.util.ExceptionUtils;
 import android.util.MathUtils;
@@ -77,6 +79,7 @@
 
 import java.io.File;
 import java.io.FileDescriptor;
+import java.io.FileFilter;
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -86,6 +89,7 @@
 public class PackageInstallerSession extends IPackageInstallerSession.Stub {
     private static final String TAG = "PackageInstaller";
     private static final boolean LOGD = true;
+    private static final String REMOVE_SPLIT_MARKER_EXTENSION = ".removed";
 
     private static final int MSG_COMMIT = 0;
 
@@ -171,6 +175,25 @@
     @GuardedBy("mLock")
     private File mInheritedFilesBase;
 
+    private static final FileFilter sAddedFilter = new FileFilter() {
+        @Override
+        public boolean accept(File file) {
+            // Installers can't stage directories, so it's fine to ignore
+            // entries like "lost+found".
+            if (file.isDirectory()) return false;
+            if (file.getName().endsWith(REMOVE_SPLIT_MARKER_EXTENSION)) return false;
+            return true;
+        }
+    };
+    private static final FileFilter sRemovedFilter = new FileFilter() {
+        @Override
+        public boolean accept(File file) {
+            if (file.isDirectory()) return false;
+            if (!file.getName().endsWith(REMOVE_SPLIT_MARKER_EXTENSION)) return false;
+            return true;
+        }
+    };
+
     private final Handler.Callback mHandlerCallback = new Handler.Callback() {
         @Override
         public boolean handleMessage(Message msg) {
@@ -346,6 +369,32 @@
     }
 
     @Override
+    public void removeSplit(String splitName) {
+        if (TextUtils.isEmpty(params.appPackageName)) {
+            throw new IllegalStateException("Must specify package name to remove a split");
+        }
+        try {
+            createRemoveSplitMarker(splitName);
+        } catch (IOException e) {
+            throw ExceptionUtils.wrap(e);
+        }
+    }
+
+    private void createRemoveSplitMarker(String splitName) throws IOException {
+        try {
+            final String markerName = splitName + REMOVE_SPLIT_MARKER_EXTENSION;
+            if (!FileUtils.isValidExtFilename(markerName)) {
+                throw new IllegalArgumentException("Invalid marker: " + markerName);
+            }
+            final File target = new File(resolveStageDir(), markerName);
+            target.createNewFile();
+            Os.chmod(target.getAbsolutePath(), 0 /*mode*/);
+        } catch (ErrnoException e) {
+            throw e.rethrowAsIOException();
+        }
+    }
+
+    @Override
     public ParcelFileDescriptor openWrite(String name, long offsetBytes, long lengthBytes) {
         try {
             return openWriteInternal(name, offsetBytes, lengthBytes);
@@ -608,22 +657,28 @@
         mResolvedStagedFiles.clear();
         mResolvedInheritedFiles.clear();
 
-        final File[] files = mResolvedStageDir.listFiles();
-        if (ArrayUtils.isEmpty(files)) {
-            throw new PackageManagerException(INSTALL_FAILED_INVALID_APK, "No packages staged");
+        final File[] removedFiles = mResolvedStageDir.listFiles(sRemovedFilter);
+        final List<String> removeSplitList = new ArrayList<>();
+        if (!ArrayUtils.isEmpty(removedFiles)) {
+            for (File removedFile : removedFiles) {
+                final String fileName = removedFile.getName();
+                final String splitName = fileName.substring(
+                        0, fileName.length() - REMOVE_SPLIT_MARKER_EXTENSION.length());
+                removeSplitList.add(splitName);
+            }
         }
 
+        final File[] addedFiles = mResolvedStageDir.listFiles(sAddedFilter);
+        if (ArrayUtils.isEmpty(addedFiles) && removeSplitList.size() == 0) {
+            throw new PackageManagerException(INSTALL_FAILED_INVALID_APK, "No packages staged");
+        }
         // Verify that all staged packages are internally consistent
         final ArraySet<String> stagedSplits = new ArraySet<>();
-        for (File file : files) {
-
-            // Installers can't stage directories, so it's fine to ignore
-            // entries like "lost+found".
-            if (file.isDirectory()) continue;
-
+        for (File addedFile : addedFiles) {
             final ApkLite apk;
             try {
-                apk = PackageParser.parseApkLite(file, PackageParser.PARSE_COLLECT_CERTIFICATES);
+                apk = PackageParser.parseApkLite(
+                        addedFile, PackageParser.PARSE_COLLECT_CERTIFICATES);
             } catch (PackageParserException e) {
                 throw PackageManagerException.from(e);
             }
@@ -642,7 +697,7 @@
                 mSignatures = apk.signatures;
             }
 
-            assertApkConsistent(String.valueOf(file), apk);
+            assertApkConsistent(String.valueOf(addedFile), apk);
 
             // Take this opportunity to enforce uniform naming
             final String targetName;
@@ -657,8 +712,8 @@
             }
 
             final File targetFile = new File(mResolvedStageDir, targetName);
-            if (!file.equals(targetFile)) {
-                file.renameTo(targetFile);
+            if (!addedFile.equals(targetFile)) {
+                addedFile.renameTo(targetFile);
             }
 
             // Base is coming from session
@@ -669,6 +724,27 @@
             mResolvedStagedFiles.add(targetFile);
         }
 
+        if (removeSplitList.size() > 0) {
+            // validate split names marked for removal
+            final int flags = mSignatures == null ? PackageManager.GET_SIGNATURES : 0;
+            final PackageInfo pkg = mPm.getPackageInfo(params.appPackageName, flags, userId);
+            for (String splitName : removeSplitList) {
+                if (!ArrayUtils.contains(pkg.splitNames, splitName)) {
+                    throw new PackageManagerException(INSTALL_FAILED_INVALID_APK,
+                            "Split not found: " + splitName);
+                }
+            }
+
+            // ensure we've got appropriate package name, version code and signatures
+            if (mPackageName == null) {
+                mPackageName = pkg.packageName;
+                mVersionCode = pkg.versionCode;
+            }
+            if (mSignatures == null) {
+                mSignatures = pkg.signatures;
+            }
+        }
+
         if (params.mode == SessionParams.MODE_FULL_INSTALL) {
             // Full installs must include a base package
             if (!stagedSplits.contains(null)) {
@@ -707,8 +783,8 @@
                 for (int i = 0; i < existing.splitNames.length; i++) {
                     final String splitName = existing.splitNames[i];
                     final File splitFile = new File(existing.splitCodePaths[i]);
-
-                    if (!stagedSplits.contains(splitName)) {
+                    final boolean splitRemoved = removeSplitList.contains(splitName);
+                    if (!stagedSplits.contains(splitName) && !splitRemoved) {
                         mResolvedInheritedFiles.add(splitFile);
                     }
                 }
@@ -748,6 +824,11 @@
             throw new PackageManagerException(INSTALL_FAILED_INVALID_APK, tag + " package "
                     + apk.packageName + " inconsistent with " + mPackageName);
         }
+        if (params.appPackageName != null && !params.appPackageName.equals(apk.packageName)) {
+            throw new PackageManagerException(INSTALL_FAILED_INVALID_APK, tag
+                    + " specified package " + params.appPackageName
+                    + " inconsistent with " + apk.packageName);
+        }
         if (mVersionCode != apk.versionCode) {
             throw new PackageManagerException(INSTALL_FAILED_INVALID_APK, tag
                     + " version code " + apk.versionCode + " inconsistent with "
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 3f06c78..debe072 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -62,7 +62,9 @@
 import static android.content.pm.PackageManager.MATCH_ALL;
 import static android.content.pm.PackageManager.MATCH_DEBUG_TRIAGED_MISSING;
 import static android.content.pm.PackageManager.MATCH_DISABLED_COMPONENTS;
+import static android.content.pm.PackageManager.MATCH_ENCRYPTION_AWARE;
 import static android.content.pm.PackageManager.MATCH_ENCRYPTION_AWARE_AND_UNAWARE;
+import static android.content.pm.PackageManager.MATCH_ENCRYPTION_UNAWARE;
 import static android.content.pm.PackageManager.MATCH_SYSTEM_ONLY;
 import static android.content.pm.PackageManager.MATCH_UNINSTALLED_PACKAGES;
 import static android.content.pm.PackageManager.MOVE_FAILED_DEVICE_ADMIN;
@@ -101,6 +103,7 @@
 import android.app.ActivityManager;
 import android.app.ActivityManagerNative;
 import android.app.IActivityManager;
+import android.app.admin.DevicePolicyManagerInternal;
 import android.app.admin.IDevicePolicyManager;
 import android.app.backup.IBackupManager;
 import android.content.BroadcastReceiver;
@@ -153,7 +156,6 @@
 import android.content.pm.ServiceInfo;
 import android.content.pm.Signature;
 import android.content.pm.UserInfo;
-import android.content.pm.VerificationParams;
 import android.content.pm.VerifierDeviceIdentity;
 import android.content.pm.VerifierInfo;
 import android.content.res.Resources;
@@ -358,6 +360,7 @@
     static final int SCAN_MOVE = 1<<13;
     static final int SCAN_INITIAL = 1<<14;
     static final int SCAN_CHECK_ONLY = 1<<15;
+    static final int SCAN_DONT_KILL_APP = 1<<17;
 
     static final int REMOVE_CHATTY = 1<<16;
 
@@ -497,6 +500,9 @@
     final ArrayMap<String, PackageParser.Package> mPackages =
             new ArrayMap<String, PackageParser.Package>();
 
+    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>>();
@@ -637,9 +643,6 @@
     // List of packages names to keep cached, even if they are uninstalled for all users
     private List<String> mKeepUninstalledPackages;
 
-    private boolean mUseJitProfiles =
-            SystemProperties.getBoolean("dalvik.vm.usejitprofiles", false);
-
     private static class IFVerificationParams {
         PackageParser.Package pkg;
         boolean replacing;
@@ -1426,19 +1429,21 @@
 
                         final boolean grantPermissions = (args.installFlags
                                 & PackageManager.INSTALL_GRANT_RUNTIME_PERMISSIONS) != 0;
+                        final boolean killApp = (args.installFlags
+                                & PackageManager.INSTALL_DONT_KILL_APP) == 0;
                         final String[] grantedPermissions = args.installGrantPermissions;
 
                         // Handle the parent package
-                        handlePackagePostInstall(parentRes, grantPermissions, grantedPermissions,
-                                args.observer);
+                        handlePackagePostInstall(parentRes, grantPermissions, killApp,
+                                grantedPermissions, args.observer);
 
                         // Handle the child packages
                         final int childCount = (parentRes.addedChildPackages != null)
                                 ? parentRes.addedChildPackages.size() : 0;
                         for (int i = 0; i < childCount; i++) {
                             PackageInstalledInfo childRes = parentRes.addedChildPackages.valueAt(i);
-                            handlePackagePostInstall(childRes, grantPermissions, grantedPermissions,
-                                    args.observer);
+                            handlePackagePostInstall(childRes, grantPermissions, killApp,
+                                    grantedPermissions, args.observer);
                         }
 
                         // Log tracing if needed
@@ -1633,11 +1638,12 @@
     }
 
     private void handlePackagePostInstall(PackageInstalledInfo res, boolean grantPermissions,
-            String[] grantedPermissions, IPackageInstallObserver2 installObserver) {
+            boolean killApp, String[] grantedPermissions,
+            IPackageInstallObserver2 installObserver) {
         if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
             // Send the removed broadcasts
             if (res.removedInfo != null) {
-                res.removedInfo.sendPackageRemovedBroadcasts();
+                res.removedInfo.sendPackageRemovedBroadcasts(killApp);
             }
 
             // Now that we successfully installed the package, grant runtime
@@ -2159,10 +2165,12 @@
                         }
 
                         try {
-                            int dexoptNeeded = DexFile.getDexOptNeeded(lib, null, dexCodeInstructionSet, false);
+                            // Shared libraries do not have profiles so we perform a full
+                            // AOT compilation (if needed).
+                            int dexoptNeeded = DexFile.getDexOptNeeded(
+                                    lib, dexCodeInstructionSet,
+                                    DexFile.COMPILATION_TYPE_FULL);
                             if (dexoptNeeded != DexFile.NO_DEXOPT_NEEDED) {
-                                // Shared libraries do not have profiles so we perform a full
-                                // AOT compilation.
                                 mInstaller.dexopt(lib, Process.SYSTEM_UID, dexCodeInstructionSet,
                                         dexoptNeeded, DEXOPT_PUBLIC /*dexFlags*/,
                                         StorageManager.UUID_PRIVATE_INTERNAL,
@@ -2441,7 +2449,7 @@
             // since core system apps like SettingsProvider and SystemUI
             // can't wait for user to start
             final int storageFlags;
-            if (StorageManager.isFileBasedEncryptionEnabled()) {
+            if (StorageManager.isFileEncryptedNativeOrEmulated()) {
                 storageFlags = StorageManager.FLAG_STORAGE_DE;
             } else {
                 storageFlags = StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE;
@@ -2449,33 +2457,6 @@
             reconcileAppsData(StorageManager.UUID_PRIVATE_INTERNAL, UserHandle.USER_SYSTEM,
                     storageFlags);
 
-            if (!StorageManager.isFileBasedEncryptionEnabled()
-                    && PackageManager.APPLY_FORCE_DEVICE_ENCRYPTED) {
-                // When upgrading a non-FBE device, we might need to shuffle
-                // around the default storage location of system apps
-                final List<UserInfo> users = sUserManager.getUsers(true);
-                for (PackageSetting ps : mSettings.mPackages.values()) {
-                    if (ps.pkg == null || !ps.isSystem()) continue;
-                    final int storageTarget = ps.pkg.applicationInfo.isForceDeviceEncrypted()
-                            ? StorageManager.FLAG_STORAGE_DE : StorageManager.FLAG_STORAGE_CE;
-                    for (UserInfo user : users) {
-                        if (ps.getInstalled(user.id)) {
-                            try {
-                                mInstaller.migrateAppData(StorageManager.UUID_PRIVATE_INTERNAL,
-                                        ps.name, user.id, storageTarget);
-                            } catch (InstallerException e) {
-                                logCriticalInfo(Log.WARN,
-                                        "Failed to migrate " + ps.name + ": " + e.getMessage());
-                            }
-                            // We may have just shuffled around app data
-                            // directories, so prepare it one more time
-                            prepareAppData(StorageManager.UUID_PRIVATE_INTERNAL, user.id,
-                                    storageFlags, ps.pkg, false);
-                        }
-                    }
-                }
-            }
-
             // If this is first boot after an OTA, and a normal boot, then
             // we need to clear code cache directories.
             if (mIsUpgrade && !onlyCore) {
@@ -2583,7 +2564,7 @@
     private @Nullable String getRequiredButNotReallyRequiredVerifierLPr() {
         final Intent intent = new Intent(Intent.ACTION_PACKAGE_NEEDS_VERIFICATION);
 
-        final List<ResolveInfo> matches = queryIntentReceivers(intent, PACKAGE_MIME_TYPE,
+        final List<ResolveInfo> matches = queryIntentReceiversInternal(intent, PACKAGE_MIME_TYPE,
                 MATCH_SYSTEM_ONLY | MATCH_ENCRYPTION_AWARE_AND_UNAWARE, UserHandle.USER_SYSTEM);
         if (matches.size() == 1) {
             return matches.get(0).getComponentInfo().packageName;
@@ -2598,7 +2579,7 @@
         intent.addCategory(Intent.CATEGORY_DEFAULT);
         intent.setDataAndType(Uri.fromFile(new File("foo.apk")), PACKAGE_MIME_TYPE);
 
-        final List<ResolveInfo> matches = queryIntentActivities(intent, PACKAGE_MIME_TYPE,
+        final List<ResolveInfo> matches = queryIntentActivitiesInternal(intent, PACKAGE_MIME_TYPE,
                 MATCH_SYSTEM_ONLY | MATCH_ENCRYPTION_AWARE_AND_UNAWARE, UserHandle.USER_SYSTEM);
         if (matches.size() == 1) {
             return matches.get(0).getComponentInfo().packageName;
@@ -2610,7 +2591,7 @@
     private @NonNull ComponentName getIntentFilterVerifierComponentNameLPr() {
         final Intent intent = new Intent(Intent.ACTION_INTENT_FILTER_NEEDS_VERIFICATION);
 
-        final List<ResolveInfo> matches = queryIntentReceivers(intent, PACKAGE_MIME_TYPE,
+        final List<ResolveInfo> matches = queryIntentReceiversInternal(intent, PACKAGE_MIME_TYPE,
                 MATCH_SYSTEM_ONLY | MATCH_ENCRYPTION_AWARE_AND_UNAWARE, UserHandle.USER_SYSTEM);
         ResolveInfo best = null;
         final int N = matches.size();
@@ -2645,7 +2626,7 @@
         }
 
         final Intent resolverIntent = new Intent(Intent.ACTION_RESOLVE_EPHEMERAL_PACKAGE);
-        final List<ResolveInfo> resolvers = queryIntentServices(resolverIntent, null,
+        final List<ResolveInfo> resolvers = queryIntentServicesInternal(resolverIntent, null,
                 MATCH_SYSTEM_ONLY | MATCH_ENCRYPTION_AWARE_AND_UNAWARE, UserHandle.USER_SYSTEM);
 
         final int N = resolvers.size();
@@ -2690,7 +2671,7 @@
         intent.addCategory(Intent.CATEGORY_DEFAULT);
         intent.setDataAndType(Uri.fromFile(new File("foo.apk")), PACKAGE_MIME_TYPE);
 
-        final List<ResolveInfo> matches = queryIntentActivities(intent, PACKAGE_MIME_TYPE,
+        final List<ResolveInfo> matches = queryIntentActivitiesInternal(intent, PACKAGE_MIME_TYPE,
                 MATCH_SYSTEM_ONLY | MATCH_ENCRYPTION_AWARE_AND_UNAWARE, UserHandle.USER_SYSTEM);
         if (matches.size() == 0) {
             return null;
@@ -2785,7 +2766,7 @@
 
     private List<String> resolveAllBrowserApps(int userId) {
         // Resolve the canonical browser intent and check that the handleAllWebDataURI boolean is set
-        List<ResolveInfo> list = queryIntentActivities(sBrowserIntent, null,
+        List<ResolveInfo> list = queryIntentActivitiesInternal(sBrowserIntent, null,
                 PackageManager.MATCH_ALL, userId);
 
         final int count = list.size();
@@ -2805,7 +2786,7 @@
     }
 
     private boolean packageIsBrowser(String packageName, int userId) {
-        List<ResolveInfo> list = queryIntentActivities(sBrowserIntent, null,
+        List<ResolveInfo> list = queryIntentActivitiesInternal(sBrowserIntent, null,
                 PackageManager.MATCH_ALL, userId);
         final int N = list.size();
         for (int i = 0; i < N; i++) {
@@ -2915,7 +2896,8 @@
     @Override
     public boolean isPackageAvailable(String packageName, int userId) {
         if (!sUserManager.exists(userId)) return false;
-        enforceCrossUserPermission(Binder.getCallingUid(), userId, false, false, "is package available");
+        enforceCrossUserPermission(Binder.getCallingUid(), userId,
+                false /* requireFullPermission */, false /* checkShell */, "is package available");
         synchronized (mPackages) {
             PackageParser.Package p = mPackages.get(packageName);
             if (p != null) {
@@ -2935,7 +2917,8 @@
     public PackageInfo getPackageInfo(String packageName, int flags, int userId) {
         if (!sUserManager.exists(userId)) return null;
         flags = updateFlagsForPackage(flags, userId, packageName);
-        enforceCrossUserPermission(Binder.getCallingUid(), userId, false, false, "get package info");
+        enforceCrossUserPermission(Binder.getCallingUid(), userId,
+                false /* requireFullPermission */, false /* checkShell */, "get package info");
         // reader
         synchronized (mPackages) {
             PackageParser.Package p = mPackages.get(packageName);
@@ -2981,7 +2964,8 @@
     public int getPackageUid(String packageName, int flags, int userId) {
         if (!sUserManager.exists(userId)) return -1;
         flags = updateFlagsForPackage(flags, userId, packageName);
-        enforceCrossUserPermission(Binder.getCallingUid(), userId, false, false, "get package uid");
+        enforceCrossUserPermission(Binder.getCallingUid(), userId,
+                false /* requireFullPermission */, false /* checkShell */, "get package uid");
 
         // reader
         synchronized (mPackages) {
@@ -3004,7 +2988,8 @@
     public int[] getPackageGids(String packageName, int flags, int userId) {
         if (!sUserManager.exists(userId)) return null;
         flags = updateFlagsForPackage(flags, userId, packageName);
-        enforceCrossUserPermission(Binder.getCallingUid(), userId, false, false,
+        enforceCrossUserPermission(Binder.getCallingUid(), userId,
+                false /* requireFullPermission */, false /* checkShell */,
                 "getPackageGids");
 
         // reader
@@ -3050,9 +3035,15 @@
     }
 
     @Override
-    public List<PermissionInfo> queryPermissionsByGroup(String group, int flags) {
+    public @Nullable ParceledListSlice<PermissionInfo> queryPermissionsByGroup(String group,
+            int flags) {
         // reader
         synchronized (mPackages) {
+            if (group != null && !mPermissionGroups.containsKey(group)) {
+                // This is thrown as NameNotFoundException
+                return null;
+            }
+
             ArrayList<PermissionInfo> out = new ArrayList<PermissionInfo>(10);
             for (BasePermission p : mSettings.mPermissions.values()) {
                 if (group == null) {
@@ -3065,11 +3056,7 @@
                     }
                 }
             }
-
-            if (out.size() > 0) {
-                return out;
-            }
-            return mPermissionGroups.containsKey(group) ? out : null;
+            return new ParceledListSlice<>(out);
         }
     }
 
@@ -3083,7 +3070,7 @@
     }
 
     @Override
-    public List<PermissionGroupInfo> getAllPermissionGroups(int flags) {
+    public @NonNull ParceledListSlice<PermissionGroupInfo> getAllPermissionGroups(int flags) {
         // reader
         synchronized (mPackages) {
             final int N = mPermissionGroups.size();
@@ -3092,7 +3079,7 @@
             for (PackageParser.PermissionGroup pg : mPermissionGroups.values()) {
                 out.add(PackageParser.generatePermissionGroupInfo(pg, flags));
             }
-            return out;
+            return new ParceledListSlice<>(out);
         }
     }
 
@@ -3144,7 +3131,8 @@
     public ApplicationInfo getApplicationInfo(String packageName, int flags, int userId) {
         if (!sUserManager.exists(userId)) return null;
         flags = updateFlagsForApplication(flags, userId, packageName);
-        enforceCrossUserPermission(Binder.getCallingUid(), userId, false, false, "get application info");
+        enforceCrossUserPermission(Binder.getCallingUid(), userId,
+                false /* requireFullPermission */, false /* checkShell */, "get application info");
         // writer
         synchronized (mPackages) {
             PackageParser.Package p = mPackages.get(packageName);
@@ -3243,7 +3231,7 @@
      * Return if the user key is currently unlocked.
      */
     private boolean isUserKeyUnlocked(int userId) {
-        if (StorageManager.isFileBasedEncryptionEnabled()) {
+        if (StorageManager.isFileEncryptedNativeOrEmulated()) {
             final IMountService mount = IMountService.Stub
                     .asInterface(ServiceManager.getService("mount"));
             if (mount == null) {
@@ -3359,7 +3347,8 @@
     public ActivityInfo getActivityInfo(ComponentName component, int flags, int userId) {
         if (!sUserManager.exists(userId)) return null;
         flags = updateFlagsForComponent(flags, userId, component);
-        enforceCrossUserPermission(Binder.getCallingUid(), userId, false, false, "get activity info");
+        enforceCrossUserPermission(Binder.getCallingUid(), userId,
+                false /* requireFullPermission */, false /* checkShell */, "get activity info");
         synchronized (mPackages) {
             PackageParser.Activity a = mActivities.mActivities.get(component);
 
@@ -3404,7 +3393,8 @@
     public ActivityInfo getReceiverInfo(ComponentName component, int flags, int userId) {
         if (!sUserManager.exists(userId)) return null;
         flags = updateFlagsForComponent(flags, userId, component);
-        enforceCrossUserPermission(Binder.getCallingUid(), userId, false, false, "get receiver info");
+        enforceCrossUserPermission(Binder.getCallingUid(), userId,
+                false /* requireFullPermission */, false /* checkShell */, "get receiver info");
         synchronized (mPackages) {
             PackageParser.Activity a = mReceivers.mActivities.get(component);
             if (DEBUG_PACKAGE_INFO) Log.v(
@@ -3423,7 +3413,8 @@
     public ServiceInfo getServiceInfo(ComponentName component, int flags, int userId) {
         if (!sUserManager.exists(userId)) return null;
         flags = updateFlagsForComponent(flags, userId, component);
-        enforceCrossUserPermission(Binder.getCallingUid(), userId, false, false, "get service info");
+        enforceCrossUserPermission(Binder.getCallingUid(), userId,
+                false /* requireFullPermission */, false /* checkShell */, "get service info");
         synchronized (mPackages) {
             PackageParser.Service s = mServices.mServices.get(component);
             if (DEBUG_PACKAGE_INFO) Log.v(
@@ -3442,7 +3433,8 @@
     public ProviderInfo getProviderInfo(ComponentName component, int flags, int userId) {
         if (!sUserManager.exists(userId)) return null;
         flags = updateFlagsForComponent(flags, userId, component);
-        enforceCrossUserPermission(Binder.getCallingUid(), userId, false, false, "get provider info");
+        enforceCrossUserPermission(Binder.getCallingUid(), userId,
+                false /* requireFullPermission */, false /* checkShell */, "get provider info");
         synchronized (mPackages) {
             PackageParser.Provider p = mProviders.mProviders.get(component);
             if (DEBUG_PACKAGE_INFO) Log.v(
@@ -3485,22 +3477,17 @@
     }
 
     @Override
-    public FeatureInfo[] getSystemAvailableFeatures() {
-        Collection<FeatureInfo> featSet;
+    public @NonNull ParceledListSlice<FeatureInfo> getSystemAvailableFeatures() {
         synchronized (mPackages) {
-            featSet = mAvailableFeatures.values();
-            int size = featSet.size();
-            if (size > 0) {
-                FeatureInfo[] features = new FeatureInfo[size+1];
-                featSet.toArray(features);
-                FeatureInfo fi = new FeatureInfo();
-                fi.reqGlEsVersion = SystemProperties.getInt("ro.opengles.version",
-                        FeatureInfo.GL_ES_VERSION_UNDEFINED);
-                features[size] = fi;
-                return features;
-            }
+            final ArrayList<FeatureInfo> res = new ArrayList<>(mAvailableFeatures.values());
+
+            final FeatureInfo fi = new FeatureInfo();
+            fi.reqGlEsVersion = SystemProperties.getInt("ro.opengles.version",
+                    FeatureInfo.GL_ES_VERSION_UNDEFINED);
+            res.add(fi);
+
+            return new ParceledListSlice<>(res);
         }
-        return null;
     }
 
     @Override
@@ -3834,7 +3821,8 @@
                 android.Manifest.permission.GRANT_RUNTIME_PERMISSIONS,
                 "grantRuntimePermission");
 
-        enforceCrossUserPermission(Binder.getCallingUid(), userId, true, false,
+        enforceCrossUserPermission(Binder.getCallingUid(), userId,
+                true /* requireFullPermission */, true /* checkShell */,
                 "grantRuntimePermission");
 
         final int uid;
@@ -3945,7 +3933,8 @@
                 android.Manifest.permission.REVOKE_RUNTIME_PERMISSIONS,
                 "revokeRuntimePermission");
 
-        enforceCrossUserPermission(Binder.getCallingUid(), userId, true, false,
+        enforceCrossUserPermission(Binder.getCallingUid(), userId,
+                true /* requireFullPermission */, true /* checkShell */,
                 "revokeRuntimePermission");
 
         final int appId;
@@ -4049,7 +4038,8 @@
 
         enforceGrantRevokeRuntimePermissionPermissions("getPermissionFlags");
 
-        enforceCrossUserPermission(Binder.getCallingUid(), userId, true, false,
+        enforceCrossUserPermission(Binder.getCallingUid(), userId,
+                true /* requireFullPermission */, false /* checkShell */,
                 "getPermissionFlags");
 
         synchronized (mPackages) {
@@ -4082,7 +4072,8 @@
 
         enforceGrantRevokeRuntimePermissionPermissions("updatePermissionFlags");
 
-        enforceCrossUserPermission(Binder.getCallingUid(), userId, true, false,
+        enforceCrossUserPermission(Binder.getCallingUid(), userId,
+                true /* requireFullPermission */, true /* checkShell */,
                 "updatePermissionFlags");
 
         // Only the system can change these flags and nothing else.
@@ -4139,7 +4130,8 @@
 
         enforceGrantRevokeRuntimePermissionPermissions("updatePermissionFlagsForAllApps");
 
-        enforceCrossUserPermission(Binder.getCallingUid(), userId, true, false,
+        enforceCrossUserPermission(Binder.getCallingUid(), userId,
+                true /* requireFullPermission */, true /* checkShell */,
                 "updatePermissionFlagsForAllApps");
 
         // Only the system can change system fixed flags.
@@ -4245,7 +4237,8 @@
                 // TODO: remove these terrible hacks
                 if (actionName.startsWith("android.net.netmon.lingerExpired")
                         || actionName.startsWith("com.android.server.sip.SipWakeupTimer")
-                        || actionName.startsWith("com.android.internal.telephony.data-reconnect")) {
+                        || actionName.startsWith("com.android.internal.telephony.data-reconnect")
+                        || actionName.startsWith("android.net.netmon.launchCaptivePortalApp")) {
                     return true;
                 }
             }
@@ -4450,6 +4443,13 @@
     }
 
     @Override
+    public List<String> getAllPackages() {
+        synchronized (mPackages) {
+            return new ArrayList<String>(mPackages.keySet());
+        }
+    }
+
+    @Override
     public String[] getPackagesForUid(int uid) {
         uid = UserHandle.getAppId(uid);
         // reader
@@ -4572,8 +4572,10 @@
             int flags, int userId) {
         if (!sUserManager.exists(userId)) return null;
         flags = updateFlagsForResolve(flags, userId, intent);
-        enforceCrossUserPermission(Binder.getCallingUid(), userId, false, false, "resolve intent");
-        List<ResolveInfo> query = queryIntentActivities(intent, resolvedType, flags, userId);
+        enforceCrossUserPermission(Binder.getCallingUid(), userId,
+                false /* requireFullPermission */, false /* checkShell */, "resolve intent");
+        final List<ResolveInfo> query = queryIntentActivitiesInternal(intent, resolvedType, flags,
+                userId);
         final ResolveInfo bestChoice =
                 chooseBestActivity(intent, resolvedType, flags, query, userId);
 
@@ -4605,7 +4607,8 @@
             filter.dump(new PrintStreamPrinter(System.out), "    ");
         }
         intent.setComponent(null);
-        List<ResolveInfo> query = queryIntentActivities(intent, resolvedType, flags, userId);
+        final List<ResolveInfo> query = queryIntentActivitiesInternal(intent, resolvedType, flags,
+                userId);
         // Find any earlier preferred or last chosen entries and nuke them
         findPreferredActivity(intent, resolvedType,
                 flags, query, 0, false, true, false, userId);
@@ -4618,7 +4621,8 @@
     public ResolveInfo getLastChosenActivity(Intent intent, String resolvedType, int flags) {
         final int userId = UserHandle.getCallingUserId();
         if (DEBUG_PREFERRED) Log.v(TAG, "Querying last chosen activity for " + intent);
-        List<ResolveInfo> query = queryIntentActivities(intent, resolvedType, flags, userId);
+        final List<ResolveInfo> query = queryIntentActivitiesInternal(intent, resolvedType, flags,
+                userId);
         return findPreferredActivity(intent, resolvedType, flags, query, 0,
                 false, false, false, userId);
     }
@@ -5029,11 +5033,19 @@
     }
 
     @Override
-    public List<ResolveInfo> queryIntentActivities(Intent intent,
+    public @NonNull ParceledListSlice<ResolveInfo> queryIntentActivities(Intent intent,
+            String resolvedType, int flags, int userId) {
+        return new ParceledListSlice<>(
+                queryIntentActivitiesInternal(intent, resolvedType, flags, userId));
+    }
+
+    private @NonNull List<ResolveInfo> queryIntentActivitiesInternal(Intent intent,
             String resolvedType, int flags, int userId) {
         if (!sUserManager.exists(userId)) return Collections.emptyList();
         flags = updateFlagsForResolve(flags, userId, intent);
-        enforceCrossUserPermission(Binder.getCallingUid(), userId, false, false, "query intent activities");
+        enforceCrossUserPermission(Binder.getCallingUid(), userId,
+                false /* requireFullPermission */, false /* checkShell */,
+                "query intent activities");
         ComponentName comp = intent.getComponent();
         if (comp == null) {
             if (intent.getSelector() != null) {
@@ -5518,16 +5530,24 @@
     }
 
     @Override
-    public List<ResolveInfo> queryIntentActivityOptions(ComponentName caller,
+    public @NonNull ParceledListSlice<ResolveInfo> queryIntentActivityOptions(ComponentName caller,
+            Intent[] specifics, String[] specificTypes, Intent intent,
+            String resolvedType, int flags, int userId) {
+        return new ParceledListSlice<>(queryIntentActivityOptionsInternal(caller, specifics,
+                specificTypes, intent, resolvedType, flags, userId));
+    }
+
+    private @NonNull List<ResolveInfo> queryIntentActivityOptionsInternal(ComponentName caller,
             Intent[] specifics, String[] specificTypes, Intent intent,
             String resolvedType, int flags, int userId) {
         if (!sUserManager.exists(userId)) return Collections.emptyList();
         flags = updateFlagsForResolve(flags, userId, intent);
-        enforceCrossUserPermission(Binder.getCallingUid(), userId, false,
-                false, "query intent activity options");
+        enforceCrossUserPermission(Binder.getCallingUid(), userId,
+                false /* requireFullPermission */, false /* checkShell */,
+                "query intent activity options");
         final String resultsAction = intent.getAction();
 
-        List<ResolveInfo> results = queryIntentActivities(intent, resolvedType, flags
+        final List<ResolveInfo> results = queryIntentActivitiesInternal(intent, resolvedType, flags
                 | PackageManager.GET_RESOLVED_FILTER, userId);
 
         if (DEBUG_INTENT_MATCHING) {
@@ -5692,8 +5712,14 @@
     }
 
     @Override
-    public List<ResolveInfo> queryIntentReceivers(Intent intent, String resolvedType, int flags,
-            int userId) {
+    public @NonNull ParceledListSlice<ResolveInfo> queryIntentReceivers(Intent intent,
+            String resolvedType, int flags, int userId) {
+        return new ParceledListSlice<>(
+                queryIntentReceiversInternal(intent, resolvedType, flags, userId));
+    }
+
+    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);
         ComponentName comp = intent.getComponent();
@@ -5725,7 +5751,7 @@
                 return mReceivers.queryIntentForPackage(intent, resolvedType, flags, pkg.receivers,
                         userId);
             }
-            return null;
+            return Collections.emptyList();
         }
     }
 
@@ -5733,7 +5759,7 @@
     public ResolveInfo resolveService(Intent intent, String resolvedType, int flags, int userId) {
         if (!sUserManager.exists(userId)) return null;
         flags = updateFlagsForResolve(flags, userId, intent);
-        List<ResolveInfo> query = queryIntentServices(intent, resolvedType, flags, userId);
+        List<ResolveInfo> query = queryIntentServicesInternal(intent, resolvedType, flags, userId);
         if (query != null) {
             if (query.size() >= 1) {
                 // If there is more than one service with the same priority,
@@ -5745,8 +5771,14 @@
     }
 
     @Override
-    public List<ResolveInfo> queryIntentServices(Intent intent, String resolvedType, int flags,
-            int userId) {
+    public @NonNull ParceledListSlice<ResolveInfo> queryIntentServices(Intent intent,
+            String resolvedType, int flags, int userId) {
+        return new ParceledListSlice<>(
+                queryIntentServicesInternal(intent, resolvedType, flags, userId));
+    }
+
+    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);
         ComponentName comp = intent.getComponent();
@@ -5778,12 +5810,18 @@
                 return mServices.queryIntentForPackage(intent, resolvedType, flags, pkg.services,
                         userId);
             }
-            return null;
+            return Collections.emptyList();
         }
     }
 
     @Override
-    public List<ResolveInfo> queryIntentContentProviders(
+    public @NonNull ParceledListSlice<ResolveInfo> queryIntentContentProviders(Intent intent,
+            String resolvedType, int flags, int userId) {
+        return new ParceledListSlice<>(
+                queryIntentContentProvidersInternal(intent, resolvedType, flags, userId));
+    }
+
+    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);
@@ -5816,7 +5854,7 @@
                 return mProviders.queryIntentForPackage(
                         intent, resolvedType, flags, pkg.providers, userId);
             }
-            return null;
+            return Collections.emptyList();
         }
     }
 
@@ -5825,7 +5863,9 @@
         if (!sUserManager.exists(userId)) return ParceledListSlice.emptyList();
         flags = updateFlagsForPackage(flags, userId, null);
         final boolean listUninstalled = (flags & MATCH_UNINSTALLED_PACKAGES) != 0;
-        enforceCrossUserPermission(Binder.getCallingUid(), userId, true, false, "get installed packages");
+        enforceCrossUserPermission(Binder.getCallingUid(), userId,
+                true /* requireFullPermission */, false /* checkShell */,
+                "get installed packages");
 
         // writer
         synchronized (mPackages) {
@@ -5977,7 +6017,8 @@
 
         mContext.enforceCallingOrSelfPermission(Manifest.permission.ACCESS_EPHEMERAL_APPS,
                 "getEphemeralApplications");
-        enforceCrossUserPermission(Binder.getCallingUid(), userId, true, false,
+        enforceCrossUserPermission(Binder.getCallingUid(), userId,
+                true /* requireFullPermission */, false /* checkShell */,
                 "getEphemeralApplications");
         synchronized (mPackages) {
             List<EphemeralApplicationInfo> ephemeralApps = mEphemeralApplicationRegistry
@@ -5991,7 +6032,8 @@
 
     @Override
     public boolean isEphemeralApplication(String packageName, int userId) {
-        enforceCrossUserPermission(Binder.getCallingUid(), userId, true, false,
+        enforceCrossUserPermission(Binder.getCallingUid(), userId,
+                true /* requireFullPermission */, false /* checkShell */,
                 "isEphemeral");
         if (DISABLE_EPHEMERAL_APPS) {
             return false;
@@ -6015,7 +6057,8 @@
             return null;
         }
 
-        enforceCrossUserPermission(Binder.getCallingUid(), userId, true, false,
+        enforceCrossUserPermission(Binder.getCallingUid(), userId,
+                true /* requireFullPermission */, false /* checkShell */,
                 "getCookie");
         if (!isCallerSameApp(packageName)) {
             return null;
@@ -6032,7 +6075,8 @@
             return true;
         }
 
-        enforceCrossUserPermission(Binder.getCallingUid(), userId, true, false,
+        enforceCrossUserPermission(Binder.getCallingUid(), userId,
+                true /* requireFullPermission */, true /* checkShell */,
                 "setCookie");
         if (!isCallerSameApp(packageName)) {
             return false;
@@ -6051,7 +6095,8 @@
 
         mContext.enforceCallingOrSelfPermission(Manifest.permission.ACCESS_EPHEMERAL_APPS,
                 "getEphemeralApplicationIcon");
-        enforceCrossUserPermission(Binder.getCallingUid(), userId, true, false,
+        enforceCrossUserPermission(Binder.getCallingUid(), userId,
+                true /* requireFullPermission */, false /* checkShell */,
                 "getEphemeralApplicationIcon");
         synchronized (mPackages) {
             return mEphemeralApplicationRegistry.getEphemeralApplicationIconLPw(
@@ -6065,7 +6110,12 @@
                 && UserHandle.getAppId(Binder.getCallingUid()) == pkg.applicationInfo.uid;
     }
 
-    public List<ApplicationInfo> getPersistentApplications(int flags) {
+    @Override
+    public @NonNull ParceledListSlice<ApplicationInfo> getPersistentApplications(int flags) {
+        return new ParceledListSlice<>(getPersistentApplicationsInternal(flags));
+    }
+
+    private @NonNull List<ApplicationInfo> getPersistentApplicationsInternal(int flags) {
         final ArrayList<ApplicationInfo> finalList = new ArrayList<ApplicationInfo>();
 
         // reader
@@ -6074,9 +6124,16 @@
             final int userId = UserHandle.getCallingUserId();
             while (i.hasNext()) {
                 final PackageParser.Package p = i.next();
-                if (p.applicationInfo != null
-                        && (p.applicationInfo.flags&ApplicationInfo.FLAG_PERSISTENT) != 0
-                        && (!mSafeMode || isSystemApp(p))) {
+                if (p.applicationInfo == null) continue;
+
+                final boolean matchesUnaware = ((flags & MATCH_ENCRYPTION_UNAWARE) != 0)
+                        && !p.applicationInfo.isEncryptionAware();
+                final boolean matchesAware = ((flags & MATCH_ENCRYPTION_AWARE) != 0)
+                        && p.applicationInfo.isEncryptionAware();
+
+                if ((p.applicationInfo.flags & ApplicationInfo.FLAG_PERSISTENT) != 0
+                        && (!mSafeMode || isSystemApp(p))
+                        && (matchesUnaware || matchesAware)) {
                     PackageSetting ps = mSettings.mPackages.get(p.packageName);
                     if (ps != null) {
                         ApplicationInfo ai = PackageParser.generateApplicationInfo(p, flags,
@@ -6140,11 +6197,11 @@
     }
 
     @Override
-    public ParceledListSlice<ProviderInfo> queryContentProviders(String processName,
+    public @NonNull ParceledListSlice<ProviderInfo> queryContentProviders(String processName,
             int uid, int flags) {
         final int userId = processName != null ? UserHandle.getUserId(uid)
                 : UserHandle.getCallingUserId();
-        if (!sUserManager.exists(userId)) return null;
+        if (!sUserManager.exists(userId)) return ParceledListSlice.emptyList();
         flags = updateFlagsForComponent(flags, userId, processName);
 
         ArrayList<ProviderInfo> finalList = null;
@@ -6176,7 +6233,7 @@
             return new ParceledListSlice<ProviderInfo>(finalList);
         }
 
-        return null;
+        return ParceledListSlice.emptyList();
     }
 
     @Override
@@ -6189,10 +6246,14 @@
     }
 
     @Override
-    public List<InstrumentationInfo> queryInstrumentation(String targetPackage,
+    public @NonNull ParceledListSlice<InstrumentationInfo> queryInstrumentation(
+            String targetPackage, int flags) {
+        return new ParceledListSlice<>(queryInstrumentationInternal(targetPackage, flags));
+    }
+
+    private @NonNull List<InstrumentationInfo> queryInstrumentationInternal(String targetPackage,
             int flags) {
-        ArrayList<InstrumentationInfo> finalList =
-            new ArrayList<InstrumentationInfo>();
+        ArrayList<InstrumentationInfo> finalList = new ArrayList<InstrumentationInfo>();
 
         // reader
         synchronized (mPackages) {
@@ -6830,7 +6891,7 @@
 
         // Extract pacakges only if profile-guided compilation is enabled because
         // otherwise BackgroundDexOptService will not dexopt them later.
-        if (!mUseJitProfiles || !isUpgrade()) {
+        if (!isUpgrade()) {
             return;
         }
 
@@ -6912,10 +6973,6 @@
 
             targetInstructionSet = instructionSet != null ? instructionSet :
                     getPrimaryInstructionSet(p.applicationInfo);
-            if (!force && !useProfiles && p.mDexOptPerformed.contains(targetInstructionSet)) {
-                // Skip only if we do not use profiles since they might trigger a recompilation.
-                return false;
-            }
         }
         long callingId = Binder.clearCallingIdentity();
         try {
@@ -7896,13 +7953,17 @@
         // Request the ActivityManager to kill the process(only for existing packages)
         // so that we do not end up in a confused state while the user is still using the older
         // version of the application while the new one gets installed.
-        if ((scanFlags & SCAN_REPLACING) != 0) {
-            Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "killApplication");
+        final boolean isReplacing = (scanFlags & SCAN_REPLACING) != 0;
+        final boolean killApp = (scanFlags & SCAN_DONT_KILL_APP) == 0;
+        if (killApp) {
+            if (isReplacing) {
+                Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "killApplication");
 
-            killApplication(pkg.applicationInfo.packageName,
-                        pkg.applicationInfo.uid, "replace pkg");
+                killApplication(pkg.applicationInfo.packageName,
+                            pkg.applicationInfo.uid, "replace pkg");
 
-            Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
+                Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
+            }
         }
 
         // Also need to kill any apps that are dependent on the library.
@@ -10403,21 +10464,13 @@
     }
 
     @Override
-    public void installPackage(String originPath, IPackageInstallObserver2 observer,
-            int installFlags, String installerPackageName, VerificationParams verificationParams,
-            String packageAbiOverride) {
-        installPackageAsUser(originPath, observer, installFlags, installerPackageName,
-                verificationParams, packageAbiOverride, UserHandle.getCallingUserId());
-    }
-
-    @Override
     public void installPackageAsUser(String originPath, IPackageInstallObserver2 observer,
-            int installFlags, String installerPackageName, VerificationParams verificationParams,
-            String packageAbiOverride, int userId) {
+            int installFlags, String installerPackageName, int userId) {
         mContext.enforceCallingOrSelfPermission(android.Manifest.permission.INSTALL_PACKAGES, null);
 
         final int callingUid = Binder.getCallingUid();
-        enforceCrossUserPermission(callingUid, userId, true, true, "installPackageAsUser");
+        enforceCrossUserPermission(callingUid, userId,
+                true /* requireFullPermission */, true /* checkShell */, "installPackageAsUser");
 
         if (isUserRestricted(userId, UserManager.DISALLOW_INSTALL_APPS)) {
             try {
@@ -10456,14 +10509,15 @@
                     + "to use the PackageManager.INSTALL_GRANT_RUNTIME_PERMISSIONS flag");
         }
 
-        verificationParams.setInstallerUid(callingUid);
-
         final File originFile = new File(originPath);
         final OriginInfo origin = OriginInfo.fromUntrustedFile(originFile);
 
         final Message msg = mHandler.obtainMessage(INIT_COPY);
-        final InstallParams params = new InstallParams(origin, null, observer, installFlags,
-                installerPackageName, null, verificationParams, user, packageAbiOverride, null);
+        final VerificationInfo verificationInfo = new VerificationInfo(
+                null /*originatingUri*/, null /*referrer*/, -1 /*originatingUid*/, callingUid);
+        final InstallParams params = new InstallParams(origin, null /*moveInfo*/, observer,
+                installFlags, installerPackageName, null /*volumeUuid*/, verificationInfo, user,
+                null /*packageAbiOverride*/, null /*grantedPermissions*/);
         params.setTraceMethod("installAsUser").setTraceCookie(System.identityHashCode(params));
         msg.obj = params;
 
@@ -10483,10 +10537,9 @@
                 Slog.d(TAG, "Ephemeral install of " + packageName);
             }
         }
-        final VerificationParams verifParams = new VerificationParams(
-                null, sessionParams.originatingUri, sessionParams.referrerUri,
-                sessionParams.originatingUid);
-        verifParams.setInstallerUid(installerUid);
+        final VerificationInfo verificationInfo = new VerificationInfo(
+                sessionParams.originatingUri, sessionParams.referrerUri,
+                sessionParams.originatingUid, installerUid);
 
         final OriginInfo origin;
         if (stagedDir != null) {
@@ -10498,7 +10551,7 @@
         final Message msg = mHandler.obtainMessage(INIT_COPY);
         final InstallParams params = new InstallParams(origin, null, observer,
                 sessionParams.installFlags, installerPackageName, sessionParams.volumeUuid,
-                verifParams, user, sessionParams.abiOverride,
+                verificationInfo, user, sessionParams.abiOverride,
                 sessionParams.grantedRuntimePermissions);
         params.setTraceMethod("installStage").setTraceCookie(System.identityHashCode(params));
         msg.obj = params;
@@ -10548,7 +10601,8 @@
         mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USERS, null);
         PackageSetting pkgSetting;
         final int uid = Binder.getCallingUid();
-        enforceCrossUserPermission(uid, userId, true, true,
+        enforceCrossUserPermission(uid, userId,
+                true /* requireFullPermission */, true /* checkShell */,
                 "setApplicationHiddenSetting for user " + userId);
 
         if (hidden && isPackageDeviceAdmin(packageName, userId)) {
@@ -10598,7 +10652,7 @@
         info.removedPackage = packageName;
         info.removedUsers = new int[] {userId};
         info.uid = UserHandle.getUid(userId, pkgSetting.appId);
-        info.sendPackageRemovedBroadcasts();
+        info.sendPackageRemovedBroadcasts(true /*killApp*/);
     }
 
     private void sendPackagesSuspendedForUser(String[] pkgList, int userId, boolean suspended) {
@@ -10621,8 +10675,9 @@
     @Override
     public boolean getApplicationHiddenSettingAsUser(String packageName, int userId) {
         mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USERS, null);
-        enforceCrossUserPermission(Binder.getCallingUid(), userId, true,
-                false, "getApplicationHidden for user " + userId);
+        enforceCrossUserPermission(Binder.getCallingUid(), userId,
+                true /* requireFullPermission */, false /* checkShell */,
+                "getApplicationHidden for user " + userId);
         PackageSetting pkgSetting;
         long callingId = Binder.clearCallingIdentity();
         try {
@@ -10648,8 +10703,9 @@
                 null);
         PackageSetting pkgSetting;
         final int uid = Binder.getCallingUid();
-        enforceCrossUserPermission(uid, userId, true, true, "installExistingPackage for user "
-                + userId);
+        enforceCrossUserPermission(uid, userId,
+                true /* requireFullPermission */, true /* checkShell */,
+                "installExistingPackage for user " + userId);
         if (isUserRestricted(userId, UserManager.DISALLOW_INSTALL_APPS)) {
             return PackageManager.INSTALL_FAILED_USER_RESTRICTED;
         }
@@ -10698,7 +10754,8 @@
     public String[] setPackagesSuspendedAsUser(String[] packageNames, boolean suspended,
             int userId) {
         mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USERS, null);
-        enforceCrossUserPermission(Binder.getCallingUid(), userId, true, true,
+        enforceCrossUserPermission(Binder.getCallingUid(), userId,
+                true /* requireFullPermission */, true /* checkShell */,
                 "setPackagesSuspended for user " + userId);
 
         if (ArrayUtils.isEmpty(packageNames)) {
@@ -10756,8 +10813,9 @@
 
     @Override
     public boolean isPackageSuspendedForUser(String packageName, int userId) {
-        enforceCrossUserPermission(Binder.getCallingUid(), userId, true,
-                false, "isPackageSuspendedForUser for user " + userId);
+        enforceCrossUserPermission(Binder.getCallingUid(), userId,
+                true /* requireFullPermission */, false /* checkShell */,
+                "isPackageSuspendedForUser for user " + userId);
         synchronized (mPackages) {
             final PackageSetting pkgSetting = mSettings.mPackages.get(packageName);
             return pkgSetting != null && pkgSetting.getSuspended(userId);
@@ -11070,21 +11128,22 @@
     }
 
     @Override
-    public List<IntentFilterVerificationInfo> getIntentFilterVerifications(String packageName) {
+    public @NonNull ParceledListSlice<IntentFilterVerificationInfo> getIntentFilterVerifications(
+            String packageName) {
         synchronized (mPackages) {
-            return mSettings.getIntentFilterVerificationsLPr(packageName);
+            return new ParceledListSlice<>(mSettings.getIntentFilterVerificationsLPr(packageName));
         }
     }
 
     @Override
-    public List<IntentFilter> getAllIntentFilters(String packageName) {
+    public @NonNull ParceledListSlice<IntentFilter> getAllIntentFilters(String packageName) {
         if (TextUtils.isEmpty(packageName)) {
-            return Collections.<IntentFilter>emptyList();
+            return ParceledListSlice.emptyList();
         }
         synchronized (mPackages) {
             PackageParser.Package pkg = mPackages.get(packageName);
             if (pkg == null || pkg.activities == null) {
-                return Collections.<IntentFilter>emptyList();
+                return ParceledListSlice.emptyList();
             }
             final int count = pkg.activities.size();
             ArrayList<IntentFilter> result = new ArrayList<>();
@@ -11094,7 +11153,7 @@
                     result.addAll(activity.intents);
                 }
             }
-            return result;
+            return new ParceledListSlice<>(result);
         }
     }
 
@@ -11533,6 +11592,30 @@
         }
     }
 
+    static class VerificationInfo {
+        /** A constant used to indicate that a uid value is not present. */
+        public static final int NO_UID = -1;
+
+        /** URI referencing where the package was downloaded from. */
+        final Uri originatingUri;
+
+        /** HTTP referrer URI associated with the originatingURI. */
+        final Uri referrer;
+
+        /** UID of the application that the install request originated from. */
+        final int originatingUid;
+
+        /** UID of application requesting the install */
+        final int installerUid;
+
+        VerificationInfo(Uri originatingUri, Uri referrer, int originatingUid, int installerUid) {
+            this.originatingUri = originatingUri;
+            this.referrer = referrer;
+            this.originatingUid = originatingUid;
+            this.installerUid = installerUid;
+        }
+    }
+
     class InstallParams extends HandlerParams {
         final OriginInfo origin;
         final MoveInfo move;
@@ -11540,15 +11623,15 @@
         int installFlags;
         final String installerPackageName;
         final String volumeUuid;
-        final VerificationParams verificationParams;
         private InstallArgs mArgs;
         private int mRet;
         final String packageAbiOverride;
         final String[] grantedRuntimePermissions;
+        final VerificationInfo verificationInfo;
 
         InstallParams(OriginInfo origin, MoveInfo move, IPackageInstallObserver2 observer,
                 int installFlags, String installerPackageName, String volumeUuid,
-                VerificationParams verificationParams, UserHandle user, String packageAbiOverride,
+                VerificationInfo verificationInfo, UserHandle user, String packageAbiOverride,
                 String[] grantedPermissions) {
             super(user);
             this.origin = origin;
@@ -11557,7 +11640,7 @@
             this.installFlags = installFlags;
             this.installerPackageName = installerPackageName;
             this.volumeUuid = volumeUuid;
-            this.verificationParams = verificationParams;
+            this.verificationInfo = verificationInfo;
             this.packageAbiOverride = packageAbiOverride;
             this.grantedRuntimePermissions = grantedPermissions;
         }
@@ -11796,7 +11879,7 @@
                     verification.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
 
                     // Query all live verifiers based on current user state
-                    final List<ResolveInfo> receivers = queryIntentReceivers(verification,
+                    final List<ResolveInfo> receivers = queryIntentReceiversInternal(verification,
                             PACKAGE_MIME_TYPE, 0, verifierUser.getIdentifier());
 
                     if (DEBUG_VERIFY) {
@@ -11821,26 +11904,22 @@
                     verification.putExtra(PackageManager.EXTRA_VERIFICATION_VERSION_CODE,
                             pkgLite.versionCode);
 
-                    if (verificationParams != null) {
-                        if (verificationParams.getVerificationURI() != null) {
-                           verification.putExtra(PackageManager.EXTRA_VERIFICATION_URI,
-                                 verificationParams.getVerificationURI());
-                        }
-                        if (verificationParams.getOriginatingURI() != null) {
+                    if (verificationInfo != null) {
+                        if (verificationInfo.originatingUri != null) {
                             verification.putExtra(Intent.EXTRA_ORIGINATING_URI,
-                                  verificationParams.getOriginatingURI());
+                                    verificationInfo.originatingUri);
                         }
-                        if (verificationParams.getReferrer() != null) {
+                        if (verificationInfo.referrer != null) {
                             verification.putExtra(Intent.EXTRA_REFERRER,
-                                  verificationParams.getReferrer());
+                                    verificationInfo.referrer);
                         }
-                        if (verificationParams.getOriginatingUid() >= 0) {
+                        if (verificationInfo.originatingUid >= 0) {
                             verification.putExtra(Intent.EXTRA_ORIGINATING_UID,
-                                  verificationParams.getOriginatingUid());
+                                    verificationInfo.originatingUid);
                         }
-                        if (verificationParams.getInstallerUid() >= 0) {
+                        if (verificationInfo.installerUid >= 0) {
                             verification.putExtra(PackageManager.EXTRA_VERIFICATION_INSTALLER_UID,
-                                  verificationParams.getInstallerUid());
+                                    verificationInfo.installerUid);
                         }
                     }
 
@@ -13057,6 +13136,15 @@
         }
     }
 
+    public List<String> getPreviousCodePaths(String packageName) {
+        final PackageSetting ps = mSettings.mPackages.get(packageName);
+        final List<String> result = new ArrayList<String>();
+        if (ps != null && ps.oldCodePaths != null) {
+            result.addAll(ps.oldCodePaths);
+        }
+        return result;
+    }
+
     private void replaceNonSystemPackageLI(PackageParser.Package deletedPackage,
             PackageParser.Package pkg, int parseFlags, int scanFlags, UserHandle user,
             int[] allUsers, String installerPackageName, PackageInstalledInfo res) {
@@ -13066,12 +13154,16 @@
         String pkgName = deletedPackage.packageName;
         boolean deletedPkg = true;
         boolean addedPkg = false;
+        boolean updatedSettings = false;
+        final boolean killApp = (scanFlags & SCAN_DONT_KILL_APP) == 0;
+        final int deleteFlags = PackageManager.DELETE_KEEP_DATA
+                | (killApp ? 0 : PackageManager.DELETE_DONT_KILL_APP);
 
         final long origUpdateTime = (pkg.mExtras != null)
                 ? ((PackageSetting)pkg.mExtras).lastUpdateTime : 0;
 
         // First delete the existing package while retaining the data directory
-        if (!deletePackageLI(pkgName, null, true, allUsers, PackageManager.DELETE_KEEP_DATA,
+        if (!deletePackageLI(pkgName, null, true, allUsers, deleteFlags,
                 res.removedInfo, true, pkg)) {
             // If the existing package wasn't successfully deleted
             res.setError(INSTALL_FAILED_REPLACE_COULDNT_DELETE, "replaceNonSystemPackageLI");
@@ -13097,6 +13189,27 @@
                 final PackageParser.Package newPackage = scanPackageTracedLI(pkg, parseFlags,
                         scanFlags | SCAN_UPDATE_TIME, System.currentTimeMillis(), user);
                 updateSettingsLI(newPackage, installerPackageName, allUsers, res, user);
+
+                // Update the in-memory copy of the previous code paths.
+                PackageSetting ps = mSettings.mPackages.get(pkgName);
+                if (!killApp) {
+                    if (ps.oldCodePaths == null) {
+                        ps.oldCodePaths = new ArraySet<>();
+                    }
+                    Collections.addAll(ps.oldCodePaths, deletedPackage.baseCodePath);
+                    if (deletedPackage.splitCodePaths != null) {
+                        Collections.addAll(ps.oldCodePaths, deletedPackage.splitCodePaths);
+                    }
+                } else {
+                    ps.oldCodePaths = null;
+                }
+                if (ps.childPackageNames != null) {
+                    for (int i = ps.childPackageNames.size() - 1; i >= 0; --i) {
+                        final String childPkgName = ps.childPackageNames.get(i);
+                        final PackageSetting childPs = mSettings.mPackages.get(childPkgName);
+                        childPs.oldCodePaths = ps.oldCodePaths;
+                    }
+                }
                 prepareAppDataAfterInstall(newPackage);
                 addedPkg = true;
             } catch (PackageManagerException e) {
@@ -13109,7 +13222,7 @@
 
             // Revert all internal state mutations and added folders for the failed install
             if (addedPkg) {
-                deletePackageLI(pkgName, null, true, allUsers, PackageManager.DELETE_KEEP_DATA,
+                deletePackageLI(pkgName, null, true, allUsers, deleteFlags,
                         res.removedInfo, true, null);
             }
 
@@ -13330,18 +13443,21 @@
         return null;
     }
 
-    private void removeNativeBinariesLI(PackageParser.Package pkg) {
+    private void removeNativeBinariesLI(PackageSetting ps) {
         // Remove the lib path for the parent package
-        PackageSetting ps = (PackageSetting) pkg.mExtras;
         if (ps != null) {
             NativeLibraryHelper.removeNativeBinariesLI(ps.legacyNativeLibraryPathString);
-        }
-        // Remove the lib path for the child packages
-        final int childCount = (pkg.childPackages != null) ? pkg.childPackages.size() : 0;
-        for (int i = 0; i < childCount; i++) {
-            ps = (PackageSetting) pkg.childPackages.get(i).mExtras;
-            if (ps != null) {
-                NativeLibraryHelper.removeNativeBinariesLI(ps.legacyNativeLibraryPathString);
+            // Remove the lib path for the child packages
+            final int childCount = (ps.childPackageNames != null) ? ps.childPackageNames.size() : 0;
+            for (int i = 0; i < childCount; i++) {
+                PackageSetting childPs = null;
+                synchronized (mPackages) {
+                    childPs = mSettings.peekPackageLPr(ps.childPackageNames.get(i));
+                }
+                if (childPs != null) {
+                    NativeLibraryHelper.removeNativeBinariesLI(childPs
+                            .legacyNativeLibraryPathString);
+                }
             }
         }
     }
@@ -13559,6 +13675,9 @@
             // moving a complete application; perform an initial scan on the new install location
             scanFlags |= SCAN_INITIAL;
         }
+        if ((installFlags & PackageManager.INSTALL_DONT_KILL_APP) != 0) {
+            scanFlags |= SCAN_DONT_KILL_APP;
+        }
 
         // Result object to be returned
         res.setReturnCode(PackageManager.INSTALL_SUCCEEDED);
@@ -13825,21 +13944,17 @@
                 return;
             }
 
-            // Extract package to save the VM unzipping the APK in memory during
-            // launch. Only do this if profile-guided compilation is enabled because
-            // otherwise BackgroundDexOptService will not dexopt the package later.
-            if (mUseJitProfiles) {
-                Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "dexopt");
-                // Do not run PackageDexOptimizer through the local performDexOpt
-                // method because `pkg` is not in `mPackages` yet.
-                int result = mPackageDexOptimizer.performDexOpt(pkg, null /* instructionSets */,
-                        false /* useProfiles */, true /* extractOnly */);
-                Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
-                if (result == PackageDexOptimizer.DEX_OPT_FAILED) {
-                    String msg = "Extracking package failed for " + pkgName;
-                    res.setError(INSTALL_FAILED_DEXOPT, msg);
-                    return;
-                }
+
+            Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "dexopt");
+            // Do not run PackageDexOptimizer through the local performDexOpt
+            // method because `pkg` is not in `mPackages` yet.
+            int result = mPackageDexOptimizer.performDexOpt(pkg, null /* instructionSets */,
+                    false /* useProfiles */, true /* extractOnly */);
+            Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
+            if (result == PackageDexOptimizer.DEX_OPT_FAILED) {
+                String msg = "Extracking package failed for " + pkgName;
+                res.setError(INSTALL_FAILED_DEXOPT, msg);
+                return;
             }
         }
 
@@ -14126,25 +14241,48 @@
             return;
         }
 
-        for (int currentUserId : users) {
-            if (getBlockUninstallForUser(packageName, currentUserId)) {
-                try {
-                    observer.onPackageDeleted(packageName,
-                            PackageManager.DELETE_FAILED_OWNER_BLOCKED, null);
-                } catch (RemoteException re) {
-                }
-                return;
+        if (!deleteAllUsers && getBlockUninstallForUser(packageName, userId)) {
+            try {
+                observer.onPackageDeleted(packageName,
+                        PackageManager.DELETE_FAILED_OWNER_BLOCKED, null);
+            } catch (RemoteException re) {
             }
+            return;
         }
 
         if (DEBUG_REMOVE) {
-            Slog.d(TAG, "deletePackageAsUser: pkg=" + packageName + " user=" + userId);
+            Slog.d(TAG, "deletePackageAsUser: pkg=" + packageName + " user=" + userId
+                    + " deleteAllUsers: " + deleteAllUsers );
         }
         // Queue up an async operation since the package deletion may take a little while.
         mHandler.post(new Runnable() {
             public void run() {
                 mHandler.removeCallbacks(this);
-                final int returnCode = deletePackageX(packageName, userId, flags);
+                int returnCode;
+                if (!deleteAllUsers) {
+                    returnCode = deletePackageX(packageName, userId, flags);
+                } else {
+                    int[] blockUninstallUserIds = getBlockUninstallForUsers(packageName, users);
+                    // If nobody is blocking uninstall, proceed with delete for all users
+                    if (ArrayUtils.isEmpty(blockUninstallUserIds)) {
+                        returnCode = deletePackageX(packageName, userId, flags);
+                    } else {
+                        // Otherwise uninstall individually for users with blockUninstalls=false
+                        final int userFlags = flags & ~PackageManager.DELETE_ALL_USERS;
+                        for (int userId : users) {
+                            if (!ArrayUtils.contains(blockUninstallUserIds, userId)) {
+                                returnCode = deletePackageX(packageName, userId, userFlags);
+                                if (returnCode != PackageManager.DELETE_SUCCEEDED) {
+                                    Slog.w(TAG, "Package delete failed for user " + userId
+                                            + ", returnCode " + returnCode);
+                                }
+                            }
+                        }
+                        // The app has only been marked uninstalled for certain users.
+                        // We still need to report that delete was blocked
+                        returnCode = PackageManager.DELETE_FAILED_OWNER_BLOCKED;
+                    }
+                }
                 try {
                     observer.onPackageDeleted(packageName, returnCode, null);
                 } catch (RemoteException e) {
@@ -14154,6 +14292,16 @@
         });
     }
 
+    private int[] getBlockUninstallForUsers(String packageName, int[] userIds) {
+        int[] result = EMPTY_INT_ARRAY;
+        for (int userId : userIds) {
+            if (getBlockUninstallForUser(packageName, userId)) {
+                result = ArrayUtils.appendInt(result, userId);
+            }
+        }
+        return result;
+    }
+
     @Override
     public boolean isPackageDeviceAdminOnAnyUser(String packageName) {
         return isPackageDeviceAdmin(packageName, UserHandle.USER_ALL);
@@ -14250,7 +14398,8 @@
         }
 
         if (res) {
-            info.sendPackageRemovedBroadcasts();
+            final boolean killApp = (flags & PackageManager.INSTALL_DONT_KILL_APP) == 0;
+            info.sendPackageRemovedBroadcasts(killApp);
             info.sendSystemPackageUpdatedBroadcasts();
             info.sendSystemPackageAppearedBroadcasts();
         }
@@ -14282,12 +14431,12 @@
         ArrayMap<String, PackageRemovedInfo> removedChildPackages;
         ArrayMap<String, PackageInstalledInfo> appearedChildPackages;
 
-        void sendPackageRemovedBroadcasts() {
-            sendPackageRemovedBroadcastInternal();
+        void sendPackageRemovedBroadcasts(boolean killApp) {
+            sendPackageRemovedBroadcastInternal(killApp);
             final int childCount = removedChildPackages != null ? removedChildPackages.size() : 0;
             for (int i = 0; i < childCount; i++) {
                 PackageRemovedInfo childInfo = removedChildPackages.valueAt(i);
-                childInfo.sendPackageRemovedBroadcastInternal();
+                childInfo.sendPackageRemovedBroadcastInternal(killApp);
             }
         }
 
@@ -14329,10 +14478,11 @@
                     null, 0, removedPackage, null, null);
         }
 
-        private void sendPackageRemovedBroadcastInternal() {
+        private void sendPackageRemovedBroadcastInternal(boolean killApp) {
             Bundle extras = new Bundle(2);
             extras.putInt(Intent.EXTRA_UID, removedAppId >= 0  ? removedAppId : uid);
             extras.putBoolean(Intent.EXTRA_DATA_REMOVED, dataRemoved);
+            extras.putBoolean(Intent.EXTRA_DONT_KILL_APP, !killApp);
             if (isUpdate || isRemovedPackageSystemUpdate) {
                 extras.putBoolean(Intent.EXTRA_REPLACING, true);
             }
@@ -14464,7 +14614,7 @@
     private boolean deleteSystemPackageLI(PackageParser.Package deletedPkg,
             PackageSetting deletedPs, int[] allUserHandles, int flags, PackageRemovedInfo outInfo,
             boolean writeSettings) {
-        if (deletedPkg.parentPackage != null) {
+        if (deletedPs.parentPackageName != null) {
             Slog.w(TAG, "Attempt to delete child system package " + deletedPkg.packageName);
             return false;
         }
@@ -14477,7 +14627,7 @@
         // the system pkg from system partition
         // reader
         synchronized (mPackages) {
-            disabledPs = mSettings.getDisabledSystemPkgLPr(deletedPkg.packageName);
+            disabledPs = mSettings.getDisabledSystemPkgLPr(deletedPs.name);
         }
 
         if (DEBUG_REMOVE) Slog.d(TAG, "deleteSystemPackageLI: newPs=" + deletedPkg.packageName
@@ -14503,10 +14653,10 @@
         // Delete the updated package
         outInfo.isRemovedPackageSystemUpdate = true;
         if (outInfo.removedChildPackages != null) {
-            final int childCount = (deletedPkg.childPackages != null)
-                    ? deletedPkg.childPackages.size() : 0;
+            final int childCount = (deletedPs.childPackageNames != null)
+                    ? deletedPs.childPackageNames.size() : 0;
             for (int i = 0; i < childCount; i++) {
-                String childPackageName = deletedPkg.childPackages.get(i).packageName;
+                String childPackageName = deletedPs.childPackageNames.get(i);
                 if (disabledPs.childPackageNames != null && disabledPs.childPackageNames
                         .contains(childPackageName)) {
                     PackageRemovedInfo childInfo = outInfo.removedChildPackages.get(
@@ -14526,7 +14676,7 @@
             flags |= PackageManager.DELETE_KEEP_DATA;
         }
 
-        boolean ret = deleteInstalledPackageLI(deletedPkg, true, flags, allUserHandles,
+        boolean ret = deleteInstalledPackageLI(deletedPs, true, flags, allUserHandles,
                 outInfo, writeSettings, disabledPs.pkg);
         if (!ret) {
             return false;
@@ -14537,7 +14687,7 @@
             // Reinstate the old system package
             enableSystemPackageLPw(disabledPs.pkg);
             // Remove any native libraries from the upgraded package.
-            removeNativeBinariesLI(deletedPkg);
+            removeNativeBinariesLI(deletedPs);
         }
 
         // Install the system package
@@ -14594,29 +14744,18 @@
         return true;
     }
 
-    private boolean deleteInstalledPackageLI(PackageParser.Package pkg,
+    private boolean deleteInstalledPackageLI(PackageSetting ps,
             boolean deleteCodeAndResources, int flags, int[] allUserHandles,
             PackageRemovedInfo outInfo, boolean writeSettings,
             PackageParser.Package replacingPackage) {
-        PackageSetting ps = null;
-
         synchronized (mPackages) {
-            pkg = mPackages.get(pkg.packageName);
-            if (pkg == null) {
-                return false;
-            }
-
-            ps = mSettings.mPackages.get(pkg.packageName);
-            if (ps == null) {
-                return false;
-            }
-
             if (outInfo != null) {
                 outInfo.uid = ps.appId;
             }
 
             if (outInfo != null && outInfo.removedChildPackages != null) {
-                final int childCount = (pkg.childPackages != null) ? pkg.childPackages.size() : 0;
+                final int childCount = (ps.childPackageNames != null)
+                        ? ps.childPackageNames.size() : 0;
                 for (int i = 0; i < childCount; i++) {
                     String childPackageName = ps.childPackageNames.get(i);
                     PackageSetting childPs = mSettings.mPackages.get(childPackageName);
@@ -14636,11 +14775,11 @@
         removePackageDataLI(ps, allUserHandles, outInfo, flags, writeSettings);
 
         // Delete the child packages data
-        final int childCount = (pkg.childPackages != null) ? pkg.childPackages.size() : 0;
+        final int childCount = (ps.childPackageNames != null) ? ps.childPackageNames.size() : 0;
         for (int i = 0; i < childCount; i++) {
             PackageSetting childPs;
             synchronized (mPackages) {
-                childPs = mSettings.peekPackageLPr(pkg.childPackages.get(i).packageName);
+                childPs = mSettings.peekPackageLPr(ps.childPackageNames.get(i));
             }
             if (childPs != null) {
                 PackageRemovedInfo childOutInfo = (outInfo != null
@@ -14656,7 +14795,7 @@
         }
 
         // Delete application code and resources only for parent packages
-        if (ps.pkg.parentPackage == null) {
+        if (ps.parentPackageName == null) {
             if (deleteCodeAndResources && (outInfo != null)) {
                 outInfo.args = createInstallArgsForExisting(packageFlagsToInstallFlags(ps),
                         ps.codePathString, ps.resourcePathString, getAppDexInstructionSets(ps));
@@ -14747,7 +14886,7 @@
                 return false;
             }
 
-            if (ps.pkg.parentPackage != null && (!isSystemApp(ps)
+            if (ps.parentPackageName != null && (!isSystemApp(ps)
                     || (flags & PackageManager.DELETE_SYSTEM_APP) != 0)) {
                 if (DEBUG_REMOVE) {
                     Slog.d(TAG, "Uninstalled child package:" + packageName + " for user:"
@@ -14834,8 +14973,11 @@
         } else {
             if (DEBUG_REMOVE) Slog.d(TAG, "Removing non-system package: " + ps.name);
             // Kill application pre-emptively especially for apps on sd.
-            killApplication(packageName, ps.appId, "uninstall pkg");
-            ret = deleteInstalledPackageLI(ps.pkg, deleteCodeAndResources, flags, allUserHandles,
+            final boolean killApp = (flags & PackageManager.DELETE_DONT_KILL_APP) == 0;
+            if (killApp) {
+                killApplication(packageName, ps.appId, "uninstall pkg");
+            }
+            ret = deleteInstalledPackageLI(ps, deleteCodeAndResources, flags, allUserHandles,
                     outInfo, writeSettings, replacingPackage);
         }
 
@@ -15012,11 +15154,29 @@
     }
 
     @Override
+    public void clearApplicationProfileData(String packageName) {
+        enforceSystemOrRoot("Only the system can clear all profile data");
+        try {
+            mInstaller.rmProfiles(packageName);
+        } catch (InstallerException ex) {
+            Log.e(TAG, "Could not clear profile data of package " + packageName);
+        }
+    }
+
+    @Override
     public void clearApplicationUserData(final String packageName,
             final IPackageDataObserver observer, final int userId) {
         mContext.enforceCallingOrSelfPermission(
                 android.Manifest.permission.CLEAR_APP_USER_DATA, null);
-        enforceCrossUserPermission(Binder.getCallingUid(), userId, true, false, "clear application data");
+
+        enforceCrossUserPermission(Binder.getCallingUid(), userId,
+                true /* requireFullPermission */, false /* checkShell */, "clear application data");
+
+        final DevicePolicyManagerInternal dpmi = LocalServices
+                .getService(DevicePolicyManagerInternal.class);
+        if (dpmi != null && dpmi.hasDeviceOwnerOrProfileOwner(packageName, userId)) {
+            throw new SecurityException("Cannot clear data for a device owner or a profile owner");
+        }
         // Queue up an async operation since the package deletion may take a little while.
         mHandler.post(new Runnable() {
             public void run() {
@@ -15028,8 +15188,8 @@
                 clearExternalStorageDataSync(packageName, userId, true);
                 if (succeeded) {
                     // invoke DeviceStorageMonitor's update method to clear any notifications
-                    DeviceStorageMonitorInternal
-                            dsm = LocalServices.getService(DeviceStorageMonitorInternal.class);
+                    DeviceStorageMonitorInternal dsm = LocalServices
+                            .getService(DeviceStorageMonitorInternal.class);
                     if (dsm != null) {
                         dsm.checkMemory();
                     }
@@ -15428,22 +15588,6 @@
         return true;
     }
 
-
-    @Override
-    public void addPackageToPreferred(String packageName) {
-        Slog.w(TAG, "addPackageToPreferred: this is now a no-op");
-    }
-
-    @Override
-    public void removePackageFromPreferred(String packageName) {
-        Slog.w(TAG, "removePackageFromPreferred: this is now a no-op");
-    }
-
-    @Override
-    public List<PackageInfo> getPreferredPackages(int flags) {
-        return new ArrayList<PackageInfo>();
-    }
-
     private int getUidTargetSdkVersionLockedLPr(int uid) {
         Object obj = mSettings.getUserIdLPr(uid);
         if (obj instanceof SharedUserSetting) {
@@ -15479,7 +15623,8 @@
             String opname) {
         // writer
         int callingUid = Binder.getCallingUid();
-        enforceCrossUserPermission(callingUid, userId, true, false, "add preferred activity");
+        enforceCrossUserPermission(callingUid, userId,
+                true /* requireFullPermission */, false /* checkShell */, "add preferred activity");
         if (filter.countActions() == 0) {
             Slog.w(TAG, "Cannot set a preferred activity with no filter actions");
             return;
@@ -15524,7 +15669,9 @@
         }
 
         final int callingUid = Binder.getCallingUid();
-        enforceCrossUserPermission(callingUid, userId, true, false, "replace preferred activity");
+        enforceCrossUserPermission(callingUid, userId,
+                true /* requireFullPermission */, false /* checkShell */,
+                "replace preferred activity");
         synchronized (mPackages) {
             if (mContext.checkCallingOrSelfPermission(
                     android.Manifest.permission.SET_PREFERRED_APPLICATIONS)
@@ -16293,7 +16440,7 @@
         intent.addCategory(Intent.CATEGORY_HOME);
 
         final int callingUserId = UserHandle.getCallingUserId();
-        List<ResolveInfo> list = queryIntentActivities(intent, null,
+        List<ResolveInfo> list = queryIntentActivitiesInternal(intent, null,
                 PackageManager.GET_META_DATA, callingUserId);
         ResolveInfo preferred = findPreferredActivity(intent, null, 0, list, 0,
                 true, false, false, callingUserId);
@@ -16342,7 +16489,8 @@
         final int uid = Binder.getCallingUid();
         final int permission = mContext.checkCallingOrSelfPermission(
                 android.Manifest.permission.CHANGE_COMPONENT_ENABLED_STATE);
-        enforceCrossUserPermission(uid, userId, false, true, "set enabled");
+        enforceCrossUserPermission(uid, userId,
+                false /* requireFullPermission */, true /* checkShell */, "set enabled");
         final boolean allowedByPermission = (permission == PackageManager.PERMISSION_GRANTED);
         boolean sendNow = false;
         boolean isApp = (className == null);
@@ -16481,7 +16629,8 @@
         final int permission = mContext.checkCallingOrSelfPermission(
                 android.Manifest.permission.CHANGE_COMPONENT_ENABLED_STATE);
         final boolean allowedByPermission = (permission == PackageManager.PERMISSION_GRANTED);
-        enforceCrossUserPermission(uid, userId, true, true, "stop package");
+        enforceCrossUserPermission(uid, userId,
+                true /* requireFullPermission */, true /* checkShell */, "stop package");
         // writer
         synchronized (mPackages) {
             if (mSettings.setPackageStoppedStateLPw(this, packageName, stopped,
@@ -16503,7 +16652,8 @@
     public int getApplicationEnabledSetting(String packageName, int userId) {
         if (!sUserManager.exists(userId)) return COMPONENT_ENABLED_STATE_DISABLED;
         int uid = Binder.getCallingUid();
-        enforceCrossUserPermission(uid, userId, false, false, "get enabled");
+        enforceCrossUserPermission(uid, userId,
+                false /* requireFullPermission */, false /* checkShell */, "get enabled");
         // reader
         synchronized (mPackages) {
             return mSettings.getApplicationEnabledSettingLPr(packageName, userId);
@@ -16514,7 +16664,8 @@
     public int getComponentEnabledSetting(ComponentName componentName, int userId) {
         if (!sUserManager.exists(userId)) return COMPONENT_ENABLED_STATE_DISABLED;
         int uid = Binder.getCallingUid();
-        enforceCrossUserPermission(uid, userId, false, false, "get component enabled");
+        enforceCrossUserPermission(uid, userId,
+                false /* requireFullPermission */, false /* checkShell */, "get component enabled");
         // reader
         synchronized (mPackages) {
             return mSettings.getComponentEnabledSettingLPr(componentName, userId);
@@ -17285,8 +17436,9 @@
     }
 
     private String dumpDomainString(String packageName) {
-        List<IntentFilterVerificationInfo> iviList = getIntentFilterVerifications(packageName);
-        List<IntentFilter> filters = getAllIntentFilters(packageName);
+        List<IntentFilterVerificationInfo> iviList = getIntentFilterVerifications(packageName)
+                .getList();
+        List<IntentFilter> filters = getAllIntentFilters(packageName).getList();
 
         ArraySet<String> result = new ArraySet<>();
         if (iviList.size() > 0) {
@@ -18021,6 +18173,13 @@
 
             if (ps.getInstalled(userId)) {
                 prepareAppData(volumeUuid, userId, flags, ps.pkg, restoreconNeeded);
+
+                if (maybeMigrateAppData(volumeUuid, userId, ps.pkg)) {
+                    // We may have just shuffled around app data directories, so
+                    // prepare them one more time
+                    prepareAppData(volumeUuid, userId, flags, ps.pkg, restoreconNeeded);
+                }
+
                 preparedCount++;
             }
         }
@@ -18148,6 +18307,30 @@
         }
     }
 
+    /**
+     * For system apps on non-FBE devices, this method migrates any existing
+     * CE/DE data to match the {@code forceDeviceEncrypted} flag requested by
+     * the app.
+     */
+    private boolean maybeMigrateAppData(String volumeUuid, int userId, PackageParser.Package pkg) {
+        if (pkg.isSystemApp() && !StorageManager.isFileEncryptedNativeOrEmulated()
+                && PackageManager.APPLY_FORCE_DEVICE_ENCRYPTED) {
+            final int storageTarget = pkg.applicationInfo.isForceDeviceEncrypted()
+                    ? StorageManager.FLAG_STORAGE_DE : StorageManager.FLAG_STORAGE_CE;
+            synchronized (mInstallLock) {
+                try {
+                    mInstaller.migrateAppData(volumeUuid, pkg.packageName, userId, storageTarget);
+                } catch (InstallerException e) {
+                    logCriticalInfo(Log.WARN,
+                            "Failed to migrate " + pkg.packageName + ": " + e.getMessage());
+                }
+            }
+            return true;
+        } else {
+            return false;
+        }
+    }
+
     private void unfreezePackage(String packageName) {
         synchronized (mPackages) {
             final PackageSetting ps = mSettings.mPackages.get(packageName);
@@ -18388,7 +18571,8 @@
         final Message msg = mHandler.obtainMessage(INIT_COPY);
         final OriginInfo origin = OriginInfo.fromExistingFile(codeFile);
         final InstallParams params = new InstallParams(origin, move, installObserver, installFlags,
-                installerPackageName, volumeUuid, null, user, packageAbiOverride, null);
+                installerPackageName, volumeUuid, null /*verificationInfo*/, user,
+                packageAbiOverride, null);
         params.setTraceMethod("movePackage").setTraceCookie(System.identityHashCode(params));
         msg.obj = params;
 
@@ -19043,6 +19227,11 @@
                 return permissionsState.isPermissionReviewRequired(userId);
             }
         }
+
+        @Override
+        public ApplicationInfo getApplicationInfo(String packageName, int userId) {
+            return PackageManagerService.this.getApplicationInfo(packageName, 0 /*flags*/, userId);
+        }
     }
 
     @Override
@@ -19070,4 +19259,14 @@
     boolean isHistoricalPackageUsageAvailable() {
         return mPackageUsage.isHistoricalPackageUsageAvailable();
     }
+
+    /**
+     * Return a <b>copy</b> of the collection of packages known to the package manager.
+     * @return A copy of the values of mPackages.
+     */
+    Collection<PackageParser.Package> getPackages() {
+        synchronized (mPackages) {
+            return new ArrayList<>(mPackages.values());
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java b/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java
index a3ac514..f79d6ee 100644
--- a/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java
+++ b/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java
@@ -16,13 +16,15 @@
 
 package com.android.server.pm;
 
+import static com.android.server.pm.PackageManagerService.DEBUG_DEXOPT;
+import static com.android.server.pm.PackageManagerService.TAG;
+
 import android.app.AppGlobals;
 import android.content.Intent;
 import android.content.pm.PackageParser;
-import android.content.pm.PackageParser.Package;
 import android.content.pm.ResolveInfo;
-import android.os.UserHandle;
 import android.os.RemoteException;
+import android.os.UserHandle;
 import android.util.ArraySet;
 import android.util.Log;
 
@@ -35,9 +37,6 @@
 import java.util.List;
 import java.util.Set;
 
-import static com.android.server.pm.PackageManagerService.DEBUG_DEXOPT;
-import static com.android.server.pm.PackageManagerService.TAG;
-
 /**
  * Class containing helper methods for the PackageManagerService.
  *
@@ -49,7 +48,8 @@
     private static ArraySet<String> getPackageNamesForIntent(Intent intent, int userId) {
         List<ResolveInfo> ris = null;
         try {
-            ris = AppGlobals.getPackageManager().queryIntentReceivers(intent, null, 0, userId);
+            ris = AppGlobals.getPackageManager().queryIntentReceivers(intent, null, 0, userId)
+                    .getList();
         } catch (RemoteException e) {
         }
         ArraySet<String> pkgNames = new ArraySet<String>();
diff --git a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
index abee007..d77168c 100644
--- a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
+++ b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
@@ -95,6 +95,8 @@
                     return runInstallCommit();
                 case "install-create":
                     return runInstallCreate();
+                case "install-remove":
+                    return runInstallRemove();
                 case "install-write":
                     return runInstallWrite();
                 case "compile":
@@ -136,11 +138,12 @@
                 pw.println("Error: must either specify a package size or an APK file");
                 return 1;
             }
-            if (doWriteSession(sessionId, inPath, params.sessionParams.sizeBytes, "base.apk",
+            if (doWriteSplit(sessionId, inPath, params.sessionParams.sizeBytes, "base.apk",
                     false /*logSuccess*/) != PackageInstaller.STATUS_SUCCESS) {
                 return 1;
             }
-            if (doCommitSession(sessionId, false /*logSuccess*/) != PackageInstaller.STATUS_SUCCESS) {
+            if (doCommitSession(sessionId, false /*logSuccess*/)
+                    != PackageInstaller.STATUS_SUCCESS) {
                 return 1;
             }
             abandonSession = false;
@@ -225,7 +228,20 @@
         final int sessionId = Integer.parseInt(getNextArg());
         final String splitName = getNextArg();
         final String path = getNextArg();
-        return doWriteSession(sessionId, path, sizeBytes, splitName, true /*logSuccess*/);
+        return doWriteSplit(sessionId, path, sizeBytes, splitName, true /*logSuccess*/);
+    }
+
+    private int runInstallRemove() throws RemoteException {
+        final PrintWriter pw = getOutPrintWriter();
+
+        final int sessionId = Integer.parseInt(getNextArg());
+
+        final String splitName = getNextArg();
+        if (splitName == null) {
+            pw.println("Error: split name not specified");
+            return 1;
+        }
+        return doRemoveSplit(sessionId, splitName, true /*logSuccess*/);
     }
 
     private int runCompile() throws RemoteException {
@@ -233,17 +249,30 @@
         boolean useJitProfiles = false;
         boolean extractOnly = false;
         boolean forceCompilation = false;
+        boolean allPackages = false;
+        boolean clearProfileData = false;
         String compilationMode = "default";
 
         String opt;
         while ((opt = getNextOption()) != null) {
             switch (opt) {
-                case "-m":
-                    compilationMode = getNextArgRequired();
+                case "-a":
+                    allPackages = true;
+                    break;
+                case "-c":
+                    clearProfileData = true;
                     break;
                 case "-f":
                     forceCompilation = true;
                     break;
+                case "-m":
+                    compilationMode = getNextArgRequired();
+                    break;
+                case "--reset":
+                    forceCompilation = true;
+                    clearProfileData = true;
+                    compilationMode = "extract";
+                    break;
                 default:
                     pw.println("Error: Unknown option: " + opt);
                     return 1;
@@ -255,7 +284,7 @@
                 useJitProfiles = SystemProperties.getBoolean("dalvik.vm.usejitprofiles", false);
                 extractOnly = false;
                 break;
-            case "all":
+            case "full":
                 useJitProfiles = false;
                 extractOnly = false;
                 break;
@@ -272,19 +301,49 @@
                 return 1;
         }
 
-        String packageName = getNextArg();
-        if (packageName == null) {
-            pw.println("Error: package name not specified");
-            return 1;
+        List<String> packageNames = null;
+        if (allPackages) {
+            packageNames = mInterface.getAllPackages();
+        } else {
+            String packageName = getNextArg();
+            if (packageName == null) {
+                pw.println("Error: package name not specified");
+                return 1;
+            }
+            packageNames = Collections.singletonList(packageName);
         }
 
-        boolean success = mInterface.performDexOpt(packageName, null /* instructionSet */,
-                useJitProfiles, extractOnly, forceCompilation);
-        if (success) {
+        List<String> failedPackages = new ArrayList<>();
+        for (String packageName : packageNames) {
+            if (clearProfileData) {
+                mInterface.clearApplicationProfileData(packageName);
+            }
+
+            boolean result = mInterface.performDexOpt(packageName, null /* instructionSet */,
+                        useJitProfiles, extractOnly, forceCompilation);
+            if (!result) {
+                failedPackages.add(packageName);
+            }
+        }
+
+        if (failedPackages.isEmpty()) {
             pw.println("Success");
             return 0;
+        } else if (failedPackages.size() == 1) {
+            pw.println("Failure: package " + failedPackages.get(0) + " could not be compiled");
+            return 1;
         } else {
-            pw.println("Failure: package " + packageName + " could not be compiled");
+            pw.print("Failure: the following packages could not be compiled: ");
+            boolean is_first = true;
+            for (String packageName : failedPackages) {
+                if (is_first) {
+                    is_first = false;
+                } else {
+                    pw.print(", ");
+                }
+                pw.print(packageName);
+            }
+            pw.println();
             return 1;
         }
     }
@@ -317,11 +376,7 @@
 
     private int runListFeatures() throws RemoteException {
         final PrintWriter pw = getOutPrintWriter();
-        final List<FeatureInfo> list = new ArrayList<FeatureInfo>();
-        final FeatureInfo[] rawList = mInterface.getSystemAvailableFeatures();
-        for (int i=0; i<rawList.length; i++) {
-            list.add(rawList[i]);
-        }
+        final List<FeatureInfo> list = mInterface.getSystemAvailableFeatures().getList();
 
         // sort by name
         Collections.sort(list, new Comparator<FeatureInfo>() {
@@ -380,7 +435,7 @@
         }
 
         final List<InstrumentationInfo> list =
-                mInterface.queryInstrumentation(targetPackage, 0 /*flags*/);
+                mInterface.queryInstrumentation(targetPackage, 0 /*flags*/).getList();
 
         // sort by target package
         Collections.sort(list, new Comparator<InstrumentationInfo>() {
@@ -521,7 +576,7 @@
 
     private int runListPermissionGroups() throws RemoteException {
         final PrintWriter pw = getOutPrintWriter();
-        final List<PermissionGroupInfo> pgs = mInterface.getAllPermissionGroups(0);
+        final List<PermissionGroupInfo> pgs = mInterface.getAllPermissionGroups(0).getList();
 
         final int count = pgs.size();
         for (int p = 0; p < count ; p++) {
@@ -568,7 +623,7 @@
         final ArrayList<String> groupList = new ArrayList<String>();
         if (groups) {
             final List<PermissionGroupInfo> infos =
-                    mInterface.getAllPermissionGroups(0 /*flags*/);
+                    mInterface.getAllPermissionGroups(0 /*flags*/).getList();
             final int count = infos.size();
             for (int i = 0; i < count; i++) {
                 groupList.add(infos.get(i).name);
@@ -627,12 +682,18 @@
             }
         }
 
-        String packageName = getNextArg();
+        final String packageName = getNextArg();
         if (packageName == null) {
             pw.println("Error: package name not specified");
             return 1;
         }
 
+        // if a split is specified, just remove it and not the whole package
+        final String splitName = getNextArg();
+        if (splitName != null) {
+            return runRemoveSplit(packageName, splitName);
+        }
+
         userId = translateUserId(userId, "runUninstall");
         if (userId == UserHandle.USER_ALL) {
             userId = UserHandle.USER_SYSTEM;
@@ -670,6 +731,36 @@
         }
     }
 
+    private int runRemoveSplit(String packageName, String splitName) throws RemoteException {
+        final PrintWriter pw = getOutPrintWriter();
+        final SessionParams sessionParams = new SessionParams(SessionParams.MODE_INHERIT_EXISTING);
+        sessionParams.installFlags |= PackageManager.INSTALL_REPLACE_EXISTING;
+        sessionParams.appPackageName = packageName;
+        final int sessionId =
+                doCreateSession(sessionParams, null /*installerPackageName*/, UserHandle.USER_ALL);
+        boolean abandonSession = true;
+        try {
+            if (doRemoveSplit(sessionId, splitName, false /*logSuccess*/)
+                    != PackageInstaller.STATUS_SUCCESS) {
+                return 1;
+            }
+            if (doCommitSession(sessionId, false /*logSuccess*/)
+                    != PackageInstaller.STATUS_SUCCESS) {
+                return 1;
+            }
+            abandonSession = false;
+            pw.println("Success");
+            return 0;
+        } finally {
+            if (abandonSession) {
+                try {
+                    doAbandonSession(sessionId, false /*logSuccess*/);
+                } catch (Exception ignore) {
+                }
+            }
+        }
+    }
+
     private Intent parseIntentAndUser() throws URISyntaxException {
         mTargetUser = UserHandle.USER_CURRENT;
         Intent intent = Intent.parseCommandArgs(this, new Intent.CommandOptionHandler() {
@@ -718,7 +809,7 @@
         }
         try {
             List<ResolveInfo> result = mInterface.queryIntentActivities(intent, null, 0,
-                    mTargetUser);
+                    mTargetUser).getList();
             PrintWriter pw = getOutPrintWriter();
             if (result == null || result.size() <= 0) {
                 pw.println("No activities found");
@@ -745,7 +836,7 @@
         }
         try {
             List<ResolveInfo> result = mInterface.queryIntentServices(intent, null, 0,
-                    mTargetUser);
+                    mTargetUser).getList();
             PrintWriter pw = getOutPrintWriter();
             if (result == null || result.size() <= 0) {
                 pw.println("No services found");
@@ -772,7 +863,7 @@
         }
         try {
             List<ResolveInfo> result = mInterface.queryIntentReceivers(intent, null, 0,
-                    mTargetUser);
+                    mTargetUser).getList();
             PrintWriter pw = getOutPrintWriter();
             if (result == null || result.size() <= 0) {
                 pw.println("No receivers found");
@@ -909,7 +1000,7 @@
         return sessionId;
     }
 
-    private int doWriteSession(int sessionId, String inPath, long sizeBytes, String splitName,
+    private int doWriteSplit(int sessionId, String inPath, long sizeBytes, String splitName,
             boolean logSuccess) throws RemoteException {
         final PrintWriter pw = getOutPrintWriter();
         if ("-".equals(inPath)) {
@@ -965,6 +1056,27 @@
         }
     }
 
+    private int doRemoveSplit(int sessionId, String splitName, boolean logSuccess)
+            throws RemoteException {
+        final PrintWriter pw = getOutPrintWriter();
+        PackageInstaller.Session session = null;
+        try {
+            session = new PackageInstaller.Session(
+                    mInterface.getPackageInstaller().openSession(sessionId));
+            session.removeSplit(splitName);
+
+            if (logSuccess) {
+                pw.println("Success");
+            }
+            return 0;
+        } catch (IOException e) {
+            pw.println("Error: failed to remove split; " + e.getMessage());
+            return 1;
+        } finally {
+            IoUtils.closeQuietly(session);
+        }
+    }
+
     private int doCommitSession(int sessionId, boolean logSuccess) throws RemoteException {
         final PrintWriter pw = getOutPrintWriter();
         PackageInstaller.Session session = null;
@@ -1051,7 +1163,7 @@
                 prefix = "  ";
             }
             List<PermissionInfo> ps =
-                    mInterface.queryPermissionsByGroup(groupList.get(i), 0 /*flags*/);
+                    mInterface.queryPermissionsByGroup(groupList.get(i), 0 /*flags*/).getList();
             final int count = ps.size();
             boolean first = true;
             for (int p = 0 ; p < count ; p++) {
@@ -1139,12 +1251,17 @@
         pw.println("  help");
         pw.println("    Print this help text.");
         pw.println("");
-        pw.println("  compile [-m MODE] [-f] TARGET-PACKAGE");
-        pw.println("    Trigger compilation of TARGET-PACKAGE.");
+        pw.println("  compile [-m MODE] [-f] [-c] [--reset] (-a | TARGET-PACKAGE)");
+        pw.println("    Trigger compilation of TARGET-PACKAGE or all packages if \"-a\".");
         pw.println("    Options:");
-        pw.println("      -m: select compilation mode");
-        pw.println("          MODE can be one of \"default\", \"all\", \"profile\", and \"extract\"");
+        pw.println("      -a: compile all packages");
+        pw.println("      -c: clear profile data before compiling");
         pw.println("      -f: force compilation even if not needed");
+        pw.println("      -m: select compilation mode");
+        pw.println("          MODE can be one of \"default\", \"full\", \"profile\"," +
+                   " and \"extract\"");
+        pw.println("      --reset: restore package to its post-install state");
+        pw.println("          shorthand for \"-c -f -m extract\"");
         pw.println("  list features");
         pw.println("    Prints all features of the system.");
         pw.println("  list instrumentation [-f] [TARGET-PACKAGE]");
diff --git a/services/core/java/com/android/server/pm/PackageSettingBase.java b/services/core/java/com/android/server/pm/PackageSettingBase.java
index e5eec7e..1434718 100644
--- a/services/core/java/com/android/server/pm/PackageSettingBase.java
+++ b/services/core/java/com/android/server/pm/PackageSettingBase.java
@@ -30,6 +30,7 @@
 import java.io.File;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Set;
 
 /**
  * Settings base class for pending and resolved classes.
@@ -118,7 +119,14 @@
      * platform will refuse to launch packages in a frozen state.
      */
     boolean frozen = false;
-
+    /**
+     * Non-persisted value. During an "upgrade without restart", we need the set
+     * of all previous code paths so we can surgically add the new APKs to the
+     * active classloader. If at any point an application is upgraded with a
+     * restart, this field will be cleared since the classloader would be created
+     * using the full set of code paths when the package's process is started.
+     */
+    Set<String> oldCodePaths;
     PackageSettingBase origPackage;
 
     /** Package name of the app that installed this package */
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index 1652185..4c77f28 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -2604,7 +2604,6 @@
         if (pkg.volumeUuid != null) {
             serializer.attribute(null, "volumeUuid", pkg.volumeUuid);
         }
-
         if (pkg.parentPackageName != null) {
             serializer.attribute(null, "parentPackageName", pkg.parentPackageName);
         }
@@ -3049,7 +3048,7 @@
             tmpPa.dump(new LogPrinter(Log.DEBUG, TAG), "  ");
         }
         Intent intent = new Intent();
-        int flags = 0;
+        int flags = PackageManager.MATCH_ENCRYPTION_AWARE_AND_UNAWARE;
         intent.setAction(tmpPa.getAction(0));
         for (int i=0; i<tmpPa.countCategories(); i++) {
             String cat = tmpPa.getCategory(i);
@@ -4171,9 +4170,19 @@
     };
 
     static final Object[] PRIVATE_FLAG_DUMP_SPEC = new Object[] {
-        ApplicationInfo.PRIVATE_FLAG_PRIVILEGED, "PRIVILEGED",
-        ApplicationInfo.PRIVATE_FLAG_FORWARD_LOCK, "FORWARD_LOCK",
+        ApplicationInfo.PRIVATE_FLAG_HIDDEN, "HIDDEN",
         ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE, "CANT_SAVE_STATE",
+        ApplicationInfo.PRIVATE_FLAG_FORWARD_LOCK, "FORWARD_LOCK",
+        ApplicationInfo.PRIVATE_FLAG_PRIVILEGED, "PRIVILEGED",
+        ApplicationInfo.PRIVATE_FLAG_HAS_DOMAIN_URLS, "HAS_DOMAIN_URLS",
+        ApplicationInfo.PRIVATE_FLAG_FORCE_DEVICE_ENCRYPTED, "FORCE_DEVICE_ENCRYPTED",
+        ApplicationInfo.PRIVATE_FLAG_ENCRYPTION_AWARE, "ENCRYPTION_AWARE",
+        ApplicationInfo.PRIVATE_FLAG_AUTOPLAY, "AUTOPLAY",
+        ApplicationInfo.PRIVATE_FLAG_PARTIALLY_ENCRYPTION_AWARE, "PARTIALLY_ENCRYPTION_AWARE",
+        ApplicationInfo.PRIVATE_FLAG_EPHEMERAL, "EPHEMERAL",
+        ApplicationInfo.PRIVATE_FLAG_REQUIRED_FOR_SYSTEM_USER, "REQUIRED_FOR_SYSTEM_USER",
+        ApplicationInfo.PRIVATE_FLAG_RESIZEABLE_ACTIVITIES, "RESIZEABLE_ACTIVITIES",
+        ApplicationInfo.PRIVATE_FLAG_BACKUP_IN_FOREGROUND, "BACKUP_IN_FOREGROUND",
     };
 
     void dumpVersionLPr(IndentingPrintWriter pw) {
@@ -4282,6 +4291,7 @@
         }
         pw.print(prefix); pw.print("  versionCode="); pw.print(ps.versionCode);
         if (ps.pkg != null) {
+            pw.print(" minSdk="); pw.print(ps.pkg.applicationInfo.minSdkVersion);
             pw.print(" targetSdk="); pw.print(ps.pkg.applicationInfo.targetSdkVersion);
         }
         pw.println();
@@ -4316,6 +4326,10 @@
             }
             pw.print(prefix); pw.print("  versionName="); pw.println(ps.pkg.mVersionName);
             pw.print(prefix); pw.print("  splits="); dumpSplitNames(pw, ps.pkg); pw.println();
+            final int apkSigningVersion = PackageParser.getApkSigningVersion(ps.pkg);
+            if (apkSigningVersion != PackageParser.APK_SIGNING_UNKNOWN) {
+                pw.print(prefix); pw.print("  apkSigningVersion="); pw.println(apkSigningVersion);
+            }
             pw.print(prefix); pw.print("  applicationInfo=");
                 pw.println(ps.pkg.applicationInfo.toString());
             pw.print(prefix); pw.print("  flags="); printFlags(pw, ps.pkg.applicationInfo.flags,
diff --git a/services/core/java/com/android/server/pm/ShortcutService.java b/services/core/java/com/android/server/pm/ShortcutService.java
new file mode 100644
index 0000000..1cd0592
--- /dev/null
+++ b/services/core/java/com/android/server/pm/ShortcutService.java
@@ -0,0 +1,2133 @@
+/*
+ * 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.annotation.UserIdInt;
+import android.app.ActivityManager;
+import android.content.ComponentName;
+import android.content.ContentProvider;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.IShortcutService;
+import android.content.pm.LauncherApps;
+import android.content.pm.LauncherApps.ShortcutQuery;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.pm.ParceledListSlice;
+import android.content.pm.ShortcutInfo;
+import android.content.pm.ShortcutServiceInternal;
+import android.content.pm.ShortcutServiceInternal.ShortcutChangeListener;
+import android.graphics.Bitmap;
+import android.graphics.Bitmap.CompressFormat;
+import android.graphics.BitmapFactory;
+import android.graphics.Canvas;
+import android.graphics.RectF;
+import android.graphics.drawable.Icon;
+import android.net.Uri;
+import android.os.Binder;
+import android.os.Environment;
+import android.os.Handler;
+import android.os.ParcelFileDescriptor;
+import android.os.PersistableBundle;
+import android.os.Process;
+import android.os.RemoteException;
+import android.os.ResultReceiver;
+import android.os.SELinux;
+import android.os.ShellCommand;
+import android.os.UserHandle;
+import android.text.TextUtils;
+import android.text.format.Formatter;
+import android.text.format.Time;
+import android.util.ArrayMap;
+import android.util.ArraySet;
+import android.util.AtomicFile;
+import android.util.KeyValueListParser;
+import android.util.Slog;
+import android.util.SparseArray;
+import android.util.TypedValue;
+import android.util.Xml;
+
+import com.android.internal.annotations.GuardedBy;
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.os.BackgroundThread;
+import com.android.internal.util.FastXmlSerializer;
+import com.android.internal.util.Preconditions;
+import com.android.server.LocalServices;
+import com.android.server.SystemService;
+
+import libcore.io.IoUtils;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+import org.xmlpull.v1.XmlSerializer;
+
+import java.io.File;
+import java.io.FileDescriptor;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.PrintWriter;
+import java.net.URISyntaxException;
+import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.function.Predicate;
+
+/**
+ * TODO:
+ *
+ * - Detect when already registered instances are passed to APIs again, which might break
+ *   internal bitmap handling.
+ *
+ * - Listen to PACKAGE_*, remove orphan info, update timestamp for icon res
+ *   -> Need to scan all packages when a user starts too.
+ *   -> Clear data -> remove all dynamic?  but not the pinned?
+ *
+ * - Pinned per each launcher package (multiple launchers)
+ *
+ * - Make save async (should we?)
+ *
+ * - Scan and remove orphan bitmaps (just in case).
+ *
+ * - Backup & restore
+ */
+public class ShortcutService extends IShortcutService.Stub {
+    static final String TAG = "ShortcutService";
+
+    static final boolean DEBUG = false; // STOPSHIP if true
+    static final boolean DEBUG_LOAD = false; // STOPSHIP if true
+
+    @VisibleForTesting
+    static final long DEFAULT_RESET_INTERVAL_SEC = 24 * 60 * 60; // 1 day
+
+    @VisibleForTesting
+    static final int DEFAULT_MAX_DAILY_UPDATES = 10;
+
+    @VisibleForTesting
+    static final int DEFAULT_MAX_SHORTCUTS_PER_APP = 5;
+
+    @VisibleForTesting
+    static final int DEFAULT_MAX_ICON_DIMENSION_DP = 96;
+
+    @VisibleForTesting
+    static final int DEFAULT_MAX_ICON_DIMENSION_LOWRAM_DP = 48;
+
+    @VisibleForTesting
+    static final String DEFAULT_ICON_PERSIST_FORMAT = CompressFormat.PNG.name();
+
+    @VisibleForTesting
+    static final int DEFAULT_ICON_PERSIST_QUALITY = 100;
+
+    private static final int SAVE_DELAY_MS = 5000; // in milliseconds.
+
+    @VisibleForTesting
+    static final String FILENAME_BASE_STATE = "shortcut_service.xml";
+
+    @VisibleForTesting
+    static final String DIRECTORY_PER_USER = "shortcut_service";
+
+    @VisibleForTesting
+    static final String FILENAME_USER_PACKAGES = "shortcuts.xml";
+
+    static final String DIRECTORY_BITMAPS = "bitmaps";
+
+    static final String TAG_ROOT = "root";
+    static final String TAG_PACKAGE = "package";
+    static final String TAG_LAST_RESET_TIME = "last_reset_time";
+    static final String TAG_INTENT_EXTRAS = "intent-extras";
+    static final String TAG_EXTRAS = "extras";
+    static final String TAG_SHORTCUT = "shortcut";
+
+    static final String ATTR_VALUE = "value";
+    static final String ATTR_NAME = "name";
+    static final String ATTR_DYNAMIC_COUNT = "dynamic-count";
+    static final String ATTR_CALL_COUNT = "call-count";
+    static final String ATTR_LAST_RESET = "last-reset";
+    static final String ATTR_ID = "id";
+    static final String ATTR_ACTIVITY = "activity";
+    static final String ATTR_TITLE = "title";
+    static final String ATTR_INTENT = "intent";
+    static final String ATTR_WEIGHT = "weight";
+    static final String ATTR_TIMESTAMP = "timestamp";
+    static final String ATTR_FLAGS = "flags";
+    static final String ATTR_ICON_RES = "icon-res";
+    static final String ATTR_BITMAP_PATH = "bitmap-path";
+
+    @VisibleForTesting
+    interface ConfigConstants {
+        /**
+         * Key name for the throttling reset interval, in seconds. (long)
+         */
+        String KEY_RESET_INTERVAL_SEC = "reset_interval_sec";
+
+        /**
+         * Key name for the max number of modifying API calls per app for every interval. (int)
+         */
+        String KEY_MAX_DAILY_UPDATES = "max_daily_updates";
+
+        /**
+         * Key name for the max icon dimensions in DP, for non-low-memory devices.
+         */
+        String KEY_MAX_ICON_DIMENSION_DP = "max_icon_dimension_dp";
+
+        /**
+         * Key name for the max icon dimensions in DP, for low-memory devices.
+         */
+        String KEY_MAX_ICON_DIMENSION_DP_LOWRAM = "max_icon_dimension_dp_lowram";
+
+        /**
+         * Key name for the max dynamic shortcuts per app. (int)
+         */
+        String KEY_MAX_SHORTCUTS = "max_shortcuts";
+
+        /**
+         * Key name for icon compression quality, 0-100.
+         */
+        String KEY_ICON_QUALITY = "icon_quality";
+
+        /**
+         * Key name for icon compression format: "PNG", "JPEG" or "WEBP"
+         */
+        String KEY_ICON_FORMAT = "icon_format";
+    }
+
+    final Context mContext;
+
+    private final Object mLock = new Object();
+
+    private final Handler mHandler;
+
+    @GuardedBy("mLock")
+    private final ArrayList<ShortcutChangeListener> mListeners = new ArrayList<>(1);
+
+    @GuardedBy("mLock")
+    private long mRawLastResetTime;
+
+    /**
+     * User ID -> package name -> list of ShortcutInfos.
+     */
+    @GuardedBy("mLock")
+    private final SparseArray<ArrayMap<String, PackageShortcuts>> mShortcuts =
+            new SparseArray<>();
+
+    /**
+     * Max number of dynamic shortcuts that each application can have at a time.
+     */
+    private int mMaxDynamicShortcuts;
+
+    /**
+     * Max number of updating API calls that each application can make a day.
+     */
+    int mMaxDailyUpdates;
+
+    /**
+     * Actual throttling-reset interval.  By default it's a day.
+     */
+    private long mResetInterval;
+
+    /**
+     * Icon max width/height in pixels.
+     */
+    private int mMaxIconDimension;
+
+    private CompressFormat mIconPersistFormat;
+    private int mIconPersistQuality;
+
+    public ShortcutService(Context context) {
+        mContext = Preconditions.checkNotNull(context);
+        LocalServices.addService(ShortcutServiceInternal.class, new LocalService());
+        mHandler = new Handler(BackgroundThread.get().getLooper());
+    }
+
+    /**
+     * System service lifecycle.
+     */
+    public static final class Lifecycle extends SystemService {
+        final ShortcutService mService;
+
+        public Lifecycle(Context context) {
+            super(context);
+            mService = new ShortcutService(context);
+        }
+
+        @Override
+        public void onStart() {
+            publishBinderService(Context.SHORTCUT_SERVICE, mService);
+        }
+
+        @Override
+        public void onBootPhase(int phase) {
+            mService.onBootPhase(phase);
+        }
+
+        @Override
+        public void onCleanupUser(int userHandle) {
+            synchronized (mService.mLock) {
+                mService.onCleanupUserInner(userHandle);
+            }
+        }
+
+        @Override
+        public void onUnlockUser(int userId) {
+            synchronized (mService.mLock) {
+                mService.onStartUserLocked(userId);
+            }
+        }
+    }
+
+    /** lifecycle event */
+    void onBootPhase(int phase) {
+        if (DEBUG) {
+            Slog.d(TAG, "onBootPhase: " + phase);
+        }
+        switch (phase) {
+            case SystemService.PHASE_LOCK_SETTINGS_READY:
+                initialize();
+                break;
+        }
+    }
+
+    /** lifecycle event */
+    void onStartUserLocked(int userId) {
+        // Preload
+        getUserShortcutsLocked(userId);
+    }
+
+    /** lifecycle event */
+    void onCleanupUserInner(int userId) {
+        // Unload
+        mShortcuts.delete(userId);
+    }
+
+    /** Return the base state file name */
+    private AtomicFile getBaseStateFile() {
+        final File path = new File(injectSystemDataPath(), FILENAME_BASE_STATE);
+        path.mkdirs();
+        return new AtomicFile(path);
+    }
+
+    /**
+     * Init the instance. (load the state file, etc)
+     */
+    private void initialize() {
+        synchronized (mLock) {
+            loadConfigurationLocked();
+            loadBaseStateLocked();
+        }
+    }
+
+    /**
+     * Load the configuration from Settings.
+     */
+    private void loadConfigurationLocked() {
+        updateConfigurationLocked(injectShortcutManagerConstants());
+    }
+
+    /**
+     * Load the configuration from Settings.
+     */
+    @VisibleForTesting
+    boolean updateConfigurationLocked(String config) {
+        boolean result = true;
+
+        final KeyValueListParser parser = new KeyValueListParser(',');
+        try {
+            parser.setString(config);
+        } catch (IllegalArgumentException e) {
+            // Failed to parse the settings string, log this and move on
+            // with defaults.
+            Slog.e(TAG, "Bad shortcut manager settings", e);
+            result = false;
+        }
+
+        mResetInterval = parser.getLong(
+                ConfigConstants.KEY_RESET_INTERVAL_SEC, DEFAULT_RESET_INTERVAL_SEC)
+                * 1000L;
+
+        mMaxDailyUpdates = (int) parser.getLong(
+                ConfigConstants.KEY_MAX_DAILY_UPDATES, DEFAULT_MAX_DAILY_UPDATES);
+
+        mMaxDynamicShortcuts = (int) parser.getLong(
+                ConfigConstants.KEY_MAX_SHORTCUTS, DEFAULT_MAX_SHORTCUTS_PER_APP);
+
+        final int iconDimensionDp = injectIsLowRamDevice()
+                ? (int) parser.getLong(
+                    ConfigConstants.KEY_MAX_ICON_DIMENSION_DP_LOWRAM,
+                    DEFAULT_MAX_ICON_DIMENSION_LOWRAM_DP)
+                : (int) parser.getLong(
+                    ConfigConstants.KEY_MAX_ICON_DIMENSION_DP,
+                    DEFAULT_MAX_ICON_DIMENSION_DP);
+
+        mMaxIconDimension = injectDipToPixel(iconDimensionDp);
+
+        mIconPersistFormat = CompressFormat.valueOf(
+                parser.getString(ConfigConstants.KEY_ICON_FORMAT, DEFAULT_ICON_PERSIST_FORMAT));
+
+        mIconPersistQuality = (int) parser.getLong(
+                ConfigConstants.KEY_ICON_QUALITY,
+                DEFAULT_ICON_PERSIST_QUALITY);
+
+        return result;
+    }
+
+    @VisibleForTesting
+    String injectShortcutManagerConstants() {
+        return android.provider.Settings.Global.getString(
+                mContext.getContentResolver(),
+                android.provider.Settings.Global.SHORTCUT_MANAGER_CONSTANTS);
+    }
+
+    @VisibleForTesting
+    int injectDipToPixel(int dip) {
+        return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dip,
+                mContext.getResources().getDisplayMetrics());
+    }
+
+    // === Persisting ===
+
+    @Nullable
+    static String parseStringAttribute(XmlPullParser parser, String attribute) {
+        return parser.getAttributeValue(null, attribute);
+    }
+
+    static int parseIntAttribute(XmlPullParser parser, String attribute) {
+        return (int) parseLongAttribute(parser, attribute);
+    }
+
+    static long parseLongAttribute(XmlPullParser parser, String attribute) {
+        final String value = parseStringAttribute(parser, attribute);
+        if (TextUtils.isEmpty(value)) {
+            return 0;
+        }
+        try {
+            return Long.parseLong(value);
+        } catch (NumberFormatException e) {
+            Slog.e(TAG, "Error parsing long " + value);
+            return 0;
+        }
+    }
+
+    @Nullable
+    static ComponentName parseComponentNameAttribute(XmlPullParser parser, String attribute) {
+        final String value = parseStringAttribute(parser, attribute);
+        if (TextUtils.isEmpty(value)) {
+            return null;
+        }
+        return ComponentName.unflattenFromString(value);
+    }
+
+    @Nullable
+    static Intent parseIntentAttribute(XmlPullParser parser, String attribute) {
+        final String value = parseStringAttribute(parser, attribute);
+        if (TextUtils.isEmpty(value)) {
+            return null;
+        }
+        try {
+            return Intent.parseUri(value, /* flags =*/ 0);
+        } catch (URISyntaxException e) {
+            Slog.e(TAG, "Error parsing intent", e);
+            return null;
+        }
+    }
+
+    static void writeTagValue(XmlSerializer out, String tag, String value) throws IOException {
+        if (TextUtils.isEmpty(value)) return;
+
+        out.startTag(null, tag);
+        out.attribute(null, ATTR_VALUE, value);
+        out.endTag(null, tag);
+    }
+
+    static void writeTagValue(XmlSerializer out, String tag, long value) throws IOException {
+        writeTagValue(out, tag, Long.toString(value));
+    }
+
+    static void writeTagExtra(XmlSerializer out, String tag, PersistableBundle bundle)
+            throws IOException, XmlPullParserException {
+        if (bundle == null) return;
+
+        out.startTag(null, tag);
+        bundle.saveToXml(out);
+        out.endTag(null, tag);
+    }
+
+    static void writeAttr(XmlSerializer out, String name, String value) throws IOException {
+        if (TextUtils.isEmpty(value)) return;
+
+        out.attribute(null, name, value);
+    }
+
+    static void writeAttr(XmlSerializer out, String name, long value) throws IOException {
+        writeAttr(out, name, String.valueOf(value));
+    }
+
+    static void writeAttr(XmlSerializer out, String name, ComponentName comp) throws IOException {
+        if (comp == null) return;
+        writeAttr(out, name, comp.flattenToString());
+    }
+
+    static void writeAttr(XmlSerializer out, String name, Intent intent) throws IOException {
+        if (intent == null) return;
+
+        writeAttr(out, name, intent.toUri(/* flags =*/ 0));
+    }
+
+    @VisibleForTesting
+    void saveBaseStateLocked() {
+        final AtomicFile file = getBaseStateFile();
+        if (DEBUG) {
+            Slog.i(TAG, "Saving to " + file.getBaseFile());
+        }
+
+        FileOutputStream outs = null;
+        try {
+            outs = file.startWrite();
+
+            // Write to XML
+            XmlSerializer out = new FastXmlSerializer();
+            out.setOutput(outs, StandardCharsets.UTF_8.name());
+            out.startDocument(null, true);
+            out.startTag(null, TAG_ROOT);
+
+            // Body.
+            writeTagValue(out, TAG_LAST_RESET_TIME, mRawLastResetTime);
+
+            // Epilogue.
+            out.endTag(null, TAG_ROOT);
+            out.endDocument();
+
+            // Close.
+            file.finishWrite(outs);
+        } catch (IOException e) {
+            Slog.e(TAG, "Failed to write to file " + file.getBaseFile(), e);
+            file.failWrite(outs);
+        }
+    }
+
+    private void loadBaseStateLocked() {
+        mRawLastResetTime = 0;
+
+        final AtomicFile file = getBaseStateFile();
+        if (DEBUG) {
+            Slog.i(TAG, "Loading from " + file.getBaseFile());
+        }
+        try (FileInputStream in = file.openRead()) {
+            XmlPullParser parser = Xml.newPullParser();
+            parser.setInput(in, StandardCharsets.UTF_8.name());
+
+            int type;
+            while ((type = parser.next()) != XmlPullParser.END_DOCUMENT) {
+                if (type != XmlPullParser.START_TAG) {
+                    continue;
+                }
+                final int depth = parser.getDepth();
+                // Check the root tag
+                final String tag = parser.getName();
+                if (depth == 1) {
+                    if (!TAG_ROOT.equals(tag)) {
+                        Slog.e(TAG, "Invalid root tag: " + tag);
+                        return;
+                    }
+                    continue;
+                }
+                // Assume depth == 2
+                switch (tag) {
+                    case TAG_LAST_RESET_TIME:
+                        mRawLastResetTime = parseLongAttribute(parser, ATTR_VALUE);
+                        break;
+                    default:
+                        Slog.e(TAG, "Invalid tag: " + tag);
+                        break;
+                }
+            }
+        } catch (FileNotFoundException e) {
+            // Use the default
+        } catch (IOException|XmlPullParserException e) {
+            Slog.e(TAG, "Failed to read file " + file.getBaseFile(), e);
+
+            mRawLastResetTime = 0;
+        }
+        // Adjust the last reset time.
+        getLastResetTimeLocked();
+    }
+
+    private void saveUserLocked(@UserIdInt int userId) {
+        final File path = new File(injectUserDataPath(userId), FILENAME_USER_PACKAGES);
+        if (DEBUG) {
+            Slog.i(TAG, "Saving to " + path);
+        }
+        path.mkdirs();
+        final AtomicFile file = new AtomicFile(path);
+        FileOutputStream outs = null;
+        try {
+            outs = file.startWrite();
+
+            // Write to XML
+            XmlSerializer out = new FastXmlSerializer();
+            out.setOutput(outs, StandardCharsets.UTF_8.name());
+            out.startDocument(null, true);
+            out.startTag(null, TAG_ROOT);
+
+            final ArrayMap<String, PackageShortcuts> packages = getUserShortcutsLocked(userId);
+
+            // Body.
+            for (int i = 0; i < packages.size(); i++) {
+                final String packageName = packages.keyAt(i);
+                final PackageShortcuts packageShortcuts = packages.valueAt(i);
+
+                packageShortcuts.saveToXml(out);
+            }
+
+            // Epilogue.
+            out.endTag(null, TAG_ROOT);
+            out.endDocument();
+
+            // Close.
+            file.finishWrite(outs);
+        } catch (IOException|XmlPullParserException e) {
+            Slog.e(TAG, "Failed to write to file " + file.getBaseFile(), e);
+            file.failWrite(outs);
+        }
+    }
+
+    static IOException throwForInvalidTag(int depth, String tag) throws IOException {
+        throw new IOException(String.format("Invalid tag '%s' found at depth %d", tag, depth));
+    }
+
+    @Nullable
+    private ArrayMap<String, PackageShortcuts> loadUserLocked(@UserIdInt int userId) {
+        final File path = new File(injectUserDataPath(userId), FILENAME_USER_PACKAGES);
+        if (DEBUG) {
+            Slog.i(TAG, "Loading from " + path);
+        }
+        final AtomicFile file = new AtomicFile(path);
+
+        final FileInputStream in;
+        try {
+            in = file.openRead();
+        } catch (FileNotFoundException e) {
+            if (DEBUG) {
+                Slog.i(TAG, "Not found " + path);
+            }
+            return null;
+        }
+        final ArrayMap<String, PackageShortcuts> ret = new ArrayMap<>();
+        try {
+            XmlPullParser parser = Xml.newPullParser();
+            parser.setInput(in, StandardCharsets.UTF_8.name());
+
+            PackageShortcuts shortcuts = null;
+
+            int type;
+            while ((type = parser.next()) != XmlPullParser.END_DOCUMENT) {
+                if (type != XmlPullParser.START_TAG) {
+                    continue;
+                }
+                final int depth = parser.getDepth();
+
+                final String tag = parser.getName();
+                if (DEBUG_LOAD) {
+                    Slog.d(TAG, String.format("depth=%d type=%d name=%s",
+                            depth, type, tag));
+                }
+                switch (depth) {
+                    case 1: {
+                        if (TAG_ROOT.equals(tag)) {
+                            continue;
+                        }
+                        break;
+                    }
+                    case 2: {
+                        switch (tag) {
+                            case TAG_PACKAGE:
+                                shortcuts = PackageShortcuts.loadFromXml(parser, userId);
+                                ret.put(shortcuts.mPackageName, shortcuts);
+                                continue;
+                        }
+                        break;
+                    }
+                }
+                throwForInvalidTag(depth, tag);
+            }
+            return ret;
+        } catch (IOException|XmlPullParserException e) {
+            Slog.e(TAG, "Failed to read file " + file.getBaseFile(), e);
+            return null;
+        } finally {
+            IoUtils.closeQuietly(in);
+        }
+    }
+
+    // TODO Actually make it async.
+    private void scheduleSaveBaseState() {
+        synchronized (mLock) {
+            saveBaseStateLocked();
+        }
+    }
+
+    // TODO Actually make it async.
+    private void scheduleSaveUser(@UserIdInt int userId) {
+        synchronized (mLock) {
+            saveUserLocked(userId);
+        }
+    }
+
+    /** Return the last reset time. */
+    long getLastResetTimeLocked() {
+        updateTimes();
+        return mRawLastResetTime;
+    }
+
+    /** Return the next reset time. */
+    long getNextResetTimeLocked() {
+        updateTimes();
+        return mRawLastResetTime + mResetInterval;
+    }
+
+    /**
+     * Update the last reset time.
+     */
+    private void updateTimes() {
+
+        final long now = injectCurrentTimeMillis();
+
+        final long prevLastResetTime = mRawLastResetTime;
+
+        if (mRawLastResetTime == 0) { // first launch.
+            // TODO Randomize??
+            mRawLastResetTime = now;
+        } else if (now < mRawLastResetTime) {
+            // Clock rewound.
+            // TODO Randomize??
+            mRawLastResetTime = now;
+        } else {
+            // TODO Do it properly.
+            while ((mRawLastResetTime + mResetInterval) <= now) {
+                mRawLastResetTime += mResetInterval;
+            }
+        }
+        if (prevLastResetTime != mRawLastResetTime) {
+            scheduleSaveBaseState();
+        }
+    }
+
+    /** Return the per-user state. */
+    @GuardedBy("mLock")
+    @NonNull
+    private ArrayMap<String, PackageShortcuts> getUserShortcutsLocked(@UserIdInt int userId) {
+        ArrayMap<String, PackageShortcuts> userPackages = mShortcuts.get(userId);
+        if (userPackages == null) {
+            userPackages = loadUserLocked(userId);
+            if (userPackages == null) {
+                userPackages = new ArrayMap<>();
+            }
+            mShortcuts.put(userId, userPackages);
+        }
+        return userPackages;
+    }
+
+    /** Return the per-user per-package state. */
+    @GuardedBy("mLock")
+    @NonNull
+    private PackageShortcuts getPackageShortcutsLocked(
+            @NonNull String packageName, @UserIdInt int userId) {
+        final ArrayMap<String, PackageShortcuts> userPackages = getUserShortcutsLocked(userId);
+        PackageShortcuts shortcuts = userPackages.get(packageName);
+        if (shortcuts == null) {
+            shortcuts = new PackageShortcuts(userId, packageName);
+            userPackages.put(packageName, shortcuts);
+        }
+        return shortcuts;
+    }
+
+    // === Caller validation ===
+
+    void removeIcon(@UserIdInt int userId, ShortcutInfo shortcut) {
+        if (shortcut.getBitmapPath() != null) {
+            if (DEBUG) {
+                Slog.d(TAG, "Removing " + shortcut.getBitmapPath());
+            }
+            new File(shortcut.getBitmapPath()).delete();
+
+            shortcut.setBitmapPath(null);
+            shortcut.setIconResourceId(0);
+            shortcut.clearFlags(ShortcutInfo.FLAG_HAS_ICON_FILE | ShortcutInfo.FLAG_HAS_ICON_RES);
+        }
+    }
+
+    @VisibleForTesting
+    static class FileOutputStreamWithPath extends FileOutputStream {
+        private final File mFile;
+
+        public FileOutputStreamWithPath(File file) throws FileNotFoundException {
+            super(file);
+            mFile = file;
+        }
+
+        public File getFile() {
+            return mFile;
+        }
+    }
+
+    /**
+     * Build the cached bitmap filename for a shortcut icon.
+     *
+     * The filename will be based on the ID, except certain characters will be escaped.
+     */
+    @VisibleForTesting
+    FileOutputStreamWithPath openIconFileForWrite(@UserIdInt int userId, ShortcutInfo shortcut)
+            throws IOException {
+        final File packagePath = new File(getUserBitmapFilePath(userId),
+                shortcut.getPackageName());
+        if (!packagePath.isDirectory()) {
+            packagePath.mkdirs();
+            if (!packagePath.isDirectory()) {
+                throw new IOException("Unable to create directory " + packagePath);
+            }
+            SELinux.restorecon(packagePath);
+        }
+
+        final String baseName = String.valueOf(injectCurrentTimeMillis());
+        for (int suffix = 0;; suffix++) {
+            final String filename = (suffix == 0 ? baseName : baseName + "_" + suffix) + ".png";
+            final File file = new File(packagePath, filename);
+            if (!file.exists()) {
+                if (DEBUG) {
+                    Slog.d(TAG, "Saving icon to " + file.getAbsolutePath());
+                }
+                return new FileOutputStreamWithPath(file);
+            }
+        }
+    }
+
+    void saveIconAndFixUpShortcut(@UserIdInt int userId, ShortcutInfo shortcut) {
+        if (shortcut.hasIconFile() || shortcut.hasIconResource()) {
+            return;
+        }
+
+        final long token = Binder.clearCallingIdentity();
+        try {
+            // Clear icon info on the shortcut.
+            shortcut.setIconResourceId(0);
+            shortcut.setBitmapPath(null);
+
+            final Icon icon = shortcut.getIcon();
+            if (icon == null) {
+                return; // has no icon
+            }
+
+            Bitmap bitmap = null;
+            try {
+                switch (icon.getType()) {
+                    case Icon.TYPE_RESOURCE: {
+                        injectValidateIconResPackage(shortcut, icon);
+
+                        shortcut.setIconResourceId(icon.getResId());
+                        shortcut.addFlags(ShortcutInfo.FLAG_HAS_ICON_RES);
+                        return;
+                    }
+                    case Icon.TYPE_BITMAP: {
+                        bitmap = icon.getBitmap();
+                        break;
+                    }
+                    case Icon.TYPE_URI: {
+                        final Uri uri = ContentProvider.maybeAddUserId(icon.getUri(), userId);
+
+                        try (InputStream is = mContext.getContentResolver().openInputStream(uri)) {
+
+                            bitmap = BitmapFactory.decodeStream(is);
+
+                        } catch (IOException e) {
+                            Slog.e(TAG, "Unable to load icon from " + uri);
+                            return;
+                        }
+                        break;
+                    }
+                    default:
+                        // This shouldn't happen because we've already validated the icon, but
+                        // just in case.
+                        throw ShortcutInfo.getInvalidIconException();
+                }
+                if (bitmap == null) {
+                    Slog.e(TAG, "Null bitmap detected");
+                    return;
+                }
+                // Shrink and write to the file.
+                File path = null;
+                try {
+                    final FileOutputStreamWithPath out = openIconFileForWrite(userId, shortcut);
+                    try {
+                        path = out.getFile();
+
+                        shrinkBitmap(bitmap, mMaxIconDimension)
+                                .compress(mIconPersistFormat, mIconPersistQuality, out);
+
+                        shortcut.setBitmapPath(out.getFile().getAbsolutePath());
+                        shortcut.addFlags(ShortcutInfo.FLAG_HAS_ICON_FILE);
+                    } finally {
+                        IoUtils.closeQuietly(out);
+                    }
+                } catch (IOException|RuntimeException e) {
+                    // STOPSHIP Change wtf to e
+                    Slog.wtf(ShortcutService.TAG, "Unable to write bitmap to file", e);
+                    if (path != null && path.exists()) {
+                        path.delete();
+                    }
+                }
+            } finally {
+                if (bitmap != null) {
+                    bitmap.recycle();
+                }
+                // Once saved, we won't use the original icon information, so null it out.
+                shortcut.clearIcon();
+            }
+        } finally {
+            Binder.restoreCallingIdentity(token);
+        }
+    }
+
+    // Unfortunately we can't do this check in unit tests because we fake creator package names,
+    // so override in unit tests.
+    // TODO CTS this case.
+    void injectValidateIconResPackage(ShortcutInfo shortcut, Icon icon) {
+        if (!shortcut.getPackageName().equals(icon.getResPackage())) {
+            throw new IllegalArgumentException(
+                    "Icon resource must reside in shortcut owner package");
+        }
+    }
+
+    @VisibleForTesting
+    static Bitmap shrinkBitmap(Bitmap in, int maxSize) {
+        // Original width/height.
+        final int ow = in.getWidth();
+        final int oh = in.getHeight();
+        if ((ow <= maxSize) && (oh <= maxSize)) {
+            if (DEBUG) {
+                Slog.d(TAG, String.format("Icon size %dx%d, no need to shrink", ow, oh));
+            }
+            return in;
+        }
+        final int longerDimension = Math.max(ow, oh);
+
+        // New width and height.
+        final int nw = ow * maxSize / longerDimension;
+        final int nh = oh * maxSize / longerDimension;
+        if (DEBUG) {
+            Slog.d(TAG, String.format("Icon size %dx%d, shrinking to %dx%d",
+                    ow, oh, nw, nh));
+        }
+
+        final Bitmap scaledBitmap = Bitmap.createBitmap(nw, nh, Bitmap.Config.ARGB_8888);
+        final Canvas c = new Canvas(scaledBitmap);
+
+        final RectF dst = new RectF(0, 0, nw, nh);
+
+        c.drawBitmap(in, /*src=*/ null, dst, /* paint =*/ null);
+
+        in.recycle();
+
+        return scaledBitmap;
+    }
+
+    // === Caller validation ===
+
+    private boolean isCallerSystem() {
+        final int callingUid = injectBinderCallingUid();
+         return UserHandle.isSameApp(callingUid, Process.SYSTEM_UID);
+    }
+
+    private boolean isCallerShell() {
+        final int callingUid = injectBinderCallingUid();
+        return callingUid == Process.SHELL_UID || callingUid == Process.ROOT_UID;
+    }
+
+    private void enforceSystemOrShell() {
+        Preconditions.checkState(isCallerSystem() || isCallerShell(),
+                "Caller must be system or shell");
+    }
+
+    private void enforceShell() {
+        Preconditions.checkState(isCallerShell(), "Caller must be shell");
+    }
+
+    private void verifyCaller(@NonNull String packageName, @UserIdInt int userId) {
+        Preconditions.checkStringNotEmpty(packageName, "packageName");
+
+        if (isCallerSystem()) {
+            return; // no check
+        }
+
+        final int callingUid = injectBinderCallingUid();
+
+        // Otherwise, make sure the arguments are valid.
+        if (UserHandle.getUserId(callingUid) != userId) {
+            throw new SecurityException("Invalid user-ID");
+        }
+        if (injectGetPackageUid(packageName, userId) == injectBinderCallingUid()) {
+            return; // Caller is valid.
+        }
+        throw new SecurityException("Caller UID= doesn't own " + packageName);
+    }
+
+    // Test overrides it.
+    int injectGetPackageUid(@NonNull String packageName, @UserIdInt int userId) {
+        try {
+
+            // TODO Is MATCH_UNINSTALLED_PACKAGES correct to get SD card app info?
+
+            return mContext.getPackageManager().getPackageUidAsUser(packageName,
+                    PackageManager.MATCH_ENCRYPTION_AWARE_AND_UNAWARE
+                            | PackageManager.MATCH_UNINSTALLED_PACKAGES, userId);
+        } catch (NameNotFoundException e) {
+            return -1;
+        }
+    }
+
+    /**
+     * Throw if {@code numShortcuts} is bigger than {@link #mMaxDynamicShortcuts}.
+     */
+    void enforceMaxDynamicShortcuts(int numShortcuts) {
+        if (numShortcuts > mMaxDynamicShortcuts) {
+            throw new IllegalArgumentException("Max number of dynamic shortcuts exceeded");
+        }
+    }
+
+    /**
+     * - Sends a notification to LauncherApps
+     * - Write to file
+     */
+    private void userPackageChanged(@NonNull String packageName, @UserIdInt int userId) {
+        notifyListeners(packageName, userId);
+        scheduleSaveUser(userId);
+    }
+
+    private void notifyListeners(@NonNull String packageName, @UserIdInt int userId) {
+        final ArrayList<ShortcutChangeListener> copy;
+        final List<ShortcutInfo> shortcuts = new ArrayList<>();
+        synchronized (mLock) {
+            copy = new ArrayList<>(mListeners);
+
+            getPackageShortcutsLocked(packageName, userId)
+                    .findAll(shortcuts, /* query =*/ null, ShortcutInfo.CLONE_REMOVE_NON_KEY_INFO);
+        }
+        for (int i = copy.size() - 1; i >= 0; i--) {
+            copy.get(i).onShortcutChanged(packageName, shortcuts, userId);
+        }
+    }
+
+    /**
+     * Clean up / validate an incoming shortcut.
+     * - Make sure all mandatory fields are set.
+     * - Make sure the intent's extras are persistable, and them to set
+     *  {@link ShortcutInfo#mIntentPersistableExtras}.  Also clear its extras.
+     * - Clear flags.
+     *
+     * TODO Detailed unit tests
+     */
+    private void fixUpIncomingShortcutInfo(@NonNull ShortcutInfo shortcut, boolean forUpdate) {
+        Preconditions.checkNotNull(shortcut, "Null shortcut detected");
+        if (shortcut.getActivityComponent() != null) {
+            Preconditions.checkState(
+                    shortcut.getPackageName().equals(
+                            shortcut.getActivityComponent().getPackageName()),
+                    "Activity package name mismatch");
+        }
+
+        if (!forUpdate) {
+            shortcut.enforceMandatoryFields();
+        }
+        if (shortcut.getIcon() != null) {
+            ShortcutInfo.validateIcon(shortcut.getIcon());
+        }
+
+        validateForXml(shortcut.getId());
+        validateForXml(shortcut.getTitle());
+        validatePersistableBundleForXml(shortcut.getIntentPersistableExtras());
+        validatePersistableBundleForXml(shortcut.getExtras());
+
+        shortcut.setFlags(0);
+    }
+
+    // KXmlSerializer is strict and doesn't allow certain characters, so we disallow those
+    // characters.
+
+    private static void validatePersistableBundleForXml(PersistableBundle b) {
+        if (b == null || b.size() == 0) {
+            return;
+        }
+        for (String key : b.keySet()) {
+            validateForXml(key);
+            final Object value = b.get(key);
+            if (value == null) {
+                continue;
+            } else if (value instanceof String) {
+                validateForXml((String) value);
+            } else if (value instanceof String[]) {
+                for (String v : (String[]) value) {
+                    validateForXml(v);
+                }
+            } else if (value instanceof PersistableBundle) {
+                validatePersistableBundleForXml((PersistableBundle) value);
+            }
+        }
+    }
+
+    private static void validateForXml(String s) {
+        if (TextUtils.isEmpty(s)) {
+            return;
+        }
+        for (int i = s.length() - 1; i >= 0; i--) {
+            if (!isAllowedInXml(s.charAt(i))) {
+                throw new IllegalArgumentException("Unsupported character detected in: " + s);
+            }
+        }
+    }
+
+    private static boolean isAllowedInXml(char c) {
+        return (c >= 0x20 && c <= 0xd7ff) || (c >= 0xe000 && c <= 0xfffd);
+    }
+
+    // === APIs ===
+
+    @Override
+    public boolean setDynamicShortcuts(String packageName, ParceledListSlice shortcutInfoList,
+            @UserIdInt int userId) {
+        verifyCaller(packageName, userId);
+
+        final List<ShortcutInfo> newShortcuts = (List<ShortcutInfo>) shortcutInfoList.getList();
+        final int size = newShortcuts.size();
+
+        synchronized (mLock) {
+            final PackageShortcuts ps = getPackageShortcutsLocked(packageName, userId);
+
+            // Throttling.
+            if (!ps.tryApiCall(this)) {
+                return false;
+            }
+            enforceMaxDynamicShortcuts(size);
+
+            // Validate the shortcuts.
+            for (int i = 0; i < size; i++) {
+                fixUpIncomingShortcutInfo(newShortcuts.get(i), /* forUpdate= */ false);
+            }
+
+            // First, remove all un-pinned; dynamic shortcuts
+            ps.deleteAllDynamicShortcuts(this);
+
+            // Then, add/update all.  We need to make sure to take over "pinned" flag.
+            for (int i = 0; i < size; i++) {
+                final ShortcutInfo newShortcut = newShortcuts.get(i);
+                newShortcut.addFlags(ShortcutInfo.FLAG_DYNAMIC);
+                ps.updateShortcutWithCapping(this, newShortcut);
+            }
+        }
+        userPackageChanged(packageName, userId);
+        return true;
+    }
+
+    @Override
+    public boolean updateShortcuts(String packageName, ParceledListSlice shortcutInfoList,
+            @UserIdInt int userId) {
+        verifyCaller(packageName, userId);
+
+        final List<ShortcutInfo> newShortcuts = (List<ShortcutInfo>) shortcutInfoList.getList();
+        final int size = newShortcuts.size();
+
+        synchronized (mLock) {
+            final PackageShortcuts ps = getPackageShortcutsLocked(packageName, userId);
+
+            // Throttling.
+            if (!ps.tryApiCall(this)) {
+                return false;
+            }
+
+            for (int i = 0; i < size; i++) {
+                final ShortcutInfo source = newShortcuts.get(i);
+                fixUpIncomingShortcutInfo(source, /* forUpdate= */ true);
+
+                final ShortcutInfo target = ps.findShortcutById(source.getId());
+                if (target != null) {
+                    final boolean replacingIcon = (source.getIcon() != null);
+                    if (replacingIcon) {
+                        removeIcon(userId, target);
+                    }
+
+                    target.copyNonNullFieldsFrom(source);
+
+                    if (replacingIcon) {
+                        saveIconAndFixUpShortcut(userId, target);
+                    }
+                }
+            }
+        }
+        userPackageChanged(packageName, userId);
+
+        return true;
+    }
+
+    @Override
+    public boolean addDynamicShortcut(String packageName, ShortcutInfo newShortcut,
+            @UserIdInt int userId) {
+        verifyCaller(packageName, userId);
+
+        synchronized (mLock) {
+            final PackageShortcuts ps = getPackageShortcutsLocked(packageName, userId);
+
+            // Throttling.
+            if (!ps.tryApiCall(this)) {
+                return false;
+            }
+
+            // Validate the shortcut.
+            fixUpIncomingShortcutInfo(newShortcut, /* forUpdate= */ false);
+
+            // Add it.
+            newShortcut.addFlags(ShortcutInfo.FLAG_DYNAMIC);
+            ps.updateShortcutWithCapping(this, newShortcut);
+        }
+        userPackageChanged(packageName, userId);
+
+        return true;
+    }
+
+    @Override
+    public void deleteDynamicShortcut(String packageName, String shortcutId,
+            @UserIdInt int userId) {
+        verifyCaller(packageName, userId);
+        Preconditions.checkStringNotEmpty(shortcutId, "shortcutId must be provided");
+
+        synchronized (mLock) {
+            getPackageShortcutsLocked(packageName, userId).deleteDynamicWithId(this, shortcutId);
+        }
+        userPackageChanged(packageName, userId);
+    }
+
+    @Override
+    public void deleteAllDynamicShortcuts(String packageName, @UserIdInt int userId) {
+        verifyCaller(packageName, userId);
+
+        synchronized (mLock) {
+            getPackageShortcutsLocked(packageName, userId).deleteAllDynamicShortcuts(this);
+        }
+        userPackageChanged(packageName, userId);
+    }
+
+    @Override
+    public ParceledListSlice<ShortcutInfo> getDynamicShortcuts(String packageName,
+            @UserIdInt int userId) {
+        verifyCaller(packageName, userId);
+        synchronized (mLock) {
+            return getShortcutsWithQueryLocked(
+                    packageName, userId, ShortcutInfo.CLONE_REMOVE_FOR_CREATOR,
+                    ShortcutInfo::isDynamic);
+        }
+    }
+
+    @Override
+    public ParceledListSlice<ShortcutInfo> getPinnedShortcuts(String packageName,
+            @UserIdInt int userId) {
+        verifyCaller(packageName, userId);
+        synchronized (mLock) {
+            return getShortcutsWithQueryLocked(
+                    packageName, userId, ShortcutInfo.CLONE_REMOVE_FOR_CREATOR,
+                    ShortcutInfo::isPinned);
+        }
+    }
+
+    private ParceledListSlice<ShortcutInfo> getShortcutsWithQueryLocked(@NonNull String packageName,
+            @UserIdInt int userId, int cloneFlags, @NonNull Predicate<ShortcutInfo> query) {
+
+        final ArrayList<ShortcutInfo> ret = new ArrayList<>();
+
+        getPackageShortcutsLocked(packageName, userId).findAll(ret, query, cloneFlags);
+
+        return new ParceledListSlice<>(ret);
+    }
+
+    @Override
+    public int getMaxDynamicShortcutCount(String packageName, @UserIdInt int userId)
+            throws RemoteException {
+        verifyCaller(packageName, userId);
+
+        return mMaxDynamicShortcuts;
+    }
+
+    @Override
+    public int getRemainingCallCount(String packageName, @UserIdInt int userId) {
+        verifyCaller(packageName, userId);
+
+        synchronized (mLock) {
+            return mMaxDailyUpdates
+                    - getPackageShortcutsLocked(packageName, userId).getApiCallCount(this);
+        }
+    }
+
+    @Override
+    public long getRateLimitResetTime(String packageName, @UserIdInt int userId) {
+        verifyCaller(packageName, userId);
+
+        synchronized (mLock) {
+            return getNextResetTimeLocked();
+        }
+    }
+
+    @Override
+    public int getIconMaxDimensions(String packageName, int userId) throws RemoteException {
+        synchronized (mLock) {
+            return mMaxIconDimension;
+        }
+    }
+
+    /**
+     * Reset all throttling, for developer options and command line.  Only system/shell can call it.
+     */
+    @Override
+    public void resetThrottling() {
+        enforceSystemOrShell();
+
+        resetThrottlingInner();
+    }
+
+    @VisibleForTesting
+    void resetThrottlingInner() {
+        synchronized (mLock) {
+            mRawLastResetTime = injectCurrentTimeMillis();
+        }
+        scheduleSaveBaseState();
+        Slog.i(TAG, "ShortcutManager: throttling counter reset");
+    }
+
+    /**
+     * Entry point from {@link LauncherApps}.
+     */
+    private class LocalService extends ShortcutServiceInternal {
+        @Override
+        public List<ShortcutInfo> getShortcuts(
+                @NonNull String callingPackage, long changedSince,
+                @Nullable String packageName, @Nullable ComponentName componentName,
+                int queryFlags, int userId) {
+            final ArrayList<ShortcutInfo> ret = new ArrayList<>();
+            final int cloneFlag =
+                    ((queryFlags & ShortcutQuery.FLAG_GET_KEY_FIELDS_ONLY) == 0)
+                            ? ShortcutInfo.CLONE_REMOVE_FOR_LAUNCHER
+                            : ShortcutInfo.CLONE_REMOVE_NON_KEY_INFO;
+
+            synchronized (mLock) {
+                if (packageName != null) {
+                    getShortcutsInnerLocked(packageName, changedSince, componentName, queryFlags,
+                            userId, ret, cloneFlag);
+                } else {
+                    final ArrayMap<String, PackageShortcuts> packages =
+                            getUserShortcutsLocked(userId);
+                    for (int i = packages.size() - 1; i >= 0; i--) {
+                        getShortcutsInnerLocked(
+                                packages.keyAt(i),
+                                changedSince, componentName, queryFlags, userId, ret, cloneFlag);
+                    }
+                }
+            }
+            return ret;
+        }
+
+        private void getShortcutsInnerLocked(@Nullable String packageName,long changedSince,
+                @Nullable ComponentName componentName, int queryFlags,
+                int userId, ArrayList<ShortcutInfo> ret, int cloneFlag) {
+            getPackageShortcutsLocked(packageName, userId).findAll(ret,
+                    (ShortcutInfo si) -> {
+                        if (si.getLastChangedTimestamp() < changedSince) {
+                            return false;
+                        }
+                        if (componentName != null
+                                && !componentName.equals(si.getActivityComponent())) {
+                            return false;
+                        }
+                        final boolean matchDynamic =
+                                ((queryFlags & ShortcutQuery.FLAG_GET_DYNAMIC) != 0)
+                                && si.isDynamic();
+                        final boolean matchPinned =
+                                ((queryFlags & ShortcutQuery.FLAG_GET_PINNED) != 0)
+                                        && si.isPinned();
+                        return matchDynamic || matchPinned;
+                    }, cloneFlag);
+        }
+
+        @Override
+        public List<ShortcutInfo> getShortcutInfo(
+                @NonNull String callingPackage,
+                @NonNull String packageName, @Nullable List<String> ids, int userId) {
+            // Calling permission must be checked by LauncherAppsImpl.
+            Preconditions.checkStringNotEmpty(packageName, "packageName");
+
+            final ArrayList<ShortcutInfo> ret = new ArrayList<>(ids.size());
+            final ArraySet<String> idSet = new ArraySet<>(ids);
+            synchronized (mLock) {
+                getPackageShortcutsLocked(packageName, userId).findAll(ret,
+                        (ShortcutInfo si) -> idSet.contains(si.getId()),
+                        ShortcutInfo.CLONE_REMOVE_FOR_LAUNCHER);
+            }
+            return ret;
+        }
+
+        @Override
+        public void pinShortcuts(@NonNull String callingPackage, @NonNull String packageName,
+                @NonNull List<String> shortcutIds, int userId) {
+            // Calling permission must be checked by LauncherAppsImpl.
+            Preconditions.checkStringNotEmpty(packageName, "packageName");
+            Preconditions.checkNotNull(shortcutIds, "shortcutIds");
+
+            synchronized (mLock) {
+                getPackageShortcutsLocked(packageName, userId).replacePinned(
+                        ShortcutService.this, callingPackage, shortcutIds);
+            }
+            userPackageChanged(packageName, userId);
+        }
+
+        @Override
+        public Intent createShortcutIntent(@NonNull String callingPackage,
+                @NonNull String packageName, @NonNull String shortcutId, int userId) {
+            // Calling permission must be checked by LauncherAppsImpl.
+            Preconditions.checkStringNotEmpty(packageName, "packageName can't be empty");
+            Preconditions.checkStringNotEmpty(shortcutId, "shortcutId can't be empty");
+
+            synchronized (mLock) {
+                final ShortcutInfo fullShortcut =
+                        getPackageShortcutsLocked(packageName, userId)
+                        .findShortcutById(shortcutId);
+                return fullShortcut == null ? null : fullShortcut.getIntent();
+            }
+        }
+
+        @Override
+        public void addListener(@NonNull ShortcutChangeListener listener) {
+            synchronized (mLock) {
+                mListeners.add(Preconditions.checkNotNull(listener));
+            }
+        }
+
+        @Override
+        public int getShortcutIconResId(@NonNull String callingPackage,
+                @NonNull ShortcutInfo shortcut, int userId) {
+            Preconditions.checkNotNull(shortcut, "shortcut");
+
+            synchronized (mLock) {
+                final ShortcutInfo shortcutInfo = getPackageShortcutsLocked(
+                        shortcut.getPackageName(), userId).findShortcutById(shortcut.getId());
+                return (shortcutInfo != null && shortcutInfo.hasIconResource())
+                        ? shortcutInfo.getIconResourceId() : 0;
+            }
+        }
+
+        @Override
+        public ParcelFileDescriptor getShortcutIconFd(@NonNull String callingPackage,
+                @NonNull ShortcutInfo shortcutIn, int userId) {
+            Preconditions.checkNotNull(shortcutIn, "shortcut");
+
+            synchronized (mLock) {
+                final ShortcutInfo shortcutInfo = getPackageShortcutsLocked(
+                        shortcutIn.getPackageName(), userId).findShortcutById(shortcutIn.getId());
+                if (shortcutInfo == null || !shortcutInfo.hasIconFile()) {
+                    return null;
+                }
+                try {
+                    if (shortcutInfo.getBitmapPath() == null) {
+                        Slog.w(TAG, "null bitmap detected in getShortcutIconFd()");
+                        return null;
+                    }
+                    return ParcelFileDescriptor.open(
+                            new File(shortcutInfo.getBitmapPath()),
+                            ParcelFileDescriptor.MODE_READ_ONLY);
+                } catch (FileNotFoundException e) {
+                    Slog.e(TAG, "Icon file not found: " + shortcutInfo.getBitmapPath());
+                    return null;
+                }
+            }
+        }
+    }
+
+    // === Dump ===
+
+    @Override
+    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
+                != PackageManager.PERMISSION_GRANTED) {
+            pw.println("Permission Denial: can't dump UserManager from from pid="
+                    + Binder.getCallingPid()
+                    + ", uid=" + Binder.getCallingUid()
+                    + " without permission "
+                    + android.Manifest.permission.DUMP);
+            return;
+        }
+        dumpInner(pw);
+    }
+
+    @VisibleForTesting
+    void dumpInner(PrintWriter pw) {
+        synchronized (mLock) {
+            final long now = injectCurrentTimeMillis();
+            pw.print("Now: [");
+            pw.print(now);
+            pw.print("] ");
+            pw.print(formatTime(now));
+
+            pw.print("  Raw last reset: [");
+            pw.print(mRawLastResetTime);
+            pw.print("] ");
+            pw.print(formatTime(mRawLastResetTime));
+
+            final long last = getLastResetTimeLocked();
+            pw.print("  Last reset: [");
+            pw.print(last);
+            pw.print("] ");
+            pw.print(formatTime(last));
+
+            final long next = getNextResetTimeLocked();
+            pw.print("  Next reset: [");
+            pw.print(next);
+            pw.print("] ");
+            pw.print(formatTime(next));
+            pw.println();
+
+            pw.print("  Max icon dim: ");
+            pw.print(mMaxIconDimension);
+            pw.print("  Icon format: ");
+            pw.print(mIconPersistFormat);
+            pw.print("  Icon quality: ");
+            pw.print(mIconPersistQuality);
+            pw.println();
+
+            pw.println();
+
+            for (int i = 0; i < mShortcuts.size(); i++) {
+                dumpUserLocked(pw, mShortcuts.keyAt(i));
+            }
+        }
+    }
+
+    private void dumpUserLocked(PrintWriter pw, int userId) {
+        pw.print("  User: ");
+        pw.print(userId);
+        pw.println();
+
+        final ArrayMap<String, PackageShortcuts> packages = mShortcuts.get(userId);
+        if (packages == null) {
+            return;
+        }
+        for (int j = 0; j < packages.size(); j++) {
+            dumpPackageLocked(pw, userId, packages.keyAt(j));
+        }
+        pw.println();
+    }
+
+    private void dumpPackageLocked(PrintWriter pw, int userId, String packageName) {
+        final PackageShortcuts packageShortcuts = mShortcuts.get(userId).get(packageName);
+        if (packageShortcuts == null) {
+            return;
+        }
+
+        packageShortcuts.dump(this, pw, "    ");
+    }
+
+    static String formatTime(long time) {
+        Time tobj = new Time();
+        tobj.set(time);
+        return tobj.format("%Y-%m-%d %H:%M:%S");
+    }
+
+    // === Shell support ===
+
+    @Override
+    public void onShellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err,
+            String[] args, ResultReceiver resultReceiver) throws RemoteException {
+
+        enforceShell();
+
+        (new MyShellCommand()).exec(this, in, out, err, args, resultReceiver);
+    }
+
+    /**
+     * Handle "adb shell cmd".
+     */
+    private class MyShellCommand extends ShellCommand {
+        @Override
+        public int onCommand(String cmd) {
+            if (cmd == null) {
+                return handleDefaultCommands(cmd);
+            }
+            final PrintWriter pw = getOutPrintWriter();
+            int ret = 1;
+            switch (cmd) {
+                case "reset-package-throttling":
+                    ret = handleResetPackageThrottling();
+                    break;
+                case "reset-throttling":
+                    ret = handleResetThrottling();
+                    break;
+                case "override-config":
+                    ret = handleOverrideConfig();
+                    break;
+                case "reset-config":
+                    ret = handleResetConfig();
+                    break;
+                default:
+                    return handleDefaultCommands(cmd);
+            }
+            if (ret == 0) {
+                pw.println("Success");
+            }
+            return ret;
+        }
+
+        @Override
+        public void onHelp() {
+            final PrintWriter pw = getOutPrintWriter();
+            pw.println("Usage: cmd shortcut COMMAND [options ...]");
+            pw.println();
+            pw.println("cmd shortcut reset-package-throttling [--user USER_ID] PACKAGE");
+            pw.println("    Reset throttling for a package");
+            pw.println();
+            pw.println("cmd shortcut reset-throttling");
+            pw.println("    Reset throttling for all packages and users");
+            pw.println();
+            pw.println("cmd shortcut override-config CONFIG");
+            pw.println("    Override the configuration for testing (will last until reboot)");
+            pw.println();
+            pw.println("cmd shortcut reset-config");
+            pw.println("    Reset the configuration set with \"update-config\"");
+            pw.println();
+        }
+
+        private int handleResetThrottling() {
+            resetThrottling();
+            return 0;
+        }
+
+        private int handleResetPackageThrottling() {
+            final PrintWriter pw = getOutPrintWriter();
+
+            int userId = UserHandle.USER_SYSTEM;
+            String opt;
+            while ((opt = getNextOption()) != null) {
+                switch (opt) {
+                    case "--user":
+                        userId = UserHandle.parseUserArg(getNextArgRequired());
+                        break;
+                    default:
+                        pw.println("Error: Unknown option: " + opt);
+                        return 1;
+                }
+            }
+            final String packageName = getNextArgRequired();
+
+            synchronized (mLock) {
+                getPackageShortcutsLocked(packageName, userId).resetRateLimitingForCommandLine();
+                saveUserLocked(userId);
+            }
+
+            return 0;
+        }
+
+        private int handleOverrideConfig() {
+            final PrintWriter pw = getOutPrintWriter();
+            final String config = getNextArgRequired();
+
+            synchronized (mLock) {
+                if (!updateConfigurationLocked(config)) {
+                    pw.println("override-config failed.  See logcat for details.");
+                    return 1;
+                }
+            }
+            return 0;
+        }
+
+        private int handleResetConfig() {
+            synchronized (mLock) {
+                loadConfigurationLocked();
+            }
+            return 0;
+        }
+    }
+
+    // === Unit test support ===
+
+    // Injection point.
+    long injectCurrentTimeMillis() {
+        return System.currentTimeMillis();
+    }
+
+    // Injection point.
+    int injectBinderCallingUid() {
+        return getCallingUid();
+    }
+
+    File injectSystemDataPath() {
+        return Environment.getDataSystemDirectory();
+    }
+
+    File injectUserDataPath(@UserIdInt int userId) {
+        return new File(Environment.getDataSystemCeDirectory(userId), DIRECTORY_PER_USER);
+    }
+
+    @VisibleForTesting
+    boolean injectIsLowRamDevice() {
+        return ActivityManager.isLowRamDeviceStatic();
+    }
+
+    File getUserBitmapFilePath(@UserIdInt int userId) {
+        return new File(injectUserDataPath(userId), DIRECTORY_BITMAPS);
+    }
+
+    @VisibleForTesting
+    SparseArray<ArrayMap<String, PackageShortcuts>> getShortcutsForTest() {
+        return mShortcuts;
+    }
+
+    @VisibleForTesting
+    int getMaxDynamicShortcutsForTest() {
+        return mMaxDynamicShortcuts;
+    }
+
+    @VisibleForTesting
+    int getMaxDailyUpdatesForTest() {
+        return mMaxDailyUpdates;
+    }
+
+    @VisibleForTesting
+    long getResetIntervalForTest() {
+        return mResetInterval;
+    }
+
+    @VisibleForTesting
+    int getMaxIconDimensionForTest() {
+        return mMaxIconDimension;
+    }
+
+    @VisibleForTesting
+    CompressFormat getIconPersistFormatForTest() {
+        return mIconPersistFormat;
+    }
+
+    @VisibleForTesting
+    int getIconPersistQualityForTest() {
+        return mIconPersistQuality;
+    }
+
+    @VisibleForTesting
+    ShortcutInfo getPackageShortcutForTest(String packageName, String shortcutId, int userId) {
+        synchronized (mLock) {
+            return getPackageShortcutsLocked(packageName, userId).findShortcutById(shortcutId);
+        }
+    }
+}
+
+/**
+ * All the information relevant to shortcuts from a single package (per-user).
+ */
+class PackageShortcuts {
+    private static final String TAG = ShortcutService.TAG;
+
+    @UserIdInt
+    final int mUserId;
+
+    @NonNull
+    final String mPackageName;
+
+    /**
+     * All the shortcuts from the package, keyed on IDs.
+     */
+    final private ArrayMap<String, ShortcutInfo> mShortcuts = new ArrayMap<>();
+
+    /**
+     * # of dynamic shortcuts.
+     */
+    private int mDynamicShortcutCount = 0;
+
+    /**
+     * # of times the package has called rate-limited APIs.
+     */
+    private int mApiCallCount;
+
+    /**
+     * When {@link #mApiCallCount} was reset last time.
+     */
+    private long mLastResetTime;
+
+    PackageShortcuts(int userId, String packageName) {
+        mUserId = userId;
+        mPackageName = packageName;
+    }
+
+    @GuardedBy("mLock")
+    @Nullable
+    public ShortcutInfo findShortcutById(String id) {
+        return mShortcuts.get(id);
+    }
+
+    private ShortcutInfo deleteShortcut(@NonNull ShortcutService s,
+            @NonNull String id) {
+        final ShortcutInfo shortcut = mShortcuts.remove(id);
+        if (shortcut != null) {
+            s.removeIcon(mUserId, shortcut);
+            shortcut.clearFlags(ShortcutInfo.FLAG_DYNAMIC | ShortcutInfo.FLAG_PINNED);
+        }
+        return shortcut;
+    }
+
+    void addShortcut(@NonNull ShortcutService s, @NonNull ShortcutInfo newShortcut) {
+        deleteShortcut(s, newShortcut.getId());
+        s.saveIconAndFixUpShortcut(mUserId, newShortcut);
+        mShortcuts.put(newShortcut.getId(), newShortcut);
+    }
+
+    /**
+     * Add a shortcut, or update one with the same ID, with taking over existing flags.
+     *
+     * It checks the max number of dynamic shortcuts.
+     */
+    @GuardedBy("mLock")
+    public void updateShortcutWithCapping(@NonNull ShortcutService s,
+            @NonNull ShortcutInfo newShortcut) {
+        final ShortcutInfo oldShortcut = mShortcuts.get(newShortcut.getId());
+
+        int oldFlags = 0;
+        int newDynamicCount = mDynamicShortcutCount;
+
+        if (oldShortcut != null) {
+            oldFlags = oldShortcut.getFlags();
+            if (oldShortcut.isDynamic()) {
+                newDynamicCount--;
+            }
+        }
+        if (newShortcut.isDynamic()) {
+            newDynamicCount++;
+        }
+        // Make sure there's still room.
+        s.enforceMaxDynamicShortcuts(newDynamicCount);
+
+        // Okay, make it dynamic and add.
+        newShortcut.addFlags(oldFlags);
+
+        addShortcut(s, newShortcut);
+        mDynamicShortcutCount = newDynamicCount;
+    }
+
+    /**
+     * Remove all shortcuts that aren't pinned nor dynamic.
+     */
+    private void removeOrphans(@NonNull ShortcutService s) {
+        ArrayList<String> removeList = null; // Lazily initialize.
+
+        for (int i = mShortcuts.size() - 1; i >= 0; i--) {
+            final ShortcutInfo si = mShortcuts.valueAt(i);
+
+            if (si.isPinned() || si.isDynamic()) continue;
+
+            if (removeList == null) {
+                removeList = new ArrayList<>();
+            }
+            removeList.add(si.getId());
+        }
+        if (removeList != null) {
+            for (int i = removeList.size() - 1 ; i >= 0; i--) {
+                deleteShortcut(s, removeList.get(i));
+            }
+        }
+    }
+
+    @GuardedBy("mLock")
+    public void deleteAllDynamicShortcuts(@NonNull ShortcutService s) {
+        for (int i = mShortcuts.size() - 1; i >= 0; i--) {
+            mShortcuts.valueAt(i).clearFlags(ShortcutInfo.FLAG_DYNAMIC);
+        }
+        removeOrphans(s);
+        mDynamicShortcutCount = 0;
+    }
+
+    @GuardedBy("mLock")
+    public void deleteDynamicWithId(@NonNull ShortcutService s, @NonNull String shortcutId) {
+        final ShortcutInfo oldShortcut = mShortcuts.get(shortcutId);
+
+        if (oldShortcut == null) {
+            return;
+        }
+        if (oldShortcut.isDynamic()) {
+            mDynamicShortcutCount--;
+        }
+        if (oldShortcut.isPinned()) {
+            oldShortcut.clearFlags(ShortcutInfo.FLAG_DYNAMIC);
+        } else {
+            deleteShortcut(s, shortcutId);
+        }
+    }
+
+    @GuardedBy("mLock")
+    public void replacePinned(@NonNull ShortcutService s, String launcherPackage,
+            List<String> shortcutIds) {
+
+        // TODO Should be per launcherPackage.
+
+        // First, un-pin all shortcuts
+        for (int i = mShortcuts.size() - 1; i >= 0; i--) {
+            mShortcuts.valueAt(i).clearFlags(ShortcutInfo.FLAG_PINNED);
+        }
+
+        // Then pin ALL
+        for (int i = shortcutIds.size() - 1; i >= 0; i--) {
+            final ShortcutInfo shortcut = mShortcuts.get(shortcutIds.get(i));
+            if (shortcut != null) {
+                shortcut.addFlags(ShortcutInfo.FLAG_PINNED);
+            }
+        }
+
+        removeOrphans(s);
+    }
+
+    /**
+     * Number of calls that the caller has made, since the last reset.
+     */
+    @GuardedBy("mLock")
+    public int getApiCallCount(@NonNull ShortcutService s) {
+        final long last = s.getLastResetTimeLocked();
+
+        final long now = s.injectCurrentTimeMillis();
+        if (mLastResetTime > now) {
+            // Clock rewound. // TODO Test it
+            mLastResetTime = now;
+        }
+
+        // If not reset yet, then reset.
+        if (mLastResetTime < last) {
+            mApiCallCount = 0;
+            mLastResetTime = last;
+        }
+        return mApiCallCount;
+    }
+
+    /**
+     * If the caller app hasn't been throttled yet, increment {@link #mApiCallCount}
+     * and return true.  Otherwise just return false.
+     */
+    @GuardedBy("mLock")
+    public boolean tryApiCall(@NonNull ShortcutService s) {
+        if (getApiCallCount(s) >= s.mMaxDailyUpdates) {
+            return false;
+        }
+        mApiCallCount++;
+        return true;
+    }
+
+    @GuardedBy("mLock")
+    public void resetRateLimitingForCommandLine() {
+        mApiCallCount = 0;
+        mLastResetTime = 0;
+    }
+
+    /**
+     * Find all shortcuts that match {@code query}.
+     */
+    @GuardedBy("mLock")
+    public void findAll(@NonNull List<ShortcutInfo> result,
+            @Nullable Predicate<ShortcutInfo> query, int cloneFlag) {
+        for (int i = 0; i < mShortcuts.size(); i++) {
+            final ShortcutInfo si = mShortcuts.valueAt(i);
+            if (query == null || query.test(si)) {
+                result.add(si.clone(cloneFlag));
+            }
+        }
+    }
+
+    public void dump(@NonNull ShortcutService s, @NonNull PrintWriter pw, @NonNull String prefix) {
+        pw.print(prefix);
+        pw.print("Package: ");
+        pw.print(mPackageName);
+        pw.println();
+
+        pw.print(prefix);
+        pw.print("  ");
+        pw.print("Calls: ");
+        pw.print(getApiCallCount(s));
+        pw.println();
+
+        // This should be after getApiCallCount(), which may update it.
+        pw.print(prefix);
+        pw.print("  ");
+        pw.print("Last reset: [");
+        pw.print(mLastResetTime);
+        pw.print("] ");
+        pw.print(s.formatTime(mLastResetTime));
+        pw.println();
+
+        pw.println("      Shortcuts:");
+        long totalBitmapSize = 0;
+        final ArrayMap<String, ShortcutInfo> shortcuts = mShortcuts;
+        final int size = shortcuts.size();
+        for (int i = 0; i < size; i++) {
+            final ShortcutInfo si = shortcuts.valueAt(i);
+            pw.print("        ");
+            pw.println(si.toInsecureString());
+            if (si.getBitmapPath() != null) {
+                final long len = new File(si.getBitmapPath()).length();
+                pw.print("          ");
+                pw.print("bitmap size=");
+                pw.println(len);
+
+                totalBitmapSize += len;
+            }
+        }
+        pw.print(prefix);
+        pw.print("  ");
+        pw.print("Total bitmap size: ");
+        pw.print(totalBitmapSize);
+        pw.print(" (");
+        pw.print(Formatter.formatFileSize(s.mContext, totalBitmapSize));
+        pw.println(")");
+    }
+
+    public void saveToXml(@NonNull XmlSerializer out) throws IOException, XmlPullParserException {
+        out.startTag(null, ShortcutService.TAG_PACKAGE);
+
+        ShortcutService.writeAttr(out, ShortcutService.ATTR_NAME, mPackageName);
+        ShortcutService.writeAttr(out, ShortcutService.ATTR_DYNAMIC_COUNT, mDynamicShortcutCount);
+        ShortcutService.writeAttr(out, ShortcutService.ATTR_CALL_COUNT, mApiCallCount);
+        ShortcutService.writeAttr(out, ShortcutService.ATTR_LAST_RESET, mLastResetTime);
+
+        final int size = mShortcuts.size();
+        for (int j = 0; j < size; j++) {
+            saveShortcut(out, mShortcuts.valueAt(j));
+        }
+
+        out.endTag(null, ShortcutService.TAG_PACKAGE);
+    }
+
+    private static void saveShortcut(XmlSerializer out, ShortcutInfo si)
+            throws IOException, XmlPullParserException {
+        out.startTag(null, ShortcutService.TAG_SHORTCUT);
+        ShortcutService.writeAttr(out, ShortcutService.ATTR_ID, si.getId());
+        // writeAttr(out, "package", si.getPackageName()); // not needed
+        ShortcutService.writeAttr(out, ShortcutService.ATTR_ACTIVITY, si.getActivityComponent());
+        // writeAttr(out, "icon", si.getIcon());  // We don't save it.
+        ShortcutService.writeAttr(out, ShortcutService.ATTR_TITLE, si.getTitle());
+        ShortcutService.writeAttr(out, ShortcutService.ATTR_INTENT, si.getIntentNoExtras());
+        ShortcutService.writeAttr(out, ShortcutService.ATTR_WEIGHT, si.getWeight());
+        ShortcutService.writeAttr(out, ShortcutService.ATTR_TIMESTAMP,
+                si.getLastChangedTimestamp());
+        ShortcutService.writeAttr(out, ShortcutService.ATTR_FLAGS, si.getFlags());
+        ShortcutService.writeAttr(out, ShortcutService.ATTR_ICON_RES, si.getIconResourceId());
+        ShortcutService.writeAttr(out, ShortcutService.ATTR_BITMAP_PATH, si.getBitmapPath());
+
+        ShortcutService.writeTagExtra(out, ShortcutService.TAG_INTENT_EXTRAS,
+                si.getIntentPersistableExtras());
+        ShortcutService.writeTagExtra(out, ShortcutService.TAG_EXTRAS, si.getExtras());
+
+        out.endTag(null, ShortcutService.TAG_SHORTCUT);
+    }
+
+    public static PackageShortcuts loadFromXml(XmlPullParser parser, int userId)
+            throws IOException, XmlPullParserException {
+
+        final String packageName = ShortcutService.parseStringAttribute(parser,
+                ShortcutService.ATTR_NAME);
+
+        final PackageShortcuts ret = new PackageShortcuts(userId, packageName);
+
+        ret.mDynamicShortcutCount =
+                ShortcutService.parseIntAttribute(parser, ShortcutService.ATTR_DYNAMIC_COUNT);
+        ret.mApiCallCount =
+                ShortcutService.parseIntAttribute(parser, ShortcutService.ATTR_CALL_COUNT);
+        ret.mLastResetTime =
+                ShortcutService.parseLongAttribute(parser, ShortcutService.ATTR_LAST_RESET);
+
+        final int outerDepth = parser.getDepth();
+        int type;
+        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
+                && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
+            if (type != XmlPullParser.START_TAG) {
+                continue;
+            }
+            final int depth = parser.getDepth();
+            final String tag = parser.getName();
+            switch (tag) {
+                case ShortcutService.TAG_SHORTCUT:
+                    final ShortcutInfo si = parseShortcut(parser, packageName);
+
+                    // Don't use addShortcut(), we don't need to save the icon.
+                    ret.mShortcuts.put(si.getId(), si);
+                    continue;
+            }
+            throw ShortcutService.throwForInvalidTag(depth, tag);
+        }
+        return ret;
+    }
+
+    private static ShortcutInfo parseShortcut(XmlPullParser parser, String packageName)
+            throws IOException, XmlPullParserException {
+        String id;
+        ComponentName activityComponent;
+        // Icon icon;
+        String title;
+        Intent intent;
+        PersistableBundle intentPersistableExtras = null;
+        int weight;
+        PersistableBundle extras = null;
+        long lastChangedTimestamp;
+        int flags;
+        int iconRes;
+        String bitmapPath;
+
+        id = ShortcutService.parseStringAttribute(parser, ShortcutService.ATTR_ID);
+        activityComponent = ShortcutService.parseComponentNameAttribute(parser,
+                ShortcutService.ATTR_ACTIVITY);
+        title = ShortcutService.parseStringAttribute(parser, ShortcutService.ATTR_TITLE);
+        intent = ShortcutService.parseIntentAttribute(parser, ShortcutService.ATTR_INTENT);
+        weight = (int) ShortcutService.parseLongAttribute(parser, ShortcutService.ATTR_WEIGHT);
+        lastChangedTimestamp = (int) ShortcutService.parseLongAttribute(parser,
+                ShortcutService.ATTR_TIMESTAMP);
+        flags = (int) ShortcutService.parseLongAttribute(parser, ShortcutService.ATTR_FLAGS);
+        iconRes = (int) ShortcutService.parseLongAttribute(parser, ShortcutService.ATTR_ICON_RES);
+        bitmapPath = ShortcutService.parseStringAttribute(parser, ShortcutService.ATTR_BITMAP_PATH);
+
+        final int outerDepth = parser.getDepth();
+        int type;
+        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
+                && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
+            if (type != XmlPullParser.START_TAG) {
+                continue;
+            }
+            final int depth = parser.getDepth();
+            final String tag = parser.getName();
+            if (ShortcutService.DEBUG_LOAD) {
+                Slog.d(TAG, String.format("  depth=%d type=%d name=%s",
+                        depth, type, tag));
+            }
+            switch (tag) {
+                case ShortcutService.TAG_INTENT_EXTRAS:
+                    intentPersistableExtras = PersistableBundle.restoreFromXml(parser);
+                    continue;
+                case ShortcutService.TAG_EXTRAS:
+                    extras = PersistableBundle.restoreFromXml(parser);
+                    continue;
+            }
+            throw ShortcutService.throwForInvalidTag(depth, tag);
+        }
+        return new ShortcutInfo(
+                id, packageName, activityComponent, /* icon =*/ null, title, intent,
+                intentPersistableExtras, weight, extras, lastChangedTimestamp, flags,
+                iconRes, bitmapPath);
+    }
+}
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index 5490260..8206bda 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -50,6 +50,7 @@
 import android.os.Process;
 import android.os.RemoteException;
 import android.os.ResultReceiver;
+import android.os.SELinux;
 import android.os.ServiceManager;
 import android.os.ShellCommand;
 import android.os.UserHandle;
@@ -758,23 +759,28 @@
     }
 
     @Override
-    public ParcelFileDescriptor getUserIcon(int userId) {
+    public ParcelFileDescriptor getUserIcon(int targetUserId) {
         String iconPath;
         synchronized (mPackagesLock) {
-            UserInfo info = getUserInfoNoChecks(userId);
-            if (info == null || info.partial) {
-                Slog.w(LOG_TAG, "getUserIcon: unknown user #" + userId);
+            UserInfo targetUserInfo = getUserInfoNoChecks(targetUserId);
+            if (targetUserInfo == null || targetUserInfo.partial) {
+                Slog.w(LOG_TAG, "getUserIcon: unknown user #" + targetUserId);
                 return null;
             }
-            int callingGroupId = getUserInfoNoChecks(UserHandle.getCallingUserId()).profileGroupId;
-            if (callingGroupId == UserInfo.NO_PROFILE_GROUP_ID
-                    || callingGroupId != info.profileGroupId) {
+
+            final int callingUserId = UserHandle.getCallingUserId();
+            final int callingGroupId = getUserInfoNoChecks(callingUserId).profileGroupId;
+            final int targetGroupId = targetUserInfo.profileGroupId;
+            final boolean sameGroup = (callingGroupId != UserInfo.NO_PROFILE_GROUP_ID
+                    && callingGroupId == targetGroupId);
+            if ((callingUserId != targetUserId) && !sameGroup) {
                 checkManageUsersPermission("get the icon of a user who is not related");
             }
-            if (info.iconPath == null) {
+
+            if (targetUserInfo.iconPath == null) {
                 return null;
             }
-            iconPath = info.iconPath;
+            iconPath = targetUserInfo.iconPath;
         }
 
         try {
@@ -1229,7 +1235,7 @@
             }
             FileOutputStream os;
             if (bitmap.compress(Bitmap.CompressFormat.PNG, 100, os = new FileOutputStream(tmp))
-                    && tmp.renameTo(file)) {
+                    && tmp.renameTo(file) && SELinux.restorecon(file)) {
                 info.iconPath = file.getAbsolutePath();
             }
             try {
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index e1a0299..76a93d4 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -28,6 +28,8 @@
 import static android.view.WindowManager.DOCKED_TOP;
 import static android.view.WindowManager.DOCKED_LEFT;
 import static android.view.WindowManager.DOCKED_RIGHT;
+import static android.view.WindowManager.TAKE_SCREENSHOT_FULLSCREEN;
+import static android.view.WindowManager.TAKE_SCREENSHOT_SELECTED_REGION;
 import static android.view.WindowManager.LayoutParams.*;
 import static android.view.WindowManagerPolicy.WindowManagerFuncs.CAMERA_LENS_COVERED;
 import static android.view.WindowManagerPolicy.WindowManagerFuncs.CAMERA_LENS_COVER_ABSENT;
@@ -57,6 +59,7 @@
 import android.content.IntentFilter;
 import android.content.ServiceConnection;
 import android.content.pm.ActivityInfo;
+import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
 import android.content.res.CompatibilityInfo;
@@ -76,6 +79,7 @@
 import android.media.RingtoneManager;
 import android.media.session.MediaSessionLegacyHelper;
 import android.os.Binder;
+import android.os.Build;
 import android.os.Bundle;
 import android.os.Debug;
 import android.os.FactoryTest;
@@ -107,6 +111,7 @@
 import android.util.Log;
 import android.util.Slog;
 import android.util.SparseArray;
+import android.util.LongSparseArray;
 import android.view.Display;
 import android.view.Gravity;
 import android.view.HapticFeedbackConstants;
@@ -135,6 +140,7 @@
 import com.android.internal.R;
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.policy.PhoneWindow;
+import com.android.internal.policy.IShortcutService;
 import com.android.internal.statusbar.IStatusBarService;
 import com.android.internal.util.ScreenShapeHelper;
 import com.android.internal.widget.PointerLocationView;
@@ -205,6 +211,13 @@
     static final int SHORT_PRESS_SLEEP_GO_TO_SLEEP = 0;
     static final int SHORT_PRESS_SLEEP_GO_TO_SLEEP_AND_GO_HOME = 1;
 
+    // Controls navigation bar opacity depending on which workspace stacks are currently
+    // visible.
+    // Nav bar is always opaque when either the freeform stack or docked stack is visible.
+    static final int NAV_BAR_OPAQUE_WHEN_FREEFORM_OR_DOCKED = 0;
+    // Nav bar is always translucent when the freeform stack is visible, otherwise always opaque.
+    static final int NAV_BAR_TRANSLUCENT_WHEN_FREEFORM_OPAQUE_OTHERWISE = 1;
+
     static final int APPLICATION_MEDIA_SUBLAYER = -2;
     static final int APPLICATION_MEDIA_OVERLAY_SUBLAYER = -1;
     static final int APPLICATION_PANEL_SUBLAYER = 1;
@@ -238,6 +251,12 @@
     // app shows again. If that doesn't happen for 30s we drop the gesture.
     private static final long PANIC_GESTURE_EXPIRATION = 30000;
 
+    private static final String SYSUI_PACKAGE = "com.android.systemui";
+    private static final String SYSUI_SCREENSHOT_SERVICE =
+            "com.android.systemui.screenshot.TakeScreenshotService";
+    private static final String SYSUI_SCREENSHOT_ERROR_RECEIVER =
+            "com.android.systemui.screenshot.ScreenshotServiceErrorReceiver";
+
     /**
      * Keyguard stuff
      */
@@ -336,6 +355,8 @@
     int[] mNavigationBarHeightForRotationInCarMode = new int[4];
     int[] mNavigationBarWidthForRotationInCarMode = new int[4];
 
+    private LongSparseArray<IShortcutService> mShortcutKeyServices = new LongSparseArray<>();
+
     // Whether to allow dock apps with METADATA_DOCK_HOME to temporarily take over the Home key.
     // This is for car dock and this is updated from resource.
     private boolean mEnableCarDockHomeCapture = true;
@@ -531,6 +552,7 @@
     boolean mForceStatusBar;
     boolean mForceStatusBarFromKeyguard;
     private boolean mForceStatusBarTransparent;
+    int mNavBarOpacityMode = NAV_BAR_OPAQUE_WHEN_FREEFORM_OR_DOCKED;
     boolean mHideLockScreen;
     boolean mForcingShowNavBar;
     int mForcingShowNavBarLayer;
@@ -1232,7 +1254,7 @@
                             + SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS) {
                 mScreenshotChordVolumeDownKeyConsumed = true;
                 cancelPendingPowerKeyAction();
-
+                mScreenshotRunnable.setScreenshotType(TAKE_SCREENSHOT_FULLSCREEN);
                 mHandler.postDelayed(mScreenshotRunnable, getScreenshotChordLongPressDelay());
             }
         }
@@ -1262,12 +1284,20 @@
         }
     };
 
-    private final Runnable mScreenshotRunnable = new Runnable() {
+    private class ScreenshotRunnable implements Runnable {
+        private int mScreenshotType = TAKE_SCREENSHOT_FULLSCREEN;
+
+        public void setScreenshotType(int screenshotType) {
+            mScreenshotType = screenshotType;
+        }
+
         @Override
         public void run() {
-            takeScreenshot();
+            takeScreenshot(mScreenshotType);
         }
-    };
+    }
+
+    private final ScreenshotRunnable mScreenshotRunnable = new ScreenshotRunnable();
 
     @Override
     public void showGlobalActions() {
@@ -1711,6 +1741,9 @@
         if (mContext.getPackageManager().hasSystemFeature(FEATURE_PICTURE_IN_PICTURE)) {
             mShortPressWindowBehavior = SHORT_PRESS_WINDOW_PICTURE_IN_PICTURE;
         }
+
+        mNavBarOpacityMode = res.getInteger(
+                com.android.internal.R.integer.config_navBarOpacityMode);
     }
 
     @Override
@@ -2049,7 +2082,7 @@
 
                 // check if user has enabled this operation. SecurityException will be thrown if
                 // this app has not been allowed by the user
-                final int mode = mAppOpsManager.checkOp(outAppOp[0], callingUid,
+                final int mode = mAppOpsManager.checkOpNoThrow(outAppOp[0], callingUid,
                         attrs.packageName);
                 switch (mode) {
                     case AppOpsManager.MODE_ALLOWED:
@@ -2058,6 +2091,17 @@
                         // actually be hidden in WindowManagerService
                         return WindowManagerGlobal.ADD_OKAY;
                     case AppOpsManager.MODE_ERRORED:
+                        try {
+                            ApplicationInfo appInfo = mContext.getPackageManager()
+                                    .getApplicationInfo(attrs.packageName,
+                                            UserHandle.getUserId(callingUid));
+                            // Don't crash legacy apps
+                            if (appInfo.targetSdkVersion < Build.VERSION_CODES.M) {
+                                return WindowManagerGlobal.ADD_OKAY;
+                            }
+                        } catch (PackageManager.NameNotFoundException e) {
+                            /* ignore */
+                        }
                         return WindowManagerGlobal.ADD_PERMISSION_DENIED;
                     default:
                         // in the default mode, we will make a decision here based on
@@ -2283,29 +2327,33 @@
         case TYPE_NAVIGATION_BAR_PANEL:
             // some panels (e.g. search) need to show on top of the navigation bar
             return 22;
+        case TYPE_SCREENSHOT:
+            // screenshot selection layer shouldn't go above system error, but it should cover
+            // navigation bars at the very least.
+            return 23;
         case TYPE_SYSTEM_ERROR:
             // system-level error dialogs
-            return 23;
+            return 24;
         case TYPE_MAGNIFICATION_OVERLAY:
             // used to highlight the magnified portion of a display
-            return 24;
+            return 25;
         case TYPE_DISPLAY_OVERLAY:
             // used to simulate secondary display devices
-            return 25;
+            return 26;
         case TYPE_DRAG:
             // the drag layer: input for drag-and-drop is associated with this window,
             // which sits above all other focusable windows
-            return 26;
+            return 27;
         case TYPE_ACCESSIBILITY_OVERLAY:
             // overlay put by accessibility services to intercept user interaction
-            return 27;
-        case TYPE_SECURE_SYSTEM_OVERLAY:
             return 28;
-        case TYPE_BOOT_PROGRESS:
+        case TYPE_SECURE_SYSTEM_OVERLAY:
             return 29;
+        case TYPE_BOOT_PROGRESS:
+            return 30;
         case TYPE_POINTER:
             // the (mouse) pointer layer
-            return 30;
+            return 31;
         }
         Log.e(TAG, "Unknown window type: " + type);
         return 2;
@@ -3005,6 +3053,15 @@
                     }
                 }
             }
+        } else if (keyCode == KeyEvent.KEYCODE_S && event.isMetaPressed()
+                && event.isCtrlPressed()) {
+            if (down && repeatCount == 0) {
+                int type = event.isShiftPressed() ? TAKE_SCREENSHOT_SELECTED_REGION
+                        : TAKE_SCREENSHOT_FULLSCREEN;
+                mScreenshotRunnable.setScreenshotType(type);
+                mHandler.post(mScreenshotRunnable);
+                return -1;
+            }
         } else if (keyCode == KeyEvent.KEYCODE_SLASH && event.isMetaPressed()) {
             if (down) {
                 if (repeatCount == 0) {
@@ -3052,6 +3109,7 @@
             }
         } else if (keyCode == KeyEvent.KEYCODE_SYSRQ) {
             if (down && repeatCount == 0) {
+                mScreenshotRunnable.setScreenshotType(TAKE_SCREENSHOT_FULLSCREEN);
                 mHandler.post(mScreenshotRunnable);
             }
             return -1;
@@ -3100,7 +3158,9 @@
                 dispatchDirectAudioEvent(event);
                 return -1;
             }
-        } else if (KeyEvent.isMetaKey(keyCode)) {
+        }
+
+        if (KeyEvent.isMetaKey(keyCode)) {
             if (down) {
                 mPendingMetaAction = true;
             } else if (mPendingMetaAction) {
@@ -3215,6 +3275,35 @@
             return -1;
         }
 
+        if (down) {
+            long shortcutCode = (long) keyCode;
+            if (event.isCtrlPressed()) {
+                shortcutCode |= ((long) KeyEvent.META_CTRL_ON) << Integer.SIZE;
+            }
+
+            if (event.isAltPressed()) {
+                shortcutCode |= ((long) KeyEvent.META_ALT_ON) << Integer.SIZE;
+            }
+
+            if (event.isShiftPressed()) {
+                shortcutCode |= ((long) KeyEvent.META_SHIFT_ON) << Integer.SIZE;
+            }
+
+            if (event.isMetaPressed()) {
+                shortcutCode |= ((long) KeyEvent.META_META_ON) << Integer.SIZE;
+            }
+
+            IShortcutService shortcutService = mShortcutKeyServices.get(shortcutCode);
+            if (shortcutService != null) {
+                try {
+                    shortcutService.notifyShortcutKeyPressed(shortcutCode);
+                } catch (RemoteException e) {
+                    mShortcutKeyServices.delete(shortcutCode);
+                }
+                return -1;
+            }
+        }
+
         // Reserve all the META modifier combos for system behavior
         if ((metaState & KeyEvent.META_META_ON) != 0) {
             return -1;
@@ -3304,6 +3393,18 @@
         return false;
     }
 
+    public void registerShortcutKey(long shortcutCode, IShortcutService shortcutService)
+            throws RemoteException {
+        synchronized (mLock) {
+            IShortcutService service = mShortcutKeyServices.get(shortcutCode);
+            if (service != null && service.asBinder().pingBinder()) {
+                throw new RemoteException("Key already exists.");
+            }
+
+            mShortcutKeyServices.put(shortcutCode, shortcutService);
+        }
+    }
+
     private void launchAssistLongPressAction() {
         performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false);
         sendCloseSystemWindows(SYSTEM_DIALOG_REASON_ASSIST);
@@ -4338,9 +4439,11 @@
                                     "Laying out navigation bar window: (%d,%d - %d,%d)",
                                     pf.left, pf.top, pf.right, pf.bottom));
                 } else if ((attrs.type == TYPE_SECURE_SYSTEM_OVERLAY
-                                || attrs.type == TYPE_BOOT_PROGRESS)
+                                || attrs.type == TYPE_BOOT_PROGRESS
+                                || attrs.type == TYPE_SCREENSHOT)
                         && ((fl & FLAG_FULLSCREEN) != 0)) {
-                    // Fullscreen secure system overlays get what they ask for.
+                    // Fullscreen secure system overlays get what they ask for. Screenshot region
+                    // selection overlay should also expand to full screen.
                     pf.left = df.left = of.left = cf.left = mOverscanScreenLeft;
                     pf.top = df.top = of.top = cf.top = mOverscanScreenTop;
                     pf.right = df.right = of.right = cf.right = mOverscanScreenLeft
@@ -5089,21 +5192,22 @@
                 if (mScreenshotConnection != null) {
                     mContext.unbindService(mScreenshotConnection);
                     mScreenshotConnection = null;
+                    notifyScreenshotError();
                 }
             }
         }
     };
 
     // Assume this is called from the Handler thread.
-    private void takeScreenshot() {
+    private void takeScreenshot(final int screenshotType) {
         synchronized (mScreenshotLock) {
             if (mScreenshotConnection != null) {
                 return;
             }
-            ComponentName cn = new ComponentName("com.android.systemui",
-                    "com.android.systemui.screenshot.TakeScreenshotService");
-            Intent intent = new Intent();
-            intent.setComponent(cn);
+            final ComponentName serviceComponent = new ComponentName(SYSUI_PACKAGE,
+                    SYSUI_SCREENSHOT_SERVICE);
+            final Intent serviceIntent = new Intent();
+            serviceIntent.setComponent(serviceComponent);
             ServiceConnection conn = new ServiceConnection() {
                 @Override
                 public void onServiceConnected(ComponentName name, IBinder service) {
@@ -5112,7 +5216,7 @@
                             return;
                         }
                         Messenger messenger = new Messenger(service);
-                        Message msg = Message.obtain(null, 1);
+                        Message msg = Message.obtain(null, screenshotType);
                         final ServiceConnection myConn = this;
                         Handler h = new Handler(mHandler.getLooper()) {
                             @Override
@@ -5138,17 +5242,35 @@
                         }
                     }
                 }
+
                 @Override
-                public void onServiceDisconnected(ComponentName name) {}
+                public void onServiceDisconnected(ComponentName name) {
+                    notifyScreenshotError();
+                }
             };
-            if (mContext.bindServiceAsUser(
-                    intent, conn, Context.BIND_AUTO_CREATE, UserHandle.CURRENT)) {
+            if (mContext.bindServiceAsUser(serviceIntent, conn,
+                    Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE_WHILE_AWAKE,
+                    UserHandle.CURRENT)) {
                 mScreenshotConnection = conn;
                 mHandler.postDelayed(mScreenshotTimeout, 10000);
             }
         }
     }
 
+    /**
+     * Notifies the screenshot service to show an error.
+     */
+    private void notifyScreenshotError() {
+        // If the service process is killed, then ask it to clean up after itself
+        final ComponentName errorComponent = new ComponentName(SYSUI_PACKAGE,
+                SYSUI_SCREENSHOT_ERROR_RECEIVER);
+        Intent errorIntent = new Intent();
+        errorIntent.setComponent(errorComponent);
+        errorIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT |
+                Intent.FLAG_RECEIVER_FOREGROUND);
+        mContext.sendBroadcastAsUser(errorIntent, UserHandle.ALL);
+    }
+
     /** {@inheritDoc} */
     @Override
     public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags) {
@@ -7003,7 +7125,7 @@
         // is visible but also when we are resizing for the transitions when docked stack
         // visibility changes.
         mForceShowSystemBars = dockedStackVisible || freeformStackVisible || resizing;
-        final boolean forceOpaqueSystemBars = mForceShowSystemBars && !mForceStatusBarFromKeyguard;
+        final boolean forceOpaqueStatusBar = mForceShowSystemBars && !mForceStatusBarFromKeyguard;
 
         // apply translucent bar vis flags
         WindowState transWin = isStatusBarKeyguard() && !mHideLockScreen
@@ -7028,11 +7150,12 @@
         }
 
         if ((!areTranslucentBarsAllowed() && transWin != mStatusBar)
-                || forceOpaqueSystemBars) {
-            vis &= ~(View.NAVIGATION_BAR_TRANSLUCENT | View.STATUS_BAR_TRANSLUCENT
-                    | View.SYSTEM_UI_TRANSPARENT);
+                || forceOpaqueStatusBar) {
+            vis &= ~(View.STATUS_BAR_TRANSLUCENT | View.STATUS_BAR_TRANSPARENT);
         }
 
+        vis = configureNavBarOpacity(vis, dockedStackVisible, freeformStackVisible, resizing);
+
         if (mForceWindowDrawsStatusBarBackground) {
             vis |= View.STATUS_BAR_TRANSPARENT;
             vis &= ~View.STATUS_BAR_TRANSLUCENT;
@@ -7105,6 +7228,41 @@
         return vis;
     }
 
+    /**
+     * @return the current visibility flags with the nav-bar opacity related flags toggled based
+     *         on the nav bar opacity rules chosen by {@link #mNavBarOpacityMode}.
+     */
+    private int configureNavBarOpacity(int visibility, boolean dockedStackVisible,
+            boolean freeformStackVisible, boolean isDockedDividerResizing) {
+        if (mNavBarOpacityMode == NAV_BAR_OPAQUE_WHEN_FREEFORM_OR_DOCKED) {
+            if (dockedStackVisible || freeformStackVisible || isDockedDividerResizing) {
+                visibility = setNavBarOpaqueFlag(visibility);
+            }
+        } else if (mNavBarOpacityMode == NAV_BAR_TRANSLUCENT_WHEN_FREEFORM_OPAQUE_OTHERWISE) {
+            if (isDockedDividerResizing) {
+                visibility = setNavBarOpaqueFlag(visibility);
+            } else if (freeformStackVisible) {
+                visibility = setNavBarTranslucentFlag(visibility);
+            } else {
+                visibility = setNavBarOpaqueFlag(visibility);
+            }
+        }
+
+        if (!areTranslucentBarsAllowed()) {
+            visibility &= ~View.NAVIGATION_BAR_TRANSLUCENT;
+        }
+        return visibility;
+    }
+
+    private int setNavBarOpaqueFlag(int visibility) {
+        return visibility &= ~(View.NAVIGATION_BAR_TRANSLUCENT | View.NAVIGATION_BAR_TRANSPARENT);
+    }
+
+    private int setNavBarTranslucentFlag(int visibility) {
+        visibility &= ~View.NAVIGATION_BAR_TRANSPARENT;
+        return visibility |= View.NAVIGATION_BAR_TRANSLUCENT;
+    }
+
     private void clearClearableFlagsLw() {
         int newVal = mResettingSystemUiFlags | View.SYSTEM_UI_CLEARABLE_FLAGS;
         if (newVal != mResettingSystemUiFlags) {
diff --git a/services/core/java/com/android/server/policy/ShortcutManager.java b/services/core/java/com/android/server/policy/ShortcutManager.java
index 9284442..57ae523 100644
--- a/services/core/java/com/android/server/policy/ShortcutManager.java
+++ b/services/core/java/com/android/server/policy/ShortcutManager.java
@@ -138,14 +138,16 @@
                     ComponentName componentName = new ComponentName(packageName, className);
                     try {
                         info = packageManager.getActivityInfo(componentName,
-                                PackageManager.MATCH_ENCRYPTION_AWARE_AND_UNAWARE);
+                                PackageManager.MATCH_ENCRYPTION_AWARE_AND_UNAWARE
+                                | PackageManager.MATCH_UNINSTALLED_PACKAGES);
                     } catch (PackageManager.NameNotFoundException e) {
                         String[] packages = packageManager.canonicalToCurrentPackageNames(
                                 new String[] { packageName });
                         componentName = new ComponentName(packages[0], className);
                         try {
                             info = packageManager.getActivityInfo(componentName,
-                                    PackageManager.MATCH_ENCRYPTION_AWARE_AND_UNAWARE);
+                                    PackageManager.MATCH_ENCRYPTION_AWARE_AND_UNAWARE
+                                    | PackageManager.MATCH_UNINSTALLED_PACKAGES);
                         } catch (PackageManager.NameNotFoundException e1) {
                             Log.w(TAG, "Unable to add bookmark: " + packageName
                                     + "/" + className, e);
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index f901f95..91d8671 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -50,6 +50,7 @@
 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.util.EventLog;
 import android.util.Slog;
@@ -57,9 +58,11 @@
 import android.util.TimeUtils;
 import android.view.Display;
 import android.view.WindowManagerPolicy;
+
 import com.android.internal.app.IAppOpsService;
 import com.android.internal.app.IBatteryStats;
 import com.android.internal.os.BackgroundThread;
+import com.android.internal.util.ArrayUtils;
 import com.android.server.EventLogTags;
 import com.android.server.ServiceThread;
 import com.android.server.SystemService;
@@ -254,6 +257,9 @@
     // True if boot completed occurred.  We keep the screen on until this happens.
     private boolean mBootCompleted;
 
+    // Runnables that should be triggered on boot completed
+    private Runnable[] mBootCompletedRunnables;
+
     // True if auto-suspend mode is enabled.
     // Refer to autosuspend.h.
     private boolean mHalAutoSuspendModeEnabled;
@@ -525,6 +531,16 @@
                 userActivityNoUpdateLocked(
                         now, PowerManager.USER_ACTIVITY_EVENT_OTHER, 0, Process.SYSTEM_UID);
                 updatePowerStateLocked();
+
+                if (!ArrayUtils.isEmpty(mBootCompletedRunnables)) {
+                    Slog.d(TAG, "Posting " + mBootCompletedRunnables.length + " delayed runnables");
+                    for (Runnable r : mBootCompletedRunnables) {
+                        BackgroundThread.getHandler().post(r);
+                    }
+                }
+                mBootCompletedRunnables = null;
+
+                incrementBootCount();
             }
         }
     }
@@ -750,7 +766,17 @@
         mDirty |= DIRTY_SETTINGS;
     }
 
-    void updateLowPowerModeLocked() {
+    private void postAfterBootCompleted(Runnable r) {
+        if (mBootCompleted) {
+            BackgroundThread.getHandler().post(r);
+        } else {
+            Slog.d(TAG, "Delaying runnable until system is booted");
+            mBootCompletedRunnables = ArrayUtils.appendElement(Runnable.class,
+                    mBootCompletedRunnables, r);
+        }
+    }
+
+    private void updateLowPowerModeLocked() {
         if (mIsPowered && mLowPowerModeSetting) {
             if (DEBUG_SPEW) {
                 Slog.d(TAG, "updateLowPowerModeLocked: powered, turning setting off");
@@ -767,7 +793,7 @@
         if (mLowPowerModeEnabled != lowPowerModeEnabled) {
             mLowPowerModeEnabled = lowPowerModeEnabled;
             powerHintInternal(POWER_HINT_LOW_POWER, lowPowerModeEnabled ? 1 : 0);
-            BackgroundThread.getHandler().post(new Runnable() {
+            postAfterBootCompleted(new Runnable() {
                 @Override
                 public void run() {
                     Intent intent = new Intent(PowerManager.ACTION_POWER_SAVE_MODE_CHANGING)
@@ -2890,6 +2916,20 @@
         return suspendBlocker;
     }
 
+    private void incrementBootCount() {
+        synchronized (mLock) {
+            int count;
+            try {
+                count = Settings.Global.getInt(
+                        getContext().getContentResolver(), Settings.Global.BOOT_COUNT);
+            } catch (SettingNotFoundException e) {
+                count = 0;
+            }
+            Settings.Global.putInt(
+                    getContext().getContentResolver(), Settings.Global.BOOT_COUNT, count + 1);
+        }
+    }
+
     private static WorkSource copyWorkSource(WorkSource workSource) {
         return workSource != null ? new WorkSource(workSource) : null;
     }
diff --git a/services/core/java/com/android/server/search/Searchables.java b/services/core/java/com/android/server/search/Searchables.java
index 0046fbb..6bacdfd 100644
--- a/services/core/java/com/android/server/search/Searchables.java
+++ b/services/core/java/com/android/server/search/Searchables.java
@@ -410,7 +410,7 @@
             activities =
                     mPm.queryIntentActivities(intent,
                     intent.resolveTypeIfNeeded(mContext.getContentResolver()),
-                    flags, mUserId);
+                    flags, mUserId).getList();
         } catch (RemoteException re) {
             // Local call
         }
diff --git a/services/core/java/com/android/server/trust/TrustAgentWrapper.java b/services/core/java/com/android/server/trust/TrustAgentWrapper.java
index e5c5b2bc..858f7c7 100644
--- a/services/core/java/com/android/server/trust/TrustAgentWrapper.java
+++ b/services/core/java/com/android/server/trust/TrustAgentWrapper.java
@@ -81,6 +81,7 @@
     private boolean mBound;
     private long mScheduledRestartUptimeMillis;
     private long mMaximumTimeToLock; // from DevicePolicyManager
+    private boolean mPendingSuccessfulUnlock = false;
 
     // Trust state
     private boolean mTrusted;
@@ -234,6 +235,11 @@
             setCallback(mCallback);
             updateDevicePolicyFeatures();
 
+            if (mPendingSuccessfulUnlock) {
+                onUnlockAttempt(true);
+                mPendingSuccessfulUnlock = false;
+            }
+
             if (mTrustManagerService.isDeviceLockedInner(mUserId)) {
                 onDeviceLocked();
             } else {
@@ -302,7 +308,11 @@
      */
     public void onUnlockAttempt(boolean successful) {
         try {
-            if (mTrustAgentService != null) mTrustAgentService.onUnlockAttempt(successful);
+            if (mTrustAgentService != null) {
+                mTrustAgentService.onUnlockAttempt(successful);
+            } else {
+                mPendingSuccessfulUnlock = successful;
+            }
         } catch (RemoteException e) {
             onError(e);
         }
diff --git a/services/core/java/com/android/server/trust/TrustManagerService.java b/services/core/java/com/android/server/trust/TrustManagerService.java
index b54e866..984fb76 100644
--- a/services/core/java/com/android/server/trust/TrustManagerService.java
+++ b/services/core/java/com/android/server/trust/TrustManagerService.java
@@ -19,7 +19,6 @@
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.content.PackageMonitor;
 import com.android.internal.widget.LockPatternUtils;
-import com.android.internal.widget.LockPatternUtils.StrongAuthTracker;
 import com.android.server.SystemService;
 
 import org.xmlpull.v1.XmlPullParser;
@@ -104,7 +103,7 @@
     private static final int MSG_SET_DEVICE_LOCKED = 10;
     private static final int MSG_FLUSH_TRUST_USUALLY_MANAGED = 11;
 
-    public static final int TRUST_USUALLY_MANAGED_FLUSH_DELAY = 2 * 60 * 1000;
+    private static final int TRUST_USUALLY_MANAGED_FLUSH_DELAY = 2 * 60 * 1000;
 
     private final ArraySet<AgentInfo> mActiveAgents = new ArraySet<>();
     private final ArrayList<ITrustListener> mTrustListeners = new ArrayList<>();
@@ -136,13 +135,7 @@
         mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
         mActivityManager = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);
         mLockPatternUtils = new LockPatternUtils(context);
-
-        mStrongAuthTracker = new StrongAuthTracker(context) {
-            @Override
-            public void onStrongAuthRequiredChanged(int userId) {
-                refreshAgentList(userId);
-            }
-        };
+        mStrongAuthTracker = new StrongAuthTracker(context);
     }
 
     @Override
@@ -231,24 +224,24 @@
                 TRUST_USUALLY_MANAGED_FLUSH_DELAY);
     }
 
-    void refreshAgentList(int userId) {
-        if (DEBUG) Slog.d(TAG, "refreshAgentList()");
+    void refreshAgentList(int userIdOrAll) {
+        if (DEBUG) Slog.d(TAG, "refreshAgentList(" + userIdOrAll + ")");
         if (!mTrustAgentsCanRun) {
             return;
         }
-        if (userId != UserHandle.USER_ALL && userId < UserHandle.USER_SYSTEM) {
-            Log.e(TAG, "refreshAgentList(userId=" + userId + "): Invalid user handle,"
+        if (userIdOrAll != UserHandle.USER_ALL && userIdOrAll < UserHandle.USER_SYSTEM) {
+            Log.e(TAG, "refreshAgentList(userId=" + userIdOrAll + "): Invalid user handle,"
                     + " must be USER_ALL or a specific user.", new Throwable("here"));
-            userId = UserHandle.USER_ALL;
+            userIdOrAll = UserHandle.USER_ALL;
         }
         PackageManager pm = mContext.getPackageManager();
 
         List<UserInfo> userInfos;
-        if (userId == UserHandle.USER_ALL) {
+        if (userIdOrAll == UserHandle.USER_ALL) {
             userInfos = mUserManager.getUsers(true /* excludeDying */);
         } else {
             userInfos = new ArrayList<>();
-            userInfos.add(mUserManager.getUserInfo(userId));
+            userInfos.add(mUserManager.getUserInfo(userIdOrAll));
         }
         LockPatternUtils lockPatternUtils = mLockPatternUtils;
 
@@ -261,7 +254,7 @@
             if (!userInfo.supportsSwitchToByUser()) continue;
             if (!mActivityManager.isUserRunning(userInfo.id)) continue;
             if (!lockPatternUtils.isSecure(userInfo.id)) continue;
-            if (!mStrongAuthTracker.isTrustAllowedForUser(userInfo.id)) continue;
+            if (!mStrongAuthTracker.canAgentsRunForUser(userInfo.id)) continue;
             DevicePolicyManager dpm = lockPatternUtils.getDevicePolicyManager();
             int disabledFeatures = dpm.getKeyguardDisabledFeatures(null, userInfo.id);
             final boolean disableTrustAgents =
@@ -302,7 +295,7 @@
         boolean trustMayHaveChanged = false;
         for (int i = 0; i < obsoleteAgents.size(); i++) {
             AgentInfo info = obsoleteAgents.valueAt(i);
-            if (userId == UserHandle.USER_ALL || userId == info.userId) {
+            if (userIdOrAll == UserHandle.USER_ALL || userIdOrAll == info.userId) {
                 if (info.agent.isManagingTrust()) {
                     trustMayHaveChanged = true;
                 }
@@ -312,10 +305,10 @@
         }
 
         if (trustMayHaveChanged) {
-            if (userId == UserHandle.USER_ALL) {
+            if (userIdOrAll == UserHandle.USER_ALL) {
                 updateTrustAll();
             } else {
-                updateTrust(userId, 0);
+                updateTrust(userIdOrAll, 0);
             }
         }
     }
@@ -578,6 +571,10 @@
     }
 
     private void dispatchUnlockAttempt(boolean successful, int userId) {
+        if (successful) {
+            mStrongAuthTracker.allowTrustFromUnlock(userId);
+        }
+
         for (int i = 0; i < mActiveAgents.size(); i++) {
             AgentInfo info = mActiveAgents.valueAt(i);
             if (info.userId == userId) {
@@ -608,6 +605,10 @@
     }
 
     private void dispatchOnTrustChanged(boolean enabled, int userId, int flags) {
+        if (DEBUG) {
+            Log.i(TAG, "onTrustChanged(" + enabled + ", " + userId + ", 0x"
+                    + Integer.toHexString(flags) + ")");
+        }
         if (!enabled) flags = 0;
         for (int i = 0; i < mTrustListeners.size(); i++) {
             try {
@@ -623,6 +624,9 @@
     }
 
     private void dispatchOnTrustManagedChanged(boolean managed, int userId) {
+        if (DEBUG) {
+            Log.i(TAG, "onTrustManagedChanged(" + managed + ", " + userId + ")");
+        }
         for (int i = 0; i < mTrustListeners.size(); i++) {
             try {
                 mTrustListeners.get(i).onTrustManagedChanged(managed, userId);
@@ -980,4 +984,61 @@
                     null /* scheduler */);
         }
     }
+
+    private class StrongAuthTracker extends LockPatternUtils.StrongAuthTracker {
+
+        SparseBooleanArray mStartFromSuccessfulUnlock = new SparseBooleanArray();
+
+        public StrongAuthTracker(Context context) {
+            super(context);
+        }
+
+        @Override
+        public void onStrongAuthRequiredChanged(int userId) {
+            mStartFromSuccessfulUnlock.delete(userId);
+
+            if (DEBUG) {
+                Log.i(TAG, "onStrongAuthRequiredChanged(" + userId + ") ->"
+                        + " trustAllowed=" + isTrustAllowedForUser(userId)
+                        + " agentsCanRun=" + canAgentsRunForUser(userId));
+            }
+
+            refreshAgentList(userId);
+
+            // The list of active trust agents may not have changed, if there was a previous call
+            // to allowTrustFromUnlock, so we update the trust here too.
+            updateTrust(userId, 0 /* flags */);
+        }
+
+        boolean canAgentsRunForUser(int userId) {
+            return mStartFromSuccessfulUnlock.get(userId)
+                    || super.isTrustAllowedForUser(userId);
+        }
+
+        /**
+         * Temporarily suppress strong auth requirements for {@param userId} until strong auth
+         * changes again. Must only be called when we know about a successful unlock already
+         * before the underlying StrongAuthTracker.
+         *
+         * Note that this only changes whether trust agents can be started, not the actual trusted
+         * value.
+         */
+        void allowTrustFromUnlock(int userId) {
+            if (userId < UserHandle.USER_SYSTEM) {
+                throw new IllegalArgumentException("userId must be a valid user: " + userId);
+            }
+            boolean previous = canAgentsRunForUser(userId);
+            mStartFromSuccessfulUnlock.put(userId, true);
+
+            if (DEBUG) {
+                Log.i(TAG, "allowTrustFromUnlock(" + userId + ") ->"
+                        + " trustAllowed=" + isTrustAllowedForUser(userId)
+                        + " agentsCanRun=" + canAgentsRunForUser(userId));
+            }
+
+            if (canAgentsRunForUser(userId) != previous) {
+                refreshAgentList(userId);
+            }
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/tv/TvInputManagerService.java b/services/core/java/com/android/server/tv/TvInputManagerService.java
index 8a2729e..30442bc 100644
--- a/services/core/java/com/android/server/tv/TvInputManagerService.java
+++ b/services/core/java/com/android/server/tv/TvInputManagerService.java
@@ -1292,6 +1292,7 @@
         @Override
         public void unblockContent(
                 IBinder sessionToken, String unblockedRating, int userId) {
+            ensureParentalControlsPermission();
             final int callingUid = Binder.getCallingUid();
             final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid,
                     userId, "unblockContent");
@@ -2512,7 +2513,7 @@
 
         // For the recording session only
         @Override
-        public void onTuned() {
+        public void onTuned(Uri channelUri) {
             synchronized (mLock) {
                 if (DEBUG) {
                     Slog.d(TAG, "onTuned()");
@@ -2521,7 +2522,7 @@
                     return;
                 }
                 try {
-                    mSessionState.client.onTuned(mSessionState.seq);
+                    mSessionState.client.onTuned(mSessionState.seq, channelUri);
                 } catch (RemoteException e) {
                     Slog.e(TAG, "error in onTuned", e);
                 }
diff --git a/services/core/java/com/android/server/utils/ManagedApplicationService.java b/services/core/java/com/android/server/utils/ManagedApplicationService.java
new file mode 100644
index 0000000..a645701
--- /dev/null
+++ b/services/core/java/com/android/server/utils/ManagedApplicationService.java
@@ -0,0 +1,220 @@
+/**
+ * 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.utils;
+
+import android.annotation.NonNull;
+import android.app.PendingIntent;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.os.IBinder;
+import android.os.IBinder.DeathRecipient;
+import android.os.IInterface;
+import android.os.RemoteException;
+import android.os.UserHandle;
+import android.util.Slog;
+
+import java.util.Objects;
+
+/**
+ * Manages the lifecycle of an application-provided service bound from system server.
+ *
+ * @hide
+ */
+public class ManagedApplicationService {
+    private final String TAG = getClass().getSimpleName();
+
+    private final Context mContext;
+    private final int mUserId;
+    private final ComponentName mComponent;
+    private final int mClientLabel;
+    private final String mSettingsAction;
+    private final BinderChecker mChecker;
+
+    private final DeathRecipient mDeathRecipient = new DeathRecipient() {
+        @Override
+        public void binderDied() {
+            synchronized (mLock) {
+                mBoundInterface = null;
+            }
+        }
+    };
+
+    private final Object mLock = new Object();
+
+    // State protected by mLock
+    private ServiceConnection mPendingConnection;
+    private ServiceConnection mConnection;
+    private IInterface mBoundInterface;
+
+
+    private ManagedApplicationService(final Context context, final ComponentName component,
+            final int userId, int clientLabel, String settingsAction,
+            BinderChecker binderChecker) {
+        mContext = context;
+        mComponent = component;
+        mUserId = userId;
+        mClientLabel = clientLabel;
+        mSettingsAction = settingsAction;
+        mChecker = binderChecker;
+    }
+
+    /**
+     * Implement to validate returned IBinder instance.
+     */
+    public interface BinderChecker {
+        IInterface asInterface(IBinder binder);
+        boolean checkType(IInterface service);
+    }
+
+    /**
+     * Create a new ManagedApplicationService object but do not yet bind to the user service.
+     *
+     * @param context a Context to use for binding the application service.
+     * @param component the {@link ComponentName} of the application service to bind.
+     * @param userId the user ID of user to bind the application service as.
+     * @param clientLabel the resource ID of a label displayed to the user indicating the
+     *      binding service.
+     * @param settingsAction an action that can be used to open the Settings UI to enable/disable
+     *      binding to these services.
+     * @param binderChecker an interface used to validate the returned binder object.
+     * @return a ManagedApplicationService instance.
+     */
+    public static ManagedApplicationService build(@NonNull final Context context,
+        @NonNull final ComponentName component, final int userId, @NonNull int clientLabel,
+        @NonNull String settingsAction, @NonNull BinderChecker binderChecker) {
+        return new ManagedApplicationService(context, component, userId, clientLabel,
+            settingsAction, binderChecker);
+    }
+
+    /**
+     * @return the user ID of the user that owns the bound service.
+     */
+    public int getUserId() {
+        return mUserId;
+    }
+
+    /**
+     * @return the component of the bound service.
+     */
+    public ComponentName getComponent() {
+        return mComponent;
+    }
+
+    /**
+     * Asynchronously unbind from the application service if the bound service component and user
+     * does not match the given signature.
+     *
+     * @param componentName the component that must match.
+     * @param userId the user ID that must match.
+     * @return {@code true} if not matching.
+     */
+    public boolean disconnectIfNotMatching(final ComponentName componentName, final int userId) {
+        if (matches(componentName, userId)) {
+            return false;
+        }
+        disconnect();
+        return true;
+    }
+
+    /**
+     * Asynchronously unbind from the application service if bound.
+     */
+    public void disconnect() {
+        synchronized (mLock) {
+            // Wipe out pending connections
+            mPendingConnection = null;
+
+            // Unbind existing connection, if it exists
+            if (mConnection != null) {
+                mContext.unbindService(mConnection);
+                mConnection = null;
+            }
+
+            mBoundInterface = null;
+        }
+    }
+
+    /**
+     * Asynchronously bind to the application service if not bound.
+     */
+    public void connect() {
+        synchronized (mLock) {
+            if (mConnection != null || mPendingConnection != null) {
+                // We're already connected or are trying to connect
+                return;
+            }
+
+            final PendingIntent pendingIntent = PendingIntent.getActivity(
+                    mContext, 0, new Intent(mSettingsAction), 0);
+            final Intent intent = new Intent().setComponent(mComponent).
+                    putExtra(Intent.EXTRA_CLIENT_LABEL, mClientLabel).
+                    putExtra(Intent.EXTRA_CLIENT_INTENT, pendingIntent);
+
+            final ServiceConnection serviceConnection = new ServiceConnection() {
+                @Override
+                public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
+                    synchronized (mLock) {
+                        if (mPendingConnection == this) {
+                            // No longer pending, remove from pending connection
+                            mPendingConnection = null;
+                            mConnection = this;
+                        } else {
+                            // Service connection wasn't pending, must have been disconnected
+                            mContext.unbindService(this);
+                        }
+
+                        try {
+                            iBinder.linkToDeath(mDeathRecipient, 0);
+                            mBoundInterface = mChecker.asInterface(iBinder);
+                            if (!mChecker.checkType(mBoundInterface)) {
+                                // Received an invalid binder, disconnect
+                                mContext.unbindService(this);
+                                mBoundInterface = null;
+                            }
+                        } catch (RemoteException e) {
+                            // DOA
+                            Slog.w(TAG, "Unable to bind service: " + intent, e);
+                            mBoundInterface = null;
+                        }
+                    }
+                }
+
+                @Override
+                public void onServiceDisconnected(ComponentName componentName) {
+                    Slog.w(TAG, "Service disconnected: " + intent);
+                }
+            };
+
+            mPendingConnection = serviceConnection;
+
+            try {
+                if (!mContext.bindServiceAsUser(intent, serviceConnection,
+                        Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE,
+                        new UserHandle(mUserId))) {
+                    Slog.w(TAG, "Unable to bind service: " + intent);
+                }
+            } catch (SecurityException e) {
+                Slog.w(TAG, "Unable to bind service: " + intent, e);
+            }
+        }
+    }
+
+    private boolean matches(final ComponentName component, final int userId) {
+        return Objects.equals(mComponent, component) && mUserId == userId;
+    }
+}
diff --git a/services/core/java/com/android/server/vr/EnabledComponentsObserver.java b/services/core/java/com/android/server/vr/EnabledComponentsObserver.java
new file mode 100644
index 0000000..1363fb9
--- /dev/null
+++ b/services/core/java/com/android/server/vr/EnabledComponentsObserver.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.vr;
+
+import android.annotation.NonNull;
+import android.app.ActivityManager;
+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.content.pm.ServiceInfo;
+import android.content.pm.UserInfo;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.UserHandle;
+import android.os.UserManager;
+import android.provider.Settings;
+import android.text.TextUtils;
+import android.util.ArraySet;
+import android.util.Slog;
+import android.util.SparseArray;
+
+import com.android.internal.content.PackageMonitor;
+import com.android.server.vr.SettingsObserver.SettingChangeListener;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * Detects changes in packages, settings, and current users that may affect whether components
+ * implementing a given service can be run.
+ *
+ * @hide
+ */
+public class EnabledComponentsObserver implements SettingChangeListener {
+
+    private static final String TAG = EnabledComponentsObserver.class.getSimpleName();
+    private static final String ENABLED_SERVICES_SEPARATOR = ":";
+
+    public static final int NO_ERROR = 0;
+    public static final int DISABLED = -1;
+    public static final int NOT_INSTALLED = -2;
+
+    private final Object mLock;
+    private final Context mContext;
+    private final String mSettingName;
+    private final String mServiceName;
+    private final String mServicePermission;
+    private final SparseArray<ArraySet<ComponentName>> mInstalledSet = new SparseArray<>();
+    private final SparseArray<ArraySet<ComponentName>> mEnabledSet = new SparseArray<>();
+    private final Set<EnabledComponentChangeListener> mEnabledComponentListeners = new ArraySet<>();
+
+    /**
+     * Implement this to receive callbacks when relevant changes to the allowed components occur.
+     */
+    public interface EnabledComponentChangeListener {
+
+        /**
+         * Called when a change in the allowed components occurs.
+         */
+        void onEnabledComponentChanged();
+    }
+
+    private EnabledComponentsObserver(@NonNull Context context, @NonNull String settingName,
+            @NonNull String servicePermission, @NonNull String serviceName, @NonNull Object lock,
+            @NonNull Collection<EnabledComponentChangeListener> listeners) {
+        mLock = lock;
+        mContext = context;
+        mSettingName = settingName;
+        mServiceName = serviceName;
+        mServicePermission = servicePermission;
+        mEnabledComponentListeners.addAll(listeners);
+    }
+
+    /**
+     * Create a EnabledComponentObserver instance.
+     *
+     * @param context the context to query for changes.
+     * @param handler a handler to receive lifecycle events from system services on.
+     * @param settingName the name of a setting to monitor for a list of enabled components.
+     * @param looper a {@link Looper} to use for receiving package callbacks.
+     * @param servicePermission the permission required by the components to be bound.
+     * @param serviceName the intent action implemented by the tracked components.
+     * @param lock a lock object used to guard instance state in all callbacks and method calls.
+     * @return an EnableComponentObserver instance.
+     */
+    public static EnabledComponentsObserver build(@NonNull Context context,
+            @NonNull Handler handler, @NonNull String settingName, @NonNull Looper looper,
+            @NonNull String servicePermission, @NonNull String serviceName,
+            @NonNull final Object lock,
+            @NonNull Collection<EnabledComponentChangeListener> listeners) {
+
+        SettingsObserver s = SettingsObserver.build(context, handler, settingName);
+
+        final EnabledComponentsObserver o = new EnabledComponentsObserver(context, settingName,
+                servicePermission, serviceName, lock, listeners);
+
+        PackageMonitor packageMonitor = new PackageMonitor() {
+            @Override
+            public void onSomePackagesChanged() {
+                o.onPackagesChanged();
+
+            }
+
+            @Override
+            public void onPackageDisappeared(String packageName, int reason) {
+                o.onPackagesChanged();
+
+            }
+
+            @Override
+            public void onPackageModified(String packageName) {
+                o.onPackagesChanged();
+
+            }
+
+            @Override
+            public boolean onHandleForceStop(Intent intent, String[] packages, int uid,
+                    boolean doit) {
+                o.onPackagesChanged();
+
+                return super.onHandleForceStop(intent, packages, uid, doit);
+            }
+        };
+
+        packageMonitor.register(context, looper, UserHandle.ALL, true);
+
+        s.addListener(o);
+
+        return o;
+
+    }
+
+    public void onPackagesChanged() {
+        rebuildAll();
+    }
+
+    @Override
+    public void onSettingChanged() {
+        rebuildAll();
+    }
+
+    @Override
+    public void onSettingRestored(String prevValue, String newValue, int userId) {
+        rebuildAll();
+    }
+
+    public void onUsersChanged() {
+        rebuildAll();
+    }
+
+    /**
+     * Rebuild the sets of allowed components for each current user profile.
+     */
+    public void rebuildAll() {
+        synchronized (mLock) {
+            mInstalledSet.clear();
+            mEnabledSet.clear();
+            final int[] userIds = getCurrentProfileIds();
+            for (int i : userIds) {
+                ArraySet<ComponentName> implementingPackages = loadComponentNamesForUser(i);
+                ArraySet<ComponentName> packagesFromSettings =
+                        loadComponentNamesFromSetting(mSettingName, i);
+                packagesFromSettings.retainAll(implementingPackages);
+
+                mInstalledSet.put(i, implementingPackages);
+                mEnabledSet.put(i, packagesFromSettings);
+
+            }
+        }
+        sendSettingChanged();
+    }
+
+    /**
+     * Check whether a given component is present and enabled for the given user.
+     *
+     * @param component the component to check.
+     * @param userId the user ID for the component to check.
+     * @return {@code true} if present and enabled.
+     */
+    public int isValid(ComponentName component, int userId) {
+        synchronized (mLock) {
+            ArraySet<ComponentName> installedComponents = mInstalledSet.get(userId);
+            if (installedComponents == null || !installedComponents.contains(component)) {
+                return NOT_INSTALLED;
+            }
+            ArraySet<ComponentName> validComponents = mEnabledSet.get(userId);
+            if (validComponents == null || !validComponents.contains(component)) {
+                return DISABLED;
+            }
+            return NO_ERROR;
+        }
+    }
+
+    private int[] getCurrentProfileIds() {
+        UserManager userManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
+        if (userManager == null) {
+            return null;
+        }
+        int currentUserId = ActivityManager.getCurrentUser();
+        List<UserInfo> profiles = userManager.getProfiles(currentUserId);
+        if (profiles == null) {
+            return null;
+        }
+        final int s = profiles.size();
+        int[] userIds = new int[s];
+        int ctr = 0;
+        for (UserInfo info : profiles) {
+            userIds[ctr++] = info.id;
+        }
+        return userIds;
+    }
+
+    private ArraySet<ComponentName> loadComponentNamesForUser(int userId) {
+        ArraySet<ComponentName> installed = new ArraySet<>();
+        PackageManager pm = mContext.getPackageManager();
+        Intent queryIntent = new Intent(mServiceName);
+        List<ResolveInfo> installedServices = pm.queryIntentServicesAsUser(
+                queryIntent,
+                PackageManager.GET_SERVICES | PackageManager.GET_META_DATA,
+                userId);
+        if (installedServices != null) {
+            for (int i = 0, count = installedServices.size(); i < count; i++) {
+                ResolveInfo resolveInfo = installedServices.get(i);
+                ServiceInfo info = resolveInfo.serviceInfo;
+
+                ComponentName component = new ComponentName(info.packageName, info.name);
+                if (!mServicePermission.equals(info.permission)) {
+                    Slog.w(TAG, "Skipping service " + info.packageName + "/" + info.name
+                            + ": it does not require the permission "
+                            + mServicePermission);
+                    continue;
+                }
+                installed.add(component);
+            }
+        }
+        return installed;
+    }
+
+    private ArraySet<ComponentName> loadComponentNamesFromSetting(String settingName,
+            int userId) {
+        final ContentResolver cr = mContext.getContentResolver();
+        String settingValue = Settings.Secure.getStringForUser(
+                cr,
+                settingName,
+                userId);
+        if (TextUtils.isEmpty(settingValue))
+            return new ArraySet<>();
+        String[] restored = settingValue.split(ENABLED_SERVICES_SEPARATOR);
+        ArraySet<ComponentName> result = new ArraySet<>(restored.length);
+        for (int i = 0; i < restored.length; i++) {
+            ComponentName value = ComponentName.unflattenFromString(restored[i]);
+            if (null != value) {
+                result.add(value);
+            }
+        }
+        return result;
+    }
+
+    private void sendSettingChanged() {
+        for (EnabledComponentChangeListener l : mEnabledComponentListeners) {
+            l.onEnabledComponentChanged();
+        }
+    }
+
+}
diff --git a/services/core/java/com/android/server/vr/SettingsObserver.java b/services/core/java/com/android/server/vr/SettingsObserver.java
new file mode 100644
index 0000000..ce76863
--- /dev/null
+++ b/services/core/java/com/android/server/vr/SettingsObserver.java
@@ -0,0 +1,145 @@
+/**
+ * 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.vr;
+
+import android.annotation.NonNull;
+import android.content.BroadcastReceiver;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.Intent;
+import android.database.ContentObserver;
+import android.net.Uri;
+import android.os.Handler;
+import android.os.UserHandle;
+import android.provider.Settings;
+import android.util.ArraySet;
+
+import java.util.Objects;
+import java.util.Set;
+
+/**
+ * Detects changes in a given setting.
+ *
+ * @hide
+ */
+public class SettingsObserver {
+
+    private final String mSecureSettingName;
+    private final BroadcastReceiver mSettingRestorReceiver;
+    private final ContentObserver mContentObserver;
+    private final Set<SettingChangeListener> mSettingsListeners = new ArraySet<>();
+
+    /**
+     * Implement this to receive callbacks when the setting tracked by this observer changes.
+     */
+    public interface SettingChangeListener {
+
+        /**
+         * Called when the tracked setting has changed.
+         */
+        void onSettingChanged();
+
+
+        /**
+         * Called when the tracked setting has been restored for a particular user.
+         *
+         * @param prevValue the previous value of the setting.
+         * @param newValue the new value of the setting.
+         * @param userId the user ID for which this setting has been restored.
+         */
+        void onSettingRestored(String prevValue, String newValue, int userId);
+    }
+
+    private SettingsObserver(@NonNull final Context context, @NonNull final Handler handler,
+            @NonNull final Uri settingUri, @NonNull final String secureSettingName) {
+
+        mSecureSettingName = secureSettingName;
+        mSettingRestorReceiver = new BroadcastReceiver() {
+            @Override
+            public void onReceive(Context context, Intent intent) {
+                if (Intent.ACTION_SETTING_RESTORED.equals(intent.getAction())) {
+                    String element = intent.getStringExtra(Intent.EXTRA_SETTING_NAME);
+                    if (Objects.equals(element, secureSettingName)) {
+                        String prevValue = intent.getStringExtra(Intent.EXTRA_SETTING_PREVIOUS_VALUE);
+                        String newValue = intent.getStringExtra(Intent.EXTRA_SETTING_NEW_VALUE);
+                        sendSettingRestored(prevValue, newValue, getSendingUserId());
+                    }
+                }
+            }
+        };
+
+        mContentObserver = new ContentObserver(handler) {
+            @Override
+            public void onChange(boolean selfChange, Uri uri) {
+                if (uri == null || settingUri.equals(uri)) {
+                    sendSettingChanged();
+                }
+            }
+        };
+
+        ContentResolver resolver = context.getContentResolver();
+        resolver.registerContentObserver(settingUri, false, mContentObserver,
+                UserHandle.USER_ALL);
+    }
+
+    /**
+     * Create a SettingsObserver instance.
+     *
+     * @param context the context to query for settings changes.
+     * @param handler the handler to use for a settings ContentObserver.
+     * @param settingName the setting to track.
+     * @return a SettingsObserver instance.
+     */
+    public static SettingsObserver build(@NonNull Context context, @NonNull Handler handler,
+            @NonNull String settingName) {
+        Uri settingUri = Settings.Secure.getUriFor(settingName);
+
+        return new SettingsObserver(context, handler, settingUri, settingName);
+    }
+
+    /**
+     * Add a listener for setting changes.
+     *
+     * @param listener a {@link SettingChangeListener} instance.
+     */
+    public void addListener(@NonNull SettingChangeListener listener) {
+        mSettingsListeners.add(listener);
+
+    }
+
+    /**
+     * Remove a listener for setting changes.
+     *
+     * @param listener a {@link SettingChangeListener} instance.
+     */
+    public void removeListener(@NonNull SettingChangeListener listener) {
+        mSettingsListeners.remove(listener);
+
+    }
+
+    private void sendSettingChanged() {
+        for (SettingChangeListener l : mSettingsListeners) {
+            l.onSettingChanged();
+        }
+    }
+
+    private void sendSettingRestored(final String prevValue, final String newValue, final int userId) {
+        for (SettingChangeListener l : mSettingsListeners) {
+            l.onSettingRestored(prevValue, newValue, userId);
+        }
+    }
+
+}
diff --git a/services/core/java/com/android/server/vr/VrManagerInternal.java b/services/core/java/com/android/server/vr/VrManagerInternal.java
index 42db364..6b5523f 100644
--- a/services/core/java/com/android/server/vr/VrManagerInternal.java
+++ b/services/core/java/com/android/server/vr/VrManagerInternal.java
@@ -1,4 +1,4 @@
-/*
+/**
  * Copyright (C) 2015 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
@@ -15,14 +15,22 @@
  */
 package com.android.server.vr;
 
+import android.annotation.NonNull;
+import android.content.ComponentName;
+
 /**
- * VR mode local system service interface.
+ * Service for accessing the VR mode manager.
  *
  * @hide Only for use within system server.
  */
 public abstract class VrManagerInternal {
 
     /**
+     * The error code returned on success.
+     */
+    public static final int NO_ERROR = 0;
+
+    /**
      * Return current VR mode state.
      *
      * @return {@code true} if VR mode is enabled.
@@ -33,8 +41,11 @@
      * Set the current VR mode state.
      *
      * @param enabled {@code true} to enable VR mode.
+     * @param packageName The package name of the requested VrListenerService to bind.
+     * @param userId the user requesting the VrListenerService component.
      */
-    public abstract void setVrMode(boolean enabled);
+    public abstract void setVrMode(boolean enabled, @NonNull ComponentName packageName,
+            int userId);
 
     /**
      * Add a listener for VR mode state changes.
@@ -43,13 +54,23 @@
      * </p>
      * @param listener the listener instance to add.
      */
-    public abstract void registerListener(VrStateListener listener);
+    public abstract void registerListener(@NonNull VrStateListener listener);
 
     /**
      * Remove the listener from the current set of listeners.
      *
      * @param listener the listener to remove.
      */
-    public abstract void unregisterListener(VrStateListener listener);
+    public abstract void unregisterListener(@NonNull VrStateListener listener);
+
+   /**
+    * Return NO_ERROR if the given package is installed on the device and enabled as a
+    * VrListenerService for the given current user, or a negative error code indicating a failure.
+    *
+    * @param packageName the name of the package to check, or null to select the default package.
+    * @return NO_ERROR if the given package is installed and is enabled, or a negative error code
+    *       given in {@link android.service.vr.VrModeException} on failure.
+    */
+    public abstract int hasVrPackage(@NonNull ComponentName packageName, int userId);
 
 }
diff --git a/services/core/java/com/android/server/vr/VrManagerService.java b/services/core/java/com/android/server/vr/VrManagerService.java
index 2f076d1..f5914faf 100644
--- a/services/core/java/com/android/server/vr/VrManagerService.java
+++ b/services/core/java/com/android/server/vr/VrManagerService.java
@@ -1,4 +1,4 @@
-/*
+/**
  * Copyright (C) 2015 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
@@ -15,24 +15,54 @@
  */
 package com.android.server.vr;
 
+import android.app.AppOpsManager;
+import android.annotation.NonNull;
 import android.content.Context;
+import android.content.ComponentName;
 import android.content.Intent;
 import android.content.pm.PackageManager;
+import android.os.Binder;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.IInterface;
+import android.os.Looper;
 import android.os.UserHandle;
+import android.provider.Settings;
+import android.service.vr.IVrListener;
+import android.service.vr.VrListenerService;
 import android.util.ArraySet;
 import android.util.Slog;
 
+import com.android.internal.R;
 import com.android.server.SystemService;
+import com.android.server.vr.EnabledComponentsObserver.EnabledComponentChangeListener;
+import com.android.server.utils.ManagedApplicationService;
+import com.android.server.utils.ManagedApplicationService.BinderChecker;
 
 import java.util.ArrayList;
+import java.util.Set;
 
 /**
- * Service tracking whether VR mode is active, and notifying listening system services of state
- * changes.
+ * Service tracking whether VR mode is active, and notifying listening services of state changes.
+ * <p/>
+ * Services running in system server may modify the state of VrManagerService via the interface in
+ * VrManagerInternal, and may register to receive callbacks when the system VR mode changes via the
+ * interface given in VrStateListener.
+ * <p/>
+ * Device vendors may choose to receive VR state changes by implementing the VR mode HAL, e.g.:
+ *  hardware/libhardware/modules/vr
+ * <p/>
+ * In general applications may enable or disable VR mode by calling
+ * {@link android.app.Activity#setVrMode)}.  An application may also implement a service to be run
+ * while in VR mode by implementing {@link android.service.vr.VrListenerService}.
  *
- * {@hide}
+ * @see {@link android.service.vr.VrListenerService}
+ * @see {@link com.android.server.vr.VrManagerInternal}
+ * @see {@link com.android.server.vr.VrStateListener}
+ *
+ * @hide
  */
-public class VrManagerService extends SystemService {
+public class VrManagerService extends SystemService implements EnabledComponentChangeListener{
 
     public static final String TAG = "VrManagerService";
 
@@ -40,9 +70,48 @@
     private static native void setVrModeNative(boolean enabled);
 
     private final Object mLock = new Object();
-    private boolean mVrModeEnabled = false;
-    private ArraySet<VrStateListener> mListeners = new ArraySet<>();
 
+    private final IBinder mOverlayToken = new Binder();
+
+    // State protected by mLock
+    private boolean mVrModeEnabled = false;
+    private final Set<VrStateListener> mListeners = new ArraySet<>();
+    private EnabledComponentsObserver mComponentObserver;
+    private ManagedApplicationService mCurrentVrService;
+    private Context mContext;
+
+    private static final BinderChecker sBinderChecker = new BinderChecker() {
+        @Override
+        public IInterface asInterface(IBinder binder) {
+            return IVrListener.Stub.asInterface(binder);
+        }
+
+        @Override
+        public boolean checkType(IInterface service) {
+            return service instanceof IVrListener;
+        }
+    };
+
+    /**
+     * Called when a user, package, or setting changes that could affect whether or not the
+     * currently bound VrListenerService is changed.
+     */
+    @Override
+    public void onEnabledComponentChanged() {
+        synchronized (mLock) {
+            if (mCurrentVrService == null) {
+                return; // No active services
+            }
+
+            // There is an active service, update it if needed
+            updateCurrentVrServiceLocked(mVrModeEnabled, mCurrentVrService.getComponent(),
+                    mCurrentVrService.getUserId());
+        }
+    }
+
+    /**
+     * Implementation of VrManagerInternal.  Callable only from system services.
+     */
     private final class LocalService extends VrManagerInternal {
         @Override
         public boolean isInVrMode() {
@@ -50,8 +119,8 @@
         }
 
         @Override
-        public void setVrMode(boolean enabled) {
-            VrManagerService.this.setVrMode(enabled);
+        public void setVrMode(boolean enabled, ComponentName packageName, int userId) {
+            VrManagerService.this.setVrMode(enabled, packageName, userId);
         }
 
         @Override
@@ -63,6 +132,11 @@
         public void unregisterListener(VrStateListener listener) {
             VrManagerService.this.removeListener(listener);
         }
+
+        @Override
+        public int hasVrPackage(ComponentName packageName, int userId) {
+            return VrManagerService.this.hasVrPackage(packageName, userId);
+        }
     }
 
     public VrManagerService(Context context) {
@@ -73,11 +147,186 @@
     public void onStart() {
         synchronized(mLock) {
             initializeNative();
+            mContext = getContext();
         }
 
         publishLocalService(VrManagerInternal.class, new LocalService());
     }
 
+    @Override
+    public void onBootPhase(int phase) {
+        if (phase == SystemService.PHASE_THIRD_PARTY_APPS_CAN_START) {
+            synchronized (mLock) {
+                Looper looper = Looper.getMainLooper();
+                Handler handler = new Handler(looper);
+                ArrayList<EnabledComponentChangeListener> listeners = new ArrayList<>();
+                listeners.add(this);
+                mComponentObserver = EnabledComponentsObserver.build(mContext, handler,
+                        Settings.Secure.ENABLED_VR_LISTENERS, looper,
+                        android.Manifest.permission.BIND_VR_LISTENER_SERVICE,
+                        VrListenerService.SERVICE_INTERFACE, mLock, listeners);
+
+                mComponentObserver.rebuildAll();
+            }
+        }
+    }
+
+    @Override
+    public void onStartUser(int userHandle) {
+        synchronized (mLock) {
+            mComponentObserver.onUsersChanged();
+        }
+    }
+
+    @Override
+    public void onSwitchUser(int userHandle) {
+        synchronized (mLock) {
+            mComponentObserver.onUsersChanged();
+        }
+
+    }
+
+    @Override
+    public void onStopUser(int userHandle) {
+        synchronized (mLock) {
+            mComponentObserver.onUsersChanged();
+        }
+
+    }
+
+    @Override
+    public void onCleanupUser(int userHandle) {
+        synchronized (mLock) {
+            mComponentObserver.onUsersChanged();
+        }
+    }
+
+    private void updateOverlayStateLocked() {
+        final long identity = Binder.clearCallingIdentity();
+        try {
+            AppOpsManager appOpsManager = getContext().getSystemService(AppOpsManager.class);
+            if (appOpsManager != null) {
+                appOpsManager.setUserRestriction(AppOpsManager.OP_SYSTEM_ALERT_WINDOW,
+                        mVrModeEnabled, mOverlayToken);
+            }
+        } finally {
+            Binder.restoreCallingIdentity(identity);
+        }
+    }
+
+    /**
+     * Send VR mode changes (if the mode state has changed), and update the bound/unbound state of
+     * the currently selected VR listener service.  If the component selected for the VR listener
+     * service has changed, unbind the previous listener and bind the new listener (if enabled).
+     * <p/>
+     * Note: Must be called while holding {@code mLock}.
+     *
+     * @param enabled new state for VR mode.
+     * @param component new component to be bound as a VR listener.
+     * @param userId user owning the component to be bound.
+     *
+     * @return {@code true} if the component/user combination specified is valid.
+     */
+    private boolean updateCurrentVrServiceLocked(boolean enabled,
+            @NonNull ComponentName component, int userId) {
+
+        // Always send mode change events.
+        changeVrModeLocked(enabled);
+
+        boolean validUserComponent = (mComponentObserver.isValid(component, userId) ==
+                EnabledComponentsObserver.NO_ERROR);
+
+        if (!enabled || !validUserComponent) {
+            // Unbind whatever is running
+            if (mCurrentVrService != null) {
+                Slog.i(TAG, "Disconnecting " + mCurrentVrService.getComponent() + " for user " +
+                        mCurrentVrService.getUserId());
+                mCurrentVrService.disconnect();
+                mCurrentVrService = null;
+            }
+            return validUserComponent;
+        }
+
+        if (mCurrentVrService != null) {
+            // Unbind any running service that doesn't match the component/user selection
+            if (mCurrentVrService.disconnectIfNotMatching(component, userId)) {
+                Slog.i(TAG, "Disconnecting " + mCurrentVrService.getComponent() + " for user " +
+                        mCurrentVrService.getUserId());
+                mCurrentVrService = VrManagerService.create(mContext, component, userId);
+                mCurrentVrService.connect();
+                Slog.i(TAG, "Connecting " + mCurrentVrService.getComponent() + " for user " +
+                        mCurrentVrService.getUserId());
+            }
+            // The service with the correct component/user is bound
+        } else {
+            // Nothing was previously running, bind a new service
+            mCurrentVrService = VrManagerService.create(mContext, component, userId);
+            mCurrentVrService.connect();
+            Slog.i(TAG, "Connecting " + mCurrentVrService.getComponent() + " for user " +
+                    mCurrentVrService.getUserId());
+        }
+
+        return validUserComponent;
+    }
+
+    /**
+     * Send VR mode change callbacks to HAL and system services if mode has actually changed.
+     * <p/>
+     * Note: Must be called while holding {@code mLock}.
+     *
+     * @param enabled new state of the VR mode.
+     */
+    private void changeVrModeLocked(boolean enabled) {
+        if (mVrModeEnabled != enabled) {
+            mVrModeEnabled = enabled;
+
+            // Log mode change event.
+            Slog.i(TAG, "VR mode " + ((mVrModeEnabled) ? "enabled" : "disabled"));
+            setVrModeNative(mVrModeEnabled);
+
+            updateOverlayStateLocked();
+            onVrModeChangedLocked();
+        }
+    }
+
+    /**
+     * Notify system services of VR mode change.
+     * <p/>
+     * Note: Must be called while holding {@code mLock}.
+     */
+    private void onVrModeChangedLocked() {
+        for (VrStateListener l : mListeners) {
+            l.onVrStateChanged(mVrModeEnabled);
+        }
+    }
+
+    /**
+     * Helper function for making ManagedApplicationService instances.
+     */
+    private static ManagedApplicationService create(@NonNull Context context,
+            @NonNull ComponentName component, int userId) {
+        return ManagedApplicationService.build(context, component, userId,
+                R.string.vr_listener_binding_label, Settings.ACTION_VR_LISTENER_SETTINGS,
+                sBinderChecker);
+    }
+
+    /*
+     * Implementation of VrManagerInternal calls.  These are callable from system services.
+     */
+
+    private boolean setVrMode(boolean enabled, @NonNull ComponentName targetPackageName,
+            int userId) {
+        synchronized (mLock) {
+            return updateCurrentVrServiceLocked(enabled, targetPackageName, userId);
+        }
+    }
+
+    private boolean getVrMode() {
+        synchronized (mLock) {
+            return mVrModeEnabled;
+        }
+    }
+
     private void addListener(VrStateListener listener) {
         synchronized (mLock) {
             mListeners.add(listener);
@@ -90,30 +339,9 @@
         }
     }
 
-    private void setVrMode(boolean enabled) {
+    private int hasVrPackage(@NonNull ComponentName targetPackageName, int userId) {
         synchronized (mLock) {
-            if (mVrModeEnabled != enabled) {
-                mVrModeEnabled = enabled;
-                // Log mode change event.
-                Slog.i(TAG, "VR mode " + ((mVrModeEnabled) ? "enabled" : "disabled"));
-                setVrModeNative(mVrModeEnabled);
-                onVrModeChangedLocked();
-            }
-        }
-    }
-
-    private boolean getVrMode() {
-        synchronized (mLock) {
-            return mVrModeEnabled;
-        }
-    }
-
-    /**
-     * Notify system services of VR mode change.
-     */
-    private void onVrModeChangedLocked() {
-        for (VrStateListener l : mListeners) {
-            l.onVrStateChanged(mVrModeEnabled);
+            return mComponentObserver.isValid(targetPackageName, userId);
         }
     }
 }
diff --git a/services/core/java/com/android/server/vr/VrStateListener.java b/services/core/java/com/android/server/vr/VrStateListener.java
index b8af4b2..b0603c8 100644
--- a/services/core/java/com/android/server/vr/VrStateListener.java
+++ b/services/core/java/com/android/server/vr/VrStateListener.java
@@ -1,4 +1,4 @@
-/*
+/**
  * Copyright (C) 2015 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
@@ -16,7 +16,9 @@
 package com.android.server.vr;
 
 /**
- * Listener for state changes in VrManagerService,
+ * Listener for state changes in VrManagerService.
+ *
+ * @hide Only for use within system server.
  */
 public abstract class VrStateListener {
 
diff --git a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
index ba0d340..ccbdad2 100644
--- a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
+++ b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
@@ -882,6 +882,9 @@
             wallpaper = mLockWallpaperMap.get(userId);
             if (wallpaper == null) {
                 // It's already gone; we're done.
+                if (DEBUG) {
+                    Slog.i(TAG, "Lock wallpaper already cleared");
+                }
                 return;
             }
         } else {
@@ -902,14 +905,19 @@
                 wallpaper.wallpaperFile.delete();
                 wallpaper.cropFile.delete();
                 if (which == FLAG_SET_LOCK) {
+                    mLockWallpaperMap.remove(userId);
                     final IWallpaperManagerCallback cb = mKeyguardListener;
                     if (cb != null) {
+                        if (DEBUG) {
+                            Slog.i(TAG, "Notifying keyguard of lock wallpaper clear");
+                        }
                         try {
                             cb.onWallpaperChanged();
                         } catch (RemoteException e) {
                             // Oh well it went away; no big deal
                         }
                     }
+                    saveSettingsLocked(userId);
                     return;
                 }
             }
@@ -1309,7 +1317,7 @@
                 List<ResolveInfo> ris =
                         mIPackageManager.queryIntentServices(intent,
                                 intent.resolveTypeIfNeeded(mContext.getContentResolver()),
-                                PackageManager.GET_META_DATA, serviceUserId);
+                                PackageManager.GET_META_DATA, serviceUserId).getList();
                 for (int i=0; i<ris.size(); i++) {
                     ServiceInfo rsi = ris.get(i).serviceInfo;
                     if (rsi.name.equals(si.name) &&
diff --git a/services/core/java/com/android/server/webkit/WebViewUpdateService.java b/services/core/java/com/android/server/webkit/WebViewUpdateService.java
index 9c770e1..2db6b5d 100644
--- a/services/core/java/com/android/server/webkit/WebViewUpdateService.java
+++ b/services/core/java/com/android/server/webkit/WebViewUpdateService.java
@@ -190,7 +190,7 @@
         userAddedFilter.addAction(Intent.ACTION_USER_ADDED);
         getContext().registerReceiver(mWebViewUpdatedReceiver, userAddedFilter);
 
-        publishBinderService("webviewupdate", new BinderService());
+        publishBinderService("webviewupdate", new BinderService(), true /*allowIsolated*/);
     }
 
     private static boolean existsValidNonFallbackProvider(WebViewProviderInfo[] providers) {
diff --git a/services/core/java/com/android/server/wm/AppWindowAnimator.java b/services/core/java/com/android/server/wm/AppWindowAnimator.java
index a81fba0..55b3c7b 100644
--- a/services/core/java/com/android/server/wm/AppWindowAnimator.java
+++ b/services/core/java/com/android/server/wm/AppWindowAnimator.java
@@ -190,7 +190,8 @@
 
     public void clearThumbnail() {
         if (thumbnail != null) {
-            thumbnail.destroy();
+            thumbnail.hide();
+            mService.mWindowPlacerLocked.destroyAfterTransaction(thumbnail);
             thumbnail = null;
         }
         deferThumbnailDestruction = false;
diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java
index f9e258d..9795c93 100644
--- a/services/core/java/com/android/server/wm/AppWindowToken.java
+++ b/services/core/java/com/android/server/wm/AppWindowToken.java
@@ -129,6 +129,7 @@
     boolean mAlwaysFocusable;
 
     boolean mAppStopped;
+    int mPendingRelaunchCount;
 
     ArrayDeque<Rect> mFrozenBounds = new ArrayDeque<>();
 
@@ -354,6 +355,11 @@
                 continue;
             }
 
+            if (DEBUG_ADD_REMOVE) Slog.e(TAG_WM, "win=" + win
+                    + " destroySurfaces: mAppStopped=" + mAppStopped
+                    + " win.mWindowRemovalAllowed=" + win.mWindowRemovalAllowed
+                    + " win.mRemoveOnExit=" + win.mRemoveOnExit);
+
             win.destroyOrSaveSurface();
             if (win.mRemoveOnExit) {
                 win.mAnimatingExit = false;
@@ -372,14 +378,19 @@
         }
     }
 
-    // The application has stopped, so destroy any surfaces which were keeping alive
-    // in case they were still being used.
-    void notifyAppStopped() {
-        mAppStopped = true;
-        destroySurfaces();
+    /**
+     * If the application has stopped it is okay to destroy any surfaces which were keeping alive
+     * in case they were still being used.
+     */
+    void notifyAppStopped(boolean stopped) {
+        if (DEBUG_ADD_REMOVE) Slog.v(TAG, "notifyAppStopped: stopped=" + stopped + " " + this);
+        mAppStopped = stopped;
 
-        // Remove any starting window that was added for this app if they are still around.
-        mTask.mService.scheduleRemoveStartingWindowLocked(this);
+        if (stopped) {
+            destroySurfaces();
+            // Remove any starting window that was added for this app if they are still around.
+            mTask.mService.scheduleRemoveStartingWindowLocked(this);
+        }
     }
 
     /**
@@ -472,7 +483,7 @@
                 winNdx = Math.min(winNdx - 1, allAppWindows.size() - 1)) {
             WindowState win = allAppWindows.get(winNdx);
             if (win.mAppDied) {
-                if (DEBUG_WINDOW_MOVEMENT) {
+                if (DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) {
                     Slog.w(TAG, "removeAllDeadWindows: " + win);
                 }
                 // Set mDestroying, we don't want any animation or delayed removal here.
@@ -521,6 +532,26 @@
         }
     }
 
+    boolean isRelaunching() {
+        return mPendingRelaunchCount > 0;
+    }
+
+    void startRelaunching() {
+        if (canFreezeBounds()) {
+            freezeBounds();
+        }
+        mPendingRelaunchCount++;
+    }
+
+    void finishRelaunching() {
+        if (canFreezeBounds()) {
+            unfreezeBounds();
+        }
+        if (mPendingRelaunchCount > 0) {
+            mPendingRelaunchCount--;
+        }
+    }
+
     void addWindow(WindowState w) {
         for (int i = allAppWindows.size() - 1; i >= 0; i--) {
             WindowState candidate = allAppWindows.get(i);
@@ -569,20 +600,26 @@
         }
     }
 
+    private boolean canFreezeBounds() {
+        // For freeform windows, we can't freeze the bounds at the moment because this would make
+        // the resizing unresponsive.
+        return mTask != null && !mTask.inFreeformWorkspace();
+    }
+
     /**
      * Freezes the task bounds. The size of this task reported the app will be fixed to the bounds
      * freezed by {@link Task#prepareFreezingBounds} until {@link #unfreezeBounds} gets called, even
      * if they change in the meantime. If the bounds are already frozen, the bounds will be frozen
      * with a queue.
      */
-    void freezeBounds() {
+    private void freezeBounds() {
         mFrozenBounds.offer(new Rect(mTask.mPreparedFrozenBounds));
     }
 
     /**
      * Unfreezes the previously frozen bounds. See {@link #freezeBounds}.
      */
-    void unfreezeBounds() {
+    private void unfreezeBounds() {
         mFrozenBounds.remove();
         for (int i = windows.size() - 1; i >= 0; i--) {
             final WindowState win = windows.get(i);
@@ -648,7 +685,10 @@
                     pw.print(" startingMoved="); pw.println(startingMoved);
         }
         if (!mFrozenBounds.isEmpty()) {
-            pw.print(prefix); pw.print("mFrozenBounds="); pw.print(mFrozenBounds);
+            pw.print(prefix); pw.print("mFrozenBounds="); pw.println(mFrozenBounds);
+        }
+        if (mPendingRelaunchCount != 0) {
+            pw.print(prefix); pw.print("mPendingRelaunchCount="); pw.println(mPendingRelaunchCount);
         }
     }
 
diff --git a/services/core/java/com/android/server/wm/BoundsAnimationController.java b/services/core/java/com/android/server/wm/BoundsAnimationController.java
index f0efebe..79d3d84 100644
--- a/services/core/java/com/android/server/wm/BoundsAnimationController.java
+++ b/services/core/java/com/android/server/wm/BoundsAnimationController.java
@@ -54,7 +54,8 @@
         private final AnimateBoundsUser mTarget;
         private final Rect mFrom;
         private final Rect mTo;
-        private final Rect mTmpRect;
+        private final Rect mTmpRect = new Rect();
+        private final Rect mTmpTaskBounds = new Rect();
         private final boolean mMoveToFullScreen;
         // True if this this animation was cancelled and will be replaced the another animation from
         // the same {@link #AnimateBoundsUser} target.
@@ -63,17 +64,40 @@
         // {@link #AnimateBoundsUser} target.
         private final boolean mReplacement;
 
+        // Depending on whether we are animating from
+        // a smaller to a larger size
+        private final int mFrozenTaskWidth;
+        private final int mFrozenTaskHeight;
+
         BoundsAnimator(AnimateBoundsUser target, Rect from, Rect to,
                 boolean moveToFullScreen, boolean replacement) {
             super();
             mTarget = target;
             mFrom = from;
             mTo = to;
-            mTmpRect = new Rect();
             mMoveToFullScreen = moveToFullScreen;
             mReplacement = replacement;
             addUpdateListener(this);
             addListener(this);
+
+            // If we are animating from smaller to larger, we want to change the task bounds
+            // to their final size immediately so we can use scaling to make the window
+            // larger. Likewise if we are going from bigger to smaller, we want to wait until
+            // the end so we don't have to upscale from the smaller finished size.
+            if (animatingToLargerSize()) {
+                mFrozenTaskWidth = mTo.width();
+                mFrozenTaskHeight = mTo.height();
+            } else {
+                mFrozenTaskWidth = mFrom.width();
+                mFrozenTaskHeight = mFrom.height();
+            }
+        }
+
+        boolean animatingToLargerSize() {
+            if (mFrom.width() * mFrom.height() > mTo.width() * mTo.height()) {
+                return false;
+            }
+            return true;
         }
 
         @Override
@@ -87,7 +111,13 @@
             if (DEBUG) Slog.d(TAG, "animateUpdate: mTarget=" + mTarget + " mBounds="
                     + mTmpRect + " from=" + mFrom + " mTo=" + mTo + " value=" + value
                     + " remains=" + remains);
-            if (!mTarget.setSize(mTmpRect)) {
+
+            if (remains != 0) {
+                mTmpTaskBounds.set(mTmpRect.left, mTmpRect.top,
+                        mTmpRect.left + mFrozenTaskWidth, mTmpRect.top + mFrozenTaskHeight);
+            }
+
+            if (!mTarget.setPinnedStackSize(mTmpRect, remains != 0 ? mTmpTaskBounds : null)) {
                 // Whoops, the target doesn't feel like animating anymore. Let's immediately finish
                 // any further animation.
                 animation.cancel();
@@ -99,6 +129,10 @@
         public void onAnimationStart(Animator animation) {
             if (DEBUG) Slog.d(TAG, "onAnimationStart: mTarget=" + mTarget
                     + " mReplacement=" + mReplacement);
+            if (animatingToLargerSize()) {
+                mTarget.setPinnedStackSize(mFrom, mTo);
+            }
+
             if (!mReplacement) {
                 mTarget.onAnimationStart();
             }
@@ -108,6 +142,7 @@
         public void onAnimationEnd(Animator animation) {
             if (DEBUG) Slog.d(TAG, "onAnimationEnd: mTarget=" + mTarget
                     + " mMoveToFullScreen=" + mMoveToFullScreen + " mWillReplace=" + mWillReplace);
+
             finishAnimation();
             if (mMoveToFullScreen && !mWillReplace) {
                 mTarget.moveToFullscreen();
@@ -159,6 +194,12 @@
          * from the hierarchy and is not valid anymore.
          */
         boolean setSize(Rect bounds);
+        /**
+         * Behaves as setSize, but freezes the bounds of any tasks in the target at taskBounds,
+         * to allow for more flexibility during resizing. Only
+         * works for the pinned stack at the moment.
+         */
+        boolean setPinnedStackSize(Rect bounds, Rect taskBounds);
 
         void onAnimationStart();
 
diff --git a/services/core/java/com/android/server/wm/DimLayer.java b/services/core/java/com/android/server/wm/DimLayer.java
index fc5d8ce..95be233 100644
--- a/services/core/java/com/android/server/wm/DimLayer.java
+++ b/services/core/java/com/android/server/wm/DimLayer.java
@@ -84,10 +84,13 @@
     /** The user of this dim layer. */
     private final DimLayerUser mUser;
 
-    DimLayer(WindowManagerService service, DimLayerUser user, int displayId) {
+    private final String mName;
+
+    DimLayer(WindowManagerService service, DimLayerUser user, int displayId, String name) {
         mUser = user;
         mDisplayId = displayId;
         mService = service;
+        mName = name;
         if (DEBUG_DIM_LAYER) Slog.v(TAG, "Ctor: displayId=" + displayId);
     }
 
@@ -100,7 +103,7 @@
                     16, 16, PixelFormat.OPAQUE,
                     SurfaceControl.FX_SURFACE_DIM | SurfaceControl.HIDDEN);
             } else {
-                mDimSurface = new SurfaceControl(service.mFxSession, TAG,
+                mDimSurface = new SurfaceControl(service.mFxSession, mName,
                     16, 16, PixelFormat.OPAQUE,
                     SurfaceControl.FX_SURFACE_DIM | SurfaceControl.HIDDEN);
             }
diff --git a/services/core/java/com/android/server/wm/DimLayerController.java b/services/core/java/com/android/server/wm/DimLayerController.java
index 6d1cec4..97d0ae0 100644
--- a/services/core/java/com/android/server/wm/DimLayerController.java
+++ b/services/core/java/com/android/server/wm/DimLayerController.java
@@ -10,6 +10,8 @@
 import android.util.Slog;
 import android.util.TypedValue;
 
+import com.android.server.wm.DimLayer.DimLayerUser;
+
 import java.io.PrintWriter;
 
 /**
@@ -18,7 +20,8 @@
  * as well as other use cases (such as dimming above a dead window).
  */
 class DimLayerController {
-    private static final String TAG = TAG_WITH_CLASS_NAME ? "DimLayerController" : TAG_WM;
+    private static final String TAG_LOCAL = "DimLayerController";
+    private static final String TAG = TAG_WITH_CLASS_NAME ? TAG_LOCAL : TAG_WM;
 
     /** Amount of time in milliseconds to animate the dim surface from one value to another,
      * when no window animation is driving it. */
@@ -63,7 +66,8 @@
                     newDimLayer = state.dimLayer;
                 } else {
                     // Create new full screen dim layer.
-                    newDimLayer = new DimLayer(mDisplayContent.mService, dimLayerUser, displayId);
+                    newDimLayer = new DimLayer(mDisplayContent.mService, dimLayerUser, displayId,
+                            getDimLayerTag(dimLayerUser));
                 }
                 dimLayerUser.getDimBounds(mTmpBounds);
                 newDimLayer.setBounds(mTmpBounds);
@@ -73,7 +77,8 @@
             }
         } else {
             newDimLayer = (state.dimLayer == null || previousFullscreen)
-                    ? new DimLayer(mDisplayContent.mService, dimLayerUser, displayId)
+                    ? new DimLayer(mDisplayContent.mService, dimLayerUser, displayId,
+                            getDimLayerTag(dimLayerUser))
                     : state.dimLayer;
             dimLayerUser.getDimBounds(mTmpBounds);
             newDimLayer.setBounds(mTmpBounds);
@@ -81,6 +86,10 @@
         state.dimLayer = newDimLayer;
     }
 
+    private static String getDimLayerTag(DimLayerUser dimLayerUser) {
+        return TAG_LOCAL + "/" + dimLayerUser.toShortString();
+    }
+
     private DimLayerState getOrCreateDimLayerState(DimLayer.DimLayerUser dimLayerUser) {
         if (DEBUG_DIM_LAYER) Slog.v(TAG, "getOrCreateDimLayerState, dimLayerUser="
                 + dimLayerUser.toShortString());
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 73cea52..5212211 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -29,6 +29,7 @@
 import android.app.ActivityManager.StackId;
 import android.graphics.Rect;
 import android.graphics.Region;
+import android.graphics.Region.Op;
 import android.util.DisplayMetrics;
 import android.util.Slog;
 import android.view.Display;
@@ -426,6 +427,10 @@
             win.getTouchableRegion(mTmpRegion);
             mTouchExcludeRegion.op(mTmpRegion, Region.Op.UNION);
         }
+        if (getDockedStackVisibleForUserLocked() != null) {
+            mDividerControllerLocked.getTouchRegion(mTmpRect);
+            mTouchExcludeRegion.op(mTmpRegion, Op.UNION);
+        }
         if (mTapDetector != null) {
             mTapDetector.setTouchExcludeRegion(mTouchExcludeRegion, mNonResizeableRegion);
         }
diff --git a/services/core/java/com/android/server/wm/DockedStackDividerController.java b/services/core/java/com/android/server/wm/DockedStackDividerController.java
index b6aa3f2..36e8bbb 100644
--- a/services/core/java/com/android/server/wm/DockedStackDividerController.java
+++ b/services/core/java/com/android/server/wm/DockedStackDividerController.java
@@ -16,6 +16,17 @@
 
 package com.android.server.wm;
 
+import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
+import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
+import static android.view.WindowManager.DOCKED_BOTTOM;
+import static android.view.WindowManager.DOCKED_LEFT;
+import static android.view.WindowManager.DOCKED_RIGHT;
+import static android.view.WindowManager.DOCKED_TOP;
+import static com.android.server.wm.AppTransition.DEFAULT_APP_TRANSITION_DURATION;
+import static com.android.server.wm.AppTransition.TOUCH_RESPONSE_INTERPOLATOR;
+import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
+import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
+
 import android.content.Context;
 import android.graphics.Rect;
 import android.os.RemoteCallbackList;
@@ -30,19 +41,6 @@
 
 import com.android.server.wm.DimLayer.DimLayerUser;
 
-import java.util.ArrayList;
-
-import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
-import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
-import static android.view.WindowManager.DOCKED_BOTTOM;
-import static android.view.WindowManager.DOCKED_LEFT;
-import static android.view.WindowManager.DOCKED_RIGHT;
-import static android.view.WindowManager.DOCKED_TOP;
-import static com.android.server.wm.AppTransition.DEFAULT_APP_TRANSITION_DURATION;
-import static com.android.server.wm.AppTransition.TOUCH_RESPONSE_INTERPOLATOR;
-import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
-import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
-
 /**
  * Keeps information about the docked stack divider.
  */
@@ -97,6 +95,7 @@
     private long mAnimationDuration;
     private final Interpolator mMinimizedDockInterpolator;
     private float mMaximizeMeetFraction;
+    private final Rect mTouchRegion = new Rect();
 
     DockedStackDividerController(WindowManagerService service, DisplayContent displayContent) {
         mService = service;
@@ -106,7 +105,8 @@
                 com.android.internal.R.dimen.docked_stack_divider_thickness);
         mDividerInsets = context.getResources().getDimensionPixelSize(
                 com.android.internal.R.dimen.docked_stack_divider_insets);
-        mDimLayer = new DimLayer(displayContent.mService, this, displayContent.getDisplayId());
+        mDimLayer = new DimLayer(displayContent.mService, this, displayContent.getDisplayId(),
+                "DockedStackDim");
         mMinimizedDockInterpolator = AnimationUtils.loadInterpolator(
                 context, android.R.interpolator.fast_out_slow_in);
     }
@@ -130,6 +130,15 @@
         }
     }
 
+    void setTouchRegion(Rect touchRegion) {
+        mTouchRegion.set(touchRegion);
+    }
+
+    void getTouchRegion(Rect outRegion) {
+        outRegion.set(mTouchRegion);
+        outRegion.offset(mWindow.getFrameLw().left, mWindow.getFrameLw().top);
+    }
+
     private void resetDragResizingChangeReported() {
         final WindowList windowList = mDisplayContent.getWindowList();
         for (int i = windowList.size() - 1; i >= 0; i--) {
@@ -247,8 +256,9 @@
 
     void setResizeDimLayer(boolean visible, int targetStackId, float alpha) {
         SurfaceControl.openTransaction();
-        TaskStack stack = mDisplayContent.mService.mStackIdToStack.get(targetStackId);
-        boolean visibleAndValid = visible && stack != null;
+        final TaskStack stack = mDisplayContent.mService.mStackIdToStack.get(targetStackId);
+        final TaskStack dockedStack = mDisplayContent.getDockedStackLocked();
+        boolean visibleAndValid = visible && stack != null && dockedStack != null;
         if (visibleAndValid) {
             stack.getDimBounds(mTmpRect);
             if (mTmpRect.height() > 0 && mTmpRect.width() > 0) {
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index c7b5599..f097eb2 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -19,6 +19,7 @@
 import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
 import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
 import static android.app.ActivityManager.StackId.FULLSCREEN_WORKSPACE_STACK_ID;
+import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
 import static android.app.ActivityManager.StackId.HOME_STACK_ID;
 import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZEABLE;
 import static android.content.pm.ActivityInfo.RESIZE_MODE_UNRESIZEABLE;
@@ -685,6 +686,10 @@
                 && mStack != null && StackId.isTaskResizeableByDockedStack(mStack.mStackId);
     }
 
+    boolean isFloating() {
+        return StackId.tasksAreFloating(mStack.mStackId);
+    }
+
     /**
      * Whether the task should be treated as if it's docked. Returns true if the task
      * is currently in docked workspace, or it's side-by-side to a docked task.
diff --git a/services/core/java/com/android/server/wm/TaskPositioner.java b/services/core/java/com/android/server/wm/TaskPositioner.java
index f7035c5..92701de 100644
--- a/services/core/java/com/android/server/wm/TaskPositioner.java
+++ b/services/core/java/com/android/server/wm/TaskPositioner.java
@@ -60,7 +60,8 @@
 import java.lang.annotation.RetentionPolicy;
 
 class TaskPositioner implements DimLayer.DimLayerUser {
-    private static final String TAG = TAG_WITH_CLASS_NAME ? "TaskPositioner" : TAG_WM;
+    private static final String TAG_LOCAL = "TaskPositioner";
+    private static final String TAG = TAG_WITH_CLASS_NAME ? TAG_LOCAL : TAG_WM;
 
     // The margin the pointer position has to be within the side of the screen to be
     // considered at the side of the screen.
@@ -287,7 +288,7 @@
         }
         mService.pauseRotationLocked();
 
-        mDimLayer = new DimLayer(mService, this, mDisplay.getDisplayId());
+        mDimLayer = new DimLayer(mService, this, mDisplay.getDisplayId(), TAG_LOCAL);
         mSideMargin = dipToPixel(SIDE_MARGIN_DIP, mDisplayMetrics);
         mMinVisibleWidth = dipToPixel(MINIMUM_VISIBLE_WIDTH_IN_DP, mDisplayMetrics);
         mMinVisibleHeight = dipToPixel(MINIMUM_VISIBLE_HEIGHT_IN_DP, mDisplayMetrics);
diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java
index 07a6514..60b2e4a 100644
--- a/services/core/java/com/android/server/wm/TaskStack.java
+++ b/services/core/java/com/android/server/wm/TaskStack.java
@@ -111,6 +111,17 @@
     private float mMinimizeAmount;
     private final int mDockedStackMinimizeThickness;
 
+    // If this is true, the task will be down or upscaled
+    // to perfectly fit the region it would have been cropped
+    // to.
+    private boolean mForceScaleToCrop = false;
+    // By default, movement animations are applied to all
+    // window movement. If this is true, animations will not
+    // be applied within this stack. This is useful for example
+    // if the windows are moving as the result of a stack animation,
+    // in which case a second window animation would cause jitter.
+    private boolean mFreezeMovementAnimations = false;
+
     TaskStack(WindowManagerService service, int stackId) {
         mService = service;
         mStackId = stackId;
@@ -137,9 +148,7 @@
     boolean setBounds(
             Rect stackBounds, SparseArray<Configuration> configs, SparseArray<Rect> taskBounds,
             SparseArray<Rect> taskTempInsetBounds) {
-        if (!setBounds(stackBounds)) {
-            return false;
-        }
+        setBounds(stackBounds);
 
         // Update bounds of containing tasks.
         for (int taskNdx = mTasks.size() - 1; taskNdx >= 0; --taskNdx) {
@@ -574,7 +583,8 @@
         }
 
         mDisplayContent = displayContent;
-        mAnimationBackgroundSurface = new DimLayer(mService, this, mDisplayContent.getDisplayId());
+        mAnimationBackgroundSurface = new DimLayer(mService, this, mDisplayContent.getDisplayId(),
+                "animation background stackId=" + mStackId);
 
         Rect bounds = null;
         final TaskStack dockedStack = mService.mStackIdToStack.get(DOCKED_STACK_ID);
@@ -596,13 +606,6 @@
         }
 
         updateDisplayInfo(bounds);
-
-        if (mStackId == DOCKED_STACK_ID) {
-            // Attaching a docked stack to the display affects the size of all other static
-            // stacks since the docked stack occupies a dedicated region on screen.
-            // Resize existing static stacks so they are pushed to the side of the docked stack.
-            resizeNonDockedStacks(!FULLSCREEN, mBounds);
-        }
     }
 
     void getStackDockedModeBoundsLocked(Rect outBounds, boolean ignoreVisibility) {
@@ -711,36 +714,6 @@
         DockedDividerUtils.sanitizeStackBounds(outBounds, !dockOnTopOrLeft);
     }
 
-    /** Resizes all non-docked stacks in the system to either fullscreen or the appropriate size
-     * based on the presence of a docked stack.
-     * @param fullscreen If true the stacks will be resized to fullscreen, else they will be
-     *                   resized to the appropriate size based on the presence of a docked stack.
-     * @param dockedBounds Bounds of the docked stack.
-     */
-    private void resizeNonDockedStacks(boolean fullscreen, Rect dockedBounds) {
-        // Not using mTmpRect because we are posting the object in a message.
-        final Rect bounds = new Rect();
-        mDisplayContent.getLogicalDisplayRect(bounds);
-        if (!fullscreen) {
-            final boolean dockedOnTopOrLeft = mService.mDockedStackCreateMode
-                    == DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT;
-            getStackDockedModeBounds(bounds, bounds, FULLSCREEN_WORKSPACE_STACK_ID, dockedBounds,
-                    mDisplayContent.mDividerControllerLocked.getContentWidth(), dockedOnTopOrLeft);
-        }
-
-        final int count = mService.mStackIdToStack.size();
-        for (int i = 0; i < count; i++) {
-            final TaskStack otherStack = mService.mStackIdToStack.valueAt(i);
-            final int otherStackId = otherStack.mStackId;
-            if (StackId.isResizeableByDockedStack(otherStackId)
-                    && !otherStack.mBounds.equals(bounds)) {
-                mService.mH.sendMessage(
-                        mService.mH.obtainMessage(RESIZE_STACK, otherStackId,
-                                1 /*allowResizeInDockedMode*/, fullscreen ? null : bounds));
-            }
-        }
-    }
-
     void resetDockedStackToMiddle() {
         if (mStackId != DOCKED_STACK_ID) {
             throw new IllegalStateException("Not a docked stack=" + this);
@@ -774,12 +747,6 @@
             mService.mWindowPlacerLocked.requestTraversal();
         }
 
-        if (mStackId == DOCKED_STACK_ID) {
-            // Docked stack was detached from the display, so we no longer need to restrict the
-            // region of the screen other static stacks occupy. Go ahead and make them fullscreen.
-            resizeNonDockedStacks(FULLSCREEN, null);
-        }
-
         close();
     }
 
@@ -1128,17 +1095,38 @@
         return true;
     }
 
+    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) {
+            // I don't believe you.
+        }
+        return true;
+    }
+
     @Override  // AnimatesBounds
     public void onAnimationStart() {
         synchronized (mService.mWindowMap) {
-            setDragResizingLocked(true);
+            mFreezeMovementAnimations = true;
+            mForceScaleToCrop = true;
         }
     }
 
     @Override  // AnimatesBounds
     public void onAnimationEnd() {
         synchronized (mService.mWindowMap) {
-            setDragResizingLocked(false);
+            mFreezeMovementAnimations = false;
+            mForceScaleToCrop = false;
             mService.requestTraversal();
         }
         if (mStackId == PINNED_STACK_ID) {
@@ -1163,4 +1151,12 @@
     public void getFullScreenBounds(Rect bounds) {
         getDisplayContent().getContentRect(bounds);
     }
+
+    public boolean getFreezeMovementAnimations() {
+        return mFreezeMovementAnimations;
+    }
+
+    public boolean getForceScaleToCrop() {
+        return mForceScaleToCrop;
+    }
 }
diff --git a/services/core/java/com/android/server/wm/WindowAnimator.java b/services/core/java/com/android/server/wm/WindowAnimator.java
index 85bddee..4698e4e 100644
--- a/services/core/java/com/android/server/wm/WindowAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowAnimator.java
@@ -771,6 +771,7 @@
         }
 
         mService.destroyPreservedSurfaceLocked();
+        mService.mWindowPlacerLocked.destroyPendingSurfaces();
 
         if (DEBUG_WINDOW_TRACE) {
             Slog.i(TAG, "!!! animate: exit mAnimating=" + mAnimating
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index daeecfc..304449d 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -20,9 +20,13 @@
 import android.animation.ValueAnimator;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.app.ActivityManagerInternal;
 import android.app.ActivityManagerNative;
 import android.app.AppOpsManager;
 import android.app.IActivityManager;
+import android.app.Notification;
+import android.app.NotificationManager;
+import android.app.PendingIntent;
 import android.app.admin.DevicePolicyManager;
 import android.content.BroadcastReceiver;
 import android.content.ContentResolver;
@@ -117,8 +121,10 @@
 import android.view.inputmethod.InputMethodManagerInternal;
 import android.widget.Toast;
 
+import com.android.internal.R;
 import com.android.internal.app.IAssistScreenshotReceiver;
 import com.android.internal.os.IResultReceiver;
+import com.android.internal.policy.IShortcutService;
 import com.android.internal.util.FastPrintWriter;
 import com.android.internal.view.IInputContext;
 import com.android.internal.view.IInputMethodClient;
@@ -362,6 +368,7 @@
     final WindowManagerPolicy mPolicy = new PhoneWindowManager();
 
     final IActivityManager mActivityManager;
+    final ActivityManagerInternal mAmInternal;
 
     final AppOpsManager mAppOps;
 
@@ -902,6 +909,7 @@
         mAppTransition.registerListenerLocked(mActivityManagerAppTransitionNotifier);
 
         mActivityManager = ActivityManagerNative.getDefault();
+        mAmInternal = LocalServices.getService(ActivityManagerInternal.class);
         mAppOps = (AppOpsManager)context.getSystemService(Context.APP_OPS_SERVICE);
         AppOpsManager.OnOpChangedInternalListener opListener =
                 new AppOpsManager.OnOpChangedInternalListener() {
@@ -2143,12 +2151,15 @@
 
     void removeWindowLocked(WindowState win) {
         win.mWindowRemovalAllowed = true;
+        if (DEBUG_ADD_REMOVE) Slog.v(TAG,
+                "removeWindowLocked: " + win + " callers=" + Debug.getCallers(4));
+
         final boolean startingWindow = win.mAttrs.type == TYPE_APPLICATION_STARTING;
         if (startingWindow) {
             if (DEBUG_STARTING_WINDOW) Slog.d(TAG_WM, "Starting window removed " + win);
         }
 
-        if (localLOGV || DEBUG_FOCUS || DEBUG_FOCUS_LIGHT && win==mCurrentFocus) Slog.v(
+        if (localLOGV || DEBUG_FOCUS || DEBUG_FOCUS_LIGHT && win == mCurrentFocus) Slog.v(
                 TAG_WM, "Remove " + win + " client="
                 + Integer.toHexString(System.identityHashCode(win.mClient.asBinder()))
                 + ", surfaceController=" + win.mWinAnimator.mSurfaceController + " Callers="
@@ -2333,6 +2344,7 @@
                 mTokenMap.remove(token.token);
             } else if (atoken != null) {
                 atoken.firstWindowDrawn = false;
+                atoken.allDrawn = false;
             }
         }
 
@@ -4015,10 +4027,8 @@
 
     public void removeAppStartingWindow(IBinder token) {
         synchronized (mWindowMap) {
-            AppWindowToken wtoken = mTokenMap.get(token).appWindowToken;
-            if (wtoken.startingWindow != null) {
-                scheduleRemoveStartingWindowLocked(wtoken);
-            }
+            final AppWindowToken wtoken = mTokenMap.get(token).appWindowToken;
+            scheduleRemoveStartingWindowLocked(wtoken);
         }
     }
 
@@ -4192,7 +4202,7 @@
     }
 
     @Override
-    public void notifyAppStopped(IBinder token) {
+    public void notifyAppStopped(IBinder token, boolean stopped) {
         if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
                 "notifyAppStopped()")) {
             throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
@@ -4205,7 +4215,7 @@
                 Slog.w(TAG_WM, "Attempted to set visibility of non-existing app token: " + token);
                 return;
             }
-            wtoken.notifyAppStopped();
+            wtoken.notifyAppStopped(stopped);
         }
     }
 
@@ -4242,8 +4252,32 @@
                 wtoken.appDied = false;
                 wtoken.removeAllWindows();
             } else if (visible) {
+                if (DEBUG_ADD_REMOVE) Slog.v(
+                        TAG_WM, "No longer Stopped: " + wtoken);
                 wtoken.mAppStopped = false;
                 wtoken.setWindowsExiting(false);
+                mOpeningApps.add(wtoken);
+                wtoken.startingMoved = false;
+
+                // If the token is currently hidden (should be the
+                // common case), then we need to set up to wait for
+                // its windows to be ready.
+                if (wtoken.hidden) {
+                    wtoken.allDrawn = false;
+                    wtoken.deferClearAllDrawn = false;
+                    wtoken.waitingToShow = true;
+
+                    if (wtoken.clientHidden) {
+                        // In the case where we are making an app visible
+                        // but holding off for a transition, we still need
+                        // to tell the client to make its windows visible so
+                        // they get drawn.  Otherwise, we will wait on
+                        // performing the transition until all windows have
+                        // been drawn, they never will be, and we are sad.
+                        wtoken.clientHidden = false;
+                        wtoken.sendAppVisibilityToClients();
+                    }
+                }
             }
 
             // If we are preparing an app transition, then delay changing
@@ -4261,29 +4295,7 @@
                 }
                 wtoken.inPendingTransaction = true;
                 if (visible) {
-                    mOpeningApps.add(wtoken);
-                    wtoken.startingMoved = false;
                     wtoken.mEnteringAnimation = true;
-
-                    // If the token is currently hidden (should be the
-                    // common case), then we need to set up to wait for
-                    // its windows to be ready.
-                    if (wtoken.hidden) {
-                        wtoken.allDrawn = false;
-                        wtoken.deferClearAllDrawn = false;
-                        wtoken.waitingToShow = true;
-
-                        if (wtoken.clientHidden) {
-                            // In the case where we are making an app visible
-                            // but holding off for a transition, we still need
-                            // to tell the client to make its windows visible so
-                            // they get drawn.  Otherwise, we will wait on
-                            // performing the transition until all windows have
-                            // been drawn, they never will be, and we are sad.
-                            wtoken.clientHidden = false;
-                            wtoken.sendAppVisibilityToClients();
-                        }
-                    }
                 } else {
                     wtoken.setWindowsExiting(true);
                     mClosingApps.add(wtoken);
@@ -4497,17 +4509,30 @@
     }
 
     void scheduleRemoveStartingWindowLocked(AppWindowToken wtoken) {
+        if (wtoken == null) {
+            return;
+        }
         if (mH.hasMessages(H.REMOVE_STARTING, wtoken)) {
             // Already scheduled.
             return;
         }
-        if (wtoken != null && wtoken.startingWindow != null) {
-            if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, Debug.getCallers(1) +
-                    ": Schedule remove starting " + wtoken + (wtoken != null ?
-                    " startingWindow=" + wtoken.startingWindow : ""));
-            Message m = mH.obtainMessage(H.REMOVE_STARTING, wtoken);
-            mH.sendMessage(m);
+
+        if (wtoken.startingWindow == null) {
+            if (wtoken.startingData != null) {
+                // Starting window has not been added yet, but it is scheduled to be added.
+                // Go ahead and cancel the request.
+                if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM,
+                        "Clearing startingData for token=" + wtoken);
+                wtoken.startingData = null;
+            }
+            return;
         }
+
+        if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, Debug.getCallers(1) +
+                ": Schedule remove starting " + wtoken + (wtoken != null ?
+                " startingWindow=" + wtoken.startingWindow : ""));
+        Message m = mH.obtainMessage(H.REMOVE_STARTING, wtoken);
+        mH.sendMessage(m);
     }
 
     void dumpAppTokensLocked() {
@@ -7448,6 +7473,35 @@
         return mCurrentFocus;
     }
 
+    private void showAuditSafeModeNotification() {
+        PendingIntent pendingIntent = PendingIntent.getActivity(mContext, 0,
+                new Intent(Intent.ACTION_VIEW,
+                           Uri.parse("https://support.google.com/nexus/answer/2852139")), 0);
+
+        String title = mContext.getString(R.string.audit_safemode_notification);
+
+        Notification notification = new Notification.Builder(mContext)
+                .setSmallIcon(com.android.internal.R.drawable.stat_sys_warning)
+                .setWhen(0)
+                .setOngoing(true)
+                .setTicker(title)
+                .setLocalOnly(true)
+                .setPriority(Notification.PRIORITY_HIGH)
+                .setVisibility(Notification.VISIBILITY_PUBLIC)
+                .setColor(mContext.getColor(
+                        com.android.internal.R.color.system_notification_accent_color))
+                .setContentTitle(title)
+                .setContentText(mContext.getString(R.string.audit_safemode_notification_details))
+                .setContentIntent(pendingIntent)
+                .build();
+
+        NotificationManager notificationManager = (NotificationManager) mContext
+                .getSystemService(Context.NOTIFICATION_SERVICE);
+
+        notificationManager.notifyAsUser(null, R.string.audit_safemode_notification, notification,
+                UserHandle.ALL);
+    }
+
     public boolean detectSafeMode() {
         if (!mInputMonitor.waitForInputDevicesReady(
                 INPUT_DEVICES_READY_FOR_SAFE_MODE_DETECTION_TIMEOUT_MILLIS)) {
@@ -7480,6 +7534,7 @@
 
                     if (auditSafeMode >= buildDate) {
                         mSafeMode = true;
+                        showAuditSafeModeNotification();
                     } else {
                         SystemProperties.set(ShutdownThread.REBOOT_SAFEMODE_PROPERTY, "");
                         SystemProperties.set(ShutdownThread.AUDIT_SAFEMODE_PROPERTY, "");
@@ -7606,6 +7661,9 @@
 
         public static final int WINDOW_REPLACEMENT_TIMEOUT = 46;
 
+        public static final int NOTIFY_APP_TRANSITION_STARTING = 47;
+        public static final int NOTIFY_STARTING_WINDOW_DRAWN = 48;
+
         /**
          * Used to denote that an integer field in a message will not be used.
          */
@@ -8203,6 +8261,13 @@
                         token.clearTimedoutReplacesLocked();
                     }
                 }
+                case NOTIFY_APP_TRANSITION_STARTING: {
+                    mAmInternal.notifyAppTransitionStarting(msg.arg1);
+                }
+                break;
+                case NOTIFY_STARTING_WINDOW_DRAWN: {
+                    mAmInternal.notifyStartingWindowDrawn();
+                }
                 break;
             }
             if (DEBUG_WINDOW_TRACE) {
@@ -8752,10 +8817,10 @@
         i -= lastBelow;
         if (i != numRemoved) {
             displayContent.layoutNeeded = true;
-            Slog.w(TAG_WM, "On display=" + displayContent.getDisplayId() + " Rebuild removed " +
-                    numRemoved + " windows but added " + i,
-                    new RuntimeException("here").fillInStackTrace());
-            for (i=0; i<numRemoved; i++) {
+            Slog.w(TAG_WM, "On display=" + displayContent.getDisplayId() + " Rebuild removed "
+                    + numRemoved + " windows but added " + i + " rebuildAppWindowListLocked() "
+                    + " callers=" + Debug.getCallers(10));
+            for (i = 0; i < numRemoved; i++) {
                 WindowState ws = mRebuildTmp[i];
                 if (ws.mRebuilding) {
                     StringWriter sw = new StringWriter();
@@ -9606,8 +9671,8 @@
     public void notifyAppRelaunching(IBinder token) {
         synchronized (mWindowMap) {
             AppWindowToken appWindow = findAppWindowToken(token);
-            if (canFreezeBounds(appWindow)) {
-                appWindow.freezeBounds();
+            if (appWindow != null) {
+                appWindow.startRelaunching();
             }
         }
     }
@@ -9615,20 +9680,12 @@
     public void notifyAppRelaunchingFinished(IBinder token) {
         synchronized (mWindowMap) {
             AppWindowToken appWindow = findAppWindowToken(token);
-            if (canFreezeBounds(appWindow)) {
-                appWindow.unfreezeBounds();
+            if (appWindow != null) {
+                appWindow.finishRelaunching();
             }
         }
     }
 
-    private boolean canFreezeBounds(AppWindowToken appWindow) {
-
-        // For freeform windows, we can't freeze the bounds at the moment because this would make
-        // the resizing unresponsive.
-        return appWindow != null && appWindow.mTask != null
-                && !appWindow.mTask.inFreeformWorkspace();
-    }
-
     @Override
     public int getDockedDividerInsetsLw() {
         return getDefaultDisplayContentLocked().getDockedDividerController().getContentInsets();
@@ -10381,6 +10438,15 @@
     }
 
     @Override
+    public void setDockedStackDividerTouchRegion(Rect touchRegion) {
+        synchronized (mWindowMap) {
+            getDefaultDisplayContentLocked().getDockedDividerController()
+                    .setTouchRegion(touchRegion);
+            setFocusTaskRegionLocked();
+        }
+    }
+
+    @Override
     public void setResizeDimLayer(boolean visible, int targetStackId, float alpha) {
         synchronized (mWindowMap) {
             getDefaultDisplayContentLocked().getDockedDividerController().setResizeDimLayer(
@@ -10580,6 +10646,16 @@
         }
     }
 
+    public void registerShortcutKey(long shortcutCode, IShortcutService shortcutKeyReceiver)
+            throws RemoteException {
+        if (!checkCallingPermission(Manifest.permission.REGISTER_WINDOW_MANAGER_LISTENERS,
+                "registerShortcutKey")) {
+            throw new SecurityException(
+                    "Requires REGISTER_WINDOW_MANAGER_LISTENERS permission");
+        }
+        mPolicy.registerShortcutKey(shortcutCode, shortcutKeyReceiver);
+    }
+
     private final class LocalService extends WindowManagerInternal {
         @Override
         public void requestTraversalFromDisplayManager() {
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 40b6b50..910788e 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -101,6 +101,10 @@
 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
 
 class WindowList extends ArrayList<WindowState> {
+    WindowList() {}
+    WindowList(WindowList windowList) {
+        super(windowList);
+    }
 }
 
 /**
@@ -184,6 +188,10 @@
 
     private Configuration mConfiguration = Configuration.EMPTY;
     private Configuration mOverrideConfig = Configuration.EMPTY;
+    // Represents the changes from our override configuration applied
+    // to the global configuration. This is the only form of configuration
+    // which is suitable for delivery to the client.
+    private Configuration mMergedConfiguration = new Configuration();
     // Sticky answer to isConfigChanged(), remains true until new Configuration is assigned.
     // Used only on {@link #TYPE_KEYGUARD}.
     private boolean mConfigHasChanged;
@@ -434,9 +442,9 @@
     // If not null, the window that will be used to replace the old one. This is being set when
     // the window is added and unset when this window reports its first draw.
     WindowState mReplacingWindow = null;
-
     // Whether this window is being moved via the resize API
     boolean mMovedByResize;
+
     /**
      * Wake lock for drawing.
      * Even though it's slightly more expensive to do so, we will use a separate wake lock
@@ -635,7 +643,7 @@
 
         final Task task = getTask();
         final boolean fullscreenTask = task == null || task.isFullscreen();
-        final boolean freeformWorkspace = task != null && task.inFreeformWorkspace();
+        final boolean windowsAreFloating = task != null && task.isFloating();
 
         if (fullscreenTask || (isChildWindow()
                 && (mAttrs.privateFlags & PRIVATE_FLAG_LAYOUT_CHILD_WINDOW_IN_PARENT_FRAME) != 0)) {
@@ -661,10 +669,10 @@
                 mContainingFrame.top -= mContainingFrame.bottom - cf.bottom;
             }
 
-            if (freeformWorkspace) {
-                // In free form mode we have only to set the rectangle if it wasn't set already. No
-                // need to intersect it with the (visible) "content frame" since it is allowed to
-                // be outside the visible desktop.
+            if (windowsAreFloating) {
+                // In floating modes (e.g. freeform, pinned) we have only to set the rectangle 
+                // if it wasn't set already. No need to intersect it with the (visible) 
+                // "content frame" since it is allowed to be outside the visible desktop.
                 if (mContainingFrame.isEmpty()) {
                     mContainingFrame.set(cf);
                 }
@@ -720,7 +728,7 @@
 
         // Make sure the content and visible frames are inside of the
         // final window frame.
-        if (freeformWorkspace && !mFrame.isEmpty()) {
+        if (windowsAreFloating && !mFrame.isEmpty()) {
             // 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..
@@ -772,9 +780,9 @@
                     Math.min(mStableFrame.bottom, frame.bottom));
         }
 
-        if (!inFreeformWorkspace()) {
-            // Freeform windows can be positioned outside of the display frame, but that is not a
-            // reason to provide them with overscan insets.
+        if (fullscreenTask && !windowsAreFloating) {
+            // Windows that are not fullscreen can be positioned outside of the display frame,
+            // but that is not a reason to provide them with overscan insets.
             mOverscanInsets.set(Math.max(mOverscanFrame.left - frame.left, 0),
                     Math.max(mOverscanFrame.top - frame.top, 0),
                     Math.max(frame.right - mOverscanFrame.right, 0),
@@ -1355,6 +1363,11 @@
         mConfiguration = newConfig;
         mOverrideConfig = newOverrideConfig;
         mConfigHasChanged = false;
+
+        mMergedConfiguration.setTo(newConfig);
+        if (newOverrideConfig != null && newOverrideConfig != Configuration.EMPTY) {
+            mMergedConfiguration.updateFrom(newOverrideConfig);
+        }
     }
 
     void setHasSurface(boolean hasSurface) {
@@ -1616,9 +1629,10 @@
             mTurnOnScreen = true;
         }
         if (isConfigChanged()) {
+            final Configuration newConfig = updateConfiguration();
             if (DEBUG_CONFIGURATION) Slog.i(TAG, "Window " + this + " visible with new config: "
-                    + mService.mCurConfiguration);
-            outConfig.setTo(mService.mCurConfiguration);
+                    + newConfig);
+            outConfig.setTo(newConfig);
         }
     }
 
@@ -1902,6 +1916,12 @@
             mWinAnimator.hide("saved surface");
             mWinAnimator.mDrawState = WindowStateAnimator.NO_SURFACE;
             setHasSurface(false);
+            // The client should have disconnected at this point, but if it doesn't,
+            // we need to make sure it's disconnected. Otherwise when we reuse the surface
+            // the client can't reconnect to the buffer queue, and rendering will fail.
+            if (mWinAnimator.mSurfaceController != null) {
+                mWinAnimator.mSurfaceController.disconnectInTransaction();
+            }
         } else {
             mWinAnimator.destroySurfaceLocked();
         }
@@ -2055,21 +2075,30 @@
         }
     }
 
+    /**
+     * Update our current configurations, based on task configuration.
+     *
+     * @return A configuration suitable for sending to the client.
+     */
+    private Configuration updateConfiguration() {
+        final Task task = getTask();
+        final Configuration overrideConfig =
+            (task != null) ? task.mOverrideConfig : Configuration.EMPTY;
+        final boolean configChanged = isConfigChanged();
+        if ((DEBUG_RESIZE || DEBUG_ORIENTATION || DEBUG_CONFIGURATION) && configChanged) {
+            Slog.i(TAG, "Sending new config to window " + this + ": " +
+                    " / config=" + mService.mCurConfiguration + " overrideConfig=" + overrideConfig);
+        }
+        setConfiguration(mService.mCurConfiguration, overrideConfig);
+        return mMergedConfiguration;
+    }
+
     void reportResized() {
         Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "wm.reportResized_" + getWindowTag());
         try {
             if (DEBUG_RESIZE || DEBUG_ORIENTATION) Slog.v(TAG, "Reporting new frame to " + this
                     + ": " + mCompatFrame);
-            final boolean configChanged = isConfigChanged();
-            final Task task = getTask();
-            final Configuration overrideConfig =
-                    (task != null) ? task.mOverrideConfig : Configuration.EMPTY;
-            if ((DEBUG_RESIZE || DEBUG_ORIENTATION || DEBUG_CONFIGURATION) && configChanged) {
-                Slog.i(TAG, "Sending new config to window " + this + ": "
-                        + " / config="
-                        + mService.mCurConfiguration + " overrideConfig=" + overrideConfig);
-            }
-            setConfiguration(mService.mCurConfiguration, overrideConfig);
+            final Configuration newConfig = isConfigChanged() ? updateConfiguration() : null;
             if (DEBUG_ORIENTATION && mWinAnimator.mDrawState == WindowStateAnimator.DRAW_PENDING)
                 Slog.i(TAG, "Resizing " + this + " WITH DRAW PENDING");
 
@@ -2080,7 +2109,6 @@
             final Rect stableInsets = mLastStableInsets;
             final Rect outsets = mLastOutsets;
             final boolean reportDraw = mWinAnimator.mDrawState == WindowStateAnimator.DRAW_PENDING;
-            final Configuration newConfig = configChanged ? mConfiguration : null;
             if (mAttrs.type != WindowManager.LayoutParams.TYPE_APPLICATION_STARTING
                     && mClient instanceof IWindow.Stub) {
                 // To prevent deadlock simulate one-way call if win.mClient is a local object.
@@ -2229,7 +2257,7 @@
         // background.
         return (mDisplayContent.mDividerControllerLocked.isResizing()
                         || mAppToken != null && !mAppToken.mFrozenBounds.isEmpty()) &&
-                !task.inFreeformWorkspace() && isVisibleLw();
+                !task.inFreeformWorkspace() && !isGoneForLayoutLw();
 
     }
 
@@ -2479,7 +2507,8 @@
         final int ph = mContainingFrame.height();
         final Task task = getTask();
         final boolean nonFullscreenTask = task != null && !task.isFullscreen();
-
+        final boolean fitToDisplay = task != null &&
+            !task.isFloating();
         float x, y;
         int w,h;
 
@@ -2536,7 +2565,17 @@
                 (int) (y + mAttrs.verticalMargin * ph), mFrame);
 
         // Now make sure the window fits in the overall display frame.
-        Gravity.applyDisplay(mAttrs.gravity, mDisplayFrame, mFrame);
+        if (fitToDisplay) {
+            Gravity.applyDisplay(mAttrs.gravity, mDisplayFrame, mFrame);
+        }
+
+        // We need to make sure we update the CompatFrame as it is used for
+        // cropping decisions, etc, on systems where we lack a decor layer.
+        mCompatFrame.set(mFrame);
+        if (mEnforceSizeCompat) {
+            // See comparable block in computeFrameLw.
+            mCompatFrame.scale(mInvGlobalScale);
+        }
     }
 
     boolean isChildWindow() {
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index c623047..bf8a62e 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -20,6 +20,7 @@
 import static android.view.WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
 import static android.view.WindowManager.LayoutParams.FLAG_SCALED;
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ADD_REMOVE;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ANIM;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYERS;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT_REPEATS;
@@ -433,9 +434,12 @@
                 + " remove=" + mWin.mRemoveOnExit
                 + " windowAnimating=" + isWindowAnimating());
 
-        final int N = mWin.mChildWindows.size();
-        for (int i=0; i<N; i++) {
-            mWin.mChildWindows.get(i).mWinAnimator.finishExit();
+        if (!mWin.mChildWindows.isEmpty()) {
+            // Copying to a different list as multiple children can be removed.
+            final WindowList childWindows = new WindowList(mWin.mChildWindows);
+            for (int i = childWindows.size() - 1; i >= 0; i--) {
+                childWindows.get(i).mWinAnimator.finishExit();
+            }
         }
 
         if (mEnteringAnimation) {
@@ -467,9 +471,8 @@
             return;
         }
 
-        if (WindowManagerService.localLOGV) Slog.v(
-                TAG, "Exit animation finished in " + this
-                + ": remove=" + mWin.mRemoveOnExit);
+        if (WindowManagerService.localLOGV || DEBUG_ADD_REMOVE) Slog.v(TAG,
+                "Exit animation finished in " + this + ": remove=" + mWin.mRemoveOnExit);
 
 
         mWin.mDestroying = true;
@@ -1115,11 +1118,11 @@
         }
     }
 
-    void updateSurfaceWindowCrop(final boolean recoveringMemory) {
+    Rect calculateSurfaceWindowCrop() {
         final WindowState w = mWin;
         final DisplayContent displayContent = w.getDisplayContent();
         if (displayContent == null) {
-            return;
+            return null;
         }
         final DisplayInfo displayInfo = displayContent.getDisplayInfo();
         if (DEBUG_WINDOW_CROP) Slog.d(TAG, "Updating crop for window: " + w + ", " + "mLastCrop=" +
@@ -1187,7 +1190,7 @@
         clipRect.offset(attrs.surfaceInsets.left, attrs.surfaceInsets.top);
 
         adjustCropToStackBounds(w, clipRect, isFreeformResizing);
-        if (DEBUG_WINDOW_CROP) Slog.d(TAG, "Clip rect after stack adjustment=" + mClipRect);
+        if (DEBUG_WINDOW_CROP) Slog.d(TAG, "Clip rect after stack adjustment=" + clipRect);
 
         w.transformFromScreenToSurfaceSpace(clipRect);
 
@@ -1196,6 +1199,10 @@
             clipRect.setEmpty();
         }
 
+        return clipRect;
+    }
+
+    void updateSurfaceWindowCrop(Rect clipRect, boolean recoveringMemory) {
         if (!clipRect.equals(mLastClipRect)) {
             mLastClipRect.set(clipRect);
             mSurfaceController.setCropInTransaction(clipRect, recoveringMemory);
@@ -1223,6 +1230,11 @@
             return;
         }
 
+        final WindowState winShowWhenLocked = (WindowState) mPolicy.getWinShowWhenLockedLw();
+        if (w == winShowWhenLocked) {
+            return;
+        }
+
         final TaskStack stack = task.mStack;
         stack.getDimBounds(mTmpStackBounds);
         // When we resize we use the big surface approach, which means we can't trust the
@@ -1232,6 +1244,7 @@
                 w.mFrame.left + mWin.mXOffset - w.getAttrs().surfaceInsets.left;
         final int frameY = isFreeformResizing ? (int) mSurfaceController.getY() :
                 w.mFrame.top + mWin.mYOffset - w.getAttrs().surfaceInsets.top;
+
         // We need to do some acrobatics with surface position, because their clip region is
         // relative to the inside of the surface, but the stack bounds aren't.
         clipRect.left = Math.max(0,
@@ -1246,14 +1259,44 @@
 
     void setSurfaceBoundariesLocked(final boolean recoveringMemory) {
         final WindowState w = mWin;
+        final Task task = w.getTask();
 
         mTmpSize.set(w.mShownPosition.x, w.mShownPosition.y, 0, 0);
         calculateSurfaceBounds(w, w.getAttrs());
 
-        mSurfaceController.setPositionInTransaction(mTmpSize.left, mTmpSize.top, recoveringMemory);
+        float extraHScale = (float) 1.0;
+        float extraVScale = (float) 1.0;
 
-        mSurfaceController.setMatrixInTransaction(mDsDx * w.mHScale, mDtDx * w.mVScale,
-                mDsDy * w.mHScale, mDtDy * w.mVScale, recoveringMemory);
+        final Rect crop = calculateSurfaceWindowCrop();
+        if (task != null && task.mStack.getForceScaleToCrop()) {
+            extraHScale = crop.width() / (float)mTmpSize.width();
+            extraVScale = crop.height() / (float)mTmpSize.height();
+
+            // In the case of ForceScaleToCrop we scale entire tasks together,
+            // and so we need to scale our offsets relative to the task bounds
+            // or parent and child windows would fall out of alignment.
+            int posX = (int) (mTmpSize.left - w.mAttrs.x * (1 - extraHScale));
+            int posY = (int) (mTmpSize.top - w.mAttrs.y * (1 - extraVScale));
+            posX += w.getAttrs().surfaceInsets.left * (1 - extraHScale);
+            posY += w.getAttrs().surfaceInsets.top * (1 - extraVScale);
+            mSurfaceController.setPositionInTransaction(posX, posY, recoveringMemory);
+
+            // Since we are scaled to fit in our previously desired crop, we can now
+            // expose the whole window in buffer space, and not risk extending
+            // past where the system would have cropped us
+            crop.set(0, 0, mTmpSize.width(), mTmpSize.height());
+            updateSurfaceWindowCrop(crop, recoveringMemory);
+        } else {
+            mSurfaceController.setPositionInTransaction(mTmpSize.left, mTmpSize.top,
+                    recoveringMemory);
+            updateSurfaceWindowCrop(crop, recoveringMemory);
+        }
+
+
+        mSurfaceController.setMatrixInTransaction(mDsDx * w.mHScale * extraHScale,
+                mDtDx * w.mVScale * extraVScale,
+                mDsDy * w.mHScale * extraHScale,
+                mDtDy * w.mVScale * extraVScale, recoveringMemory);
         mSurfaceResized = mSurfaceController.setSizeInTransaction(
                 mTmpSize.width(), mTmpSize.height(),
                 recoveringMemory);
@@ -1265,7 +1308,6 @@
             w.applyDimLayerIfNeeded();
         }
 
-        updateSurfaceWindowCrop(recoveringMemory);
     }
 
     void prepareSurfaceLocked(final boolean recoveringMemory) {
@@ -1404,7 +1446,7 @@
             SurfaceControl.openTransaction();
             mSurfaceController.setPositionInTransaction(mWin.mFrame.left + left,
                     mWin.mFrame.top + top, false);
-            updateSurfaceWindowCrop(false);
+            updateSurfaceWindowCrop(calculateSurfaceWindowCrop(), false);
         } catch (RuntimeException e) {
             Slog.w(TAG, "Error positioning surface of " + mWin
                     + " pos=(" + left + "," + top + ")", e);
diff --git a/services/core/java/com/android/server/wm/WindowSurfaceController.java b/services/core/java/com/android/server/wm/WindowSurfaceController.java
index 2972a24..fb07512 100644
--- a/services/core/java/com/android/server/wm/WindowSurfaceController.java
+++ b/services/core/java/com/android/server/wm/WindowSurfaceController.java
@@ -138,7 +138,7 @@
 
     void destroyInTransaction() {
         //        if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) {
-        Slog.i(TAG, "Destroying surface " + this + " called by " + Debug.getCallers(4));
+        Slog.i(TAG, "Destroying surface " + this + " called by " + Debug.getCallers(8));
         //        }
         try {
             if (mSurfaceControl != null) {
@@ -152,6 +152,20 @@
         }
     }
 
+    void disconnectInTransaction() {
+        if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) {
+            Slog.i(TAG, "Disconnecting client: " + this);
+        }
+
+        try {
+            if (mSurfaceControl != null) {
+                mSurfaceControl.disconnect();
+            }
+        } catch (RuntimeException e) {
+            Slog.w(TAG, "Error disconnecting surface in: " + this, e);
+        }
+    }
+
     void setCropInTransaction(Rect clipRect, boolean recoveringMemory) {
         if (SHOW_TRANSACTIONS) logSurface(
                 "CROP " + clipRect.toShortString(), null);
diff --git a/services/core/java/com/android/server/wm/WindowSurfacePlacer.java b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
index f705df8..8ada2f1 100644
--- a/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
+++ b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
@@ -1,5 +1,9 @@
 package com.android.server.wm;
 
+import static android.app.ActivityManagerInternal.APP_TRANSITION_SAVED_SURFACE;
+import static android.app.ActivityManagerInternal.APP_TRANSITION_STARTING_WINDOW;
+import static android.app.ActivityManagerInternal.APP_TRANSITION_TIMEOUT;
+import static android.app.ActivityManagerInternal.APP_TRANSITION_WINDOWS_DRAWN;
 import static android.view.WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;
 import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
@@ -120,6 +124,8 @@
     }
     private final LayerAndToken mTmpLayerAndToken = new LayerAndToken();
 
+    private final ArrayList<SurfaceControl> mPendingDestroyingSurfaces = new ArrayList<>();
+
     public WindowSurfacePlacer(WindowManagerService service) {
         mService = service;
         mWallpaperControllerLocked = mService.mWallpaperControllerLocked;
@@ -537,6 +543,7 @@
         mService.enableScreenIfNeededLocked();
 
         mService.scheduleAnimationLocked();
+        mService.mWindowPlacerLocked.destroyPendingSurfaces();
 
         if (DEBUG_WINDOW_TRACE) Slog.e(TAG,
                 "performSurfacePlacementInner exit: animating=" + mService.mAnimator.isAnimating());
@@ -646,6 +653,7 @@
 
             for (int i = windows.size() - 1; i >= 0; i--) {
                 WindowState w = windows.get(i);
+                final Task task = w.getTask();
                 final boolean obscuredChanged = w.mObscured != mObscured;
 
                 // Update effect.
@@ -678,7 +686,8 @@
                     final boolean adjustedForMinimizedDockedStack = w.getTask() != null &&
                             w.getTask().mStack.isAdjustedForMinimizedDockedStack();
                     if ((w.mAttrs.privateFlags & PRIVATE_FLAG_NO_MOVE_ANIMATION) == 0
-                            && !w.isDragResizing() && !adjustedForMinimizedDockedStack) {
+                            && !w.isDragResizing() && !adjustedForMinimizedDockedStack
+                            && (task == null || !w.getTask().mStack.getFreezeMovementAnimations())) {
                         winAnimator.setMoveAnimation(left, top);
                     }
 
@@ -782,6 +791,7 @@
                                 }
                             }
                         } else if (w.isDrawnLw()) {
+                            mService.mH.sendEmptyMessage(NOTIFY_STARTING_WINDOW_DRAWN);
                             atoken.startingDisplayed = true;
                         }
                     }
@@ -1262,6 +1272,7 @@
                 "Checking " + appsCount + " opening apps (frozen="
                         + mService.mDisplayFrozen + " timeout="
                         + mService.mAppTransition.isTimeout() + ")...");
+        int reason = APP_TRANSITION_TIMEOUT;
         if (!mService.mAppTransition.isTimeout()) {
             for (int i = 0; i < appsCount; i++) {
                 AppWindowToken wtoken = mService.mOpeningApps.valueAt(i);
@@ -1269,13 +1280,25 @@
                         "Check opening app=" + wtoken + ": allDrawn="
                         + wtoken.allDrawn + " startingDisplayed="
                         + wtoken.startingDisplayed + " startingMoved="
-                        + wtoken.startingMoved);
+                        + wtoken.startingMoved + " isRelaunching()="
+                        + wtoken.isRelaunching());
 
+                if (wtoken.isRelaunching()) {
+                    return false;
+                }
+
+                final boolean drawnBeforeRestoring = wtoken.allDrawn;
                 wtoken.restoreSavedSurfaces();
 
                 if (!wtoken.allDrawn && !wtoken.startingDisplayed && !wtoken.startingMoved) {
                     return false;
                 }
+                if (wtoken.allDrawn) {
+                    reason = drawnBeforeRestoring ? APP_TRANSITION_WINDOWS_DRAWN
+                            : APP_TRANSITION_SAVED_SURFACE;
+                } else {
+                    reason = APP_TRANSITION_STARTING_WINDOW;
+                }
             }
 
             // We also need to wait for the specs to be fetched, if needed.
@@ -1285,9 +1308,15 @@
             }
 
             // If the wallpaper is visible, we need to check it's ready too.
-            return !mWallpaperControllerLocked.isWallpaperVisible() ||
+            boolean wallpaperReady = !mWallpaperControllerLocked.isWallpaperVisible() ||
                     mWallpaperControllerLocked.wallpaperTransitionReady();
+            if (wallpaperReady) {
+                mService.mH.obtainMessage(NOTIFY_APP_TRANSITION_STARTING, reason, 0).sendToTarget();
+                return true;
+            }
+            return false;
         }
+        mService.mH.obtainMessage(NOTIFY_APP_TRANSITION_STARTING, reason, 0).sendToTarget();
         return true;
     }
 
@@ -1598,6 +1627,25 @@
         }
     }
 
+    /**
+     * Puts the {@param surface} into a pending list to be destroyed after the current transaction
+     * has been committed.
+     */
+    void destroyAfterTransaction(SurfaceControl surface) {
+        mPendingDestroyingSurfaces.add(surface);
+    }
+
+    /**
+     * Destroys any surfaces that have been put into the pending list with
+     * {@link #destroyAfterTransaction}.
+     */
+    void destroyPendingSurfaces() {
+        for (int i = mPendingDestroyingSurfaces.size() - 1; i >= 0; i--) {
+            mPendingDestroyingSurfaces.get(i).destroy();
+        }
+        mPendingDestroyingSurfaces.clear();
+    }
+
     public void dump(PrintWriter pw, String prefix) {
         pw.print(prefix); pw.print("mTraversalScheduled="); pw.println(mTraversalScheduled);
     }
diff --git a/services/core/jni/com_android_server_location_GnssLocationProvider.cpp b/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
index c97323c..e2c71a1 100644
--- a/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
+++ b/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
@@ -140,7 +140,7 @@
             ALOGD("Unknown constellation type with Svid = %d.", info.svid);
             info.constellation = GNSS_CONSTELLATION_UNKNOWN;
         }
-        info.snr = sv_status->sv_list[i].snr;
+        info.c_n0_dbhz = sv_status->sv_list[i].snr;
         info.elevation = sv_status->sv_list[i].elevation;
         info.azimuth = sv_status->sv_list[i].azimuth;
         info.flags = GNSS_SV_FLAGS_NONE;
@@ -698,12 +698,12 @@
 }
 
 static jint android_location_GnssLocationProvider_read_sv_status(JNIEnv* env, jobject /* obj */,
-        jintArray svidWithFlagArray, jfloatArray snrArray, jfloatArray elevArray,
+        jintArray svidWithFlagArray, jfloatArray cn0Array, jfloatArray elevArray,
         jfloatArray azumArray)
 {
     // this should only be called from within a call to reportSvStatus
     jint* svidWithFlags = env->GetIntArrayElements(svidWithFlagArray, 0);
-    jfloat* snrs = env->GetFloatArrayElements(snrArray, 0);
+    jfloat* cn0s = env->GetFloatArrayElements(cn0Array, 0);
     jfloat* elev = env->GetFloatArrayElements(elevArray, 0);
     jfloat* azim = env->GetFloatArrayElements(azumArray, 0);
 
@@ -713,13 +713,13 @@
         svidWithFlags[i] = (info.svid << SVID_SHIFT_WIDTH) |
             (info.constellation << CONSTELLATION_TYPE_SHIFT_WIDTH) |
             info.flags;
-        snrs[i] = info.snr;
+        cn0s[i] = info.c_n0_dbhz;
         elev[i] = info.elevation;
         azim[i] = info.azimuth;
     }
 
     env->ReleaseIntArrayElements(svidWithFlagArray, svidWithFlags, 0);
-    env->ReleaseFloatArrayElements(snrArray, snrs, 0);
+    env->ReleaseFloatArrayElements(cn0Array, cn0s, 0);
     env->ReleaseFloatArrayElements(elevArray, elev, 0);
     env->ReleaseFloatArrayElements(azumArray, azim, 0);
     return (jint) sGnssSvListSize;
@@ -1087,15 +1087,34 @@
 const char *const JavaMethodHelper<bool>::signature_ = "(Z)V";
 
 #define SET(setter, value) object.callSetter("set" # setter, (value))
-#define SET_IF(flag, setter, value) \
-        if (flags & (flag)) object.callSetter("set" # setter, (value))
+
+// If you want to check if a flag is not set, use SET_IF_NOT(FLAG, setter,
+// value) to do that. SET_IF(!FLAG, setter, value) won't compile.
+//
+// This macros generates compilation error if the provided 'flag' is not a
+// single token. For example, 'GNSS_CLOCK_HAS_BIAS' can be accepted, but
+// '!GNSS_CLOCK_HAS_DRIFT' will fail to compile.
+#define SET_IF(flag, setter, value) do { \
+        if (flags & flag) { \
+            JavaObject& name_check_##flag = object; \
+            name_check_##flag.callSetter("set" # setter, (value)); \
+        } \
+    } while (false)
+#define SET_IF_NOT(flag, setter, value) do { \
+        if (!(flags & flag)) { \
+            JavaObject& name_check_##flag = object; \
+            name_check_##flag.callSetter("set" # setter, (value)); \
+        } \
+    } while (false)
 
 static jobject translate_gps_clock(JNIEnv* env, GpsClock* clock) {
     static uint32_t discontinuity_count_to_handle_old_lock_type = 0;
     JavaObject object(env, "android/location/GnssClock");
     GpsClockFlags flags = clock->flags;
 
-    SET_IF(GNSS_CLOCK_HAS_LEAP_SECOND, LeapSecond, clock->leap_second);
+    SET_IF(GNSS_CLOCK_HAS_LEAP_SECOND,
+           LeapSecond,
+           static_cast<int32_t>(clock->leap_second));
 
     // GnssClock only supports the more effective HW_CLOCK type, so type
     // handling and documentation complexity has been removed.  To convert the
@@ -1122,18 +1141,18 @@
         break;
     }
 
-    SET(TimeInNs, clock->time_ns);
+    SET(TimeNanos, clock->time_ns);
     SET_IF(GNSS_CLOCK_HAS_TIME_UNCERTAINTY,
-           TimeUncertaintyInNs,
+           TimeUncertaintyNanos,
            clock->time_uncertainty_ns);
-    SET_IF(GNSS_CLOCK_HAS_FULL_BIAS, FullBiasInNs, clock->full_bias_ns);
-    SET_IF(GNSS_CLOCK_HAS_BIAS, BiasInNs, clock->bias_ns);
+    SET_IF(GNSS_CLOCK_HAS_FULL_BIAS, FullBiasNanos, clock->full_bias_ns);
+    SET_IF(GNSS_CLOCK_HAS_BIAS, BiasNanos, clock->bias_ns);
     SET_IF(GNSS_CLOCK_HAS_BIAS_UNCERTAINTY,
-           BiasUncertaintyInNs,
+           BiasUncertaintyNanos,
            clock->bias_uncertainty_ns);
-    SET_IF(GNSS_CLOCK_HAS_DRIFT, DriftInNsPerSec, clock->drift_nsps);
+    SET_IF(GNSS_CLOCK_HAS_DRIFT, DriftNanosPerSecond, clock->drift_nsps);
     SET_IF(GNSS_CLOCK_HAS_DRIFT_UNCERTAINTY,
-           DriftUncertaintyInNsPerSec,
+           DriftUncertaintyNanosPerSecond,
            clock->drift_uncertainty_nsps);
 
     return object.get();
@@ -1143,20 +1162,21 @@
     JavaObject object(env, "android/location/GnssClock");
     GpsClockFlags flags = clock->flags;
 
-    SET_IF(GNSS_CLOCK_HAS_LEAP_SECOND, LeapSecond, clock->leap_second);
-    SET(Type, static_cast<uint8_t>(GPS_CLOCK_TYPE_LOCAL_HW_TIME));
-    SET(TimeInNs, clock->time_ns);
+    SET_IF(GNSS_CLOCK_HAS_LEAP_SECOND,
+           LeapSecond,
+           static_cast<int32_t>(clock->leap_second));
+    SET(TimeNanos, clock->time_ns);
     SET_IF(GNSS_CLOCK_HAS_TIME_UNCERTAINTY,
-           TimeUncertaintyInNs,
+           TimeUncertaintyNanos,
            clock->time_uncertainty_ns);
-    SET_IF(GNSS_CLOCK_HAS_FULL_BIAS, FullBiasInNs, clock->full_bias_ns);
-    SET_IF(GNSS_CLOCK_HAS_BIAS, BiasInNs, clock->bias_ns);
+    SET_IF(GNSS_CLOCK_HAS_FULL_BIAS, FullBiasNanos, clock->full_bias_ns);
+    SET_IF(GNSS_CLOCK_HAS_BIAS, BiasNanos, clock->bias_ns);
     SET_IF(GNSS_CLOCK_HAS_BIAS_UNCERTAINTY,
-           BiasUncertaintyInNs,
+           BiasUncertaintyNanos,
            clock->bias_uncertainty_ns);
-    SET_IF(GNSS_CLOCK_HAS_DRIFT, DriftInNsPerSec, clock->drift_nsps);
+    SET_IF(GNSS_CLOCK_HAS_DRIFT, DriftNanosPerSecond, clock->drift_nsps);
     SET_IF(GNSS_CLOCK_HAS_DRIFT_UNCERTAINTY,
-           DriftUncertaintyInNsPerSec,
+           DriftUncertaintyNanosPerSecond,
            clock->drift_uncertainty_nsps);
 
     SET(HardwareClockDiscontinuityCount, clock->hw_clock_discontinuity_count);
@@ -1168,41 +1188,30 @@
                                          GpsMeasurement* measurement) {
     JavaObject object(env, "android/location/GnssMeasurement");
     GpsMeasurementFlags flags = measurement->flags;
-    SET(Svid, static_cast<int16_t>(measurement->prn));
+    SET(Svid, static_cast<int32_t>(measurement->prn));
     if (measurement->prn >= 1 || measurement->prn <= 32) {
-        SET(ConstellationType, static_cast<uint8_t>(GNSS_CONSTELLATION_GPS));
+        SET(ConstellationType, static_cast<int32_t>(GNSS_CONSTELLATION_GPS));
     } else {
         ALOGD("Unknown constellation type with Svid = %d.", measurement->prn);
         SET(ConstellationType,
-            static_cast<uint8_t>(GNSS_CONSTELLATION_UNKNOWN));
+            static_cast<int32_t>(GNSS_CONSTELLATION_UNKNOWN));
     }
-    SET(TimeOffsetInNs, measurement->time_offset_ns);
-    SET(State, measurement->state);
-    SET(ReceivedSvTimeInNs, measurement->received_gps_tow_ns);
-    SET(ReceivedSvTimeUncertaintyInNs,
+    SET(TimeOffsetNanos, measurement->time_offset_ns);
+    SET(State, static_cast<int32_t>(measurement->state));
+    SET(ReceivedSvTimeNanos, measurement->received_gps_tow_ns);
+    SET(ReceivedSvTimeUncertaintyNanos,
         measurement->received_gps_tow_uncertainty_ns);
-    SET(Cn0InDbHz, measurement->c_n0_dbhz);
-    SET(PseudorangeRateInMetersPerSec, measurement->pseudorange_rate_mps);
-    SET(PseudorangeRateUncertaintyInMetersPerSec,
+    SET(Cn0DbHz, measurement->c_n0_dbhz);
+    SET(PseudorangeRateMetersPerSecond, measurement->pseudorange_rate_mps);
+    SET(PseudorangeRateUncertaintyMetersPerSecond,
         measurement->pseudorange_rate_uncertainty_mps);
-    SET(AccumulatedDeltaRangeState, measurement->accumulated_delta_range_state);
-    SET(AccumulatedDeltaRangeInMeters, measurement->accumulated_delta_range_m);
-    SET(AccumulatedDeltaRangeUncertaintyInMeters,
+    SET(AccumulatedDeltaRangeState,
+        static_cast<int32_t>(measurement->accumulated_delta_range_state));
+    SET(AccumulatedDeltaRangeMeters, measurement->accumulated_delta_range_m);
+    SET(AccumulatedDeltaRangeUncertaintyMeters,
         measurement->accumulated_delta_range_uncertainty_m);
-    SET_IF(GNSS_MEASUREMENT_HAS_PSEUDORANGE,
-           PseudorangeInMeters,
-           measurement->pseudorange_m);
-    SET_IF(GNSS_MEASUREMENT_HAS_PSEUDORANGE_UNCERTAINTY,
-           PseudorangeUncertaintyInMeters,
-           measurement->pseudorange_uncertainty_m);
-    SET_IF(GNSS_MEASUREMENT_HAS_CODE_PHASE,
-           CodePhaseInChips,
-           measurement->code_phase_chips);
-    SET_IF(GNSS_MEASUREMENT_HAS_CODE_PHASE_UNCERTAINTY,
-           CodePhaseUncertaintyInChips,
-           measurement->code_phase_uncertainty_chips);
     SET_IF(GNSS_MEASUREMENT_HAS_CARRIER_FREQUENCY,
-           CarrierFrequencyInHz,
+           CarrierFrequencyHz,
            measurement->carrier_frequency_hz);
     SET_IF(GNSS_MEASUREMENT_HAS_CARRIER_CYCLES,
            CarrierCycles,
@@ -1213,33 +1222,13 @@
     SET_IF(GNSS_MEASUREMENT_HAS_CARRIER_PHASE_UNCERTAINTY,
            CarrierPhaseUncertainty,
            measurement->carrier_phase_uncertainty);
-    SET(LossOfLock, measurement->loss_of_lock);
-    SET_IF(GNSS_MEASUREMENT_HAS_BIT_NUMBER, BitNumber, measurement->bit_number);
-    SET_IF(GNSS_MEASUREMENT_HAS_TIME_FROM_LAST_BIT,
-           TimeFromLastBitInMs,
-           measurement->time_from_last_bit_ms);
-    SET_IF(GNSS_MEASUREMENT_HAS_DOPPLER_SHIFT,
-           DopplerShiftInHz,
-           measurement->doppler_shift_hz);
-    SET_IF(GNSS_MEASUREMENT_HAS_DOPPLER_SHIFT_UNCERTAINTY,
-           DopplerShiftUncertaintyInHz,
-           measurement->doppler_shift_uncertainty_hz);
-    SET(MultipathIndicator, measurement->multipath_indicator);
+    SET(MultipathIndicator,
+        static_cast<int32_t>(measurement->multipath_indicator));
     SET_IF(GNSS_MEASUREMENT_HAS_SNR, SnrInDb, measurement->snr_db);
-    SET_IF(GNSS_MEASUREMENT_HAS_ELEVATION,
-           ElevationInDeg,
-           measurement->elevation_deg);
-    SET_IF(GNSS_MEASUREMENT_HAS_ELEVATION_UNCERTAINTY,
-           ElevationUncertaintyInDeg,
-           measurement->elevation_uncertainty_deg);
-    SET_IF(GNSS_MEASUREMENT_HAS_AZIMUTH,
-           AzimuthInDeg,
-           measurement->azimuth_deg);
-    SET_IF(GNSS_MEASUREMENT_HAS_AZIMUTH_UNCERTAINTY,
-           AzimuthUncertaintyInDeg,
-           measurement->azimuth_uncertainty_deg);
-    SET(UsedInFix,
-        (flags & GNSS_MEASUREMENT_HAS_USED_IN_FIX) && measurement->used_in_fix);
+
+    SET_IF_NOT(GPS_MEASUREMENT_HAS_UNCORRECTED_PSEUDORANGE_RATE,
+               PseudorangeRateCorrected,
+               true);
 
     return object.get();
 }
@@ -1250,34 +1239,23 @@
     GpsMeasurementFlags flags = measurement->flags;
 
     SET(Svid, measurement->svid);
-    SET(ConstellationType, measurement->constellation);
-    SET(TimeOffsetInNs, measurement->time_offset_ns);
-    SET(State, measurement->state);
-    SET(ReceivedSvTimeInNs, measurement->received_sv_time_in_ns);
-    SET(ReceivedSvTimeUncertaintyInNs,
+    SET(ConstellationType, static_cast<int32_t>(measurement->constellation));
+    SET(TimeOffsetNanos, measurement->time_offset_ns);
+    SET(State, static_cast<int32_t>(measurement->state));
+    SET(ReceivedSvTimeNanos, measurement->received_sv_time_in_ns);
+    SET(ReceivedSvTimeUncertaintyNanos,
         measurement->received_sv_time_uncertainty_in_ns);
-    SET(Cn0InDbHz, measurement->c_n0_dbhz);
-    SET(PseudorangeRateInMetersPerSec, measurement->pseudorange_rate_mps);
-    SET(PseudorangeRateUncertaintyInMetersPerSec,
+    SET(Cn0DbHz, measurement->c_n0_dbhz);
+    SET(PseudorangeRateMetersPerSecond, measurement->pseudorange_rate_mps);
+    SET(PseudorangeRateUncertaintyMetersPerSecond,
         measurement->pseudorange_rate_uncertainty_mps);
-    SET(AccumulatedDeltaRangeState, measurement->accumulated_delta_range_state);
-    SET(AccumulatedDeltaRangeInMeters, measurement->accumulated_delta_range_m);
-    SET(AccumulatedDeltaRangeUncertaintyInMeters,
+    SET(AccumulatedDeltaRangeState,
+        static_cast<int32_t>(measurement->accumulated_delta_range_state));
+    SET(AccumulatedDeltaRangeMeters, measurement->accumulated_delta_range_m);
+    SET(AccumulatedDeltaRangeUncertaintyMeters,
         measurement->accumulated_delta_range_uncertainty_m);
-    SET_IF(GNSS_MEASUREMENT_HAS_PSEUDORANGE,
-           PseudorangeInMeters,
-           measurement->pseudorange_m);
-    SET_IF(GNSS_MEASUREMENT_HAS_PSEUDORANGE_UNCERTAINTY,
-           PseudorangeUncertaintyInMeters,
-           measurement->pseudorange_uncertainty_m);
-    SET_IF(GNSS_MEASUREMENT_HAS_CODE_PHASE,
-           CodePhaseInChips,
-           measurement->code_phase_chips);
-    SET_IF(GNSS_MEASUREMENT_HAS_CODE_PHASE_UNCERTAINTY,
-           CodePhaseUncertaintyInChips,
-           measurement->code_phase_uncertainty_chips);
     SET_IF(GNSS_MEASUREMENT_HAS_CARRIER_FREQUENCY,
-           CarrierFrequencyInHz,
+           CarrierFrequencyHz,
            measurement->carrier_frequency_hz);
     SET_IF(GNSS_MEASUREMENT_HAS_CARRIER_CYCLES,
            CarrierCycles,
@@ -1288,32 +1266,9 @@
     SET_IF(GNSS_MEASUREMENT_HAS_CARRIER_PHASE_UNCERTAINTY,
            CarrierPhaseUncertainty,
            measurement->carrier_phase_uncertainty);
-    SET_IF(GNSS_MEASUREMENT_HAS_BIT_NUMBER, BitNumber, measurement->bit_number);
-    SET_IF(GNSS_MEASUREMENT_HAS_TIME_FROM_LAST_BIT,
-           TimeFromLastBitInMs,
-           measurement->time_from_last_bit_ms);
-    SET_IF(GNSS_MEASUREMENT_HAS_DOPPLER_SHIFT,
-           DopplerShiftInHz,
-           measurement->doppler_shift_hz);
-    SET_IF(GNSS_MEASUREMENT_HAS_DOPPLER_SHIFT_UNCERTAINTY,
-           DopplerShiftUncertaintyInHz,
-           measurement->doppler_shift_uncertainty_hz);
-    SET(MultipathIndicator, measurement->multipath_indicator);
+    SET(MultipathIndicator,
+        static_cast<int32_t>(measurement->multipath_indicator));
     SET_IF(GNSS_MEASUREMENT_HAS_SNR, SnrInDb, measurement->snr_db);
-    SET_IF(GNSS_MEASUREMENT_HAS_ELEVATION,
-           ElevationInDeg,
-           measurement->elevation_deg);
-    SET_IF(GNSS_MEASUREMENT_HAS_ELEVATION_UNCERTAINTY,
-           ElevationUncertaintyInDeg,
-           measurement->elevation_uncertainty_deg);
-    SET_IF(GNSS_MEASUREMENT_HAS_AZIMUTH,
-           AzimuthInDeg,
-           measurement->azimuth_deg);
-    SET_IF(GNSS_MEASUREMENT_HAS_AZIMUTH_UNCERTAINTY,
-           AzimuthUncertaintyInDeg,
-           measurement->azimuth_uncertainty_deg);
-    SET(UsedInFix,
-        (flags & GNSS_MEASUREMENT_HAS_USED_IN_FIX) && measurement->used_in_fix);
 
     return object.get();
 }
@@ -1493,21 +1448,22 @@
         return NULL;
     }
     JavaObject object(env, "android/location/GnssNavigationMessage");
-    SET(Svid, static_cast<int16_t>(message->prn));
+    SET(Svid, static_cast<int32_t>(message->prn));
     if (message->prn >=1 && message->prn <= 32) {
-        SET(ConstellationType, static_cast<uint8_t>(GNSS_CONSTELLATION_GPS));
+        SET(ConstellationType, static_cast<int32_t>(GNSS_CONSTELLATION_GPS));
         // Legacy driver doesn't set the higher byte to constellation type
         // correctly. Set the higher byte to 'GPS'.
-        SET(Type, static_cast<int16_t>(message->type | 0x0100));
+        SET(Type, static_cast<int32_t>(message->type | 0x0100));
     } else {
         ALOGD("Unknown constellation type with Svid = %d.", message->prn);
         SET(ConstellationType,
-            static_cast<uint8_t>(GNSS_CONSTELLATION_UNKNOWN));
-        SET(Type, static_cast<int16_t>(GNSS_NAVIGATION_MESSAGE_TYPE_UNKNOWN));
+            static_cast<int32_t>(GNSS_CONSTELLATION_UNKNOWN));
+        SET(Type, static_cast<int32_t>(GNSS_NAVIGATION_MESSAGE_TYPE_UNKNOWN));
     }
-    SET(MessageId, message->message_id);
-    SET(SubmessageId, message->submessage_id);
+    SET(MessageId, static_cast<int32_t>(message->message_id));
+    SET(SubmessageId, static_cast<int32_t>(message->submessage_id));
     object.callSetter("setData", data, dataLength);
+    SET(Status, static_cast<int32_t>(message->status));
     return object.get();
 }
 
@@ -1520,11 +1476,12 @@
         return NULL;
     }
     JavaObject object(env, "android/location/GnssNavigationMessage");
-    SET(Type, message->type);
-    SET(Svid, message->svid);
-    SET(MessageId, message->message_id);
-    SET(SubmessageId, message->submessage_id);
+    SET(Type, static_cast<int32_t>(message->type));
+    SET(Svid, static_cast<int32_t>(message->svid));
+    SET(MessageId, static_cast<int32_t>(message->message_id));
+    SET(SubmessageId, static_cast<int32_t>(message->submessage_id));
     object.callSetter("setData", data, dataLength);
+    SET(Status, static_cast<int32_t>(message->status));
     return object.get();
 }
 
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 60c3a35..ea1a569 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -31,8 +31,9 @@
 import android.Manifest.permission;
 import android.accessibilityservice.AccessibilityServiceInfo;
 import android.accounts.AccountManager;
+import android.annotation.IntDef;
 import android.annotation.NonNull;
-import android.annotation.Nullable;
+import android.annotation.UserIdInt;
 import android.app.Activity;
 import android.app.ActivityManager;
 import android.app.ActivityManagerNative;
@@ -151,6 +152,8 @@
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.PrintWriter;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 import java.nio.charset.StandardCharsets;
 import java.security.cert.CertificateException;
 import java.security.cert.CertificateFactory;
@@ -280,6 +283,20 @@
     private static final int PROFILE_KEYGUARD_FEATURES =
             PROFILE_KEYGUARD_FEATURES_AFFECT_OWNER | PROFILE_KEYGUARD_FEATURES_PROFILE_ONLY;
 
+    private static final int CODE_OK = 0;
+    private static final int CODE_HAS_DEVICE_OWNER = 1;
+    private static final int CODE_USER_HAS_PROFILE_OWNER = 2;
+    private static final int CODE_USER_NOT_RUNNING = 3;
+    private static final int CODE_USER_SETUP_COMPLETED = 4;
+    private static final int CODE_NONSYSTEM_USER_EXISTS = 5;
+    private static final int CODE_ACCOUNTS_NOT_EMPTY = 6;
+    private static final int CODE_NOT_SYSTEM_USER = 7;
+
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef({ CODE_OK, CODE_HAS_DEVICE_OWNER, CODE_USER_HAS_PROFILE_OWNER, CODE_USER_NOT_RUNNING,
+            CODE_USER_SETUP_COMPLETED, CODE_NOT_SYSTEM_USER })
+    private @interface DeviceOwnerPreConditionCode {}
+
     private static final int DEVICE_ADMIN_DEACTIVATE_TIMEOUT = 10000;
 
     final Context mContext;
@@ -308,7 +325,7 @@
      * Whether or not device admin feature is supported. If it isn't return defaults for all
      * public methods.
      */
-    private boolean mHasFeature;
+    boolean mHasFeature;
 
     private final SecurityLogMonitor mSecurityLogMonitor;
 
@@ -328,7 +345,7 @@
 
         @Override
         public void onReceive(Context context, Intent intent) {
-            if (RemoteBugreportUtils.ACTION_REMOTE_BUGREPORT_DISPATCH.equals(intent.getAction())
+            if (DevicePolicyManager.ACTION_REMOTE_BUGREPORT_DISPATCH.equals(intent.getAction())
                     && mRemoteBugreportServiceIsActive.get()) {
                 onBugreportFinished(intent);
             }
@@ -342,10 +359,9 @@
             String action = intent.getAction();
             mInjector.getNotificationManager().cancel(LOG_TAG,
                     RemoteBugreportUtils.NOTIFICATION_ID);
-            if (RemoteBugreportUtils.ACTION_REMOTE_BUGREPORT_SHARING_ACCEPTED.equals(action)) {
+            if (DevicePolicyManager.ACTION_BUGREPORT_SHARING_ACCEPTED.equals(action)) {
                 onBugreportSharingAccepted();
-            } else if (RemoteBugreportUtils.ACTION_REMOTE_BUGREPORT_SHARING_DECLINED
-                    .equals(action)) {
+            } else if (DevicePolicyManager.ACTION_BUGREPORT_SHARING_DECLINED.equals(action)) {
                 onBugreportSharingDeclined();
             }
             mContext.unregisterReceiver(mRemoteBugreportConsentReceiver);
@@ -437,15 +453,14 @@
                     && userHandle == mOwners.getDeviceOwnerUserId()
                     && getDeviceOwnerRemoteBugreportUri() != null) {
                 IntentFilter filterConsent = new IntentFilter();
-                filterConsent.addAction(
-                        RemoteBugreportUtils.ACTION_REMOTE_BUGREPORT_SHARING_DECLINED);
-                filterConsent.addAction(
-                        RemoteBugreportUtils.ACTION_REMOTE_BUGREPORT_SHARING_ACCEPTED);
+                filterConsent.addAction(DevicePolicyManager.ACTION_BUGREPORT_SHARING_DECLINED);
+                filterConsent.addAction(DevicePolicyManager.ACTION_BUGREPORT_SHARING_ACCEPTED);
                 mContext.registerReceiver(mRemoteBugreportConsentReceiver, filterConsent);
-                mInjector.getNotificationManager().notify(LOG_TAG,
+                mInjector.getNotificationManager().notifyAsUser(LOG_TAG,
                         RemoteBugreportUtils.NOTIFICATION_ID,
                         RemoteBugreportUtils.buildNotification(mContext,
-                                RemoteBugreportUtils.NOTIFICATION_BUGREPORT_FINISHED_NOT_ACCEPTED));
+                                DevicePolicyManager.NOTIFICATION_BUGREPORT_FINISHED_NOT_ACCEPTED),
+                                UserHandle.ALL);
             }
             if (Intent.ACTION_BOOT_COMPLETED.equals(action)
                     || ACTION_EXPIRED_PASSWORD_NOTIFICATION.equals(action)) {
@@ -769,7 +784,7 @@
                 out.attribute(null, ATTR_VALUE, Boolean.toString(disableContactsSearch));
                 out.endTag(null, TAG_DISABLE_CONTACTS_SEARCH);
             }
-            if (disableBluetoothContactSharing) {
+            if (!disableBluetoothContactSharing) {
                 out.startTag(null, TAG_DISABLE_BLUETOOTH_CONTACT_SHARING);
                 out.attribute(null, ATTR_VALUE,
                         Boolean.toString(disableBluetoothContactSharing));
@@ -1622,14 +1637,12 @@
         }
         // Still at the first stage of CryptKeeper double bounce, mOwners.hasDeviceOwner is
         // always false at this point.
-        if ("encrypted".equals(mInjector.systemPropertiesGet("ro.crypto.state"))
-                && "trigger_restart_min_framework".equals(
-                        mInjector.systemPropertiesGet("vold.decrypt"))){
+        if (StorageManager.inCryptKeeperBounce()) {
             return;
         }
 
         if (!TextUtils.isEmpty(mInjector.systemPropertiesGet(PROPERTY_DEVICE_OWNER_PRESENT))) {
-            Slog.wtf(LOG_TAG, "Trying to set ro.device_owner, but it has already been set?");
+            Slog.w(LOG_TAG, "Trying to set ro.device_owner, but it has already been set?");
         } else {
             if (mOwners.hasDeviceOwner()) {
                 mInjector.systemPropertiesSet(PROPERTY_DEVICE_OWNER_PRESENT, "true");
@@ -2624,7 +2637,7 @@
                 }
             } catch (InterruptedException e) {
                 Thread.currentThread().interrupt();
-            } catch (RuntimeException e) {
+            } catch (RuntimeException | AssertionError e) {
                 Log.e(LOG_TAG, "Could not connect to KeyChain service", e);
             }
             if (!hasCert) {
@@ -3628,7 +3641,7 @@
             if (count == 0 ||
                     count > admin.maximumFailedPasswordsForWipe ||
                     (count == admin.maximumFailedPasswordsForWipe &&
-                            mUserManager.getUserInfo(userId).isPrimary())) {
+                            getUserInfo(userId).isPrimary())) {
                 count = admin.maximumFailedPasswordsForWipe;
                 strictestAdmin = admin;
             }
@@ -3636,6 +3649,15 @@
         return strictestAdmin;
     }
 
+    private UserInfo getUserInfo(@UserIdInt int userId) {
+        final long token = mInjector.binderClearCallingIdentity();
+        try {
+            return mUserManager.getUserInfo(userId);
+        } finally {
+            mInjector.binderRestoreCallingIdentity(token);
+        }
+    }
+
     @Override
     public boolean resetPassword(String passwordOrNull, int flags) throws RemoteException {
         if (!mHasFeature) {
@@ -4840,17 +4862,11 @@
      * {@link DevicePolicyManager#ENCRYPTION_STATUS_ACTIVE}.
      */
     private int getEncryptionStatus() {
-        String status = mInjector.systemPropertiesGet("ro.crypto.state", "unsupported");
-        if ("encrypted".equalsIgnoreCase(status)) {
-            final long token = mInjector.binderClearCallingIdentity();
-            try {
-                return LockPatternUtils.isDeviceEncrypted()
-                        ? DevicePolicyManager.ENCRYPTION_STATUS_ACTIVE
-                        : DevicePolicyManager.ENCRYPTION_STATUS_ACTIVE_DEFAULT_KEY;
-            } finally {
-                mInjector.binderRestoreCallingIdentity(token);
-            }
-        } else if ("unencrypted".equalsIgnoreCase(status)) {
+        if (StorageManager.isEncrypted()) {
+            return StorageManager.isNonDefaultBlockEncrypted() ?
+                      DevicePolicyManager.ENCRYPTION_STATUS_ACTIVE
+                    : DevicePolicyManager.ENCRYPTION_STATUS_ACTIVE_DEFAULT_KEY;
+        } else if (StorageManager.isEncryptable()) {
             return DevicePolicyManager.ENCRYPTION_STATUS_INACTIVE;
         } else {
             return DevicePolicyManager.ENCRYPTION_STATUS_UNSUPPORTED;
@@ -5068,9 +5084,9 @@
             mRemoteBugreportServiceIsActive.set(true);
             mRemoteBugreportSharingAccepted.set(false);
             registerRemoteBugreportReceivers();
-            mInjector.getNotificationManager().notify(LOG_TAG, RemoteBugreportUtils.NOTIFICATION_ID,
+            mInjector.getNotificationManager().notifyAsUser(LOG_TAG, RemoteBugreportUtils.NOTIFICATION_ID,
                     RemoteBugreportUtils.buildNotification(mContext,
-                            RemoteBugreportUtils.NOTIFICATION_BUGREPORT_STARTED));
+                            DevicePolicyManager.NOTIFICATION_BUGREPORT_STARTED), UserHandle.ALL);
             mHandler.postDelayed(mRemoteBugreportTimeoutRunnable,
                     RemoteBugreportUtils.REMOTE_BUGREPORT_TIMEOUT_MILLIS);
             return true;
@@ -5104,7 +5120,7 @@
     private void registerRemoteBugreportReceivers() {
         try {
             IntentFilter filterFinished = new IntentFilter(
-                    RemoteBugreportUtils.ACTION_REMOTE_BUGREPORT_DISPATCH,
+                    DevicePolicyManager.ACTION_REMOTE_BUGREPORT_DISPATCH,
                     RemoteBugreportUtils.BUGREPORT_MIMETYPE);
             mContext.registerReceiver(mRemoteBugreportFinishedReceiver, filterFinished);
         } catch (IntentFilter.MalformedMimeTypeException e) {
@@ -5112,8 +5128,8 @@
             Slog.w(LOG_TAG, "Failed to set type " + RemoteBugreportUtils.BUGREPORT_MIMETYPE, e);
         }
         IntentFilter filterConsent = new IntentFilter();
-        filterConsent.addAction(RemoteBugreportUtils.ACTION_REMOTE_BUGREPORT_SHARING_DECLINED);
-        filterConsent.addAction(RemoteBugreportUtils.ACTION_REMOTE_BUGREPORT_SHARING_ACCEPTED);
+        filterConsent.addAction(DevicePolicyManager.ACTION_BUGREPORT_SHARING_DECLINED);
+        filterConsent.addAction(DevicePolicyManager.ACTION_BUGREPORT_SHARING_ACCEPTED);
         mContext.registerReceiver(mRemoteBugreportConsentReceiver, filterConsent);
     }
 
@@ -5126,16 +5142,17 @@
             bugreportUriString = bugreportUri.toString();
         }
         String bugreportHash = intent.getStringExtra(
-                RemoteBugreportUtils.EXTRA_REMOTE_BUGREPORT_HASH);
+                DevicePolicyManager.EXTRA_REMOTE_BUGREPORT_HASH);
         if (mRemoteBugreportSharingAccepted.get()) {
             shareBugreportWithDeviceOwnerIfExists(bugreportUriString, bugreportHash);
             mInjector.getNotificationManager().cancel(LOG_TAG,
                     RemoteBugreportUtils.NOTIFICATION_ID);
         } else {
             setDeviceOwnerRemoteBugreportUriAndHash(bugreportUriString, bugreportHash);
-            mInjector.getNotificationManager().notify(LOG_TAG, RemoteBugreportUtils.NOTIFICATION_ID,
+            mInjector.getNotificationManager().notifyAsUser(LOG_TAG, RemoteBugreportUtils.NOTIFICATION_ID,
                     RemoteBugreportUtils.buildNotification(mContext,
-                            RemoteBugreportUtils.NOTIFICATION_BUGREPORT_FINISHED_NOT_ACCEPTED));
+                            DevicePolicyManager.NOTIFICATION_BUGREPORT_FINISHED_NOT_ACCEPTED),
+                            UserHandle.ALL);
         }
         mContext.unregisterReceiver(mRemoteBugreportFinishedReceiver);
     }
@@ -5166,9 +5183,10 @@
         if (bugreportUriString != null) {
             shareBugreportWithDeviceOwnerIfExists(bugreportUriString, bugreportHash);
         } else if (mRemoteBugreportServiceIsActive.get()) {
-            mInjector.getNotificationManager().notify(LOG_TAG, RemoteBugreportUtils.NOTIFICATION_ID,
+            mInjector.getNotificationManager().notifyAsUser(LOG_TAG, RemoteBugreportUtils.NOTIFICATION_ID,
                     RemoteBugreportUtils.buildNotification(mContext,
-                            RemoteBugreportUtils.NOTIFICATION_BUGREPORT_ACCEPTED_NOT_FINISHED));
+                            DevicePolicyManager.NOTIFICATION_BUGREPORT_ACCEPTED_NOT_FINISHED),
+                            UserHandle.ALL);
         }
     }
 
@@ -5530,7 +5548,8 @@
         Preconditions.checkNotNull(packageName, "packageName is null");
         final int callingUid = mInjector.binderGetCallingUid();
         try {
-            int uid = mContext.getPackageManager().getPackageUidAsUser(packageName, 0);
+            int uid = mContext.getPackageManager().getPackageUidAsUser(packageName,
+                    UserHandle.getUserId(callingUid));
             if (uid != callingUid) {
                 throw new SecurityException("Invalid packageName");
             }
@@ -5896,7 +5915,7 @@
      * - adb if there are not accounts.
      */
     private void enforceCanSetProfileOwnerLocked(int userHandle) {
-        UserInfo info = mUserManager.getUserInfo(userHandle);
+        UserInfo info = getUserInfo(userHandle);
         if (info == null) {
             // User doesn't exist.
             throw new IllegalArgumentException(
@@ -5933,52 +5952,40 @@
     /**
      * The Device owner can only be set by adb or an app with the MANAGE_PROFILE_AND_DEVICE_OWNERS
      * permission.
-     * The device owner can only be set before the setup phase of the primary user has completed,
-     * except for adb if no accounts or additional users are present on the device.
      */
     private void enforceCanSetDeviceOwnerLocked(int userId) {
-        if (mOwners.hasDeviceOwner()) {
-            throw new IllegalStateException("Trying to set the device owner, but device owner "
-                    + "is already set.");
-        }
-        if (mOwners.hasProfileOwner(userId)) {
-            throw new IllegalStateException("Trying to set the device owner, but the user already "
-                    + "has a profile owner.");
-        }
-        if (!mUserManager.isUserRunning(new UserHandle(userId))) {
-            throw new IllegalStateException("User not running: " + userId);
-        }
-
         int callingUid = mInjector.binderGetCallingUid();
-        if (callingUid == Process.SHELL_UID || callingUid == Process.ROOT_UID) {
-            if (!hasUserSetupCompleted(UserHandle.USER_SYSTEM)) {
-                return;
-            }
-            // STOPSHIP Do proper check in split user mode
-            if (!mInjector.userManagerIsSplitSystemUser()) {
-                if (mUserManager.getUserCount() > 1) {
-                    throw new IllegalStateException(
-                            "Not allowed to set the device owner because there "
-                                    + "are already several users on the device");
-                }
-                if (AccountManager.get(mContext).getAccounts().length > 0) {
-                    throw new IllegalStateException(
-                            "Not allowed to set the device owner because there "
-                                    + "are already some accounts on the device");
-                }
-            }
-            return;
+        boolean isAdb = callingUid == Process.SHELL_UID || callingUid == Process.ROOT_UID;
+        if (!isAdb) {
+            mContext.enforceCallingOrSelfPermission(
+                    android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS, null);
         }
-        // STOPSHIP check the caller UID with userId
 
-        mContext.enforceCallingOrSelfPermission(
-                android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS, null);
-        // STOPSHIP Do proper check in split user mode
-        if (!mInjector.userManagerIsSplitSystemUser()) {
-            if (hasUserSetupCompleted(UserHandle.USER_SYSTEM)) {
-                throw new IllegalStateException("Cannot set the device owner if the device is "
-                        + "already set-up");
-            }
+        final int code = checkSetDeviceOwnerPreCondition(userId, isAdb);
+        switch (code) {
+            case CODE_OK:
+                return;
+            case CODE_HAS_DEVICE_OWNER:
+                throw new IllegalStateException(
+                        "Trying to set the device owner, but device owner is already set.");
+            case CODE_USER_HAS_PROFILE_OWNER:
+                throw new IllegalStateException("Trying to set the device owner, but the user "
+                        + "already has a profile owner.");
+            case CODE_USER_NOT_RUNNING:
+                throw new IllegalStateException("User not running: " + userId);
+            case CODE_NOT_SYSTEM_USER:
+                throw new IllegalStateException("User is not system user");
+            case CODE_USER_SETUP_COMPLETED:
+                throw new IllegalStateException(
+                        "Cannot set the device owner if the device is already set-up");
+            case CODE_NONSYSTEM_USER_EXISTS:
+                throw new IllegalStateException("Not allowed to set the device owner because there "
+                        + "are already several users on the device");
+            case CODE_ACCOUNTS_NOT_EMPTY:
+                throw new IllegalStateException("Not allowed to set the device owner because there "
+                        + "are already some accounts on the device");
+            default:
+                throw new IllegalStateException("Unknown @DeviceOwnerPreConditionCode " + code);
         }
     }
 
@@ -6060,12 +6067,7 @@
     }
 
     private boolean isManagedProfile(int userHandle) {
-        long ident = mInjector.binderClearCallingIdentity();
-        try {
-            return mUserManager.getUserInfo(userHandle).isManagedProfile();
-        } finally {
-            mInjector.binderRestoreCallingIdentity(ident);
-        }
+        return getUserInfo(userHandle).isManagedProfile();
     }
 
     private void enableIfNecessary(String packageName, int userId) {
@@ -6404,7 +6406,7 @@
         try {
             // If we have an enabled packages list for a managed profile the packages
             // we should check are installed for the parent user.
-            UserInfo user = mUserManager.getUserInfo(userIdToCheck);
+            UserInfo user = getUserInfo(userIdToCheck);
             if (user.isManagedProfile()) {
                 userIdToCheck = user.profileGroupId;
             }
@@ -6450,7 +6452,7 @@
             List<AccessibilityServiceInfo> enabledServices = null;
             long id = mInjector.binderClearCallingIdentity();
             try {
-                UserInfo user = mUserManager.getUserInfo(userId);
+                UserInfo user = getUserInfo(userId);
                 if (user.isManagedProfile()) {
                     userId = user.profileGroupId;
                 }
@@ -6532,7 +6534,7 @@
             if (result != null) {
                 long id = mInjector.binderClearCallingIdentity();
                 try {
-                    UserInfo user = mUserManager.getUserInfo(userId);
+                    UserInfo user = getUserInfo(userId);
                     if (user.isManagedProfile()) {
                         userId = user.profileGroupId;
                     }
@@ -6586,7 +6588,7 @@
         long token = mInjector.binderClearCallingIdentity();
         try {
             UserInfo currentUser;
-            UserInfo callingUser = mUserManager.getUserInfo(callingUserId);
+            UserInfo callingUser = getUserInfo(callingUserId);
             try {
                 currentUser = mInjector.getIActivityManager().getCurrentUser();
             } catch (RemoteException e) {
@@ -7125,7 +7127,7 @@
                         intent,
                         intent.resolveTypeIfNeeded(mContext.getContentResolver()),
                         PackageManager.MATCH_ENCRYPTION_AWARE_AND_UNAWARE,
-                        parentUserId);
+                        parentUserId).getList();
 
                 if (VERBOSE_LOG) {
                     Slog.d(LOG_TAG, "Enabling system activities: " + activitiesToEnable);
@@ -7809,6 +7811,26 @@
                 listener.onCrossProfileWidgetProvidersChanged(userId, packages);
             }
         }
+
+        @Override
+        public boolean hasDeviceOwnerOrProfileOwner(String packageName, int userId) {
+            if (!mHasFeature || packageName == null) {
+                return false;
+            }
+            if (userId < 0) {
+                throw new UnsupportedOperationException("userId should be >= 0");
+            }
+            synchronized (DevicePolicyManagerService.this) {
+                if (packageName.equals(mOwners.getProfileOwnerPackage(userId))) {
+                    return true;
+                }
+                if (userId == mOwners.getDeviceOwnerUserId()
+                        && packageName.equals(mOwners.getDeviceOwnerPackageName())) {
+                    return true;
+                }
+            }
+            return false;
+        }
     }
 
     /**
@@ -8035,6 +8057,10 @@
 
     @Override
     public boolean isProvisioningAllowed(String action) {
+        if (!mHasFeature) {
+            return false;
+        }
+
         final int callingUserId = mInjector.userHandleGetCallingUserId();
         if (DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE.equals(action)) {
             if (!hasFeatureManagedUsers()) {
@@ -8099,23 +8125,55 @@
         throw new IllegalArgumentException("Unknown provisioning action " + action);
     }
 
-    private boolean isDeviceOwnerProvisioningAllowed(int callingUserId) {
-        synchronized (this) {
-            if (mOwners.hasDeviceOwner()) {
-                return false;
+    /*
+     * The device owner can only be set before the setup phase of the primary user has completed,
+     * except for adb command if no accounts or additional users are present on the device.
+     */
+    private synchronized @DeviceOwnerPreConditionCode int checkSetDeviceOwnerPreCondition(
+            int deviceOwnerUserId, boolean isAdb) {
+        if (mOwners.hasDeviceOwner()) {
+            return CODE_HAS_DEVICE_OWNER;
+        }
+        if (mOwners.hasProfileOwner(deviceOwnerUserId)) {
+            return CODE_USER_HAS_PROFILE_OWNER;
+        }
+        if (!mUserManager.isUserRunning(new UserHandle(deviceOwnerUserId))) {
+            return CODE_USER_NOT_RUNNING;
+        }
+        if (isAdb) {
+            // if shell command runs after user setup completed check device status. Otherwise, OK.
+            if (hasUserSetupCompleted(UserHandle.USER_SYSTEM)) {
+                if (!mInjector.userManagerIsSplitSystemUser()) {
+                    if (mUserManager.getUserCount() > 1) {
+                        return CODE_NONSYSTEM_USER_EXISTS;
+                    }
+                    if (AccountManager.get(mContext).getAccounts().length > 0) {
+                        return CODE_ACCOUNTS_NOT_EMPTY;
+                    }
+                } else {
+                    // STOPSHIP Do proper check in split user mode
+                }
             }
+            return CODE_OK;
+        } else {
+            if (!mInjector.userManagerIsSplitSystemUser()) {
+                // In non-split user mode, DO has to be user 0
+                if (deviceOwnerUserId != UserHandle.USER_SYSTEM) {
+                    return CODE_NOT_SYSTEM_USER;
+                }
+                // In non-split user mode, only provision DO before setup wizard completes
+                if (hasUserSetupCompleted(UserHandle.USER_SYSTEM)) {
+                    return CODE_USER_SETUP_COMPLETED;
+                }
+            } else {
+                // STOPSHIP Do proper check in split user mode
+            }
+            return CODE_OK;
         }
-        if (getProfileOwner(callingUserId) != null) {
-            return false;
-        }
-        if (mInjector.settingsGlobalGetInt(Settings.Global.DEVICE_PROVISIONED, 0) != 0) {
-            return false;
-        }
-        if (callingUserId != UserHandle.USER_SYSTEM) {
-            // Device owner provisioning can only be initiated from system user.
-            return false;
-        }
-        return true;
+    }
+
+    private boolean isDeviceOwnerProvisioningAllowed(int deviceOwnerUserId) {
+        return CODE_OK == checkSetDeviceOwnerPreCondition(deviceOwnerUserId, /* isAdb */ false);
     }
 
     private boolean hasFeatureManagedUsers() {
@@ -8127,10 +8185,10 @@
     }
 
     @Override
-    public String getWifiMacAddress() {
+    public String getWifiMacAddress(ComponentName admin) {
         // Make sure caller has DO.
         synchronized (this) {
-            getActiveAdminForCallerLocked(null, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
+            getActiveAdminForCallerLocked(admin, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
         }
 
         final long ident = mInjector.binderClearCallingIdentity();
@@ -8162,13 +8220,7 @@
             getActiveAdminForCallerLocked(admin, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
         }
         final int callingUserId = mInjector.userHandleGetCallingUserId();
-        final UserInfo user;
-        long ident = mInjector.binderClearCallingIdentity();
-        try {
-            user = mUserManager.getUserInfo(callingUserId);
-        } finally {
-            mInjector.binderRestoreCallingIdentity(ident);
-        }
+        final UserInfo user = getUserInfo(callingUserId);
         return user != null && user.isManagedProfile();
     }
 
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/Owners.java b/services/devicepolicy/java/com/android/server/devicepolicy/Owners.java
index 68fd0f6..b316cbd 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/Owners.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/Owners.java
@@ -494,7 +494,6 @@
         abstract void writeInner(XmlSerializer out) throws IOException;
 
         abstract boolean readInner(XmlPullParser parser, int depth, String tag);
-
     }
 
     private class DeviceOwnerReadWriter extends FileReadWriter {
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/RemoteBugreportUtils.java b/services/devicepolicy/java/com/android/server/devicepolicy/RemoteBugreportUtils.java
index 117ba15..6d42dc9 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/RemoteBugreportUtils.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/RemoteBugreportUtils.java
@@ -19,8 +19,12 @@
 import android.annotation.IntDef;
 import android.app.Notification;
 import android.app.PendingIntent;
+import android.app.admin.DevicePolicyManager;
+import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
+import android.os.UserHandle;
+import android.provider.Settings;
 import android.text.format.DateUtils;
 
 import com.android.internal.R;
@@ -37,79 +41,62 @@
 
     @Retention(RetentionPolicy.SOURCE)
     @IntDef({
-        NOTIFICATION_BUGREPORT_STARTED,
-        NOTIFICATION_BUGREPORT_ACCEPTED_NOT_FINISHED,
-        NOTIFICATION_BUGREPORT_FINISHED_NOT_ACCEPTED
+        DevicePolicyManager.NOTIFICATION_BUGREPORT_STARTED,
+        DevicePolicyManager.NOTIFICATION_BUGREPORT_ACCEPTED_NOT_FINISHED,
+        DevicePolicyManager.NOTIFICATION_BUGREPORT_FINISHED_NOT_ACCEPTED
     })
     @interface RemoteBugreportNotificationType {}
-    static final int NOTIFICATION_BUGREPORT_STARTED = 1;
-    static final int NOTIFICATION_BUGREPORT_ACCEPTED_NOT_FINISHED = 2;
-    static final int NOTIFICATION_BUGREPORT_FINISHED_NOT_ACCEPTED = 3;
 
     static final long REMOTE_BUGREPORT_TIMEOUT_MILLIS = 10 * DateUtils.MINUTE_IN_MILLIS;
 
     static final String CTL_STOP = "ctl.stop";
     static final String REMOTE_BUGREPORT_SERVICE = "bugreportremote";
 
-    static final String ACTION_REMOTE_BUGREPORT_DISPATCH =
-            "android.intent.action.REMOTE_BUGREPORT_DISPATCH";
-    static final String ACTION_REMOTE_BUGREPORT_SHARING_ACCEPTED =
-            "com.android.server.action.REMOTE_BUGREPORT_SHARING_ACCEPTED";
-    static final String ACTION_REMOTE_BUGREPORT_SHARING_DECLINED =
-            "com.android.server.action.REMOTE_BUGREPORT_SHARING_DECLINED";
-    static final String EXTRA_REMOTE_BUGREPORT_HASH = "android.intent.extra.REMOTE_BUGREPORT_HASH";
-
     static final String BUGREPORT_MIMETYPE = "application/vnd.android.bugreport";
 
     static Notification buildNotification(Context context,
             @RemoteBugreportNotificationType int type) {
+        Intent dialogIntent = new Intent(Settings.ACTION_SHOW_REMOTE_BUGREPORT_DIALOG);
+        dialogIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
+        dialogIntent.putExtra(DevicePolicyManager.EXTRA_BUGREPORT_NOTIFICATION_TYPE, type);
+        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));
 
-        if (type == NOTIFICATION_BUGREPORT_ACCEPTED_NOT_FINISHED) {
+        if (type == DevicePolicyManager.NOTIFICATION_BUGREPORT_ACCEPTED_NOT_FINISHED) {
             builder.setContentTitle(context.getString(
-                            R.string.sharing_remote_bugreport_notification_title))
-                    .setContentText(context.getString(
-                            R.string.sharing_remote_bugreport_notification_message))
-                    .setPriority(Notification.PRIORITY_HIGH)
-                    .setProgress(0, 0, true)
-                    .setStyle(new Notification.BigTextStyle().bigText(context.getString(
-                            R.string.sharing_remote_bugreport_notification_message)));
-        } else {
+                        R.string.sharing_remote_bugreport_notification_title))
+                    .setProgress(0, 0, true);
+        } else if (type == DevicePolicyManager.NOTIFICATION_BUGREPORT_STARTED) {
+            builder.setContentTitle(context.getString(
+                        R.string.taking_remote_bugreport_notification_title))
+                    .setProgress(0, 0, true);
+        } else if (type == DevicePolicyManager.NOTIFICATION_BUGREPORT_FINISHED_NOT_ACCEPTED) {
             PendingIntent pendingIntentAccept = PendingIntent.getBroadcast(context, NOTIFICATION_ID,
-                    new Intent(ACTION_REMOTE_BUGREPORT_SHARING_ACCEPTED),
+                    new Intent(DevicePolicyManager.ACTION_BUGREPORT_SHARING_ACCEPTED),
                     PendingIntent.FLAG_CANCEL_CURRENT);
             PendingIntent pendingIntentDecline = PendingIntent.getBroadcast(context,
-                    NOTIFICATION_ID, new Intent(ACTION_REMOTE_BUGREPORT_SHARING_DECLINED),
+                    NOTIFICATION_ID, new Intent(
+                            DevicePolicyManager.ACTION_BUGREPORT_SHARING_DECLINED),
                     PendingIntent.FLAG_CANCEL_CURRENT);
             builder.addAction(new Notification.Action.Builder(null /* icon */, context.getString(
-                            R.string.share_remote_bugreport_notification_decline),
-                            pendingIntentDecline).build())
+                        R.string.decline_remote_bugreport_action), pendingIntentDecline).build())
                     .addAction(new Notification.Action.Builder(null /* icon */, context.getString(
-                            R.string.share_remote_bugreport_notification_accept),
-                            pendingIntentAccept).build())
+                        R.string.share_remote_bugreport_action), pendingIntentAccept).build())
                     .setContentTitle(context.getString(
-                            R.string.share_remote_bugreport_notification_title));
-
-            if (type == NOTIFICATION_BUGREPORT_STARTED) {
-                builder.setContentText(context.getString(
-                                R.string.share_remote_bugreport_notification_message))
-                        .setStyle(new Notification.BigTextStyle().bigText(context.getString(
-                                R.string.share_remote_bugreport_notification_message)))
-                        .setProgress(0, 0, true)
-                        .setPriority(Notification.PRIORITY_MAX)
-                        .setVibrate(new long[0]);
-            } else if (type == NOTIFICATION_BUGREPORT_FINISHED_NOT_ACCEPTED) {
-                builder.setContentText(context.getString(
-                                R.string.share_finished_remote_bugreport_notification_message))
-                        .setStyle(new Notification.BigTextStyle().bigText(context.getString(
-                                R.string.share_finished_remote_bugreport_notification_message)))
-                        .setPriority(Notification.PRIORITY_HIGH);
-            }
+                        R.string.share_remote_bugreport_notification_title))
+                    .setContentText(context.getString(
+                        R.string.share_remote_bugreport_notification_message_finished))
+                    .setStyle(new Notification.BigTextStyle().bigText(context.getString(
+                        R.string.share_remote_bugreport_notification_message_finished)));
         }
 
         return builder.build();
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 0ece6aa..e7daaa1 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -83,6 +83,7 @@
 import com.android.server.pm.LauncherAppsService;
 import com.android.server.pm.OtaDexoptService;
 import com.android.server.pm.PackageManagerService;
+import com.android.server.pm.ShortcutService;
 import com.android.server.pm.UserManagerService;
 import com.android.server.power.PowerManagerService;
 import com.android.server.power.ShutdownThread;
@@ -431,6 +432,24 @@
         mPackageManager = mSystemContext.getPackageManager();
         Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
 
+        // Manages A/B OTA dexopting. This is a bootstrap service as we need it to rename
+        // A/B artifacts after boot, before anything else might touch/need them.
+        // Note: this isn't needed during decryption (we don't have /data anyways).
+        if (!mOnlyCore) {
+            boolean disableOtaDexopt = SystemProperties.getBoolean("config.disable_otadexopt",
+                    false);
+            if (!disableOtaDexopt) {
+                traceBeginAndSlog("StartOtaDexOptService");
+                try {
+                    OtaDexoptService.main(mSystemContext, mPackageManagerService);
+                } catch (Throwable e) {
+                    reportWtf("starting OtaDexOptService", e);
+                } finally {
+                    Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
+                }
+            }
+        }
+
         traceBeginAndSlog("StartUserManagerService");
         ServiceManager.addService(Context.USER_SERVICE, UserManagerService.getInstance());
         Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
@@ -617,7 +636,6 @@
         WallpaperManagerService wallpaper = null;
         LocationManagerService location = null;
         CountryDetectorService countryDetector = null;
-        TextServicesManagerService tsms = null;
         ILockSettings lockSettings = null;
         AssetAtlasService atlas = null;
         MediaRouterService mediaRouter = null;
@@ -744,14 +762,7 @@
             }
 
             if (!disableNonCoreServices) {
-                traceBeginAndSlog("StartTextServicesManagerService");
-                try {
-                    tsms = new TextServicesManagerService(context);
-                    ServiceManager.addService(Context.TEXT_SERVICES_MANAGER_SERVICE, tsms);
-                } catch (Throwable e) {
-                    reportWtf("starting Text Service Manager Service", e);
-                }
-                Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
+                mSystemServiceManager.startService(TextServicesManagerService.Lifecycle.class);
             }
 
             if (!disableNetwork) {
@@ -1036,6 +1047,7 @@
                 traceBeginAndSlog("StartNetworkTimeUpdateService");
                 try {
                     networkTimeUpdater = new NetworkTimeUpdateService(context);
+                    ServiceManager.addService("network_time_update_service", networkTimeUpdater);
                 } catch (Throwable e) {
                     reportWtf("starting NetworkTimeUpdate service", e);
                 }
@@ -1123,20 +1135,9 @@
                     reportWtf("starting BackgroundDexOptService", e);
                 }
                 Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
-
-                // Manages A/B OTA dexopting.
-                boolean disableOtaDexopt = SystemProperties.getBoolean("config.disable_otadexopt",
-                        false);
-                if (!disableOtaDexopt) {
-                    traceBeginAndSlog("StartOtaDexOptService");
-                    try {
-                        OtaDexoptService.main(mSystemContext, mPackageManagerService);
-                    } catch (Throwable e) {
-                        reportWtf("starting BackgroundDexOptService", e);
-                    }
-                    Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
-                }
             }
+            // LauncherAppsService uses ShortcutService.
+            mSystemServiceManager.startService(ShortcutService.Lifecycle.class);
 
             mSystemServiceManager.startService(LauncherAppsService.class);
         }
@@ -1250,7 +1251,6 @@
         final CountryDetectorService countryDetectorF = countryDetector;
         final NetworkTimeUpdateService networkTimeUpdaterF = networkTimeUpdater;
         final CommonTimeManagementService commonTimeMgmtServiceF = commonTimeMgmtService;
-        final TextServicesManagerService textServiceManagerServiceF = tsms;
         final StatusBarManagerService statusBarF = statusBar;
         final AssetAtlasService atlasF = atlas;
         final InputManagerService inputManagerF = inputManager;
@@ -1366,12 +1366,6 @@
                     reportWtf("Notifying CommonTimeManagementService running", e);
                 }
                 try {
-                    if (textServiceManagerServiceF != null)
-                        textServiceManagerServiceF.systemRunning();
-                } catch (Throwable e) {
-                    reportWtf("Notifying TextServicesManagerService running", e);
-                }
-                try {
                     if (atlasF != null) atlasF.systemRunning();
                 } catch (Throwable e) {
                     reportWtf("Notifying AssetAtlasService running", e);
diff --git a/services/net/java/android/net/dhcp/DhcpClient.java b/services/net/java/android/net/dhcp/DhcpClient.java
index 4f99bff..e2562cd 100644
--- a/services/net/java/android/net/dhcp/DhcpClient.java
+++ b/services/net/java/android/net/dhcp/DhcpClient.java
@@ -84,10 +84,10 @@
 public class DhcpClient extends StateMachine {
 
     private static final String TAG = "DhcpClient";
-    private static final boolean DBG = true;
+    private static final boolean DBG = false;
     private static final boolean STATE_DBG = false;
     private static final boolean MSG_DBG = false;
-    private static final boolean PACKET_DBG = true;
+    private static final boolean PACKET_DBG = false;
 
     // Timers and timeouts.
     private static final int SECONDS = 1000;
@@ -342,14 +342,14 @@
 
         @Override
         public void run() {
-            maybeLog("Receive thread started");
+            if (DBG) Log.d(TAG, "Receive thread started");
             while (!stopped) {
                 int length = 0;  // Or compiler can't tell it's initialized if a parse error occurs.
                 try {
                     length = Os.read(mPacketSock, mPacket, 0, mPacket.length);
                     DhcpPacket packet = null;
                     packet = DhcpPacket.decodeFullPacket(mPacket, length, DhcpPacket.ENCAP_L2);
-                    maybeLog("Received packet: " + packet);
+                    if (DBG) Log.d(TAG, "Received packet: " + packet);
                     sendMessage(CMD_RECEIVED_PACKET, packet);
                 } catch (IOException|ErrnoException e) {
                     if (!stopped) {
@@ -362,7 +362,7 @@
                     }
                 }
             }
-            maybeLog("Receive thread stopped");
+            if (DBG) Log.d(TAG, "Receive thread stopped");
         }
     }
 
@@ -373,12 +373,12 @@
     private boolean transmitPacket(ByteBuffer buf, String description, Inet4Address to) {
         try {
             if (to.equals(INADDR_BROADCAST)) {
-                maybeLog("Broadcasting " + description);
+                if (DBG) Log.d(TAG, "Broadcasting " + description);
                 Os.sendto(mPacketSock, buf.array(), 0, buf.limit(), 0, mInterfaceBroadcastAddr);
             } else {
                 // It's safe to call getpeername here, because we only send unicast packets if we
                 // have an IP address, and we connect the UDP socket in DhcpHaveAddressState#enter.
-                maybeLog("Unicasting " + description + " to " + Os.getpeername(mUdpSock));
+                if (DBG) Log.d(TAG, "Unicasting " + description + " to " + Os.getpeername(mUdpSock));
                 Os.write(mUdpSock, buf);
             }
         } catch(ErrnoException|IOException e) {
@@ -454,10 +454,6 @@
         mController.sendMessage(CMD_ON_QUIT);
     }
 
-    private void maybeLog(String msg) {
-        if (DBG) Log.d(TAG, msg);
-    }
-
     abstract class LoggingState extends State {
         public void enter() {
             if (STATE_DBG) Log.d(TAG, "Entering state " + getName());
@@ -592,7 +588,7 @@
                     transitionTo(mStoppedState);
                     return HANDLED;
                 case CMD_ONESHOT_TIMEOUT:
-                    maybeLog("Timed out");
+                    if (DBG) Log.d(TAG, "Timed out");
                     notifyFailure();
                     return HANDLED;
                 default:
@@ -790,7 +786,7 @@
 
         @Override
         public void exit() {
-            maybeLog("Clearing IP address");
+            if (DBG) Log.d(TAG, "Clearing IP address");
             setIpAddress(new LinkAddress("0.0.0.0/0"));
         }
     }
diff --git a/services/net/java/android/net/dhcp/DhcpPacket.java b/services/net/java/android/net/dhcp/DhcpPacket.java
index 6a255e5..e27f69e 100644
--- a/services/net/java/android/net/dhcp/DhcpPacket.java
+++ b/services/net/java/android/net/dhcp/DhcpPacket.java
@@ -819,7 +819,11 @@
             // server-to-server packets, e.g. for relays.
             if (!isPacketToOrFromClient(udpSrcPort, udpDstPort) &&
                 !isPacketServerToServer(udpSrcPort, udpDstPort)) {
-                return null;
+                // This should almost never happen because we use SO_ATTACH_FILTER on the packet
+                // socket to drop packets that don't have the right source ports. However, it's
+                // possible that a packet arrives between when the socket is bound and when the
+                // filter is set. http://b/26696823 .
+                throw new ParseException("Unexpected UDP ports %d->%d", udpSrcPort, udpDstPort);
             }
         }
 
diff --git a/services/net/java/android/net/ip/IpManager.java b/services/net/java/android/net/ip/IpManager.java
index 2a90c60..c7c5015 100644
--- a/services/net/java/android/net/ip/IpManager.java
+++ b/services/net/java/android/net/ip/IpManager.java
@@ -63,12 +63,9 @@
  * @hide
  */
 public class IpManager extends StateMachine {
-    private static final boolean DBG = true;
+    private static final boolean DBG = false;
     private static final boolean VDBG = false;
 
-    private static final boolean NO_CALLBACKS = false;
-    private static final boolean SEND_CALLBACKS = true;
-
     // For message logging.
     private static final Class[] sMessageClasses = { IpManager.class, DhcpClient.class };
     private static final SparseArray<String> sWhatToString =
@@ -98,6 +95,10 @@
         public void onProvisioningSuccess(LinkProperties newLp) {}
         public void onProvisioningFailure(LinkProperties newLp) {}
 
+        // This is called whenever 464xlat is being enabled or disabled (i.e.
+        // started or stopped).
+        public void on464XlatChange(boolean enabled) {}
+
         // Invoked on LinkProperties changes.
         public void onLinkPropertiesChange(LinkProperties newLp) {}
 
@@ -207,6 +208,13 @@
 
     private static final int MAX_LOG_RECORDS = 1000;
 
+    private static final boolean NO_CALLBACKS = false;
+    private static final boolean SEND_CALLBACKS = true;
+
+    // This must match the interface prefix in clatd.c.
+    // TODO: Revert this hack once IpManager and Nat464Xlat work in concert.
+    private static final String CLAT_PREFIX = "v4-";
+
     private final Object mLock = new Object();
     private final State mStoppedState = new StoppedState();
     private final State mStoppingState = new StoppingState();
@@ -215,6 +223,7 @@
     private final String mTag;
     private final Context mContext;
     private final String mInterfaceName;
+    private final String mClatInterfaceName;
     @VisibleForTesting
     protected final Callback mCallback;
     private final INetworkManagementService mNwService;
@@ -241,15 +250,23 @@
 
     public IpManager(Context context, String ifName, Callback callback)
                 throws IllegalArgumentException {
+        this(context, ifName, callback, INetworkManagementService.Stub.asInterface(
+                ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE)));
+    }
+
+    /**
+     * An expanded constructor, useful for dependency injection.
+     */
+    public IpManager(Context context, String ifName, Callback callback,
+            INetworkManagementService nwService) throws IllegalArgumentException {
         super(IpManager.class.getSimpleName() + "." + ifName);
         mTag = getName();
 
         mContext = context;
         mInterfaceName = ifName;
+        mClatInterfaceName = CLAT_PREFIX + ifName;
         mCallback = callback;
-
-        mNwService = INetworkManagementService.Stub.asInterface(
-                ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE));
+        mNwService = nwService;
 
         mNetlinkTracker = new NetlinkTracker(
                 mInterfaceName,
@@ -258,7 +275,22 @@
                     public void update() {
                         sendMessage(EVENT_NETLINK_LINKPROPERTIES_CHANGED);
                     }
-                });
+                }) {
+            @Override
+            public void interfaceAdded(String iface) {
+                if (mClatInterfaceName.equals(iface)) {
+                    mCallback.on464XlatChange(true);
+                }
+            }
+
+            @Override
+            public void interfaceRemoved(String iface) {
+                if (mClatInterfaceName.equals(iface)) {
+                    mCallback.on464XlatChange(false);
+                }
+            }
+        };
+
         try {
             mNwService.registerObserver(mNetlinkTracker);
         } catch (RemoteException e) {
@@ -277,25 +309,6 @@
         super.start();
     }
 
-    /**
-     * A special constructor for use in testing that bypasses some of the more
-     * complicated setup bits.
-     *
-     * TODO: Figure out how to delete this yet preserve testability.
-     */
-    @VisibleForTesting
-    protected IpManager(String ifName, Callback callback) {
-        super(IpManager.class.getSimpleName() + ".test-" + ifName);
-        mTag = getName();
-
-        mInterfaceName = ifName;
-        mCallback = callback;
-
-        mContext = null;
-        mNwService = null;
-        mNetlinkTracker = null;
-    }
-
     @Override
     protected void onQuitting() {
         mCallback.onQuit();
diff --git a/services/net/java/android/net/ip/IpReachabilityMonitor.java b/services/net/java/android/net/ip/IpReachabilityMonitor.java
index 88155f7..5b4fd50 100644
--- a/services/net/java/android/net/ip/IpReachabilityMonitor.java
+++ b/services/net/java/android/net/ip/IpReachabilityMonitor.java
@@ -132,7 +132,7 @@
  */
 public class IpReachabilityMonitor {
     private static final String TAG = "IpReachabilityMonitor";
-    private static final boolean DBG = true;
+    private static final boolean DBG = false;
     private static final boolean VDBG = false;
 
     public interface Callback {
diff --git a/services/print/java/com/android/server/print/PrintManagerService.java b/services/print/java/com/android/server/print/PrintManagerService.java
index e6f4177..8cfc4a3 100644
--- a/services/print/java/com/android/server/print/PrintManagerService.java
+++ b/services/print/java/com/android/server/print/PrintManagerService.java
@@ -41,13 +41,16 @@
 import android.print.IPrintDocumentAdapter;
 import android.print.IPrintJobStateChangeListener;
 import android.print.IPrintManager;
+import android.print.IPrintServicesChangeListener;
 import android.print.IPrinterDiscoveryObserver;
 import android.print.PrintAttributes;
 import android.print.PrintJobId;
 import android.print.PrintJobInfo;
+import android.print.PrintManager;
 import android.print.PrinterId;
 import android.printservice.PrintServiceInfo;
 import android.provider.Settings;
+import android.util.Log;
 import android.util.SparseArray;
 
 import com.android.internal.content.PackageMonitor;
@@ -66,6 +69,8 @@
  * PrintManager implementation is contained within.
  */
 public final class PrintManagerService extends SystemService {
+    private static final String LOG_TAG = "PrintManagerService";
+
     private final PrintManagerImpl mPrintManagerImpl;
 
     public PrintManagerService(Context context) {
@@ -253,7 +258,10 @@
         }
 
         @Override
-        public List<PrintServiceInfo> getEnabledPrintServices(int userId) {
+        public List<PrintServiceInfo> getPrintServices(int selectionFlags, int userId) {
+            Preconditions.checkFlagsArgument(selectionFlags,
+                    PrintManager.DISABLED_SERVICES | PrintManager.ENABLED_SERVICES);
+
             final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId);
             final UserState userState;
             synchronized (mLock) {
@@ -262,34 +270,44 @@
                     return null;
                 }
                 userState = getOrCreateUserStateLocked(resolvedUserId);
-
-                // The user state might be updated via the same observer-set as the caller of this
-                // interface. If the caller is called back first the user state is not yet updated
-                // and the user gets and inconsistent view. Hence force an update.
-                userState.updateIfNeededLocked();
             }
             final long identity = Binder.clearCallingIdentity();
             try {
-                return userState.getEnabledPrintServices();
+                return userState.getPrintServices(selectionFlags);
             } finally {
                 Binder.restoreCallingIdentity(identity);
             }
         }
 
         @Override
-        public List<PrintServiceInfo> getInstalledPrintServices(int userId) {
+        public void setPrintServiceEnabled(ComponentName service, boolean isEnabled, int userId) {
             final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId);
+            final int appId = UserHandle.getAppId(Binder.getCallingUid());
+
+            try {
+                if (appId != Process.SYSTEM_UID && appId != UserHandle.getAppId(
+                        mContext.getPackageManager().getPackageUidAsUser(
+                                PrintManager.PRINT_SPOOLER_PACKAGE_NAME, resolvedUserId))) {
+                    throw new SecurityException("Only system and print spooler can call this");
+                }
+            } catch (PackageManager.NameNotFoundException e) {
+                Log.e(LOG_TAG, "Could not verify caller", e);
+                return;
+            }
+
+            service = Preconditions.checkNotNull(service);
+
             final UserState userState;
             synchronized (mLock) {
-                // Only the current group members can get installed services.
+                // Only the current group members can enable / disable services.
                 if (resolveCallingProfileParentLocked(resolvedUserId) != getCurrentUserId()) {
-                    return null;
+                    return;
                 }
                 userState = getOrCreateUserStateLocked(resolvedUserId);
             }
             final long identity = Binder.clearCallingIdentity();
             try {
-                return userState.getInstalledPrintServices();
+                userState.setPrintServiceEnabled(service, isEnabled);
             } finally {
                 Binder.restoreCallingIdentity(identity);
             }
@@ -496,6 +514,50 @@
         }
 
         @Override
+        public void addPrintServicesChangeListener(IPrintServicesChangeListener listener,
+                int userId) throws RemoteException {
+            listener = Preconditions.checkNotNull(listener);
+
+            final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId);
+            final UserState userState;
+            synchronized (mLock) {
+                // Only the current group members can add a print services listener.
+                if (resolveCallingProfileParentLocked(resolvedUserId) != getCurrentUserId()) {
+                    return;
+                }
+                userState = getOrCreateUserStateLocked(resolvedUserId);
+            }
+            final long identity = Binder.clearCallingIdentity();
+            try {
+                userState.addPrintServicesChangeListener(listener);
+            } finally {
+                Binder.restoreCallingIdentity(identity);
+            }
+        }
+
+        @Override
+        public void removePrintServicesChangeListener(IPrintServicesChangeListener listener,
+                int userId) {
+            listener = Preconditions.checkNotNull(listener);
+
+            final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId);
+            final UserState userState;
+            synchronized (mLock) {
+                // Only the current group members can remove a print job listener.
+                if (resolveCallingProfileParentLocked(resolvedUserId) != getCurrentUserId()) {
+                    return;
+                }
+                userState = getOrCreateUserStateLocked(resolvedUserId);
+            }
+            final long identity = Binder.clearCallingIdentity();
+            try {
+                userState.removePrintServicesChangeListener(listener);
+            } finally {
+                Binder.restoreCallingIdentity(identity);
+            }
+        }
+
+        @Override
         public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
             fd = Preconditions.checkNotNull(fd);
             pw = Preconditions.checkNotNull(pw);
@@ -550,43 +612,79 @@
 
         private void registerBroadcastReceivers() {
             PackageMonitor monitor = new PackageMonitor() {
-                private void updateServices(String packageName) {
-                    if (!mUserManager.isUserUnlocked(getChangingUserId())) return;
-                    synchronized (mLock) {
-                        // A background user/profile's print jobs are running but there is
-                        // no UI shown. Hence, if the packages of such a user change we need
-                        // to handle it as the change may affect ongoing print jobs.
-                        boolean servicesChanged = false;
-                        UserState userState = getOrCreateUserStateLocked(getChangingUserId());
+                /**
+                 * Checks if the package contains a print service.
+                 *
+                 * @param packageName The name of the package
+                 *
+                 * @return true iff the package contains a print service
+                 */
+                private boolean hasPrintService(String packageName) {
+                    Intent intent = new Intent(android.printservice.PrintService.SERVICE_INTERFACE);
+                    intent.setPackage(packageName);
 
-                        List<PrintServiceInfo> installedServices = userState
-                                .getInstalledPrintServices();
-                        final int numInstalledServices = installedServices.size();
-                        for (int i = 0; i < numInstalledServices; i++) {
-                            if (installedServices.get(i).getResolveInfo().serviceInfo.packageName
-                                    .equals(packageName)) {
-                                servicesChanged = true;
-                                break;
-                            }
-                        }
-                        if (servicesChanged) {
-                            userState.updateIfNeededLocked();
+                    List<ResolveInfo> installedServices = mContext.getPackageManager()
+                            .queryIntentServicesAsUser(intent,
+                                    GET_SERVICES | MATCH_DEBUG_TRIAGED_MISSING,
+                                    getChangingUserId());
+
+                    return installedServices != null && !installedServices.isEmpty();
+                }
+
+                /**
+                 * Checks if there is a print service currently registered for this package.
+                 *
+                 * @param userState The userstate for the current user
+                 * @param packageName The name of the package
+                 *
+                 * @return true iff the package contained (and might still contain) a print service
+                 */
+                private boolean hadPrintService(@NonNull UserState userState, String packageName) {
+                    List<PrintServiceInfo> installedServices = userState
+                            .getPrintServices(PrintManager.ALL_SERVICES);
+
+                    if (installedServices == null) {
+                        return false;
+                    }
+
+                    final int numInstalledServices = installedServices.size();
+                    for (int i = 0; i < numInstalledServices; i++) {
+                        if (installedServices.get(i).getResolveInfo().serviceInfo.packageName
+                                .equals(packageName)) {
+                            return true;
                         }
                     }
+
+                    return false;
                 }
 
                 @Override
                 public void onPackageModified(String packageName) {
                     if (!mUserManager.isUserUnlocked(getChangingUserId())) return;
-                    updateServices(packageName);
-                    getOrCreateUserStateLocked(getChangingUserId()).prunePrintServices();
+                    UserState userState = getOrCreateUserStateLocked(getChangingUserId());
+
+                    synchronized (mLock) {
+                        if (hadPrintService(userState, packageName)
+                                || hasPrintService(packageName)) {
+                            userState.updateIfNeededLocked();
+                        }
+                    }
+
+                    userState.prunePrintServices();
                 }
 
                 @Override
                 public void onPackageRemoved(String packageName, int uid) {
                     if (!mUserManager.isUserUnlocked(getChangingUserId())) return;
-                    updateServices(packageName);
-                    getOrCreateUserStateLocked(getChangingUserId()).prunePrintServices();
+                    UserState userState = getOrCreateUserStateLocked(getChangingUserId());
+
+                    synchronized (mLock) {
+                        if (hadPrintService(userState, packageName)) {
+                            userState.updateIfNeededLocked();
+                        }
+                    }
+
+                    userState.prunePrintServices();
                 }
 
                 @Override
@@ -601,7 +699,7 @@
                         boolean stoppedSomePackages = false;
 
                         List<PrintServiceInfo> enabledServices = userState
-                                .getEnabledPrintServices();
+                                .getPrintServices(PrintManager.ENABLED_SERVICES);
                         if (enabledServices == null) {
                             return false;
                         }
@@ -630,21 +728,11 @@
                 @Override
                 public void onPackageAdded(String packageName, int uid) {
                     if (!mUserManager.isUserUnlocked(getChangingUserId())) return;
-
-                    // A background user/profile's print jobs are running but there is
-                    // no UI shown. Hence, if the packages of such a user change we need
-                    // to handle it as the change may affect ongoing print jobs.
-                    Intent intent = new Intent(android.printservice.PrintService.SERVICE_INTERFACE);
-                    intent.setPackage(packageName);
-
-                    List<ResolveInfo> installedServices = mContext.getPackageManager()
-                            .queryIntentServicesAsUser(intent,
-                                    GET_SERVICES | MATCH_DEBUG_TRIAGED_MISSING,
-                                    getChangingUserId());
-
-                    if (installedServices != null) {
-                        UserState userState = getOrCreateUserStateLocked(getChangingUserId());
-                        userState.updateIfNeededLocked();
+                    synchronized (mLock) {
+                        if (hasPrintService(packageName)) {
+                            UserState userState = getOrCreateUserStateLocked(getChangingUserId());
+                            userState.updateIfNeededLocked();
+                        }
                     }
                 }
             };
diff --git a/services/print/java/com/android/server/print/RemotePrintSpooler.java b/services/print/java/com/android/server/print/RemotePrintSpooler.java
index d179b95..e1d8c6c 100644
--- a/services/print/java/com/android/server/print/RemotePrintSpooler.java
+++ b/services/print/java/com/android/server/print/RemotePrintSpooler.java
@@ -36,6 +36,7 @@
 import android.print.IPrintSpoolerClient;
 import android.print.PrintJobId;
 import android.print.PrintJobInfo;
+import android.print.PrintManager;
 import android.print.PrinterId;
 import android.printservice.PrintService;
 import android.util.Slog;
@@ -115,8 +116,8 @@
         mCallbacks = callbacks;
         mClient = new PrintSpoolerClient(this);
         mIntent = new Intent();
-        mIntent.setComponent(new ComponentName("com.android.printspooler",
-                "com.android.printspooler.model.PrintSpoolerService"));
+        mIntent.setComponent(new ComponentName(PrintManager.PRINT_SPOOLER_PACKAGE_NAME,
+                PrintManager.PRINT_SPOOLER_PACKAGE_NAME + ".model.PrintSpoolerService"));
     }
 
     public final List<PrintJobInfo> getPrintJobInfos(ComponentName componentName, int state,
diff --git a/services/print/java/com/android/server/print/UserState.java b/services/print/java/com/android/server/print/UserState.java
index fcf2fc8..f2f555b 100644
--- a/services/print/java/com/android/server/print/UserState.java
+++ b/services/print/java/com/android/server/print/UserState.java
@@ -44,6 +44,7 @@
 import android.os.UserHandle;
 import android.print.IPrintDocumentAdapter;
 import android.print.IPrintJobStateChangeListener;
+import android.print.IPrintServicesChangeListener;
 import android.print.IPrinterDiscoveryObserver;
 import android.print.PrintAttributes;
 import android.print.PrintJobId;
@@ -121,6 +122,8 @@
 
     private List<PrintJobStateChangeListenerRecord> mPrintJobStateChangeListenerRecords;
 
+    private List<PrintServicesChangeListenerRecord> mPrintServicesChangeListenerRecords;
+
     private boolean mDestroyed;
 
     public UserState(Context context, int userId, Object lock) {
@@ -342,29 +345,63 @@
         mSpooler.setPrintJobState(printJobId, PrintJobInfo.STATE_QUEUED, null);
     }
 
-    public @Nullable List<PrintServiceInfo> getEnabledPrintServices() {
+    public @Nullable List<PrintServiceInfo> getPrintServices(int selectionFlags) {
         synchronized (mLock) {
-            List<PrintServiceInfo> enabledServices = null;
+            List<PrintServiceInfo> selectedServices = null;
             final int installedServiceCount = mInstalledServices.size();
             for (int i = 0; i < installedServiceCount; i++) {
                 PrintServiceInfo installedService = mInstalledServices.get(i);
+
                 ComponentName componentName = new ComponentName(
                         installedService.getResolveInfo().serviceInfo.packageName,
                         installedService.getResolveInfo().serviceInfo.name);
-                if (mActiveServices.containsKey(componentName)) {
-                    if (enabledServices == null) {
-                        enabledServices = new ArrayList<PrintServiceInfo>();
+
+                // Update isEnabled under the same lock the final returned list is created
+                installedService.setIsEnabled(mActiveServices.containsKey(componentName));
+
+                if (installedService.isEnabled()) {
+                    if ((selectionFlags & PrintManager.ENABLED_SERVICES) == 0) {
+                        continue;
                     }
-                    enabledServices.add(installedService);
+                } else {
+                    if ((selectionFlags & PrintManager.DISABLED_SERVICES) == 0) {
+                        continue;
+                    }
                 }
+
+                if (selectedServices == null) {
+                    selectedServices = new ArrayList<>();
+                }
+                selectedServices.add(installedService);
             }
-            return enabledServices;
+            return selectedServices;
         }
     }
 
-    public List<PrintServiceInfo> getInstalledPrintServices() {
+    public void setPrintServiceEnabled(@NonNull ComponentName serviceName, boolean isEnabled) {
         synchronized (mLock) {
-            return mInstalledServices;
+            boolean isChanged = false;
+            if (isEnabled) {
+                isChanged = mDisabledServices.remove(serviceName);
+            } else {
+                // Make sure to only disable services that are currently installed
+                final int numServices = mInstalledServices.size();
+                for (int i = 0; i < numServices; i++) {
+                    PrintServiceInfo service = mInstalledServices.get(i);
+
+                    if (service.getComponentName().equals(serviceName)) {
+                        mDisabledServices.add(serviceName);
+                        isChanged = true;
+                        break;
+                    }
+                }
+            }
+
+            if (isChanged) {
+                writeDisabledPrintServicesLocked(mDisabledServices);
+
+                onConfigurationChangedLocked();
+            }
         }
     }
 
@@ -523,6 +560,44 @@
         }
     }
 
+    public void addPrintServicesChangeListener(@NonNull IPrintServicesChangeListener listener)
+            throws RemoteException {
+        synchronized (mLock) {
+            throwIfDestroyedLocked();
+            if (mPrintServicesChangeListenerRecords == null) {
+                mPrintServicesChangeListenerRecords = new ArrayList<>();
+            }
+            mPrintServicesChangeListenerRecords.add(
+                    new PrintServicesChangeListenerRecord(listener) {
+                        @Override
+                        public void onBinderDied() {
+                            mPrintServicesChangeListenerRecords.remove(this);
+                        }
+                    });
+        }
+    }
+
+    public void removePrintServicesChangeListener(@NonNull IPrintServicesChangeListener listener) {
+        synchronized (mLock) {
+            throwIfDestroyedLocked();
+            if (mPrintServicesChangeListenerRecords == null) {
+                return;
+            }
+            final int recordCount = mPrintServicesChangeListenerRecords.size();
+            for (int i = 0; i < recordCount; i++) {
+                PrintServicesChangeListenerRecord record =
+                        mPrintServicesChangeListenerRecords.get(i);
+                if (record.listener.asBinder().equals(listener.asBinder())) {
+                    mPrintServicesChangeListenerRecords.remove(i);
+                    break;
+                }
+            }
+            if (mPrintServicesChangeListenerRecords.isEmpty()) {
+                mPrintServicesChangeListenerRecords = null;
+            }
+        }
+    }
+
     @Override
     public void onPrintJobStateChanged(PrintJobInfo printJob) {
         mPrintJobForAppCache.onPrintJobStateChanged(printJob);
@@ -530,6 +605,10 @@
                 printJob.getAppId(), 0, printJob.getId()).sendToTarget();
     }
 
+    public void onPrintServicesChanged() {
+        mHandler.obtainMessage(UserStateHandler.MSG_DISPATCH_PRINT_SERVICES_CHANGED).sendToTarget();
+    }
+
     @Override
     public void onPrintersAdded(List<PrinterInfo> printers) {
         synchronized (mLock) {
@@ -894,6 +973,8 @@
                 iterator.remove();
             }
         }
+
+        onPrintServicesChanged();
     }
 
     private void addServiceLocked(RemotePrintService service) {
@@ -978,8 +1059,29 @@
         }
     }
 
+    private void handleDispatchPrintServicesChanged() {
+        final List<PrintServicesChangeListenerRecord> records;
+        synchronized (mLock) {
+            if (mPrintServicesChangeListenerRecords == null) {
+                return;
+            }
+            records = new ArrayList<>(mPrintServicesChangeListenerRecords);
+        }
+        final int recordCount = records.size();
+        for (int i = 0; i < recordCount; i++) {
+            PrintServicesChangeListenerRecord record = records.get(i);
+
+            try {
+                record.listener.onPrintServicesChanged();;
+            } catch (RemoteException re) {
+                Log.e(LOG_TAG, "Error notifying for print services change", re);
+            }
+        }
+    }
+
     private final class UserStateHandler extends Handler {
         public static final int MSG_DISPATCH_PRINT_JOB_STATE_CHANGED = 1;
+        public static final int MSG_DISPATCH_PRINT_SERVICES_CHANGED = 2;
 
         public UserStateHandler(Looper looper) {
             super(looper, null, false);
@@ -987,10 +1089,17 @@
 
         @Override
         public void handleMessage(Message message) {
-            if (message.what == MSG_DISPATCH_PRINT_JOB_STATE_CHANGED) {
-                PrintJobId printJobId = (PrintJobId) message.obj;
-                final int appId = message.arg1;
-                handleDispatchPrintJobStateChanged(printJobId, appId);
+            switch (message.what) {
+                case MSG_DISPATCH_PRINT_JOB_STATE_CHANGED:
+                    PrintJobId printJobId = (PrintJobId) message.obj;
+                    final int appId = message.arg1;
+                    handleDispatchPrintJobStateChanged(printJobId, appId);
+                    break;
+                case MSG_DISPATCH_PRINT_SERVICES_CHANGED:
+                    handleDispatchPrintServicesChanged();
+                    break;
+                default:
+                    // not reached
             }
         }
     }
@@ -1015,6 +1124,23 @@
         public abstract void onBinderDied();
     }
 
+    private abstract class PrintServicesChangeListenerRecord implements DeathRecipient {
+        @NonNull final IPrintServicesChangeListener listener;
+
+        public PrintServicesChangeListenerRecord(@NonNull IPrintServicesChangeListener listener) throws RemoteException {
+            this.listener = listener;
+            listener.asBinder().linkToDeath(this, 0);
+        }
+
+        @Override
+        public void binderDied() {
+            listener.asBinder().unlinkToDeath(this, 0);
+            onBinderDied();
+        }
+
+        public abstract void onBinderDied();
+    }
+
     private class PrinterDiscoverySessionMediator {
         private final ArrayMap<PrinterId, PrinterInfo> mPrinters =
                 new ArrayMap<PrinterId, PrinterInfo>();
diff --git a/services/tests/servicestests/AndroidManifest.xml b/services/tests/servicestests/AndroidManifest.xml
index 3ae1072..23f186c 100644
--- a/services/tests/servicestests/AndroidManifest.xml
+++ b/services/tests/servicestests/AndroidManifest.xml
@@ -106,6 +106,10 @@
 
         <service android:name="com.android.server.job.MockPriorityJobService"
                  android:permission="android.permission.BIND_JOB_SERVICE" />
+
+        <activity android:name="com.android.server.pm.ShortcutManagerTest$ShortcutActivity" />
+        <activity android:name="com.android.server.pm.ShortcutManagerTest$ShortcutActivity2" />
+        <activity android:name="com.android.server.pm.ShortcutManagerTest$ShortcutActivity3" />
     </application>
 
     <instrumentation
diff --git a/services/tests/servicestests/res/drawable-nodpi/black_1024x4096.png b/services/tests/servicestests/res/drawable-nodpi/black_1024x4096.png
new file mode 100644
index 0000000..f700326
--- /dev/null
+++ b/services/tests/servicestests/res/drawable-nodpi/black_1024x4096.png
Binary files differ
diff --git a/services/tests/servicestests/res/drawable-nodpi/black_16x64.png b/services/tests/servicestests/res/drawable-nodpi/black_16x64.png
new file mode 100644
index 0000000..315763e
--- /dev/null
+++ b/services/tests/servicestests/res/drawable-nodpi/black_16x64.png
Binary files differ
diff --git a/services/tests/servicestests/res/drawable-nodpi/black_32x32.png b/services/tests/servicestests/res/drawable-nodpi/black_32x32.png
new file mode 100644
index 0000000..8958f6b
--- /dev/null
+++ b/services/tests/servicestests/res/drawable-nodpi/black_32x32.png
Binary files differ
diff --git a/services/tests/servicestests/res/drawable-nodpi/black_4096x1024.png b/services/tests/servicestests/res/drawable-nodpi/black_4096x1024.png
new file mode 100644
index 0000000..f675030
--- /dev/null
+++ b/services/tests/servicestests/res/drawable-nodpi/black_4096x1024.png
Binary files differ
diff --git a/services/tests/servicestests/res/drawable-nodpi/black_4096x4096.png b/services/tests/servicestests/res/drawable-nodpi/black_4096x4096.png
new file mode 100644
index 0000000..999d858
--- /dev/null
+++ b/services/tests/servicestests/res/drawable-nodpi/black_4096x4096.png
Binary files differ
diff --git a/services/tests/servicestests/res/drawable-nodpi/black_512x512.png b/services/tests/servicestests/res/drawable-nodpi/black_512x512.png
new file mode 100644
index 0000000..40d1c2c
--- /dev/null
+++ b/services/tests/servicestests/res/drawable-nodpi/black_512x512.png
Binary files differ
diff --git a/services/tests/servicestests/res/drawable-nodpi/black_64x16.png b/services/tests/servicestests/res/drawable-nodpi/black_64x16.png
new file mode 100644
index 0000000..5883015
--- /dev/null
+++ b/services/tests/servicestests/res/drawable-nodpi/black_64x16.png
Binary files differ
diff --git a/services/tests/servicestests/res/drawable-nodpi/black_64x64.png b/services/tests/servicestests/res/drawable-nodpi/black_64x64.png
new file mode 100644
index 0000000..71cfafc
--- /dev/null
+++ b/services/tests/servicestests/res/drawable-nodpi/black_64x64.png
Binary files differ
diff --git a/services/tests/servicestests/res/drawable-nodpi/icon1.png b/services/tests/servicestests/res/drawable-nodpi/icon1.png
new file mode 100644
index 0000000..64eb294
--- /dev/null
+++ b/services/tests/servicestests/res/drawable-nodpi/icon1.png
Binary files differ
diff --git a/services/tests/servicestests/res/drawable-nodpi/icon2.png b/services/tests/servicestests/res/drawable-nodpi/icon2.png
new file mode 100644
index 0000000..7502484
--- /dev/null
+++ b/services/tests/servicestests/res/drawable-nodpi/icon2.png
Binary files differ
diff --git a/services/tests/servicestests/res/drawable/icon1.png b/services/tests/servicestests/res/drawable/icon1.png
new file mode 100644
index 0000000..64eb294
--- /dev/null
+++ b/services/tests/servicestests/res/drawable/icon1.png
Binary files differ
diff --git a/services/tests/servicestests/res/drawable/icon2.png b/services/tests/servicestests/res/drawable/icon2.png
new file mode 100644
index 0000000..7502484
--- /dev/null
+++ b/services/tests/servicestests/res/drawable/icon2.png
Binary files differ
diff --git a/services/tests/servicestests/src/android/net/dhcp/DhcpPacketTest.java b/services/tests/servicestests/src/android/net/dhcp/DhcpPacketTest.java
index 2a967e6..c322ab8 100644
--- a/services/tests/servicestests/src/android/net/dhcp/DhcpPacketTest.java
+++ b/services/tests/servicestests/src/android/net/dhcp/DhcpPacketTest.java
@@ -558,6 +558,39 @@
     }
 
     @SmallTest
+    public void testUdpInvalidDstPort() throws Exception {
+        final ByteBuffer packet = ByteBuffer.wrap(HexEncoding.decode((
+            // Ethernet header.
+            "9cd917000000001c2e0000000800" +
+            // IP header.
+            "45a00148000040003d115087d18194fb0a0f7af2" +
+            // UDP header. TODO: fix invalid checksum (due to MAC address obfuscation).
+            // NOTE: The destination port is a non-DHCP port.
+            "0043aaaa01341268" +
+            // BOOTP header.
+            "02010600d628ba8200000000000000000a0f7af2000000000a0fc818" +
+            // MAC address.
+            "9cd91700000000000000000000000000" +
+            // Server name.
+            "0000000000000000000000000000000000000000000000000000000000000000" +
+            "0000000000000000000000000000000000000000000000000000000000000000" +
+            // File.
+            "0000000000000000000000000000000000000000000000000000000000000000" +
+            "0000000000000000000000000000000000000000000000000000000000000000" +
+            "0000000000000000000000000000000000000000000000000000000000000000" +
+            "0000000000000000000000000000000000000000000000000000000000000000" +
+            // Options.
+            "6382536335010236040a0169fc3304000151800104ffff000003040a0fc817060cd1818003d1819403" +
+            "d18180060f0777766d2e6564751c040a0fffffff000000"
+        ).toCharArray(), false));
+
+        try {
+            DhcpPacket.decodeFullPacket(packet, ENCAP_L2);
+            fail("Packet with invalid dst port did not throw ParseException");
+        } catch (ParseException expected) {}
+    }
+
+    @SmallTest
     public void testMultipleRouters() throws Exception {
         final ByteBuffer packet = ByteBuffer.wrap(HexEncoding.decode((
             // Ethernet header.
diff --git a/services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java b/services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java
index 5874429..69f12eb 100644
--- a/services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java
@@ -59,14 +59,17 @@
 import android.os.MessageQueue;
 import android.os.Messenger;
 import android.os.MessageQueue.IdleHandler;
+import android.os.SystemClock;
 import android.test.AndroidTestCase;
 import android.test.suitebuilder.annotation.LargeTest;
 import android.test.suitebuilder.annotation.SmallTest;
 import android.util.Log;
 import android.util.LogPrinter;
 
+import com.android.internal.util.WakeupMessage;
 import com.android.server.connectivity.NetworkAgentInfo;
 import com.android.server.connectivity.NetworkMonitor;
+import com.android.server.net.NetworkPinner;
 
 import java.net.InetAddress;
 import java.util.concurrent.CountDownLatch;
@@ -87,10 +90,30 @@
 
     private BroadcastInterceptingContext mServiceContext;
     private WrappedConnectivityService mService;
-    private ConnectivityManager mCm;
+    private WrappedConnectivityManager mCm;
     private MockNetworkAgent mWiFiNetworkAgent;
     private MockNetworkAgent mCellNetworkAgent;
 
+    // This class exists to test bindProcessToNetwork and getBoundNetworkForProcess. These methods
+    // do not go through ConnectivityService but talk to netd directly, so they don't automatically
+    // reflect the state of our test ConnectivityService.
+    private class WrappedConnectivityManager extends ConnectivityManager {
+        private Network mFakeBoundNetwork;
+
+        public synchronized boolean bindProcessToNetwork(Network network) {
+            mFakeBoundNetwork = network;
+            return true;
+        }
+
+        public synchronized Network getBoundNetworkForProcess() {
+            return mFakeBoundNetwork;
+        }
+
+        public WrappedConnectivityManager(Context context, ConnectivityService service) {
+            super(context, service);
+        }
+    }
+
     private class MockContext extends BroadcastInterceptingContext {
         MockContext(Context base) {
             super(base);
@@ -484,6 +507,35 @@
         }
     }
 
+    private class FakeWakeupMessage extends WakeupMessage {
+        private static final int UNREASONABLY_LONG_WAIT = 1000;
+
+        public FakeWakeupMessage(Context context, Handler handler, String cmdName, int cmd) {
+            super(context, handler, cmdName, cmd);
+        }
+
+        @Override
+        public void schedule(long when) {
+            long delayMs = when - SystemClock.elapsedRealtime();
+            if (delayMs < 0) delayMs = 0;
+            if (delayMs > UNREASONABLY_LONG_WAIT) {
+                fail("Attempting to send msg more than " + UNREASONABLY_LONG_WAIT +
+                        "ms into the future: " + delayMs);
+            }
+            mHandler.sendEmptyMessageDelayed(mCmd, delayMs);
+        }
+
+        @Override
+        public void cancel() {
+            mHandler.removeMessages(mCmd);
+        }
+
+        @Override
+        public void onAlarm() {
+            throw new AssertionError("Should never happen. Update this fake.");
+        }
+    }
+
     // NetworkMonitor implementation allowing overriding of Internet connectivity probe result.
     private class WrappedNetworkMonitor extends NetworkMonitor {
         // HTTP response code fed back to NetworkMonitor for Internet connectivity probe.
@@ -498,6 +550,12 @@
         protected int isCaptivePortal() {
             return gen204ProbeResult;
         }
+
+        @Override
+        protected WakeupMessage makeWakeupMessage(
+                Context context, Handler handler, String cmdName, int cmd) {
+            return new FakeWakeupMessage(context, handler, cmdName, cmd);
+        }
     }
 
     private class WrappedConnectivityService extends ConnectivityService {
@@ -575,10 +633,10 @@
         int delays = 0;
         while (!criteria.get()) {
             try {
-                Thread.sleep(100);
+                Thread.sleep(50);
             } catch (InterruptedException e) {
             }
-            if (++delays == 5) fail();
+            if (++delays == 10) fail();
         }
     }
 
@@ -594,6 +652,8 @@
     public void setUp() throws Exception {
         super.setUp();
 
+        NetworkMonitor.SetDefaultLingerTime(120);
+
         // InstrumentationTestRunner prepares a looper, but AndroidJUnitRunner does not.
         // http://b/25897652 .
         if (Looper.myLooper() == null) {
@@ -607,7 +667,8 @@
                 mock(INetworkPolicyManager.class));
 
         mService.systemReady();
-        mCm = new ConnectivityManager(getContext(), mService);
+        mCm = new WrappedConnectivityManager(getContext(), mService);
+        mCm.bindProcessToNetwork(null);
     }
 
     private int transportToLegacyType(int transport) {
@@ -674,8 +735,6 @@
 
     @LargeTest
     public void testLingering() throws Exception {
-        // Decrease linger timeout to the minimum allowed by AlarmManagerService.
-        NetworkMonitor.SetDefaultLingerTime(5000);
         verifyNoNetwork();
         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
@@ -702,10 +761,8 @@
         assertTrue(mCm.getAllNetworks()[0].equals(mCellNetworkAgent.getNetwork()) ||
                 mCm.getAllNetworks()[1].equals(mCellNetworkAgent.getNetwork()));
         // Test cellular linger timeout.
-        try {
-            Thread.sleep(6000);
-        } catch (InterruptedException e) {
-        }
+        waitFor(new Criteria() {
+                public boolean get() { return mCm.getAllNetworks().length == 1; } });
         verifyActiveNetwork(TRANSPORT_WIFI);
         assertEquals(1, mCm.getAllNetworks().length);
         assertEquals(mCm.getAllNetworks()[0], mCm.getActiveNetwork());
@@ -1543,4 +1600,103 @@
         String url = mCm.getCaptivePortalServerUrl();
         assertEquals("http://connectivitycheck.gstatic.com/generate_204", url);
     }
+
+    private static class TestNetworkPinner extends NetworkPinner {
+        public static boolean awaitPin(int timeoutMs) {
+            synchronized(sLock) {
+                if (sNetwork == null) {
+                    try {
+                        sLock.wait(timeoutMs);
+                    } catch (InterruptedException e) {}
+                }
+                return sNetwork != null;
+            }
+        }
+
+        public static boolean awaitUnpin(int timeoutMs) {
+            synchronized(sLock) {
+                if (sNetwork != null) {
+                    try {
+                        sLock.wait(timeoutMs);
+                    } catch (InterruptedException e) {}
+                }
+                return sNetwork == null;
+            }
+        }
+    }
+
+    private void assertPinnedToWifiWithCellDefault() {
+        assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getBoundNetworkForProcess());
+        assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
+    }
+
+    private void assertPinnedToWifiWithWifiDefault() {
+        assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getBoundNetworkForProcess());
+        assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
+    }
+
+    private void assertNotPinnedToWifi() {
+        assertNull(mCm.getBoundNetworkForProcess());
+        assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
+    }
+
+    @SmallTest
+    public void testNetworkPinner() {
+        NetworkRequest wifiRequest = new NetworkRequest.Builder()
+                .addTransportType(TRANSPORT_WIFI)
+                .build();
+        assertNull(mCm.getBoundNetworkForProcess());
+
+        TestNetworkPinner.pin(mServiceContext, wifiRequest);
+        assertNull(mCm.getBoundNetworkForProcess());
+
+        mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
+        mCellNetworkAgent.connect(true);
+        mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
+        mWiFiNetworkAgent.connect(false);
+
+        // When wi-fi connects, expect to be pinned.
+        assertTrue(TestNetworkPinner.awaitPin(100));
+        assertPinnedToWifiWithCellDefault();
+
+        // Disconnect and expect the pin to drop.
+        mWiFiNetworkAgent.disconnect();
+        assertTrue(TestNetworkPinner.awaitUnpin(100));
+        assertNotPinnedToWifi();
+
+        // Reconnecting does not cause the pin to come back.
+        mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
+        mWiFiNetworkAgent.connect(false);
+        assertFalse(TestNetworkPinner.awaitPin(100));
+        assertNotPinnedToWifi();
+
+        // Pinning while connected causes the pin to take effect immediately.
+        TestNetworkPinner.pin(mServiceContext, wifiRequest);
+        assertTrue(TestNetworkPinner.awaitPin(100));
+        assertPinnedToWifiWithCellDefault();
+
+        // Explicitly unpin and expect to use the default network again.
+        TestNetworkPinner.unpin();
+        assertNotPinnedToWifi();
+
+        // Disconnect cell and wifi.
+        ConditionVariable cv = waitForConnectivityBroadcasts(3);  // cell down, wifi up, wifi down.
+        mCellNetworkAgent.disconnect();
+        mWiFiNetworkAgent.disconnect();
+        waitFor(cv);
+
+        // Pinning takes effect even if the pinned network is the default when the pin is set...
+        TestNetworkPinner.pin(mServiceContext, wifiRequest);
+        mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
+        mWiFiNetworkAgent.connect(false);
+        assertTrue(TestNetworkPinner.awaitPin(100));
+        assertPinnedToWifiWithWifiDefault();
+
+        // ... and is maintained even when that network is no longer the default.
+        cv = waitForConnectivityBroadcasts(1);
+        mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
+        mCellNetworkAgent.connect(true);
+        waitFor(cv);
+        assertPinnedToWifiWithCellDefault();
+    }
 }
diff --git a/services/tests/servicestests/src/com/android/server/DropBoxTest.java b/services/tests/servicestests/src/com/android/server/DropBoxTest.java
index 055ce76..7f28d44 100644
--- a/services/tests/servicestests/src/com/android/server/DropBoxTest.java
+++ b/services/tests/servicestests/src/com/android/server/DropBoxTest.java
@@ -54,7 +54,7 @@
     public void testAddText() throws Exception {
         File dir = getEmptyDir("testAddText");
         DropBoxManagerService service = new DropBoxManagerService(getContext(), dir);
-        DropBoxManager dropbox = new DropBoxManager(service.getServiceStub());
+        DropBoxManager dropbox = new DropBoxManager(getContext(), service.getServiceStub());
 
         long before = System.currentTimeMillis();
         Thread.sleep(5);
@@ -90,7 +90,7 @@
     public void testAddData() throws Exception {
         File dir = getEmptyDir("testAddData");
         DropBoxManagerService service = new DropBoxManagerService(getContext(), dir);
-        DropBoxManager dropbox = new DropBoxManager(service.getServiceStub());
+        DropBoxManager dropbox = new DropBoxManager(getContext(), service.getServiceStub());
 
         long before = System.currentTimeMillis();
         dropbox.addData("DropBoxTest", "TEST".getBytes(), 0);
@@ -135,7 +135,7 @@
         gz3.close();
 
         DropBoxManagerService service = new DropBoxManagerService(getContext(), dir);
-        DropBoxManager dropbox = new DropBoxManager(service.getServiceStub());
+        DropBoxManager dropbox = new DropBoxManager(getContext(), service.getServiceStub());
 
         dropbox.addFile("DropBoxTest", f0, DropBoxManager.IS_TEXT);
         dropbox.addFile("DropBoxTest", f1, DropBoxManager.IS_TEXT | DropBoxManager.IS_GZIPPED);
@@ -201,7 +201,7 @@
         new FileOutputStream(new File(dir, "DropBoxTest@" + (before + 100002) + ".lost")).close();
 
         DropBoxManagerService service = new DropBoxManagerService(getContext(), dir);
-        DropBoxManager dropbox = new DropBoxManager(service.getServiceStub());
+        DropBoxManager dropbox = new DropBoxManager(getContext(), service.getServiceStub());
 
         // Until a write, the timestamps are taken at face value
         DropBoxManager.Entry e0 = dropbox.getNextEntry(null, before);
@@ -252,7 +252,7 @@
     public void testIsTagEnabled() throws Exception {
         File dir = getEmptyDir("testIsTagEnabled");
         DropBoxManagerService service = new DropBoxManagerService(getContext(), dir);
-        DropBoxManager dropbox = new DropBoxManager(service.getServiceStub());
+        DropBoxManager dropbox = new DropBoxManager(getContext(), service.getServiceStub());
 
         long before = System.currentTimeMillis();
         dropbox.addText("DropBoxTest", "TEST-ENABLED");
@@ -285,7 +285,7 @@
     public void testGetNextEntry() throws Exception {
         File dir = getEmptyDir("testGetNextEntry");
         DropBoxManagerService service = new DropBoxManagerService(getContext(), dir);
-        DropBoxManager dropbox = new DropBoxManager(service.getServiceStub());
+        DropBoxManager dropbox = new DropBoxManager(getContext(), service.getServiceStub());
 
         long before = System.currentTimeMillis();
         dropbox.addText("DropBoxTest.A", "A0");
@@ -347,7 +347,7 @@
         final int overhead = 64;
         long before = System.currentTimeMillis();
         DropBoxManagerService service = new DropBoxManagerService(getContext(), dir);
-        DropBoxManager dropbox = new DropBoxManager(service.getServiceStub());
+        DropBoxManager dropbox = new DropBoxManager(getContext(), service.getServiceStub());
 
         addRandomEntry(dropbox, "DropBoxTest0", blockSize - overhead);
         addRandomEntry(dropbox, "DropBoxTest0", blockSize - overhead);
@@ -441,7 +441,7 @@
         // Write one normal entry and another so big that it is instantly tombstoned
         long before = System.currentTimeMillis();
         DropBoxManagerService service = new DropBoxManagerService(getContext(), dir);
-        DropBoxManager dropbox = new DropBoxManager(service.getServiceStub());
+        DropBoxManager dropbox = new DropBoxManager(getContext(), service.getServiceStub());
 
         dropbox.addText("DropBoxTest", "TEST");
         addRandomEntry(dropbox, "DropBoxTest", blockSize * 20);
@@ -472,7 +472,7 @@
         File dir = getEmptyDir("testFileCountLimits");
 
         DropBoxManagerService service = new DropBoxManagerService(getContext(), dir);
-        DropBoxManager dropbox = new DropBoxManager(service.getServiceStub());
+        DropBoxManager dropbox = new DropBoxManager(getContext(), service.getServiceStub());
         dropbox.addText("DropBoxTest", "TEST0");
         dropbox.addText("DropBoxTest", "TEST1");
         dropbox.addText("DropBoxTest", "TEST2");
@@ -525,7 +525,7 @@
         File dir = new File(getEmptyDir("testCreateDropBoxManagerWith"), "InvalidDirectory");
         new FileOutputStream(dir).close();  // Create an empty file
         DropBoxManagerService service = new DropBoxManagerService(getContext(), dir);
-        DropBoxManager dropbox = new DropBoxManager(service.getServiceStub());
+        DropBoxManager dropbox = new DropBoxManager(getContext(), service.getServiceStub());
 
         dropbox.addText("DropBoxTest", "should be ignored");
         dropbox.addData("DropBoxTest", "should be ignored".getBytes(), 0);
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 212b37c..e897e3d 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
@@ -969,6 +969,8 @@
 
         mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
 
+        when(mContext.userManagerForMock.isSplitSystemUser()).thenReturn(true);
+
         // Make sure the admin packge is installed to each user.
         setUpPackageManagerForAdmin(admin1, DpmMockContext.CALLER_SYSTEM_USER_UID);
         setUpPackageManagerForAdmin(admin3, DpmMockContext.CALLER_SYSTEM_USER_UID);
@@ -1008,6 +1010,7 @@
      * finds the right component from a package name upon migration.
      */
     public void testDeviceOwnerMigration() throws Exception {
+        when(mContext.userManagerForMock.isSplitSystemUser()).thenReturn(true);
         checkDeviceOwnerWithMultipleDeviceAdmins();
 
         // Overwrite the device owner setting and clears the clas name.
@@ -1441,10 +1444,10 @@
 
         // Test 1. Caller doesn't have DO or DA.
         try {
-            dpm.getWifiMacAddress();
+            dpm.getWifiMacAddress(admin1);
             fail();
         } catch (SecurityException e) {
-            MoreAsserts.assertContainsRegex("No active admin owned", e.getMessage());
+            MoreAsserts.assertContainsRegex("No active admin", e.getMessage());
         }
 
         // DO needs to be an DA.
@@ -1453,19 +1456,19 @@
 
         // Test 2. Caller has DA, but not DO.
         try {
-            dpm.getWifiMacAddress();
+            dpm.getWifiMacAddress(admin1);
             fail();
         } catch (SecurityException e) {
-            MoreAsserts.assertContainsRegex("No active admin owned", e.getMessage());
+            MoreAsserts.assertContainsRegex("does not own the device", e.getMessage());
         }
 
         // Test 3. Caller has PO, but not DO.
         assertTrue(dpm.setProfileOwner(admin1, null, UserHandle.USER_SYSTEM));
         try {
-            dpm.getWifiMacAddress();
+            dpm.getWifiMacAddress(admin1);
             fail();
         } catch (SecurityException e) {
-            MoreAsserts.assertContainsRegex("No active admin owned", e.getMessage());
+            MoreAsserts.assertContainsRegex("does not own the device", e.getMessage());
         }
 
         // Remove PO.
@@ -1475,17 +1478,17 @@
         assertTrue(dpm.setDeviceOwner(admin1, null, UserHandle.USER_SYSTEM));
 
         // 4-1.  But no WifiInfo.
-        assertNull(dpm.getWifiMacAddress());
+        assertNull(dpm.getWifiMacAddress(admin1));
 
         // 4-2.  Returns WifiInfo, but with the default MAC.
         when(mContext.wifiManager.getConnectionInfo()).thenReturn(new WifiInfo());
-        assertNull(dpm.getWifiMacAddress());
+        assertNull(dpm.getWifiMacAddress(admin1));
 
         // 4-3. With a real MAC address.
         final WifiInfo wi = new WifiInfo();
         wi.setMacAddress("11:22:33:44:55:66");
         when(mContext.wifiManager.getConnectionInfo()).thenReturn(wi);
-        assertEquals("11:22:33:44:55:66", dpm.getWifiMacAddress());
+        assertEquals("11:22:33:44:55:66", dpm.getWifiMacAddress(admin1));
     }
 
     public void testRebootCanOnlyBeCalledByDeviceOwner() throws Exception {
diff --git a/services/tests/servicestests/src/com/android/server/notification/RankingHelperTest.java b/services/tests/servicestests/src/com/android/server/notification/RankingHelperTest.java
index f1fe346..32501ad 100644
--- a/services/tests/servicestests/src/com/android/server/notification/RankingHelperTest.java
+++ b/services/tests/servicestests/src/com/android/server/notification/RankingHelperTest.java
@@ -15,12 +15,6 @@
  */
 package com.android.server.notification;
 
-import static android.service.notification.NotificationListenerService.Ranking.IMPORTANCE_UNSPECIFIED;
-import static android.service.notification.NotificationListenerService.Ranking.IMPORTANCE_HIGH;
-import static android.service.notification.NotificationListenerService.Ranking.IMPORTANCE_LOW;
-import static android.service.notification.NotificationListenerService.Ranking.IMPORTANCE_MAX;
-import static android.service.notification.NotificationListenerService.Ranking.IMPORTANCE_NONE;
-
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 
diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutInfoTest.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutInfoTest.java
new file mode 100644
index 0000000..eb16a1d
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutInfoTest.java
@@ -0,0 +1,44 @@
+
+/*
+ * 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.content.pm.ShortcutInfo;
+import android.test.AndroidTestCase;
+
+import com.android.server.testutis.TestUtils;
+
+/**
+ * Tests for {@link ShortcutInfo}.
+
+ m FrameworksServicesTests &&
+ adb install \
+   -r -g ${ANDROID_PRODUCT_OUT}/data/app/FrameworksServicesTests/FrameworksServicesTests.apk &&
+ adb shell am instrument -e class com.android.server.pm.ShortcutInfoTest \
+   -w com.android.frameworks.servicestests/android.support.test.runner.AndroidJUnitRunner
+
+ */
+public class ShortcutInfoTest extends AndroidTestCase {
+
+    public void testNoId() {
+        TestUtils.assertExpectException(
+                IllegalArgumentException.class,
+                "ID must be provided",
+                () -> new ShortcutInfo.Builder(mContext).build());
+    }
+
+    // TODO Add more tests.
+}
diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest.java
new file mode 100644
index 0000000..f2c42db
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest.java
@@ -0,0 +1,1944 @@
+/*
+ * 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 static org.mockito.Mockito.mock;
+
+import android.annotation.NonNull;
+import android.annotation.UserIdInt;
+import android.app.Activity;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ILauncherApps;
+import android.content.pm.LauncherApps;
+import android.content.pm.LauncherApps.ShortcutQuery;
+import android.content.pm.PackageManager;
+import android.content.pm.ShortcutInfo;
+import android.content.pm.ShortcutManager;
+import android.content.pm.ShortcutServiceInternal;
+import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.Bitmap.CompressFormat;
+import android.graphics.BitmapFactory;
+import android.graphics.drawable.Icon;
+import android.os.BaseBundle;
+import android.os.Bundle;
+import android.os.FileUtils;
+import android.os.ParcelFileDescriptor;
+import android.os.UserHandle;
+import android.os.UserManager;
+import android.test.AndroidTestCase;
+import android.test.mock.MockContext;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.util.Log;
+
+import com.android.frameworks.servicestests.R;
+import com.android.internal.util.Preconditions;
+import com.android.server.LocalServices;
+import com.android.server.SystemService;
+import com.android.server.pm.LauncherAppsService.LauncherAppsImpl;
+import com.android.server.pm.ShortcutService.ConfigConstants;
+import com.android.server.pm.ShortcutService.FileOutputStreamWithPath;
+
+import libcore.io.IoUtils;
+
+import org.junit.Assert;
+
+import java.io.BufferedReader;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileReader;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Tests for ShortcutService and ShortcutManager.
+ *
+ m FrameworksServicesTests &&
+ adb install \
+ -r -g ${ANDROID_PRODUCT_OUT}/data/app/FrameworksServicesTests/FrameworksServicesTests.apk &&
+ adb shell am instrument -e class com.android.server.pm.ShortcutManagerTest \
+ -w com.android.frameworks.servicestests/android.support.test.runner.AndroidJUnitRunner
+
+ * TODO: Add checks with assertAllNotHaveIcon()
+ *
+ * TODO: separate, detailed tests for ShortcutInfo (CTS?) *
+ *
+ * TODO: Cross-user test (do in CTS?)
+ *
+ */
+@SmallTest
+public class ShortcutManagerTest extends AndroidTestCase {
+    private static final String TAG = "ShortcutManagerTest";
+
+    /**
+     * Whether to enable dump or not.  Should be only true when debugging to avoid bugs where
+     * dump affecting the behavior.
+     */
+    private static final boolean ENABLE_DUMP = false; // DO NOT SUBMIT WITH true
+
+    private class BaseContext extends MockContext {
+        @Override
+        public Object getSystemService(String name) {
+            switch (name) {
+                case Context.USER_SERVICE:
+                    return mMockUserManager;
+            }
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public PackageManager getPackageManager() {
+            return mMockPackageManager;
+        }
+
+        @Override
+        public Resources getResources() {
+            return ShortcutManagerTest.this.getContext().getResources();
+        }
+    }
+
+    /** Context used in the client side */
+    private class ClientContext extends BaseContext {
+        @Override
+        public String getPackageName() {
+            return mInjectedClientPackage;
+        }
+    }
+
+    /** Context used in the service side */
+    private final class ServiceContext extends BaseContext {
+    }
+
+    /** ShortcutService with injection override methods. */
+    private final class ShortcutServiceTestable extends ShortcutService {
+        public ShortcutServiceTestable(Context context) {
+            super(context);
+
+        }
+
+        @Override
+        String injectShortcutManagerConstants() {
+            return ConfigConstants.KEY_RESET_INTERVAL_SEC + "=" + (INTERVAL / 1000) + ","
+                    + ConfigConstants.KEY_MAX_SHORTCUTS + "=" + MAX_SHORTCUTS + ","
+                    + ConfigConstants.KEY_MAX_DAILY_UPDATES + "=" + MAX_DAILY_UPDATES + ","
+                    + ConfigConstants.KEY_MAX_ICON_DIMENSION_DP + "=" + MAX_ICON_DIMENSION + ","
+                    + ConfigConstants.KEY_MAX_ICON_DIMENSION_DP_LOWRAM + "="
+                    + MAX_ICON_DIMENSION_LOWRAM + ","
+                    + ConfigConstants.KEY_ICON_FORMAT + "=PNG,"
+                    + ConfigConstants.KEY_ICON_QUALITY + "=100";
+        }
+
+        @Override
+        int injectDipToPixel(int dip) {
+            return dip;
+        }
+
+        @Override
+        long injectCurrentTimeMillis() {
+            return mInjectedCurrentTimeLillis;
+        }
+
+        @Override
+        int injectBinderCallingUid() {
+            return mInjectedCallingUid;
+        }
+
+        @Override
+        int injectGetPackageUid(String packageName, int userId) {
+            Integer uid = mInjectedPackageUidMap.get(packageName);
+            return UserHandle.getUid(getCallingUserId(), (uid != null ? uid : 0));
+        }
+
+        @Override
+        File injectSystemDataPath() {
+            return new File(mInjectedFilePathRoot, "system");
+        }
+
+        @Override
+        File injectUserDataPath(@UserIdInt int userId) {
+            return new File(mInjectedFilePathRoot, "user-" + userId);
+        }
+
+        @Override
+        void injectValidateIconResPackage(ShortcutInfo shortcut, Icon icon) {
+            // Can't check
+        }
+
+        @Override
+        boolean injectIsLowRamDevice() {
+            return mInjectdIsLowRamDevice;
+        }
+    }
+
+    /** ShortcutManager with injection override methods. */
+    private class ShortcutManagerTestable extends ShortcutManager {
+        public ShortcutManagerTestable(Context context, ShortcutServiceTestable service) {
+            super(context, service);
+        }
+
+        @Override
+        protected int injectMyUserId() {
+            return UserHandle.getUserId(mInjectedCallingUid);
+        }
+    }
+
+    private class LauncherAppImplTestable extends LauncherAppsImpl {
+        public LauncherAppImplTestable(Context context) {
+            super(context);
+        }
+
+        @Override
+        public void ensureInUserProfiles(UserHandle userToCheck, String message) {
+            // SKIP
+        }
+
+        @Override
+        public void verifyCallingPackage(String callingPackage) {
+            // SKIP
+        }
+    }
+
+    private class LauncherAppsTestable extends LauncherApps {
+        public LauncherAppsTestable(Context context, ILauncherApps service) {
+            super(context, service);
+        }
+    }
+
+    public static class ShortcutActivity extends Activity {
+    }
+
+    public static class ShortcutActivity2 extends Activity {
+    }
+
+    public static class ShortcutActivity3 extends Activity {
+    }
+
+    private ServiceContext mServiceContext;
+    private ClientContext mClientContext;
+
+    private ShortcutServiceTestable mService;
+    private ShortcutManagerTestable mManager;
+    private ShortcutServiceInternal mInternal;
+
+    private LauncherAppImplTestable mLauncherAppImpl;
+    private LauncherAppsTestable mLauncherApps;
+
+    private File mInjectedFilePathRoot;
+
+    private long mInjectedCurrentTimeLillis;
+
+    private boolean mInjectdIsLowRamDevice;
+
+    private int mInjectedCallingUid;
+    private String mInjectedClientPackage;
+
+    private Map<String, Integer> mInjectedPackageUidMap;
+
+    private PackageManager mMockPackageManager;
+    private UserManager mMockUserManager;
+
+    private static final String CALLING_PACKAGE_1 = "com.android.test.1";
+    private static final int CALLING_UID_1 = 10001;
+
+    private static final String CALLING_PACKAGE_2 = "com.android.test.2";
+    private static final int CALLING_UID_2 = 10002;
+
+    private static final String CALLING_PACKAGE_3 = "com.android.test.3";
+    private static final int CALLING_UID_3 = 10003;
+
+    private static final String LAUNCHER_1 = "com.android.launcher.1";
+    private static final int LAUNCHER_UID_1 = 10011;
+
+    private static final String LAUNCHER_2 = "com.android.launcher.2";
+    private static final int LAUNCHER_UID_2 = 10012;
+
+    private static final int USER_10 = 10;
+    private static final int USER_11 = 11;
+
+    private static final long START_TIME = 1234560000000L;
+
+    private static final long INTERVAL = 10000;
+
+    private static final int MAX_SHORTCUTS = 10;
+
+    private static final int MAX_DAILY_UPDATES = 3;
+
+    private static final int MAX_ICON_DIMENSION = 128;
+
+    private static final int MAX_ICON_DIMENSION_LOWRAM = 32;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        mServiceContext = new ServiceContext();
+        mClientContext = new ClientContext();
+
+        mMockPackageManager = mock(PackageManager.class);
+        mMockUserManager = mock(UserManager.class);
+
+        // Prepare injection values.
+
+        mInjectedCurrentTimeLillis = START_TIME;
+
+        mInjectedPackageUidMap = new HashMap<>();
+        mInjectedPackageUidMap.put(CALLING_PACKAGE_1, CALLING_UID_1);
+        mInjectedPackageUidMap.put(CALLING_PACKAGE_2, CALLING_UID_2);
+        mInjectedPackageUidMap.put(CALLING_PACKAGE_3, CALLING_UID_3);
+        mInjectedPackageUidMap.put(LAUNCHER_1, LAUNCHER_UID_1);
+        mInjectedPackageUidMap.put(LAUNCHER_2, LAUNCHER_UID_2);
+
+        mInjectedFilePathRoot = new File(getContext().getCacheDir(), "test-files");
+
+        // Empty the data directory.
+        if (mInjectedFilePathRoot.exists()) {
+            Assert.assertTrue("failed to delete dir",
+                    FileUtils.deleteContents(mInjectedFilePathRoot));
+        }
+        mInjectedFilePathRoot.mkdirs();
+
+        initService();
+        setCaller(CALLING_PACKAGE_1);
+    }
+
+    /** (Re-) init the manager and the service. */
+    private void initService() {
+        LocalServices.removeServiceForTest(ShortcutServiceInternal.class);
+
+        // Instantiate targets.
+        mService = new ShortcutServiceTestable(mServiceContext);
+        mManager = new ShortcutManagerTestable(mClientContext, mService);
+
+        mInternal = LocalServices.getService(ShortcutServiceInternal.class);
+
+        mLauncherAppImpl = new LauncherAppImplTestable(mServiceContext);
+        mLauncherApps = new LauncherAppsTestable(mClientContext, mLauncherAppImpl);
+
+        // Load the setting file.
+        mService.onBootPhase(SystemService.PHASE_LOCK_SETTINGS_READY);
+    }
+
+    /** Replace the current calling package */
+    private void setCaller(String packageName, int userId) {
+        mInjectedClientPackage = packageName;
+        mInjectedCallingUid = UserHandle.getUid(userId,
+                Preconditions.checkNotNull(mInjectedPackageUidMap.get(packageName),
+                        "Unknown package"));
+    }
+
+    private void setCaller(String packageName) {
+        setCaller(packageName, UserHandle.USER_SYSTEM);
+    }
+
+    private String getCallingPackage() {
+        return mInjectedClientPackage;
+    }
+
+    private void runWithCaller(String packageName, int userId, Runnable r) {
+        final String previousPackage = mInjectedClientPackage;
+        final int previousUid = mInjectedCallingUid;
+
+        setCaller(packageName, userId);
+
+        r.run();
+
+        setCaller(previousPackage, previousUid);
+    }
+
+    private int getCallingUserId() {
+        return UserHandle.getUserId(mInjectedCallingUid);
+    }
+
+    private UserHandle getCallingUser() {
+        return UserHandle.of(getCallingUserId());
+    }
+
+    /** For debugging */
+    private void dumpsysOnLogcat() {
+        if (!ENABLE_DUMP) return;
+
+        final ByteArrayOutputStream out = new ByteArrayOutputStream();
+        final PrintWriter pw = new PrintWriter(out);
+        mService.dumpInner(pw);
+        pw.close();
+
+        Log.e(TAG, "Dumping ShortcutService:");
+        for (String line : out.toString().split("\n")) {
+            Log.e(TAG, line);
+        }
+    }
+
+    /**
+     * For debugging, dump arbitrary file on logcat.
+     */
+    private void dumpFileOnLogcat(String path) {
+        if (!ENABLE_DUMP) return;
+
+        Log.i(TAG, "Dumping file: " + path);
+        final StringBuilder sb = new StringBuilder();
+        try (BufferedReader br = new BufferedReader(new FileReader(path))) {
+            String line;
+            while ((line = br.readLine()) != null) {
+                Log.i(TAG, line);
+            }
+        } catch (Exception e) {
+            Log.e(TAG, "Couldn't read file", e);
+            fail("Exception " + e);
+        }
+    }
+
+    /**
+     * For debugging, dump the main state file on logcat.
+     */
+    private void dumpBaseStateFile() {
+        dumpFileOnLogcat(mInjectedFilePathRoot.getAbsolutePath()
+                + "/system/" + ShortcutService.FILENAME_BASE_STATE);
+    }
+
+    /**
+     * For debugging, dump per-user state file on logcat.
+     */
+    private void dumpUserFile(int userId) {
+        dumpFileOnLogcat(mInjectedFilePathRoot.getAbsolutePath()
+                + "/user-" + userId
+                + "/" + ShortcutService.FILENAME_USER_PACKAGES);
+    }
+
+    private static Bundle makeBundle(Object... keysAndValues) {
+        Preconditions.checkState((keysAndValues.length % 2) == 0);
+
+        if (keysAndValues.length == 0) {
+            return null;
+        }
+        final Bundle ret = new Bundle();
+
+        for (int i = keysAndValues.length - 2; i >= 0; i -= 2) {
+            final String key = keysAndValues[i].toString();
+            final Object value = keysAndValues[i + 1];
+
+            if (value == null) {
+                ret.putString(key, null);
+            } else if (value instanceof Integer) {
+                ret.putInt(key, (Integer) value);
+            } else if (value instanceof String) {
+                ret.putString(key, (String) value);
+            } else if (value instanceof Bundle) {
+                ret.putBundle(key, (Bundle) value);
+            } else {
+                fail("Type not supported yet: " + value.getClass().getName());
+            }
+        }
+        return ret;
+    }
+
+    /**
+     * Make a shortcut with an ID.
+     */
+    private ShortcutInfo makeShortcut(String id) {
+        return makeShortcut(
+                id, "Title-" + id, /* activity =*/ null, /* icon =*/ null,
+                makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), /* weight =*/ 0);
+    }
+
+    /**
+     * Make a shortcut with an ID and timestamp.
+     */
+    private ShortcutInfo makeShortcutWithTimestamp(String id, long timestamp) {
+        final ShortcutInfo s = makeShortcut(
+                id, "Title-" + id, /* activity =*/ null, /* icon =*/ null,
+                makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), /* weight =*/ 0);
+        s.setTimestamp(timestamp);
+        return s;
+    }
+
+    /**
+     * Make a shortcut with an ID and icon.
+     */
+    private ShortcutInfo makeShortcutWithIcon(String id, Icon icon) {
+        return makeShortcut(
+                id, "Title-" + id, /* activity =*/ null, icon,
+                makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), /* weight =*/ 0);
+    }
+
+    private ShortcutInfo makePackageShortcut(String packageName, String id) {
+        String origCaller = getCallingPackage();
+
+        setCaller(packageName);
+        ShortcutInfo s = makeShortcut(
+                id, "Title-" + id, /* activity =*/ null, /* icon =*/ null,
+                makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), /* weight =*/ 0);
+        setCaller(origCaller); // restore the caller
+
+        return s;
+    }
+
+    /**
+     * Make multiple shortcuts with IDs.
+     */
+    private List<ShortcutInfo> makeShortcuts(String... ids) {
+        final ArrayList<ShortcutInfo> ret = new ArrayList();
+        for (String id : ids) {
+            ret.add(makeShortcut(id));
+        }
+        return ret;
+    }
+
+    private ShortcutInfo.Builder makeShortcutBuilder() {
+        return new ShortcutInfo.Builder(mClientContext);
+    }
+
+    /**
+     * Make a shortcut with details.
+     */
+    private ShortcutInfo makeShortcut(String id, String title, ComponentName activity,
+            Icon icon, Intent intent, int weight) {
+        final ShortcutInfo.Builder  b = new ShortcutInfo.Builder(mClientContext)
+                .setId(id)
+                .setTitle(title)
+                .setWeight(weight)
+                .setIntent(intent);
+        if (icon != null) {
+            b.setIcon(icon);
+        }
+        if (activity != null) {
+            b.setActivityComponent(activity);
+        }
+        final ShortcutInfo s = b.build();
+
+        s.setTimestamp(mInjectedCurrentTimeLillis); // HACK
+
+        return s;
+    }
+
+    /**
+     * Make an intent.
+     */
+    private Intent makeIntent(String action, Class<?> clazz, Object... bundleKeysAndValues) {
+        final Intent intent = new Intent(action);
+        intent.setComponent(makeComponent(clazz));
+        intent.replaceExtras(makeBundle(bundleKeysAndValues));
+        return intent;
+    }
+
+    /**
+     * Make an component name, with the client context.
+     */
+    @NonNull
+    private ComponentName makeComponent(Class<?> clazz) {
+        return new ComponentName(mClientContext, clazz);
+    }
+
+    @NonNull
+    private ShortcutInfo findById(List<ShortcutInfo> list, String id) {
+        for (ShortcutInfo s : list) {
+            if (s.getId().equals(id)) {
+                return s;
+            }
+        }
+        fail("Shortcut with id " + id + " not found");
+        return null;
+    }
+
+    private void assertResetTimes(long expectedLastResetTime, long expectedNextResetTime) {
+        assertEquals(expectedLastResetTime, mService.getLastResetTimeLocked());
+        assertEquals(expectedNextResetTime, mService.getNextResetTimeLocked());
+    }
+
+    @NonNull
+    private List<ShortcutInfo> assertShortcutIds(@NonNull List<ShortcutInfo> actualShortcuts,
+            String... expectedIds) {
+        assertEquals(expectedIds.length, actualShortcuts.size());
+        final HashSet<String> expected = new HashSet<>(Arrays.asList(expectedIds));
+        final HashSet<String> actual = new HashSet<>();
+        for (ShortcutInfo s : actualShortcuts) {
+            actual.add(s.getId());
+        }
+
+        // Compare the sets.
+        assertEquals(expected, actual);
+        return actualShortcuts;
+    }
+
+    @NonNull
+    private List<ShortcutInfo> assertAllHaveIntents(
+            @NonNull List<ShortcutInfo> actualShortcuts) {
+        for (ShortcutInfo s : actualShortcuts) {
+            assertNotNull("ID " + s.getId(), s.getIntent());
+        }
+        return actualShortcuts;
+    }
+
+    @NonNull
+    private List<ShortcutInfo> assertAllNotHaveIntents(
+            @NonNull List<ShortcutInfo> actualShortcuts) {
+        for (ShortcutInfo s : actualShortcuts) {
+            assertNull("ID " + s.getId(), s.getIntent());
+        }
+        return actualShortcuts;
+    }
+
+    @NonNull
+    private List<ShortcutInfo> assertAllHaveTitle(
+            @NonNull List<ShortcutInfo> actualShortcuts) {
+        for (ShortcutInfo s : actualShortcuts) {
+            assertNotNull("ID " + s.getId(), s.getTitle());
+        }
+        return actualShortcuts;
+    }
+
+    @NonNull
+    private List<ShortcutInfo> assertAllNotHaveTitle(
+            @NonNull List<ShortcutInfo> actualShortcuts) {
+        for (ShortcutInfo s : actualShortcuts) {
+            assertNull("ID " + s.getId(), s.getTitle());
+        }
+        return actualShortcuts;
+    }
+
+    @NonNull
+    private List<ShortcutInfo> assertAllNotHaveIcon(
+            @NonNull List<ShortcutInfo> actualShortcuts) {
+        for (ShortcutInfo s : actualShortcuts) {
+            assertNull("ID " + s.getId(), s.getIcon());
+        }
+        return actualShortcuts;
+    }
+
+    @NonNull
+    private List<ShortcutInfo> assertAllHaveIconResId(
+            @NonNull List<ShortcutInfo> actualShortcuts) {
+        for (ShortcutInfo s : actualShortcuts) {
+            assertTrue("ID " + s.getId() + " not have icon res ID", s.hasIconResource());
+            assertFalse("ID " + s.getId() + " shouldn't have icon FD", s.hasIconFile());
+        }
+        return actualShortcuts;
+    }
+
+    @NonNull
+    private List<ShortcutInfo> assertAllHaveIconFile(
+            @NonNull List<ShortcutInfo> actualShortcuts) {
+        for (ShortcutInfo s : actualShortcuts) {
+            assertFalse("ID " + s.getId() + " shouldn't have icon res ID", s.hasIconResource());
+            assertTrue("ID " + s.getId() + " not have icon FD", s.hasIconFile());
+        }
+        return actualShortcuts;
+    }
+
+    @NonNull
+    private List<ShortcutInfo> assertAllHaveIcon(
+            @NonNull List<ShortcutInfo> actualShortcuts) {
+        for (ShortcutInfo s : actualShortcuts) {
+            assertTrue("ID " + s.getId(), s.hasIconFile() || s.hasIconResource());
+        }
+        return actualShortcuts;
+    }
+
+    @NonNull
+    private List<ShortcutInfo> assertAllHaveFlags(@NonNull List<ShortcutInfo> actualShortcuts,
+            int shortcutFlags) {
+        for (ShortcutInfo s : actualShortcuts) {
+            assertTrue("ID " + s.getId(), s.hasFlags(shortcutFlags));
+        }
+        return actualShortcuts;
+    }
+
+    @NonNull
+    private List<ShortcutInfo> assertAllKeyFieldsOnly(
+            @NonNull List<ShortcutInfo> actualShortcuts) {
+        for (ShortcutInfo s : actualShortcuts) {
+            assertTrue("ID " + s.getId(), s.hasKeyFieldsOnly());
+        }
+        return actualShortcuts;
+    }
+
+    @NonNull
+    private List<ShortcutInfo> assertAllNotKeyFieldsOnly(
+            @NonNull List<ShortcutInfo> actualShortcuts) {
+        for (ShortcutInfo s : actualShortcuts) {
+            assertFalse("ID " + s.getId(), s.hasKeyFieldsOnly());
+        }
+        return actualShortcuts;
+    }
+
+    @NonNull
+    private List<ShortcutInfo> assertAllDynamic(@NonNull List<ShortcutInfo> actualShortcuts) {
+        return assertAllHaveFlags(actualShortcuts, ShortcutInfo.FLAG_DYNAMIC);
+    }
+
+    @NonNull
+    private List<ShortcutInfo> assertAllPinned(@NonNull List<ShortcutInfo> actualShortcuts) {
+        return assertAllHaveFlags(actualShortcuts, ShortcutInfo.FLAG_PINNED);
+    }
+
+    @NonNull
+    private List<ShortcutInfo> assertAllDynamicOrPinned(
+            @NonNull List<ShortcutInfo> actualShortcuts) {
+        for (ShortcutInfo s : actualShortcuts) {
+            assertTrue("ID " + s.getId(), s.isDynamic() || s.isPinned());
+        }
+        return actualShortcuts;
+    }
+
+    private void assertBitmapSize(int expectedWidth, int expectedHeight, @NonNull Bitmap bitmap) {
+        assertEquals("width", expectedWidth, bitmap.getWidth());
+        assertEquals("height", expectedHeight, bitmap.getHeight());
+    }
+
+    private <T> void assertAllUnique(Collection<T> list) {
+        final Set<Object> set = new HashSet<>();
+        for (T item : list) {
+            if (set.contains(item)) {
+                fail("Duplicate item found: " + item + " (in the list: " + list + ")");
+            }
+            set.add(item);
+        }
+    }
+
+    @NonNull
+    private Bitmap pfdToBitmap(@NonNull ParcelFileDescriptor pfd) {
+        Preconditions.checkNotNull(pfd);
+        try {
+            return BitmapFactory.decodeFileDescriptor(pfd.getFileDescriptor());
+        } finally {
+            IoUtils.closeQuietly(pfd);
+        }
+    }
+
+    private void assertBundleEmpty(BaseBundle b) {
+        assertTrue(b == null || b.size() == 0);
+    }
+
+    private ShortcutInfo getPackageShortcut(String packageName, String shortcutId, int userId) {
+        return mService.getPackageShortcutForTest(packageName, shortcutId, userId);
+    }
+
+    private ShortcutInfo getPackageShortcut(String packageName, String shortcutId) {
+        return getPackageShortcut(packageName, shortcutId, getCallingUserId());
+    }
+
+    private ShortcutInfo getCallerShortcut(String shortcutId) {
+        return getPackageShortcut(getCallingPackage(), shortcutId, getCallingUserId());
+    }
+
+    /**
+     * Test for the first launch path, no settings file available.
+     */
+    public void testFirstInitialize() {
+        assertResetTimes(START_TIME, START_TIME + INTERVAL);
+    }
+
+    /**
+     * Test for {@link ShortcutService#updateTimes()}
+     */
+    public void testUpdateAndGetNextResetTimeLocked() {
+        assertResetTimes(START_TIME, START_TIME + INTERVAL);
+
+        // Advance clock.
+        mInjectedCurrentTimeLillis += 100;
+
+        // Shouldn't have changed.
+        assertResetTimes(START_TIME, START_TIME + INTERVAL);
+
+        // Advance clock, almost the reset time.
+        mInjectedCurrentTimeLillis = START_TIME + INTERVAL - 1;
+
+        // Shouldn't have changed.
+        assertResetTimes(START_TIME, START_TIME + INTERVAL);
+
+        // Advance clock.
+        mInjectedCurrentTimeLillis += 1;
+
+        assertResetTimes(START_TIME + INTERVAL, START_TIME + 2 * INTERVAL);
+
+        // Advance further; 4 days since start.
+        mInjectedCurrentTimeLillis = START_TIME + 4 * INTERVAL + 50;
+
+        assertResetTimes(START_TIME + 4 * INTERVAL, START_TIME + 5 * INTERVAL);
+    }
+
+    /**
+     * Test for the restoration from saved file.
+     */
+    public void testInitializeFromSavedFile() {
+
+        mInjectedCurrentTimeLillis = START_TIME + 4 * INTERVAL + 50;
+        assertResetTimes(START_TIME + 4 * INTERVAL, START_TIME + 5 * INTERVAL);
+
+        mService.saveBaseStateLocked();
+
+        dumpBaseStateFile();
+
+        // Restore.
+        initService();
+
+        assertResetTimes(START_TIME + 4 * INTERVAL, START_TIME + 5 * INTERVAL);
+    }
+
+    /**
+     * Test for the restoration from restored file.
+     */
+    public void testLoadFromBrokenFile() {
+        // TODO Add various broken cases.
+    }
+
+    public void testLoadConfig() {
+        mService.updateConfigurationLocked(
+                ConfigConstants.KEY_RESET_INTERVAL_SEC + "=123,"
+                        + ConfigConstants.KEY_MAX_SHORTCUTS + "=4,"
+                        + ConfigConstants.KEY_MAX_DAILY_UPDATES + "=5,"
+                        + ConfigConstants.KEY_MAX_ICON_DIMENSION_DP + "=100,"
+                        + ConfigConstants.KEY_MAX_ICON_DIMENSION_DP_LOWRAM + "=50,"
+                        + ConfigConstants.KEY_ICON_FORMAT + "=WEBP,"
+                        + ConfigConstants.KEY_ICON_QUALITY + "=75");
+        assertEquals(123000, mService.getResetIntervalForTest());
+        assertEquals(4, mService.getMaxDynamicShortcutsForTest());
+        assertEquals(5, mService.getMaxDailyUpdatesForTest());
+        assertEquals(100, mService.getMaxIconDimensionForTest());
+        assertEquals(CompressFormat.WEBP, mService.getIconPersistFormatForTest());
+        assertEquals(75, mService.getIconPersistQualityForTest());
+
+        mInjectdIsLowRamDevice = true;
+        mService.updateConfigurationLocked(
+                ConfigConstants.KEY_MAX_ICON_DIMENSION_DP + "=100,"
+                        + ConfigConstants.KEY_MAX_ICON_DIMENSION_DP_LOWRAM + "=50,"
+                        + ConfigConstants.KEY_ICON_FORMAT + "=JPEG");
+        assertEquals(ShortcutService.DEFAULT_RESET_INTERVAL_SEC * 1000,
+                mService.getResetIntervalForTest());
+
+        assertEquals(ShortcutService.DEFAULT_MAX_SHORTCUTS_PER_APP,
+                mService.getMaxDynamicShortcutsForTest());
+
+        assertEquals(ShortcutService.DEFAULT_MAX_DAILY_UPDATES,
+                mService.getMaxDailyUpdatesForTest());
+
+        assertEquals(50, mService.getMaxIconDimensionForTest());
+
+        assertEquals(CompressFormat.JPEG, mService.getIconPersistFormatForTest());
+
+        assertEquals(ShortcutService.DEFAULT_ICON_PERSIST_QUALITY,
+                mService.getIconPersistQualityForTest());
+    }
+
+    // === Test for app side APIs ===
+
+    /** Test for {@link android.content.pm.ShortcutManager#getMaxDynamicShortcutCount()} */
+    public void testGetMaxDynamicShortcutCount() {
+        assertEquals(MAX_SHORTCUTS, mManager.getMaxDynamicShortcutCount());
+    }
+
+    /** Test for {@link android.content.pm.ShortcutManager#getRemainingCallCount()} */
+    public void testGetRemainingCallCount() {
+        assertEquals(MAX_DAILY_UPDATES, mManager.getRemainingCallCount());
+    }
+
+    /** Test for {@link android.content.pm.ShortcutManager#getRateLimitResetTime()} */
+    public void testGetRateLimitResetTime() {
+        assertEquals(START_TIME + INTERVAL, mManager.getRateLimitResetTime());
+
+        mInjectedCurrentTimeLillis = START_TIME + 4 * INTERVAL + 50;
+
+        assertEquals(START_TIME + 5 * INTERVAL, mManager.getRateLimitResetTime());
+    }
+
+    public void testSetDynamicShortcuts() {
+        final Icon icon1 = Icon.createWithResource(mContext, R.drawable.icon1);
+        final Icon icon2 = Icon.createWithBitmap(BitmapFactory.decodeResource(
+                mContext.getResources(), R.drawable.icon2));
+
+        final ShortcutInfo si1 = makeShortcut(
+                "shortcut1",
+                "Title 1",
+                makeComponent(ShortcutActivity.class),
+                icon1,
+                makeIntent(Intent.ACTION_ASSIST, ShortcutActivity2.class,
+                        "key1", "val1", "nest", makeBundle("key", 123)),
+                /* weight */ 10);
+
+        final ShortcutInfo si2 = makeShortcut(
+                "shortcut2",
+                "Title 2",
+                /* activity */ null,
+                icon2,
+                makeIntent(Intent.ACTION_ASSIST, ShortcutActivity3.class),
+                /* weight */ 12);
+        final ShortcutInfo si3 = makeShortcut("shortcut3");
+
+        assertTrue(mManager.setDynamicShortcuts(Arrays.asList(si1, si2)));
+        assertShortcutIds(assertAllNotKeyFieldsOnly(
+                mManager.getDynamicShortcuts()),
+                "shortcut1", "shortcut2");
+        assertEquals(2, mManager.getRemainingCallCount());
+
+        // TODO: Check fields
+
+        assertTrue(mManager.setDynamicShortcuts(Arrays.asList(si1)));
+        assertShortcutIds(assertAllNotKeyFieldsOnly(
+                mManager.getDynamicShortcuts()),
+                "shortcut1");
+        assertEquals(1, mManager.getRemainingCallCount());
+
+        assertTrue(mManager.setDynamicShortcuts(Arrays.asList()));
+        assertEquals(0, mManager.getDynamicShortcuts().size());
+        assertEquals(0, mManager.getRemainingCallCount());
+
+        dumpsysOnLogcat();
+
+        mInjectedCurrentTimeLillis++; // Need to advance the clock for reset to work.
+        mService.resetThrottlingInner();
+
+        dumpsysOnLogcat();
+
+        assertTrue(mManager.setDynamicShortcuts(Arrays.asList(si2, si3)));
+        assertEquals(2, mManager.getDynamicShortcuts().size());
+
+        // TODO Check max number
+    }
+
+    public void testAddDynamicShortcuts() {
+        final ShortcutInfo si1 = makeShortcut("shortcut1");
+        final ShortcutInfo si2 = makeShortcut("shortcut2");
+        final ShortcutInfo si3 = makeShortcut("shortcut3");
+
+        assertEquals(3, mManager.getRemainingCallCount());
+
+        assertTrue(mManager.setDynamicShortcuts(Arrays.asList(si1)));
+        assertEquals(2, mManager.getRemainingCallCount());
+        assertShortcutIds(assertAllNotKeyFieldsOnly(
+                mManager.getDynamicShortcuts()),
+                "shortcut1");
+
+        assertTrue(mManager.addDynamicShortcut(si2));
+        assertEquals(1, mManager.getRemainingCallCount());
+        assertShortcutIds(assertAllNotKeyFieldsOnly(
+                mManager.getDynamicShortcuts()),
+                "shortcut1", "shortcut2");
+
+        // Add with the same ID
+        assertTrue(mManager.addDynamicShortcut(makeShortcut("shortcut1")));
+        assertEquals(0, mManager.getRemainingCallCount());
+        assertShortcutIds(assertAllNotKeyFieldsOnly(
+                mManager.getDynamicShortcuts()),
+                "shortcut1", "shortcut2");
+
+        // TODO Check max number
+
+        // TODO Check fields.
+    }
+
+    public void testDeleteDynamicShortcut() {
+        final ShortcutInfo si1 = makeShortcut("shortcut1");
+        final ShortcutInfo si2 = makeShortcut("shortcut2");
+        final ShortcutInfo si3 = makeShortcut("shortcut3");
+
+        assertTrue(mManager.setDynamicShortcuts(Arrays.asList(si1, si2, si3)));
+        assertShortcutIds(assertAllNotKeyFieldsOnly(
+                mManager.getDynamicShortcuts()),
+                "shortcut1", "shortcut2", "shortcut3");
+
+        assertEquals(2, mManager.getRemainingCallCount());
+
+        mManager.deleteDynamicShortcut("shortcut1");
+        assertShortcutIds(assertAllNotKeyFieldsOnly(
+                mManager.getDynamicShortcuts()),
+                "shortcut2", "shortcut3");
+
+        mManager.deleteDynamicShortcut("shortcut1");
+        assertShortcutIds(assertAllNotKeyFieldsOnly(
+                mManager.getDynamicShortcuts()),
+                "shortcut2", "shortcut3");
+
+        mManager.deleteDynamicShortcut("shortcutXXX");
+        assertShortcutIds(assertAllNotKeyFieldsOnly(
+                mManager.getDynamicShortcuts()),
+                "shortcut2", "shortcut3");
+
+        mManager.deleteDynamicShortcut("shortcut2");
+        assertShortcutIds(assertAllNotKeyFieldsOnly(
+                mManager.getDynamicShortcuts()),
+                "shortcut3");
+
+        mManager.deleteDynamicShortcut("shortcut3");
+        assertShortcutIds(assertAllNotKeyFieldsOnly(
+                mManager.getDynamicShortcuts()));
+
+        // Still 2 calls left.
+        assertEquals(2, mManager.getRemainingCallCount());
+
+        // TODO Make sure pinned shortcuts won't be deleted.
+    }
+
+    public void testDeleteAllDynamicShortcuts() {
+        final ShortcutInfo si1 = makeShortcut("shortcut1");
+        final ShortcutInfo si2 = makeShortcut("shortcut2");
+        final ShortcutInfo si3 = makeShortcut("shortcut3");
+
+        assertTrue(mManager.setDynamicShortcuts(Arrays.asList(si1, si2, si3)));
+        assertShortcutIds(assertAllNotKeyFieldsOnly(
+                mManager.getDynamicShortcuts()),
+                "shortcut1", "shortcut2", "shortcut3");
+
+        assertEquals(2, mManager.getRemainingCallCount());
+
+        mManager.deleteAllDynamicShortcuts();
+        assertEquals(0, mManager.getDynamicShortcuts().size());
+        assertEquals(2, mManager.getRemainingCallCount());
+
+        // Note delete shouldn't affect throttling, so...
+        assertEquals(0, mManager.getDynamicShortcuts().size());
+        assertEquals(0, mManager.getDynamicShortcuts().size());
+        assertEquals(0, mManager.getDynamicShortcuts().size());
+
+        // This should still work.
+        assertTrue(mManager.setDynamicShortcuts(Arrays.asList(si1, si2, si3)));
+        assertEquals(3, mManager.getDynamicShortcuts().size());
+
+        // Still 1 call left
+        assertEquals(1, mManager.getRemainingCallCount());
+
+        // TODO Make sure pinned shortcuts won't be deleted.
+    }
+
+    public void testThrottling() {
+        final ShortcutInfo si1 = makeShortcut("shortcut1");
+
+        assertTrue(mManager.setDynamicShortcuts(Arrays.asList(si1)));
+        assertEquals(2, mManager.getRemainingCallCount());
+
+        mInjectedCurrentTimeLillis++;
+        assertTrue(mManager.setDynamicShortcuts(Arrays.asList(si1)));
+        assertEquals(1, mManager.getRemainingCallCount());
+
+        mInjectedCurrentTimeLillis++;
+        assertTrue(mManager.setDynamicShortcuts(Arrays.asList(si1)));
+        assertEquals(0, mManager.getRemainingCallCount());
+
+        // Reached the max
+
+        mInjectedCurrentTimeLillis++;
+        assertFalse(mManager.setDynamicShortcuts(Arrays.asList(si1)));
+        assertEquals(0, mManager.getRemainingCallCount());
+
+        // Still throttled
+        mInjectedCurrentTimeLillis = START_TIME + INTERVAL - 1;
+        assertFalse(mManager.setDynamicShortcuts(Arrays.asList(si1)));
+        assertEquals(0, mManager.getRemainingCallCount());
+
+        // Now it should work.
+        mInjectedCurrentTimeLillis++;
+        assertTrue(mManager.setDynamicShortcuts(Arrays.asList(si1))); // fail
+        assertEquals(2, mManager.getRemainingCallCount());
+
+        mInjectedCurrentTimeLillis++;
+        assertTrue(mManager.setDynamicShortcuts(Arrays.asList(si1)));
+        assertEquals(1, mManager.getRemainingCallCount());
+
+        mInjectedCurrentTimeLillis++;
+        assertTrue(mManager.setDynamicShortcuts(Arrays.asList(si1)));
+        assertEquals(0, mManager.getRemainingCallCount());
+
+        mInjectedCurrentTimeLillis++;
+        assertFalse(mManager.setDynamicShortcuts(Arrays.asList(si1)));
+        assertEquals(0, mManager.getRemainingCallCount());
+
+        // 4 days later...
+        mInjectedCurrentTimeLillis = START_TIME + 4 * INTERVAL;
+        assertTrue(mManager.setDynamicShortcuts(Arrays.asList(si1)));
+        assertEquals(2, mManager.getRemainingCallCount());
+
+        // Make sure getRemainingCallCount() itself gets reset withou calling setDynamicShortcuts().
+        mInjectedCurrentTimeLillis = START_TIME + 8 * INTERVAL;
+        assertEquals(3, mManager.getRemainingCallCount());
+    }
+
+    public void testThrottling_perPackage() {
+        final ShortcutInfo si1 = makeShortcut("shortcut1");
+
+        assertTrue(mManager.setDynamicShortcuts(Arrays.asList(si1)));
+        assertEquals(2, mManager.getRemainingCallCount());
+
+        mInjectedCurrentTimeLillis++;
+        assertTrue(mManager.setDynamicShortcuts(Arrays.asList(si1)));
+        assertEquals(1, mManager.getRemainingCallCount());
+
+        mInjectedCurrentTimeLillis++;
+        assertTrue(mManager.setDynamicShortcuts(Arrays.asList(si1)));
+        assertEquals(0, mManager.getRemainingCallCount());
+
+        // Reached the max
+
+        mInjectedCurrentTimeLillis++;
+        assertFalse(mManager.setDynamicShortcuts(Arrays.asList(si1)));
+
+        // Try from a different caller.
+        mInjectedClientPackage = CALLING_PACKAGE_2;
+        mInjectedCallingUid = CALLING_UID_2;
+
+        // Need to create a new one wit the updated package name.
+        final ShortcutInfo si2 = makeShortcut("shortcut1");
+
+        assertEquals(3, mManager.getRemainingCallCount());
+
+        assertTrue(mManager.setDynamicShortcuts(Arrays.asList(si2)));
+        assertEquals(2, mManager.getRemainingCallCount());
+
+        mInjectedCurrentTimeLillis++;
+        assertTrue(mManager.setDynamicShortcuts(Arrays.asList(si2)));
+        assertEquals(1, mManager.getRemainingCallCount());
+
+        // Back to the original caller, still throttled.
+        mInjectedClientPackage = CALLING_PACKAGE_1;
+        mInjectedCallingUid = CALLING_UID_1;
+
+        mInjectedCurrentTimeLillis = START_TIME + INTERVAL - 1;
+        assertEquals(0, mManager.getRemainingCallCount());
+        assertFalse(mManager.setDynamicShortcuts(Arrays.asList(si1)));
+        assertEquals(0, mManager.getRemainingCallCount());
+
+        // Now it should work.
+        mInjectedCurrentTimeLillis++;
+        assertTrue(mManager.setDynamicShortcuts(Arrays.asList(si1)));
+
+        mInjectedCurrentTimeLillis++;
+        assertTrue(mManager.setDynamicShortcuts(Arrays.asList(si1)));
+
+        mInjectedCurrentTimeLillis++;
+        assertTrue(mManager.setDynamicShortcuts(Arrays.asList(si1)));
+
+        mInjectedCurrentTimeLillis++;
+        assertFalse(mManager.setDynamicShortcuts(Arrays.asList(si1)));
+
+        mInjectedCurrentTimeLillis = START_TIME + 4 * INTERVAL;
+        assertTrue(mManager.setDynamicShortcuts(Arrays.asList(si1)));
+        assertTrue(mManager.setDynamicShortcuts(Arrays.asList(si1)));
+        assertTrue(mManager.setDynamicShortcuts(Arrays.asList(si1)));
+        assertFalse(mManager.setDynamicShortcuts(Arrays.asList(si1)));
+
+        mInjectedClientPackage = CALLING_PACKAGE_2;
+        mInjectedCallingUid = CALLING_UID_2;
+
+        assertEquals(3, mManager.getRemainingCallCount());
+
+        assertTrue(mManager.setDynamicShortcuts(Arrays.asList(si2)));
+        assertTrue(mManager.setDynamicShortcuts(Arrays.asList(si2)));
+        assertTrue(mManager.setDynamicShortcuts(Arrays.asList(si2)));
+        assertFalse(mManager.setDynamicShortcuts(Arrays.asList(si2)));
+    }
+
+    public void testIcons() {
+        final Icon res32x32 = Icon.createWithResource(mContext, R.drawable.black_32x32);
+        final Icon res64x64 = Icon.createWithResource(mContext, R.drawable.black_64x64);
+        final Icon res512x512 = Icon.createWithResource(mContext, R.drawable.black_512x512);
+
+        final Icon bmp32x32 = Icon.createWithBitmap(BitmapFactory.decodeResource(
+                mContext.getResources(), R.drawable.black_32x32));
+        final Icon bmp64x64 = Icon.createWithBitmap(BitmapFactory.decodeResource(
+                mContext.getResources(), R.drawable.black_64x64));
+        final Icon bmp512x512 = Icon.createWithBitmap(BitmapFactory.decodeResource(
+                mContext.getResources(), R.drawable.black_512x512));
+
+        // Set from package 1
+        setCaller(CALLING_PACKAGE_1);
+        assertTrue(mManager.setDynamicShortcuts(Arrays.asList(
+                makeShortcutWithIcon("res32x32", res32x32),
+                makeShortcutWithIcon("res64x64", res64x64),
+                makeShortcutWithIcon("bmp32x32", bmp32x32),
+                makeShortcutWithIcon("bmp64x64", bmp64x64),
+                makeShortcutWithIcon("bmp512x512", bmp512x512),
+                makeShortcut("none")
+        )));
+
+        // getDynamicShortcuts() shouldn't return icons, thus assertAllNotHaveIcon().
+        assertShortcutIds(assertAllNotHaveIcon(mManager.getDynamicShortcuts()),
+                "res32x32",
+                "res64x64",
+                "bmp32x32",
+                "bmp64x64",
+                "bmp512x512",
+                "none");
+
+        // Call from another caller with the same ID, just to make sure storage is per-package.
+        setCaller(CALLING_PACKAGE_2);
+        assertTrue(mManager.setDynamicShortcuts(Arrays.asList(
+                makeShortcutWithIcon("res32x32", res512x512),
+                makeShortcutWithIcon("res64x64", res512x512),
+                makeShortcutWithIcon("none", res512x512)
+        )));
+        assertShortcutIds(assertAllNotHaveIcon(mManager.getDynamicShortcuts()),
+                "res32x32",
+                "res64x64",
+                "none");
+
+        // Re-initialize and load from the files.
+        initService();
+
+        // Load from launcher.
+        Bitmap bmp;
+
+        setCaller(LAUNCHER_1);
+
+        // Check hasIconResource()/hasIconFile().
+        assertShortcutIds(assertAllHaveIconResId(mLauncherApps.getShortcutInfo(
+                CALLING_PACKAGE_1, Arrays.asList("res32x32"),
+                getCallingUser())), "res32x32");
+
+        assertShortcutIds(assertAllHaveIconResId(mLauncherApps.getShortcutInfo(
+                CALLING_PACKAGE_1, Arrays.asList("res64x64"), getCallingUser())),
+                "res64x64");
+
+        assertShortcutIds(assertAllHaveIconFile(mLauncherApps.getShortcutInfo(
+                CALLING_PACKAGE_1, Arrays.asList("bmp32x32"), getCallingUser())),
+                "bmp32x32");
+
+        assertShortcutIds(assertAllHaveIconFile(mLauncherApps.getShortcutInfo(
+                CALLING_PACKAGE_1, Arrays.asList("bmp64x64"), getCallingUser())),
+                "bmp64x64");
+
+        assertShortcutIds(assertAllHaveIconFile(mLauncherApps.getShortcutInfo(
+                CALLING_PACKAGE_1, Arrays.asList("bmp512x512"), getCallingUser())),
+                "bmp512x512");
+
+        // Check
+        assertEquals(
+                R.drawable.black_32x32,
+                mLauncherApps.getShortcutIconResId(
+                        makePackageShortcut(CALLING_PACKAGE_1, "res32x32"), getCallingUser()));
+
+        assertEquals(
+                R.drawable.black_64x64,
+                mLauncherApps.getShortcutIconResId(
+
+                        makePackageShortcut(CALLING_PACKAGE_1, "res64x64"), getCallingUser()));
+
+        assertEquals(
+                0, // because it's not a resource
+                mLauncherApps.getShortcutIconResId(
+                        makePackageShortcut(CALLING_PACKAGE_1, "bmp32x32"), getCallingUser()));
+        assertEquals(
+                0, // because it's not a resource
+                mLauncherApps.getShortcutIconResId(
+                        makePackageShortcut(CALLING_PACKAGE_1, "bmp64x64"), getCallingUser()));
+        assertEquals(
+                0, // because it's not a resource
+                mLauncherApps.getShortcutIconResId(
+                        makePackageShortcut(CALLING_PACKAGE_1, "bmp512x512"), getCallingUser()));
+
+        bmp = pfdToBitmap(mLauncherApps.getShortcutIconFd(
+                makePackageShortcut(CALLING_PACKAGE_1, "bmp32x32"), getCallingUser()));
+        assertBitmapSize(32, 32, bmp);
+
+        bmp = pfdToBitmap(mLauncherApps.getShortcutIconFd(
+                makePackageShortcut(CALLING_PACKAGE_1, "bmp64x64"), getCallingUser()));
+        assertBitmapSize(64, 64, bmp);
+
+        bmp = pfdToBitmap(mLauncherApps.getShortcutIconFd(
+                makePackageShortcut(CALLING_PACKAGE_1, "bmp512x512"), getCallingUser()));
+        assertBitmapSize(128, 128, bmp);
+
+        // TODO Test the content URI case too.
+    }
+
+    private void checkShrinkBitmap(int expectedWidth, int expectedHeight, int resId, int maxSize) {
+        assertBitmapSize(expectedWidth, expectedHeight,
+                ShortcutService.shrinkBitmap(BitmapFactory.decodeResource(
+                        mContext.getResources(), resId),
+                        maxSize));
+    }
+
+    public void testShrinkBitmap() {
+        checkShrinkBitmap(32, 32, R.drawable.black_512x512, 32);
+        checkShrinkBitmap(511, 511, R.drawable.black_512x512, 511);
+        checkShrinkBitmap(512, 512, R.drawable.black_512x512, 512);
+
+        checkShrinkBitmap(1024, 4096, R.drawable.black_1024x4096, 4096);
+        checkShrinkBitmap(1024, 4096, R.drawable.black_1024x4096, 4100);
+        checkShrinkBitmap(512, 2048, R.drawable.black_1024x4096, 2048);
+
+        checkShrinkBitmap(4096, 1024, R.drawable.black_4096x1024, 4096);
+        checkShrinkBitmap(4096, 1024, R.drawable.black_4096x1024, 4100);
+        checkShrinkBitmap(2048, 512, R.drawable.black_4096x1024, 2048);
+    }
+
+    private File openIconFileForWriteAndGetPath(int userId, String packageName)
+            throws IOException {
+        // Shortcut IDs aren't used in the path, so just pass the same ID.
+        final FileOutputStreamWithPath out =
+                mService.openIconFileForWrite(userId, makePackageShortcut(packageName, "id"));
+        out.close();
+        return out.getFile();
+    }
+
+    public void testOpenIconFileForWrite() throws IOException {
+        mInjectedCurrentTimeLillis = 1000;
+
+        final File p10_1_1 = openIconFileForWriteAndGetPath(10, CALLING_PACKAGE_1);
+        final File p10_1_2 = openIconFileForWriteAndGetPath(10, CALLING_PACKAGE_1);
+
+        final File p10_2_1 = openIconFileForWriteAndGetPath(10, CALLING_PACKAGE_2);
+        final File p10_2_2 = openIconFileForWriteAndGetPath(10, CALLING_PACKAGE_2);
+
+        final File p11_1_1 = openIconFileForWriteAndGetPath(11, CALLING_PACKAGE_1);
+        final File p11_1_2 = openIconFileForWriteAndGetPath(11, CALLING_PACKAGE_1);
+
+        mInjectedCurrentTimeLillis++;
+
+        final File p10_1_3 = openIconFileForWriteAndGetPath(10, CALLING_PACKAGE_1);
+        final File p10_1_4 = openIconFileForWriteAndGetPath(10, CALLING_PACKAGE_1);
+        final File p10_1_5 = openIconFileForWriteAndGetPath(10, CALLING_PACKAGE_1);
+
+        final File p10_2_3 = openIconFileForWriteAndGetPath(10, CALLING_PACKAGE_2);
+        final File p11_1_3 = openIconFileForWriteAndGetPath(11, CALLING_PACKAGE_1);
+
+        // Make sure their paths are all unique
+        assertAllUnique(Arrays.asList(
+                p10_1_1,
+                p10_1_2,
+                p10_1_3,
+                p10_1_4,
+                p10_1_5,
+
+                p10_2_1,
+                p10_2_2,
+                p10_2_3,
+
+                p11_1_1,
+                p11_1_2,
+                p11_1_3
+        ));
+
+        // Check each set has the same parent.
+        assertEquals(p10_1_1.getParent(), p10_1_2.getParent());
+        assertEquals(p10_1_1.getParent(), p10_1_3.getParent());
+        assertEquals(p10_1_1.getParent(), p10_1_4.getParent());
+        assertEquals(p10_1_1.getParent(), p10_1_5.getParent());
+
+        assertEquals(p10_2_1.getParent(), p10_2_2.getParent());
+        assertEquals(p10_2_1.getParent(), p10_2_3.getParent());
+
+        assertEquals(p11_1_1.getParent(), p11_1_2.getParent());
+        assertEquals(p11_1_1.getParent(), p11_1_3.getParent());
+
+        // Check the parents are still unique.
+        assertAllUnique(Arrays.asList(
+                p10_1_1.getParent(),
+                p10_2_1.getParent(),
+                p11_1_1.getParent()
+        ));
+
+        // All files created at the same time for the same package/user, expcet for the first ones,
+        // will have "_" in the path.
+        assertFalse(p10_1_1.getName().contains("_"));
+        assertTrue(p10_1_2.getName().contains("_"));
+        assertFalse(p10_1_3.getName().contains("_"));
+        assertTrue(p10_1_4.getName().contains("_"));
+        assertTrue(p10_1_5.getName().contains("_"));
+
+        assertFalse(p10_2_1.getName().contains("_"));
+        assertTrue(p10_2_2.getName().contains("_"));
+        assertFalse(p10_2_3.getName().contains("_"));
+
+        assertFalse(p11_1_1.getName().contains("_"));
+        assertTrue(p11_1_2.getName().contains("_"));
+        assertFalse(p11_1_3.getName().contains("_"));
+    }
+
+    public void testUpdateShortcuts() {
+        runWithCaller(CALLING_PACKAGE_1, UserHandle.USER_SYSTEM, () -> {
+            assertTrue(mManager.setDynamicShortcuts(Arrays.asList(
+                    makeShortcut("s1"),
+                    makeShortcut("s2"),
+                    makeShortcut("s3"),
+                    makeShortcut("s4"),
+                    makeShortcut("s5")
+            )));
+        });
+        runWithCaller(CALLING_PACKAGE_2, UserHandle.USER_SYSTEM, () -> {
+            assertTrue(mManager.setDynamicShortcuts(Arrays.asList(
+                    makeShortcut("s1"),
+                    makeShortcut("s2"),
+                    makeShortcut("s3"),
+                    makeShortcut("s4"),
+                    makeShortcut("s5")
+            )));
+        });
+        runWithCaller(LAUNCHER_1, UserHandle.USER_SYSTEM, () -> {
+            mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, Arrays.asList("s2", "s3"),
+                    getCallingUser());
+            mLauncherApps.pinShortcuts(CALLING_PACKAGE_2, Arrays.asList("s4", "s5"),
+                    getCallingUser());
+        });
+        runWithCaller(CALLING_PACKAGE_1, UserHandle.USER_SYSTEM, () -> {
+            mManager.deleteDynamicShortcut("s1");
+            mManager.deleteDynamicShortcut("s2");
+        });
+        runWithCaller(CALLING_PACKAGE_2, UserHandle.USER_SYSTEM, () -> {
+            mManager.deleteDynamicShortcut("s1");
+            mManager.deleteDynamicShortcut("s3");
+            mManager.deleteDynamicShortcut("s5");
+        });
+        runWithCaller(CALLING_PACKAGE_1, UserHandle.USER_SYSTEM, () -> {
+            assertShortcutIds(assertAllDynamic(
+                    mManager.getDynamicShortcuts()),
+                    "s3", "s4", "s5");
+            assertShortcutIds(assertAllPinned(
+                    mManager.getPinnedShortcuts()),
+                    "s2", "s3");
+        });
+        runWithCaller(CALLING_PACKAGE_2, UserHandle.USER_SYSTEM, () -> {
+            assertShortcutIds(assertAllDynamic(
+                    mManager.getDynamicShortcuts()),
+                    "s2", "s4");
+            assertShortcutIds(assertAllPinned(
+                    mManager.getPinnedShortcuts()),
+                    "s4", "s5");
+        });
+
+        runWithCaller(CALLING_PACKAGE_1, UserHandle.USER_SYSTEM, () -> {
+            ShortcutInfo s2 = makeShortcutBuilder()
+                    .setId("s2")
+                    .setIcon(Icon.createWithResource(mContext, R.drawable.black_32x32))
+                    .build();
+
+            ShortcutInfo s4 = makeShortcutBuilder()
+                    .setId("s4")
+                    .setTitle("new title")
+                    .build();
+
+            mManager.updateShortcuts(Arrays.asList(s2, s4));
+        });
+        runWithCaller(CALLING_PACKAGE_2, UserHandle.USER_SYSTEM, () -> {
+            ShortcutInfo s2 = makeShortcutBuilder()
+                    .setId("s2")
+                    .setIntent(makeIntent(Intent.ACTION_ANSWER, ShortcutActivity.class,
+                            "key1", "val1"))
+                    .build();
+
+            ShortcutInfo s4 = makeShortcutBuilder()
+                    .setId("s4")
+                    .setIntent(new Intent(Intent.ACTION_ALL_APPS))
+                    .build();
+
+            mManager.updateShortcuts(Arrays.asList(s2, s4));
+        });
+
+        runWithCaller(CALLING_PACKAGE_1, UserHandle.USER_SYSTEM, () -> {
+            assertShortcutIds(assertAllDynamic(
+                    mManager.getDynamicShortcuts()),
+                    "s3", "s4", "s5");
+            assertShortcutIds(assertAllPinned(
+                    mManager.getPinnedShortcuts()),
+                    "s2", "s3");
+
+            ShortcutInfo s = getCallerShortcut("s2");
+            assertTrue(s.hasIconResource());
+            assertEquals(R.drawable.black_32x32, s.getIconResourceId());
+            assertEquals("Title-s2", s.getTitle());
+
+            s = getCallerShortcut("s4");
+            assertFalse(s.hasIconResource());
+            assertEquals(0, s.getIconResourceId());
+            assertEquals("new title", s.getTitle());
+        });
+        runWithCaller(CALLING_PACKAGE_2, UserHandle.USER_SYSTEM, () -> {
+            assertShortcutIds(assertAllDynamic(
+                    mManager.getDynamicShortcuts()),
+                    "s2", "s4");
+            assertShortcutIds(assertAllPinned(
+                    mManager.getPinnedShortcuts()),
+                    "s4", "s5");
+
+            ShortcutInfo s = getCallerShortcut("s2");
+            assertFalse(s.hasIconResource());
+            assertEquals(0, s.getIconResourceId());
+            assertEquals("Title-s2", s.getTitle());
+            assertEquals(Intent.ACTION_ANSWER, s.getIntent().getAction());
+            assertEquals(1, s.getIntent().getExtras().size());
+
+            s = getCallerShortcut("s4");
+            assertFalse(s.hasIconResource());
+            assertEquals(0, s.getIconResourceId());
+            assertEquals("Title-s4", s.getTitle());
+            assertEquals(Intent.ACTION_ALL_APPS, s.getIntent().getAction());
+            assertBundleEmpty(s.getIntent().getExtras());
+        });
+        // TODO Check with other fields too.
+
+        // TODO Check bitmap removal too.
+    }
+
+    // TODO: updateShortcuts()
+    // TODO: getPinnedShortcuts()
+
+    // === Test for launcher side APIs ===
+
+    private static ShortcutQuery buildQuery(long changedSince,
+            String packageName, ComponentName componentName,
+            /* @ShortcutQuery.QueryFlags */ int flags) {
+        final ShortcutQuery q = new ShortcutQuery();
+        q.setChangedSince(changedSince);
+        q.setPackage(packageName);
+        q.setActivity(componentName);
+        q.setQueryFlags(flags);
+        return q;
+    }
+
+    public void testGetShortcuts() {
+
+        // Set up shortcuts.
+
+        setCaller(CALLING_PACKAGE_1);
+        final ShortcutInfo s1_1 = makeShortcutWithTimestamp("s1", 5000);
+        final ShortcutInfo s1_2 = makeShortcutWithTimestamp("s2", 1000);
+
+        assertTrue(mManager.setDynamicShortcuts(Arrays.asList(s1_1, s1_2)));
+
+        setCaller(CALLING_PACKAGE_2);
+        final ShortcutInfo s2_2 = makeShortcutWithTimestamp("s2", 1500);
+        final ShortcutInfo s2_3 = makeShortcutWithTimestamp("s3", 3000);
+        final ShortcutInfo s2_4 = makeShortcutWithTimestamp("s4", 500);
+        assertTrue(mManager.setDynamicShortcuts(Arrays.asList(s2_2, s2_3, s2_4)));
+
+        setCaller(CALLING_PACKAGE_3);
+        final ShortcutInfo s3_2 = makeShortcutWithTimestamp("s3", 5000);
+        assertTrue(mManager.setDynamicShortcuts(Arrays.asList(s3_2)));
+
+        setCaller(LAUNCHER_1);
+
+        // Get dynamic
+        assertAllDynamic(assertAllHaveTitle(assertAllNotHaveIntents(assertShortcutIds(
+                assertAllNotKeyFieldsOnly(
+                mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_1,
+                        /* activity =*/ null, ShortcutQuery.FLAG_GET_DYNAMIC), getCallingUser())),
+                "s1", "s2"))));
+
+        // Get pinned
+        assertShortcutIds(
+                mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_1,
+                        /* activity =*/ null,
+                        ShortcutQuery.FLAG_GET_PINNED), getCallingUser())
+                /* none */);
+
+        // Get both, with timestamp
+        assertAllDynamic(assertAllHaveTitle(assertAllNotHaveIntents(assertShortcutIds(
+                assertAllNotKeyFieldsOnly(mLauncherApps.getShortcuts(buildQuery(
+                        /* time =*/ 1000, CALLING_PACKAGE_2,
+                        /* activity =*/ null,
+                        ShortcutQuery.FLAG_GET_PINNED | ShortcutQuery.FLAG_GET_DYNAMIC),
+                        getCallingUser())),
+                "s2", "s3"))));
+
+        // FLAG_GET_KEY_FIELDS_ONLY
+        assertAllDynamic(assertAllNotHaveTitle(assertAllNotHaveIntents(assertShortcutIds(
+                assertAllKeyFieldsOnly(mLauncherApps.getShortcuts(buildQuery(
+                        /* time =*/ 1000, CALLING_PACKAGE_2,
+                        /* activity =*/ null,
+                        ShortcutQuery.FLAG_GET_DYNAMIC | ShortcutQuery.FLAG_GET_KEY_FIELDS_ONLY),
+                        getCallingUser())),
+                "s2", "s3"))));
+
+        // Pin some shortcuts.
+        mLauncherApps.pinShortcuts(CALLING_PACKAGE_2,
+                Arrays.asList("s3", "s4"), getCallingUser());
+
+        // Pinned ones only
+        assertAllPinned(assertAllHaveTitle(assertAllNotHaveIntents(assertShortcutIds(
+                assertAllNotKeyFieldsOnly(mLauncherApps.getShortcuts(buildQuery(
+                        /* time =*/ 1000, CALLING_PACKAGE_2,
+                        /* activity =*/ null,
+                        ShortcutQuery.FLAG_GET_PINNED),
+                        getCallingUser())),
+                "s3"))));
+
+        // All packages.
+        assertShortcutIds(assertAllNotKeyFieldsOnly(
+                mLauncherApps.getShortcuts(buildQuery(
+                        /* time =*/ 5000, /* package= */ null,
+                        /* activity =*/ null,
+                        ShortcutQuery.FLAG_GET_DYNAMIC | ShortcutQuery.FLAG_GET_PINNED),
+                        getCallingUser())),
+                "s1", "s3");
+
+        // TODO More tests: pinned but dynamic, filter by activity
+    }
+
+    public void testGetShortcutInfo() {
+        // Create shortcuts.
+        setCaller(CALLING_PACKAGE_1);
+        final ShortcutInfo s1_1 = makeShortcut(
+                "s1",
+                "Title 1",
+                makeComponent(ShortcutActivity.class),
+                /* icon =*/ null,
+                makeIntent(Intent.ACTION_ASSIST, ShortcutActivity2.class,
+                        "key1", "val1", "nest", makeBundle("key", 123)),
+                /* weight */ 10);
+
+        final ShortcutInfo s1_2 = makeShortcut(
+                "s2",
+                "Title 2",
+                /* activity */ null,
+                /* icon =*/ null,
+                makeIntent(Intent.ACTION_ASSIST, ShortcutActivity3.class),
+                /* weight */ 12);
+
+        assertTrue(mManager.setDynamicShortcuts(Arrays.asList(s1_1, s1_2)));
+        dumpsysOnLogcat();
+
+        setCaller(CALLING_PACKAGE_2);
+        final ShortcutInfo s2_1 = makeShortcut(
+                "s1",
+                "ABC",
+                makeComponent(ShortcutActivity2.class),
+                /* icon =*/ null,
+                makeIntent(Intent.ACTION_ANSWER, ShortcutActivity2.class,
+                        "key1", "val1", "nest", makeBundle("key", 123)),
+                /* weight */ 10);
+        assertTrue(mManager.setDynamicShortcuts(Arrays.asList(s2_1)));
+        dumpsysOnLogcat();
+
+        // Pin some.
+        setCaller(LAUNCHER_1);
+
+        mLauncherApps.pinShortcuts(CALLING_PACKAGE_1,
+                Arrays.asList("s2"), getCallingUser());
+
+        dumpsysOnLogcat();
+
+        // Delete some.
+        setCaller(CALLING_PACKAGE_1);
+        assertShortcutIds(mManager.getPinnedShortcuts(), "s2");
+        mManager.deleteDynamicShortcut("s2");
+        assertShortcutIds(mManager.getPinnedShortcuts(), "s2");
+
+        dumpsysOnLogcat();
+
+        setCaller(LAUNCHER_1);
+        List<ShortcutInfo> list;
+
+        // Note we don't guarantee the orders.
+        list = assertShortcutIds(assertAllHaveTitle(assertAllNotHaveIntents(
+                assertAllNotKeyFieldsOnly(
+                mLauncherApps.getShortcutInfo(CALLING_PACKAGE_1,
+                Arrays.asList("s2", "s1", "s3", null), getCallingUser())))),
+                "s1", "s2");
+        assertEquals("Title 1", findById(list, "s1").getTitle());
+        assertEquals("Title 2", findById(list, "s2").getTitle());
+
+        assertShortcutIds(assertAllHaveTitle(assertAllNotHaveIntents(
+                mLauncherApps.getShortcutInfo(CALLING_PACKAGE_1,
+                        Arrays.asList("s3"), getCallingUser())))
+                /* none */);
+
+        list = assertShortcutIds(assertAllHaveTitle(assertAllNotHaveIntents(
+                mLauncherApps.getShortcutInfo(CALLING_PACKAGE_2,
+                        Arrays.asList("s1", "s2", "s3"), getCallingUser()))),
+                "s1");
+        assertEquals("ABC", findById(list, "s1").getTitle());
+    }
+
+    public void testPinShortcutAndGetPinnedShortcuts() {
+        // Create some shortcuts.
+        setCaller(CALLING_PACKAGE_1);
+        final ShortcutInfo s1_1 = makeShortcutWithTimestamp("s1", 1000);
+        final ShortcutInfo s1_2 = makeShortcutWithTimestamp("s2", 2000);
+
+        assertTrue(mManager.setDynamicShortcuts(Arrays.asList(s1_1, s1_2)));
+
+        setCaller(CALLING_PACKAGE_2);
+        final ShortcutInfo s2_2 = makeShortcutWithTimestamp("s2", 1500);
+        final ShortcutInfo s2_3 = makeShortcutWithTimestamp("s3", 3000);
+        final ShortcutInfo s2_4 = makeShortcutWithTimestamp("s4", 500);
+        assertTrue(mManager.setDynamicShortcuts(Arrays.asList(s2_2, s2_3, s2_4)));
+
+        setCaller(CALLING_PACKAGE_3);
+        final ShortcutInfo s3_2 = makeShortcutWithTimestamp("s2", 1000);
+        assertTrue(mManager.setDynamicShortcuts(Arrays.asList(s2_2)));
+
+        // Pin some.
+        setCaller(LAUNCHER_1);
+
+        mLauncherApps.pinShortcuts(CALLING_PACKAGE_1,
+                Arrays.asList("s2", "s3"), getCallingUser());
+
+        mLauncherApps.pinShortcuts(CALLING_PACKAGE_2,
+                Arrays.asList("s3", "s4", "s5"), getCallingUser());
+
+        mLauncherApps.pinShortcuts(CALLING_PACKAGE_3,
+                Arrays.asList("s3"), getCallingUser());  // Note ID doesn't exist
+
+        // Delete some.
+        setCaller(CALLING_PACKAGE_1);
+        assertShortcutIds(mManager.getPinnedShortcuts(), "s2");
+        mManager.deleteDynamicShortcut("s2");
+        assertShortcutIds(mManager.getPinnedShortcuts(), "s2");
+
+        setCaller(CALLING_PACKAGE_2);
+        assertShortcutIds(mManager.getPinnedShortcuts(), "s3", "s4");
+        mManager.deleteDynamicShortcut("s3");
+        assertShortcutIds(mManager.getPinnedShortcuts(), "s3", "s4");
+
+        setCaller(CALLING_PACKAGE_3);
+        assertShortcutIds(mManager.getPinnedShortcuts() /* none */);
+        mManager.deleteDynamicShortcut("s2");
+        assertShortcutIds(mManager.getPinnedShortcuts() /* none */);
+
+        // Get pinned shortcuts from launcher
+        setCaller(LAUNCHER_1);
+
+        // CALLING_PACKAGE_1 deleted s2, but it's pinned, so it still exists.
+        assertShortcutIds(assertAllPinned(assertAllNotKeyFieldsOnly(
+                mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_1,
+                /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED), getCallingUser()))),
+                "s2");
+
+        assertShortcutIds(assertAllPinned(assertAllNotKeyFieldsOnly(
+                mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_2,
+                /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED), getCallingUser()))),
+                "s3", "s4");
+
+        assertShortcutIds(assertAllPinned(assertAllNotKeyFieldsOnly(
+                mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_3,
+                /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED), getCallingUser())))
+                /* none */);
+    }
+
+    public void testCreateShortcutIntent() {
+        // Create some shortcuts.
+        setCaller(CALLING_PACKAGE_1);
+        final ShortcutInfo s1_1 = makeShortcut(
+                "s1",
+                "Title 1",
+                makeComponent(ShortcutActivity.class),
+                /* icon =*/ null,
+                makeIntent(Intent.ACTION_ASSIST, ShortcutActivity2.class,
+                        "key1", "val1", "nest", makeBundle("key", 123)),
+                /* weight */ 10);
+
+        final ShortcutInfo s1_2 = makeShortcut(
+                "s2",
+                "Title 2",
+                /* activity */ null,
+                /* icon =*/ null,
+                makeIntent(Intent.ACTION_ASSIST, ShortcutActivity3.class),
+                /* weight */ 12);
+
+        assertTrue(mManager.setDynamicShortcuts(Arrays.asList(s1_1, s1_2)));
+
+        setCaller(CALLING_PACKAGE_2);
+        final ShortcutInfo s2_1 = makeShortcut(
+                "s1",
+                "ABC",
+                makeComponent(ShortcutActivity.class),
+                /* icon =*/ null,
+                makeIntent(Intent.ACTION_ANSWER, ShortcutActivity.class,
+                        "key1", "val1", "nest", makeBundle("key", 123)),
+                /* weight */ 10);
+        assertTrue(mManager.setDynamicShortcuts(Arrays.asList(s2_1)));
+
+        // Pin all.
+        setCaller(LAUNCHER_1);
+        mLauncherApps.pinShortcuts(CALLING_PACKAGE_1,
+                Arrays.asList("s1", "s2"), getCallingUser());
+
+        mLauncherApps.pinShortcuts(CALLING_PACKAGE_2,
+                Arrays.asList("s1"), getCallingUser());
+
+        // Just to make it complicated, delete some.
+        setCaller(CALLING_PACKAGE_1);
+        mManager.deleteDynamicShortcut("s2");
+
+        // intent and check.
+        setCaller(LAUNCHER_1);
+        Intent intent;
+        intent = mInternal.createShortcutIntent(getCallingPackage(),
+                CALLING_PACKAGE_1, "s1", getCallingUserId());
+        assertEquals(ShortcutActivity2.class.getName(), intent.getComponent().getClassName());
+
+        intent = mInternal.createShortcutIntent(getCallingPackage(),
+                CALLING_PACKAGE_1, "s2", getCallingUserId());
+        assertEquals(ShortcutActivity3.class.getName(), intent.getComponent().getClassName());
+
+        intent = mInternal.createShortcutIntent(getCallingPackage(),
+                CALLING_PACKAGE_2, "s1", getCallingUserId());
+        assertEquals(ShortcutActivity.class.getName(), intent.getComponent().getClassName());
+
+        // TODO Check extra, etc
+    }
+
+    // === Test for persisting ===
+
+    public void testSaveAndLoadUser_empty() {
+        assertTrue(mManager.setDynamicShortcuts(Arrays.asList()));
+
+        Log.i(TAG, "Saved state");
+        dumpsysOnLogcat();
+        dumpUserFile(0);
+
+        // Restore.
+        initService();
+
+        assertEquals(0, mManager.getDynamicShortcuts().size());
+    }
+
+    /**
+     * Try save and load, also stop/start the user.
+     */
+    public void testSaveAndLoadUser() {
+        // First, create some shortcuts and save.
+        runWithCaller(CALLING_PACKAGE_1, UserHandle.USER_SYSTEM, () -> {
+            final Icon icon1 = Icon.createWithResource(mContext, R.drawable.black_64x16);
+            final Icon icon2 = Icon.createWithBitmap(BitmapFactory.decodeResource(
+                    mContext.getResources(), R.drawable.icon2));
+
+            final ShortcutInfo si1 = makeShortcut(
+                    "s1",
+                    "title1-1",
+                    makeComponent(ShortcutActivity.class),
+                    icon1,
+                    makeIntent(Intent.ACTION_ASSIST, ShortcutActivity2.class,
+                            "key1", "val1", "nest", makeBundle("key", 123)),
+                        /* weight */ 10);
+
+            final ShortcutInfo si2 = makeShortcut(
+                    "s2",
+                    "title1-2",
+                        /* activity */ null,
+                    icon2,
+                    makeIntent(Intent.ACTION_ASSIST, ShortcutActivity3.class),
+                        /* weight */ 12);
+
+            assertTrue(mManager.setDynamicShortcuts(Arrays.asList(si1, si2)));
+
+            assertEquals(START_TIME + INTERVAL, mManager.getRateLimitResetTime());
+            assertEquals(2, mManager.getRemainingCallCount());
+        });
+        runWithCaller(CALLING_PACKAGE_2, UserHandle.USER_SYSTEM, () -> {
+            final Icon icon1 = Icon.createWithResource(mContext, R.drawable.black_16x64);
+            final Icon icon2 = Icon.createWithBitmap(BitmapFactory.decodeResource(
+                    mContext.getResources(), R.drawable.icon2));
+
+            final ShortcutInfo si1 = makeShortcut(
+                    "s1",
+                    "title2-1",
+                    makeComponent(ShortcutActivity.class),
+                    icon1,
+                    makeIntent(Intent.ACTION_ASSIST, ShortcutActivity2.class,
+                            "key1", "val1", "nest", makeBundle("key", 123)),
+                        /* weight */ 10);
+
+            final ShortcutInfo si2 = makeShortcut(
+                    "s2",
+                    "title2-2",
+                        /* activity */ null,
+                    icon2,
+                    makeIntent(Intent.ACTION_ASSIST, ShortcutActivity3.class),
+                        /* weight */ 12);
+
+            assertTrue(mManager.setDynamicShortcuts(Arrays.asList(si1, si2)));
+
+            assertEquals(START_TIME + INTERVAL, mManager.getRateLimitResetTime());
+            assertEquals(2, mManager.getRemainingCallCount());
+        });
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
+            final Icon icon1 = Icon.createWithResource(mContext, R.drawable.black_64x64);
+            final Icon icon2 = Icon.createWithBitmap(BitmapFactory.decodeResource(
+                    mContext.getResources(), R.drawable.icon2));
+
+            final ShortcutInfo si1 = makeShortcut(
+                    "s1",
+                    "title10-1-1",
+                    makeComponent(ShortcutActivity.class),
+                    icon1,
+                    makeIntent(Intent.ACTION_ASSIST, ShortcutActivity2.class,
+                            "key1", "val1", "nest", makeBundle("key", 123)),
+                        /* weight */ 10);
+
+            final ShortcutInfo si2 = makeShortcut(
+                    "s2",
+                    "title10-1-2",
+                        /* activity */ null,
+                    icon2,
+                    makeIntent(Intent.ACTION_ASSIST, ShortcutActivity3.class),
+                        /* weight */ 12);
+
+            assertTrue(mManager.setDynamicShortcuts(Arrays.asList(si1, si2)));
+
+            assertEquals(START_TIME + INTERVAL, mManager.getRateLimitResetTime());
+            assertEquals(2, mManager.getRemainingCallCount());
+        });
+
+        // Restore.
+        initService();
+
+        // Before the load, the map should be empty.
+        assertEquals(0, mService.getShortcutsForTest().size());
+
+        // this will pre-load the per-user info.
+        mService.onStartUserLocked(UserHandle.USER_SYSTEM);
+
+        // Now it's loaded.
+        assertEquals(1, mService.getShortcutsForTest().size());
+
+        runWithCaller(CALLING_PACKAGE_1, UserHandle.USER_SYSTEM, () -> {
+            assertShortcutIds(assertAllDynamic(assertAllHaveIntents(assertAllHaveIcon(
+                    mManager.getDynamicShortcuts()))), "s1", "s2");
+            assertEquals(2, mManager.getRemainingCallCount());
+
+            assertEquals("title1-1", getCallerShortcut("s1").getTitle());
+            assertEquals("title1-2", getCallerShortcut("s2").getTitle());
+        });
+        runWithCaller(CALLING_PACKAGE_2, UserHandle.USER_SYSTEM, () -> {
+            assertShortcutIds(assertAllDynamic(assertAllHaveIntents(assertAllHaveIcon(
+                    mManager.getDynamicShortcuts()))), "s1", "s2");
+            assertEquals(2, mManager.getRemainingCallCount());
+
+            assertEquals("title2-1", getCallerShortcut("s1").getTitle());
+            assertEquals("title2-2", getCallerShortcut("s2").getTitle());
+        });
+
+        // Start another user
+        mService.onStartUserLocked(USER_10);
+
+        // Now the size is 2.
+        assertEquals(2, mService.getShortcutsForTest().size());
+
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
+            assertShortcutIds(assertAllDynamic(assertAllHaveIntents(assertAllHaveIcon(
+                    mManager.getDynamicShortcuts()))), "s1", "s2");
+            assertEquals(2, mManager.getRemainingCallCount());
+
+            assertEquals("title10-1-1", getCallerShortcut("s1").getTitle());
+            assertEquals("title10-1-2", getCallerShortcut("s2").getTitle());
+        });
+
+        // Try stopping the user
+        mService.onCleanupUserInner(USER_10);
+
+        // Now it's unloaded.
+        assertEquals(1, mService.getShortcutsForTest().size());
+
+        // TODO Check all other fields
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/testutis/TestUtils.java b/services/tests/servicestests/src/com/android/server/testutis/TestUtils.java
new file mode 100644
index 0000000..52e8f37
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/testutis/TestUtils.java
@@ -0,0 +1,47 @@
+/*
+ * 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.testutis;
+
+import android.test.MoreAsserts;
+
+import junit.framework.Assert;
+
+public class TestUtils {
+    private TestUtils() {
+    }
+
+    public static void assertExpectException(Class<? extends Throwable> expectedExceptionType,
+            Runnable r) {
+        assertExpectException(expectedExceptionType, null, r);
+    }
+
+    public static void assertExpectException(Class<? extends Throwable> expectedExceptionType,
+            String expectedExceptionMessageRegex, Runnable r) {
+        try {
+            r.run();
+            Assert.fail("Expected exception type " + expectedExceptionType.getClass().getName()
+                    + " was not thrown");
+        } catch (Throwable e) {
+            Assert.assertTrue(
+                    "Expected exception type was " + expectedExceptionType.getClass().getName()
+                    + " but caught " + e.getClass().getName(),
+                    expectedExceptionType.isAssignableFrom(e.getClass()));
+            if (expectedExceptionMessageRegex != null) {
+                MoreAsserts.assertContainsRegex(expectedExceptionMessageRegex, e.getMessage());
+            }
+        }
+    }
+}
diff --git a/services/usage/java/com/android/server/usage/UsageStatsService.java b/services/usage/java/com/android/server/usage/UsageStatsService.java
index 8b250f4..8da1785 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsService.java
@@ -437,7 +437,7 @@
                 return false;
             }
         } catch (RemoteException re) {
-            return false;
+            throw re.rethrowFromSystemServer();
         }
 
         final long elapsedRealtime = SystemClock.elapsedRealtime();
@@ -805,6 +805,7 @@
                 return false;
             }
         } catch (RemoteException re) {
+            throw re.rethrowFromSystemServer();
         }
 
         if (isActiveDeviceAdmin(packageName, userId)) {
@@ -849,7 +850,7 @@
             }
             apps = slice.getList();
         } catch (RemoteException e) {
-            return new int[0];
+            throw e.rethrowFromSystemServer();
         }
 
         // State of each uid.  Key is the uid.  Value lower 16 bits is the number of apps
@@ -1258,7 +1259,7 @@
                 userId = ActivityManagerNative.getDefault().handleIncomingUser(Binder.getCallingPid(),
                         Binder.getCallingUid(), userId, false, true, "isAppInactive", null);
             } catch (RemoteException re) {
-                return false;
+                throw re.rethrowFromSystemServer();
             }
             final long token = Binder.clearCallingIdentity();
             try {
@@ -1277,7 +1278,7 @@
                         Binder.getCallingPid(), callingUid, userId, false, true,
                         "setAppIdle", null);
             } catch (RemoteException re) {
-                return;
+                throw re.rethrowFromSystemServer();
             }
             getContext().enforceCallingPermission(Manifest.permission.CHANGE_APP_IDLE_STATE,
                     "No permission to change app idle state");
diff --git a/services/usb/java/com/android/server/usb/MtpNotificationManager.java b/services/usb/java/com/android/server/usb/MtpNotificationManager.java
index 17039bb..101e200 100644
--- a/services/usb/java/com/android/server/usb/MtpNotificationManager.java
+++ b/services/usb/java/com/android/server/usb/MtpNotificationManager.java
@@ -24,6 +24,7 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
+import android.content.pm.PackageManager;
 import android.content.res.Resources;
 import android.hardware.usb.UsbConstants;
 import android.hardware.usb.UsbDevice;
@@ -101,8 +102,8 @@
                 TAG, device.getDeviceId(), notification);
     }
 
-    void hideNotification(UsbDevice device) {
-        mContext.getSystemService(NotificationManager.class).cancel(TAG, device.getDeviceId());
+    void hideNotification(int deviceId) {
+        mContext.getSystemService(NotificationManager.class).cancel(TAG, deviceId);
     }
 
     private class Receiver extends BroadcastReceiver {
@@ -121,7 +122,13 @@
         }
     }
 
-    static boolean isMtpDevice(UsbDevice device) {
+    static boolean shouldShowNotification(PackageManager packageManager, UsbDevice device) {
+        // We don't show MTP notification for devices that has FEATURE_AUTOMOTIVE.
+        return !packageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE) &&
+                isMtpDevice(device);
+    }
+
+    private static boolean isMtpDevice(UsbDevice device) {
         for (int i = 0; i < device.getInterfaceCount(); i++) {
             final UsbInterface usbInterface = device.getInterface(i);
             if ((usbInterface.getInterfaceClass() == UsbConstants.USB_CLASS_STILL_IMAGE &&
diff --git a/services/usb/java/com/android/server/usb/UsbSettingsManager.java b/services/usb/java/com/android/server/usb/UsbSettingsManager.java
index c4d7336..de9ede3 100644
--- a/services/usb/java/com/android/server/usb/UsbSettingsManager.java
+++ b/services/usb/java/com/android/server/usb/UsbSettingsManager.java
@@ -738,7 +738,7 @@
         // Send broadcast to running activity with registered intent
         mUserContext.sendBroadcast(intent);
 
-        if (MtpNotificationManager.isMtpDevice(device)) {
+        if (MtpNotificationManager.shouldShowNotification(mPackageManager, device)) {
             // Show notification if the device is MTP storage.
             mMtpNotificationManager.showNotification(device);
         } else {
@@ -769,9 +769,7 @@
         if (DEBUG) Slog.d(TAG, "usbDeviceRemoved, sending " + intent);
         mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
 
-        if (MtpNotificationManager.isMtpDevice(device)) {
-            mMtpNotificationManager.hideNotification(device);
-        }
+        mMtpNotificationManager.hideNotification(device.getDeviceId());
     }
 
     public void accessoryAttached(UsbAccessory accessory) {
diff --git a/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerHelper.java b/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerHelper.java
index e05f00d..40687b0 100644
--- a/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerHelper.java
+++ b/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerHelper.java
@@ -171,7 +171,7 @@
 
             // Fetch a ModelData instance from the hash map. Creates a new one if none
             // exists.
-            ModelData modelData = getOrCreateGenericModelData(modelId);
+            ModelData modelData = getOrCreateGenericModelDataLocked(modelId);
 
             IRecognitionStatusCallback oldCallback = modelData.getCallback();
             if (oldCallback != null) {
@@ -373,7 +373,7 @@
             // Also clear the internal state once the recognition has been stopped.
             modelData.setLoaded();
             modelData.clearCallback();
-            if (!computeRecognitionRunning()) {
+            if (!computeRecognitionRunningLocked()) {
                 internalClearGlobalStateLocked();
             }
             return status;
@@ -505,12 +505,12 @@
         if (modelId == null || mModule == null) {
             return STATUS_ERROR;
         }
-        ModelData modelData = mGenericModelDataMap.get(modelId);
-        if (modelData == null) {
-            Slog.w(TAG, "Unload error: Attempting unload invalid generic model with id:" + modelId);
-            return STATUS_ERROR;
-        }
         synchronized (mLock) {
+            ModelData modelData = mGenericModelDataMap.get(modelId);
+            if (modelData == null) {
+                Slog.w(TAG, "Unload error: Attempting unload invalid generic model with id:" + modelId);
+                return STATUS_ERROR;
+            }
             if (!modelData.isModelLoaded()) {
                 // Nothing to do here.
                 Slog.i(TAG, "Unload: Given generic model is not loaded:" + modelId);
@@ -530,7 +530,7 @@
                 Slog.w(TAG, "unloadGenericSoundModel() force-marking model as unloaded.");
             }
             mGenericModelDataMap.remove(modelId);
-            if (DBG) dumpGenericModelState();
+            if (DBG) dumpGenericModelStateLocked();
             return status;
         }
     }
@@ -580,7 +580,7 @@
         if (event.status != SoundTrigger.RECOGNITION_STATUS_SUCCESS) {
             return;
         }
-        ModelData model = getModelDataFor(event.soundModelHandle);
+        ModelData model = getModelDataForLocked(event.soundModelHandle);
         if (model == null) {
             Slog.w(TAG, "Generic recognition event: Model does not exist for handle: " +
                     event.soundModelHandle);
@@ -919,7 +919,7 @@
         mIsPowerSaveMode = mPowerManager.isPowerSaveMode();
     }
 
-    private ModelData getOrCreateGenericModelData(UUID modelId) {
+    private ModelData getOrCreateGenericModelDataLocked(UUID modelId) {
         ModelData modelData = mGenericModelDataMap.get(modelId);
         if (modelData == null) {
             modelData = new ModelData(modelId);
@@ -932,7 +932,7 @@
     // Instead of maintaining a second hashmap of modelHandle -> ModelData, we just
     // iterate through to find the right object (since we don't expect 100s of models
     // to be stored).
-    private ModelData getModelDataFor(int modelHandle) {
+    private ModelData getModelDataForLocked(int modelHandle) {
         // Fetch ModelData object corresponding to the model handle.
         for (ModelData model : mGenericModelDataMap.values()) {
             if (model.getHandle() == modelHandle) {
@@ -988,7 +988,7 @@
                 }
             }
         }
-        if (DBG) dumpGenericModelState();
+        if (DBG) dumpGenericModelStateLocked();
         return status;
     }
 
@@ -1017,11 +1017,11 @@
                 }
             }
         }
-        if (DBG) dumpGenericModelState();
+        if (DBG) dumpGenericModelStateLocked();
         return status;
     }
 
-    private void dumpGenericModelState() {
+    private void dumpGenericModelStateLocked() {
         for (UUID modelId : mGenericModelDataMap.keySet()) {
             ModelData modelData = mGenericModelDataMap.get(modelId);
             Slog.i(TAG, "Model :" + modelData.toString());
@@ -1030,28 +1030,24 @@
 
     // Computes whether we have any recognition running at all (voice or generic). Sets
     // the mRecognitionRunning variable with the result.
-    private boolean computeRecognitionRunning() {
-        synchronized (mLock) {
-            if (mModuleProperties == null || mModule == null) {
-                mRecognitionRunning = false;
-                return mRecognitionRunning;
-            }
-            if (mKeyphraseListener != null &&
-                    mKeyphraseStarted &&
-                    mCurrentKeyphraseModelHandle != INVALID_VALUE &&
-                    mCurrentSoundModel != null) {
+    private boolean computeRecognitionRunningLocked() {
+        if (mModuleProperties == null || mModule == null) {
+            mRecognitionRunning = false;
+            return mRecognitionRunning;
+        }
+        if (mKeyphraseListener != null && mKeyphraseStarted &&
+            mCurrentKeyphraseModelHandle != INVALID_VALUE && mCurrentSoundModel != null) {
+            mRecognitionRunning = true;
+            return mRecognitionRunning;
+        }
+        for (UUID modelId : mGenericModelDataMap.keySet()) {
+            ModelData modelData = mGenericModelDataMap.get(modelId);
+            if (modelData.isModelStarted()) {
                 mRecognitionRunning = true;
                 return mRecognitionRunning;
             }
-            for (UUID modelId : mGenericModelDataMap.keySet()) {
-                ModelData modelData = mGenericModelDataMap.get(modelId);
-                if (modelData.isModelStarted()) {
-                    mRecognitionRunning = true;
-                    return mRecognitionRunning;
-                }
-            }
-            mRecognitionRunning = false;
         }
+        mRecognitionRunning = false;
         return mRecognitionRunning;
     }
 
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
index 6ab0b99..837b4a4 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
@@ -75,7 +75,7 @@
  */
 public class VoiceInteractionManagerService extends SystemService {
     static final String TAG = "VoiceInteractionManagerService";
-    static final boolean DEBUG = true;
+    static final boolean DEBUG = false;
 
     final Context mContext;
     final ContentResolver mResolver;
diff --git a/telecomm/java/android/telecom/Call.java b/telecomm/java/android/telecom/Call.java
index de90202..10808da 100644
--- a/telecomm/java/android/telecom/Call.java
+++ b/telecomm/java/android/telecom/Call.java
@@ -624,6 +624,21 @@
                     parcelableCall.getExtras(),
                     parcelableCall.getIntentExtras());
         }
+
+        @Override
+        public String toString() {
+            StringBuilder sb = new StringBuilder();
+            sb.append("[pa: ");
+            sb.append(mAccountHandle);
+            sb.append(", hdl: ");
+            sb.append(Log.pii(mHandle));
+            sb.append(", caps: ");
+            sb.append(capabilitiesToString(mCallCapabilities));
+            sb.append(", props: ");
+            sb.append(mCallProperties);
+            sb.append("]");
+            return sb.toString();
+        }
     }
 
     public static abstract class Callback {
@@ -1000,6 +1015,48 @@
         }
     }
 
+    @Override
+    public String toString() {
+        return new StringBuilder().
+                append("Call [id: ").
+                append(mTelecomCallId).
+                append(", state: ").
+                append(stateToString(mState)).
+                append(", details: ").
+                append(mDetails).
+                append("]").toString();
+    }
+
+    /**
+     * @param state An integer value of a {@code STATE_*} constant.
+     * @return A string representation of the value.
+     */
+    private static String stateToString(int state) {
+        switch (state) {
+            case STATE_NEW:
+                return "NEW";
+            case STATE_RINGING:
+                return "RINGING";
+            case STATE_DIALING:
+                return "DIALING";
+            case STATE_ACTIVE:
+                return "ACTIVE";
+            case STATE_HOLDING:
+                return "HOLDING";
+            case STATE_DISCONNECTED:
+                return "DISCONNECTED";
+            case STATE_CONNECTING:
+                return "CONNECTING";
+            case STATE_DISCONNECTING:
+                return "DISCONNECTING";
+            case STATE_SELECT_PHONE_ACCOUNT:
+                return "SELECT_PHONE_ACCOUNT";
+            default:
+                Log.w(Call.class, "Unknown state %d", state);
+                return "UNKNOWN";
+        }
+    }
+
     /**
      * Adds a listener to this {@code Call}.
      *
diff --git a/telecomm/java/android/telecom/Conference.java b/telecomm/java/android/telecom/Conference.java
index 094b3a9..1b70d65 100644
--- a/telecomm/java/android/telecom/Conference.java
+++ b/telecomm/java/android/telecom/Conference.java
@@ -181,7 +181,10 @@
      * @hide
      */
     public void removeCapability(int capability) {
-        mConnectionCapabilities &= ~capability;
+        int newCapabilities = mConnectionCapabilities;
+        newCapabilities &= ~capability;
+
+        setConnectionCapabilities(newCapabilities);
     }
 
     /**
@@ -191,7 +194,10 @@
      * @hide
      */
     public void addCapability(int capability) {
-        mConnectionCapabilities |= capability;
+        int newCapabilities = mConnectionCapabilities;
+        newCapabilities |= capability;
+
+        setConnectionCapabilities(newCapabilities);
     }
 
     /**
diff --git a/telecomm/java/android/telecom/Log.java b/telecomm/java/android/telecom/Log.java
index 3f32dbe..2ab0525 100644
--- a/telecomm/java/android/telecom/Log.java
+++ b/telecomm/java/android/telecom/Log.java
@@ -16,7 +16,10 @@
 
 package android.telecom;
 
+import android.net.Uri;
 import android.os.AsyncTask;
+import android.telephony.PhoneNumberUtils;
+import android.text.TextUtils;
 
 import java.security.MessageDigest;
 import java.security.NoSuchAlgorithmException;
@@ -152,10 +155,37 @@
     public static String pii(Object pii) {
         if (pii == null || VERBOSE) {
             return String.valueOf(pii);
+        } if (pii instanceof Uri) {
+            return piiUri((Uri) pii);
         }
         return "[" + secureHash(String.valueOf(pii).getBytes()) + "]";
     }
 
+    private static String piiUri(Uri handle) {
+        StringBuilder sb = new StringBuilder();
+        String scheme = handle.getScheme();
+        if (!TextUtils.isEmpty(scheme)) {
+            sb.append(scheme).append(":");
+        }
+        String value = handle.getSchemeSpecificPart();
+        if (!TextUtils.isEmpty(value)) {
+            for (int i = 0; i < value.length(); i++) {
+                char c = value.charAt(i);
+                if (PhoneNumberUtils.isStartsPostDial(c)) {
+                    sb.append(c);
+                } else if (PhoneNumberUtils.isDialable(c)) {
+                    sb.append("*");
+                } else if (('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z')) {
+                    sb.append("*");
+                } else {
+                    sb.append(c);
+                }
+            }
+        }
+        return sb.toString();
+
+    }
+
     private static String secureHash(byte[] input) {
         if (sMessageDigest != null) {
             sMessageDigest.reset();
diff --git a/telecomm/java/android/telecom/TelecomManager.java b/telecomm/java/android/telecom/TelecomManager.java
index 9f478df..8afb455 100644
--- a/telecomm/java/android/telecom/TelecomManager.java
+++ b/telecomm/java/android/telecom/TelecomManager.java
@@ -1425,7 +1425,9 @@
      * <p> This method displays the UI to manage blocked numbers only if
      * {@link android.provider.BlockedNumberContract#canCurrentUserBlockNumbers(Context)} returns
      * {@code true} for the current user.
+     * @deprecated Use {@link #createManageBlockedNumbersIntent()} instead.
      */
+    // TODO: Delete this.
     public void launchManageBlockedNumbersActivity() {
         ITelecomService service = getTelecomService();
         if (service != null) {
@@ -1437,6 +1439,26 @@
         }
     }
 
+    /**
+     * Creates the {@link Intent} which can be used with {@link Context#startActivity(Intent)} to
+     * launch the activity to manage blocked numbers.
+     * <p> The activity will display the UI to manage blocked numbers only if
+     * {@link android.provider.BlockedNumberContract#canCurrentUserBlockNumbers(Context)} returns
+     * {@code true} for the current user.
+     */
+    public Intent createManageBlockedNumbersIntent() {
+        ITelecomService service = getTelecomService();
+        Intent result = null;
+        if (service != null) {
+            try {
+                result = service.createManageBlockedNumbersIntent();
+            } catch (RemoteException e) {
+                Log.e(TAG, "Error calling ITelecomService#createManageBlockedNumbersIntent", e);
+            }
+        }
+        return result;
+    }
+
     private ITelecomService getTelecomService() {
         if (mTelecomServiceOverride != null) {
             return mTelecomServiceOverride;
diff --git a/telecomm/java/com/android/internal/telecom/ITelecomService.aidl b/telecomm/java/com/android/internal/telecom/ITelecomService.aidl
index 95c8db5..3c250f1 100644
--- a/telecomm/java/com/android/internal/telecom/ITelecomService.aidl
+++ b/telecomm/java/com/android/internal/telecom/ITelecomService.aidl
@@ -17,6 +17,7 @@
 package com.android.internal.telecom;
 
 import android.content.ComponentName;
+import android.content.Intent;
 import android.telecom.ParcelableCallAnalytics;
 import android.telecom.PhoneAccountHandle;
 import android.net.Uri;
@@ -247,5 +248,11 @@
     /**
     * @see TelecomServiceImpl#launchManageBlockedNumbersActivity
     **/
+    // TODO: Delete this.
     void launchManageBlockedNumbersActivity(in String callingPackageName);
+
+    /**
+    * @see TelecomServiceImpl#createManageBlockedNumbersIntent
+    **/
+    Intent createManageBlockedNumbersIntent();
 }
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 1278c07..ea437d0 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -251,6 +251,30 @@
      */
     public static final String KEY_CARRIER_WFC_IMS_AVAILABLE_BOOL = "carrier_wfc_ims_available_bool";
 
+    /**
+     * Default WFC_IMS_mode 0: WIFI_ONLY
+     *                      1: CELLULAR_PREFERRED
+     *                      2: WIFI_PREFERRED
+     * @hide
+     */
+    public static final String KEY_CARRIER_DEFAULT_WFC_IMS_MODE_INT =
+            "carrier_default_wfc_ims_mode_int";
+    /**
+     * Default WFC_IMS_enabled: true VoWiFi by default is on
+     *                          false VoWiFi by default is off
+     * @hide
+     */
+    public static final String KEY_CARRIER_DEFAULT_WFC_IMS_ENABLED_BOOL =
+            "carrier_default_wfc_ims_enabled_bool";
+
+    /**
+     * Default WFC_IMS_roaming_enabled: true VoWiFi roaming by default is on
+     *                                  false VoWiFi roaming by default is off
+     * @hide
+     */
+    public static final String KEY_CARRIER_DEFAULT_WFC_IMS_ROAMING_ENABLED_BOOL =
+            "carrier_default_wfc_ims_roaming_enabled_bool";
+
     /** Flag specifying whether provisioning is required for VOLTE. */
     public static final String KEY_CARRIER_VOLTE_PROVISIONING_REQUIRED_BOOL
             = "carrier_volte_provisioning_required_bool";
@@ -613,6 +637,9 @@
         sDefaults.putBoolean(KEY_CARRIER_VOLTE_AVAILABLE_BOOL, false);
         sDefaults.putBoolean(KEY_CARRIER_VT_AVAILABLE_BOOL, false);
         sDefaults.putBoolean(KEY_CARRIER_WFC_IMS_AVAILABLE_BOOL, false);
+        sDefaults.putBoolean(KEY_CARRIER_DEFAULT_WFC_IMS_ENABLED_BOOL, false);
+        sDefaults.putBoolean(KEY_CARRIER_DEFAULT_WFC_IMS_ROAMING_ENABLED_BOOL, false);
+        sDefaults.putInt(KEY_CARRIER_DEFAULT_WFC_IMS_MODE_INT, 2);
         sDefaults.putBoolean(KEY_CARRIER_FORCE_DISABLE_ETWS_CMAS_TEST_BOOL, false);
         sDefaults.putBoolean(KEY_CARRIER_VOLTE_PROVISIONING_REQUIRED_BOOL, false);
         sDefaults.putBoolean(KEY_CARRIER_VOLTE_TTY_SUPPORTED_BOOL, true);
@@ -637,7 +664,7 @@
         sDefaults.putBoolean(KEY_SHOW_CDMA_CHOICES_BOOL, false);
         sDefaults.putBoolean(KEY_SHOW_ONSCREEN_DIAL_BUTTON_BOOL, true);
         sDefaults.putBoolean(KEY_SIM_NETWORK_UNLOCK_ALLOW_DISMISS_BOOL, true);
-        sDefaults.putBoolean(KEY_SUPPORT_PAUSE_IMS_VIDEO_CALLS_BOOL, true);
+        sDefaults.putBoolean(KEY_SUPPORT_PAUSE_IMS_VIDEO_CALLS_BOOL, false);
         sDefaults.putBoolean(KEY_SUPPORT_SWAP_AFTER_MERGE_BOOL, true);
         sDefaults.putBoolean(KEY_USE_HFA_FOR_PROVISIONING_BOOL, false);
         sDefaults.putBoolean(KEY_USE_OTASP_FOR_PROVISIONING_BOOL, false);
diff --git a/telephony/java/android/telephony/ServiceState.java b/telephony/java/android/telephony/ServiceState.java
index ad007c6..39a9295 100644
--- a/telephony/java/android/telephony/ServiceState.java
+++ b/telephony/java/android/telephony/ServiceState.java
@@ -36,7 +36,7 @@
 public class ServiceState implements Parcelable {
 
     static final String LOG_TAG = "PHONE";
-    static final boolean DBG = true;
+    static final boolean DBG = false;
     static final boolean VDBG = false;  // STOPSHIP if true
 
     /**
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index e90be91..b482811 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -4403,7 +4403,6 @@
             Log.e(TAG, "Error calling ITelephony#getDataEnabled", e);
         } catch (NullPointerException e) {
         }
-        Log.d(TAG, "getDataEnabled: retVal=" + retVal);
         return retVal;
     }
 
diff --git a/telephony/java/com/android/ims/ImsCallProfile.java b/telephony/java/com/android/ims/ImsCallProfile.java
index 5f84e0c..96c6243 100644
--- a/telephony/java/com/android/ims/ImsCallProfile.java
+++ b/telephony/java/com/android/ims/ImsCallProfile.java
@@ -178,7 +178,7 @@
      *  Codec: Codec info.
      *  DisplayText: Display text for the call.
      *  AdditionalCallInfo: Additional call info.
-     *  CallRadioTech: The radio tech on which the call is placed.
+     *  CallPull: Boolean value specifying if the call is a pulled call.
      */
     public static final String EXTRA_OI = "oi";
     public static final String EXTRA_CNA = "cna";
@@ -188,6 +188,7 @@
     public static final String EXTRA_CODEC = "Codec";
     public static final String EXTRA_DISPLAY_TEXT = "DisplayText";
     public static final String EXTRA_ADDITIONAL_CALL_INFO = "AdditionalCallInfo";
+    public static final String EXTRA_IS_CALL_PULL = "CallPull";
 
     /**
      * Extra key which the RIL can use to indicate the radio technology used for a call.
diff --git a/telephony/java/com/android/internal/telephony/RILConstants.java b/telephony/java/com/android/internal/telephony/RILConstants.java
index bba357e..7f90731 100644
--- a/telephony/java/com/android/internal/telephony/RILConstants.java
+++ b/telephony/java/com/android/internal/telephony/RILConstants.java
@@ -92,6 +92,11 @@
     int NO_SMS_TO_ACK = 48;                   /* ACK received when there is no SMS to ack */
     int NETWORK_ERR = 49;                     /* Received error from network */
     int REQUEST_RATE_LIMITED = 50;            /* Operation denied due to overly-frequent requests */
+    int SIM_BUSY = 51;                        /* SIM is busy */
+    int SIM_FULL = 52;                        /* The target EF is full */
+    int NETWORK_REJECT = 53;                  /* Request is rejected by network */
+    int OPERATION_NOT_ALLOWED = 54;           /* Not allowed the request now */
+    int EMPTY_RECORD = 55;                    /* The request record is empty */
     // Below is list of OEM specific error codes which can by used by OEMs in case they don't want to
     // reveal particular replacement for Generic failure
     int OEM_ERROR_1 = 501;
diff --git a/test-runner/src/android/test/mock/MockPackageManager.java b/test-runner/src/android/test/mock/MockPackageManager.java
index da43460..e851c8d 100644
--- a/test-runner/src/android/test/mock/MockPackageManager.java
+++ b/test-runner/src/android/test/mock/MockPackageManager.java
@@ -25,7 +25,6 @@
 import android.content.IntentSender;
 import android.content.pm.ActivityInfo;
 import android.content.pm.ApplicationInfo;
-import android.content.pm.ContainerEncryptionParams;
 import android.content.pm.EphemeralApplicationInfo;
 import android.content.pm.FeatureInfo;
 import android.content.pm.IPackageDataObserver;
@@ -44,7 +43,6 @@
 import android.content.pm.ProviderInfo;
 import android.content.pm.ResolveInfo;
 import android.content.pm.ServiceInfo;
-import android.content.pm.VerificationParams;
 import android.content.pm.VerifierDeviceIdentity;
 import android.content.res.Resources;
 import android.content.res.XmlResourceParser;
@@ -520,6 +518,14 @@
         throw new UnsupportedOperationException();
     }
 
+    /** @hide */
+    @Override
+    public Drawable getManagedUserBadgedDrawable(Drawable drawable, Rect badgeLocation,
+            int badgeDensity) {
+        throw new UnsupportedOperationException();
+    }
+
+
     @Override
     public Drawable getUserBadgedIcon(Drawable icon, UserHandle user) {
         throw new UnsupportedOperationException();
@@ -602,14 +608,6 @@
         throw new UnsupportedOperationException();
     }
 
-    /** @hide */
-    @Override
-    public void installPackageAsUser(Uri packageURI, PackageInstallObserver observer,
-            int flags, String installerPackageName, int userId) {
-        throw new UnsupportedOperationException();
-    }
-
-
     @Override
     public void setInstallerPackageName(String targetPackage,
             String installerPackageName) {
@@ -873,26 +871,6 @@
      * @hide
      */
     @Override
-    public void installPackageWithVerification(Uri packageURI, IPackageInstallObserver observer,
-            int flags, String installerPackageName, Uri verificationURI,
-            ContainerEncryptionParams encryptionParams) {
-        throw new UnsupportedOperationException();
-    }
-
-    /**
-     * @hide
-     */
-    @Override
-    public void installPackageWithVerificationAndEncryption(Uri packageURI,
-            IPackageInstallObserver observer, int flags, String installerPackageName,
-            VerificationParams verificationParams, ContainerEncryptionParams encryptionParams) {
-        throw new UnsupportedOperationException();
-    }
-
-    /**
-     * @hide
-     */
-    @Override
     public boolean setApplicationHiddenSettingAsUser(String packageName, boolean hidden,
             UserHandle user) {
         return false;
@@ -1024,27 +1002,6 @@
      * @hide
      */
     @Override
-    public void installPackageWithVerification(Uri packageURI,
-            PackageInstallObserver observer, int flags, String installerPackageName,
-            Uri verificationURI,
-            ContainerEncryptionParams encryptionParams) {
-        throw new UnsupportedOperationException();
-    }
-
-    /**
-     * @hide
-     */
-    @Override
-    public void installPackageWithVerificationAndEncryption(Uri packageURI,
-            PackageInstallObserver observer, int flags, String installerPackageName,
-            VerificationParams verificationParams, ContainerEncryptionParams encryptionParams) {
-        throw new UnsupportedOperationException();
-    }
-
-    /**
-     * @hide
-     */
-    @Override
     public void addCrossProfileIntentFilter(IntentFilter filter, int sourceUserId, int targetUserId,
             int flags) {
         throw new UnsupportedOperationException();
diff --git a/tests/AppLaunch/src/com/android/tests/applaunch/AppLaunch.java b/tests/AppLaunch/src/com/android/tests/applaunch/AppLaunch.java
index 4bed941..ed7351f8 100644
--- a/tests/AppLaunch/src/com/android/tests/applaunch/AppLaunch.java
+++ b/tests/AppLaunch/src/com/android/tests/applaunch/AppLaunch.java
@@ -160,7 +160,7 @@
         for (String pair : appNames) {
             String[] parts = pair.split("\\^");
             if (parts.length != 2) {
-                Log.e(TAG, "The apps key is incorectly formatted");
+                Log.e(TAG, "The apps key is incorrectly formatted");
                 fail();
             }
 
@@ -176,6 +176,10 @@
         }
     }
 
+    private boolean hasLeanback(Context context) {
+        return context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_LEANBACK);
+    }
+
     private void createMappings() {
         mNameToIntent = new LinkedHashMap<String, Intent>();
         mNameToProcess = new LinkedHashMap<String, String>();
@@ -183,9 +187,12 @@
         PackageManager pm = getInstrumentation().getContext()
                 .getPackageManager();
         Intent intentToResolve = new Intent(Intent.ACTION_MAIN);
-        intentToResolve.addCategory(Intent.CATEGORY_LAUNCHER);
+        intentToResolve.addCategory(hasLeanback(getInstrumentation().getContext()) ?
+                Intent.CATEGORY_LEANBACK_LAUNCHER :
+                Intent.CATEGORY_LAUNCHER);
         List<ResolveInfo> ris = pm.queryIntentActivities(intentToResolve, 0);
         resolveLoop(ris, intentToResolve, pm);
+        // For Wear
         intentToResolve = new Intent(WEARABLE_ACTION_GOOGLE);
         ris = pm.queryIntentActivities(intentToResolve, 0);
         resolveLoop(ris, intentToResolve, pm);
@@ -232,7 +239,7 @@
         // report error if any of the following is true:
         // * launch thread is alive
         // * result is not null, but:
-        //   * result is not START_SUCESS
+        //   * result is not START_SUCCESS
         //   * or in case of no force stop, result is not TASK_TO_FRONT either
         if (t.isAlive() || (result != null
                 && ((result.result != ActivityManager.START_SUCCESS)
diff --git a/tests/HwAccelerationTest/res/drawable/default_wallpaper.jpg b/tests/HwAccelerationTest/res/drawable/default_wallpaper.jpg
deleted file mode 100644
index 5acad94..0000000
--- a/tests/HwAccelerationTest/res/drawable/default_wallpaper.jpg
+++ /dev/null
Binary files differ
diff --git a/tests/HwAccelerationTest/res/drawable/default_wallpaper.png b/tests/HwAccelerationTest/res/drawable/default_wallpaper.png
new file mode 100644
index 0000000..187a6c0
--- /dev/null
+++ b/tests/HwAccelerationTest/res/drawable/default_wallpaper.png
Binary files differ
diff --git a/tests/HwAccelerationTest/res/layout/projection_clipping.xml b/tests/HwAccelerationTest/res/layout/projection_clipping.xml
index 1f2b939..1ea9f9c 100644
--- a/tests/HwAccelerationTest/res/layout/projection_clipping.xml
+++ b/tests/HwAccelerationTest/res/layout/projection_clipping.xml
@@ -3,24 +3,32 @@
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
     android:layout_height="match_parent">
-    <FrameLayout
+    <ScrollView
+        android:orientation="vertical"
         android:translationX="50dp"
         android:translationY="50dp"
         android:elevation="30dp"
         android:layout_width="200dp"
         android:layout_height="200dp"
         android:background="@drawable/round_rect_background">
-        <View
-            android:id="@+id/clickable1"
-            android:layout_width="100dp"
-            android:layout_height="100dp"
-            android:background="?android:attr/selectableItemBackgroundBorderless"/>
-        <View
-            android:id="@+id/clickable2"
-            android:translationX="50dp"
-            android:translationY="10dp"
-            android:layout_width="150dp"
-            android:layout_height="100dp"
-            android:background="?android:attr/selectableItemBackgroundBorderless"/>
-    </FrameLayout>
+        <FrameLayout
+            android:layout_width="200dp"
+            android:layout_height="wrap_content">
+            <View
+                android:layout_width="200dp"
+                android:layout_height="2000dp"/>
+            <View
+                android:id="@+id/clickable1"
+                android:layout_width="100dp"
+                android:layout_height="100dp"
+                android:background="?android:attr/selectableItemBackgroundBorderless"/>
+            <View
+                android:id="@+id/clickable2"
+                android:translationX="50dp"
+                android:translationY="10dp"
+                android:layout_width="150dp"
+                android:layout_height="100dp"
+                android:background="?android:attr/selectableItemBackgroundBorderless"/>
+       </FrameLayout>
+    </ScrollView>
 </LinearLayout>
diff --git a/tests/NetworkSecurityConfigTest/res/xml/bad_extra_debug_resource.xml b/tests/NetworkSecurityConfigTest/res/xml/bad_extra_debug_resource.xml
new file mode 100644
index 0000000..8093b9d
--- /dev/null
+++ b/tests/NetworkSecurityConfigTest/res/xml/bad_extra_debug_resource.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<network-security-config>
+  <base-config>
+    <trust-anchors>
+    </trust-anchors>
+  </base-config>
+</network-security-config>
diff --git a/tests/NetworkSecurityConfigTest/res/xml/bad_extra_debug_resource_debug.xml b/tests/NetworkSecurityConfigTest/res/xml/bad_extra_debug_resource_debug.xml
new file mode 100644
index 0000000..fc24df5
--- /dev/null
+++ b/tests/NetworkSecurityConfigTest/res/xml/bad_extra_debug_resource_debug.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- debug-overrides not inside network-security-config should cause a parsing error -->
+<debug-overrides>
+  <trust-anchors>
+    <certificates src="system" />
+  </trust-anchors>
+</debug-overrides>
diff --git a/tests/NetworkSecurityConfigTest/res/xml/extra_debug_resource.xml b/tests/NetworkSecurityConfigTest/res/xml/extra_debug_resource.xml
new file mode 100644
index 0000000..8093b9d
--- /dev/null
+++ b/tests/NetworkSecurityConfigTest/res/xml/extra_debug_resource.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<network-security-config>
+  <base-config>
+    <trust-anchors>
+    </trust-anchors>
+  </base-config>
+</network-security-config>
diff --git a/tests/NetworkSecurityConfigTest/res/xml/extra_debug_resource_debug.xml b/tests/NetworkSecurityConfigTest/res/xml/extra_debug_resource_debug.xml
new file mode 100644
index 0000000..6a2ad37
--- /dev/null
+++ b/tests/NetworkSecurityConfigTest/res/xml/extra_debug_resource_debug.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<network-security-config>
+  <debug-overrides>
+    <trust-anchors>
+      <certificates src="system" />
+    </trust-anchors>
+  </debug-overrides>
+</network-security-config>
diff --git a/tests/NetworkSecurityConfigTest/src/android/security/net/config/XmlConfigTests.java b/tests/NetworkSecurityConfigTest/src/android/security/net/config/XmlConfigTests.java
index 35e3ef4..10bcc18 100644
--- a/tests/NetworkSecurityConfigTest/src/android/security/net/config/XmlConfigTests.java
+++ b/tests/NetworkSecurityConfigTest/src/android/security/net/config/XmlConfigTests.java
@@ -431,4 +431,37 @@
         TestUtils.assertConnectionSucceeds(context, "android.com", 443);
         TestUtils.assertUrlConnectionSucceeds(context, "android.com", 443);
     }
+
+    public void testExtraDebugResource() throws Exception {
+        XmlConfigSource source =
+                new XmlConfigSource(getContext(), R.xml.extra_debug_resource, true);
+        ApplicationConfig appConfig = new ApplicationConfig(source);
+        assertFalse(appConfig.hasPerDomainConfigs());
+        NetworkSecurityConfig config = appConfig.getConfigForHostname("");
+        MoreAsserts.assertNotEmpty(config.getTrustAnchors());
+
+        // Check that the _debug file is ignored if debug is false.
+        source = new XmlConfigSource(getContext(), R.xml.extra_debug_resource, false);
+        appConfig = new ApplicationConfig(source);
+        assertFalse(appConfig.hasPerDomainConfigs());
+        config = appConfig.getConfigForHostname("");
+        MoreAsserts.assertEmpty(config.getTrustAnchors());
+    }
+
+    public void testExtraDebugResourceIgnored() throws Exception {
+        // Verify that parsing the extra debug config resource fails only when debugging is true.
+        XmlConfigSource source =
+                new XmlConfigSource(getContext(), R.xml.bad_extra_debug_resource, false);
+        ApplicationConfig appConfig = new ApplicationConfig(source);
+        // Force parsing the config file.
+        appConfig.getConfigForHostname("");
+
+        source = new XmlConfigSource(getContext(), R.xml.bad_extra_debug_resource, true);
+        appConfig = new ApplicationConfig(source);
+        try {
+            appConfig.getConfigForHostname("");
+            fail("Bad extra debug resource did not fail to parse");
+        } catch (RuntimeException expected) {
+        }
+    }
 }
diff --git a/tests/OneMedia/src/com/android/onemedia/playback/LocalRenderer.java b/tests/OneMedia/src/com/android/onemedia/playback/LocalRenderer.java
index c8a8d6c..6463e1f 100644
--- a/tests/OneMedia/src/com/android/onemedia/playback/LocalRenderer.java
+++ b/tests/OneMedia/src/com/android/onemedia/playback/LocalRenderer.java
@@ -47,7 +47,7 @@
         OnBufferingUpdateListener, OnCompletionListener, OnErrorListener,
         OnAudioFocusChangeListener {
     private static final String TAG = "MediaPlayerManager";
-    private static final boolean DEBUG = true;
+    private static final boolean DEBUG = false;
     private static long sDebugInstanceId = 0;
 
     private static final String[] SUPPORTED_FEATURES = {
diff --git a/tests/SoundTriggerTestApp/src/com/android/test/soundtrigger/TestSoundTriggerActivity.java b/tests/SoundTriggerTestApp/src/com/android/test/soundtrigger/TestSoundTriggerActivity.java
index 4770c05..3ca96d2 100644
--- a/tests/SoundTriggerTestApp/src/com/android/test/soundtrigger/TestSoundTriggerActivity.java
+++ b/tests/SoundTriggerTestApp/src/com/android/test/soundtrigger/TestSoundTriggerActivity.java
@@ -40,7 +40,7 @@
 
 public class TestSoundTriggerActivity extends Activity {
     private static final String TAG = "TestSoundTriggerActivity";
-    private static final boolean DBG = true;
+    private static final boolean DBG = false;
 
     private SoundTriggerUtil mSoundTriggerUtil;
     private Random mRandom;
diff --git a/tests/SoundTriggerTests/Android.mk b/tests/SoundTriggerTests/Android.mk
index 407a9d7..ac562b9 100644
--- a/tests/SoundTriggerTests/Android.mk
+++ b/tests/SoundTriggerTests/Android.mk
@@ -18,7 +18,14 @@
 
 LOCAL_MODULE_TAGS := tests
 
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
+ifeq ($(SOUND_TRIGGER_USE_STUB_MODULE), 1)
+  LOCAL_SRC_FILES := $(call all-subdir-java-files)
+  LOCAL_PRIVILEGED_MODULE := true
+  LOCAL_CERTIFICATE := platform
+  TARGET_OUT_DATA_APPS_PRIVILEGED := $(TARGET_OUT_DATA)/priv-app
+else
+  LOCAL_SRC_FILES := src/android/hardware/soundtrigger/SoundTriggerTest.java
+endif
 
 LOCAL_JAVA_LIBRARIES := android.test.runner
 
diff --git a/tests/SoundTriggerTests/AndroidManifest.xml b/tests/SoundTriggerTests/AndroidManifest.xml
index 5e5a108..e8b9dd3 100644
--- a/tests/SoundTriggerTests/AndroidManifest.xml
+++ b/tests/SoundTriggerTests/AndroidManifest.xml
@@ -14,7 +14,10 @@
      limitations under the License.
 -->
 
-<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="android.hardware.soundtrigger">
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="android.hardware.soundtrigger">
+    <uses-permission android:name="android.permission.MANAGE_SOUND_TRIGGER" />
+
     <application>
         <uses-library android:name="android.test.runner" />
     </application>
diff --git a/tests/SoundTriggerTests/src/android/hardware/soundtrigger/stubhal/GenericSoundModelTest.java b/tests/SoundTriggerTests/src/android/hardware/soundtrigger/stubhal/GenericSoundModelTest.java
new file mode 100644
index 0000000..7acb472
--- /dev/null
+++ b/tests/SoundTriggerTests/src/android/hardware/soundtrigger/stubhal/GenericSoundModelTest.java
@@ -0,0 +1,85 @@
+/*
+ * 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.hardware.soundtrigger;
+
+import java.util.Random;
+import java.util.UUID;
+
+import android.content.Context;
+import android.hardware.soundtrigger.SoundTrigger.GenericSoundModel;
+import android.media.soundtrigger.SoundTriggerManager;
+import android.os.ParcelUuid;
+import android.os.ServiceManager;
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+
+import com.android.internal.app.ISoundTriggerService;
+
+import java.util.Arrays;
+import java.util.Random;
+import java.util.UUID;
+
+public class GenericSoundModelTest extends AndroidTestCase {
+    private Random mRandom = new Random();
+
+    @SmallTest
+    public void testUpdateGenericSoundModel() throws Exception {
+        Context context = getContext();
+        ISoundTriggerService mSoundTriggerService = ISoundTriggerService.Stub.asInterface(
+            ServiceManager.getService(Context.SOUND_TRIGGER_SERVICE));
+        SoundTriggerManager mSoundTriggerManager = (SoundTriggerManager) context.getSystemService(
+            Context.SOUND_TRIGGER_SERVICE);
+
+        byte[] data = new byte[1024];
+        mRandom.nextBytes(data);
+        UUID modelUuid = UUID.randomUUID();
+        UUID mVendorUuid = UUID.randomUUID();
+        GenericSoundModel model = new GenericSoundModel(modelUuid, mVendorUuid, data);
+
+        mSoundTriggerService.updateSoundModel(model);
+        GenericSoundModel returnedModel =
+            mSoundTriggerService.getSoundModel(new ParcelUuid(modelUuid));
+
+        assertEquals(model, returnedModel);
+
+        // Cleanup sound model
+        mSoundTriggerService.deleteSoundModel(new ParcelUuid(modelUuid));
+    }
+
+
+    @SmallTest
+    public void testDeleteGenericSoundModel() throws Exception {
+        Context context = getContext();
+        ISoundTriggerService mSoundTriggerService = ISoundTriggerService.Stub.asInterface(
+            ServiceManager.getService(Context.SOUND_TRIGGER_SERVICE));
+        SoundTriggerManager mSoundTriggerManager = (SoundTriggerManager) context.getSystemService(
+            Context.SOUND_TRIGGER_SERVICE);
+
+        byte[] data = new byte[1024];
+        mRandom.nextBytes(data);
+        UUID modelUuid = UUID.randomUUID();
+        UUID mVendorUuid = UUID.randomUUID();
+        GenericSoundModel model = new GenericSoundModel(modelUuid, mVendorUuid, data);
+
+        mSoundTriggerService.updateSoundModel(model);
+        mSoundTriggerService.deleteSoundModel(new ParcelUuid(modelUuid));
+
+        GenericSoundModel returnedModel =
+            mSoundTriggerService.getSoundModel(new ParcelUuid(modelUuid));
+        assertEquals(null, returnedModel);
+    }
+}
diff --git a/tests/StatusBar/src/com/android/statusbartest/NotificationTestList.java b/tests/StatusBar/src/com/android/statusbartest/NotificationTestList.java
index 9ac4dbf..0da1bb1 100644
--- a/tests/StatusBar/src/com/android/statusbartest/NotificationTestList.java
+++ b/tests/StatusBar/src/com/android/statusbartest/NotificationTestList.java
@@ -86,6 +86,167 @@
     }
 
     private Test[] mTests = new Test[] {
+            new Test("Min priority") {
+                public void run()
+                {
+                    Notification n = new Notification.Builder(NotificationTestList.this)
+                            .setSmallIcon(R.drawable.icon2)
+                            .setContentTitle("Min priority")
+                            .setLights(0xff0000ff, 1, 0)
+                            .setPriority(Notification.PRIORITY_MIN)
+                            .build();
+                    mNM.notify(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)
+                            .setSmallIcon(R.drawable.icon2)
+                            .setContentTitle("Low priority")
+                            .setLights(0xff0000ff, 1, 0)
+                            .setPriority(Notification.PRIORITY_LOW)
+                            .build();
+                    mNM.notify(7002, n);
+                }
+            },
+            new Test("Default priority") {
+                public void run()
+                {
+                    Notification n = new Notification.Builder(NotificationTestList.this)
+                            .setSmallIcon(R.drawable.icon2)
+                            .setContentTitle("Default priority")
+                            .setLights(0xff0000ff, 1, 0)
+                            .setPriority(Notification.PRIORITY_DEFAULT)
+                            .build();
+                    mNM.notify(7004, n);
+                }
+            },
+            new Test("High priority") {
+                public void run()
+                {
+                    Notification n = new Notification.Builder(NotificationTestList.this)
+                            .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(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(7007, n);
+                }
+            },
+            new Test("Max priority with delay") {
+                public void run()
+                {
+                    try {
+                        Thread.sleep(5000);
+                    } catch (InterruptedException e) {
+                    }
+                    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(7008, n);
+                }
+            },
+            new Test("public notification") {
+                public void run()
+                {
+                    Notification n = new Notification.Builder(NotificationTestList.this)
+                            .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(7009, n);
+                }
+            },
+            new Test("private notification, no public") {
+                public void run()
+                {
+                    Notification n = new Notification.Builder(NotificationTestList.this)
+                            .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(7010, n);
+                }
+            },
+            new Test("private notification, has public") {
+                public void run()
+                {
+                    Notification n = new Notification.Builder(NotificationTestList.this)
+                            .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)
+                                    .setSmallIcon(R.drawable.icon2)
+                                    .setContentTitle("public notification of private notification")
+                                    .setPriority(Notification.PRIORITY_DEFAULT)
+                                    .setVisibility(Notification.VISIBILITY_PUBLIC)
+                                    .build())
+                            .build();
+                    mNM.notify(7011, n);
+                }
+            },
+            new Test("secret notification") {
+                public void run()
+                {
+                    Notification n = new Notification.Builder(NotificationTestList.this)
+                            .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(7012, n);
+                }
+            },
         new Test("Off") {
             public void run() {
                 PowerManager pm = (PowerManager)NotificationTestList.this.getSystemService(Context.POWER_SERVICE);
diff --git a/tests/VectorDrawableTest/res/color/fill_gradient_linear_clamp.xml b/tests/VectorDrawableTest/res/color/fill_gradient_linear_clamp.xml
new file mode 100644
index 0000000..6a24453
--- /dev/null
+++ b/tests/VectorDrawableTest/res/color/fill_gradient_linear_clamp.xml
@@ -0,0 +1,30 @@
+<?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.
+ */
+-->
+<gradient xmlns:android="http://schemas.android.com/apk/res/android"
+          android:angle="90"
+          android:startColor="?android:attr/colorPrimary"
+          android:endColor="?android:attr/colorControlActivated"
+          android:centerColor="#00ff0000"
+          android:startX="0"
+          android:startY="0"
+          android:endX="50"
+          android:endY="50"
+          android:type="linear"
+          android:tileMode="clamp">
+</gradient>
\ No newline at end of file
diff --git a/tests/VectorDrawableTest/res/color/fill_gradient_linear_item_overlap_mirror.xml b/tests/VectorDrawableTest/res/color/fill_gradient_linear_item_overlap_mirror.xml
new file mode 100644
index 0000000..d342bca
--- /dev/null
+++ b/tests/VectorDrawableTest/res/color/fill_gradient_linear_item_overlap_mirror.xml
@@ -0,0 +1,34 @@
+<?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.
+ */
+-->
+<gradient xmlns:android="http://schemas.android.com/apk/res/android"
+          android:angle="90"
+          android:startColor="?android:attr/colorPrimary"
+          android:endColor="?android:attr/colorControlActivated"
+          android:centerColor="#f00"
+          android:startX="0"
+          android:startY="0"
+          android:endX="50"
+          android:endY="50"
+          android:type="linear"
+          android:tileMode="mirror">
+    <item android:offset="0.1" android:color="?android:attr/colorPrimary"/>
+    <item android:offset="0.4" android:color="#f00"/>
+    <item android:offset="0.4" android:color="#fff"/>
+    <item android:offset="0.9" android:color="?android:attr/colorControlActivated"/>
+</gradient>
\ No newline at end of file
diff --git a/tests/VectorDrawableTest/res/color/fill_gradient_linear_item_repeat.xml b/tests/VectorDrawableTest/res/color/fill_gradient_linear_item_repeat.xml
new file mode 100644
index 0000000..afb45aa
--- /dev/null
+++ b/tests/VectorDrawableTest/res/color/fill_gradient_linear_item_repeat.xml
@@ -0,0 +1,33 @@
+<?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.
+ */
+-->
+<gradient xmlns:android="http://schemas.android.com/apk/res/android"
+          android:angle="90"
+          android:startColor="?android:attr/colorPrimary"
+          android:endColor="?android:attr/colorControlActivated"
+          android:centerColor="#f00"
+          android:startX="0"
+          android:startY="0"
+          android:endX="50"
+          android:endY="50"
+          android:type="linear"
+          android:tileMode="repeat">
+    <item android:offset="0.1" android:color="?android:attr/colorPrimary"/>
+    <item android:offset="0.4" android:color="#fff"/>
+    <item android:offset="0.9" android:color="?android:attr/colorControlActivated"/>
+</gradient>
\ No newline at end of file
diff --git a/tests/VectorDrawableTest/res/color/fill_gradient_radial_clamp.xml b/tests/VectorDrawableTest/res/color/fill_gradient_radial_clamp.xml
new file mode 100644
index 0000000..64b32f6
--- /dev/null
+++ b/tests/VectorDrawableTest/res/color/fill_gradient_radial_clamp.xml
@@ -0,0 +1,28 @@
+<?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.
+ */
+-->
+<gradient xmlns:android="http://schemas.android.com/apk/res/android"
+          android:centerColor="#ff0000"
+          android:endColor="?android:attr/colorControlActivated"
+          android:centerX="300"
+          android:centerY="300"
+          android:gradientRadius="50"
+          android:startColor="?android:attr/colorPrimary"
+          android:type="radial"
+          android:tileMode="clamp">
+</gradient>
\ No newline at end of file
diff --git a/tests/VectorDrawableTest/res/color/fill_gradient_radial_item.xml b/tests/VectorDrawableTest/res/color/fill_gradient_radial_item.xml
index 51b0e17..c6cea7c 100644
--- a/tests/VectorDrawableTest/res/color/fill_gradient_radial_item.xml
+++ b/tests/VectorDrawableTest/res/color/fill_gradient_radial_item.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-    <!--
+<!--
 /*
  * Copyright (C) 2016 The Android Open Source Project
  *
diff --git a/tests/VectorDrawableTest/res/color/fill_gradient_radial_item_repeat.xml b/tests/VectorDrawableTest/res/color/fill_gradient_radial_item_repeat.xml
new file mode 100644
index 0000000..fb4346a
--- /dev/null
+++ b/tests/VectorDrawableTest/res/color/fill_gradient_radial_item_repeat.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.
+ */
+-->
+<gradient xmlns:android="http://schemas.android.com/apk/res/android"
+          android:centerColor="#ff0000"
+          android:endColor="#ff0000ff"
+          android:centerX="300"
+          android:centerY="300"
+          android:gradientRadius="50"
+          android:startColor="#ffffffff"
+          android:type="radial"
+          android:tileMode="repeat">
+    <item android:offset="0.1" android:color="?android:attr/colorPrimary"/>
+    <item android:offset="0.4" android:color="#fff"/>
+    <item android:offset="0.9" android:color="?android:attr/colorControlActivated"/>
+</gradient>
\ No newline at end of file
diff --git a/tests/VectorDrawableTest/res/color/fill_gradient_radial_item_short.xml b/tests/VectorDrawableTest/res/color/fill_gradient_radial_item_short.xml
index 8caa1b4..fefbe9f 100644
--- a/tests/VectorDrawableTest/res/color/fill_gradient_radial_item_short.xml
+++ b/tests/VectorDrawableTest/res/color/fill_gradient_radial_item_short.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-    <!--
+<!--
 /*
  * Copyright (C) 2016 The Android Open Source Project
  *
diff --git a/tests/VectorDrawableTest/res/color/fill_gradient_radial_item_short_mirror.xml b/tests/VectorDrawableTest/res/color/fill_gradient_radial_item_short_mirror.xml
new file mode 100644
index 0000000..8b5ad7c
--- /dev/null
+++ b/tests/VectorDrawableTest/res/color/fill_gradient_radial_item_short_mirror.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.
+ */
+-->
+<gradient xmlns:android="http://schemas.android.com/apk/res/android"
+          android:centerX="300"
+          android:centerY="300"
+          android:gradientRadius="50"
+          android:type="radial"
+          android:tileMode="mirror">
+    <item android:offset="0.1" android:color="?android:attr/colorPrimary"/>
+    <item android:offset="0.9" android:color="?android:attr/colorControlActivated"/>
+</gradient>
\ No newline at end of file
diff --git a/tests/VectorDrawableTest/res/color/fill_gradient_sweep_clamp.xml b/tests/VectorDrawableTest/res/color/fill_gradient_sweep_clamp.xml
new file mode 100644
index 0000000..80f39f3e
--- /dev/null
+++ b/tests/VectorDrawableTest/res/color/fill_gradient_sweep_clamp.xml
@@ -0,0 +1,28 @@
+<?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.
+ */
+-->
+<gradient xmlns:android="http://schemas.android.com/apk/res/android"
+          android:centerColor="#ff0000"
+          android:endColor="#ff0000ff"
+          android:centerX="500"
+          android:centerY="500"
+          android:gradientRadius="10"
+          android:startColor="#ffffffff"
+          android:type="sweep"
+          android:tileMode="clamp">
+</gradient>
diff --git a/tests/VectorDrawableTest/res/color/fill_gradient_sweep_item_long_mirror.xml b/tests/VectorDrawableTest/res/color/fill_gradient_sweep_item_long_mirror.xml
new file mode 100644
index 0000000..0890bd6
--- /dev/null
+++ b/tests/VectorDrawableTest/res/color/fill_gradient_sweep_item_long_mirror.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.
+ */
+-->
+<gradient xmlns:android="http://schemas.android.com/apk/res/android"
+          android:centerX="500"
+          android:centerY="500"
+          android:gradientRadius="10"
+          android:type="sweep"
+          android:tileMode="mirror">
+    <item android:offset="-0.3" android:color="#f00"/>
+    <item android:offset="0.1" android:color="?android:attr/colorPrimary"/>
+    <item android:offset="0.4" android:color="#0f0"/>
+    <item android:offset="0.6" android:color="#00f"/>
+    <item android:offset="0.7" android:color="?android:attr/colorControlActivated"/>
+    <item android:offset="1.5" android:color="#00f"/>
+</gradient>
diff --git a/tests/VectorDrawableTest/res/color/fill_gradient_sweep_item_repeat.xml b/tests/VectorDrawableTest/res/color/fill_gradient_sweep_item_repeat.xml
new file mode 100644
index 0000000..2ec5014
--- /dev/null
+++ b/tests/VectorDrawableTest/res/color/fill_gradient_sweep_item_repeat.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.
+ */
+-->
+<gradient xmlns:android="http://schemas.android.com/apk/res/android"
+          android:centerColor="#ff0000"
+          android:endColor="#ff0000ff"
+          android:centerX="500"
+          android:centerY="500"
+          android:gradientRadius="10"
+          android:startColor="#ffffffff"
+          android:type="sweep"
+          android:tileMode="repeat">
+    <item android:offset="0.1" android:color="?android:attr/colorPrimary"/>
+    <item android:offset="0.4" android:color="#fff"/>
+    <item android:offset="0.9" android:color="?android:attr/colorControlActivated"/>
+</gradient>
diff --git a/tests/VectorDrawableTest/res/color/stroke_gradient_clamp.xml b/tests/VectorDrawableTest/res/color/stroke_gradient_clamp.xml
new file mode 100644
index 0000000..3d746e7
--- /dev/null
+++ b/tests/VectorDrawableTest/res/color/stroke_gradient_clamp.xml
@@ -0,0 +1,30 @@
+<?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.
+ */
+-->
+<gradient xmlns:android="http://schemas.android.com/apk/res/android"
+          android:angle="90"
+          android:centerColor="#7f7f7f"
+          android:endColor="#ffffff"
+          android:startColor="#000000"
+          android:startX="0"
+          android:endX="50"
+          android:startY="0"
+          android:endY="0"
+          android:type="linear"
+          android:tileMode="clamp">
+</gradient>
\ No newline at end of file
diff --git a/tests/VectorDrawableTest/res/color/stroke_gradient_item_alpha_mirror.xml b/tests/VectorDrawableTest/res/color/stroke_gradient_item_alpha_mirror.xml
new file mode 100644
index 0000000..352a2fd
--- /dev/null
+++ b/tests/VectorDrawableTest/res/color/stroke_gradient_item_alpha_mirror.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.
+ */
+-->
+<gradient xmlns:android="http://schemas.android.com/apk/res/android"
+          android:startX="0"
+          android:endX="50"
+          android:startY="0"
+          android:endY="0"
+          android:type="linear"
+          android:tileMode="mirror">
+    <item android:offset="0.1" android:color="#f00"/>
+    <item android:offset="0.2" android:color="#2f0f"/>
+    <item android:offset="0.9" android:color="#f00f"/>
+</gradient>
\ No newline at end of file
diff --git a/tests/VectorDrawableTest/res/color/stroke_gradient_item_repeat.xml b/tests/VectorDrawableTest/res/color/stroke_gradient_item_repeat.xml
new file mode 100644
index 0000000..42281d1
--- /dev/null
+++ b/tests/VectorDrawableTest/res/color/stroke_gradient_item_repeat.xml
@@ -0,0 +1,33 @@
+<?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.
+ */
+-->
+<gradient xmlns:android="http://schemas.android.com/apk/res/android"
+          android:angle="90"
+          android:centerColor="#7f7f7f"
+          android:endColor="#ffffff"
+          android:startColor="#000000"
+          android:startX="0"
+          android:endX="50"
+          android:startY="0"
+          android:endY="0"
+          android:type="linear"
+          android:tileMode="repeat">
+    <item android:offset="0.1" android:color="#f00"/>
+    <item android:offset="0.2" android:color="#f0f"/>
+    <item android:offset="0.9" android:color="#f00f"/>
+</gradient>
\ No newline at end of file
diff --git a/tests/VectorDrawableTest/res/drawable/vector_icon_gradient_1_clamp.xml b/tests/VectorDrawableTest/res/drawable/vector_icon_gradient_1_clamp.xml
new file mode 100644
index 0000000..2fa440a
--- /dev/null
+++ b/tests/VectorDrawableTest/res/drawable/vector_icon_gradient_1_clamp.xml
@@ -0,0 +1,91 @@
+<?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:height="64dp"
+        android:width="64dp"
+        android:viewportHeight="400"
+        android:viewportWidth="400" >
+
+<group android:name="backgroundGroup"
+       android:scaleX="0.5"
+       android:scaleY="0.5">
+    <path
+            android:name="background1"
+            android:fillColor="@color/fill_gradient_linear_clamp"
+            android:pathData="M 0,0 l 200,0 l 0, 200 l -200, 0 z" />
+    <path
+            android:name="background2"
+            android:fillColor="@color/fill_gradient_radial_clamp"
+            android:pathData="M 200,200 l 200,0 l 0, 200 l -200, 0 z" />
+    <path
+            android:name="background3"
+            android:fillColor="@color/fill_gradient_sweep_clamp"
+            android:pathData="M 400,400 l 200,0 l 0, 200 l -200, 0 z" />
+</group>
+<group
+        android:name="translateToCenterGroup"
+        android:translateX="50.0"
+        android:translateY="90.0" >
+    <path
+            android:name="twoLines"
+            android:pathData="@string/twoLinePathData"
+            android:strokeColor="@color/stroke_gradient_clamp"
+            android:strokeWidth="20" />
+
+    <group
+            android:name="rotationGroup"
+            android:pivotX="0.0"
+            android:pivotY="0.0"
+            android:rotation="-45.0">
+        <path
+                android:name="twoLines1"
+                android:pathData="@string/twoLinePathData"
+                android:strokeColor="@color/stroke_gradient_clamp"
+                android:strokeWidth="20" />
+
+        <group
+                android:name="translateGroup"
+                android:translateX="130.0"
+                android:translateY="160.0">
+            <group android:name="scaleGroup" >
+                <path
+                        android:name="twoLines3"
+                        android:pathData="@string/twoLinePathData"
+                        android:strokeColor="@color/stroke_gradient_clamp"
+                        android:strokeWidth="20" />
+            </group>
+        </group>
+
+        <group
+                android:name="translateGroupHalf"
+                android:translateX="65.0"
+                android:translateY="80.0">
+            <group android:name="scaleGroup" >
+                <path
+                        android:name="twoLines2"
+                        android:pathData="@string/twoLinePathData"
+                        android:fillColor="@color/fill_gradient_linear_clamp"
+                        android:strokeColor="@color/stroke_gradient_clamp"
+                        android:strokeWidth="20" />
+            </group>
+        </group>
+    </group>
+</group>
+
+</vector>
\ No newline at end of file
diff --git a/tests/VectorDrawableTest/res/drawable/vector_icon_gradient_2_repeat.xml b/tests/VectorDrawableTest/res/drawable/vector_icon_gradient_2_repeat.xml
new file mode 100644
index 0000000..5a43f80
--- /dev/null
+++ b/tests/VectorDrawableTest/res/drawable/vector_icon_gradient_2_repeat.xml
@@ -0,0 +1,90 @@
+<?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:height="64dp"
+        android:width="64dp"
+        android:viewportHeight="400"
+        android:viewportWidth="400" >
+
+<group android:name="backgroundGroup"
+       android:scaleX="0.5"
+       android:scaleY="0.5">
+    <path
+            android:name="background1"
+            android:fillColor="@color/fill_gradient_linear_item_repeat"
+            android:pathData="M 0,0 l 200,0 l 0, 200 l -200, 0 z" />
+    <path
+            android:name="background2"
+            android:fillColor="@color/fill_gradient_radial_item_repeat"
+            android:pathData="M 200,200 l 200,0 l 0, 200 l -200, 0 z" />
+    <path
+            android:name="background3"
+            android:fillColor="@color/fill_gradient_sweep_item_repeat"
+            android:pathData="M 400,400 l 200,0 l 0, 200 l -200, 0 z" />
+</group>
+<group
+        android:name="translateToCenterGroup"
+        android:translateX="50.0"
+        android:translateY="90.0" >
+    <path
+            android:name="twoLines"
+            android:pathData="@string/twoLinePathData"
+            android:strokeColor="@color/stroke_gradient_item_repeat"
+            android:strokeWidth="20" />
+
+    <group
+            android:name="rotationGroup"
+            android:pivotX="0.0"
+            android:pivotY="0.0"
+            android:rotation="-45.0">
+        <path
+                android:name="twoLines1"
+                android:pathData="@string/twoLinePathData"
+                android:strokeColor="@color/stroke_gradient_item_repeat"
+                android:strokeWidth="20" />
+
+        <group
+                android:name="translateGroup"
+                android:translateX="130.0"
+                android:translateY="160.0">
+            <group android:name="scaleGroup" >
+                <path
+                        android:name="twoLines3"
+                        android:pathData="@string/twoLinePathData"
+                        android:strokeColor="@color/stroke_gradient_item_repeat"
+                        android:strokeWidth="20" />
+            </group>
+        </group>
+
+        <group
+                android:name="translateGroupHalf"
+                android:translateX="65.0"
+                android:translateY="80.0">
+            <group android:name="scaleGroup" >
+                <path
+                        android:name="twoLines2"
+                        android:pathData="@string/twoLinePathData"
+                        android:strokeColor="@color/stroke_gradient_item_repeat"
+                        android:strokeWidth="20" />
+            </group>
+        </group>
+    </group>
+</group>
+
+</vector>
\ No newline at end of file
diff --git a/tests/VectorDrawableTest/res/drawable/vector_icon_gradient_3_mirror.xml b/tests/VectorDrawableTest/res/drawable/vector_icon_gradient_3_mirror.xml
new file mode 100644
index 0000000..e8de7c2
--- /dev/null
+++ b/tests/VectorDrawableTest/res/drawable/vector_icon_gradient_3_mirror.xml
@@ -0,0 +1,90 @@
+<?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:height="64dp"
+        android:width="64dp"
+        android:viewportHeight="400"
+        android:viewportWidth="400" >
+
+<group android:name="backgroundGroup"
+       android:scaleX="0.5"
+       android:scaleY="0.5">
+    <path
+            android:name="background1"
+            android:fillColor="@color/fill_gradient_linear_item_overlap_mirror"
+            android:pathData="M 0,0 l 200,0 l 0, 200 l -200, 0 z" />
+    <path
+            android:name="background2"
+            android:fillColor="@color/fill_gradient_radial_item_short_mirror"
+            android:pathData="M 200,200 l 200,0 l 0, 200 l -200, 0 z" />
+    <path
+            android:name="background3"
+            android:fillColor="@color/fill_gradient_sweep_item_long_mirror"
+            android:pathData="M 400,400 l 200,0 l 0, 200 l -200, 0 z" />
+</group>
+<group
+        android:name="translateToCenterGroup"
+        android:translateX="50.0"
+        android:translateY="90.0" >
+    <path
+            android:name="twoLines"
+            android:pathData="@string/twoLinePathData"
+            android:strokeColor="@color/stroke_gradient_item_alpha_mirror"
+            android:strokeWidth="20" />
+
+    <group
+            android:name="rotationGroup"
+            android:pivotX="0.0"
+            android:pivotY="0.0"
+            android:rotation="-45.0">
+        <path
+                android:name="twoLines1"
+                android:pathData="@string/twoLinePathData"
+                android:strokeColor="@color/stroke_gradient_item_alpha_mirror"
+                android:strokeWidth="20" />
+
+        <group
+                android:name="translateGroup"
+                android:translateX="130.0"
+                android:translateY="160.0">
+            <group android:name="scaleGroup" >
+                <path
+                        android:name="twoLines3"
+                        android:pathData="@string/twoLinePathData"
+                        android:strokeColor="@color/stroke_gradient_item_alpha_mirror"
+                        android:strokeWidth="20" />
+            </group>
+        </group>
+
+        <group
+                android:name="translateGroupHalf"
+                android:translateX="65.0"
+                android:translateY="80.0">
+            <group android:name="scaleGroup" >
+                <path
+                        android:name="twoLines2"
+                        android:pathData="@string/twoLinePathData"
+                        android:strokeColor="@color/stroke_gradient_item_alpha"
+                        android:strokeWidth="20" />
+            </group>
+        </group>
+    </group>
+</group>
+
+</vector>
\ No newline at end of file
diff --git a/tests/VectorDrawableTest/src/com/android/test/dynamic/VectorDrawablePerformance.java b/tests/VectorDrawableTest/src/com/android/test/dynamic/VectorDrawablePerformance.java
index 7172147..495d620 100644
--- a/tests/VectorDrawableTest/src/com/android/test/dynamic/VectorDrawablePerformance.java
+++ b/tests/VectorDrawableTest/src/com/android/test/dynamic/VectorDrawablePerformance.java
@@ -38,6 +38,9 @@
             R.drawable.vector_icon_gradient_1,
             R.drawable.vector_icon_gradient_2,
             R.drawable.vector_icon_gradient_3,
+            R.drawable.vector_icon_gradient_1_clamp,
+            R.drawable.vector_icon_gradient_2_repeat,
+            R.drawable.vector_icon_gradient_3_mirror,
             R.drawable.vector_icon_state_list_simple,
             R.drawable.vector_icon_state_list_theme,
             R.drawable.vector_drawable01,
diff --git a/tests/VoiceEnrollment/src/com/android/test/voiceenrollment/TestEnrollmentActivity.java b/tests/VoiceEnrollment/src/com/android/test/voiceenrollment/TestEnrollmentActivity.java
index 2494db7..54c944f9 100644
--- a/tests/VoiceEnrollment/src/com/android/test/voiceenrollment/TestEnrollmentActivity.java
+++ b/tests/VoiceEnrollment/src/com/android/test/voiceenrollment/TestEnrollmentActivity.java
@@ -31,7 +31,7 @@
 
 public class TestEnrollmentActivity extends Activity {
     private static final String TAG = "TestEnrollmentActivity";
-    private static final boolean DBG = true;
+    private static final boolean DBG = false;
 
     /** Keyphrase related constants, must match those defined in enrollment_application.xml */
     private static final int KEYPHRASE_ID = 101;
diff --git a/tests/permission/src/com/android/framework/permission/tests/ActivityManagerPermissionTests.java b/tests/permission/src/com/android/framework/permission/tests/ActivityManagerPermissionTests.java
index 3791d02..d7f4a38 100644
--- a/tests/permission/src/com/android/framework/permission/tests/ActivityManagerPermissionTests.java
+++ b/tests/permission/src/com/android/framework/permission/tests/ActivityManagerPermissionTests.java
@@ -140,7 +140,7 @@
     @SmallTest
     public void testSET_ACTIVITY_WATCHER() {
         try {
-            mAm.setActivityController(null);
+            mAm.setActivityController(null, false);
             fail("IActivityManager.setActivityController did not throw SecurityException as"
                     + " expected");
         } catch (SecurityException e) {
diff --git a/tools/aapt/AaptAssets.cpp b/tools/aapt/AaptAssets.cpp
index 3b01827..cbd8480 100644
--- a/tools/aapt/AaptAssets.cpp
+++ b/tools/aapt/AaptAssets.cpp
@@ -373,7 +373,7 @@
 void AaptLocaleValue::initFromResTable(const ResTable_config& config) {
     config.unpackLanguage(language);
     config.unpackRegion(region);
-    if (config.localeScriptWasProvided) {
+    if (config.localeScript[0] && !config.localeScriptWasComputed) {
         memcpy(script, config.localeScript, sizeof(config.localeScript));
     }
 
@@ -388,10 +388,10 @@
 
     if (script[0]) {
         memcpy(out->localeScript, script, sizeof(out->localeScript));
-        out->localeScriptWasProvided = true;
+        out->localeScriptWasComputed = false;
     } else {
         out->computeScript();
-        out->localeScriptWasProvided = false;
+        out->localeScriptWasComputed = true;
     }
 
     if (variant[0]) {
diff --git a/tools/aapt/ResourceTable.cpp b/tools/aapt/ResourceTable.cpp
index e87c7d40..6a4b637 100644
--- a/tools/aapt/ResourceTable.cpp
+++ b/tools/aapt/ResourceTable.cpp
@@ -308,29 +308,11 @@
         }
         added = true;
 
-        String16 attr16("attr");
-        
-        if (outTable->hasBagOrEntry(myPackage, attr16, ident)) {
-            sourcePos.error("Attribute \"%s\" has already been defined\n",
-                    String8(ident).string());
+        if (!outTable->makeAttribute(myPackage, ident, sourcePos, type, comment, appendComment)) {
             hasErrors = true;
             return UNKNOWN_ERROR;
         }
-        
-        char numberStr[16];
-        sprintf(numberStr, "%d", type);
-        status_t err = outTable->addBag(sourcePos, myPackage,
-                attr16, ident, String16(""),
-                String16("^type"),
-                String16(numberStr), NULL, NULL);
-        if (err != NO_ERROR) {
-            hasErrors = true;
-            return err;
-        }
-        outTable->appendComment(myPackage, attr16, ident, comment, appendComment);
-        //printf("Attribute %s comment: %s\n", String8(ident).string(),
-        //     String8(comment).string());
-        return err;
+        return NO_ERROR;
     }
 };
 
@@ -2115,6 +2097,61 @@
     return false;
 }
 
+bool ResourceTable::makeAttribute(const String16& package,
+                                  const String16& name,
+                                  const SourcePos& source,
+                                  int32_t format,
+                                  const String16& comment,
+                                  bool shouldAppendComment) {
+    const String16 attr16("attr");
+
+    // First look for this in the included resources...
+    uint32_t rid = mAssets->getIncludedResources()
+            .identifierForName(name.string(), name.size(),
+                               attr16.string(), attr16.size(),
+                               package.string(), package.size());
+    if (rid != 0) {
+        source.error("Attribute \"%s\" has already been defined", String8(name).string());
+        return false;
+    }
+
+    sp<ResourceTable::Entry> entry = getEntry(package, attr16, name, source, false);
+    if (entry == NULL) {
+        source.error("Failed to create entry attr/%s", String8(name).string());
+        return false;
+    }
+
+    if (entry->makeItABag(source) != NO_ERROR) {
+        return false;
+    }
+
+    const String16 formatKey16("^type");
+    const String16 formatValue16(String8::format("%d", format));
+
+    ssize_t idx = entry->getBag().indexOfKey(formatKey16);
+    if (idx >= 0) {
+        // We have already set a format for this attribute, check if they are different.
+        // We allow duplicate attribute definitions so long as they are identical.
+        // This is to ensure inter-operation with libraries that define the same generic attribute.
+        const Item& formatItem = entry->getBag().valueAt(idx);
+        if ((format & (ResTable_map::TYPE_ENUM | ResTable_map::TYPE_FLAGS)) ||
+                formatItem.value != formatValue16) {
+            source.error("Attribute \"%s\" already defined with incompatible format.\n"
+                         "%s:%d: Original attribute defined here.",
+                         String8(name).string(), formatItem.sourcePos.file.string(),
+                         formatItem.sourcePos.line);
+            return false;
+        }
+    } else {
+        entry->addToBag(source, formatKey16, formatValue16);
+        // Increment the number of resources we have. This is used to determine if we should
+        // even generate a resource table.
+        mNumLocal++;
+    }
+    appendComment(package, attr16, name, comment, shouldAppendComment);
+    return true;
+}
+
 void ResourceTable::canAddEntry(const SourcePos& pos,
         const String16& package, const String16& type, const String16& name)
 {
diff --git a/tools/aapt/ResourceTable.h b/tools/aapt/ResourceTable.h
index 4b7b3cd..cf1e992 100644
--- a/tools/aapt/ResourceTable.h
+++ b/tools/aapt/ResourceTable.h
@@ -571,6 +571,18 @@
 
     void getDensityVaryingResources(KeyedVector<Symbol, Vector<SymbolDefinition> >& resources);
 
+    /**
+     * Make an attribute with the specified format. If another attribute with the same name but
+     * different format exists, this method returns false. If the name is not taken, or if the
+     * format is identical, this returns true.
+     */
+    bool makeAttribute(const String16& package,
+                       const String16& name,
+                       const SourcePos& source,
+                       int32_t format,
+                       const String16& comment,
+                       bool appendComment);
+
 private:
     void writePublicDefinitions(const String16& package, FILE* fp, bool pub);
     sp<Package> getPackage(const String16& package);
diff --git a/tools/aapt2/Android.mk b/tools/aapt2/Android.mk
index f9d35ab..d311b3d 100644
--- a/tools/aapt2/Android.mk
+++ b/tools/aapt2/Android.mk
@@ -13,15 +13,12 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 #
-
-# This tool is prebuilt if we're doing an app-only build.
-ifeq ($(TARGET_BUILD_APPS)$(filter true,$(TARGET_BUILD_PDK)),)
+LOCAL_PATH:= $(call my-dir)
 
 # ==========================================================
 # Setup some common variables for the different build
 # targets here.
 # ==========================================================
-LOCAL_PATH:= $(call my-dir)
 
 main := Main.cpp
 sources := \
@@ -93,6 +90,7 @@
 	proto/TableProtoSerializer_test.cpp \
 	split/TableSplitter_test.cpp \
 	util/BigBuffer_test.cpp \
+	util/Files_test.cpp \
 	util/Maybe_test.cpp \
 	util/StringPiece_test.cpp \
 	util/Util_test.cpp \
@@ -192,4 +190,6 @@
 
 include $(BUILD_HOST_EXECUTABLE)
 
-endif # No TARGET_BUILD_APPS or TARGET_BUILD_PDK
+ifeq ($(ONE_SHOT_MAKEFILE),)
+include $(call all-makefiles-under,$(LOCAL_PATH))
+endif
diff --git a/tools/aapt2/Locale.cpp b/tools/aapt2/Locale.cpp
index 6acf3b0..12f56fc 100644
--- a/tools/aapt2/Locale.cpp
+++ b/tools/aapt2/Locale.cpp
@@ -253,7 +253,7 @@
 void LocaleValue::initFromResTable(const ResTable_config& config) {
     config.unpackLanguage(language);
     config.unpackRegion(region);
-    if (config.localeScriptWasProvided) {
+    if (config.localeScript[0] && !config.localeScriptWasComputed) {
         memcpy(script, config.localeScript, sizeof(config.localeScript));
     }
 
@@ -268,10 +268,10 @@
 
     if (script[0]) {
         memcpy(out->localeScript, script, sizeof(out->localeScript));
-        out->localeScriptWasProvided = true;
+        out->localeScriptWasComputed = false;
     } else {
         out->computeScript();
-        out->localeScriptWasProvided = false;
+        out->localeScriptWasComputed = true;
     }
 
     if (variant[0]) {
diff --git a/tools/aapt2/Resource.h b/tools/aapt2/Resource.h
index c71e249..03ca42b 100644
--- a/tools/aapt2/Resource.h
+++ b/tools/aapt2/Resource.h
@@ -77,13 +77,10 @@
     ResourceType type;
     std::u16string entry;
 
-    ResourceName() = default;
+    ResourceName() : type(ResourceType::kRaw) {}
     ResourceName(const StringPiece16& p, ResourceType t, const StringPiece16& e);
 
     bool isValid() const;
-    bool operator<(const ResourceName& rhs) const;
-    bool operator==(const ResourceName& rhs) const;
-    bool operator!=(const ResourceName& rhs) const;
     std::u16string toString() const;
 };
 
@@ -109,10 +106,6 @@
 
     ResourceName toResourceName() const;
     bool isValid() const;
-
-    bool operator<(const ResourceNameRef& rhs) const;
-    bool operator==(const ResourceNameRef& rhs) const;
-    bool operator!=(const ResourceNameRef& rhs) const;
 };
 
 /**
@@ -138,17 +131,11 @@
     uint8_t packageId() const;
     uint8_t typeId() const;
     uint16_t entryId() const;
-    bool operator<(const ResourceId& rhs) const;
-    bool operator==(const ResourceId& rhs) const;
 };
 
 struct SourcedResourceName {
     ResourceName name;
     size_t line;
-
-    inline bool operator==(const SourcedResourceName& rhs) const {
-        return name == rhs.name && line == rhs.line;
-    }
 };
 
 struct ResourceFile {
@@ -227,16 +214,23 @@
     return static_cast<uint16_t>(id);
 }
 
-inline bool ResourceId::operator<(const ResourceId& rhs) const {
-    return id < rhs.id;
+inline bool operator<(const ResourceId& lhs, const ResourceId& rhs) {
+    return lhs.id < rhs.id;
 }
 
-inline bool ResourceId::operator==(const ResourceId& rhs) const {
-    return id == rhs.id;
+inline bool operator>(const ResourceId& lhs, const ResourceId& rhs) {
+    return lhs.id > rhs.id;
 }
 
-inline ::std::ostream& operator<<(::std::ostream& out,
-        const ResourceId& resId) {
+inline bool operator==(const ResourceId& lhs, const ResourceId& rhs) {
+    return lhs.id == rhs.id;
+}
+
+inline bool operator!=(const ResourceId& lhs, const ResourceId& rhs) {
+    return lhs.id != rhs.id;
+}
+
+inline ::std::ostream& operator<<(::std::ostream& out, const ResourceId& resId) {
     std::ios_base::fmtflags oldFlags = out.flags();
     char oldFill = out.fill();
     out << "0x" << std::internal << std::setfill('0') << std::setw(8)
@@ -266,29 +260,21 @@
     return !package.empty() && !entry.empty();
 }
 
-inline bool ResourceName::operator<(const ResourceName& rhs) const {
-    return std::tie(package, type, entry)
+inline bool operator<(const ResourceName& lhs, const ResourceName& rhs) {
+    return std::tie(lhs.package, lhs.type, lhs.entry)
             < std::tie(rhs.package, rhs.type, rhs.entry);
 }
 
-inline bool operator<(const ResourceName& lhs, const ResourceNameRef& b) {
-    return ResourceNameRef(lhs) < b;
-}
-
-inline bool ResourceName::operator==(const ResourceName& rhs) const {
-    return std::tie(package, type, entry)
+inline bool operator==(const ResourceName& lhs, const ResourceName& rhs) {
+    return std::tie(lhs.package, lhs.type, lhs.entry)
             == std::tie(rhs.package, rhs.type, rhs.entry);
 }
 
-inline bool ResourceName::operator!=(const ResourceName& rhs) const {
-    return std::tie(package, type, entry)
+inline bool operator!=(const ResourceName& lhs, const ResourceName& rhs) {
+    return std::tie(lhs.package, lhs.type, lhs.entry)
             != std::tie(rhs.package, rhs.type, rhs.entry);
 }
 
-inline bool operator!=(const ResourceName& lhs, const ResourceNameRef& rhs) {
-    return ResourceNameRef(lhs) != rhs;
-}
-
 inline std::u16string ResourceName::toString() const {
     std::u16string result;
     if (!package.empty()) {
@@ -333,18 +319,18 @@
     return !package.empty() && !entry.empty();
 }
 
-inline bool ResourceNameRef::operator<(const ResourceNameRef& rhs) const {
-    return std::tie(package, type, entry)
+inline bool operator<(const ResourceNameRef& lhs, const ResourceNameRef& rhs) {
+    return std::tie(lhs.package, lhs.type, lhs.entry)
             < std::tie(rhs.package, rhs.type, rhs.entry);
 }
 
-inline bool ResourceNameRef::operator==(const ResourceNameRef& rhs) const {
-    return std::tie(package, type, entry)
+inline bool operator==(const ResourceNameRef& lhs, const ResourceNameRef& rhs) {
+    return std::tie(lhs.package, lhs.type, lhs.entry)
             == std::tie(rhs.package, rhs.type, rhs.entry);
 }
 
-inline bool ResourceNameRef::operator!=(const ResourceNameRef& rhs) const {
-    return std::tie(package, type, entry)
+inline bool operator!=(const ResourceNameRef& lhs, const ResourceNameRef& rhs) {
+    return std::tie(lhs.package, lhs.type, lhs.entry)
             != std::tie(rhs.package, rhs.type, rhs.entry);
 }
 
@@ -355,6 +341,18 @@
     return out << name.type << "/" << name.entry;
 }
 
+inline bool operator<(const ResourceName& lhs, const ResourceNameRef& b) {
+    return ResourceNameRef(lhs) < b;
+}
+
+inline bool operator!=(const ResourceName& lhs, const ResourceNameRef& rhs) {
+    return ResourceNameRef(lhs) != rhs;
+}
+
+inline bool operator==(const SourcedResourceName& lhs, const SourcedResourceName& rhs) {
+    return lhs.name == rhs.name && lhs.line == rhs.line;
+}
+
 } // namespace aapt
 
 #endif // AAPT_RESOURCE_H
diff --git a/tools/aapt2/ResourceParser.cpp b/tools/aapt2/ResourceParser.cpp
index b100e84..9704d970 100644
--- a/tools/aapt2/ResourceParser.cpp
+++ b/tools/aapt2/ResourceParser.cpp
@@ -81,6 +81,12 @@
 
 // Recursively adds resources to the ResourceTable.
 static bool addResourcesToTable(ResourceTable* table, IDiagnostics* diag, ParsedResource* res) {
+    StringPiece16 trimmedComment = util::trimWhitespace(res->comment);
+    if (trimmedComment.size() != res->comment.size()) {
+        // Only if there was a change do we re-assign.
+        res->comment = trimmedComment.toString();
+    }
+
     if (res->symbolState) {
         Symbol symbol;
         symbol.state = res->symbolState.value();
diff --git a/tools/aapt2/compile/Compile.cpp b/tools/aapt2/compile/Compile.cpp
index 5f9719e..2452a1d 100644
--- a/tools/aapt2/compile/Compile.cpp
+++ b/tools/aapt2/compile/Compile.cpp
@@ -422,10 +422,6 @@
 }
 
 class CompileContext : public IAaptContext {
-private:
-    StdErrDiagnostics mDiagnostics;
-    bool mVerbose = false;
-
 public:
     void setVerbose(bool val) {
         mVerbose = val;
@@ -444,18 +440,24 @@
        return nullptr;
     }
 
-    StringPiece16 getCompilationPackage() override {
-       return {};
+    const std::u16string& getCompilationPackage() override {
+        static std::u16string empty;
+        return empty;
     }
 
     uint8_t getPackageId() override {
        return 0x0;
     }
 
-    ISymbolTable* getExternalSymbols() override {
+    SymbolTable* getExternalSymbols() override {
        abort();
        return nullptr;
     }
+
+private:
+    StdErrDiagnostics mDiagnostics;
+    bool mVerbose = false;
+
 };
 
 /**
diff --git a/tools/aapt2/compile/Png.cpp b/tools/aapt2/compile/Png.cpp
index 9837c4e..bbf7f41 100644
--- a/tools/aapt2/compile/Png.cpp
+++ b/tools/aapt2/compile/Png.cpp
@@ -1175,7 +1175,7 @@
     if (errorMsg) {
         std::stringstream err;
         err << "9-patch malformed: " << errorMsg;
-        if (!errorEdge) {
+        if (errorEdge) {
             err << "." << std::endl;
             if (errorPixel >= 0) {
                 err << "Found at pixel #" << errorPixel << " along " << errorEdge << " edge";
diff --git a/tools/aapt2/data/AndroidManifest.xml b/tools/aapt2/data/AndroidManifest.xml
deleted file mode 100644
index d3b2fbe..0000000
--- a/tools/aapt2/data/AndroidManifest.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
-    package="com.android.app">
-    <application
-        android:name=".ActivityMain">
-    </application>
-</manifest>
diff --git a/tools/aapt2/data/Makefile b/tools/aapt2/data/Makefile
deleted file mode 100644
index 37012de..0000000
--- a/tools/aapt2/data/Makefile
+++ /dev/null
@@ -1,61 +0,0 @@
-##
-# Environment dependent variables
-##
-
-AAPT := aapt2
-ZIPALIGN := zipalign -f 4
-FRAMEWORK := ../../../../../out/target/common/obj/APPS/framework-res_intermediates/package-export.apk
-
-##
-# Project depenedent variables
-##
-
-LOCAL_PACKAGE := com.android.app
-LOCAL_RESOURCE_DIR := res
-LOCAL_LIBS := lib/out/package.apk
-LOCAL_OUT := out
-LOCAL_GEN := out/gen
-LOCAL_PROGUARD := out/proguard.rule
-
-##
-# AAPT2 custom rules.
-##
-
-PRIVATE_R_FILE := $(LOCAL_GEN)/$(subst .,/,$(LOCAL_PACKAGE))/R.java
-$(info PRIVATE_R_FILE = $(PRIVATE_R_FILE))
-
-# Eg: framework.apk, etc.
-PRIVATE_INCLUDES := $(FRAMEWORK)
-$(info PRIVATE_INCLUDES = $(PRIVATE_INCLUDES))
-
-# Eg: res/drawable/icon.png, res/values/styles.xml
-PRIVATE_RESOURCES := $(shell find $(LOCAL_RESOURCE_DIR) -mindepth 1 -maxdepth 2 -type f)
-$(info PRIVATE_RESOURCES = $(PRIVATE_RESOURCES))
-
-PRIVATE_RESOURCE_OBJECTS := $(subst /,_,$(patsubst $(LOCAL_RESOURCE_DIR)/%,%,$(filter $(LOCAL_RESOURCE_DIR)/values%,$(PRIVATE_RESOURCES))))
-PRIVATE_RESOURCE_OBJECTS := $(addprefix $(LOCAL_OUT)/,$(PRIVATE_RESOURCE_OBJECTS:.xml=.arsc.flat))
-$(info PRIVATE_RESOURCE_OBJECTS = $(PRIVATE_RESOURCE_OBJECTS))
-
-PRIVATE_FILE_OBJECTS := $(subst /,_,$(patsubst $(LOCAL_RESOURCE_DIR)/%,%,$(filter-out $(LOCAL_RESOURCE_DIR)/values%,$(PRIVATE_RESOURCES))))
-PRIVATE_FILE_OBJECTS := $(addprefix $(LOCAL_OUT)/,$(addsuffix .flat,$(PRIVATE_FILE_OBJECTS)))
-$(info PRIVATE_FILE_OBJECTS = $(PRIVATE_FILE_OBJECTS))
-
-.SECONDEXPANSION:
-
-$(LOCAL_OUT)/%.arsc.flat: $(LOCAL_RESOURCE_DIR)/$$(subst _,/,%).xml
-	$(AAPT) compile -o $(LOCAL_OUT) $<
-
-$(LOCAL_OUT)/%.flat: $(LOCAL_RESOURCE_DIR)/$$(subst _,/,%)
-	$(AAPT) compile -o $(LOCAL_OUT) $<
-
-$(LOCAL_PROGUARD) $(LOCAL_OUT)/package.apk: AndroidManifest.xml
-$(PRIVATE_R_FILE) $(LOCAL_PROGUARD) $(LOCAL_OUT)/package.apk: $(PRIVATE_FILE_OBJECTS) $(PRIVATE_RESOURCE_OBJECTS)
-	$(AAPT) link -o $(LOCAL_OUT)/package.apk --manifest AndroidManifest.xml --java $(LOCAL_GEN) --proguard $(LOCAL_PROGUARD) -I $(PRIVATE_INCLUDES) $(filter-out AndroidManifest.xml,$^) -v
-
-# Create the out directory if needed.
-dummy := $(shell test -d $(LOCAL_OUT) || mkdir -p $(LOCAL_OUT))
-
-.PHONY: all
-all: $(LOCAL_OUT)/package.apk $(LOCAL_PROGUARD) $(PRIVATE_R_FILE)
-
-.DEFAULT_GOAL := all
diff --git a/tools/aapt2/data/lib/AndroidManifest.xml b/tools/aapt2/data/lib/AndroidManifest.xml
deleted file mode 100644
index 08b468e..0000000
--- a/tools/aapt2/data/lib/AndroidManifest.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
-    package="android.appcompat">
-
-    <uses-feature android:name="bloooop" />
-</manifest>
diff --git a/tools/aapt2/data/lib/Makefile b/tools/aapt2/data/lib/Makefile
deleted file mode 100644
index 741be9a..0000000
--- a/tools/aapt2/data/lib/Makefile
+++ /dev/null
@@ -1,81 +0,0 @@
-##
-# Environment dependent variables
-##
-
-AAPT := aapt2
-ZIPALIGN := zipalign -f 4
-FRAMEWORK := ../../../../../../out/target/common/obj/APPS/framework-res_intermediates/package-export.apk
-
-##
-# Project depenedent variables
-##
-
-LOCAL_PACKAGE := android.appcompat
-LOCAL_RESOURCE_DIR := res
-LOCAL_OUT := out
-LOCAL_GEN := out/gen
-
-##
-# AAPT2 custom rules.
-##
-
-PRIVATE_APK_UNALIGNED := $(LOCAL_OUT)/package-unaligned.apk
-PRIVATE_APK_ALIGNED := $(LOCAL_OUT)/package.apk
-
-# Eg: framework.apk, etc.
-PRIVATE_LIBS := $(FRAMEWORK)
-$(info PRIVATE_LIBS = $(PRIVATE_LIBS))
-
-# Eg: gen/com/android/app/R.java
-PRIVATE_R_JAVA := $(LOCAL_GEN)/$(subst .,/,$(LOCAL_PACKAGE))/R.java
-$(info PRIVATE_R_JAVA = $(PRIVATE_R_JAVA))
-
-# Eg: res/drawable/icon.png, res/values/styles.xml
-PRIVATE_RESOURCES := $(shell find $(LOCAL_RESOURCE_DIR) -mindepth 1 -maxdepth 2 -type f)
-$(info PRIVATE_RESOURCES = $(PRIVATE_RESOURCES))
-
-# Eg: drawable, values, layouts
-PRIVATE_RESOURCE_TYPES := \
-	$(patsubst $(LOCAL_RESOURCE_DIR)/%/,%,$(sort $(dir $(PRIVATE_RESOURCES))))
-$(info PRIVATE_RESOURCE_TYPES = $(PRIVATE_RESOURCE_TYPES))
-
-# Eg: out/values-v4.apk, out/drawable-xhdpi.apk
-PRIVATE_INTERMEDIATE_TABLES := $(patsubst %,$(LOCAL_OUT)/%.apk,$(PRIVATE_RESOURCE_TYPES))
-$(info PRIVATE_INTERMEDIATE_TABLES = $(PRIVATE_INTERMEDIATE_TABLES))
-
-# Generates rules for collect phase.
-# $1: Resource type (values-v4)
-# returns: out/values-v4.apk: res/values-v4/styles.xml res/values-v4/colors.xml
-define make-collect-rule
-$(LOCAL_OUT)/$1.apk: $(filter $(LOCAL_RESOURCE_DIR)/$1/%,$(PRIVATE_RESOURCES))
-	$(AAPT) compile -o $$@ $$^
-endef
-
-# Collect: out/values-v4.apk <- res/values-v4/styles.xml res/values-v4/colors.xml
-$(foreach d,$(PRIVATE_RESOURCE_TYPES),$(eval $(call make-collect-rule,$d)))
-
-# Link: out/package-unaligned.apk <- out/values-v4.apk out/drawable-v4.apk
-$(PRIVATE_APK_UNALIGNED): $(PRIVATE_INTERMEDIATE_TABLES) $(PRIVATE_LIBS) AndroidManifest.xml
-	$(AAPT) link --manifest AndroidManifest.xml $(addprefix -I ,$(PRIVATE_LIBS)) --java $(LOCAL_GEN) -o $@ $(PRIVATE_INTERMEDIATE_TABLES) --static-lib
-
-# R.java: gen/com/android/app/R.java <- out/resources.arsc
-# No action since R.java is generated when out/resources.arsc is.
-$(PRIVATE_R_JAVA): $(PRIVATE_APK_UNALIGNED)
-
-# Assemble: zip out/resources.arsc AndroidManifest.xml and res/**/*
-$(PRIVATE_APK_ALIGNED): $(PRIVATE_APK_UNALIGNED)
-	$(ZIPALIGN) $< $@
-
-# Create the out directory if needed.
-dummy := $(shell test -d $(LOCAL_OUT) || mkdir -p $(LOCAL_OUT))
-
-.PHONY: java
-java: $(PRIVATE_R_JAVA)
-
-.PHONY: assemble
-assemble: $(PRIVATE_APK_ALIGNED)
-
-.PHONY: all
-all: assemble java
-
-.DEFAULT_GOAL := all
diff --git a/tools/aapt2/data/lib/res/layout/main.xml b/tools/aapt2/data/lib/res/layout/main.xml
deleted file mode 100644
index 187ed2d..0000000
--- a/tools/aapt2/data/lib/res/layout/main.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent"/>
diff --git a/tools/aapt2/data/lib/res/raw/hello.txt b/tools/aapt2/data/lib/res/raw/hello.txt
deleted file mode 100644
index 44fc22b..0000000
--- a/tools/aapt2/data/lib/res/raw/hello.txt
+++ /dev/null
@@ -1 +0,0 @@
-Oh howdy there
diff --git a/tools/aapt2/data/lib/res/values/styles.xml b/tools/aapt2/data/lib/res/values/styles.xml
deleted file mode 100644
index 4ce6333..0000000
--- a/tools/aapt2/data/lib/res/values/styles.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <style name="Platform.AppCompat" parent="@android:style/Theme">
-        <item name="android:windowNoTitle">true</item>
-    </style>
-
-    <bool name="allow">true</bool>
-</resources>
diff --git a/tools/aapt2/data/res/drawable/image.xml b/tools/aapt2/data/res/drawable/image.xml
deleted file mode 100644
index 9b38739..0000000
--- a/tools/aapt2/data/res/drawable/image.xml
+++ /dev/null
@@ -1,2 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<vector />
diff --git a/tools/aapt2/data/res/layout-v21/main.xml b/tools/aapt2/data/res/layout-v21/main.xml
deleted file mode 100644
index 959b349..0000000
--- a/tools/aapt2/data/res/layout-v21/main.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-              xmlns:support="http://schemas.android.com/apk/res/android.appcompat"
-    android:id="@+id/view"
-    android:layout_width="match_parent"
-    android:layout_height="wrap_content">
-</LinearLayout>
diff --git a/tools/aapt2/data/res/layout/main.xml b/tools/aapt2/data/res/layout/main.xml
deleted file mode 100644
index 8a5e9e8..0000000
--- a/tools/aapt2/data/res/layout/main.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-              xmlns:support="http://schemas.android.com/apk/res/android.appcompat"
-    android:id="@+id/view"
-    android:layout_width="match_parent"
-    android:layout_height="wrap_content">
-
-    <fragment class="android.test.sample.App$Inner" />
-
-    <variable name="user" type="com.android.User" />
-
-    <View xmlns:app="http://schemas.android.com/apk/res-auto"
-        android:id="@+id/me"
-        android:layout_width="1dp"
-        android:onClick="doClick"
-        android:text="@{user.name}"
-        android:background="#ffffff"
-        android:layout_height="match_parent"
-        app:flags="complex|weak"
-        android:colorAccent="#ffffff"/>
-</LinearLayout>
diff --git a/tools/aapt2/data/res/values-v4/styles.xml b/tools/aapt2/data/res/values-v4/styles.xml
deleted file mode 100644
index 979a82a..0000000
--- a/tools/aapt2/data/res/values-v4/styles.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <style name="App" parent="android:Theme.Material">
-        <item name="android:colorAccent">@color/accent</item>
-        <item name="android:text">Hey</item>
-    </style>
-</resources>
diff --git a/tools/aapt2/data/res/values/colors.xml b/tools/aapt2/data/res/values/colors.xml
deleted file mode 100644
index 89db5fb..0000000
--- a/tools/aapt2/data/res/values/colors.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <color name="primary">#f44336</color>
-    <color name="primary_dark">#b71c1c</color>
-    <color name="accent">#fdd835</color>
-</resources>
diff --git a/tools/aapt2/data/res/values/styles.xml b/tools/aapt2/data/res/values/styles.xml
deleted file mode 100644
index 2bbdad1..0000000
--- a/tools/aapt2/data/res/values/styles.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources xmlns:lib="http://schemas.android.com/apk/res/android.appcompat">
-    <style name="App">
-        <item name="android:background">@color/primary</item>
-        <item name="android:colorPrimary">@color/primary</item>
-        <item name="android:colorPrimaryDark">@color/primary_dark</item>
-        <item name="android:colorAccent">@color/accent</item>
-    </style>
-    <attr name="custom" format="reference" />
-    <style name="Pop">
-        <item name="custom">@android:drawable/btn_default</item>
-        <item name="android:focusable">true</item>
-    </style>
-    <string name="yo">@string/wow</string>
-
-    <declare-styleable name="View">
-        <attr name="custom" />
-        <attr name="decor">
-            <enum name="no-border" value="0"/>
-            <enum name="border" value="1"/>
-            <enum name="shadow" value="2"/>
-        </attr>
-    </declare-styleable>
-
-</resources>
diff --git a/tools/aapt2/data/res/values/test.xml b/tools/aapt2/data/res/values/test.xml
deleted file mode 100644
index d7ab1c8..0000000
--- a/tools/aapt2/data/res/values/test.xml
+++ /dev/null
@@ -1,13 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="hooha"><font bgcolor="#ffffff">Hey guys!</font> <xliff:g>My</xliff:g> name is <b>Adam</b>. How <b><i>are</i></b> you?</string>
-    <public name="hooha" type="string" id="0x7f020001"/>
-    <string name="wow">@android:string/ok</string>
-    <public name="layout_width" type="attr" />
-    <attr name="layout_width" format="boolean" />
-    <attr name="flags">
-        <flag name="complex" value="1" />
-        <flag name="pub" value="2" />
-        <flag name="weak" value="4" />
-    </attr>
-</resources>
diff --git a/tools/aapt2/data/resources.arsc b/tools/aapt2/data/resources.arsc
deleted file mode 100644
index 6a416df..0000000
--- a/tools/aapt2/data/resources.arsc
+++ /dev/null
Binary files differ
diff --git a/tools/aapt2/data/resources_base.arsc b/tools/aapt2/data/resources_base.arsc
deleted file mode 100644
index f9d0610..0000000
--- a/tools/aapt2/data/resources_base.arsc
+++ /dev/null
Binary files differ
diff --git a/tools/aapt2/data/resources_hdpi.arsc b/tools/aapt2/data/resources_hdpi.arsc
deleted file mode 100644
index 97232a3..0000000
--- a/tools/aapt2/data/resources_hdpi.arsc
+++ /dev/null
Binary files differ
diff --git a/tools/aapt2/dump/Dump.cpp b/tools/aapt2/dump/Dump.cpp
index ad7de0a..56b9f9a 100644
--- a/tools/aapt2/dump/Dump.cpp
+++ b/tools/aapt2/dump/Dump.cpp
@@ -17,6 +17,7 @@
 #include "Debug.h"
 #include "Diagnostics.h"
 #include "Flags.h"
+#include "io/ZipArchive.h"
 #include "process/IResourceTableConsumer.h"
 #include "proto/ProtoSerialize.h"
 #include "util/Files.h"
@@ -56,6 +57,35 @@
 
 void tryDumpFile(IAaptContext* context, const std::string& filePath) {
     std::string err;
+    std::unique_ptr<io::ZipFileCollection> zip = io::ZipFileCollection::create(filePath, &err);
+    if (zip) {
+        io::IFile* file = zip->findFile("resources.arsc.flat");
+        if (file) {
+            std::unique_ptr<io::IData> data = file->openAsData();
+            if (!data) {
+                context->getDiagnostics()->error(DiagMessage(filePath)
+                                                 << "failed to open resources.arsc.flat");
+                return;
+            }
+
+            pb::ResourceTable pbTable;
+            if (!pbTable.ParseFromArray(data->data(), data->size())) {
+                context->getDiagnostics()->error(DiagMessage(filePath)
+                                                 << "invalid resources.arsc.flat");
+                return;
+            }
+
+            std::unique_ptr<ResourceTable> table = deserializeTableFromPb(
+                    pbTable, Source(filePath), context->getDiagnostics());
+            if (table) {
+                DebugPrintTableOptions debugPrintTableOptions;
+                debugPrintTableOptions.showSources = true;
+                Debug::printTable(table.get(), debugPrintTableOptions);
+            }
+        }
+        return;
+    }
+
     Maybe<android::FileMap> file = file::mmapPath(filePath, &err);
     if (!file) {
         context->getDiagnostics()->error(DiagMessage(filePath) << err);
@@ -90,15 +120,16 @@
         return nullptr;
     }
 
-    StringPiece16 getCompilationPackage() override {
-        return {};
+    const std::u16string& getCompilationPackage() override {
+        static std::u16string empty;
+        return empty;
     }
 
     uint8_t getPackageId() override {
         return 0;
     }
 
-    ISymbolTable* getExternalSymbols() override {
+    SymbolTable* getExternalSymbols() override {
         abort();
         return nullptr;
     }
diff --git a/tools/aapt2/flatten/XmlFlattener.cpp b/tools/aapt2/flatten/XmlFlattener.cpp
index 8219462..3eac633 100644
--- a/tools/aapt2/flatten/XmlFlattener.cpp
+++ b/tools/aapt2/flatten/XmlFlattener.cpp
@@ -144,9 +144,9 @@
     }
 
     static bool cmpXmlAttributeById(const xml::Attribute* a, const xml::Attribute* b) {
-        if (a->compiledAttribute) {
-            if (b->compiledAttribute) {
-                return a->compiledAttribute.value().id < b->compiledAttribute.value().id;
+        if (a->compiledAttribute && a->compiledAttribute.value().id) {
+            if (b->compiledAttribute && b->compiledAttribute.value().id) {
+                return a->compiledAttribute.value().id.value() < b->compiledAttribute.value().id.value();
             }
             return true;
         } else if (!b->compiledAttribute) {
@@ -167,8 +167,8 @@
 
         // Filter the attributes.
         for (xml::Attribute& attr : node->attributes) {
-            if (mOptions.maxSdkLevel && attr.compiledAttribute) {
-                size_t sdkLevel = findAttributeSdkLevel(attr.compiledAttribute.value().id);
+            if (mOptions.maxSdkLevel && attr.compiledAttribute && attr.compiledAttribute.value().id) {
+                size_t sdkLevel = findAttributeSdkLevel(attr.compiledAttribute.value().id.value());
                 if (sdkLevel > mOptions.maxSdkLevel.value()) {
                     continue;
                 }
@@ -191,8 +191,8 @@
         uint16_t attributeIndex = 1;
         for (const xml::Attribute* xmlAttr : mFilteredAttrs) {
             // Assign the indices for specific attributes.
-            if (xmlAttr->compiledAttribute &&
-                    xmlAttr->compiledAttribute.value().id == kIdAttr) {
+            if (xmlAttr->compiledAttribute && xmlAttr->compiledAttribute.value().id &&
+                    xmlAttr->compiledAttribute.value().id.value() == kIdAttr) {
                 flatElem->idIndex = util::hostToDevice16(attributeIndex);
             } else if (xmlAttr->namespaceUri.empty()) {
                 if (xmlAttr->name == u"class") {
@@ -208,7 +208,7 @@
 
             flatAttr->rawValue.index = util::hostToDevice32(-1);
 
-            if (!xmlAttr->compiledAttribute) {
+            if (!xmlAttr->compiledAttribute || !xmlAttr->compiledAttribute.value().id) {
                 // The attribute has no associated ResourceID, so the string order doesn't matter.
                 addString(xmlAttr->name, kLowPriority, &flatAttr->name);
             } else {
@@ -221,17 +221,17 @@
                 // Lookup the StringPool for this package and make the reference there.
                 const xml::AaptAttribute& aaptAttr = xmlAttr->compiledAttribute.value();
 
-                StringPool::Ref nameRef = mPackagePools[aaptAttr.id.packageId()].makeRef(
-                        xmlAttr->name, StringPool::Context{ aaptAttr.id.id });
+                StringPool::Ref nameRef = mPackagePools[aaptAttr.id.value().packageId()].makeRef(
+                        xmlAttr->name, StringPool::Context{ aaptAttr.id.value().id });
 
                 // Add it to the list of strings to flatten.
                 addString(nameRef, &flatAttr->name);
+            }
 
-                if (mOptions.keepRawValues) {
-                    // Keep raw values (this is for static libraries).
-                    // TODO(with a smarter inflater for binary XML, we can do without this).
-                    addString(xmlAttr->value, kLowPriority, &flatAttr->rawValue);
-                }
+            if (mOptions.keepRawValues || !xmlAttr->compiledValue) {
+                // Keep raw values if the value is not compiled or
+                // if we're building a static library (need symbols).
+                addString(xmlAttr->value, kLowPriority, &flatAttr->rawValue);
             }
 
             if (xmlAttr->compiledValue) {
@@ -240,7 +240,6 @@
             } else {
                 // Flatten as a regular string type.
                 flatAttr->typedValue.dataType = android::Res_value::TYPE_STRING;
-                addString(xmlAttr->value, kLowPriority, &flatAttr->rawValue);
                 addString(xmlAttr->value, kLowPriority,
                           (ResStringPool_ref*) &flatAttr->typedValue.data);
             }
diff --git a/tools/aapt2/flatten/XmlFlattener_test.cpp b/tools/aapt2/flatten/XmlFlattener_test.cpp
index 8648879..fef5ca3 100644
--- a/tools/aapt2/flatten/XmlFlattener_test.cpp
+++ b/tools/aapt2/flatten/XmlFlattener_test.cpp
@@ -32,7 +32,7 @@
         mContext = test::ContextBuilder()
                 .setCompilationPackage(u"com.app.test")
                 .setNameManglerPolicy(NameManglerPolicy{ u"com.app.test" })
-                .setSymbolTable(test::StaticSymbolTableBuilder()
+                .addSymbolSource(test::StaticSymbolSourceBuilder()
                         .addSymbol(u"@android:attr/id", ResourceId(0x010100d0),
                                    test::AttributeBuilder().build())
                         .addSymbol(u"@com.app.test:id/id", ResourceId(0x7f020000))
diff --git a/tools/aapt2/integration-tests/Android.mk b/tools/aapt2/integration-tests/Android.mk
new file mode 100644
index 0000000..6361f9b
--- /dev/null
+++ b/tools/aapt2/integration-tests/Android.mk
@@ -0,0 +1,2 @@
+LOCAL_PATH := $(call my-dir)
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/tools/aapt2/integration-tests/AppOne/Android.mk b/tools/aapt2/integration-tests/AppOne/Android.mk
new file mode 100644
index 0000000..bc40a62
--- /dev/null
+++ b/tools/aapt2/integration-tests/AppOne/Android.mk
@@ -0,0 +1,28 @@
+#
+# 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_USE_AAPT2 := true
+LOCAL_PACKAGE_NAME := AaptTestAppOne
+LOCAL_MODULE_TAGS := tests
+LOCAL_SRC_FILES := $(call all-java-files-under,src)
+LOCAL_STATIC_ANDROID_LIBRARIES := \
+    AaptTestStaticLibOne \
+    AaptTestStaticLibTwo
+LOCAL_AAPT_FLAGS := --no-version-vectors
+include $(BUILD_PACKAGE)
diff --git a/packages/SystemUI/res/drawable/qs_background_secondary.xml b/tools/aapt2/integration-tests/AppOne/AndroidManifest.xml
similarity index 67%
copy from packages/SystemUI/res/drawable/qs_background_secondary.xml
copy to tools/aapt2/integration-tests/AppOne/AndroidManifest.xml
index 31c0162..b6d8f2d 100644
--- a/packages/SystemUI/res/drawable/qs_background_secondary.xml
+++ b/tools/aapt2/integration-tests/AppOne/AndroidManifest.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2014 The Android Open Source Project
+<!-- Copyright (C) 2016 The Android Open Source Project
 
      Licensed under the Apache License, Version 2.0 (the "License");
      you may not use this file except in compliance with the License.
@@ -13,9 +13,5 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-<shape xmlns:android="http://schemas.android.com/apk/res/android">
-    <solid android:color="@color/system_secondary_color" />
-    <corners
-        android:topLeftRadius="0dp"
-        android:topRightRadius="0dp" />
-</shape>
+
+<manifest package="com.android.aapt.app.one" />
diff --git a/tools/aapt2/data/res/drawable/icon.png b/tools/aapt2/integration-tests/AppOne/res/drawable/icon.png
similarity index 100%
rename from tools/aapt2/data/res/drawable/icon.png
rename to tools/aapt2/integration-tests/AppOne/res/drawable/icon.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable/qs_background_secondary.xml b/tools/aapt2/integration-tests/AppOne/res/drawable/image.xml
similarity index 68%
copy from packages/SystemUI/res/drawable/qs_background_secondary.xml
copy to tools/aapt2/integration-tests/AppOne/res/drawable/image.xml
index 31c0162..6132a75 100644
--- a/packages/SystemUI/res/drawable/qs_background_secondary.xml
+++ b/tools/aapt2/integration-tests/AppOne/res/drawable/image.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2014 The Android Open Source Project
+<!-- Copyright (C) 2016 The Android Open Source Project
 
      Licensed under the Apache License, Version 2.0 (the "License");
      you may not use this file except in compliance with the License.
@@ -13,9 +13,5 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-<shape xmlns:android="http://schemas.android.com/apk/res/android">
-    <solid android:color="@color/system_secondary_color" />
-    <corners
-        android:topLeftRadius="0dp"
-        android:topRightRadius="0dp" />
-</shape>
+
+<vector />
diff --git a/tools/aapt2/data/res/drawable/test.9.png b/tools/aapt2/integration-tests/AppOne/res/drawable/test.9.png
similarity index 100%
rename from tools/aapt2/data/res/drawable/test.9.png
rename to tools/aapt2/integration-tests/AppOne/res/drawable/test.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable/qs_background_secondary.xml b/tools/aapt2/integration-tests/AppOne/res/layout-v21/main.xml
similarity index 63%
copy from packages/SystemUI/res/drawable/qs_background_secondary.xml
copy to tools/aapt2/integration-tests/AppOne/res/layout-v21/main.xml
index 31c0162..9f5a4a8 100644
--- a/packages/SystemUI/res/drawable/qs_background_secondary.xml
+++ b/tools/aapt2/integration-tests/AppOne/res/layout-v21/main.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2014 The Android Open Source Project
+<!-- Copyright (C) 2016 The Android Open Source Project
 
      Licensed under the Apache License, Version 2.0 (the "License");
      you may not use this file except in compliance with the License.
@@ -13,9 +13,10 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-<shape xmlns:android="http://schemas.android.com/apk/res/android">
-    <solid android:color="@color/system_secondary_color" />
-    <corners
-        android:topLeftRadius="0dp"
-        android:topRightRadius="0dp" />
-</shape>
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+              xmlns:support="http://schemas.android.com/apk/res/android.appcompat"
+    android:id="@+id/view"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content">
+</LinearLayout>
diff --git a/tools/aapt2/integration-tests/AppOne/res/layout/main.xml b/tools/aapt2/integration-tests/AppOne/res/layout/main.xml
new file mode 100644
index 0000000..ab1a251
--- /dev/null
+++ b/tools/aapt2/integration-tests/AppOne/res/layout/main.xml
@@ -0,0 +1,36 @@
+<?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:support="http://schemas.android.com/apk/res/android.appcompat"
+    android:id="@+id/view"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content">
+
+    <fragment class="android.test.sample.App$Inner" />
+
+    <variable name="user" type="com.android.User" />
+
+    <View xmlns:app="http://schemas.android.com/apk/res-auto"
+        android:id="@+id/me"
+        android:layout_width="1dp"
+        android:onClick="doClick"
+        android:text="@{user.name}"
+        android:background="#ffffff"
+        android:layout_height="match_parent"
+        app:flags="complex|weak"
+        android:colorAccent="#ffffff"/>
+</LinearLayout>
diff --git a/tools/aapt2/data/res/raw/test.txt b/tools/aapt2/integration-tests/AppOne/res/raw/test.txt
similarity index 100%
rename from tools/aapt2/data/res/raw/test.txt
rename to tools/aapt2/integration-tests/AppOne/res/raw/test.txt
diff --git a/packages/SystemUI/res/drawable/qs_background_secondary.xml b/tools/aapt2/integration-tests/AppOne/res/values-v4/styles.xml
similarity index 67%
copy from packages/SystemUI/res/drawable/qs_background_secondary.xml
copy to tools/aapt2/integration-tests/AppOne/res/values-v4/styles.xml
index 31c0162..d8c11e2 100644
--- a/packages/SystemUI/res/drawable/qs_background_secondary.xml
+++ b/tools/aapt2/integration-tests/AppOne/res/values-v4/styles.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2014 The Android Open Source Project
+<!-- Copyright (C) 2016 The Android Open Source Project
 
      Licensed under the Apache License, Version 2.0 (the "License");
      you may not use this file except in compliance with the License.
@@ -13,9 +13,10 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-<shape xmlns:android="http://schemas.android.com/apk/res/android">
-    <solid android:color="@color/system_secondary_color" />
-    <corners
-        android:topLeftRadius="0dp"
-        android:topRightRadius="0dp" />
-</shape>
+
+<resources>
+    <style name="App" parent="android:Theme.Material">
+        <item name="android:colorAccent">@color/accent</item>
+        <item name="android:text">Hey</item>
+    </style>
+</resources>
diff --git a/packages/SystemUI/res/drawable/qs_background_secondary.xml b/tools/aapt2/integration-tests/AppOne/res/values/colors.xml
similarity index 67%
copy from packages/SystemUI/res/drawable/qs_background_secondary.xml
copy to tools/aapt2/integration-tests/AppOne/res/values/colors.xml
index 31c0162..4df5077 100644
--- a/packages/SystemUI/res/drawable/qs_background_secondary.xml
+++ b/tools/aapt2/integration-tests/AppOne/res/values/colors.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2014 The Android Open Source Project
+<!-- Copyright (C) 2016 The Android Open Source Project
 
      Licensed under the Apache License, Version 2.0 (the "License");
      you may not use this file except in compliance with the License.
@@ -13,9 +13,9 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-<shape xmlns:android="http://schemas.android.com/apk/res/android">
-    <solid android:color="@color/system_secondary_color" />
-    <corners
-        android:topLeftRadius="0dp"
-        android:topRightRadius="0dp" />
-</shape>
+
+<resources>
+    <color name="primary">#f44336</color>
+    <color name="primary_dark">#b71c1c</color>
+    <color name="accent">#fdd835</color>
+</resources>
diff --git a/tools/aapt2/integration-tests/AppOne/res/values/styles.xml b/tools/aapt2/integration-tests/AppOne/res/values/styles.xml
new file mode 100644
index 0000000..f05845c
--- /dev/null
+++ b/tools/aapt2/integration-tests/AppOne/res/values/styles.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<resources xmlns:lib="http://schemas.android.com/apk/res/android.appcompat">
+    <style name="App">
+        <item name="android:background">@color/primary</item>
+        <item name="android:colorPrimary">@color/primary</item>
+        <item name="android:colorPrimaryDark">@color/primary_dark</item>
+        <item name="android:colorAccent">@color/accent</item>
+    </style>
+    <attr name="custom" format="reference" />
+    <style name="Pop">
+        <item name="custom">@android:drawable/btn_default</item>
+        <item name="android:focusable">true</item>
+    </style>
+    <string name="yo">@string/wow</string>
+
+    <declare-styleable name="View">
+        <attr name="custom" />
+        <attr name="decor">
+            <enum name="no-border" value="0"/>
+            <enum name="border" value="1"/>
+            <enum name="shadow" value="2"/>
+        </attr>
+    </declare-styleable>
+
+</resources>
diff --git a/tools/aapt2/integration-tests/AppOne/res/values/test.xml b/tools/aapt2/integration-tests/AppOne/res/values/test.xml
new file mode 100644
index 0000000..f4b7471
--- /dev/null
+++ b/tools/aapt2/integration-tests/AppOne/res/values/test.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <!-- Reference the two static libraries -->
+    <string name="AppFooBar">@string/FooBar</string>
+    <string name="AppFoo">@string/Foo</string>
+
+    <string name="hooha"><font bgcolor="#ffffff">Hey guys!</font> <xliff:g>My</xliff:g> name is <b>Adam</b>. How <b><i>are</i></b> you?</string>
+    <public name="hooha" type="string" id="0x7f020001"/>
+    <string name="wow">@android:string/ok</string>
+    <public name="layout_width" type="attr" />
+    <attr name="layout_width" format="boolean" />
+    <attr name="flags">
+        <flag name="complex" value="1" />
+        <flag name="pub" value="2" />
+        <flag name="weak" value="4" />
+    </attr>
+</resources>
diff --git a/tools/aapt2/integration-tests/AppOne/src/com/android/aapt/app/one/AppOne.java b/tools/aapt2/integration-tests/AppOne/src/com/android/aapt/app/one/AppOne.java
new file mode 100644
index 0000000..472b35a
--- /dev/null
+++ b/tools/aapt2/integration-tests/AppOne/src/com/android/aapt/app/one/AppOne.java
@@ -0,0 +1,26 @@
+/*
+ * 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.aapt.app.one;
+
+public class AppOne {
+    // IDs from StaticLibOne
+    public static int FooId = com.android.aapt.staticlib.one.R.string.Foo;
+    public static int LayoutId = com.android.aapt.staticlib.one.R.layout.layout;
+
+    // IDs from StaticLibTwo
+    public static int FooBarId = com.android.aapt.staticlib.two.R.string.FooBar;
+}
+
diff --git a/tools/aapt2/integration-tests/StaticLibOne/Android.mk b/tools/aapt2/integration-tests/StaticLibOne/Android.mk
new file mode 100644
index 0000000..d59dc60
--- /dev/null
+++ b/tools/aapt2/integration-tests/StaticLibOne/Android.mk
@@ -0,0 +1,25 @@
+#
+# 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_USE_AAPT2 := true
+LOCAL_MODULE := AaptTestStaticLibOne
+LOCAL_MODULE_TAGS := tests
+LOCAL_SRC_FILES := $(call all-java-files-under,src)
+LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
+include $(BUILD_STATIC_JAVA_LIBRARY)
diff --git a/packages/SystemUI/res/drawable/qs_background_secondary.xml b/tools/aapt2/integration-tests/StaticLibOne/AndroidManifest.xml
similarity index 67%
copy from packages/SystemUI/res/drawable/qs_background_secondary.xml
copy to tools/aapt2/integration-tests/StaticLibOne/AndroidManifest.xml
index 31c0162..705047e 100644
--- a/packages/SystemUI/res/drawable/qs_background_secondary.xml
+++ b/tools/aapt2/integration-tests/StaticLibOne/AndroidManifest.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2014 The Android Open Source Project
+<!-- Copyright (C) 2016 The Android Open Source Project
 
      Licensed under the Apache License, Version 2.0 (the "License");
      you may not use this file except in compliance with the License.
@@ -13,9 +13,5 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-<shape xmlns:android="http://schemas.android.com/apk/res/android">
-    <solid android:color="@color/system_secondary_color" />
-    <corners
-        android:topLeftRadius="0dp"
-        android:topRightRadius="0dp" />
-</shape>
+
+<manifest package="com.android.aapt.staticlib.one" />
diff --git a/packages/SystemUI/res/drawable/qs_background_secondary.xml b/tools/aapt2/integration-tests/StaticLibOne/res/layout/layout.xml
similarity index 67%
copy from packages/SystemUI/res/drawable/qs_background_secondary.xml
copy to tools/aapt2/integration-tests/StaticLibOne/res/layout/layout.xml
index 31c0162..683c91c 100644
--- a/packages/SystemUI/res/drawable/qs_background_secondary.xml
+++ b/tools/aapt2/integration-tests/StaticLibOne/res/layout/layout.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2014 The Android Open Source Project
+<!-- Copyright (C) 2016 The Android Open Source Project
 
      Licensed under the Apache License, Version 2.0 (the "License");
      you may not use this file except in compliance with the License.
@@ -13,9 +13,6 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-<shape xmlns:android="http://schemas.android.com/apk/res/android">
-    <solid android:color="@color/system_secondary_color" />
-    <corners
-        android:topLeftRadius="0dp"
-        android:topRightRadius="0dp" />
-</shape>
+
+<View xmlns:android="http://schemas.android.com/apk/res/android"
+      android:text="@string/Foo" />
diff --git a/packages/SystemUI/res/drawable/qs_background_secondary.xml b/tools/aapt2/integration-tests/StaticLibOne/res/values/values.xml
similarity index 61%
copy from packages/SystemUI/res/drawable/qs_background_secondary.xml
copy to tools/aapt2/integration-tests/StaticLibOne/res/values/values.xml
index 31c0162..d09a485 100644
--- a/packages/SystemUI/res/drawable/qs_background_secondary.xml
+++ b/tools/aapt2/integration-tests/StaticLibOne/res/values/values.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2014 The Android Open Source Project
+<!-- Copyright (C) 2016 The Android Open Source Project
 
      Licensed under the Apache License, Version 2.0 (the "License");
      you may not use this file except in compliance with the License.
@@ -13,9 +13,15 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-<shape xmlns:android="http://schemas.android.com/apk/res/android">
-    <solid android:color="@color/system_secondary_color" />
-    <corners
-        android:topLeftRadius="0dp"
-        android:topRightRadius="0dp" />
-</shape>
+
+<resources>
+    <!-- An attribute from StaticLibOne -->
+    <attr name="StaticLibOne_attr" format="string" />
+
+    <string name="Foo">Foo</string>
+    <string name="Foo" product="tablet">Bar</string>
+
+    <declare-styleable name="Widget">
+        <attr name="StaticLibOne_attr" />
+    </declare-styleable>
+</resources>
diff --git a/core/java/android/hardware/camera2/utils/LongParcelable.aidl b/tools/aapt2/integration-tests/StaticLibOne/src/com/android/aapt/staticlib/one/StaticLibOne.java
similarity index 64%
copy from core/java/android/hardware/camera2/utils/LongParcelable.aidl
copy to tools/aapt2/integration-tests/StaticLibOne/src/com/android/aapt/staticlib/one/StaticLibOne.java
index 98ad1b2..cf48f67 100644
--- a/core/java/android/hardware/camera2/utils/LongParcelable.aidl
+++ b/tools/aapt2/integration-tests/StaticLibOne/src/com/android/aapt/staticlib/one/StaticLibOne.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2014 The Android Open Source Project
+ * Copyright (C) 2016 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -13,8 +13,10 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+package com.android.aapt.staticlib.one;
 
-package android.hardware.camera2.utils;
-
-/** @hide */
-parcelable LongParcelable;
+public class StaticLibOne {
+    // IDs from StaticLibOne
+    public static int FooId = com.android.aapt.staticlib.one.R.string.Foo;
+    public static int LayoutId = com.android.aapt.staticlib.one.R.layout.layout;
+}
diff --git a/tools/aapt2/integration-tests/StaticLibTwo/Android.mk b/tools/aapt2/integration-tests/StaticLibTwo/Android.mk
new file mode 100644
index 0000000..8b6eb41
--- /dev/null
+++ b/tools/aapt2/integration-tests/StaticLibTwo/Android.mk
@@ -0,0 +1,27 @@
+#
+# 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_USE_AAPT2 := true
+LOCAL_MODULE := AaptTestStaticLibTwo
+LOCAL_MODULE_TAGS := tests
+LOCAL_SRC_FILES := $(call all-java-files-under,src)
+LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
+LOCAL_SHARED_ANDROID_LIBRARIES := AaptTestStaticLibOne
+include $(BUILD_STATIC_JAVA_LIBRARY)
+
diff --git a/packages/SystemUI/res/drawable/qs_background_secondary.xml b/tools/aapt2/integration-tests/StaticLibTwo/AndroidManifest.xml
similarity index 67%
copy from packages/SystemUI/res/drawable/qs_background_secondary.xml
copy to tools/aapt2/integration-tests/StaticLibTwo/AndroidManifest.xml
index 31c0162..28f0699 100644
--- a/packages/SystemUI/res/drawable/qs_background_secondary.xml
+++ b/tools/aapt2/integration-tests/StaticLibTwo/AndroidManifest.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2014 The Android Open Source Project
+<!-- Copyright (C) 2016 The Android Open Source Project
 
      Licensed under the Apache License, Version 2.0 (the "License");
      you may not use this file except in compliance with the License.
@@ -13,9 +13,5 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-<shape xmlns:android="http://schemas.android.com/apk/res/android">
-    <solid android:color="@color/system_secondary_color" />
-    <corners
-        android:topLeftRadius="0dp"
-        android:topRightRadius="0dp" />
-</shape>
+
+<manifest package="com.android.aapt.staticlib.two" />
diff --git a/tools/aapt2/integration-tests/StaticLibTwo/res/drawable/vector.xml b/tools/aapt2/integration-tests/StaticLibTwo/res/drawable/vector.xml
new file mode 100644
index 0000000..dd5979f
--- /dev/null
+++ b/tools/aapt2/integration-tests/StaticLibTwo/res/drawable/vector.xml
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="utf-8"?>
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:pathData="1123"/>
diff --git a/packages/SystemUI/res/drawable/qs_background_secondary.xml b/tools/aapt2/integration-tests/StaticLibTwo/res/layout/layout_two.xml
similarity index 67%
copy from packages/SystemUI/res/drawable/qs_background_secondary.xml
copy to tools/aapt2/integration-tests/StaticLibTwo/res/layout/layout_two.xml
index 31c0162..ba98307 100644
--- a/packages/SystemUI/res/drawable/qs_background_secondary.xml
+++ b/tools/aapt2/integration-tests/StaticLibTwo/res/layout/layout_two.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2014 The Android Open Source Project
+<!-- Copyright (C) 2016 The Android Open Source Project
 
      Licensed under the Apache License, Version 2.0 (the "License");
      you may not use this file except in compliance with the License.
@@ -13,9 +13,6 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-<shape xmlns:android="http://schemas.android.com/apk/res/android">
-    <solid android:color="@color/system_secondary_color" />
-    <corners
-        android:topLeftRadius="0dp"
-        android:topRightRadius="0dp" />
-</shape>
+
+<View xmlns:custom="http://schemas.android.com/apk/res-auto"
+      custom:StaticLibOne_attr="@string/FooBar" />
diff --git a/packages/SystemUI/res/drawable/qs_background_secondary.xml b/tools/aapt2/integration-tests/StaticLibTwo/res/values/values.xml
similarity index 67%
copy from packages/SystemUI/res/drawable/qs_background_secondary.xml
copy to tools/aapt2/integration-tests/StaticLibTwo/res/values/values.xml
index 31c0162..97bb2a5 100644
--- a/packages/SystemUI/res/drawable/qs_background_secondary.xml
+++ b/tools/aapt2/integration-tests/StaticLibTwo/res/values/values.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2014 The Android Open Source Project
+<!-- Copyright (C) 2016 The Android Open Source Project
 
      Licensed under the Apache License, Version 2.0 (the "License");
      you may not use this file except in compliance with the License.
@@ -13,9 +13,7 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-<shape xmlns:android="http://schemas.android.com/apk/res/android">
-    <solid android:color="@color/system_secondary_color" />
-    <corners
-        android:topLeftRadius="0dp"
-        android:topRightRadius="0dp" />
-</shape>
+
+<resources>
+    <string name="FooBar">@string/Foo</string>
+</resources>
diff --git a/tools/aapt2/integration-tests/StaticLibTwo/src/com/android/aapt/staticlib/two/StaticLibTwo.java b/tools/aapt2/integration-tests/StaticLibTwo/src/com/android/aapt/staticlib/two/StaticLibTwo.java
new file mode 100644
index 0000000..7110dcd
--- /dev/null
+++ b/tools/aapt2/integration-tests/StaticLibTwo/src/com/android/aapt/staticlib/two/StaticLibTwo.java
@@ -0,0 +1,25 @@
+/*
+ * 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.aapt.staticlib.two;
+
+public class StaticLibTwo {
+    // IDs from StaticLibOne
+    public static int FooId = com.android.aapt.staticlib.one.R.string.Foo;
+    public static int LayoutId = com.android.aapt.staticlib.one.R.layout.layout;
+
+    // IDs from StaticLibTwo
+    public static int FooBarId = com.android.aapt.staticlib.two.R.string.FooBar;
+}
diff --git a/tools/aapt2/io/ZipArchive.cpp b/tools/aapt2/io/ZipArchive.cpp
index 329dac9..b3e7a02 100644
--- a/tools/aapt2/io/ZipArchive.cpp
+++ b/tools/aapt2/io/ZipArchive.cpp
@@ -92,9 +92,8 @@
         return {};
     }
 
-    ZipString suffix(".flat");
     void* cookie = nullptr;
-    result = StartIteration(collection->mHandle, &cookie, nullptr, &suffix);
+    result = StartIteration(collection->mHandle, &cookie, nullptr, nullptr);
     if (result != 0) {
         if (outError) *outError = ErrorCodeString(result);
         return {};
diff --git a/tools/aapt2/java/AnnotationProcessor.cpp b/tools/aapt2/java/AnnotationProcessor.cpp
index 9c25d4e..496e92e 100644
--- a/tools/aapt2/java/AnnotationProcessor.cpp
+++ b/tools/aapt2/java/AnnotationProcessor.cpp
@@ -38,7 +38,7 @@
         mComment << "/**";
     }
 
-    mComment << "\n" << " * " << std::move(comment);
+    mComment << "\n * " << std::move(comment);
 }
 
 void AnnotationProcessor::appendComment(const StringPiece16& comment) {
@@ -60,6 +60,10 @@
     }
 }
 
+void AnnotationProcessor::appendNewLine() {
+    mComment << "\n *";
+}
+
 void AnnotationProcessor::writeToStream(std::ostream* out, const StringPiece& prefix) {
     if (mHasComments) {
         std::string result = mComment.str();
diff --git a/tools/aapt2/java/AnnotationProcessor.h b/tools/aapt2/java/AnnotationProcessor.h
index e7f2be0..fadf584 100644
--- a/tools/aapt2/java/AnnotationProcessor.h
+++ b/tools/aapt2/java/AnnotationProcessor.h
@@ -61,6 +61,8 @@
     void appendComment(const StringPiece16& comment);
     void appendComment(const StringPiece& comment);
 
+    void appendNewLine();
+
     /**
      * Writes the comments and annotations to the stream, with the given prefix before each line.
      */
diff --git a/tools/aapt2/java/ClassDefinitionWriter.h b/tools/aapt2/java/ClassDefinitionWriter.h
index 04e1274..cf92c9a 100644
--- a/tools/aapt2/java/ClassDefinitionWriter.h
+++ b/tools/aapt2/java/ClassDefinitionWriter.h
@@ -65,7 +65,7 @@
              << "String " << name << "=\"" << val << "\";\n";
     }
 
-    void addResourceMember(const StringPiece16& name, AnnotationProcessor* processor,
+    void addResourceMember(const StringPiece& name, AnnotationProcessor* processor,
                            const ResourceId id) {
         ensureClassDeclaration();
         if (processor) {
@@ -76,7 +76,7 @@
     }
 
     template <typename Iterator, typename FieldAccessorFunc>
-    void addArrayMember(const StringPiece16& name, AnnotationProcessor* processor,
+    void addArrayMember(const StringPiece& name, AnnotationProcessor* processor,
                         const Iterator begin, const Iterator end, FieldAccessorFunc f) {
         ensureClassDeclaration();
         if (processor) {
diff --git a/tools/aapt2/java/JavaClassGenerator.cpp b/tools/aapt2/java/JavaClassGenerator.cpp
index 6e340a2..01330dc 100644
--- a/tools/aapt2/java/JavaClassGenerator.cpp
+++ b/tools/aapt2/java/JavaClassGenerator.cpp
@@ -23,6 +23,7 @@
 #include "java/AnnotationProcessor.h"
 #include "java/ClassDefinitionWriter.h"
 #include "java/JavaClassGenerator.h"
+#include "process/SymbolTable.h"
 #include "util/StringPiece.h"
 
 #include <algorithm>
@@ -33,8 +34,9 @@
 
 namespace aapt {
 
-JavaClassGenerator::JavaClassGenerator(ResourceTable* table, JavaClassGeneratorOptions options) :
-        mTable(table), mOptions(options) {
+JavaClassGenerator::JavaClassGenerator(IAaptContext* context, ResourceTable* table,
+                                       const JavaClassGeneratorOptions& options) :
+        mContext(context), mTable(table), mOptions(options) {
 }
 
 static void generateHeader(const StringPiece16& packageNameToGenerate, std::ostream* out) {
@@ -68,16 +70,120 @@
  * Java symbols can not contain . or -, but those are valid in a resource name.
  * Replace those with '_'.
  */
-static std::u16string transform(const StringPiece16& symbol) {
-    std::u16string output = symbol.toString();
-    for (char16_t& c : output) {
-        if (c == u'.' || c == u'-') {
-            c = u'_';
+static std::string transform(const StringPiece16& symbol) {
+    std::string output = util::utf16ToUtf8(symbol);
+    for (char& c : output) {
+        if (c == '.' || c == '-') {
+            c = '_';
         }
     }
     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& attrName,
+                                       const std::string& styleableClassName,
+                                       const StringPiece16& packageNameToGenerate) {
+    std::string output = styleableClassName;
+
+    // We may reference IDs from other packages, so prefix the entry name with
+    // the package.
+    if (!attrName.package.empty() && packageNameToGenerate != attrName.package) {
+        output += "_" + transform(attrName.package);
+    }
+    output += "_" + transform(attrName.entry);
+    return output;
+}
+
+static void addAttributeFormatDoc(AnnotationProcessor* processor, Attribute* attr) {
+    const uint32_t typeMask = attr->typeMask;
+    if (typeMask & android::ResTable_map::TYPE_REFERENCE) {
+        processor->appendComment(
+                "<p>May be a reference to another resource, in the form\n"
+                        "\"<code>@[+][<i>package</i>:]<i>type</i>/<i>name</i></code>\" or a theme\n"
+                        "attribute in the form\n"
+                        "\"<code>?[<i>package</i>:]<i>type</i>/<i>name</i></code>\".");
+    }
+
+    if (typeMask & android::ResTable_map::TYPE_STRING) {
+        processor->appendComment(
+                "<p>May be a string value, using '\\\\;' to escape characters such as\n"
+                        "'\\\\n' or '\\\\uxxxx' for a unicode character;");
+    }
+
+    if (typeMask & android::ResTable_map::TYPE_INTEGER) {
+        processor->appendComment("<p>May be an integer value, such as \"<code>100</code>\".");
+    }
+
+    if (typeMask & android::ResTable_map::TYPE_BOOLEAN) {
+        processor->appendComment(
+                "<p>May be a boolean value, such as \"<code>true</code>\" or\n"
+                        "\"<code>false</code>\".");
+    }
+
+    if (typeMask & android::ResTable_map::TYPE_COLOR) {
+        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>aarrggbb</i></code>\".");
+    }
+
+    if (typeMask & android::ResTable_map::TYPE_FLOAT) {
+        processor->appendComment(
+                "<p>May be a floating point value, such as \"<code>1.2</code>\".");
+    }
+
+    if (typeMask & android::ResTable_map::TYPE_DIMENSION) {
+        processor->appendComment(
+                "<p>May be a dimension value, which is a floating point number appended with a\n"
+                        "unit such as \"<code>14.5sp</code>\".\n"
+                        "Available units are: px (pixels), dp (density-independent pixels),\n"
+                        "sp (scaled pixels based on preferred font size), in (inches), and\n"
+                        "mm (millimeters).");
+    }
+
+    if (typeMask & android::ResTable_map::TYPE_FRACTION) {
+        processor->appendComment(
+                "<p>May be a fractional value, which is a floating point number appended with\n"
+                        "either % or %p, such as \"<code>14.5%</code>\".\n"
+                        "The % suffix always means a percentage of the base size;\n"
+                        "the optional %p suffix provides a size relative to some parent container.");
+    }
+
+    if (typeMask & (android::ResTable_map::TYPE_FLAGS | android::ResTable_map::TYPE_ENUM)) {
+        if (typeMask & android::ResTable_map::TYPE_FLAGS) {
+            processor->appendComment(
+                    "<p>Must be one or more (separated by '|') of the following "
+                            "constant values.</p>");
+        } else {
+            processor->appendComment("<p>Must be one of the following constant values.</p>");
+        }
+
+        processor->appendComment("<table>\n<colgroup align=\"left\" />\n"
+                                         "<colgroup align=\"left\" />\n"
+                                         "<colgroup align=\"left\" />\n"
+                                         "<tr><th>Constant</th><th>Value</th><th>Description</th></tr>\n");
+        for (const Attribute::Symbol& symbol : attr->symbols) {
+            std::stringstream line;
+            line << "<tr><td>" << symbol.symbol.name.value().entry << "</td>"
+            << "<td>" << std::hex << symbol.value << std::dec << "</td>"
+            << "<td>" << util::trimWhitespace(symbol.symbol.getComment()) << "</td></tr>";
+            processor->appendComment(line.str());
+        }
+        processor->appendComment("</table>");
+    }
+}
+
 bool JavaClassGenerator::skipSymbol(SymbolState state) {
     switch (mOptions.types) {
     case JavaClassGeneratorOptions::SymbolTypes::kAll:
@@ -90,127 +196,159 @@
     return true;
 }
 
+struct StyleableAttr {
+    const Reference* attrRef;
+    std::shared_ptr<Attribute> attribute;
+    std::string fieldName;
+};
+
+static bool lessStyleableAttr(const StyleableAttr& lhs, const StyleableAttr& rhs) {
+    const ResourceId lhsId = lhs.attrRef->id ? lhs.attrRef->id.value() : ResourceId(0);
+    const ResourceId rhsId = rhs.attrRef->id ? rhs.attrRef->id.value() : ResourceId(0);
+    if (lhsId < rhsId) {
+        return true;
+    } else if (lhsId > rhsId) {
+        return false;
+    } else {
+        return lhs.attrRef->name.value() < rhs.attrRef->name.value();
+    }
+}
+
 void JavaClassGenerator::writeStyleableEntryForClass(ClassDefinitionWriter* outClassDef,
                                                      AnnotationProcessor* processor,
                                                      const StringPiece16& packageNameToGenerate,
                                                      const std::u16string& entryName,
                                                      const Styleable* styleable) {
+    const std::string className = transform(entryName);
+
     // This must be sorted by resource ID.
-    std::vector<std::pair<ResourceId, ResourceNameRef>> sortedAttributes;
+    std::vector<StyleableAttr> sortedAttributes;
     sortedAttributes.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.
         assert((!mOptions.useFinal || attr.id) && "no ID set for Styleable entry");
         assert(attr.name && "no name set for Styleable entry");
-        sortedAttributes.emplace_back(attr.id ? attr.id.value() : ResourceId(0), attr.name.value());
-    }
-    std::sort(sortedAttributes.begin(), sortedAttributes.end());
 
-    auto accessorFunc = [](const std::pair<ResourceId, ResourceNameRef>& a) -> ResourceId {
-        return a.first;
+        StyleableAttr styleableAttr = {};
+        styleableAttr.attrRef = &attr;
+        styleableAttr.fieldName = transformNestedAttr(attr.name.value(), className,
+                                                      packageNameToGenerate);
+
+        Reference mangledReference;
+        mangledReference.id = attr.id;
+        mangledReference.name = attr.name;
+        if (mangledReference.name.value().package.empty()) {
+            mangledReference.name.value().package = mContext->getCompilationPackage();
+        }
+
+        if (Maybe<ResourceName> mangledName =
+                mContext->getNameMangler()->mangleName(mangledReference.name.value())) {
+            mangledReference.name = mangledName;
+        }
+
+        const SymbolTable::Symbol* symbol = mContext->getExternalSymbols()->findByReference(
+                mangledReference);
+        if (symbol) {
+            styleableAttr.attribute = symbol->attribute;
+        }
+        sortedAttributes.push_back(std::move(styleableAttr));
+    }
+    std::sort(sortedAttributes.begin(), sortedAttributes.end(), lessStyleableAttr);
+
+    const size_t attrCount = sortedAttributes.size();
+
+    if (attrCount > 0) {
+        // Build the comment string for the Styleable. It includes details about the
+        // child attributes.
+        std::stringstream styleableComment;
+        if (!styleable->getComment().empty()) {
+            styleableComment << styleable->getComment() << "\n";
+        } else {
+            styleableComment << "Attributes that can be used with a " << className << ".\n";
+        }
+        styleableComment <<
+                "<p>Includes the following attributes:</p>\n"
+                "<table>\n"
+                "<colgroup align=\"left\" />\n"
+                "<colgroup align=\"left\" />\n"
+                "<tr><th>Attribute</th><th>Description</th></tr>\n";
+
+        for (const auto& entry : sortedAttributes) {
+            const ResourceName& attrName = entry.attrRef->name.value();
+            styleableComment << "<tr><td>";
+            styleableComment << "<code>{@link #"
+                             << entry.fieldName << " "
+                             << (!attrName.package.empty()
+                                    ? attrName.package : mContext->getCompilationPackage())
+                             << ":" << attrName.entry
+                             << "}</code>";
+            styleableComment << "</td>";
+
+            styleableComment << "<td>";
+            if (entry.attribute) {
+                styleableComment << entry.attribute->getComment();
+            }
+            styleableComment << "</td></tr>\n";
+        }
+        styleableComment << "</table>\n";
+        for (const auto& entry : sortedAttributes) {
+            styleableComment << "@see #" << entry.fieldName << "\n";
+        }
+        processor->appendComment(styleableComment.str());
+    }
+
+    auto accessorFunc = [](const StyleableAttr& a) -> ResourceId {
+        return a.attrRef->id ? a.attrRef->id.value() : ResourceId(0);
     };
 
     // First we emit the array containing the IDs of each attribute.
-    outClassDef->addArrayMember(transform(entryName), processor,
+    outClassDef->addArrayMember(className, processor,
                                 sortedAttributes.begin(),
                                 sortedAttributes.end(),
                                 accessorFunc);
 
     // Now we emit the indices into the array.
-    size_t attrCount = sortedAttributes.size();
     for (size_t i = 0; i < attrCount; i++) {
-        std::stringstream name;
-        name << transform(entryName);
+        const StyleableAttr& styleableAttr = sortedAttributes[i];
+        const ResourceName& attrName = styleableAttr.attrRef->name.value();
 
-        // We may reference IDs from other packages, so prefix the entry name with
-        // the package.
-        const ResourceNameRef& itemName = sortedAttributes[i].second;
-        if (!itemName.package.empty() && packageNameToGenerate != itemName.package) {
-            name << "_" << transform(itemName.package);
+        StringPiece16 packageName = attrName.package;
+        if (packageName.empty()) {
+            packageName = mContext->getCompilationPackage();
         }
-        name << "_" << transform(itemName.entry);
 
-        outClassDef->addIntMember(name.str(), nullptr, i);
-    }
-}
+        AnnotationProcessor attrProcessor;
 
-static void addAttributeFormatDoc(AnnotationProcessor* processor, Attribute* attr) {
-    const uint32_t typeMask = attr->typeMask;
-    if (typeMask & android::ResTable_map::TYPE_REFERENCE) {
-        processor->appendComment(
-                "<p>May be a reference to another resource, in the form\n"
-                "\"<code>@[+][<i>package</i>:]<i>type</i>/<i>name</i></code>\" or a theme\n"
-                "attribute in the form\n"
-                "\"<code>?[<i>package</i>:]<i>type</i>/<i>name</i></code>\".");
-    }
+        StringPiece16 comment = styleableAttr.attrRef->getComment();
+        if (styleableAttr.attribute && comment.empty()) {
+            comment = styleableAttr.attribute->getComment();
+        }
 
-    if (typeMask & android::ResTable_map::TYPE_STRING) {
-        processor->appendComment(
-                "<p>May be a string value, using '\\\\;' to escape characters such as\n"
-                "'\\\\n' or '\\\\uxxxx' for a unicode character;");
-    }
-
-    if (typeMask & android::ResTable_map::TYPE_INTEGER) {
-        processor->appendComment("<p>May be an integer value, such as \"<code>100</code>\".");
-    }
-
-    if (typeMask & android::ResTable_map::TYPE_BOOLEAN) {
-        processor->appendComment(
-                "<p>May be a boolean value, such as \"<code>true</code>\" or\n"
-                "\"<code>false</code>\".");
-    }
-
-    if (typeMask & android::ResTable_map::TYPE_COLOR) {
-        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>aarrggbb</i></code>\".");
-    }
-
-    if (typeMask & android::ResTable_map::TYPE_FLOAT) {
-        processor->appendComment(
-                "<p>May be a floating point value, such as \"<code>1.2</code>\".");
-    }
-
-    if (typeMask & android::ResTable_map::TYPE_DIMENSION) {
-        processor->appendComment(
-                "<p>May be a dimension value, which is a floating point number appended with a\n"
-                "unit such as \"<code>14.5sp</code>\".\n"
-                "Available units are: px (pixels), dp (density-independent pixels),\n"
-                "sp (scaled pixels based on preferred font size), in (inches), and\n"
-                "mm (millimeters).");
-    }
-
-    if (typeMask & android::ResTable_map::TYPE_FRACTION) {
-        processor->appendComment(
-                "<p>May be a fractional value, which is a floating point number appended with\n"
-                "either % or %p, such as \"<code>14.5%</code>\".\n"
-                "The % suffix always means a percentage of the base size;\n"
-                "the optional %p suffix provides a size relative to some parent container.");
-    }
-
-    if (typeMask & (android::ResTable_map::TYPE_FLAGS | android::ResTable_map::TYPE_ENUM)) {
-        if (typeMask & android::ResTable_map::TYPE_FLAGS) {
-            processor->appendComment(
-                    "<p>Must be one or more (separated by '|') of the following "
-                    "constant values.</p>");
+        if (!comment.empty()) {
+            attrProcessor.appendComment("<p>\n@attr description");
+            attrProcessor.appendComment(comment);
         } else {
-            processor->appendComment("<p>Must be one of the following constant values.</p>");
+            std::stringstream defaultComment;
+            defaultComment
+                    << "<p>This symbol is the offset where the "
+                    << "{@link " << packageName << ".R.attr#" << transform(attrName.entry) << "}\n"
+                    << "attribute's value can be found in the "
+                    << "{@link #" << className << "} array.";
+            attrProcessor.appendComment(defaultComment.str());
         }
 
-        processor->appendComment("<table>\n<colgroup align=\"left\" />\n"
-                                 "<colgroup align=\"left\" />\n"
-                                 "<colgroup align=\"left\" />\n"
-                                 "<tr><th>Constant</th><th>Value</th><th>Description</th></tr>\n");
-        for (const Attribute::Symbol& symbol : attr->symbols) {
-            std::stringstream line;
-            line << "<tr><td>" << symbol.symbol.name.value().entry << "</td>"
-                 << "<td>" << std::hex << symbol.value << std::dec << "</td>"
-                 << "<td>" << util::trimWhitespace(symbol.symbol.getComment()) << "</td></tr>";
-            processor->appendComment(line.str());
+        attrProcessor.appendNewLine();
+
+        if (styleableAttr.attribute) {
+            addAttributeFormatDoc(&attrProcessor, styleableAttr.attribute.get());
+            attrProcessor.appendNewLine();
         }
-        processor->appendComment("</table>");
+
+        std::stringstream doclavaName;
+        doclavaName << "@attr name " << packageName << ":" << attrName.entry;;
+        attrProcessor.appendComment(doclavaName.str());
+        outClassDef->addIntMember(sortedAttributes[i].fieldName, &attrProcessor, i);
     }
 }
 
@@ -223,8 +361,10 @@
             continue;
         }
 
-        ResourceId id(package->id.value(), type->id.value(), entry->id.value());
-        assert(id.isValid());
+        ResourceId id;
+        if (package->id && type->id && entry->id) {
+            id = ResourceId(package->id.value(), type->id.value(), entry->id.value());
+        }
 
         std::u16string unmangledPackage;
         std::u16string unmangledName = entry->name;
diff --git a/tools/aapt2/java/JavaClassGenerator.h b/tools/aapt2/java/JavaClassGenerator.h
index 023d6d6..7e46f8c 100644
--- a/tools/aapt2/java/JavaClassGenerator.h
+++ b/tools/aapt2/java/JavaClassGenerator.h
@@ -19,7 +19,7 @@
 
 #include "ResourceTable.h"
 #include "ResourceValues.h"
-
+#include "process/IResourceTableConsumer.h"
 #include "util/StringPiece.h"
 
 #include <ostream>
@@ -51,7 +51,8 @@
  */
 class JavaClassGenerator {
 public:
-    JavaClassGenerator(ResourceTable* table, JavaClassGeneratorOptions options);
+    JavaClassGenerator(IAaptContext* context, ResourceTable* table,
+                       const JavaClassGeneratorOptions& options);
 
     /*
      * Writes the R.java file to `out`. Only symbols belonging to `package` are written.
@@ -82,6 +83,7 @@
 
     bool skipSymbol(SymbolState state);
 
+    IAaptContext* mContext;
     ResourceTable* mTable;
     JavaClassGeneratorOptions mOptions;
     std::string mError;
diff --git a/tools/aapt2/java/JavaClassGenerator_test.cpp b/tools/aapt2/java/JavaClassGenerator_test.cpp
index e9e7881..4f041b8 100644
--- a/tools/aapt2/java/JavaClassGenerator_test.cpp
+++ b/tools/aapt2/java/JavaClassGenerator_test.cpp
@@ -15,11 +15,9 @@
  */
 
 #include "java/JavaClassGenerator.h"
+#include "test/Test.h"
 #include "util/Util.h"
 
-#include "test/Builders.h"
-
-#include <gtest/gtest.h>
 #include <sstream>
 #include <string>
 
@@ -31,7 +29,11 @@
             .addSimple(u"@android:id/class", ResourceId(0x01020000))
             .build();
 
-    JavaClassGenerator generator(table.get(), {});
+    std::unique_ptr<IAaptContext> context = test::ContextBuilder()
+            .addSymbolSource(util::make_unique<ResourceTableSymbolSource>(table.get()))
+            .setNameManglerPolicy(NameManglerPolicy{ u"android" })
+            .build();
+    JavaClassGenerator generator(context.get(), table.get(), {});
 
     std::stringstream out;
     EXPECT_FALSE(generator.generate(u"android", &out));
@@ -48,7 +50,11 @@
                               .build())
             .build();
 
-    JavaClassGenerator generator(table.get(), {});
+    std::unique_ptr<IAaptContext> context = test::ContextBuilder()
+            .addSymbolSource(util::make_unique<ResourceTableSymbolSource>(table.get()))
+            .setNameManglerPolicy(NameManglerPolicy{ u"android" })
+            .build();
+    JavaClassGenerator generator(context.get(), table.get(), {});
 
     std::stringstream out;
     EXPECT_TRUE(generator.generate(u"android", &out));
@@ -72,7 +78,11 @@
             .addSimple(u"@android:id/com.foo$two", ResourceId(0x01020001))
             .build();
 
-    JavaClassGenerator generator(table.get(), {});
+    std::unique_ptr<IAaptContext> context = test::ContextBuilder()
+            .addSymbolSource(util::make_unique<ResourceTableSymbolSource>(table.get()))
+            .setNameManglerPolicy(NameManglerPolicy{ u"android" })
+            .build();
+    JavaClassGenerator generator(context.get(), table.get(), {});
     std::stringstream out;
     ASSERT_TRUE(generator.generate(u"android", u"com.android.internal", &out));
 
@@ -90,7 +100,11 @@
             .addSimple(u"@android:^attr-private/one", ResourceId(0x01010000))
             .build();
 
-    JavaClassGenerator generator(table.get(), {});
+    std::unique_ptr<IAaptContext> context = test::ContextBuilder()
+            .addSymbolSource(util::make_unique<ResourceTableSymbolSource>(table.get()))
+            .setNameManglerPolicy(NameManglerPolicy{ u"android" })
+            .build();
+    JavaClassGenerator generator(context.get(), table.get(), {});
     std::stringstream out;
     ASSERT_TRUE(generator.generate(u"android", &out));
 
@@ -110,10 +124,15 @@
             .setSymbolState(u"@android:id/two", ResourceId(0x01020001), SymbolState::kPrivate)
             .build();
 
+    std::unique_ptr<IAaptContext> context = test::ContextBuilder()
+            .addSymbolSource(util::make_unique<ResourceTableSymbolSource>(table.get()))
+            .setNameManglerPolicy(NameManglerPolicy{ u"android" })
+            .build();
+
     JavaClassGeneratorOptions options;
     options.types = JavaClassGeneratorOptions::SymbolTypes::kPublic;
     {
-        JavaClassGenerator generator(table.get(), options);
+        JavaClassGenerator generator(context.get(), table.get(), options);
         std::stringstream out;
         ASSERT_TRUE(generator.generate(u"android", &out));
         std::string output = out.str();
@@ -124,7 +143,7 @@
 
     options.types = JavaClassGeneratorOptions::SymbolTypes::kPublicPrivate;
     {
-        JavaClassGenerator generator(table.get(), options);
+        JavaClassGenerator generator(context.get(), table.get(), options);
         std::stringstream out;
         ASSERT_TRUE(generator.generate(u"android", &out));
         std::string output = out.str();
@@ -135,7 +154,7 @@
 
     options.types = JavaClassGeneratorOptions::SymbolTypes::kAll;
     {
-        JavaClassGenerator generator(table.get(), options);
+        JavaClassGenerator generator(context.get(), table.get(), options);
         std::stringstream out;
         ASSERT_TRUE(generator.generate(u"android", &out));
         std::string output = out.str();
@@ -189,7 +208,11 @@
                                   .build())
                 .build();
 
-    JavaClassGenerator generator(table.get(), {});
+    std::unique_ptr<IAaptContext> context = test::ContextBuilder()
+            .addSymbolSource(util::make_unique<ResourceTableSymbolSource>(table.get()))
+            .setNameManglerPolicy(NameManglerPolicy{ u"android" })
+            .build();
+    JavaClassGenerator generator(context.get(), table.get(), {});
 
     std::stringstream out;
     EXPECT_TRUE(generator.generate(u"android", &out));
@@ -207,8 +230,11 @@
     test::getValue<Id>(table.get(), u"@android:id/foo")
             ->setComment(std::u16string(u"This is a comment\n@deprecated"));
 
-    JavaClassGenerator generator(table.get(), {});
-
+    std::unique_ptr<IAaptContext> context = test::ContextBuilder()
+            .addSymbolSource(util::make_unique<ResourceTableSymbolSource>(table.get()))
+            .setNameManglerPolicy(NameManglerPolicy{ u"android" })
+            .build();
+    JavaClassGenerator generator(context.get(), table.get(), {});
     std::stringstream out;
     ASSERT_TRUE(generator.generate(u"android", &out));
     std::string actual = out.str();
@@ -227,7 +253,35 @@
 }
 
 TEST(JavaClassGeneratorTest, CommentsForStyleablesAndNestedAttributesArePresent) {
+    Attribute attr(false);
+    attr.setComment(StringPiece16(u"This is an attribute"));
 
+    Styleable styleable;
+    styleable.entries.push_back(Reference(test::parseNameOrDie(u"@android:attr/one")));
+    styleable.setComment(StringPiece16(u"This is a styleable"));
+
+    std::unique_ptr<ResourceTable> table = test::ResourceTableBuilder()
+            .setPackageId(u"android", 0x01)
+            .addValue(u"@android:attr/one", util::make_unique<Attribute>(attr))
+            .addValue(u"@android:styleable/Container",
+                      std::unique_ptr<Styleable>(styleable.clone(nullptr)))
+            .build();
+
+    std::unique_ptr<IAaptContext> context = test::ContextBuilder()
+            .addSymbolSource(util::make_unique<ResourceTableSymbolSource>(table.get()))
+            .setNameManglerPolicy(NameManglerPolicy{ u"android" })
+            .build();
+    JavaClassGeneratorOptions options;
+    options.useFinal = false;
+    JavaClassGenerator generator(context.get(), table.get(), options);
+    std::stringstream out;
+    ASSERT_TRUE(generator.generate(u"android", &out));
+    std::string actual = out.str();
+
+    EXPECT_NE(std::string::npos, actual.find("@attr name android:one"));
+    EXPECT_NE(std::string::npos, actual.find("@attr description"));
+    EXPECT_NE(std::string::npos, actual.find(util::utf16ToUtf8(attr.getComment())));
+    EXPECT_NE(std::string::npos, actual.find(util::utf16ToUtf8(styleable.getComment())));
 }
 
 } // namespace aapt
diff --git a/tools/aapt2/link/Link.cpp b/tools/aapt2/link/Link.cpp
index d83f6def..b84074d 100644
--- a/tools/aapt2/link/Link.cpp
+++ b/tools/aapt2/link/Link.cpp
@@ -62,7 +62,9 @@
     std::set<std::u16string> extraJavaPackages;
     Maybe<std::string> generateProguardRulesPath;
     bool noAutoVersion = false;
+    bool noVersionVectors = false;
     bool staticLib = false;
+    bool noStaticLibPackages = false;
     bool generateNonFinalIds = false;
     bool outputToDirectory = false;
     bool autoAddOverlay = false;
@@ -74,37 +76,58 @@
     TableSplitterOptions tableSplitterOptions;
 };
 
-struct LinkContext : public IAaptContext {
-    StdErrDiagnostics mDiagnostics;
-    std::unique_ptr<NameMangler> mNameMangler;
-    std::u16string mCompilationPackage;
-    uint8_t mPackageId;
-    std::unique_ptr<ISymbolTable> mSymbols;
-    bool mVerbose = false;
+class LinkContext : public IAaptContext {
+public:
+    LinkContext() : mNameMangler({}) {
+    }
 
     IDiagnostics* getDiagnostics() override {
         return &mDiagnostics;
     }
 
     NameMangler* getNameMangler() override {
-        return mNameMangler.get();
+        return &mNameMangler;
     }
 
-    StringPiece16 getCompilationPackage() override {
+    void setNameManglerPolicy(const NameManglerPolicy& policy) {
+        mNameMangler = NameMangler(policy);
+    }
+
+    const std::u16string& getCompilationPackage() override {
         return mCompilationPackage;
     }
 
+    void setCompilationPackage(const StringPiece16& packageName) {
+        mCompilationPackage = packageName.toString();
+    }
+
     uint8_t getPackageId() override {
         return mPackageId;
     }
 
-    ISymbolTable* getExternalSymbols() override {
-        return mSymbols.get();
+    void setPackageId(uint8_t id) {
+        mPackageId = id;
+    }
+
+    SymbolTable* getExternalSymbols() override {
+        return &mSymbols;
     }
 
     bool verbose() override {
         return mVerbose;
     }
+
+    void setVerbose(bool val) {
+        mVerbose = val;
+    }
+
+private:
+    StdErrDiagnostics mDiagnostics;
+    NameMangler mNameMangler;
+    std::u16string mCompilationPackage;
+    uint8_t mPackageId = 0x0;
+    SymbolTable mSymbols;
+    bool mVerbose = false;
 };
 
 static bool copyFileToArchive(io::IFile* file, const std::string& outPath,
@@ -117,11 +140,19 @@
         return false;
     }
 
-    CompiledFileInputStream inputStream(data->data(), data->size());
-    if (!inputStream.CompiledFile()) {
-        context->getDiagnostics()->error(DiagMessage(file->getSource())
-                                         << "invalid compiled file header");
-        return false;
+    const uint8_t* buffer = reinterpret_cast<const uint8_t*>(data->data());
+    size_t bufferSize = data->size();
+
+    // If the file ends with .flat, we must strip off the CompiledFileHeader from it.
+    if (util::stringEndsWith<char>(file->getSource().path, ".flat")) {
+        CompiledFileInputStream inputStream(data->data(), data->size());
+        if (!inputStream.CompiledFile()) {
+            context->getDiagnostics()->error(DiagMessage(file->getSource())
+                                             << "invalid compiled file header");
+            return false;
+        }
+        buffer = reinterpret_cast<const uint8_t*>(inputStream.data());
+        bufferSize = inputStream.size();
     }
 
     if (context->verbose()) {
@@ -129,8 +160,7 @@
     }
 
     if (writer->startEntry(outPath, compressionFlags)) {
-        if (writer->writeEntry(reinterpret_cast<const uint8_t*>(inputStream.data()),
-                               inputStream.size())) {
+        if (writer->writeEntry(buffer, bufferSize)) {
             if (writer->finishEntry()) {
                 return true;
             }
@@ -156,7 +186,7 @@
         DiagMessage msg;
         msg << "writing " << path << " to archive";
         if (maxSdkLevel) {
-            msg << " maxSdkLevel=" << maxSdkLevel.value();
+            msg << " maxSdkLevel=" << maxSdkLevel.value() << " keepRawValues=" << keepRawValues;
         }
         context->getDiagnostics()->note(msg);
     }
@@ -248,6 +278,7 @@
 
 struct ResourceFileFlattenerOptions {
     bool noAutoVersion = false;
+    bool noVersionVectors = false;
     bool keepRawValues = false;
     bool doNotCompressAnything = false;
     std::vector<std::string> extensionsToNotCompress;
@@ -267,14 +298,13 @@
         io::IFile* fileToCopy;
         std::unique_ptr<xml::XmlResource> xmlToFlatten;
         std::string dstPath;
+        bool skipVersion = false;
     };
 
     uint32_t getCompressionFlags(const StringPiece& str);
 
-    std::unique_ptr<xml::XmlResource> linkAndVersionXmlFile(const ResourceEntry* entry,
-                                                            const ResourceFile& fileDesc,
-                                                            io::IFile* file,
-                                                            ResourceTable* table);
+    bool linkAndVersionXmlFile(const ResourceEntry* entry, const ResourceFile& fileDesc,
+                               io::IFile* file, ResourceTable* table, FileOperation* outFileOp);
 
     ResourceFileFlattenerOptions mOptions;
     IAaptContext* mContext;
@@ -294,11 +324,11 @@
     return ArchiveEntry::kCompress;
 }
 
-std::unique_ptr<xml::XmlResource> ResourceFileFlattener::linkAndVersionXmlFile(
-        const ResourceEntry* entry,
-        const ResourceFile& fileDesc,
-        io::IFile* file,
-        ResourceTable* table) {
+bool ResourceFileFlattener::linkAndVersionXmlFile(const ResourceEntry* entry,
+                                                  const ResourceFile& fileDesc,
+                                                  io::IFile* file,
+                                                  ResourceTable* table,
+                                                  FileOperation* outFileOp) {
     const StringPiece srcPath = file->getSource().path;
     if (mContext->verbose()) {
         mContext->getDiagnostics()->note(DiagMessage() << "linking " << srcPath);
@@ -307,51 +337,67 @@
     std::unique_ptr<io::IData> data = file->openAsData();
     if (!data) {
         mContext->getDiagnostics()->error(DiagMessage(file->getSource()) << "failed to open file");
-        return {};
+        return false;
     }
 
-    std::unique_ptr<xml::XmlResource> xmlRes;
     if (util::stringEndsWith<char>(srcPath, ".flat")) {
-        xmlRes = loadBinaryXmlSkipFileExport(file->getSource(), data->data(), data->size(),
-                                             mContext->getDiagnostics());
+        outFileOp->xmlToFlatten = loadBinaryXmlSkipFileExport(file->getSource(),
+                                                              data->data(), data->size(),
+                                                              mContext->getDiagnostics());
     } else {
-        xmlRes = xml::inflate(data->data(), data->size(), mContext->getDiagnostics(),
-                              file->getSource());
+        outFileOp->xmlToFlatten = xml::inflate(data->data(), data->size(),
+                                               mContext->getDiagnostics(),
+                                               file->getSource());
     }
 
-    if (!xmlRes) {
-        return {};
+    if (!outFileOp->xmlToFlatten) {
+        return false;
     }
 
     // Copy the the file description header.
-    xmlRes->file = fileDesc;
+    outFileOp->xmlToFlatten->file = fileDesc;
 
     XmlReferenceLinker xmlLinker;
-    if (!xmlLinker.consume(mContext, xmlRes.get())) {
-        return {};
+    if (!xmlLinker.consume(mContext, outFileOp->xmlToFlatten.get())) {
+        return false;
     }
 
-    if (!proguard::collectProguardRules(xmlRes->file.source, xmlRes.get(), mKeepSet)) {
-        return {};
+    if (!proguard::collectProguardRules(outFileOp->xmlToFlatten->file.source,
+                                        outFileOp->xmlToFlatten.get(), mKeepSet)) {
+        return false;
     }
 
     if (!mOptions.noAutoVersion) {
+        if (mOptions.noVersionVectors) {
+            // Skip this if it is a vector or animated-vector.
+            xml::Element* el = xml::findRootElement(outFileOp->xmlToFlatten.get());
+            if (el && el->namespaceUri.empty()) {
+                if (el->name == u"vector" || el->name == u"animated-vector") {
+                    // We are NOT going to version this file.
+                    outFileOp->skipVersion = true;
+                    return true;
+                }
+            }
+        }
+
         // Find the first SDK level used that is higher than this defined config and
         // not superseded by a lower or equal SDK level resource.
         for (int sdkLevel : xmlLinker.getSdkLevels()) {
-            if (sdkLevel > xmlRes->file.config.sdkVersion) {
-                if (!shouldGenerateVersionedResource(entry, xmlRes->file.config, sdkLevel)) {
+            if (sdkLevel > outFileOp->xmlToFlatten->file.config.sdkVersion) {
+                if (!shouldGenerateVersionedResource(entry, outFileOp->xmlToFlatten->file.config,
+                                                     sdkLevel)) {
                     // If we shouldn't generate a versioned resource, stop checking.
                     break;
                 }
 
-                ResourceFile versionedFileDesc = xmlRes->file;
-                versionedFileDesc.config.sdkVersion = sdkLevel;
+                ResourceFile versionedFileDesc = outFileOp->xmlToFlatten->file;
+                versionedFileDesc.config.sdkVersion = (uint16_t) sdkLevel;
 
                 if (mContext->verbose()) {
                     mContext->getDiagnostics()->note(DiagMessage(versionedFileDesc.source)
                                                      << "auto-versioning resource from config '"
-                                                     << xmlRes->file.config << "' -> '"
+                                                     << outFileOp->xmlToFlatten->file.config
+                                                     << "' -> '"
                                                      << versionedFileDesc.config << "'");
                 }
 
@@ -365,13 +411,13 @@
                                                                  file,
                                                                  mContext->getDiagnostics());
                 if (!added) {
-                    return {};
+                    return false;
                 }
                 break;
             }
         }
     }
-    return xmlRes;
+    return true;
 }
 
 /**
@@ -415,9 +461,7 @@
                         fileDesc.config = configValue->config;
                         fileDesc.name = ResourceName(pkg->name, type->type, entry->name);
                         fileDesc.source = fileRef->getSource();
-                        fileOp.xmlToFlatten = linkAndVersionXmlFile(entry.get(), fileDesc,
-                                                                    file, table);
-                        if (!fileOp.xmlToFlatten) {
+                        if (!linkAndVersionXmlFile(entry.get(), fileDesc, file, table, &fileOp)) {
                             error = true;
                             continue;
                         }
@@ -447,7 +491,7 @@
 
                 if (fileOp.xmlToFlatten) {
                     Maybe<size_t> maxSdkLevel;
-                    if (!mOptions.noAutoVersion) {
+                    if (!mOptions.noAutoVersion && !fileOp.skipVersion) {
                         maxSdkLevel = std::max<size_t>(config.sdkVersion, 1u);
                     }
 
@@ -474,39 +518,61 @@
 class LinkCommand {
 public:
     LinkCommand(LinkContext* context, const LinkOptions& options) :
-            mOptions(options), mContext(context), mFinalTable(), mFileCollection(nullptr) {
-        std::unique_ptr<io::FileCollection> fileCollection =
-                util::make_unique<io::FileCollection>();
-
-        // Get a pointer to the FileCollection for convenience, but it will be owned by the vector.
-        mFileCollection = fileCollection.get();
-
-        // Move it to the collection.
-        mCollections.push_back(std::move(fileCollection));
+            mOptions(options), mContext(context), mFinalTable(),
+            mFileCollection(util::make_unique<io::FileCollection>()) {
     }
 
     /**
      * Creates a SymbolTable that loads symbols from the various APKs and caches the
      * results for faster lookup.
      */
-    std::unique_ptr<ISymbolTable> createSymbolTableFromIncludePaths() {
-        AssetManagerSymbolTableBuilder builder;
+    bool loadSymbolsFromIncludePaths() {
+        std::unique_ptr<AssetManagerSymbolSource> assetSource =
+                util::make_unique<AssetManagerSymbolSource>();
         for (const std::string& path : mOptions.includePaths) {
             if (mContext->verbose()) {
                 mContext->getDiagnostics()->note(DiagMessage(path) << "loading include path");
             }
 
-            std::unique_ptr<android::AssetManager> assetManager =
-                    util::make_unique<android::AssetManager>();
-            int32_t cookie = 0;
-            if (!assetManager->addAssetPath(android::String8(path.data(), path.size()), &cookie)) {
+            // First try to load the file as a static lib.
+            std::string errorStr;
+            std::unique_ptr<ResourceTable> staticInclude = loadStaticLibrary(path, &errorStr);
+            if (staticInclude) {
+                if (!mOptions.staticLib) {
+                    // Can't include static libraries when not building a static library.
+                    mContext->getDiagnostics()->error(
+                            DiagMessage(path) << "can't include static library when building app");
+                    return false;
+                }
+
+                // If we are using --no-static-lib-packages, we need to rename the package of this
+                // table to our compilation package.
+                if (mOptions.noStaticLibPackages) {
+                    if (ResourceTablePackage* pkg = staticInclude->findPackageById(0x7f)) {
+                        pkg->name = mContext->getCompilationPackage();
+                    }
+                }
+
+                mContext->getExternalSymbols()->appendSource(
+                        util::make_unique<ResourceTableSymbolSource>(staticInclude.get()));
+
+                mStaticTableIncludes.push_back(std::move(staticInclude));
+
+            } else if (!errorStr.empty()) {
+                // We had an error with reading, so fail.
+                mContext->getDiagnostics()->error(DiagMessage(path) << errorStr);
+                return false;
+            }
+
+            if (!assetSource->addAssetPath(path)) {
                 mContext->getDiagnostics()->error(
                         DiagMessage(path) << "failed to load include path");
-                return {};
+                return false;
             }
-            builder.add(std::move(assetManager));
         }
-        return builder.build();
+
+        mContext->getExternalSymbols()->appendSource(std::move(assetSource));
+        return true;
     }
 
     Maybe<AppInfo> extractAppInfoFromManifest(xml::XmlResource* xmlRes) {
@@ -571,6 +637,35 @@
         return !error;
     }
 
+    /**
+     * Returns true if no IDs have been set, false otherwise.
+     */
+    bool verifyNoIdsSet() {
+        for (const auto& package : mFinalTable.packages) {
+            for (const auto& type : package->types) {
+                if (type->id) {
+                    mContext->getDiagnostics()->error(DiagMessage() << "type " << type->type
+                                                      << " has ID " << std::hex
+                                                      << (int) type->id.value()
+                                                      << std::dec << " assigned");
+                    return false;
+                }
+
+                for (const auto& entry : type->entries) {
+                    if (entry->id) {
+                        ResourceNameRef resName(package->name, type->type, entry->name);
+                        mContext->getDiagnostics()->error(DiagMessage() << "entry " << resName
+                                                          << " has ID " << std::hex
+                                                          << (int) entry->id.value()
+                                                          << std::dec << " assigned");
+                        return false;
+                    }
+                }
+            }
+        }
+        return true;
+    }
+
     std::unique_ptr<IArchiveWriter> makeArchiveWriter() {
         if (mOptions.outputToDirectory) {
             return createDirectoryArchiveWriter(mContext->getDiagnostics(), mOptions.outputPath);
@@ -599,6 +694,32 @@
         return false;
     }
 
+    bool flattenTableToPb(ResourceTable* table, IArchiveWriter* writer) {
+        // Create the file/zip entry.
+        if (!writer->startEntry("resources.arsc.flat", 0)) {
+            mContext->getDiagnostics()->error(DiagMessage() << "failed to open");
+            return false;
+        }
+
+        std::unique_ptr<pb::ResourceTable> pbTable = serializeTableToPb(table);
+
+        // Wrap our IArchiveWriter with an adaptor that implements the ZeroCopyOutputStream
+        // interface.
+        {
+            google::protobuf::io::CopyingOutputStreamAdaptor adaptor(writer);
+
+            if (!pbTable->SerializeToZeroCopyStream(&adaptor)) {
+                mContext->getDiagnostics()->error(DiagMessage() << "failed to write");
+                return false;
+            }
+        }
+
+        if (!writer->finishEntry()) {
+            mContext->getDiagnostics()->error(DiagMessage() << "failed to finish entry");
+            return false;
+        }
+        return true;
+    }
 
     bool writeJavaFile(ResourceTable* table, const StringPiece16& packageNameToGenerate,
                        const StringPiece16& outPackage, JavaClassGeneratorOptions javaOptions) {
@@ -608,20 +729,31 @@
 
         std::string outPath = mOptions.generateJavaClassPath.value();
         file::appendPath(&outPath, file::packageToPath(util::utf16ToUtf8(outPackage)));
-        file::mkdirs(outPath);
+        if (!file::mkdirs(outPath)) {
+            mContext->getDiagnostics()->error(
+                    DiagMessage() << "failed to create directory '" << outPath << "'");
+            return false;
+        }
+
         file::appendPath(&outPath, "R.java");
 
         std::ofstream fout(outPath, std::ofstream::binary);
         if (!fout) {
-            mContext->getDiagnostics()->error(DiagMessage() << strerror(errno));
+            mContext->getDiagnostics()->error(
+                    DiagMessage() << "failed writing to '" << outPath << "': " << strerror(errno));
             return false;
         }
 
-        JavaClassGenerator generator(table, javaOptions);
+        JavaClassGenerator generator(mContext, table, javaOptions);
         if (!generator.generate(packageNameToGenerate, outPackage, &fout)) {
             mContext->getDiagnostics()->error(DiagMessage(outPath) << generator.getError());
             return false;
         }
+
+        if (!fout) {
+            mContext->getDiagnostics()->error(
+                    DiagMessage() << "failed writing to '" << outPath << "': " << strerror(errno));
+        }
         return true;
     }
 
@@ -633,12 +765,18 @@
         std::string outPath = mOptions.generateJavaClassPath.value();
         file::appendPath(&outPath,
                          file::packageToPath(util::utf16ToUtf8(mContext->getCompilationPackage())));
-        file::mkdirs(outPath);
+        if (!file::mkdirs(outPath)) {
+            mContext->getDiagnostics()->error(
+                    DiagMessage() << "failed to create directory '" << outPath << "'");
+            return false;
+        }
+
         file::appendPath(&outPath, "Manifest.java");
 
         std::ofstream fout(outPath, std::ofstream::binary);
         if (!fout) {
-            mContext->getDiagnostics()->error(DiagMessage() << strerror(errno));
+            mContext->getDiagnostics()->error(
+                    DiagMessage() << "failed writing to '" << outPath << "': " << strerror(errno));
             return false;
         }
 
@@ -649,7 +787,8 @@
         }
 
         if (!fout) {
-            mContext->getDiagnostics()->error(DiagMessage() << strerror(errno));
+            mContext->getDiagnostics()->error(
+                    DiagMessage() << "failed writing to '" << outPath << "': " << strerror(errno));
             return false;
         }
         return true;
@@ -660,32 +799,108 @@
             return true;
         }
 
-        std::ofstream fout(mOptions.generateProguardRulesPath.value(), std::ofstream::binary);
+        const std::string& outPath = mOptions.generateProguardRulesPath.value();
+        std::ofstream fout(outPath, std::ofstream::binary);
         if (!fout) {
-            mContext->getDiagnostics()->error(DiagMessage() << strerror(errno));
+            mContext->getDiagnostics()->error(
+                    DiagMessage() << "failed to open '" << outPath << "': " << strerror(errno));
             return false;
         }
 
         proguard::writeKeepSet(&fout, keepSet);
         if (!fout) {
-            mContext->getDiagnostics()->error(DiagMessage() << strerror(errno));
+            mContext->getDiagnostics()->error(
+                    DiagMessage() << "failed writing to '" << outPath << "': " << strerror(errno));
             return false;
         }
         return true;
     }
 
-    bool mergeStaticLibrary(const std::string& input) {
-        // TODO(adamlesinski): Load resources from a static library APK and merge the table into
-        // TableMerger.
-        mContext->getDiagnostics()->warn(DiagMessage()
-                                        << "linking static libraries not supported yet: "
-                                        << input);
+    std::unique_ptr<ResourceTable> loadStaticLibrary(const std::string& input,
+                                                     std::string* outError) {
+        std::unique_ptr<io::ZipFileCollection> collection = io::ZipFileCollection::create(
+                input, outError);
+        if (!collection) {
+            return {};
+        }
+        return loadTablePbFromCollection(collection.get());
+    }
+
+    std::unique_ptr<ResourceTable> loadTablePbFromCollection(io::IFileCollection* collection) {
+        io::IFile* file = collection->findFile("resources.arsc.flat");
+        if (!file) {
+            return {};
+        }
+
+        std::unique_ptr<io::IData> data = file->openAsData();
+        return loadTableFromPb(file->getSource(), data->data(), data->size(),
+                               mContext->getDiagnostics());
+    }
+
+    bool mergeStaticLibrary(const std::string& input, bool override) {
+        if (mContext->verbose()) {
+            mContext->getDiagnostics()->note(DiagMessage() << "merging static library " << input);
+        }
+
+        std::string errorStr;
+        std::unique_ptr<io::ZipFileCollection> collection =
+                io::ZipFileCollection::create(input, &errorStr);
+        if (!collection) {
+            mContext->getDiagnostics()->error(DiagMessage(input) << errorStr);
+            return false;
+        }
+
+        std::unique_ptr<ResourceTable> table = loadTablePbFromCollection(collection.get());
+        if (!table) {
+            mContext->getDiagnostics()->error(DiagMessage(input) << "invalid static library");
+            return false;
+        }
+
+        ResourceTablePackage* pkg = table->findPackageById(0x7f);
+        if (!pkg) {
+            mContext->getDiagnostics()->error(DiagMessage(input)
+                                              << "static library has no package");
+            return false;
+        }
+
+        bool result;
+        if (mOptions.noStaticLibPackages) {
+            // Merge all resources as if they were in the compilation package. This is the old
+            // behaviour of aapt.
+
+            // Add the package to the set of --extra-packages so we emit an R.java for each
+            // library package.
+            if (!pkg->name.empty()) {
+                mOptions.extraJavaPackages.insert(pkg->name);
+            }
+
+            pkg->name = u"";
+            if (override) {
+                result = mTableMerger->mergeOverlay(Source(input), table.get(), collection.get());
+            } else {
+                result = mTableMerger->merge(Source(input), table.get(), collection.get());
+            }
+
+        } else {
+            // This is the proper way to merge libraries, where the package name is preserved
+            // and resource names are mangled.
+            result = mTableMerger->mergeAndMangle(Source(input), pkg->name, table.get(),
+                                                  collection.get());
+        }
+
+        if (!result) {
+            return false;
+        }
+
+        // Make sure to move the collection into the set of IFileCollections.
+        mCollections.push_back(std::move(collection));
         return true;
     }
 
     bool mergeResourceTable(io::IFile* file, bool override) {
         if (mContext->verbose()) {
-            mContext->getDiagnostics()->note(DiagMessage() << "linking " << file->getSource());
+            mContext->getDiagnostics()->note(DiagMessage() << "merging resource table "
+                                             << file->getSource());
         }
 
         std::unique_ptr<io::IData> data = file->openAsData();
@@ -711,13 +926,14 @@
         return result;
     }
 
-    bool mergeCompiledFile(io::IFile* file, std::unique_ptr<ResourceFile> fileDesc, bool overlay) {
+    bool mergeCompiledFile(io::IFile* file, ResourceFile* fileDesc, bool override) {
         if (mContext->verbose()) {
-            mContext->getDiagnostics()->note(DiagMessage() << "adding " << file->getSource());
+            mContext->getDiagnostics()->note(DiagMessage() << "merging compiled file "
+                                             << file->getSource());
         }
 
         bool result = false;
-        if (overlay) {
+        if (override) {
             result = mTableMerger->mergeFileOverlay(*fileDesc, file);
         } else {
             result = mTableMerger->mergeFile(*fileDesc, file);
@@ -730,7 +946,7 @@
         // Add the exports of this file to the table.
         for (SourcedResourceName& exportedSymbol : fileDesc->exportedSymbols) {
             if (exportedSymbol.name.package.empty()) {
-                exportedSymbol.name.package = mContext->getCompilationPackage().toString();
+                exportedSymbol.name.package = mContext->getCompilationPackage();
             }
 
             ResourceNameRef resName = exportedSymbol.name;
@@ -743,11 +959,9 @@
 
             std::unique_ptr<Id> id = util::make_unique<Id>();
             id->setSource(fileDesc->source.withLine(exportedSymbol.line));
-            bool result = mFinalTable.addResourceAllowMangled(resName,
-                                                              ConfigDescription::defaultConfig(),
-                                                              std::string(),
-                                                              std::move(id),
-                                                              mContext->getDiagnostics());
+            bool result = mFinalTable.addResourceAllowMangled(
+                    resName, ConfigDescription::defaultConfig(), std::string(), std::move(id),
+                    mContext->getDiagnostics());
             if (!result) {
                 return false;
             }
@@ -756,12 +970,21 @@
     }
 
     /**
-     * Creates an io::IFileCollection from the ZIP archive and processes the files within.
+     * Takes a path to load as a ZIP file and merges the files within into the master ResourceTable.
+     * If override is true, conflicting resources are allowed to override each other, in order of
+     * last seen.
+     *
+     * An io::IFileCollection is created from the ZIP file and added to the set of
+     * io::IFileCollections that are open.
      */
     bool mergeArchive(const std::string& input, bool override) {
+        if (mContext->verbose()) {
+            mContext->getDiagnostics()->note(DiagMessage() << "merging archive " << input);
+        }
+
         std::string errorStr;
-        std::unique_ptr<io::ZipFileCollection> collection = io::ZipFileCollection::create(
-                input, &errorStr);
+        std::unique_ptr<io::ZipFileCollection> collection =
+                io::ZipFileCollection::create(input, &errorStr);
         if (!collection) {
             mContext->getDiagnostics()->error(DiagMessage(input) << errorStr);
             return false;
@@ -769,7 +992,7 @@
 
         bool error = false;
         for (auto iter = collection->iterator(); iter->hasNext(); ) {
-            if (!processFile(iter->next(), override)) {
+            if (!mergeFile(iter->next(), override)) {
                 error = true;
             }
         }
@@ -779,22 +1002,45 @@
         return !error;
     }
 
-    bool processFile(const std::string& path, bool override) {
+    /**
+     * Takes a path to load and merge into the master ResourceTable. If override is true,
+     * conflicting resources are allowed to override each other, in order of last seen.
+     *
+     * If the file path ends with .flata, .jar, .jack, or .zip the file is treated as ZIP archive
+     * and the files within are merged individually.
+     *
+     * Otherwise the files is processed on its own.
+     */
+    bool mergePath(const std::string& path, bool override) {
         if (util::stringEndsWith<char>(path, ".flata") ||
                 util::stringEndsWith<char>(path, ".jar") ||
                 util::stringEndsWith<char>(path, ".jack") ||
                 util::stringEndsWith<char>(path, ".zip")) {
             return mergeArchive(path, override);
+        } else if (util::stringEndsWith<char>(path, ".apk")) {
+            return mergeStaticLibrary(path, override);
         }
 
         io::IFile* file = mFileCollection->insertFile(path);
-        return processFile(file, override);
+        return mergeFile(file, override);
     }
 
-    bool processFile(io::IFile* file, bool override) {
+    /**
+     * Takes a file to load and merge into the master ResourceTable. If override is true,
+     * conflicting resources are allowed to override each other, in order of last seen.
+     *
+     * If the file ends with .arsc.flat, then it is loaded as a ResourceTable and merged into the
+     * master ResourceTable. If the file ends with .flat, then it is treated like a compiled file
+     * and the header data is read and merged into the final ResourceTable.
+     *
+     * All other file types are ignored. This is because these files could be coming from a zip,
+     * where we could have other files like classes.dex.
+     */
+    bool mergeFile(io::IFile* file, bool override) {
         const Source& src = file->getSource();
         if (util::stringEndsWith<char>(src.path, ".arsc.flat")) {
             return mergeResourceTable(file, override);
+
         } else if (util::stringEndsWith<char>(src.path, ".flat")){
             // Try opening the file and looking for an Export header.
             std::unique_ptr<io::IData> data = file->openAsData();
@@ -806,9 +1052,8 @@
             std::unique_ptr<ResourceFile> resourceFile = loadFileExportHeader(
                     src, data->data(), data->size(), mContext->getDiagnostics());
             if (resourceFile) {
-                return mergeCompiledFile(file, std::move(resourceFile), override);
+                return mergeCompiledFile(file, resourceFile.get(), override);
             }
-
             return false;
         }
 
@@ -826,32 +1071,30 @@
         }
 
         if (Maybe<AppInfo> maybeAppInfo = extractAppInfoFromManifest(manifestXml.get())) {
-            mContext->mCompilationPackage = maybeAppInfo.value().package;
+            mContext->setCompilationPackage(maybeAppInfo.value().package);
         } else {
             mContext->getDiagnostics()->error(DiagMessage(mOptions.manifestPath)
                                              << "no package specified in <manifest> tag");
             return 1;
         }
 
-        if (!util::isJavaPackageName(mContext->mCompilationPackage)) {
+        if (!util::isJavaPackageName(mContext->getCompilationPackage())) {
             mContext->getDiagnostics()->error(DiagMessage(mOptions.manifestPath)
                                              << "invalid package name '"
-                                             << mContext->mCompilationPackage
+                                             << mContext->getCompilationPackage()
                                              << "'");
             return 1;
         }
 
-        mContext->mNameMangler = util::make_unique<NameMangler>(
-                NameManglerPolicy{ mContext->mCompilationPackage });
+        mContext->setNameManglerPolicy(NameManglerPolicy{ mContext->getCompilationPackage() });
 
-        if (mContext->mCompilationPackage == u"android") {
-            mContext->mPackageId = 0x01;
+        if (mContext->getCompilationPackage() == u"android") {
+            mContext->setPackageId(0x01);
         } else {
-            mContext->mPackageId = 0x7f;
+            mContext->setPackageId(0x7f);
         }
 
-        mContext->mSymbols = createSymbolTableFromIncludePaths();
-        if (!mContext->mSymbols) {
+        if (!loadSymbolsFromIncludePaths()) {
             return 1;
         }
 
@@ -861,20 +1104,21 @@
 
         if (mContext->verbose()) {
             mContext->getDiagnostics()->note(
-                    DiagMessage() << "linking package '" << mContext->mCompilationPackage << "' "
-                                  << "with package ID " << std::hex << (int) mContext->mPackageId);
+                    DiagMessage() << "linking package '" << mContext->getCompilationPackage()
+                                  << "' with package ID " << std::hex
+                                  << (int) mContext->getPackageId());
         }
 
 
         for (const std::string& input : inputFiles) {
-            if (!processFile(input, false)) {
+            if (!mergePath(input, false)) {
                 mContext->getDiagnostics()->error(DiagMessage() << "failed parsing input");
                 return 1;
             }
         }
 
         for (const std::string& input : mOptions.overlayFiles) {
-            if (!processFile(input, true)) {
+            if (!mergePath(input, true)) {
                 mContext->getDiagnostics()->error(DiagMessage() << "failed parsing overlays");
                 return 1;
             }
@@ -893,20 +1137,28 @@
             }
         }
 
-        {
+        if (!mOptions.staticLib) {
+            // Assign IDs if we are building a regular app.
             IdAssigner idAssigner;
             if (!idAssigner.consume(mContext, &mFinalTable)) {
                 mContext->getDiagnostics()->error(DiagMessage() << "failed assigning IDs");
                 return 1;
             }
+        } else {
+            // Static libs are merged with other apps, and ID collisions are bad, so verify that
+            // no IDs have been set.
+            if (!verifyNoIdsSet()) {
+                return 1;
+            }
         }
 
-        mContext->mNameMangler = util::make_unique<NameMangler>(NameManglerPolicy{
-                mContext->mCompilationPackage, mTableMerger->getMergedPackages() });
-        mContext->mSymbols = JoinedSymbolTableBuilder()
-                .addSymbolTable(util::make_unique<SymbolTableWrapper>(&mFinalTable))
-                .addSymbolTable(std::move(mContext->mSymbols))
-                .build();
+        // Add the names to mangle based on our source merge earlier.
+        mContext->setNameManglerPolicy(NameManglerPolicy{
+                mContext->getCompilationPackage(), mTableMerger->getMergedPackages() });
+
+        // Add our table to the symbol table.
+        mContext->getExternalSymbols()->prependSource(
+                        util::make_unique<ResourceTableSymbolSource>(&mFinalTable));
 
         {
             ReferenceLinker linker;
@@ -915,20 +1167,32 @@
                 return 1;
             }
 
-            ProductFilter productFilter(mOptions.products);
-            if (!productFilter.consume(mContext, &mFinalTable)) {
-                mContext->getDiagnostics()->error(DiagMessage() << "failed stripping products");
-                return 1;
-            }
+            if (mOptions.staticLib) {
+                if (!mOptions.products.empty()) {
+                    mContext->getDiagnostics()->warn(
+                            DiagMessage() << "can't select products when building static library");
+                }
 
-            // TODO(adamlesinski): Actually pass in split constraints and handle splits at the file
-            // level.
-            TableSplitter tableSplitter({}, mOptions.tableSplitterOptions);
-            if (!tableSplitter.verifySplitConstraints(mContext)) {
-                return 1;
-            }
+                if (mOptions.tableSplitterOptions.configFilter != nullptr ||
+                        mOptions.tableSplitterOptions.preferredDensity) {
+                    mContext->getDiagnostics()->warn(
+                            DiagMessage() << "can't strip resources when building static library");
+                }
+            } else {
+                ProductFilter productFilter(mOptions.products);
+                if (!productFilter.consume(mContext, &mFinalTable)) {
+                    mContext->getDiagnostics()->error(DiagMessage() << "failed stripping products");
+                    return 1;
+                }
 
-            tableSplitter.splitTable(&mFinalTable);
+                // TODO(adamlesinski): Actually pass in split constraints and handle splits at the file
+                // level.
+                TableSplitter tableSplitter({}, mOptions.tableSplitterOptions);
+                if (!tableSplitter.verifySplitConstraints(mContext)) {
+                    return 1;
+                }
+                tableSplitter.splitTable(&mFinalTable);
+            }
         }
 
         proguard::KeepSet proguardKeepSet;
@@ -949,7 +1213,7 @@
             // AndroidManifest.xml has no resource name, but the CallSite is built from the name
             // (aka, which package the AndroidManifest.xml is coming from).
             // So we give it a package name so it can see local resources.
-            manifestXml->file.name.package = mContext->getCompilationPackage().toString();
+            manifestXml->file.name.package = mContext->getCompilationPackage();
 
             XmlReferenceLinker manifestLinker;
             if (manifestLinker.consume(mContext, manifestXml.get())) {
@@ -986,6 +1250,7 @@
         fileFlattenerOptions.doNotCompressAnything = mOptions.doNotCompressAnything;
         fileFlattenerOptions.extensionsToNotCompress = mOptions.extensionsToNotCompress;
         fileFlattenerOptions.noAutoVersion = mOptions.noAutoVersion;
+        fileFlattenerOptions.noVersionVectors = mOptions.noVersionVectors;
         ResourceFileFlattener fileFlattener(fileFlattenerOptions, mContext, &proguardKeepSet);
 
         if (!fileFlattener.flatten(&mFinalTable, archiveWriter.get())) {
@@ -1001,9 +1266,18 @@
             }
         }
 
-        if (!flattenTable(&mFinalTable, archiveWriter.get())) {
-            mContext->getDiagnostics()->error(DiagMessage() << "failed to write resources.arsc");
-            return 1;
+        if (mOptions.staticLib) {
+            if (!flattenTableToPb(&mFinalTable, archiveWriter.get())) {
+                mContext->getDiagnostics()->error(DiagMessage()
+                                                  << "failed to write resources.arsc.flat");
+                return 1;
+            }
+        } else {
+            if (!flattenTable(&mFinalTable, archiveWriter.get())) {
+                mContext->getDiagnostics()->error(DiagMessage()
+                                                  << "failed to write resources.arsc");
+                return 1;
+            }
         }
 
         if (mOptions.generateJavaClassPath) {
@@ -1065,14 +1339,17 @@
     LinkContext* mContext;
     ResourceTable mFinalTable;
 
-    ResourceTable mLocalFileTable;
     std::unique_ptr<TableMerger> mTableMerger;
 
     // A pointer to the FileCollection representing the filesystem (not archives).
-    io::FileCollection* mFileCollection;
+    std::unique_ptr<io::FileCollection> mFileCollection;
 
     // A vector of IFileCollections. This is mainly here to keep ownership of the collections.
     std::vector<std::unique_ptr<io::IFileCollection>> mCollections;
+
+    // A vector of ResourceTables. This is here to retain ownership, so that the SymbolTable
+    // can use these.
+    std::vector<std::unique_ptr<ResourceTable>> mStaticTableIncludes;
 };
 
 int link(const std::vector<StringPiece>& args) {
@@ -1089,6 +1366,7 @@
     Maybe<std::string> productList;
     bool legacyXFlag = false;
     bool requireLocalization = false;
+    bool verbose = false;
     Flags flags = Flags()
             .requiredFlag("-o", "Output path", &options.outputPath)
             .requiredFlag("--manifest", "Path to the Android manifest to build",
@@ -1104,6 +1382,10 @@
             .optionalSwitch("--no-auto-version",
                             "Disables automatic style and layout SDK versioning",
                             &options.noAutoVersion)
+            .optionalSwitch("--no-version-vectors",
+                            "Disables automatic versioning of vector drawables. Use this only\n"
+                            "when building with vector drawable support library",
+                            &options.noVersionVectors)
             .optionalSwitch("-x", "Legacy flag that specifies to use the package identifier 0x01",
                             &legacyXFlag)
             .optionalSwitch("-z", "Require localization of strings marked 'suggested'",
@@ -1127,6 +1409,9 @@
             .optionalFlag("--version-name", "Version name to inject into the AndroidManifest.xml "
                           "if none is present", &versionName)
             .optionalSwitch("--static-lib", "Generate a static Android library", &options.staticLib)
+            .optionalSwitch("--no-static-lib-packages",
+                            "Merge all library resources under the app's package",
+                            &options.noStaticLibPackages)
             .optionalSwitch("--non-final-ids", "Generates R.java without the final modifier.\n"
                             "This is implied when --static-lib is specified.",
                             &options.generateNonFinalIds)
@@ -1148,12 +1433,16 @@
                           &renameInstrumentationTargetPackage)
             .optionalFlagList("-0", "File extensions not to compress",
                               &options.extensionsToNotCompress)
-            .optionalSwitch("-v", "Enables verbose logging", &context.mVerbose);
+            .optionalSwitch("-v", "Enables verbose logging", &verbose);
 
     if (!flags.parse("aapt2 link", args, &std::cerr)) {
         return 1;
     }
 
+    if (verbose) {
+        context.setVerbose(verbose);
+    }
+
     if (privateSymbolsPackage) {
         options.privateSymbols = util::utf8ToUtf16(privateSymbolsPackage.value());
     }
@@ -1252,6 +1541,12 @@
         options.tableSplitterOptions.preferredDensity = preferredDensityConfig.density;
     }
 
+    // Turn off auto versioning for static-libs.
+    if (options.staticLib) {
+        options.noAutoVersion = true;
+        options.noVersionVectors = true;
+    }
+
     LinkCommand cmd(&context, options);
     return cmd.run(flags.getArgs());
 }
diff --git a/tools/aapt2/link/ManifestFixer_test.cpp b/tools/aapt2/link/ManifestFixer_test.cpp
index f40fbfb..18c47df 100644
--- a/tools/aapt2/link/ManifestFixer_test.cpp
+++ b/tools/aapt2/link/ManifestFixer_test.cpp
@@ -30,7 +30,7 @@
                 .setCompilationPackage(u"android")
                 .setPackageId(0x01)
                 .setNameManglerPolicy(NameManglerPolicy{ u"android" })
-                .setSymbolTable(test::StaticSymbolTableBuilder()
+                .addSymbolSource(test::StaticSymbolSourceBuilder()
                         .addSymbol(u"@android:attr/package", ResourceId(0x01010000),
                                    test::AttributeBuilder()
                                         .setTypeMask(android::ResTable_map::TYPE_STRING)
diff --git a/tools/aapt2/link/ReferenceLinker.cpp b/tools/aapt2/link/ReferenceLinker.cpp
index ef3fe4f..66eb0df 100644
--- a/tools/aapt2/link/ReferenceLinker.cpp
+++ b/tools/aapt2/link/ReferenceLinker.cpp
@@ -14,9 +14,8 @@
  * limitations under the License.
  */
 
-#include "ReferenceLinker.h"
-
 #include "Diagnostics.h"
+#include "ReferenceLinker.h"
 #include "ResourceTable.h"
 #include "ResourceUtils.h"
 #include "ResourceValues.h"
@@ -43,45 +42,10 @@
  * NOTE: All of the entries in the ResourceTable must be assigned IDs.
  */
 class ReferenceLinkerVisitor : public ValueVisitor {
-private:
-    IAaptContext* mContext;
-    ISymbolTable* mSymbols;
-    xml::IPackageDeclStack* mPackageDecls;
-    StringPool* mStringPool;
-    CallSite* mCallSite;
-    bool mError = false;
-
-    /**
-     * Transform a RawString value into a more specific, appropriate value, based on the
-     * Attribute. If a non RawString value is passed in, this is an identity transform.
-     */
-    std::unique_ptr<Item> parseValueWithAttribute(std::unique_ptr<Item> value,
-                                                  const Attribute* attr) {
-        if (RawString* rawString = valueCast<RawString>(value.get())) {
-            std::unique_ptr<Item> transformed =
-                    ResourceUtils::parseItemForAttribute(*rawString->value, attr);
-
-            // If we could not parse as any specific type, try a basic STRING.
-            if (!transformed && (attr->typeMask & android::ResTable_map::TYPE_STRING)) {
-                util::StringBuilder stringBuilder;
-                stringBuilder.append(*rawString->value);
-                if (stringBuilder) {
-                    transformed = util::make_unique<String>(
-                            mStringPool->makeRef(stringBuilder.str()));
-                }
-            }
-
-            if (transformed) {
-                return transformed;
-            }
-        };
-        return value;
-    }
-
 public:
     using ValueVisitor::visit;
 
-    ReferenceLinkerVisitor(IAaptContext* context, ISymbolTable* symbols, StringPool* stringPool,
+    ReferenceLinkerVisitor(IAaptContext* context, SymbolTable* symbols, StringPool* stringPool,
                            xml::IPackageDeclStack* decl,CallSite* callSite) :
             mContext(context), mSymbols(symbols), mPackageDecls(decl), mStringPool(stringPool),
             mCallSite(callSite) {
@@ -114,10 +78,11 @@
                                             &transformedReference);
 
             // Find the attribute in the symbol table and check if it is visible from this callsite.
-            const ISymbolTable::Symbol* symbol = ReferenceLinker::resolveAttributeCheckVisibility(
+            const SymbolTable::Symbol* symbol = ReferenceLinker::resolveAttributeCheckVisibility(
                     transformedReference, mContext->getNameMangler(), mSymbols, mCallSite, &errStr);
             if (symbol) {
                 // Assign our style key the correct ID.
+                // The ID may not exist.
                 entry.key.id = symbol->id;
 
                 // Try to convert the value to a more specific, typed value based on the
@@ -156,6 +121,41 @@
     bool hasError() {
         return mError;
     }
+
+private:
+    IAaptContext* mContext;
+    SymbolTable* mSymbols;
+    xml::IPackageDeclStack* mPackageDecls;
+    StringPool* mStringPool;
+    CallSite* mCallSite;
+    bool mError = false;
+
+    /**
+     * Transform a RawString value into a more specific, appropriate value, based on the
+     * Attribute. If a non RawString value is passed in, this is an identity transform.
+     */
+    std::unique_ptr<Item> parseValueWithAttribute(std::unique_ptr<Item> value,
+                                                  const Attribute* attr) {
+        if (RawString* rawString = valueCast<RawString>(value.get())) {
+            std::unique_ptr<Item> transformed =
+                    ResourceUtils::parseItemForAttribute(*rawString->value, attr);
+
+            // If we could not parse as any specific type, try a basic STRING.
+            if (!transformed && (attr->typeMask & android::ResTable_map::TYPE_STRING)) {
+                util::StringBuilder stringBuilder;
+                stringBuilder.append(*rawString->value);
+                if (stringBuilder) {
+                    transformed = util::make_unique<String>(
+                            mStringPool->makeRef(stringBuilder.str()));
+                }
+            }
+
+            if (transformed) {
+                return transformed;
+            }
+        };
+        return value;
+    }
 };
 
 } // namespace
@@ -164,13 +164,13 @@
  * The symbol is visible if it is public, or if the reference to it is requesting private access
  * or if the callsite comes from the same package.
  */
-bool ReferenceLinker::isSymbolVisible(const ISymbolTable::Symbol& symbol, const Reference& ref,
+bool ReferenceLinker::isSymbolVisible(const SymbolTable::Symbol& symbol, const Reference& ref,
                                       const CallSite& callSite) {
     if (!symbol.isPublic && !ref.privateReference) {
         if (ref.name) {
             return callSite.resource.package == ref.name.value().package;
-        } else if (ref.id) {
-            return ref.id.value().packageId() == symbol.id.packageId();
+        } else if (ref.id && symbol.id) {
+            return ref.id.value().packageId() == symbol.id.value().packageId();
         } else {
             return false;
         }
@@ -178,9 +178,9 @@
     return true;
 }
 
-const ISymbolTable::Symbol* ReferenceLinker::resolveSymbol(const Reference& reference,
-                                                           NameMangler* mangler,
-                                                           ISymbolTable* symbols) {
+const SymbolTable::Symbol* ReferenceLinker::resolveSymbol(const Reference& reference,
+                                                          NameMangler* mangler,
+                                                          SymbolTable* symbols) {
     if (reference.name) {
         Maybe<ResourceName> mangled = mangler->mangleName(reference.name.value());
         return symbols->findByName(mangled ? mangled.value() : reference.name.value());
@@ -191,10 +191,10 @@
     }
 }
 
-const ISymbolTable::Symbol* ReferenceLinker::resolveSymbolCheckVisibility(
-        const Reference& reference, NameMangler* nameMangler, ISymbolTable* symbols,
+const SymbolTable::Symbol* ReferenceLinker::resolveSymbolCheckVisibility(
+        const Reference& reference, NameMangler* nameMangler, SymbolTable* symbols,
         CallSite* callSite, std::string* outError) {
-    const ISymbolTable::Symbol* symbol = resolveSymbol(reference, nameMangler, symbols);
+    const SymbolTable::Symbol* symbol = resolveSymbol(reference, nameMangler, symbols);
     if (!symbol) {
         if (outError) *outError = "not found";
         return nullptr;
@@ -207,12 +207,12 @@
     return symbol;
 }
 
-const ISymbolTable::Symbol* ReferenceLinker::resolveAttributeCheckVisibility(
-        const Reference& reference, NameMangler* nameMangler, ISymbolTable* symbols,
+const SymbolTable::Symbol* ReferenceLinker::resolveAttributeCheckVisibility(
+        const Reference& reference, NameMangler* nameMangler, SymbolTable* symbols,
         CallSite* callSite, std::string* outError) {
-    const ISymbolTable::Symbol* symbol = resolveSymbolCheckVisibility(reference, nameMangler,
-                                                                      symbols, callSite,
-                                                                      outError);
+    const SymbolTable::Symbol* symbol = resolveSymbolCheckVisibility(reference, nameMangler,
+                                                                     symbols, callSite,
+                                                                     outError);
     if (!symbol) {
         return nullptr;
     }
@@ -226,10 +226,10 @@
 
 Maybe<xml::AaptAttribute> ReferenceLinker::compileXmlAttribute(const Reference& reference,
                                                                NameMangler* nameMangler,
-                                                               ISymbolTable* symbols,
+                                                               SymbolTable* symbols,
                                                                CallSite* callSite,
                                                                std::string* outError) {
-    const ISymbolTable::Symbol* symbol = resolveSymbol(reference, nameMangler, symbols);
+    const SymbolTable::Symbol* symbol = resolveSymbol(reference, nameMangler, symbols);
     if (!symbol) {
         return {};
     }
@@ -256,7 +256,7 @@
 }
 
 bool ReferenceLinker::linkReference(Reference* reference, IAaptContext* context,
-                                    ISymbolTable* symbols, xml::IPackageDeclStack* decls,
+                                    SymbolTable* symbols, xml::IPackageDeclStack* decls,
                                     CallSite* callSite) {
     assert(reference);
     assert(reference->name || reference->id);
@@ -266,9 +266,12 @@
                                     &transformedReference);
 
     std::string errStr;
-    const ISymbolTable::Symbol* s = resolveSymbolCheckVisibility(
+    const SymbolTable::Symbol* s = resolveSymbolCheckVisibility(
             transformedReference, context->getNameMangler(), symbols, callSite, &errStr);
     if (s) {
+        // The ID may not exist. This is fine because of the possibility of building against
+        // libraries without assigned IDs.
+        // Ex: Linking against own resources when building a static library.
         reference->id = s->id;
         return true;
     }
diff --git a/tools/aapt2/link/ReferenceLinker.h b/tools/aapt2/link/ReferenceLinker.h
index a0eb00c..7993aaf 100644
--- a/tools/aapt2/link/ReferenceLinker.h
+++ b/tools/aapt2/link/ReferenceLinker.h
@@ -38,36 +38,36 @@
     /**
      * Returns true if the symbol is visible by the reference and from the callsite.
      */
-    static bool isSymbolVisible(const ISymbolTable::Symbol& symbol, const Reference& ref,
+    static bool isSymbolVisible(const SymbolTable::Symbol& symbol, const Reference& ref,
                                 const CallSite& callSite);
 
     /**
      * Performs name mangling and looks up the resource in the symbol table. Returns nullptr
      * if the symbol was not found.
      */
-    static const ISymbolTable::Symbol* resolveSymbol(const Reference& reference,
-                                                     NameMangler* mangler, ISymbolTable* symbols);
+    static const SymbolTable::Symbol* resolveSymbol(const Reference& reference,
+                                                    NameMangler* mangler, 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. outError holds
      * the error message.
      */
-    static const ISymbolTable::Symbol* resolveSymbolCheckVisibility(const Reference& reference,
-                                                                    NameMangler* nameMangler,
-                                                                    ISymbolTable* symbols,
-                                                                    CallSite* callSite,
-                                                                    std::string* outError);
+    static const SymbolTable::Symbol* resolveSymbolCheckVisibility(const Reference& reference,
+                                                                   NameMangler* nameMangler,
+                                                                   SymbolTable* symbols,
+                                                                   CallSite* callSite,
+                                                                   std::string* outError);
 
     /**
      * Same as resolveSymbolCheckVisibility(), but also makes sure the symbol is an attribute.
      * That is, the return value will have a non-null value for ISymbolTable::Symbol::attribute.
      */
-    static const ISymbolTable::Symbol* resolveAttributeCheckVisibility(const Reference& reference,
-                                                                       NameMangler* nameMangler,
-                                                                       ISymbolTable* symbols,
-                                                                       CallSite* callSite,
-                                                                       std::string* outError);
+    static const SymbolTable::Symbol* resolveAttributeCheckVisibility(const Reference& reference,
+                                                                      NameMangler* nameMangler,
+                                                                      SymbolTable* symbols,
+                                                                      CallSite* callSite,
+                                                                      std::string* outError);
 
     /**
      * Resolves the attribute reference and returns an xml::AaptAttribute if successful.
@@ -75,7 +75,7 @@
      */
     static Maybe<xml::AaptAttribute> compileXmlAttribute(const Reference& reference,
                                                          NameMangler* nameMangler,
-                                                         ISymbolTable* symbols,
+                                                         SymbolTable* symbols,
                                                          CallSite* callSite,
                                                          std::string* outError);
 
@@ -92,7 +92,7 @@
      * to the reference at the callsite, the reference is updated with an ID.
      * Returns false on failure, and an error message is logged to the IDiagnostics in the context.
      */
-    static bool linkReference(Reference* reference, IAaptContext* context, ISymbolTable* symbols,
+    static bool linkReference(Reference* reference, IAaptContext* context, SymbolTable* symbols,
                               xml::IPackageDeclStack* decls, CallSite* callSite);
 
     /**
diff --git a/tools/aapt2/link/ReferenceLinker_test.cpp b/tools/aapt2/link/ReferenceLinker_test.cpp
index 8d324fe..76b2309 100644
--- a/tools/aapt2/link/ReferenceLinker_test.cpp
+++ b/tools/aapt2/link/ReferenceLinker_test.cpp
@@ -15,12 +15,9 @@
  */
 
 #include "link/ReferenceLinker.h"
-#include "process/SymbolTable.h"
+#include "test/Test.h"
 
-#include "test/Builders.h"
-#include "test/Context.h"
-
-#include <gtest/gtest.h>
+using android::ResTable_map;
 
 namespace aapt {
 
@@ -41,12 +38,10 @@
             .setCompilationPackage(u"com.app.test")
             .setPackageId(0x7f)
             .setNameManglerPolicy(NameManglerPolicy{ u"com.app.test" })
-            .setSymbolTable(JoinedSymbolTableBuilder()
-                            .addSymbolTable(util::make_unique<SymbolTableWrapper>(table.get()))
-                            .addSymbolTable(test::StaticSymbolTableBuilder()
-                                    .addPublicSymbol(u"@android:string/ok", ResourceId(0x01040034))
-                                    .build())
-                            .build())
+            .addSymbolSource(util::make_unique<ResourceTableSymbolSource>(table.get()))
+            .addSymbolSource(test::StaticSymbolSourceBuilder()
+                                     .addPublicSymbol(u"@android:string/ok", ResourceId(0x01040034))
+                                     .build())
             .build();
 
     ReferenceLinker linker;
@@ -91,19 +86,20 @@
             .setCompilationPackage(u"com.app.test")
             .setPackageId(0x7f)
             .setNameManglerPolicy(NameManglerPolicy{ u"com.app.test" })
-            .setSymbolTable(test::StaticSymbolTableBuilder()
-                    .addPublicSymbol(u"@android:style/Theme.Material", ResourceId(0x01060000))
-                    .addPublicSymbol(u"@android:attr/foo", ResourceId(0x01010001),
-                               test::AttributeBuilder()
-                                    .setTypeMask(android::ResTable_map::TYPE_COLOR)
-                                    .build())
-                    .addPublicSymbol(u"@android:attr/bar", ResourceId(0x01010002),
-                               test::AttributeBuilder()
-                                    .setTypeMask(android::ResTable_map::TYPE_FLAGS)
-                                    .addItem(u"one", 0x01)
-                                    .addItem(u"two", 0x02)
-                                    .build())
-                    .build())
+            .addSymbolSource(test::StaticSymbolSourceBuilder()
+                                     .addPublicSymbol(u"@android:style/Theme.Material",
+                                                      ResourceId(0x01060000))
+                                     .addPublicSymbol(u"@android:attr/foo", ResourceId(0x01010001),
+                                                      test::AttributeBuilder()
+                                                              .setTypeMask(ResTable_map::TYPE_COLOR)
+                                                              .build())
+                                     .addPublicSymbol(u"@android:attr/bar", ResourceId(0x01010002),
+                                                      test::AttributeBuilder()
+                                                              .setTypeMask(ResTable_map::TYPE_FLAGS)
+                                                              .addItem(u"one", 0x01)
+                                                              .addItem(u"two", 0x02)
+                                                              .build())
+                                     .build())
             .build();
 
     ReferenceLinker linker;
@@ -131,11 +127,13 @@
             .setCompilationPackage(u"com.app.test")
             .setPackageId(0x7f)
             .setNameManglerPolicy(NameManglerPolicy{ u"com.app.test", { u"com.android.support" } })
-            .setSymbolTable(test::StaticSymbolTableBuilder()
-                    .addPublicSymbol(u"@com.app.test:attr/com.android.support$foo",
-                               ResourceId(0x7f010000), test::AttributeBuilder()
-                                        .setTypeMask(android::ResTable_map::TYPE_COLOR).build())
-                    .build())
+            .addSymbolSource(test::StaticSymbolSourceBuilder()
+                                     .addPublicSymbol(u"@com.app.test:attr/com.android.support$foo",
+                                                      ResourceId(0x7f010000),
+                                                      test::AttributeBuilder()
+                                                              .setTypeMask(ResTable_map::TYPE_COLOR)
+                                                              .build())
+                                     .build())
             .build();
 
     std::unique_ptr<ResourceTable> table = test::ResourceTableBuilder()
@@ -167,12 +165,10 @@
             .setCompilationPackage(u"com.app.test")
             .setPackageId(0x7f)
             .setNameManglerPolicy(NameManglerPolicy{ u"com.app.test" })
-            .setSymbolTable(JoinedSymbolTableBuilder()
-                            .addSymbolTable(util::make_unique<SymbolTableWrapper>(table.get()))
-                            .addSymbolTable(test::StaticSymbolTableBuilder()
-                                    .addSymbol(u"@android:string/hidden", ResourceId(0x01040034))
-                                    .build())
-                            .build())
+            .addSymbolSource(util::make_unique<ResourceTableSymbolSource>(table.get()))
+            .addSymbolSource(test::StaticSymbolSourceBuilder()
+                                     .addSymbol(u"@android:string/hidden", ResourceId(0x01040034))
+                                     .build())
             .build();
 
     ReferenceLinker linker;
@@ -190,13 +186,12 @@
             .setCompilationPackage(u"com.app.test")
             .setPackageId(0x7f)
             .setNameManglerPolicy(NameManglerPolicy{ u"com.app.test", { u"com.app.lib" } })
-            .setSymbolTable(JoinedSymbolTableBuilder()
-                            .addSymbolTable(util::make_unique<SymbolTableWrapper>(table.get()))
-                            .addSymbolTable(test::StaticSymbolTableBuilder()
-                                    .addSymbol(u"@com.app.test:string/com.app.lib$hidden",
-                                               ResourceId(0x7f040034))
-                                    .build())
-                            .build())
+            .addSymbolSource(util::make_unique<ResourceTableSymbolSource>(table.get()))
+            .addSymbolSource(test::StaticSymbolSourceBuilder()
+                                     .addSymbol(u"@com.app.test:string/com.app.lib$hidden",
+                                                ResourceId(0x7f040034))
+                                     .build())
+
             .build();
 
     ReferenceLinker linker;
@@ -215,15 +210,14 @@
             .setCompilationPackage(u"com.app.test")
             .setPackageId(0x7f)
             .setNameManglerPolicy(NameManglerPolicy{ u"com.app.test" })
-            .setSymbolTable(JoinedSymbolTableBuilder()
-                            .addSymbolTable(util::make_unique<SymbolTableWrapper>(table.get()))
-                            .addSymbolTable(test::StaticSymbolTableBuilder()
-                                    .addSymbol(u"@android:attr/hidden", ResourceId(0x01010001),
-                                               test::AttributeBuilder()
-                                                    .setTypeMask(android::ResTable_map::TYPE_COLOR)
-                                                    .build())
-                                    .build())
-                            .build())
+            .addSymbolSource(util::make_unique<ResourceTableSymbolSource>(table.get()))
+            .addSymbolSource(test::StaticSymbolSourceBuilder()
+                                     .addSymbol(u"@android:attr/hidden", ResourceId(0x01010001),
+                                                test::AttributeBuilder()
+                                                        .setTypeMask(
+                                                                android::ResTable_map::TYPE_COLOR)
+                                                        .build())
+                                     .build())
             .build();
 
     ReferenceLinker linker;
diff --git a/tools/aapt2/link/TableMerger.cpp b/tools/aapt2/link/TableMerger.cpp
index 5f11745..7471e15 100644
--- a/tools/aapt2/link/TableMerger.cpp
+++ b/tools/aapt2/link/TableMerger.cpp
@@ -34,10 +34,21 @@
     assert(mMasterPackage && "package name or ID already taken");
 }
 
+bool TableMerger::merge(const Source& src, ResourceTable* table,
+                        io::IFileCollection* collection) {
+    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 */, mOptions.autoAddOverlay);
+}
+
 /**
  * This will merge packages with the same package name (or no package name).
  */
 bool TableMerger::mergeImpl(const Source& src, ResourceTable* table,
+                            io::IFileCollection* collection,
                             bool overlay, bool allowNew) {
     const uint8_t desiredPackageId = mContext->getPackageId();
 
@@ -51,26 +62,36 @@
         }
 
         if (package->name.empty() || mContext->getCompilationPackage() == package->name) {
+            FileMergeCallback callback;
+            if (collection) {
+                callback = [&](const ResourceNameRef& name, const ConfigDescription& config,
+                               FileReference* newFile, FileReference* oldFile) -> bool {
+                    // The old file's path points inside the APK, so we can use it as is.
+                    io::IFile* f = collection->findFile(util::utf16ToUtf8(*oldFile->path));
+                    if (!f) {
+                        mContext->getDiagnostics()->error(DiagMessage(src) << "file '"
+                                                          << *oldFile->path
+                                                          << "' not found");
+                        return false;
+                    }
+
+                    newFile->file = f;
+                    return true;
+                };
+            }
+
             // Merge here. Once the entries are merged and mangled, any references to
             // them are still valid. This is because un-mangled references are
             // mangled, then looked up at resolution time.
             // Also, when linking, we convert references with no package name to use
             // the compilation package name.
             error |= !doMerge(src, table, package.get(),
-                              false /* mangle */, overlay, allowNew, {});
+                              false /* mangle */, overlay, allowNew, callback);
         }
     }
     return !error;
 }
 
-bool TableMerger::merge(const Source& src, ResourceTable* table) {
-    return mergeImpl(src, table, false /* overlay */, true /* allow new */);
-}
-
-bool TableMerger::mergeOverlay(const Source& src, ResourceTable* table) {
-    return mergeImpl(src, table, true /* overlay */, mOptions.autoAddOverlay);
-}
-
 /**
  * This will merge and mangle resources from a static library.
  */
diff --git a/tools/aapt2/link/TableMerger.h b/tools/aapt2/link/TableMerger.h
index b3c22dd..80c2a5e 100644
--- a/tools/aapt2/link/TableMerger.h
+++ b/tools/aapt2/link/TableMerger.h
@@ -65,13 +65,17 @@
 
     /**
      * Merges resources from the same or empty package. This is for local sources.
+     * An io::IFileCollection is optional and used to find the referenced Files and process them.
      */
-    bool merge(const Source& src, ResourceTable* table);
+    bool merge(const Source& src, ResourceTable* table,
+               io::IFileCollection* collection = nullptr);
 
     /**
      * Merges resources from an overlay ResourceTable.
+     * An io::IFileCollection is optional and used to find the referenced Files and process them.
      */
-    bool mergeOverlay(const Source& src, ResourceTable* table);
+    bool mergeOverlay(const Source& src, ResourceTable* table,
+                      io::IFileCollection* collection = nullptr);
 
     /**
      * Merges resources from the given package, mangling the name. This is for static libraries.
@@ -104,7 +108,7 @@
 
     bool mergeFileImpl(const ResourceFile& fileDesc, io::IFile* file, bool overlay);
 
-    bool mergeImpl(const Source& src, ResourceTable* srcTable,
+    bool mergeImpl(const Source& src, ResourceTable* srcTable, io::IFileCollection* collection,
                    bool overlay, bool allowNew);
 
     bool doMerge(const Source& src, ResourceTable* srcTable, ResourceTablePackage* srcPackage,
diff --git a/tools/aapt2/link/XmlReferenceLinker.cpp b/tools/aapt2/link/XmlReferenceLinker.cpp
index a26d763..568bc74 100644
--- a/tools/aapt2/link/XmlReferenceLinker.cpp
+++ b/tools/aapt2/link/XmlReferenceLinker.cpp
@@ -34,17 +34,10 @@
  * as needed.
  */
 class ReferenceVisitor : public ValueVisitor {
-private:
-    IAaptContext* mContext;
-    ISymbolTable* mSymbols;
-    xml::IPackageDeclStack* mDecls;
-    CallSite* mCallSite;
-    bool mError;
-
 public:
     using ValueVisitor::visit;
 
-    ReferenceVisitor(IAaptContext* context, ISymbolTable* symbols, xml::IPackageDeclStack* decls,
+    ReferenceVisitor(IAaptContext* context, SymbolTable* symbols, xml::IPackageDeclStack* decls,
                      CallSite* callSite) :
              mContext(context), mSymbols(symbols), mDecls(decls), mCallSite(callSite),
              mError(false) {
@@ -59,25 +52,23 @@
     bool hasError() const {
         return mError;
     }
+
+private:
+    IAaptContext* mContext;
+    SymbolTable* mSymbols;
+    xml::IPackageDeclStack* mDecls;
+    CallSite* mCallSite;
+    bool mError;
 };
 
 /**
  * Visits each xml Element and compiles the attributes within.
  */
 class XmlVisitor : public xml::PackageAwareVisitor {
-private:
-    IAaptContext* mContext;
-    ISymbolTable* mSymbols;
-    Source mSource;
-    std::set<int>* mSdkLevelsFound;
-    CallSite* mCallSite;
-    ReferenceVisitor mReferenceVisitor;
-    bool mError = false;
-
 public:
     using xml::PackageAwareVisitor::visit;
 
-    XmlVisitor(IAaptContext* context, ISymbolTable* symbols, const Source& source,
+    XmlVisitor(IAaptContext* context, SymbolTable* symbols, const Source& source,
                std::set<int>* sdkLevelsFound, CallSite* callSite) :
             mContext(context), mSymbols(symbols), mSource(source), mSdkLevelsFound(sdkLevelsFound),
             mCallSite(callSite), mReferenceVisitor(context, symbols, this, callSite) {
@@ -105,10 +96,13 @@
 
                 // Convert the string value into a compiled Value if this is a valid attribute.
                 if (attr.compiledAttribute) {
-                    // Record all SDK levels from which the attributes were defined.
-                    const int sdkLevel = findAttributeSdkLevel(attr.compiledAttribute.value().id);
-                    if (sdkLevel > 1) {
-                        mSdkLevelsFound->insert(sdkLevel);
+                    if (attr.compiledAttribute.value().id) {
+                        // Record all SDK levels from which the attributes were defined.
+                        const size_t sdkLevel = findAttributeSdkLevel(
+                                attr.compiledAttribute.value().id.value());
+                        if (sdkLevel > 1) {
+                            mSdkLevelsFound->insert(sdkLevel);
+                        }
                     }
 
                     const Attribute* attribute = &attr.compiledAttribute.value().attribute;
@@ -124,6 +118,7 @@
                                                     << *attribute);
                         mError = true;
                     }
+
                 } else {
                     mContext->getDiagnostics()->error(DiagMessage(source)
                                                       << "attribute '" << package << ":"
@@ -150,6 +145,15 @@
     bool hasError() {
         return mError || mReferenceVisitor.hasError();
     }
+
+private:
+    IAaptContext* mContext;
+    SymbolTable* mSymbols;
+    Source mSource;
+    std::set<int>* mSdkLevelsFound;
+    CallSite* mCallSite;
+    ReferenceVisitor mReferenceVisitor;
+    bool mError = false;
 };
 
 } // namespace
diff --git a/tools/aapt2/link/XmlReferenceLinker_test.cpp b/tools/aapt2/link/XmlReferenceLinker_test.cpp
index 3bfaf91..af9098b 100644
--- a/tools/aapt2/link/XmlReferenceLinker_test.cpp
+++ b/tools/aapt2/link/XmlReferenceLinker_test.cpp
@@ -14,12 +14,9 @@
  * limitations under the License.
  */
 
+#include <test/Context.h>
 #include "link/Linkers.h"
-
-#include "test/Builders.h"
-#include "test/Context.h"
-
-#include <gtest/gtest.h>
+#include "test/Test.h"
 
 namespace aapt {
 
@@ -30,7 +27,7 @@
                 .setCompilationPackage(u"com.app.test")
                 .setNameManglerPolicy(
                         NameManglerPolicy{ u"com.app.test", { u"com.android.support" } })
-                .setSymbolTable(test::StaticSymbolTableBuilder()
+                .addSymbolSource(test::StaticSymbolSourceBuilder()
                         .addPublicSymbol(u"@android:attr/layout_width", ResourceId(0x01010000),
                                    test::AttributeBuilder()
                                         .setTypeMask(android::ResTable_map::TYPE_ENUM |
@@ -92,14 +89,16 @@
                                                     u"layout_width");
     ASSERT_NE(xmlAttr, nullptr);
     AAPT_ASSERT_TRUE(xmlAttr->compiledAttribute);
-    EXPECT_EQ(xmlAttr->compiledAttribute.value().id, ResourceId(0x01010000));
+    AAPT_ASSERT_TRUE(xmlAttr->compiledAttribute.value().id);
+    EXPECT_EQ(xmlAttr->compiledAttribute.value().id.value(), ResourceId(0x01010000));
     ASSERT_NE(xmlAttr->compiledValue, nullptr);
     ASSERT_NE(valueCast<BinaryPrimitive>(xmlAttr->compiledValue.get()), nullptr);
 
     xmlAttr = viewEl->findAttribute(u"http://schemas.android.com/apk/res/android", u"background");
     ASSERT_NE(xmlAttr, nullptr);
     AAPT_ASSERT_TRUE(xmlAttr->compiledAttribute);
-    EXPECT_EQ(xmlAttr->compiledAttribute.value().id, ResourceId(0x01010001));
+    AAPT_ASSERT_TRUE(xmlAttr->compiledAttribute.value().id);
+    EXPECT_EQ(xmlAttr->compiledAttribute.value().id.value(), ResourceId(0x01010001));
     ASSERT_NE(xmlAttr->compiledValue, nullptr);
     Reference* ref = valueCast<Reference>(xmlAttr->compiledValue.get());
     ASSERT_NE(ref, nullptr);
@@ -163,7 +162,8 @@
             u"http://schemas.android.com/apk/res/com.android.support", u"colorAccent");
     ASSERT_NE(xmlAttr, nullptr);
     AAPT_ASSERT_TRUE(xmlAttr->compiledAttribute);
-    EXPECT_EQ(xmlAttr->compiledAttribute.value().id, ResourceId(0x7f010001));
+    AAPT_ASSERT_TRUE(xmlAttr->compiledAttribute.value().id);
+    EXPECT_EQ(xmlAttr->compiledAttribute.value().id.value(), ResourceId(0x7f010001));
     ASSERT_NE(valueCast<BinaryPrimitive>(xmlAttr->compiledValue.get()), nullptr);
 }
 
@@ -182,7 +182,8 @@
                                                     u"colorAccent");
     ASSERT_NE(xmlAttr, nullptr);
     AAPT_ASSERT_TRUE(xmlAttr->compiledAttribute);
-    EXPECT_EQ(xmlAttr->compiledAttribute.value().id, ResourceId(0x7f010000));
+    AAPT_ASSERT_TRUE(xmlAttr->compiledAttribute.value().id);
+    EXPECT_EQ(xmlAttr->compiledAttribute.value().id.value(), ResourceId(0x7f010000));
     Reference* ref = valueCast<Reference>(xmlAttr->compiledValue.get());
     ASSERT_NE(ref, nullptr);
     AAPT_ASSERT_TRUE(ref->name);
@@ -209,7 +210,8 @@
                                                     u"attr");
     ASSERT_NE(xmlAttr, nullptr);
     AAPT_ASSERT_TRUE(xmlAttr->compiledAttribute);
-    EXPECT_EQ(xmlAttr->compiledAttribute.value().id, ResourceId(0x01010002));
+    AAPT_ASSERT_TRUE(xmlAttr->compiledAttribute.value().id);
+    EXPECT_EQ(xmlAttr->compiledAttribute.value().id.value(), ResourceId(0x01010002));
     Reference* ref = valueCast<Reference>(xmlAttr->compiledValue.get());
     ASSERT_NE(ref, nullptr);
     AAPT_ASSERT_TRUE(ref->id);
@@ -223,7 +225,8 @@
     xmlAttr = viewEl->findAttribute(u"http://schemas.android.com/apk/res/com.app.test", u"attr");
     ASSERT_NE(xmlAttr, nullptr);
     AAPT_ASSERT_TRUE(xmlAttr->compiledAttribute);
-    EXPECT_EQ(xmlAttr->compiledAttribute.value().id, ResourceId(0x7f010002));
+    AAPT_ASSERT_TRUE(xmlAttr->compiledAttribute.value().id);
+    EXPECT_EQ(xmlAttr->compiledAttribute.value().id.value(), ResourceId(0x7f010002));
     ref = valueCast<Reference>(xmlAttr->compiledValue.get());
     ASSERT_NE(ref, nullptr);
     AAPT_ASSERT_TRUE(ref->id);
@@ -246,7 +249,8 @@
             u"http://schemas.android.com/apk/res/com.app.test", u"attr");
     ASSERT_NE(xmlAttr, nullptr);
     AAPT_ASSERT_TRUE(xmlAttr->compiledAttribute);
-    EXPECT_EQ(xmlAttr->compiledAttribute.value().id, ResourceId(0x7f010002));
+    AAPT_ASSERT_TRUE(xmlAttr->compiledAttribute.value().id);
+    EXPECT_EQ(xmlAttr->compiledAttribute.value().id.value(), ResourceId(0x7f010002));
     Reference* ref = valueCast<Reference>(xmlAttr->compiledValue.get());
     ASSERT_NE(ref, nullptr);
     AAPT_ASSERT_TRUE(ref->id);
diff --git a/tools/aapt2/process/IResourceTableConsumer.h b/tools/aapt2/process/IResourceTableConsumer.h
index 3a88044..9affb83 100644
--- a/tools/aapt2/process/IResourceTableConsumer.h
+++ b/tools/aapt2/process/IResourceTableConsumer.h
@@ -30,14 +30,14 @@
 namespace aapt {
 
 class ResourceTable;
-struct ISymbolTable;
+class SymbolTable;
 
 struct IAaptContext {
     virtual ~IAaptContext() = default;
 
-    virtual ISymbolTable* getExternalSymbols() = 0;
+    virtual SymbolTable* getExternalSymbols() = 0;
     virtual IDiagnostics* getDiagnostics() = 0;
-    virtual StringPiece16 getCompilationPackage() = 0;
+    virtual const std::u16string& getCompilationPackage() = 0;
     virtual uint8_t getPackageId() = 0;
     virtual NameMangler* getNameMangler() = 0;
     virtual bool verbose() = 0;
diff --git a/tools/aapt2/process/SymbolTable.cpp b/tools/aapt2/process/SymbolTable.cpp
index b6030a2..eaaf06f 100644
--- a/tools/aapt2/process/SymbolTable.cpp
+++ b/tools/aapt2/process/SymbolTable.cpp
@@ -25,11 +25,83 @@
 
 namespace aapt {
 
-const ISymbolTable::Symbol* SymbolTableWrapper::findByName(const ResourceName& name) {
+void SymbolTable::appendSource(std::unique_ptr<ISymbolSource> source) {
+    mSources.push_back(std::move(source));
+
+    // We do not clear the cache, because sources earlier in the list take precedent.
+}
+
+void SymbolTable::prependSource(std::unique_ptr<ISymbolSource> source) {
+    mSources.insert(mSources.begin(), std::move(source));
+
+    // We must clear the cache in case we did a lookup before adding this resource.
+    mCache.clear();
+}
+
+const SymbolTable::Symbol* SymbolTable::findByName(const ResourceName& name) {
     if (const std::shared_ptr<Symbol>& s = mCache.get(name)) {
         return s.get();
     }
 
+    // We did not find it in the cache, so look through the sources.
+    for (auto& symbolSource : mSources) {
+        std::unique_ptr<Symbol> symbol = symbolSource->findByName(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> sharedSymbol = std::shared_ptr<Symbol>(symbol.release());
+            mCache.put(name, sharedSymbol);
+
+            if (sharedSymbol->id) {
+                // The symbol has an ID, so we can also cache this!
+                mIdCache.put(sharedSymbol->id.value(), sharedSymbol);
+            }
+            return sharedSymbol.get();
+        }
+    }
+    return nullptr;
+}
+
+const SymbolTable::Symbol* SymbolTable::findById(ResourceId id) {
+    if (const std::shared_ptr<Symbol>& s = mIdCache.get(id)) {
+        return s.get();
+    }
+
+    // We did not find it in the cache, so look through the sources.
+    for (auto& symbolSource : mSources) {
+        std::unique_ptr<Symbol> symbol = symbolSource->findById(id);
+        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> sharedSymbol = std::shared_ptr<Symbol>(symbol.release());
+            mIdCache.put(id, sharedSymbol);
+            return sharedSymbol.get();
+        }
+    }
+    return nullptr;
+}
+
+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 successfull 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
+    // succeeded to lookup by ID. Subsequent lookups will miss then hit.
+    const SymbolTable::Symbol* symbol = nullptr;
+    if (ref.id) {
+        symbol = findById(ref.id.value());
+    }
+
+    if (ref.name && !symbol) {
+        symbol = findByName(ref.name.value());
+    }
+    return symbol;
+}
+
+std::unique_ptr<SymbolTable::Symbol> ResourceTableSymbolSource::findByName(
+        const ResourceName& name) {
     Maybe<ResourceTable::SearchResult> result = mTable->findResource(name);
     if (!result) {
         if (name.type == ResourceType::kAttr) {
@@ -41,40 +113,35 @@
 
     ResourceTable::SearchResult sr = result.value();
 
-    // If no ID exists, we treat the symbol as missing. SymbolTables are used to
-    // find symbols to link.
-    if (!sr.package->id || !sr.type->id || !sr.entry->id) {
-        return {};
-    }
-
-    std::shared_ptr<Symbol> symbol = std::make_shared<Symbol>();
-    symbol->id = ResourceId(sr.package->id.value(), sr.type->id.value(), sr.entry->id.value());
+    std::unique_ptr<SymbolTable::Symbol> symbol = util::make_unique<SymbolTable::Symbol>();
     symbol->isPublic = (sr.entry->symbolStatus.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());
+    }
+
     if (name.type == ResourceType::kAttr || name.type == ResourceType::kAttrPrivate) {
         const ConfigDescription kDefaultConfig;
         ResourceConfigValue* configValue = sr.entry->findValue(kDefaultConfig);
         if (configValue) {
             // This resource has an Attribute.
             if (Attribute* attr = valueCast<Attribute>(configValue->value.get())) {
-                symbol->attribute = util::make_unique<Attribute>(*attr);
+                symbol->attribute = std::make_shared<Attribute>(*attr);
             } else {
                 return {};
             }
         }
     }
-
-    if (name.type == ResourceType::kAttrPrivate) {
-        // Masquerade this entry as kAttr.
-        mCache.put(ResourceName(name.package, ResourceType::kAttr, name.entry), symbol);
-    } else {
-        mCache.put(name, symbol);
-    }
-    return symbol.get();
+    return symbol;
 }
 
-static std::shared_ptr<ISymbolTable::Symbol> lookupAttributeInTable(const android::ResTable& table,
-                                                                    ResourceId id) {
+bool AssetManagerSymbolSource::addAssetPath(const StringPiece& path) {
+    int32_t cookie = 0;
+    return mAssets.addAssetPath(android::String8(path.data(), path.size()), &cookie);
+}
+
+static std::unique_ptr<SymbolTable::Symbol> lookupAttributeInTable(const android::ResTable& table,
+                                                                   ResourceId id) {
     // Try as a bag.
     const android::ResTable::bag_entry* entry;
     ssize_t count = table.lockBag(id.id, &entry);
@@ -84,13 +151,13 @@
     }
 
     // We found a resource.
-    std::shared_ptr<ISymbolTable::Symbol> s = std::make_shared<ISymbolTable::Symbol>();
+    std::unique_ptr<SymbolTable::Symbol> s = util::make_unique<SymbolTable::Symbol>();
     s->id = id;
 
     // Check to see if it is an attribute.
     for (size_t i = 0; i < (size_t) count; i++) {
         if (entry[i].map.name.ident == android::ResTable_map::ATTR_TYPE) {
-            s->attribute = util::make_unique<Attribute>(false);
+            s->attribute = std::make_shared<Attribute>(false);
             s->attribute->typeMask = entry[i].map.value.data;
             break;
         }
@@ -138,43 +205,36 @@
     return s;
 }
 
-const ISymbolTable::Symbol* AssetManagerSymbolTableBuilder::AssetManagerSymbolTable::findByName(
+std::unique_ptr<SymbolTable::Symbol> AssetManagerSymbolSource::findByName(
         const ResourceName& name) {
-    if (const std::shared_ptr<Symbol>& s = mCache.get(name)) {
-        return s.get();
+    const android::ResTable& table = mAssets.getResources(false);
+    StringPiece16 typeStr = toString(name.type);
+    uint32_t typeSpecFlags = 0;
+    ResourceId resId = table.identifierForName(name.entry.data(), name.entry.size(),
+                                               typeStr.data(), typeStr.size(),
+                                               name.package.data(), name.package.size(),
+                                               &typeSpecFlags);
+    if (!resId.isValid()) {
+        return {};
     }
 
-    for (const auto& asset : mAssets) {
-        const android::ResTable& table = asset->getResources(false);
-        StringPiece16 typeStr = toString(name.type);
-        uint32_t typeSpecFlags = 0;
-        ResourceId resId = table.identifierForName(name.entry.data(), name.entry.size(),
-                                                   typeStr.data(), typeStr.size(),
-                                                   name.package.data(), name.package.size(),
-                                                   &typeSpecFlags);
-        if (!resId.isValid()) {
-            continue;
-        }
-
-        std::shared_ptr<Symbol> s;
-        if (name.type == ResourceType::kAttr) {
-            s = lookupAttributeInTable(table, resId);
-        } else {
-            s = std::make_shared<Symbol>();
-            s->id = resId;
-        }
-
-        if (s) {
-            s->isPublic = (typeSpecFlags & android::ResTable_typeSpec::SPEC_PUBLIC) != 0;
-            mCache.put(name, s);
-            return s.get();
-        }
+    std::unique_ptr<SymbolTable::Symbol> s;
+    if (name.type == ResourceType::kAttr) {
+        s = lookupAttributeInTable(table, resId);
+    } else {
+        s = util::make_unique<SymbolTable::Symbol>();
+        s->id = resId;
     }
-    return nullptr;
+
+    if (s) {
+        s->isPublic = (typeSpecFlags & android::ResTable_typeSpec::SPEC_PUBLIC) != 0;
+        return s;
+    }
+    return {};
 }
 
 static Maybe<ResourceName> getResourceName(const android::ResTable& table, ResourceId id) {
-    android::ResTable::resource_name resName;
+    android::ResTable::resource_name resName = {};
     if (!table.getResourceName(id.id, true, &resName)) {
         return {};
     }
@@ -211,55 +271,38 @@
     return name;
 }
 
-const ISymbolTable::Symbol* AssetManagerSymbolTableBuilder::AssetManagerSymbolTable::findById(
-        ResourceId id) {
-    if (const std::shared_ptr<Symbol>& s = mIdCache.get(id)) {
-        return s.get();
+std::unique_ptr<SymbolTable::Symbol> AssetManagerSymbolSource::findById(ResourceId id) {
+    const android::ResTable& table = mAssets.getResources(false);
+    Maybe<ResourceName> maybeName = getResourceName(table, id);
+    if (!maybeName) {
+        return {};
     }
 
-    for (const auto& asset : mAssets) {
-        const android::ResTable& table = asset->getResources(false);
+    uint32_t typeSpecFlags = 0;
+    table.getResourceFlags(id.id, &typeSpecFlags);
 
-        Maybe<ResourceName> maybeName = getResourceName(table, id);
-        if (!maybeName) {
-            continue;
-        }
-
-        uint32_t typeSpecFlags = 0;
-        table.getResourceFlags(id.id, &typeSpecFlags);
-
-        std::shared_ptr<Symbol> s;
-        if (maybeName.value().type == ResourceType::kAttr) {
-            s = lookupAttributeInTable(table, id);
-        } else {
-            s = std::make_shared<Symbol>();
-            s->id = id;
-        }
-
-        if (s) {
-            s->isPublic = (typeSpecFlags & android::ResTable_typeSpec::SPEC_PUBLIC) != 0;
-            mIdCache.put(id, s);
-            return s.get();
-        }
+    std::unique_ptr<SymbolTable::Symbol> s;
+    if (maybeName.value().type == ResourceType::kAttr) {
+        s = lookupAttributeInTable(table, id);
+    } else {
+        s = util::make_unique<SymbolTable::Symbol>();
+        s->id = id;
     }
-    return nullptr;
-}
 
-const ISymbolTable::Symbol* JoinedSymbolTableBuilder::JoinedSymbolTable::findByName(
-        const ResourceName& name) {
-    for (auto& symbolTable : mSymbolTables) {
-        if (const Symbol* s = symbolTable->findByName(name)) {
-            return s;
-        }
+    if (s) {
+        s->isPublic = (typeSpecFlags & android::ResTable_typeSpec::SPEC_PUBLIC) != 0;
+        return s;
     }
     return {};
 }
 
-const ISymbolTable::Symbol* JoinedSymbolTableBuilder::JoinedSymbolTable::findById(ResourceId id) {
-    for (auto& symbolTable : mSymbolTables) {
-        if (const Symbol* s = symbolTable->findById(id)) {
-            return s;
-        }
+std::unique_ptr<SymbolTable::Symbol> AssetManagerSymbolSource::findByReference(
+        const Reference& ref) {
+    // AssetManager always prefers IDs.
+    if (ref.id) {
+        return findById(ref.id.value());
+    } else if (ref.name) {
+        return findByName(ref.name.value());
     }
     return {};
 }
diff --git a/tools/aapt2/process/SymbolTable.h b/tools/aapt2/process/SymbolTable.h
index 22096ed..0a6a4a5 100644
--- a/tools/aapt2/process/SymbolTable.h
+++ b/tools/aapt2/process/SymbolTable.h
@@ -25,37 +25,20 @@
 #include <utils/JenkinsHash.h>
 #include <utils/LruCache.h>
 
+#include <android-base/macros.h>
 #include <androidfw/AssetManager.h>
 #include <algorithm>
-#include <map>
 #include <memory>
 #include <vector>
 
 namespace aapt {
 
-struct ISymbolTable {
-    virtual ~ISymbolTable() = default;
-
-    struct Symbol {
-        ResourceId id;
-        std::unique_ptr<Attribute> attribute;
-        bool isPublic;
-    };
-
-    /**
-     * Never hold on to the result between calls to findByName or findById. The results
-     * are typically stored in a cache which may evict entries.
-     */
-    virtual const Symbol* findByName(const ResourceName& name) = 0;
-    virtual const Symbol* findById(ResourceId id) = 0;
-};
-
 inline android::hash_t hash_type(const ResourceName& name) {
     std::hash<std::u16string> strHash;
     android::hash_t hash = 0;
-    hash = android::JenkinsHashMix(hash, strHash(name.package));
+    hash = android::JenkinsHashMix(hash, (uint32_t) strHash(name.package));
     hash = android::JenkinsHashMix(hash, (uint32_t) name.type);
-    hash = android::JenkinsHashMix(hash, strHash(name.entry));
+    hash = android::JenkinsHashMix(hash, (uint32_t) strHash(name.entry));
     return hash;
 }
 
@@ -63,88 +46,106 @@
     return android::hash_type(id.id);
 }
 
-/**
- * Presents a ResourceTable as an ISymbolTable, caching results.
- * Instances of this class must outlive the encompassed ResourceTable.
- * Since symbols are cached, the ResourceTable should not change during the
- * lifetime of this SymbolTableWrapper.
- *
- * If a resource in the ResourceTable does not have a ResourceID assigned to it,
- * it is ignored.
- *
- * Lookups by ID are ignored.
- */
-class SymbolTableWrapper : public ISymbolTable {
+class ISymbolSource;
+
+class SymbolTable {
+public:
+    struct Symbol {
+        Maybe<ResourceId> id;
+        std::shared_ptr<Attribute> attribute;
+        bool isPublic;
+    };
+
+    SymbolTable() : mCache(200), mIdCache(200) {
+    }
+
+    void appendSource(std::unique_ptr<ISymbolSource> source);
+    void prependSource(std::unique_ptr<ISymbolSource> source);
+
+    /**
+     * Never hold on to the result between calls to findByName or findById. The results
+     * are typically stored in a cache which may evict entries.
+     */
+    const Symbol* findByName(const ResourceName& name);
+    const Symbol* findById(ResourceId id);
+
+    /**
+     * Let's the ISymbolSource decide whether looking up by name or ID is faster, if both
+     * are available.
+     */
+    const Symbol* findByReference(const Reference& ref);
+
 private:
-    ResourceTable* mTable;
+    std::vector<std::unique_ptr<ISymbolSource>> mSources;
 
     // We use shared_ptr because unique_ptr is not supported and
     // we need automatic deletion.
     android::LruCache<ResourceName, std::shared_ptr<Symbol>> mCache;
+    android::LruCache<ResourceId, std::shared_ptr<Symbol>> mIdCache;
 
+    DISALLOW_COPY_AND_ASSIGN(SymbolTable);
+};
+
+/**
+ * An interface that a symbol source implements in order to surface symbol information
+ * to the symbol table.
+ */
+class ISymbolSource {
 public:
-    SymbolTableWrapper(ResourceTable* table) : mTable(table), mCache(200) {
-    }
+    virtual ~ISymbolSource() = default;
 
-    const Symbol* findByName(const ResourceName& name) override;
+    virtual std::unique_ptr<SymbolTable::Symbol> findByName(const ResourceName& name) = 0;
+    virtual std::unique_ptr<SymbolTable::Symbol> findById(ResourceId id) = 0;
 
-    // Unsupported, all queries to ResourceTable should be done by name.
-    const Symbol* findById(ResourceId id) override {
+    /**
+     * Default implementation tries the name if it exists, else the ID.
+     */
+    virtual std::unique_ptr<SymbolTable::Symbol> findByReference(const Reference& ref) {
+        if (ref.name) {
+            return findByName(ref.name.value());
+        } else if (ref.id) {
+            return findById(ref.id.value());
+        }
         return {};
     }
 };
 
-class AssetManagerSymbolTableBuilder {
-private:
-    struct AssetManagerSymbolTable : public ISymbolTable {
-        std::vector<std::unique_ptr<android::AssetManager>> mAssets;
-
-        // We use shared_ptr because unique_ptr is not supported and
-        // we need automatic deletion.
-        android::LruCache<ResourceName, std::shared_ptr<Symbol>> mCache;
-        android::LruCache<ResourceId, std::shared_ptr<Symbol>> mIdCache;
-
-        AssetManagerSymbolTable() : mCache(200), mIdCache(200) {
-        }
-
-        const Symbol* findByName(const ResourceName& name) override;
-        const Symbol* findById(ResourceId id) override;
-    };
-
-    std::unique_ptr<AssetManagerSymbolTable> mSymbolTable =
-            util::make_unique<AssetManagerSymbolTable>();
-
+/**
+ * Exposes the resources in a ResourceTable as symbols for SymbolTable.
+ * Instances of this class must outlive the encompassed ResourceTable.
+ * Lookups by ID are ignored.
+ */
+class ResourceTableSymbolSource : public ISymbolSource {
 public:
-    AssetManagerSymbolTableBuilder& add(std::unique_ptr<android::AssetManager> assetManager) {
-        mSymbolTable->mAssets.push_back(std::move(assetManager));
-        return *this;
+    explicit ResourceTableSymbolSource(ResourceTable* table) : mTable(table) {
     }
 
-    std::unique_ptr<ISymbolTable> build() {
-        return std::move(mSymbolTable);
+    std::unique_ptr<SymbolTable::Symbol> findByName(const ResourceName& name) override;
+
+    std::unique_ptr<SymbolTable::Symbol> findById(ResourceId id) override {
+        return {};
     }
+
+private:
+    ResourceTable* mTable;
+
+    DISALLOW_COPY_AND_ASSIGN(ResourceTableSymbolSource);
 };
 
-class JoinedSymbolTableBuilder {
-private:
-    struct JoinedSymbolTable : public ISymbolTable {
-        std::vector<std::unique_ptr<ISymbolTable>> mSymbolTables;
-
-        const Symbol* findByName(const ResourceName& name) override;
-        const Symbol* findById(ResourceId id) override;
-    };
-
-    std::unique_ptr<JoinedSymbolTable> mSymbolTable = util::make_unique<JoinedSymbolTable>();
-
+class AssetManagerSymbolSource : public ISymbolSource {
 public:
-    JoinedSymbolTableBuilder& addSymbolTable(std::unique_ptr<ISymbolTable> table) {
-        mSymbolTable->mSymbolTables.push_back(std::move(table));
-        return *this;
-    }
+    AssetManagerSymbolSource() = default;
 
-    std::unique_ptr<ISymbolTable> build() {
-        return std::move(mSymbolTable);
-    }
+    bool addAssetPath(const StringPiece& path);
+
+    std::unique_ptr<SymbolTable::Symbol> findByName(const ResourceName& name) override;
+    std::unique_ptr<SymbolTable::Symbol> findById(ResourceId id) override;
+    std::unique_ptr<SymbolTable::Symbol> findByReference(const Reference& ref) override;
+
+private:
+    android::AssetManager mAssets;
+
+    DISALLOW_COPY_AND_ASSIGN(AssetManagerSymbolSource);
 };
 
 } // namespace aapt
diff --git a/tools/aapt2/process/SymbolTable_test.cpp b/tools/aapt2/process/SymbolTable_test.cpp
index 1dc3b4f..34f31be 100644
--- a/tools/aapt2/process/SymbolTable_test.cpp
+++ b/tools/aapt2/process/SymbolTable_test.cpp
@@ -15,14 +15,11 @@
  */
 
 #include "process/SymbolTable.h"
-#include "test/Builders.h"
-#include "test/Context.h"
-
-#include <gtest/gtest.h>
+#include "test/Test.h"
 
 namespace aapt {
 
-TEST(SymbolTableWrapperTest, FindSymbolsWithIds) {
+TEST(ResourceTableSymbolSourceTest, FindSymbols) {
     std::unique_ptr<ResourceTable> table = test::ResourceTableBuilder()
             .addSimple(u"@android:id/foo", ResourceId(0x01020000))
             .addSimple(u"@android:id/bar")
@@ -30,27 +27,27 @@
                       test::AttributeBuilder().build())
             .build();
 
-    SymbolTableWrapper symbolTable(table.get());
-    EXPECT_NE(symbolTable.findByName(test::parseNameOrDie(u"@android:id/foo")), nullptr);
-    EXPECT_EQ(symbolTable.findByName(test::parseNameOrDie(u"@android:id/bar")), nullptr);
+    ResourceTableSymbolSource symbolSource(table.get());
+    EXPECT_NE(nullptr, symbolSource.findByName(test::parseNameOrDie(u"@android:id/foo")));
+    EXPECT_NE(nullptr, symbolSource.findByName(test::parseNameOrDie(u"@android:id/bar")));
 
-    const ISymbolTable::Symbol* s = symbolTable.findByName(
+    std::unique_ptr<SymbolTable::Symbol> s = symbolSource.findByName(
             test::parseNameOrDie(u"@android:attr/foo"));
-    ASSERT_NE(s, nullptr);
-    EXPECT_NE(s->attribute, nullptr);
+    ASSERT_NE(nullptr, s);
+    EXPECT_NE(nullptr, s->attribute);
 }
 
-TEST(SymbolTableWrapperTest, FindPrivateAttrSymbol) {
+TEST(ResourceTableSymbolSourceTest, FindPrivateAttrSymbol) {
     std::unique_ptr<ResourceTable> table = test::ResourceTableBuilder()
             .addValue(u"@android:^attr-private/foo", ResourceId(0x01010000),
                       test::AttributeBuilder().build())
             .build();
 
-    SymbolTableWrapper symbolTable(table.get());
-    const ISymbolTable::Symbol* s = symbolTable.findByName(
+    ResourceTableSymbolSource symbolSource(table.get());
+    std::unique_ptr<SymbolTable::Symbol> s = symbolSource.findByName(
                 test::parseNameOrDie(u"@android:attr/foo"));
-    ASSERT_NE(s, nullptr);
-    EXPECT_NE(s->attribute, nullptr);
+    ASSERT_NE(nullptr, s);
+    EXPECT_NE(nullptr, s->attribute);
 }
 
 } // namespace aapt
diff --git a/tools/aapt2/proto/TableProtoDeserializer.cpp b/tools/aapt2/proto/TableProtoDeserializer.cpp
index 9856a00..86883f8 100644
--- a/tools/aapt2/proto/TableProtoDeserializer.cpp
+++ b/tools/aapt2/proto/TableProtoDeserializer.cpp
@@ -483,8 +483,13 @@
         }
 
         const size_t padding = 4 - (pbSize & 0x03);
-        mData += sizeof(uint64_t) + pbSize + padding;
-        mSize -= sizeof(uint64_t) + pbSize + padding;
+        const size_t offset = sizeof(uint64_t) + pbSize + padding;
+        if (offset > mSize) {
+            return nullptr;
+        }
+
+        mData += offset;
+        mSize -= offset;
         mPbFile = std::move(pbFile);
     }
     return mPbFile.get();
diff --git a/tools/aapt2/proto/TableProtoSerializer.cpp b/tools/aapt2/proto/TableProtoSerializer.cpp
index b3d87d8..5d1b72b 100644
--- a/tools/aapt2/proto/TableProtoSerializer.cpp
+++ b/tools/aapt2/proto/TableProtoSerializer.cpp
@@ -178,10 +178,13 @@
     void serializeReferenceToPb(const Reference& ref, pb::Reference* pbRef) {
         if (ref.id) {
             pbRef->set_id(ref.id.value().id);
-        } else if (ref.name) {
+        }
+
+        if (ref.name) {
             StringPool::Ref symbolRef = mSymbolPool->makeRef(ref.name.value().toString());
             pbRef->set_symbol_idx(static_cast<uint32_t>(symbolRef.getIndex()));
         }
+
         pbRef->set_private_(ref.privateReference);
         pbRef->set_type(serializeReferenceTypeToPb(ref.referenceType));
     }
diff --git a/tools/aapt2/proto/TableProtoSerializer_test.cpp b/tools/aapt2/proto/TableProtoSerializer_test.cpp
index 70a33f7..dd995d8 100644
--- a/tools/aapt2/proto/TableProtoSerializer_test.cpp
+++ b/tools/aapt2/proto/TableProtoSerializer_test.cpp
@@ -62,6 +62,17 @@
                                        test::buildPrimitive(android::Res_value::TYPE_INT_DEC, 321u),
                                        context->getDiagnostics()));
 
+    // Make a reference with both resource name and resource ID.
+    // The reference should point to a resource outside of this table to test that both
+    // name and id get serialized.
+    Reference expectedRef;
+    expectedRef.name = test::parseNameOrDie(u"@android:layout/main");
+    expectedRef.id = ResourceId(0x01020000);
+    ASSERT_TRUE(table->addResource(test::parseNameOrDie(u"@com.app.a:layout/abc"),
+                                   ConfigDescription::defaultConfig(), std::string(),
+                                   util::make_unique<Reference>(expectedRef),
+                                   context->getDiagnostics()));
+
     std::unique_ptr<pb::ResourceTable> pbTable = serializeTableToPb(table.get());
     ASSERT_NE(nullptr, pbTable);
 
@@ -90,6 +101,13 @@
             newTable.get(), u"@com.app.a:integer/one", test::parseConfigOrDie("land"), "tablet");
     ASSERT_NE(nullptr, prim);
     EXPECT_EQ(321u, prim->value.data);
+
+    Reference* actualRef = test::getValue<Reference>(newTable.get(), u"@com.app.a:layout/abc");
+    ASSERT_NE(nullptr, actualRef);
+    AAPT_ASSERT_TRUE(actualRef->name);
+    AAPT_ASSERT_TRUE(actualRef->id);
+    EXPECT_EQ(expectedRef.name.value(), actualRef->name.value());
+    EXPECT_EQ(expectedRef.id.value(), actualRef->id.value());
 }
 
 TEST(TableProtoSerializer, SerializeFileHeader) {
@@ -130,4 +148,27 @@
     EXPECT_EQ(test::parseNameOrDie(u"@+id/unchecked"), file->exportedSymbols[0].name);
 }
 
+TEST(TableProtoSerializer, DeserializeCorruptHeaderSafely) {
+    ResourceFile f;
+    std::unique_ptr<pb::CompiledFile> pbFile = serializeCompiledFileToPb(f);
+
+    const std::string expectedData = "1234";
+
+    std::string outputStr;
+    {
+        google::protobuf::io::StringOutputStream outStream(&outputStr);
+        CompiledFileOutputStream outFileStream(&outStream, pbFile.get());
+
+        ASSERT_TRUE(outFileStream.Write(expectedData.data(), expectedData.size()));
+        ASSERT_TRUE(outFileStream.Finish());
+    }
+
+    outputStr[0] = 0xff;
+
+    CompiledFileInputStream inFileStream(outputStr.data(), outputStr.size());
+    EXPECT_EQ(nullptr, inFileStream.CompiledFile());
+    EXPECT_EQ(nullptr, inFileStream.data());
+    EXPECT_EQ(0u, inFileStream.size());
+}
+
 } // namespace aapt
diff --git a/tools/aapt2/test/Builders.h b/tools/aapt2/test/Builders.h
index 834caf8..8c56ebc 100644
--- a/tools/aapt2/test/Builders.h
+++ b/tools/aapt2/test/Builders.h
@@ -246,7 +246,7 @@
 inline std::unique_ptr<xml::XmlResource> buildXmlDomForPackageName(IAaptContext* context,
                                                                    const StringPiece& str) {
     std::unique_ptr<xml::XmlResource> doc = buildXmlDom(str);
-    doc->file.name.package = context->getCompilationPackage().toString();
+    doc->file.name.package = context->getCompilationPackage();
     return doc;
 }
 
diff --git a/tools/aapt2/test/Context.h b/tools/aapt2/test/Context.h
index e540cd7..96752d3 100644
--- a/tools/aapt2/test/Context.h
+++ b/tools/aapt2/test/Context.h
@@ -31,33 +31,16 @@
 namespace test {
 
 class Context : public IAaptContext {
-private:
-    friend class ContextBuilder;
-
-    Context() = default;
-
-    Maybe<std::u16string> mCompilationPackage;
-    Maybe<uint8_t> mPackageId;
-    std::unique_ptr<IDiagnostics> mDiagnostics = util::make_unique<StdErrDiagnostics>();
-    std::unique_ptr<ISymbolTable> mSymbols;
-    std::unique_ptr<NameMangler> mNameMangler;
-
 public:
-    ISymbolTable* getExternalSymbols() override {
-        assert(mSymbols && "test symbols not set");
-        return mSymbols.get();
-    }
-
-    void setSymbolTable(std::unique_ptr<ISymbolTable> symbols) {
-        mSymbols = std::move(symbols);
+    SymbolTable* getExternalSymbols() override {
+        return &mSymbols;
     }
 
     IDiagnostics* getDiagnostics() override {
-        assert(mDiagnostics && "test diagnostics not set");
-        return mDiagnostics.get();
+        return &mDiagnostics;
     }
 
-    StringPiece16 getCompilationPackage() override {
+    const std::u16string& getCompilationPackage() override {
         assert(mCompilationPackage && "package name not set");
         return mCompilationPackage.value();
     }
@@ -68,13 +51,24 @@
     }
 
     NameMangler* getNameMangler() override {
-        assert(mNameMangler && "test name mangler not set");
-        return mNameMangler.get();
+        return &mNameMangler;
     }
 
     bool verbose() override {
         return false;
     }
+
+private:
+    friend class ContextBuilder;
+
+    Context() : mNameMangler({}) {
+    }
+
+    Maybe<std::u16string> mCompilationPackage;
+    Maybe<uint8_t> mPackageId;
+    StdErrDiagnostics mDiagnostics;
+    SymbolTable mSymbols;
+    NameMangler mNameMangler;
 };
 
 class ContextBuilder {
@@ -92,18 +86,13 @@
         return *this;
     }
 
-    ContextBuilder& setSymbolTable(std::unique_ptr<ISymbolTable> symbols) {
-        mContext->mSymbols = std::move(symbols);
-        return *this;
-    }
-
-    ContextBuilder& setDiagnostics(std::unique_ptr<IDiagnostics> diag) {
-        mContext->mDiagnostics = std::move(diag);
-        return *this;
-    }
-
     ContextBuilder& setNameManglerPolicy(NameManglerPolicy policy) {
-        mContext->mNameMangler = util::make_unique<NameMangler>(policy);
+        mContext->mNameMangler = NameMangler(policy);
+        return *this;
+    }
+
+    ContextBuilder& addSymbolSource(std::unique_ptr<ISymbolSource> src) {
+        mContext->getExternalSymbols()->appendSource(std::move(src));
         return *this;
     }
 
@@ -112,57 +101,72 @@
     }
 };
 
-class StaticSymbolTableBuilder {
-private:
-    struct SymbolTable : public ISymbolTable {
-        std::list<std::unique_ptr<Symbol>> mSymbols;
-        std::map<ResourceName, Symbol*> mNameMap;
-        std::map<ResourceId, Symbol*> mIdMap;
+class StaticSymbolSourceBuilder {
+public:
+    StaticSymbolSourceBuilder& addPublicSymbol(const StringPiece16& name, ResourceId id,
+                                               std::unique_ptr<Attribute> attr = {}) {
+        std::unique_ptr<SymbolTable::Symbol> symbol = util::make_unique<SymbolTable::Symbol>(
+                id, std::move(attr), true);
+        mSymbolSource->mNameMap[parseNameOrDie(name)] = symbol.get();
+        mSymbolSource->mIdMap[id] = symbol.get();
+        mSymbolSource->mSymbols.push_back(std::move(symbol));
+        return *this;
+    }
 
-        const Symbol* findByName(const ResourceName& name) override {
+    StaticSymbolSourceBuilder& addSymbol(const StringPiece16& name, ResourceId id,
+                                         std::unique_ptr<Attribute> attr = {}) {
+        std::unique_ptr<SymbolTable::Symbol> symbol = util::make_unique<SymbolTable::Symbol>(
+                id, std::move(attr), false);
+        mSymbolSource->mNameMap[parseNameOrDie(name)] = symbol.get();
+        mSymbolSource->mIdMap[id] = symbol.get();
+        mSymbolSource->mSymbols.push_back(std::move(symbol));
+        return *this;
+    }
+
+    std::unique_ptr<ISymbolSource> build() {
+        return std::move(mSymbolSource);
+    }
+
+private:
+    class StaticSymbolSource : public ISymbolSource {
+    public:
+        StaticSymbolSource() = default;
+
+        std::unique_ptr<SymbolTable::Symbol> findByName(const ResourceName& name) override {
             auto iter = mNameMap.find(name);
             if (iter != mNameMap.end()) {
-                return iter->second;
+                return cloneSymbol(iter->second);
             }
             return nullptr;
         }
 
-        const Symbol* findById(ResourceId id) override {
+        std::unique_ptr<SymbolTable::Symbol> findById(ResourceId id) override {
             auto iter = mIdMap.find(id);
             if (iter != mIdMap.end()) {
-                return iter->second;
+                return cloneSymbol(iter->second);
             }
             return nullptr;
         }
+
+        std::list<std::unique_ptr<SymbolTable::Symbol>> mSymbols;
+        std::map<ResourceName, SymbolTable::Symbol*> mNameMap;
+        std::map<ResourceId, SymbolTable::Symbol*> mIdMap;
+
+    private:
+        std::unique_ptr<SymbolTable::Symbol> cloneSymbol(SymbolTable::Symbol* sym) {
+            std::unique_ptr<SymbolTable::Symbol> clone = util::make_unique<SymbolTable::Symbol>();
+            clone->id = sym->id;
+            if (sym->attribute) {
+                clone->attribute = std::unique_ptr<Attribute>(sym->attribute->clone(nullptr));
+            }
+            clone->isPublic = sym->isPublic;
+            return clone;
+        }
+
+        DISALLOW_COPY_AND_ASSIGN(StaticSymbolSource);
     };
 
-    std::unique_ptr<SymbolTable> mSymbolTable = util::make_unique<SymbolTable>();
-
-public:
-    StaticSymbolTableBuilder& addPublicSymbol(const StringPiece16& name, ResourceId id,
-                                              std::unique_ptr<Attribute> attr = {}) {
-        std::unique_ptr<ISymbolTable::Symbol> symbol = util::make_unique<ISymbolTable::Symbol>(
-                id, std::move(attr));
-        symbol->isPublic = true;
-        mSymbolTable->mNameMap[parseNameOrDie(name)] = symbol.get();
-        mSymbolTable->mIdMap[id] = symbol.get();
-        mSymbolTable->mSymbols.push_back(std::move(symbol));
-        return *this;
-    }
-
-    StaticSymbolTableBuilder& addSymbol(const StringPiece16& name, ResourceId id,
-                                        std::unique_ptr<Attribute> attr = {}) {
-        std::unique_ptr<ISymbolTable::Symbol> symbol = util::make_unique<ISymbolTable::Symbol>(
-                id, std::move(attr));
-        mSymbolTable->mNameMap[parseNameOrDie(name)] = symbol.get();
-        mSymbolTable->mIdMap[id] = symbol.get();
-        mSymbolTable->mSymbols.push_back(std::move(symbol));
-        return *this;
-    }
-
-    std::unique_ptr<ISymbolTable> build() {
-        return std::move(mSymbolTable);
-    }
+    std::unique_ptr<StaticSymbolSource> mSymbolSource = util::make_unique<StaticSymbolSource>();
 };
 
 } // namespace test
diff --git a/media/mca/effect/java/android/media/effect/package-info.java b/tools/aapt2/test/Test.h
similarity index 64%
rename from media/mca/effect/java/android/media/effect/package-info.java
rename to tools/aapt2/test/Test.h
index b2c14ff..d4845cf 100644
--- a/media/mca/effect/java/android/media/effect/package-info.java
+++ b/tools/aapt2/test/Test.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2011 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.
@@ -14,15 +14,19 @@
  * limitations under the License.
  */
 
+#ifndef AAPT_TEST_TEST_H
+#define AAPT_TEST_TEST_H
 
-package android.media.effect;
+#include "test/Builders.h"
+#include "test/Common.h"
+#include "test/Context.h"
 
-/**
- * <h1>Effect Framework</h1>
- *
- * This package includes a collection of high-performance visual effects that make use of the
- * mobile filter framework subsystem.
- *
- * TODO: More Documentation
- *
- */
+#include <gtest/gtest.h>
+
+namespace aapt {
+namespace test {
+
+} // namespace test
+} // namespace aapt
+
+#endif // AAPT_TEST_TEST_H
diff --git a/tools/aapt2/util/Files.cpp b/tools/aapt2/util/Files.cpp
index 04e8199..6428e98 100644
--- a/tools/aapt2/util/Files.cpp
+++ b/tools/aapt2/util/Files.cpp
@@ -96,7 +96,7 @@
     const char* start = path.begin();
     const char* end = path.end();
     for (const char* current = start; current != end; ++current) {
-        if (*current == sDirSep) {
+        if (*current == sDirSep && current != start) {
             StringPiece parentPath(start, current - start);
             int result = mkdirImpl(parentPath);
             if (result < 0 && errno != EEXIST) {
@@ -139,6 +139,20 @@
     return {};
 }
 
+void appendPath(std::string* base, StringPiece part) {
+    assert(base);
+    const bool baseHasTrailingSep = (!base->empty() && *(base->end() - 1) == sDirSep);
+    const bool partHasLeadingSep = (!part.empty() && *(part.begin()) == sDirSep);
+    if (baseHasTrailingSep && partHasLeadingSep) {
+        // Remove the part's leading sep
+        part = part.substr(1, part.size() - 1);
+    } else if (!baseHasTrailingSep && !partHasLeadingSep) {
+        // None of the pieces has a separator.
+        *base += sDirSep;
+    }
+    base->append(part.data(), part.size());
+}
+
 std::string packageToPath(const StringPiece& package) {
     std::string outPath;
     for (StringPiece part : util::tokenize<char>(package, '.')) {
diff --git a/tools/aapt2/util/Files.h b/tools/aapt2/util/Files.h
index c58ba5d..c2e6115 100644
--- a/tools/aapt2/util/Files.h
+++ b/tools/aapt2/util/Files.h
@@ -61,14 +61,7 @@
 /*
  * Appends a path to `base`, separated by the directory separator.
  */
-void appendPath(std::string* base, const StringPiece& part);
-
-/*
- * Appends a series of paths to `base`, separated by the
- * system directory separator.
- */
-template <typename... Ts >
-void appendPath(std::string* base, const StringPiece& part, const Ts&... parts);
+void appendPath(std::string* base, StringPiece part);
 
 /*
  * Makes all the directories in `path`. The last element in the path
@@ -139,20 +132,6 @@
     std::vector<std::string> mPatternTokens;
 };
 
-inline void appendPath(std::string* base, const StringPiece& part) {
-    assert(base);
-    *base += sDirSep;
-    base->append(part.data(), part.size());
-}
-
-template <typename... Ts >
-void appendPath(std::string* base, const StringPiece& part, const Ts&... parts) {
-    assert(base);
-    *base += sDirSep;
-    base->append(part.data(), part.size());
-    appendPath(base, parts...);
-}
-
 } // namespace file
 } // namespace aapt
 
diff --git a/tools/aapt2/util/Files_test.cpp b/tools/aapt2/util/Files_test.cpp
new file mode 100644
index 0000000..efb0459
--- /dev/null
+++ b/tools/aapt2/util/Files_test.cpp
@@ -0,0 +1,58 @@
+/*
+ * 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 "test/Test.h"
+#include "util/Files.h"
+
+#include <sstream>
+
+namespace aapt {
+namespace file {
+
+class FilesTest : public ::testing::Test {
+public:
+    void SetUp() override {
+        std::stringstream builder;
+        builder << "hello" << sDirSep << "there";
+        mExpectedPath = builder.str();
+    }
+
+protected:
+    std::string mExpectedPath;
+};
+
+TEST_F(FilesTest, appendPath) {
+    std::string base = "hello";
+    appendPath(&base, "there");
+    EXPECT_EQ(mExpectedPath, base);
+}
+
+TEST_F(FilesTest, appendPathWithLeadingOrTrailingSeparators) {
+    std::string base = "hello/";
+    appendPath(&base, "there");
+    EXPECT_EQ(mExpectedPath, base);
+
+    base = "hello";
+    appendPath(&base, "/there");
+    EXPECT_EQ(mExpectedPath, base);
+
+    base = "hello/";
+    appendPath(&base, "/there");
+    EXPECT_EQ(mExpectedPath, base);
+}
+
+} // namespace files
+} // namespace aapt
diff --git a/tools/aapt2/xml/XmlDom.h b/tools/aapt2/xml/XmlDom.h
index 033b0a4..b374d20 100644
--- a/tools/aapt2/xml/XmlDom.h
+++ b/tools/aapt2/xml/XmlDom.h
@@ -68,7 +68,7 @@
 };
 
 struct AaptAttribute {
-    ResourceId id;
+    Maybe<ResourceId> id;
     aapt::Attribute attribute;
 };
 
diff --git a/tools/apilint/apilint.py b/tools/apilint/apilint.py
index df76bc9..a8a8c5c 100644
--- a/tools/apilint/apilint.py
+++ b/tools/apilint/apilint.py
@@ -264,6 +264,9 @@
         if "static" in f.split and "final" in f.split:
             if re.match("[A-Z0-9_]+", f.name) is None:
                 error(clazz, f, "C2", "Constant field names must be FOO_NAME")
+            elif f.typ != "java.lang.String":
+                if f.name.startswith("MIN_") or f.name.startswith("MAX_"):
+                    warn(clazz, f, "C8", "If min/max could change in future, make them dynamic methods")
 
 
 def verify_enums(clazz):
@@ -417,6 +420,9 @@
         if len(creator) == 0 or len(write) == 0 or len(describe) == 0:
             error(clazz, None, "FW3", "Parcelable requires CREATOR, writeToParcel, and describeContents; missing one")
 
+        if " final class " not in clazz.raw:
+            error(clazz, None, "FW8", "Parcelable classes must be final")
+
 
 def verify_protected(clazz):
     """Verify that no protected methods or fields are allowed."""
@@ -730,6 +736,13 @@
         if "throws java.lang.Exception" in m.raw or "throws java.lang.Throwable" in m.raw or "throws java.lang.Error" in m.raw:
             error(clazz, m, "S1", "Methods must not throw generic exceptions")
 
+        if "throws android.os.RemoteException" in m.raw:
+            if clazz.name == "android.content.ContentProviderClient": continue
+            if clazz.name == "android.os.Binder": continue
+            if clazz.name == "android.os.IBinder": continue
+
+            error(clazz, m, "FW9", "Methods calling into system server should rethrow RemoteException as RuntimeException")
+
 
 def verify_google(clazz):
     """Verifies that APIs never reference Google."""
@@ -946,6 +959,27 @@
             error(clazz, f, "C7", "Expected resource name in this class to be FooBar_Baz style")
 
 
+def verify_files(clazz):
+    """Verifies that methods accepting File also accept streams."""
+
+    has_file = set()
+    has_stream = set()
+
+    test = []
+    test.extend(clazz.ctors)
+    test.extend(clazz.methods)
+
+    for m in test:
+        if "java.io.File" in m.args:
+            has_file.add(m)
+        if "java.io.FileDescriptor" in m.args or "android.os.ParcelFileDescriptor" in m.args or "java.io.InputStream" in m.args or "java.io.OutputStream" in m.args:
+            has_stream.add(m.name)
+
+    for m in has_file:
+        if m.name not in has_stream:
+            warn(clazz, m, "M10", "Methods accepting File should also accept FileDescriptor or streams")
+
+
 def examine_clazz(clazz):
     """Find all style issues in the given class."""
     if clazz.pkg.name.startswith("java"): return
@@ -954,6 +988,7 @@
     if clazz.pkg.name.startswith("org.xml"): return
     if clazz.pkg.name.startswith("org.json"): return
     if clazz.pkg.name.startswith("org.w3c"): return
+    if clazz.pkg.name.startswith("android.icu."): return
 
     verify_constants(clazz)
     verify_enums(clazz)
@@ -989,6 +1024,7 @@
     verify_context_first(clazz)
     verify_listener_last(clazz)
     verify_resource_names(clazz)
+    verify_files(clazz)
 
 
 def examine_stream(stream):
diff --git a/tools/layoutlib/.idea/libraries/junit.xml b/tools/layoutlib/.idea/libraries/junit.xml
new file mode 100644
index 0000000..c889f5f
--- /dev/null
+++ b/tools/layoutlib/.idea/libraries/junit.xml
@@ -0,0 +1,11 @@
+<component name="libraryTable">
+  <library name="junit">
+    <CLASSES>
+      <root url="jar://$PROJECT_DIR$/../../../../out/host/common/obj/JAVA_LIBRARIES/junit_intermediates/javalib.jar!/" />
+    </CLASSES>
+    <JAVADOC />
+    <SOURCES>
+      <root url="file://$PROJECT_DIR$/../../../../external/junit/src" />
+    </SOURCES>
+  </library>
+</component>
\ No newline at end of file
diff --git a/tools/layoutlib/.idea/runConfigurations/Create.xml b/tools/layoutlib/.idea/runConfigurations/Create.xml
index 58f057a..536a23f 100644
--- a/tools/layoutlib/.idea/runConfigurations/Create.xml
+++ b/tools/layoutlib/.idea/runConfigurations/Create.xml
@@ -2,8 +2,8 @@
   <configuration default="false" name="Create" type="Application" factoryName="Application" singleton="true">
     <extension name="coverage" enabled="false" merge="false" sample_coverage="true" runner="idea" />
     <option name="MAIN_CLASS_NAME" value="com.android.tools.layoutlib.create.Main" />
-    <option name="VM_PARAMETERS" value="" />
-    <option name="PROGRAM_PARAMETERS" value="out/host/common/obj/JAVA_LIBRARIES/temp_layoutlib_intermediates/javalib.jar out/target/common/obj/JAVA_LIBRARIES/core-libart_intermediates/classes.jar out/target/common/obj/JAVA_LIBRARIES/framework_intermediates/classes.jar out/target/common/obj/JAVA_LIBRARIES/icu4j-icudata-jarjar_intermediates/classes.jar out/target/common/obj/JAVA_LIBRARIES/icu4j-icutzdata-jarjar_intermediates/classes.jar out/target/common/obj/JAVA_LIBRARIES/ext_intermediates/classes.jar out/target/common/obj/JAVA_LIBRARIES/ext_intermediates/javalib.jar" />
+    <option name="VM_PARAMETERS" value="-ea" />
+    <option name="PROGRAM_PARAMETERS" value="out/host/common/obj/JAVA_LIBRARIES/temp_layoutlib_intermediates/javalib.jar out/target/common/obj/JAVA_LIBRARIES/core-libart_intermediates/classes.jar out/target/common/obj/JAVA_LIBRARIES/framework_intermediates/classes.jar out/host/common/obj/JAVA_LIBRARIES/icu4j-icudata-host-jarjar_intermediates/classes-jarjar.jar out/host/common/obj/JAVA_LIBRARIES/icu4j-icutzdata-host-jarjar_intermediates/classes-jarjar.jar out/target/common/obj/JAVA_LIBRARIES/ext_intermediates/classes.jar out/target/common/obj/JAVA_LIBRARIES/ext_intermediates/javalib.jar" />
     <option name="WORKING_DIRECTORY" value="file://$PROJECT_DIR$/../../../../" />
     <option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
     <option name="ALTERNATIVE_JRE_PATH" value="" />
diff --git a/tools/layoutlib/Android.mk b/tools/layoutlib/Android.mk
index c2ad9ef..663e1e2 100644
--- a/tools/layoutlib/Android.mk
+++ b/tools/layoutlib/Android.mk
@@ -40,10 +40,8 @@
 built_ext_classes := $(call java-lib-files,ext)
 built_ext_data := $(call intermediates-dir-for, \
 			JAVA_LIBRARIES,ext,,COMMON)/javalib.jar
-built_icudata_dep := $(call java-lib-deps,icu4j-icudata-jarjar)
-built_icudata_data := $(call java-lib-files,icu4j-icudata-jarjar)
-built_icutzdata_dep := $(call java-lib-deps,icu4j-icutzdata-jarjar)
-built_icutzdata_data := $(call java-lib-files,icu4j-icutzdata-jarjar)
+built_icudata_dep := $(call java-lib-deps,icu4j-icudata-host-jarjar,HOST)
+built_icutzdata_dep := $(call java-lib-deps,icu4j-icutzdata-host-jarjar,HOST)
 
 built_layoutlib_create_jar := $(call intermediates-dir-for, \
 			JAVA_LIBRARIES,layoutlib_create,HOST)/javalib.jar
@@ -77,8 +75,8 @@
 	             $(built_core_classes) \
 	             $(built_framework_classes) \
 	             $(built_ext_classes) \
-		     $(built_icudata_data) \
-		     $(built_icutzdata_data) \
+		     $(built_icudata_dep) \
+		     $(built_icutzdata_dep) \
 	             $(built_ext_data)
 	$(hide) ls -l $(built_framework_classes)
 
diff --git a/tools/layoutlib/bridge/bridge.iml b/tools/layoutlib/bridge/bridge.iml
index ccc10b3..57d08cb 100644
--- a/tools/layoutlib/bridge/bridge.iml
+++ b/tools/layoutlib/bridge/bridge.iml
@@ -84,6 +84,6 @@
         </SOURCES>
       </library>
     </orderEntry>
-    <orderEntry type="library" scope="TEST" name="JUnit4" level="application" />
+    <orderEntry type="library" scope="TEST" name="junit" level="project" />
   </component>
 </module>
\ No newline at end of file
diff --git a/tools/layoutlib/bridge/src/android/content/res/BridgeTypedArray.java b/tools/layoutlib/bridge/src/android/content/res/BridgeTypedArray.java
index db4c6dc6..d0e431a 100644
--- a/tools/layoutlib/bridge/src/android/content/res/BridgeTypedArray.java
+++ b/tools/layoutlib/bridge/src/android/content/res/BridgeTypedArray.java
@@ -25,14 +25,9 @@
 import com.android.internal.util.XmlUtils;
 import com.android.layoutlib.bridge.Bridge;
 import com.android.layoutlib.bridge.android.BridgeContext;
-import com.android.layoutlib.bridge.android.BridgeXmlBlockParser;
-import com.android.layoutlib.bridge.impl.ParserFactory;
 import com.android.layoutlib.bridge.impl.ResourceHelper;
 import com.android.resources.ResourceType;
 
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-
 import android.annotation.Nullable;
 import android.content.res.Resources.NotFoundException;
 import android.content.res.Resources.Theme;
@@ -42,7 +37,6 @@
 import android.view.LayoutInflater_Delegate;
 import android.view.ViewGroup.LayoutParams;
 
-import java.io.File;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Map;
@@ -71,7 +65,7 @@
  */
 public final class BridgeTypedArray extends TypedArray {
 
-    private final BridgeResources mBridgeResources;
+    private final Resources mBridgeResources;
     private final BridgeContext mContext;
     private final boolean mPlatformFile;
 
@@ -84,7 +78,7 @@
     @Nullable
     private int[] mEmptyIds;
 
-    public BridgeTypedArray(BridgeResources resources, BridgeContext context, int len,
+    public BridgeTypedArray(Resources resources, BridgeContext context, int len,
             boolean platformFile) {
         super(resources, null, null, 0);
         mBridgeResources = resources;
@@ -305,71 +299,22 @@
         return defValue;
     }
 
-    /**
-     * Retrieve the ColorStateList for the attribute at <var>index</var>.
-     * The value may be either a single solid color or a reference to
-     * a color or complex {@link android.content.res.ColorStateList} description.
-     *
-     * @param index Index of attribute to retrieve.
-     *
-     * @return ColorStateList for the attribute, or null if not defined.
-     */
     @Override
     public ColorStateList getColorStateList(int index) {
         if (!hasValue(index)) {
             return null;
         }
 
-        ResourceValue resValue = mResourceData[index];
-        String value = resValue.getValue();
+        return ResourceHelper.getColorStateList(mResourceData[index], mContext);
+    }
 
-        if (value == null) {
+    @Override
+    public ComplexColor getComplexColor(int index) {
+        if (!hasValue(index)) {
             return null;
         }
 
-
-        try {
-            // Get the state list file content from callback to parse PSI file
-            XmlPullParser parser = mContext.getLayoutlibCallback().getXmlFileParser(value);
-            if (parser == null) {
-                // If used with a version of Android Studio that does not implement getXmlFileParser
-                // fall back to reading the file from disk
-                File f = new File(value);
-                if (f.isFile()) {
-                    parser = ParserFactory.create(f);
-                }
-            }
-            if (parser != null) {
-                BridgeXmlBlockParser blockParser = new BridgeXmlBlockParser(
-                        parser, mContext, resValue.isFramework());
-                try {
-                    return ColorStateList.createFromXml(mContext.getResources(), blockParser,
-                            mContext.getTheme());
-                } finally {
-                    blockParser.ensurePopped();
-                }
-            }
-        } catch (XmlPullParserException e) {
-            Bridge.getLog().error(LayoutLog.TAG_BROKEN,
-                    "Failed to configure parser for " + value, e, null);
-            return null;
-        } catch (Exception e) {
-            // this is an error and not warning since the file existence is checked before
-            // attempting to parse it.
-            Bridge.getLog().error(LayoutLog.TAG_RESOURCES_READ,
-                    "Failed to parse file " + value, e, null);
-
-            return null;
-        }
-
-        try {
-            int color = ResourceHelper.getColor(value);
-            return ColorStateList.valueOf(color);
-        } catch (NumberFormatException e) {
-            Bridge.getLog().error(LayoutLog.TAG_RESOURCES_FORMAT, e.getMessage(), e, null);
-        }
-
-        return null;
+        return ResourceHelper.getComplexColor(mResourceData[index], mContext);
     }
 
     /**
@@ -756,7 +701,8 @@
         if (resVal instanceof ArrayResourceValue) {
             ArrayResourceValue array = (ArrayResourceValue) resVal;
             int count = array.getElementCount();
-            return count >= 0 ? mBridgeResources.fillValues(array, new CharSequence[count]) : null;
+            return count >= 0 ? Resources_Delegate.fillValues(mBridgeResources, array, new CharSequence[count]) :
+                    null;
         }
         int id = getResourceId(index, 0);
         String resIdMessage = id > 0 ? " (resource id 0x" + Integer.toHexString(id) + ')' : "";
@@ -1004,7 +950,6 @@
     }
 
     static TypedArray obtain(Resources res, int len) {
-        return res instanceof BridgeResources ?
-                new BridgeTypedArray(((BridgeResources) res), null, len, true) : null;
+        return new BridgeTypedArray(res, null, len, true);
     }
 }
diff --git a/tools/layoutlib/bridge/src/android/content/res/ComplexColor_Accessor.java b/tools/layoutlib/bridge/src/android/content/res/ComplexColor_Accessor.java
new file mode 100644
index 0000000..09c0260
--- /dev/null
+++ b/tools/layoutlib/bridge/src/android/content/res/ComplexColor_Accessor.java
@@ -0,0 +1,46 @@
+/*
+ * 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.res;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.res.Resources.Theme;
+import android.util.AttributeSet;
+
+import java.io.IOException;
+
+/**
+ * Class that provides access to the {@link GradientColor#createFromXmlInner(Resources,
+ * XmlPullParser, AttributeSet, Theme)} and {@link ColorStateList#createFromXmlInner(Resources,
+ * XmlPullParser, AttributeSet, Theme)} methods
+ */
+public class ComplexColor_Accessor {
+    public static GradientColor createGradientColorFromXmlInner(@NonNull Resources r,
+            @NonNull XmlPullParser parser, @NonNull AttributeSet attrs, @Nullable Theme theme)
+            throws IOException, XmlPullParserException {
+        return GradientColor.createFromXmlInner(r, parser, attrs, theme);
+    }
+
+    public static ColorStateList createColorStateListFromXmlInner(@NonNull Resources r,
+            @NonNull XmlPullParser parser, @NonNull AttributeSet attrs, @Nullable Theme theme)
+            throws IOException, XmlPullParserException {
+        return ColorStateList.createFromXmlInner(r, parser, attrs, theme);
+    }
+}
diff --git a/tools/layoutlib/bridge/src/android/content/res/BridgeResources.java b/tools/layoutlib/bridge/src/android/content/res/Resources_Delegate.java
similarity index 63%
rename from tools/layoutlib/bridge/src/android/content/res/BridgeResources.java
rename to tools/layoutlib/bridge/src/android/content/res/Resources_Delegate.java
index fe46480..985dd5a 100644
--- a/tools/layoutlib/bridge/src/android/content/res/BridgeResources.java
+++ b/tools/layoutlib/bridge/src/android/content/res/Resources_Delegate.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2008 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.
@@ -28,8 +28,10 @@
 import com.android.layoutlib.bridge.android.BridgeXmlBlockParser;
 import com.android.layoutlib.bridge.impl.ParserFactory;
 import com.android.layoutlib.bridge.impl.ResourceHelper;
+import com.android.layoutlib.bridge.util.NinePatchInputStream;
 import com.android.ninepatch.NinePatch;
 import com.android.resources.ResourceType;
+import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
 import com.android.util.Pair;
 
 import org.xmlpull.v1.XmlPullParser;
@@ -37,6 +39,8 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.content.res.Resources.NotFoundException;
+import android.content.res.Resources.Theme;
 import android.graphics.drawable.Drawable;
 import android.util.AttributeSet;
 import android.util.DisplayMetrics;
@@ -50,132 +54,101 @@
 import java.util.Iterator;
 
 @SuppressWarnings("deprecation")
-public final class BridgeResources extends Resources {
+public class Resources_Delegate {
 
-    private BridgeContext mContext;
-    private LayoutlibCallback mLayoutlibCallback;
-    private boolean[] mPlatformResourceFlag = new boolean[1];
-    private TypedValue mTmpValue = new TypedValue();
+    private static boolean[] mPlatformResourceFlag = new boolean[1];
 
-    /**
-     * Simpler wrapper around FileInputStream. This is used when the input stream represent
-     * not a normal bitmap but a nine patch.
-     * This is useful when the InputStream is created in a method but used in another that needs
-     * to know whether this is 9-patch or not, such as BitmapFactory.
-     */
-    public class NinePatchInputStream extends FileInputStream {
-        private boolean mFakeMarkSupport = true;
-        public NinePatchInputStream(File file) throws FileNotFoundException {
-            super(file);
-        }
-
-        @Override
-        public boolean markSupported() {
-            //noinspection SimplifiableIfStatement
-            if (mFakeMarkSupport) {
-                // this is needed so that BitmapFactory doesn't wrap this in a BufferedInputStream.
-                return true;
-            }
-
-            return super.markSupported();
-        }
-
-        public void disableFakeMarkSupport() {
-            // disable fake mark support so that in case codec actually try to use them
-            // we don't lie to them.
-            mFakeMarkSupport = false;
-        }
-    }
-
-    /**
-     * This initializes the static field {@link Resources#mSystem} which is used
-     * by methods who get global resources using {@link Resources#getSystem()}.
-     * <p/>
-     * They will end up using our bridge resources.
-     * <p/>
-     * {@link Bridge} calls this method after setting up a new bridge.
-     */
     public static Resources initSystem(BridgeContext context,
             AssetManager assets,
             DisplayMetrics metrics,
             Configuration config,
             LayoutlibCallback layoutlibCallback) {
-        return Resources.mSystem = new BridgeResources(context,
-                assets,
-                metrics,
-                config,
-                layoutlibCallback);
+        Resources resources = new Resources(assets, metrics, config);
+        resources.mContext = context;
+        resources.mLayoutlibCallback = layoutlibCallback;
+        return Resources.mSystem = resources;
     }
 
     /**
-     * Disposes the static {@link Resources#mSystem} to make sure we don't leave objects
-     * around that would prevent us from unloading the library.
+     * Disposes the static {@link Resources#mSystem} to make sure we don't leave objects around that
+     * would prevent us from unloading the library.
      */
     public static void disposeSystem() {
-        if (Resources.mSystem instanceof BridgeResources) {
-            ((BridgeResources)(Resources.mSystem)).mContext = null;
-            ((BridgeResources)(Resources.mSystem)).mLayoutlibCallback = null;
-        }
+        Resources.mSystem.mContext = null;
+        Resources.mSystem.mLayoutlibCallback = null;
         Resources.mSystem = null;
     }
 
-    private BridgeResources(BridgeContext context, AssetManager assets, DisplayMetrics metrics,
-            Configuration config, LayoutlibCallback layoutlibCallback) {
-        super(assets, metrics, config);
-        mContext = context;
-        mLayoutlibCallback = layoutlibCallback;
+    public static BridgeTypedArray newTypeArray(Resources resources, int numEntries,
+            boolean platformFile) {
+        return new BridgeTypedArray(resources, resources.mContext, numEntries, platformFile);
     }
 
-    public BridgeTypedArray newTypeArray(int numEntries, boolean platformFile) {
-        return new BridgeTypedArray(this, mContext, numEntries, platformFile);
-    }
-
-    private Pair<String, ResourceValue> getResourceValue(int id, boolean[] platformResFlag_out) {
+    private static Pair<String, ResourceValue> getResourceValue(Resources resources, int id,
+            boolean[] platformResFlag_out) {
         // first get the String related to this id in the framework
         Pair<ResourceType, String> resourceInfo = Bridge.resolveResourceId(id);
 
+        // Set the layoutlib callback and context for resources
+        if (resources != Resources.mSystem && resources.mLayoutlibCallback == null) {
+            resources.mLayoutlibCallback = Resources.mSystem.mLayoutlibCallback;
+            resources.mContext = Resources.mSystem.mContext;
+        }
+
         if (resourceInfo != null) {
             platformResFlag_out[0] = true;
             String attributeName = resourceInfo.getSecond();
 
-            return Pair.of(attributeName, mContext.getRenderResources().getFrameworkResource(
-                    resourceInfo.getFirst(), attributeName));
+            return Pair.of(attributeName,
+                    resources.mContext.getRenderResources().getFrameworkResource(
+                            resourceInfo.getFirst(), attributeName));
         }
 
         // didn't find a match in the framework? look in the project.
-        if (mLayoutlibCallback != null) {
-            resourceInfo = mLayoutlibCallback.resolveResourceId(id);
+        if (resources.mLayoutlibCallback != null) {
+            resourceInfo = resources.mLayoutlibCallback.resolveResourceId(id);
 
             if (resourceInfo != null) {
                 platformResFlag_out[0] = false;
                 String attributeName = resourceInfo.getSecond();
 
-                return Pair.of(attributeName, mContext.getRenderResources().getProjectResource(
-                        resourceInfo.getFirst(), attributeName));
+                return Pair.of(attributeName,
+                        resources.mContext.getRenderResources().getProjectResource(
+                                resourceInfo.getFirst(), attributeName));
             }
         }
 
         return null;
     }
 
-    @Override
-    public Drawable getDrawable(int id, Theme theme) {
-        Pair<String, ResourceValue> value = getResourceValue(id, mPlatformResourceFlag);
+    @LayoutlibDelegate
+    static Drawable getDrawable(Resources resources, int id) {
+        return getDrawable(resources, id, null);
+    }
+
+    @LayoutlibDelegate
+    static Drawable getDrawable(Resources resources, int id, Theme theme) {
+        Pair<String, ResourceValue> value = getResourceValue(resources, id, mPlatformResourceFlag);
 
         if (value != null) {
-            return ResourceHelper.getDrawable(value.getSecond(), mContext, theme);
+            return ResourceHelper.getDrawable(value.getSecond(), resources.mContext, theme);
         }
 
         // id was not found or not resolved. Throw a NotFoundException.
-        throwException(id);
+        throwException(resources, id);
 
         // this is not used since the method above always throws
         return null;
     }
 
-    @Override
-    public int getColor(int id, Theme theme) throws NotFoundException {
-        Pair<String, ResourceValue> value = getResourceValue(id, mPlatformResourceFlag);
+    @LayoutlibDelegate
+    static int getColor(Resources resources, int id) {
+        return getColor(resources, id, null);
+    }
+
+    @LayoutlibDelegate
+    static int getColor(Resources resources, int id, Theme theme) throws NotFoundException {
+        Pair<String, ResourceValue> value = getResourceValue(resources, id, mPlatformResourceFlag);
 
         if (value != null) {
             ResourceValue resourceValue = value.getSecond();
@@ -187,7 +160,7 @@
                 String message;
                 if (new File(resourceValue.getValue()).isFile()) {
                     String resource = (resourceValue.isFramework() ? "@android:" : "@") + "color/"
-                      + resourceValue.getName();
+                            + resourceValue.getName();
                     message = "Hexadecimal color expected, found Color State List for " + resource;
                 } else {
                     message = e.getMessage();
@@ -200,31 +173,57 @@
         // Suppress possible NPE. getColorStateList will never return null, it will instead
         // throw an exception, but intelliJ can't figure that out
         //noinspection ConstantConditions
-        return getColorStateList(id, theme).getDefaultColor();
+        return getColorStateList(resources, id, theme).getDefaultColor();
     }
 
-    @Override
-    public ColorStateList getColorStateList(int id, Theme theme) throws NotFoundException {
-        Pair<String, ResourceValue> resValue = getResourceValue(id, mPlatformResourceFlag);
+    @LayoutlibDelegate
+    static ColorStateList getColorStateList(Resources resources, int id) throws NotFoundException {
+        return getColorStateList(resources, id, null);
+    }
+
+    @LayoutlibDelegate
+    static ColorStateList getColorStateList(Resources resources, int id, Theme theme)
+            throws NotFoundException {
+        Pair<String, ResourceValue> resValue =
+                getResourceValue(resources, id, mPlatformResourceFlag);
 
         if (resValue != null) {
             ColorStateList stateList = ResourceHelper.getColorStateList(resValue.getSecond(),
-                    mContext);
+                    resources.mContext);
             if (stateList != null) {
                 return stateList.obtainForTheme(theme);
             }
         }
 
         // id was not found or not resolved. Throw a NotFoundException.
-        throwException(id);
+        throwException(resources, id);
 
         // this is not used since the method above always throws
         return null;
     }
 
-    @Override
-    public CharSequence getText(int id) throws NotFoundException {
-        Pair<String, ResourceValue> value = getResourceValue(id, mPlatformResourceFlag);
+    @LayoutlibDelegate
+    static CharSequence getText(Resources resources, int id, CharSequence def) {
+        Pair<String, ResourceValue> value = getResourceValue(resources, id, mPlatformResourceFlag);
+
+        if (value != null) {
+            ResourceValue resValue = value.getSecond();
+
+            assert resValue != null;
+            if (resValue != null) {
+                String v = resValue.getValue();
+                if (v != null) {
+                    return v;
+                }
+            }
+        }
+
+        return def;
+    }
+
+    @LayoutlibDelegate
+    static CharSequence getText(Resources resources, int id) throws NotFoundException {
+        Pair<String, ResourceValue> value = getResourceValue(resources, id, mPlatformResourceFlag);
 
         if (value != null) {
             ResourceValue resValue = value.getSecond();
@@ -239,38 +238,38 @@
         }
 
         // id was not found or not resolved. Throw a NotFoundException.
-        throwException(id);
+        throwException(resources, id);
 
         // this is not used since the method above always throws
         return null;
     }
 
-    @Override
-    public CharSequence[] getTextArray(int id) throws NotFoundException {
-        ResourceValue resValue = getArrayResourceValue(id);
+    @LayoutlibDelegate
+    static CharSequence[] getTextArray(Resources resources, int id) throws NotFoundException {
+        ResourceValue resValue = getArrayResourceValue(resources, id);
         if (resValue == null) {
             // Error already logged by getArrayResourceValue.
             return new CharSequence[0];
         } else if (!(resValue instanceof ArrayResourceValue)) {
             return new CharSequence[]{
-                    resolveReference(resValue.getValue(), resValue.isFramework())};
+                    resolveReference(resources, resValue.getValue(), resValue.isFramework())};
         }
         ArrayResourceValue arv = ((ArrayResourceValue) resValue);
-        return fillValues(arv, new CharSequence[arv.getElementCount()]);
+        return fillValues(resources, arv, new CharSequence[arv.getElementCount()]);
     }
 
-    @Override
-    public String[] getStringArray(int id) throws NotFoundException {
-        ResourceValue resValue = getArrayResourceValue(id);
+    @LayoutlibDelegate
+    static String[] getStringArray(Resources resources, int id) throws NotFoundException {
+        ResourceValue resValue = getArrayResourceValue(resources, id);
         if (resValue == null) {
             // Error already logged by getArrayResourceValue.
             return new String[0];
         } else if (!(resValue instanceof ArrayResourceValue)) {
             return new String[]{
-                    resolveReference(resValue.getValue(), resValue.isFramework())};
+                    resolveReference(resources, resValue.getValue(), resValue.isFramework())};
         }
         ArrayResourceValue arv = ((ArrayResourceValue) resValue);
-        return fillValues(arv, new String[arv.getElementCount()]);
+        return fillValues(resources, arv, new String[arv.getElementCount()]);
     }
 
     /**
@@ -278,25 +277,26 @@
      * always Strings. The ideal signature for the method should be &lt;T super String&gt;, but java
      * generics don't support it.
      */
-    <T extends CharSequence> T[] fillValues(ArrayResourceValue resValue, T[] values) {
+    static <T extends CharSequence> T[] fillValues(Resources resources, ArrayResourceValue resValue,
+            T[] values) {
         int i = 0;
         for (Iterator<String> iterator = resValue.iterator(); iterator.hasNext(); i++) {
             @SuppressWarnings("unchecked")
-            T s = (T) resolveReference(iterator.next(), resValue.isFramework());
+            T s = (T) resolveReference(resources, iterator.next(), resValue.isFramework());
             values[i] = s;
         }
         return values;
     }
 
-    @Override
-    public int[] getIntArray(int id) throws NotFoundException {
-        ResourceValue rv = getArrayResourceValue(id);
+    @LayoutlibDelegate
+    static int[] getIntArray(Resources resources, int id) throws NotFoundException {
+        ResourceValue rv = getArrayResourceValue(resources, id);
         if (rv == null) {
             // Error already logged by getArrayResourceValue.
             return new int[0];
         } else if (!(rv instanceof ArrayResourceValue)) {
             // This is an older IDE that can only give us the first element of the array.
-            String firstValue = resolveReference(rv.getValue(), rv.isFramework());
+            String firstValue = resolveReference(resources, rv.getValue(), rv.isFramework());
             try {
                 return new int[]{getInt(firstValue)};
             } catch (NumberFormatException e) {
@@ -310,7 +310,7 @@
         int[] values = new int[resValue.getElementCount()];
         int i = 0;
         for (Iterator<String> iterator = resValue.iterator(); iterator.hasNext(); i++) {
-            String element = resolveReference(iterator.next(), resValue.isFramework());
+            String element = resolveReference(resources, iterator.next(), resValue.isFramework());
             try {
                 values[i] = getInt(element);
             } catch (NumberFormatException e) {
@@ -330,11 +330,13 @@
      * method returns the ResourceValue. This happens on older versions of the IDE, which did not
      * parse the array resources properly.
      * <p/>
+     *
      * @throws NotFoundException if no resource if found
      */
     @Nullable
-    private ResourceValue getArrayResourceValue(int id) throws NotFoundException {
-        Pair<String, ResourceValue> v = getResourceValue(id, mPlatformResourceFlag);
+    private static ResourceValue getArrayResourceValue(Resources resources, int id)
+            throws NotFoundException {
+        Pair<String, ResourceValue> v = getResourceValue(resources, id, mPlatformResourceFlag);
 
         if (v != null) {
             ResourceValue resValue = v.getSecond();
@@ -360,19 +362,20 @@
         }
 
         // id was not found or not resolved. Throw a NotFoundException.
-        throwException(id);
+        throwException(resources, id);
 
         // this is not used since the method above always throws
         return null;
     }
 
     @NonNull
-    private String resolveReference(@NonNull String ref, boolean forceFrameworkOnly) {
+    private static String resolveReference(Resources resources, @NonNull String ref,
+            boolean forceFrameworkOnly) {
         if (ref.startsWith(SdkConstants.PREFIX_RESOURCE_REF) || ref.startsWith
                 (SdkConstants.PREFIX_THEME_REF)) {
             ResourceValue rv =
-                    mContext.getRenderResources().findResValue(ref, forceFrameworkOnly);
-            rv = mContext.getRenderResources().resolveResValue(rv);
+                    resources.mContext.getRenderResources().findResValue(ref, forceFrameworkOnly);
+            rv = resources.mContext.getRenderResources().resolveResValue(rv);
             if (rv != null) {
                 return rv.getValue();
             } else {
@@ -384,9 +387,9 @@
         return ref;
     }
 
-    @Override
-    public XmlResourceParser getLayout(int id) throws NotFoundException {
-        Pair<String, ResourceValue> v = getResourceValue(id, mPlatformResourceFlag);
+    @LayoutlibDelegate
+    static XmlResourceParser getLayout(Resources resources, int id) throws NotFoundException {
+        Pair<String, ResourceValue> v = getResourceValue(resources, id, mPlatformResourceFlag);
 
         if (v != null) {
             ResourceValue value = v.getSecond();
@@ -394,8 +397,8 @@
 
             try {
                 // check if the current parser can provide us with a custom parser.
-                if (mPlatformResourceFlag[0] == false) {
-                    parser = mLayoutlibCallback.getParser(value);
+                if (!mPlatformResourceFlag[0]) {
+                    parser = resources.mLayoutlibCallback.getParser(value);
                 }
 
                 // create a new one manually if needed.
@@ -409,7 +412,8 @@
                 }
 
                 if (parser != null) {
-                    return new BridgeXmlBlockParser(parser, mContext, mPlatformResourceFlag[0]);
+                    return new BridgeXmlBlockParser(parser, resources.mContext,
+                            mPlatformResourceFlag[0]);
                 }
             } catch (XmlPullParserException e) {
                 Bridge.getLog().error(LayoutLog.TAG_BROKEN,
@@ -422,19 +426,19 @@
         }
 
         // id was not found or not resolved. Throw a NotFoundException.
-        throwException(id);
+        throwException(resources, id);
 
         // this is not used since the method above always throws
         return null;
     }
 
-    @Override
-    public XmlResourceParser getAnimation(int id) throws NotFoundException {
-        Pair<String, ResourceValue> v = getResourceValue(id, mPlatformResourceFlag);
+    @LayoutlibDelegate
+    static XmlResourceParser getAnimation(Resources resources, int id) throws NotFoundException {
+        Pair<String, ResourceValue> v = getResourceValue(resources, id, mPlatformResourceFlag);
 
         if (v != null) {
             ResourceValue value = v.getSecond();
-            XmlPullParser parser = null;
+            XmlPullParser parser;
 
             try {
                 File xml = new File(value.getValue());
@@ -443,7 +447,8 @@
                     // give that to our XmlBlockParser
                     parser = ParserFactory.create(xml);
 
-                    return new BridgeXmlBlockParser(parser, mContext, mPlatformResourceFlag[0]);
+                    return new BridgeXmlBlockParser(parser, resources.mContext,
+                            mPlatformResourceFlag[0]);
                 }
             } catch (XmlPullParserException e) {
                 Bridge.getLog().error(LayoutLog.TAG_BROKEN,
@@ -456,26 +461,31 @@
         }
 
         // id was not found or not resolved. Throw a NotFoundException.
-        throwException(id);
+        throwException(resources, id);
 
         // this is not used since the method above always throws
         return null;
     }
 
-    @Override
-    public TypedArray obtainAttributes(AttributeSet set, int[] attrs) {
-        return mContext.obtainStyledAttributes(set, attrs);
+    @LayoutlibDelegate
+    static TypedArray obtainAttributes(Resources resources, AttributeSet set, int[] attrs) {
+        return resources.mContext.obtainStyledAttributes(set, attrs);
     }
 
-    @Override
-    public TypedArray obtainTypedArray(int id) throws NotFoundException {
+    @LayoutlibDelegate
+    static TypedArray obtainAttributes(Resources resources, Resources.Theme theme, AttributeSet
+            set, int[] attrs) {
+        return Resources.obtainAttributes_Original(resources, theme, set, attrs);
+    }
+
+    @LayoutlibDelegate
+    static TypedArray obtainTypedArray(Resources resources, int id) throws NotFoundException {
         throw new UnsupportedOperationException();
     }
 
-
-    @Override
-    public float getDimension(int id) throws NotFoundException {
-        Pair<String, ResourceValue> value = getResourceValue(id, mPlatformResourceFlag);
+    @LayoutlibDelegate
+    static float getDimension(Resources resources, int id) throws NotFoundException {
+        Pair<String, ResourceValue> value = getResourceValue(resources, id, mPlatformResourceFlag);
 
         if (value != null) {
             ResourceValue resValue = value.getSecond();
@@ -490,26 +500,26 @@
                     } else if (v.equals(BridgeConstants.WRAP_CONTENT)) {
                         return LayoutParams.WRAP_CONTENT;
                     }
-
+                    TypedValue tmpValue = new TypedValue();
                     if (ResourceHelper.parseFloatAttribute(
-                            value.getFirst(), v, mTmpValue, true /*requireUnit*/) &&
-                            mTmpValue.type == TypedValue.TYPE_DIMENSION) {
-                        return mTmpValue.getDimension(getDisplayMetrics());
+                            value.getFirst(), v, tmpValue, true /*requireUnit*/) &&
+                            tmpValue.type == TypedValue.TYPE_DIMENSION) {
+                        return tmpValue.getDimension(resources.getDisplayMetrics());
                     }
                 }
             }
         }
 
         // id was not found or not resolved. Throw a NotFoundException.
-        throwException(id);
+        throwException(resources, id);
 
         // this is not used since the method above always throws
         return 0;
     }
 
-    @Override
-    public int getDimensionPixelOffset(int id) throws NotFoundException {
-        Pair<String, ResourceValue> value = getResourceValue(id, mPlatformResourceFlag);
+    @LayoutlibDelegate
+    static int getDimensionPixelOffset(Resources resources, int id) throws NotFoundException {
+        Pair<String, ResourceValue> value = getResourceValue(resources, id, mPlatformResourceFlag);
 
         if (value != null) {
             ResourceValue resValue = value.getSecond();
@@ -518,26 +528,27 @@
             if (resValue != null) {
                 String v = resValue.getValue();
                 if (v != null) {
+                    TypedValue tmpValue = new TypedValue();
                     if (ResourceHelper.parseFloatAttribute(
-                            value.getFirst(), v, mTmpValue, true /*requireUnit*/) &&
-                            mTmpValue.type == TypedValue.TYPE_DIMENSION) {
-                        return TypedValue.complexToDimensionPixelOffset(mTmpValue.data,
-                                getDisplayMetrics());
+                            value.getFirst(), v, tmpValue, true /*requireUnit*/) &&
+                            tmpValue.type == TypedValue.TYPE_DIMENSION) {
+                        return TypedValue.complexToDimensionPixelOffset(tmpValue.data,
+                                resources.getDisplayMetrics());
                     }
                 }
             }
         }
 
         // id was not found or not resolved. Throw a NotFoundException.
-        throwException(id);
+        throwException(resources, id);
 
         // this is not used since the method above always throws
         return 0;
     }
 
-    @Override
-    public int getDimensionPixelSize(int id) throws NotFoundException {
-        Pair<String, ResourceValue> value = getResourceValue(id, mPlatformResourceFlag);
+    @LayoutlibDelegate
+    static int getDimensionPixelSize(Resources resources, int id) throws NotFoundException {
+        Pair<String, ResourceValue> value = getResourceValue(resources, id, mPlatformResourceFlag);
 
         if (value != null) {
             ResourceValue resValue = value.getSecond();
@@ -546,26 +557,27 @@
             if (resValue != null) {
                 String v = resValue.getValue();
                 if (v != null) {
+                    TypedValue tmpValue = new TypedValue();
                     if (ResourceHelper.parseFloatAttribute(
-                            value.getFirst(), v, mTmpValue, true /*requireUnit*/) &&
-                            mTmpValue.type == TypedValue.TYPE_DIMENSION) {
-                        return TypedValue.complexToDimensionPixelSize(mTmpValue.data,
-                                getDisplayMetrics());
+                            value.getFirst(), v, tmpValue, true /*requireUnit*/) &&
+                            tmpValue.type == TypedValue.TYPE_DIMENSION) {
+                        return TypedValue.complexToDimensionPixelSize(tmpValue.data,
+                                resources.getDisplayMetrics());
                     }
                 }
             }
         }
 
         // id was not found or not resolved. Throw a NotFoundException.
-        throwException(id);
+        throwException(resources, id);
 
         // this is not used since the method above always throws
         return 0;
     }
 
-    @Override
-    public int getInteger(int id) throws NotFoundException {
-        Pair<String, ResourceValue> value = getResourceValue(id, mPlatformResourceFlag);
+    @LayoutlibDelegate
+    static int getInteger(Resources resources, int id) throws NotFoundException {
+        Pair<String, ResourceValue> value = getResourceValue(resources, id, mPlatformResourceFlag);
 
         if (value != null) {
             ResourceValue resValue = value.getSecond();
@@ -584,15 +596,15 @@
         }
 
         // id was not found or not resolved. Throw a NotFoundException.
-        throwException(id);
+        throwException(resources, id);
 
         // this is not used since the method above always throws
         return 0;
     }
 
-    @Override
-    public boolean getBoolean(int id) throws NotFoundException {
-        Pair<String, ResourceValue> value = getResourceValue(id, mPlatformResourceFlag);
+    @LayoutlibDelegate
+    static boolean getBoolean(Resources resources, int id) throws NotFoundException {
+        Pair<String, ResourceValue> value = getResourceValue(resources, id, mPlatformResourceFlag);
 
         if (value != null) {
             ResourceValue resValue = value.getSecond();
@@ -606,61 +618,62 @@
         }
 
         // id was not found or not resolved. Throw a NotFoundException.
-        throwException(id);
+        throwException(resources, id);
 
         // this is not used since the method above always throws
         return false;
     }
 
-    @Override
-    public String getResourceEntryName(int resid) throws NotFoundException {
+    @LayoutlibDelegate
+    static String getResourceEntryName(Resources resources, int resid) throws NotFoundException {
         throw new UnsupportedOperationException();
     }
 
-    @Override
-    public String getResourceName(int resid) throws NotFoundException {
+    @LayoutlibDelegate
+    static String getResourceName(Resources resources, int resid) throws NotFoundException {
         throw new UnsupportedOperationException();
     }
 
-    @Override
-    public String getResourceTypeName(int resid) throws NotFoundException {
+    @LayoutlibDelegate
+    static String getResourceTypeName(Resources resources, int resid) throws NotFoundException {
         throw new UnsupportedOperationException();
     }
 
-    @Override
-    public String getString(int id, Object... formatArgs) throws NotFoundException {
-        String s = getString(id);
+    @LayoutlibDelegate
+    static String getString(Resources resources, int id, Object... formatArgs)
+            throws NotFoundException {
+        String s = getString(resources, id);
         if (s != null) {
             return String.format(s, formatArgs);
 
         }
 
         // id was not found or not resolved. Throw a NotFoundException.
-        throwException(id);
+        throwException(resources, id);
 
         // this is not used since the method above always throws
         return null;
     }
 
-    @Override
-    public String getString(int id) throws NotFoundException {
-        Pair<String, ResourceValue> value = getResourceValue(id, mPlatformResourceFlag);
+    @LayoutlibDelegate
+    static String getString(Resources resources, int id) throws NotFoundException {
+        Pair<String, ResourceValue> value = getResourceValue(resources, id, mPlatformResourceFlag);
 
         if (value != null && value.getSecond().getValue() != null) {
             return value.getSecond().getValue();
         }
 
         // id was not found or not resolved. Throw a NotFoundException.
-        throwException(id);
+        throwException(resources, id);
 
         // this is not used since the method above always throws
         return null;
     }
 
-    @Override
-    public void getValue(int id, TypedValue outValue, boolean resolveRefs)
+    @LayoutlibDelegate
+    static void getValue(Resources resources, int id, TypedValue outValue, boolean resolveRefs)
             throws NotFoundException {
-        Pair<String, ResourceValue> value = getResourceValue(id, mPlatformResourceFlag);
+        Pair<String, ResourceValue> value = getResourceValue(resources, id, mPlatformResourceFlag);
 
         if (value != null) {
             ResourceValue resVal = value.getSecond();
@@ -673,7 +686,7 @@
                 }
                 if (resVal instanceof DensityBasedResourceValue) {
                     outValue.density =
-                      ((DensityBasedResourceValue) resVal).getResourceDensity().getDpiValue();
+                            ((DensityBasedResourceValue) resVal).getResourceDensity().getDpiValue();
                 }
 
                 // else it's a string
@@ -684,18 +697,18 @@
         }
 
         // id was not found or not resolved. Throw a NotFoundException.
-        throwException(id);
+        throwException(resources, id);
     }
 
-    @Override
-    public void getValue(String name, TypedValue outValue, boolean resolveRefs)
+    @LayoutlibDelegate
+    static void getValue(Resources resources, String name, TypedValue outValue, boolean resolveRefs)
             throws NotFoundException {
         throw new UnsupportedOperationException();
     }
 
-    @Override
-    public XmlResourceParser getXml(int id) throws NotFoundException {
-        Pair<String, ResourceValue> value = getResourceValue(id, mPlatformResourceFlag);
+    @LayoutlibDelegate
+    static XmlResourceParser getXml(Resources resources, int id) throws NotFoundException {
+        Pair<String, ResourceValue> value = getResourceValue(resources, id, mPlatformResourceFlag);
 
         if (value != null) {
             String v = value.getSecond().getValue();
@@ -707,7 +720,8 @@
                     try {
                         XmlPullParser parser = ParserFactory.create(f);
 
-                        return new BridgeXmlBlockParser(parser, mContext, mPlatformResourceFlag[0]);
+                        return new BridgeXmlBlockParser(parser, resources.mContext,
+                                mPlatformResourceFlag[0]);
                     } catch (XmlPullParserException e) {
                         NotFoundException newE = new NotFoundException();
                         newE.initCause(e);
@@ -722,25 +736,31 @@
         }
 
         // id was not found or not resolved. Throw a NotFoundException.
-        throwException(id);
+        throwException(resources, id);
 
         // this is not used since the method above always throws
         return null;
     }
 
-    @Override
-    public XmlResourceParser loadXmlResourceParser(String file, int id,
+    @LayoutlibDelegate
+    static XmlResourceParser loadXmlResourceParser(Resources resources, int id,
+            String type) throws NotFoundException {
+        return resources.loadXmlResourceParser_Original(id, type);
+    }
+
+    @LayoutlibDelegate
+    static XmlResourceParser loadXmlResourceParser(Resources resources, String file, int id,
             int assetCookie, String type) throws NotFoundException {
         // even though we know the XML file to load directly, we still need to resolve the
         // id so that we can know if it's a platform or project resource.
         // (mPlatformResouceFlag will get the result and will be used later).
-        getResourceValue(id, mPlatformResourceFlag);
+        getResourceValue(resources, id, mPlatformResourceFlag);
 
         File f = new File(file);
         try {
             XmlPullParser parser = ParserFactory.create(f);
 
-            return new BridgeXmlBlockParser(parser, mContext, mPlatformResourceFlag[0]);
+            return new BridgeXmlBlockParser(parser, resources.mContext, mPlatformResourceFlag[0]);
         } catch (XmlPullParserException e) {
             NotFoundException newE = new NotFoundException();
             newE.initCause(e);
@@ -752,9 +772,9 @@
         }
     }
 
-    @Override
-    public InputStream openRawResource(int id) throws NotFoundException {
-        Pair<String, ResourceValue> value = getResourceValue(id, mPlatformResourceFlag);
+    @LayoutlibDelegate
+    static InputStream openRawResource(Resources resources, int id) throws NotFoundException {
+        Pair<String, ResourceValue> value = getResourceValue(resources, id, mPlatformResourceFlag);
 
         if (value != null) {
             String path = value.getSecond().getValue();
@@ -781,15 +801,16 @@
         }
 
         // id was not found or not resolved. Throw a NotFoundException.
-        throwException(id);
+        throwException(resources, id);
 
         // this is not used since the method above always throws
         return null;
     }
 
-    @Override
-    public InputStream openRawResource(int id, TypedValue value) throws NotFoundException {
-        getValue(id, value, true);
+    @LayoutlibDelegate
+    static InputStream openRawResource(Resources resources, int id, TypedValue value) throws
+            NotFoundException {
+        getValue(resources, id, value, true);
 
         String path = value.string.toString();
 
@@ -813,23 +834,27 @@
         throw new NotFoundException();
     }
 
-    @Override
-    public AssetFileDescriptor openRawResourceFd(int id) throws NotFoundException {
+    @LayoutlibDelegate
+    static AssetFileDescriptor openRawResourceFd(Resources resources, int id) throws
+            NotFoundException {
         throw new UnsupportedOperationException();
     }
 
     /**
-     * Builds and throws a {@link Resources.NotFoundException} based on a resource id and a resource type.
+     * Builds and throws a {@link Resources.NotFoundException} based on a resource id and a resource
+     * type.
+     *
      * @param id the id of the resource
+     *
      * @throws NotFoundException
      */
-    private void throwException(int id) throws NotFoundException {
+    private static void throwException(Resources resources, int id) throws NotFoundException {
         // first get the String related to this id in the framework
         Pair<ResourceType, String> resourceInfo = Bridge.resolveResourceId(id);
 
         // if the name is unknown in the framework, get it from the custom view loader.
-        if (resourceInfo == null && mLayoutlibCallback != null) {
-            resourceInfo = mLayoutlibCallback.resolveResourceId(id);
+        if (resourceInfo == null && resources.mLayoutlibCallback != null) {
+            resourceInfo = resources.mLayoutlibCallback.resolveResourceId(id);
         }
 
         String message;
@@ -845,7 +870,7 @@
         throw new NotFoundException(message);
     }
 
-    private int getInt(String v) throws NumberFormatException {
+    private static int getInt(String v) throws NumberFormatException {
         int radix = 10;
         if (v.startsWith("0x")) {
             v = v.substring(2);
diff --git a/tools/layoutlib/bridge/src/android/graphics/BitmapFactory_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/BitmapFactory_Delegate.java
index 8d5863b..8bd2a7a 100644
--- a/tools/layoutlib/bridge/src/android/graphics/BitmapFactory_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/BitmapFactory_Delegate.java
@@ -23,7 +23,7 @@
 import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
 
 import android.annotation.Nullable;
-import android.content.res.BridgeResources.NinePatchInputStream;
+import com.android.layoutlib.bridge.util.NinePatchInputStream;
 import android.graphics.BitmapFactory.Options;
 import android.graphics.Bitmap_Delegate.BitmapCreateFlags;
 
diff --git a/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java
index c4fbd56..fa880f0 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java
@@ -142,7 +142,7 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static void native_setBitmap(long canvas, Bitmap bitmap) {
+    public static void native_setBitmap(long canvas, Bitmap bitmap) {
         Canvas_Delegate canvasDelegate = sManager.getDelegate(canvas);
         Bitmap_Delegate bitmapDelegate = Bitmap_Delegate.getDelegate(bitmap);
         if (canvasDelegate == null || bitmapDelegate==null) {
@@ -153,7 +153,7 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static boolean native_isOpaque(long nativeCanvas) {
+    public static boolean native_isOpaque(long nativeCanvas) {
         // get the delegate from the native int.
         Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
         if (canvasDelegate == null) {
@@ -164,10 +164,10 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static void native_setHighContrastText(long nativeCanvas, boolean highContrastText){}
+    public static void native_setHighContrastText(long nativeCanvas, boolean highContrastText){}
 
     @LayoutlibDelegate
-    /*package*/ static int native_getWidth(long nativeCanvas) {
+    public static int native_getWidth(long nativeCanvas) {
         // get the delegate from the native int.
         Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
         if (canvasDelegate == null) {
@@ -178,7 +178,7 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static int native_getHeight(long nativeCanvas) {
+    public static int native_getHeight(long nativeCanvas) {
         // get the delegate from the native int.
         Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
         if (canvasDelegate == null) {
@@ -189,7 +189,7 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static int native_save(long nativeCanvas, int saveFlags) {
+    public static int native_save(long nativeCanvas, int saveFlags) {
         // get the delegate from the native int.
         Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
         if (canvasDelegate == null) {
@@ -200,7 +200,7 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static int native_saveLayer(long nativeCanvas, float l,
+    public static int native_saveLayer(long nativeCanvas, float l,
                                                float t, float r, float b,
                                                long paint, int layerFlags) {
         // get the delegate from the native int.
@@ -219,7 +219,7 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static int native_saveLayerAlpha(long nativeCanvas, float l,
+    public static int native_saveLayerAlpha(long nativeCanvas, float l,
                                                     float t, float r, float b,
                                                     int alpha, int layerFlags) {
         // get the delegate from the native int.
@@ -232,7 +232,7 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static void native_restore(long nativeCanvas, boolean throwOnUnderflow) {
+    public static void native_restore(long nativeCanvas, boolean throwOnUnderflow) {
         // FIXME: implement throwOnUnderflow.
         // get the delegate from the native int.
         Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
@@ -244,7 +244,7 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static void native_restoreToCount(long nativeCanvas, int saveCount,
+    public static void native_restoreToCount(long nativeCanvas, int saveCount,
             boolean throwOnUnderflow) {
         // FIXME: implement throwOnUnderflow.
         // get the delegate from the native int.
@@ -257,7 +257,7 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static int native_getSaveCount(long nativeCanvas) {
+    public static int native_getSaveCount(long nativeCanvas) {
         // get the delegate from the native int.
         Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
         if (canvasDelegate == null) {
@@ -268,7 +268,7 @@
     }
 
     @LayoutlibDelegate
-   /*package*/ static void native_translate(long nativeCanvas, float dx, float dy) {
+   public static void native_translate(long nativeCanvas, float dx, float dy) {
         // get the delegate from the native int.
         Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
         if (canvasDelegate == null) {
@@ -279,7 +279,7 @@
     }
 
     @LayoutlibDelegate
-       /*package*/ static void native_scale(long nativeCanvas, float sx, float sy) {
+       public static void native_scale(long nativeCanvas, float sx, float sy) {
             // get the delegate from the native int.
             Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
             if (canvasDelegate == null) {
@@ -290,7 +290,7 @@
         }
 
     @LayoutlibDelegate
-    /*package*/ static void native_rotate(long nativeCanvas, float degrees) {
+    public static void native_rotate(long nativeCanvas, float degrees) {
         // get the delegate from the native int.
         Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
         if (canvasDelegate == null) {
@@ -301,7 +301,7 @@
     }
 
     @LayoutlibDelegate
-   /*package*/ static void native_skew(long nativeCanvas, float kx, float ky) {
+   public static void native_skew(long nativeCanvas, float kx, float ky) {
         // get the delegate from the native int.
         Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
         if (canvasDelegate == null) {
@@ -325,7 +325,7 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static void native_concat(long nCanvas, long nMatrix) {
+    public static void native_concat(long nCanvas, long nMatrix) {
         // get the delegate from the native int.
         Canvas_Delegate canvasDelegate = sManager.getDelegate(nCanvas);
         if (canvasDelegate == null) {
@@ -353,7 +353,7 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static void native_setMatrix(long nCanvas, long nMatrix) {
+    public static void native_setMatrix(long nCanvas, long nMatrix) {
         // get the delegate from the native int.
         Canvas_Delegate canvasDelegate = sManager.getDelegate(nCanvas);
         if (canvasDelegate == null) {
@@ -383,7 +383,7 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static boolean native_clipRect(long nCanvas,
+    public static boolean native_clipRect(long nCanvas,
                                                   float left, float top,
                                                   float right, float bottom,
                                                   int regionOp) {
@@ -397,7 +397,7 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static boolean native_clipPath(long nativeCanvas,
+    public static boolean native_clipPath(long nativeCanvas,
                                                   long nativePath,
                                                   int regionOp) {
         Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
@@ -414,7 +414,7 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static boolean native_clipRegion(long nativeCanvas,
+    public static boolean native_clipRegion(long nativeCanvas,
                                                     long nativeRegion,
                                                     int regionOp) {
         Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
@@ -431,7 +431,7 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static void nativeSetDrawFilter(long nativeCanvas, long nativeFilter) {
+    public static void nativeSetDrawFilter(long nativeCanvas, long nativeFilter) {
         Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
         if (canvasDelegate == null) {
             return;
@@ -446,7 +446,7 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static boolean native_getClipBounds(long nativeCanvas,
+    public static boolean native_getClipBounds(long nativeCanvas,
                                                        Rect bounds) {
         // get the delegate from the native int.
         Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
@@ -467,7 +467,7 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static void native_getCTM(long canvas, long matrix) {
+    public static void native_getCTM(long canvas, long matrix) {
         // get the delegate from the native int.
         Canvas_Delegate canvasDelegate = sManager.getDelegate(canvas);
         if (canvasDelegate == null) {
@@ -484,13 +484,13 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static boolean native_quickReject(long nativeCanvas, long path) {
+    public static boolean native_quickReject(long nativeCanvas, long path) {
         // FIXME properly implement quickReject
         return false;
     }
 
     @LayoutlibDelegate
-    /*package*/ static boolean native_quickReject(long nativeCanvas,
+    public static boolean native_quickReject(long nativeCanvas,
                                                      float left, float top,
                                                      float right, float bottom) {
         // FIXME properly implement quickReject
@@ -498,7 +498,7 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static void native_drawColor(long nativeCanvas, final int color, final int mode) {
+    public static void native_drawColor(long nativeCanvas, final int color, final int mode) {
         // get the delegate from the native int.
         Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
         if (canvasDelegate == null) {
@@ -529,14 +529,14 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static void native_drawPaint(long nativeCanvas, long paint) {
+    public static void native_drawPaint(long nativeCanvas, long paint) {
         // FIXME
         Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
                 "Canvas.drawPaint is not supported.", null, null /*data*/);
     }
 
     @LayoutlibDelegate
-    /*package*/ static void native_drawPoint(long nativeCanvas, float x, float y,
+    public static void native_drawPoint(long nativeCanvas, float x, float y,
             long nativePaint) {
         // FIXME
         Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
@@ -544,7 +544,7 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static void native_drawPoints(long nativeCanvas, float[] pts, int offset, int count,
+    public static void native_drawPoints(long nativeCanvas, float[] pts, int offset, int count,
             long nativePaint) {
         // FIXME
         Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
@@ -552,7 +552,7 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static void native_drawLine(long nativeCanvas,
+    public static void native_drawLine(long nativeCanvas,
             final float startX, final float startY, final float stopX, final float stopY,
             long paint) {
         draw(nativeCanvas, paint, false /*compositeOnly*/, false /*forceSrcMode*/,
@@ -565,7 +565,7 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static void native_drawLines(long nativeCanvas,
+    public static void native_drawLines(long nativeCanvas,
             final float[] pts, final int offset, final int count,
             long nativePaint) {
         draw(nativeCanvas, nativePaint, false /*compositeOnly*/,
@@ -581,7 +581,7 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static void native_drawRect(long nativeCanvas,
+    public static void native_drawRect(long nativeCanvas,
             final float left, final float top, final float right, final float bottom, long paint) {
 
         draw(nativeCanvas, paint, false /*compositeOnly*/, false /*forceSrcMode*/,
@@ -607,7 +607,7 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static void native_drawOval(long nativeCanvas, final float left,
+    public static void native_drawOval(long nativeCanvas, final float left,
             final float top, final float right, final float bottom, long paint) {
         if (right > left && bottom > top) {
             draw(nativeCanvas, paint, false /*compositeOnly*/, false /*forceSrcMode*/,
@@ -634,7 +634,7 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static void native_drawCircle(long nativeCanvas,
+    public static void native_drawCircle(long nativeCanvas,
             float cx, float cy, float radius, long paint) {
         native_drawOval(nativeCanvas,
                 cx - radius, cy - radius, cx + radius, cy + radius,
@@ -642,7 +642,7 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static void native_drawArc(long nativeCanvas,
+    public static void native_drawArc(long nativeCanvas,
             final float left, final float top, final float right, final float bottom,
             final float startAngle, final float sweep,
             final boolean useCenter, long paint) {
@@ -674,7 +674,7 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static void native_drawRoundRect(long nativeCanvas,
+    public static void native_drawRoundRect(long nativeCanvas,
             final float left, final float top, final float right, final float bottom,
             final float rx, final float ry, long paint) {
         draw(nativeCanvas, paint, false /*compositeOnly*/, false /*forceSrcMode*/,
@@ -704,7 +704,7 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static void native_drawPath(long nativeCanvas, long path, long paint) {
+    public static void native_drawPath(long nativeCanvas, long path, long paint) {
         final Path_Delegate pathDelegate = Path_Delegate.getDelegate(path);
         if (pathDelegate == null) {
             return;
@@ -756,7 +756,7 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static void native_drawRegion(long nativeCanvas, long nativeRegion,
+    public static void native_drawRegion(long nativeCanvas, long nativeRegion,
             long nativePaint) {
         // FIXME
         Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
@@ -764,7 +764,7 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static void native_drawNinePatch(Canvas thisCanvas, long nativeCanvas,
+    public static void native_drawNinePatch(Canvas thisCanvas, long nativeCanvas,
             long nativeBitmap, long ninePatch, final float dstLeft, final float dstTop,
             final float dstRight, final float dstBottom, long nativePaintOrZero,
             final int screenDensity, final int bitmapDensity) {
@@ -811,7 +811,7 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static void native_drawBitmap(Canvas thisCanvas, long nativeCanvas, Bitmap bitmap,
+    public static void native_drawBitmap(Canvas thisCanvas, long nativeCanvas, Bitmap bitmap,
                                                  float left, float top,
                                                  long nativePaintOrZero,
                                                  int canvasDensity,
@@ -833,7 +833,7 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static void native_drawBitmap(Canvas thisCanvas, long nativeCanvas, Bitmap bitmap,
+    public static void native_drawBitmap(Canvas thisCanvas, long nativeCanvas, Bitmap bitmap,
                                  float srcLeft, float srcTop, float srcRight, float srcBottom,
                                  float dstLeft, float dstTop, float dstRight, float dstBottom,
                                  long nativePaintOrZero, int screenDensity, int bitmapDensity) {
@@ -849,7 +849,7 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static void native_drawBitmap(long nativeCanvas, int[] colors,
+    public static void native_drawBitmap(long nativeCanvas, int[] colors,
                                                 int offset, int stride, final float x,
                                                  final float y, int width, int height,
                                                  boolean hasAlpha,
@@ -874,7 +874,7 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static void nativeDrawBitmapMatrix(long nCanvas, Bitmap bitmap,
+    public static void nativeDrawBitmapMatrix(long nCanvas, Bitmap bitmap,
                                                       long nMatrix, long nPaint) {
         // get the delegate from the native int.
         Canvas_Delegate canvasDelegate = sManager.getDelegate(nCanvas);
@@ -915,7 +915,7 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static void nativeDrawBitmapMesh(long nCanvas, Bitmap bitmap,
+    public static void nativeDrawBitmapMesh(long nCanvas, Bitmap bitmap,
             int meshWidth, int meshHeight, float[] verts, int vertOffset, int[] colors,
             int colorOffset, long nPaint) {
         // FIXME
@@ -924,7 +924,7 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static void nativeDrawVertices(long nCanvas, int mode, int n,
+    public static void nativeDrawVertices(long nCanvas, int mode, int n,
             float[] verts, int vertOffset,
             float[] texs, int texOffset,
             int[] colors, int colorOffset,
@@ -936,14 +936,14 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static void native_drawText(long nativeCanvas, char[] text, int index, int count,
+    public static void native_drawText(long nativeCanvas, char[] text, int index, int count,
             float startX, float startY, int flags, long paint, long typeface) {
         drawText(nativeCanvas, text, index, count, startX, startY, (flags & 1) != 0,
                 paint, typeface);
     }
 
     @LayoutlibDelegate
-    /*package*/ static void native_drawText(long nativeCanvas, String text,
+    public static void native_drawText(long nativeCanvas, String text,
             int start, int end, float x, float y, final int flags, long paint,
             long typeface) {
         int count = end - start;
@@ -954,7 +954,7 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static void native_drawTextRun(long nativeCanvas, String text,
+    public static void native_drawTextRun(long nativeCanvas, String text,
             int start, int end, int contextStart, int contextEnd,
             float x, float y, boolean isRtl, long paint, long typeface) {
         int count = end - start;
@@ -965,14 +965,14 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static void native_drawTextRun(long nativeCanvas, char[] text,
+    public static void native_drawTextRun(long nativeCanvas, char[] text,
             int start, int count, int contextStart, int contextCount,
             float x, float y, boolean isRtl, long paint, long typeface) {
         drawText(nativeCanvas, text, start, count, x, y, isRtl, paint, typeface);
     }
 
     @LayoutlibDelegate
-    /*package*/ static void native_drawTextOnPath(long nativeCanvas,
+    public static void native_drawTextOnPath(long nativeCanvas,
                                                      char[] text, int index,
                                                      int count, long path,
                                                      float hOffset,
@@ -984,7 +984,7 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static void native_drawTextOnPath(long nativeCanvas,
+    public static void native_drawTextOnPath(long nativeCanvas,
                                                      String text, long path,
                                                      float hOffset,
                                                      float vOffset,
diff --git a/tools/layoutlib/bridge/src/android/graphics/Paint_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Paint_Delegate.java
index 514d785..33296e1 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Paint_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Paint_Delegate.java
@@ -223,6 +223,14 @@
         return mColorFilter;
     }
 
+    public void setColorFilter(long colorFilterPtr) {
+        mColorFilter = ColorFilter_Delegate.getDelegate(colorFilterPtr);
+    }
+
+    public void setShader(long shaderPtr) {
+        mShader = Shader_Delegate.getDelegate(shaderPtr);
+    }
+
     /**
      * Returns the {@link Shader} delegate or null if none have been set
      *
diff --git a/tools/layoutlib/bridge/src/android/graphics/Path_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Path_Delegate.java
index e1da27b..08f0cb4 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Path_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Path_Delegate.java
@@ -572,7 +572,7 @@
         return null;
     }
 
-    private static void addPath(long destPath, long srcPath, AffineTransform transform) {
+    public static void addPath(long destPath, long srcPath, AffineTransform transform) {
         Path_Delegate destPathDelegate = sManager.getDelegate(destPath);
         if (destPathDelegate == null) {
             return;
@@ -630,7 +630,7 @@
      * Fills the given {@link RectF} with the path bounds.
      * @param bounds the RectF to be filled.
      */
-    private void fillBounds(RectF bounds) {
+    public void fillBounds(RectF bounds) {
         Rectangle2D rect = mPath.getBounds2D();
         bounds.left = (float)rect.getMinX();
         bounds.right = (float)rect.getMaxX();
@@ -644,7 +644,7 @@
      * @param x The x-coordinate of the start of a new contour
      * @param y The y-coordinate of the start of a new contour
      */
-    private void moveTo(float x, float y) {
+    public void moveTo(float x, float y) {
         mPath.moveTo(mLastX = x, mLastY = y);
     }
 
@@ -658,7 +658,7 @@
      * @param dy The amount to add to the y-coordinate of the end of the
      *           previous contour, to specify the start of a new contour
      */
-    private void rMoveTo(float dx, float dy) {
+    public void rMoveTo(float dx, float dy) {
         dx += mLastX;
         dy += mLastY;
         mPath.moveTo(mLastX = dx, mLastY = dy);
@@ -672,7 +672,7 @@
      * @param x The x-coordinate of the end of a line
      * @param y The y-coordinate of the end of a line
      */
-    private void lineTo(float x, float y) {
+    public void lineTo(float x, float y) {
         if (!hasPoints()) {
             mPath.moveTo(mLastX = 0, mLastY = 0);
         }
@@ -689,7 +689,7 @@
      * @param dy The amount to add to the y-coordinate of the previous point on
      *           this contour, to specify a line
      */
-    private void rLineTo(float dx, float dy) {
+    public void rLineTo(float dx, float dy) {
         if (!hasPoints()) {
             mPath.moveTo(mLastX = 0, mLastY = 0);
         }
@@ -714,7 +714,7 @@
      * @param x2 The x-coordinate of the end point on a quadratic curve
      * @param y2 The y-coordinate of the end point on a quadratic curve
      */
-    private void quadTo(float x1, float y1, float x2, float y2) {
+    public void quadTo(float x1, float y1, float x2, float y2) {
         mPath.quadTo(x1, y1, mLastX = x2, mLastY = y2);
     }
 
@@ -732,7 +732,7 @@
      * @param dy2 The amount to add to the y-coordinate of the last point on
      *            this contour, for the end point of a quadratic curve
      */
-    private void rQuadTo(float dx1, float dy1, float dx2, float dy2) {
+    public void rQuadTo(float dx1, float dy1, float dx2, float dy2) {
         if (!hasPoints()) {
             mPath.moveTo(mLastX = 0, mLastY = 0);
         }
@@ -755,7 +755,7 @@
      * @param x3 The x-coordinate of the end point on a cubic curve
      * @param y3 The y-coordinate of the end point on a cubic curve
      */
-    private void cubicTo(float x1, float y1, float x2, float y2,
+    public void cubicTo(float x1, float y1, float x2, float y2,
                         float x3, float y3) {
         if (!hasPoints()) {
             mPath.moveTo(0, 0);
@@ -768,7 +768,7 @@
      * current point on this contour. If there is no previous point, then a
      * moveTo(0,0) is inserted automatically.
      */
-    private void rCubicTo(float dx1, float dy1, float dx2, float dy2,
+    public void rCubicTo(float dx1, float dy1, float dx2, float dy2,
                          float dx3, float dy3) {
         if (!hasPoints()) {
             mPath.moveTo(mLastX = 0, mLastY = 0);
@@ -798,7 +798,7 @@
      *                    mod 360.
      * @param forceMoveTo If true, always begin a new contour with the arc
      */
-    private void arcTo(float left, float top, float right, float bottom, float startAngle,
+    public void arcTo(float left, float top, float right, float bottom, float startAngle,
             float sweepAngle,
             boolean forceMoveTo) {
         Arc2D arc = new Arc2D.Float(left, top, right - left, bottom - top, -startAngle,
@@ -812,7 +812,7 @@
      * Close the current contour. If the current point is not equal to the
      * first point of the contour, a line segment is automatically added.
      */
-    private void close() {
+    public void close() {
         mPath.closePath();
     }
 
@@ -831,7 +831,7 @@
      * @param bottom The bottom of a rectangle to add to the path
      * @param dir    The direction to wind the rectangle's contour
      */
-    private void addRect(float left, float top, float right, float bottom,
+    public void addRect(float left, float top, float right, float bottom,
                         int dir) {
         moveTo(left, top);
 
diff --git a/tools/layoutlib/bridge/src/android/graphics/drawable/AnimatedVectorDrawable_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/drawable/AnimatedVectorDrawable_Delegate.java
new file mode 100644
index 0000000..200fe3b
--- /dev/null
+++ b/tools/layoutlib/bridge/src/android/graphics/drawable/AnimatedVectorDrawable_Delegate.java
@@ -0,0 +1,284 @@
+/*
+ * 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.graphics.drawable;
+
+import com.android.ide.common.rendering.api.LayoutLog;
+import com.android.internal.view.animation.NativeInterpolatorFactoryHelper_Delegate;
+import com.android.layoutlib.bridge.Bridge;
+import com.android.layoutlib.bridge.impl.DelegateManager;
+import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
+
+import android.animation.Animator;
+import android.animation.AnimatorSet;
+import android.animation.ObjectAnimator;
+import android.animation.PropertyValuesHolder;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.graphics.drawable.AnimatedVectorDrawable.VectorDrawableAnimatorRT;
+import android.graphics.drawable.VectorDrawable_Delegate.VFullPath_Delegate;
+import android.graphics.drawable.VectorDrawable_Delegate.VGroup_Delegate;
+import android.graphics.drawable.VectorDrawable_Delegate.VNativeObject;
+import android.graphics.drawable.VectorDrawable_Delegate.VPathRenderer_Delegate;
+
+import java.util.ArrayList;
+import java.util.function.Consumer;
+
+/**
+ * Delegate used to provide new implementation of a select few methods of {@link
+ * AnimatedVectorDrawable}
+ * <p>
+ * Through the layoutlib_create tool, the original  methods of AnimatedVectorDrawable have been
+ * replaced by calls to methods of the same name in this delegate class.
+ */
+@SuppressWarnings("unused")
+public class AnimatedVectorDrawable_Delegate {
+    private static DelegateManager<AnimatorSetHolder> sAnimatorSets = new
+            DelegateManager<>(AnimatorSetHolder.class);
+    private static DelegateManager<PropertySetter> sHolders = new
+            DelegateManager<>(PropertySetter.class);
+
+
+    @LayoutlibDelegate
+    /*package*/ static long nCreateAnimatorSet() {
+        return sAnimatorSets.addNewDelegate(new AnimatorSetHolder());
+    }
+
+    @LayoutlibDelegate
+    /*package*/ static void nAddAnimator(long setPtr, long propertyValuesHolder,
+            long nativeInterpolator, long startDelay, long duration, int repeatCount) {
+        PropertySetter holder = sHolders.getDelegate(propertyValuesHolder);
+        if (holder == null || holder.getValues() == null) {
+            return;
+        }
+
+        ObjectAnimator animator = new ObjectAnimator();
+        animator.setValues(holder.getValues());
+        animator.setInterpolator(
+                NativeInterpolatorFactoryHelper_Delegate.getDelegate(nativeInterpolator));
+        animator.setStartDelay(startDelay);
+        animator.setDuration(duration);
+        animator.setRepeatCount(repeatCount);
+        animator.setTarget(holder);
+        animator.setPropertyName(holder.getValues().getPropertyName());
+
+        AnimatorSetHolder set = sAnimatorSets.getDelegate(setPtr);
+        assert set != null;
+        set.addAnimator(animator);
+    }
+
+    @LayoutlibDelegate
+    /*package*/ static long nCreateGroupPropertyHolder(long nativePtr, int propertyId,
+            float startValue, float endValue) {
+        VGroup_Delegate group = VNativeObject.getDelegate(nativePtr);
+        Consumer<Float> setter = group.getPropertySetter(propertyId);
+
+        return sHolders.addNewDelegate(FloatPropertySetter.of(setter, startValue,
+                endValue));
+    }
+
+    @LayoutlibDelegate
+    /*package*/ static long nCreatePathDataPropertyHolder(long nativePtr, long startValuePtr,
+            long endValuePtr) {
+        Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED, "AnimatedVectorDrawable path " +
+                "animations are not supported.", null, null);
+        return 0;
+    }
+
+    @LayoutlibDelegate
+    /*package*/ static long nCreatePathColorPropertyHolder(long nativePtr, int propertyId,
+            int startValue, int endValue) {
+        VFullPath_Delegate path = VNativeObject.getDelegate(nativePtr);
+        Consumer<Integer> setter = path.getIntPropertySetter(propertyId);
+
+        return sHolders.addNewDelegate(IntPropertySetter.of(setter, startValue,
+                endValue));
+    }
+
+    @LayoutlibDelegate
+    /*package*/ static long nCreatePathPropertyHolder(long nativePtr, int propertyId,
+            float startValue, float endValue) {
+        VFullPath_Delegate path = VNativeObject.getDelegate(nativePtr);
+        Consumer<Float> setter = path.getFloatPropertySetter(propertyId);
+
+        return sHolders.addNewDelegate(FloatPropertySetter.of(setter, startValue,
+                endValue));
+    }
+
+    @LayoutlibDelegate
+    /*package*/ static long nCreateRootAlphaPropertyHolder(long nativePtr, float startValue,
+            float endValue) {
+        VPathRenderer_Delegate renderer = VNativeObject.getDelegate(nativePtr);
+
+        return sHolders.addNewDelegate(FloatPropertySetter.of(renderer::setRootAlpha,
+                startValue,
+                endValue));
+    }
+
+    @LayoutlibDelegate
+    /*package*/ static void nSetPropertyHolderData(long nativePtr, float[] data, int length) {
+        PropertySetter setter = sHolders.getDelegate(nativePtr);
+        assert setter != null;
+
+        setter.setValues(data);
+    }
+
+    @LayoutlibDelegate
+    /*package*/ static void nStart(long animatorSetPtr, VectorDrawableAnimatorRT set, int id) {
+        AnimatorSetHolder animatorSet = sAnimatorSets.getDelegate(animatorSetPtr);
+        assert animatorSet != null;
+
+        animatorSet.start();
+    }
+
+    @LayoutlibDelegate
+    /*package*/ static void nReverse(long animatorSetPtr, VectorDrawableAnimatorRT set, int id) {
+        AnimatorSetHolder animatorSet = sAnimatorSets.getDelegate(animatorSetPtr);
+        assert animatorSet != null;
+
+        animatorSet.reverse();
+    }
+
+    @LayoutlibDelegate
+    /*package*/ static void nEnd(long animatorSetPtr) {
+        AnimatorSetHolder animatorSet = sAnimatorSets.getDelegate(animatorSetPtr);
+        assert animatorSet != null;
+
+        animatorSet.end();
+    }
+
+    @LayoutlibDelegate
+    /*package*/ static void nReset(long animatorSetPtr) {
+        AnimatorSetHolder animatorSet = sAnimatorSets.getDelegate(animatorSetPtr);
+        assert animatorSet != null;
+
+        animatorSet.end();
+        animatorSet.start();
+    }
+
+    private static class AnimatorSetHolder {
+        private ArrayList<Animator> mAnimators = new ArrayList<>();
+        private AnimatorSet mAnimatorSet = null;
+
+        private void addAnimator(@NonNull Animator animator) {
+            mAnimators.add(animator);
+        }
+
+        private void ensureAnimatorSet() {
+            if (mAnimatorSet == null) {
+                mAnimatorSet = new AnimatorSet();
+                mAnimatorSet.playTogether(mAnimators);
+            }
+        }
+
+        private void start() {
+            ensureAnimatorSet();
+
+            mAnimatorSet.start();
+        }
+
+        private void end() {
+            mAnimatorSet.end();
+        }
+
+        private void reset() {
+            end();
+            start();
+        }
+
+        private void reverse() {
+            mAnimatorSet.reverse();
+        }
+    }
+
+    /**
+     * Class that allows setting a value and holds the range of values for the given property.
+     *
+     * @param <T> the type of the property
+     */
+    private static class PropertySetter<T> {
+        final Consumer<T> mValueSetter;
+        private PropertyValuesHolder mValues;
+
+        private PropertySetter(@NonNull Consumer<T> valueSetter) {
+            mValueSetter = valueSetter;
+        }
+
+        /**
+         * Method to set an {@link Integer} value for this property. The default implementation of
+         * this method doesn't do anything. This method is accessed via reflection by the
+         * PropertyValuesHolder.
+         */
+        public void setIntValue(Integer value) {
+        }
+
+        /**
+         * Method to set an {@link Integer} value for this property. The default implementation of
+         * this method doesn't do anything. This method is accessed via reflection by the
+         * PropertyValuesHolder.
+         */
+        public void setFloatValue(Float value) {
+        }
+
+        void setValues(float... values) {
+            mValues = PropertyValuesHolder.ofFloat("floatValue", values);
+        }
+
+        @Nullable
+        PropertyValuesHolder getValues() {
+            return mValues;
+        }
+
+        void setValues(int... values) {
+            mValues = PropertyValuesHolder.ofInt("intValue", values);
+        }
+    }
+
+    private static class IntPropertySetter extends PropertySetter<Integer> {
+        private IntPropertySetter(Consumer<Integer> valueSetter) {
+            super(valueSetter);
+        }
+
+        private static PropertySetter of(Consumer<Integer> valueSetter, int... values) {
+            PropertySetter setter = new IntPropertySetter(valueSetter);
+            setter.setValues(values);
+
+            return setter;
+        }
+
+        public void setIntValue(Integer value) {
+            mValueSetter.accept(value);
+        }
+    }
+
+    private static class FloatPropertySetter extends PropertySetter<Float> {
+        private FloatPropertySetter(Consumer<Float> valueSetter) {
+            super(valueSetter);
+        }
+
+        private static PropertySetter of(Consumer<Float> valueSetter, float... values) {
+            PropertySetter setter = new FloatPropertySetter(valueSetter);
+            setter.setValues(values);
+
+            return setter;
+        }
+
+        public void setFloatValue(Float value) {
+            mValueSetter.accept(value);
+        }
+
+    }
+}
diff --git a/tools/layoutlib/bridge/src/android/graphics/drawable/AnimatedVectorDrawable_VectorDrawableAnimatorRT_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/drawable/AnimatedVectorDrawable_VectorDrawableAnimatorRT_Delegate.java
new file mode 100644
index 0000000..3d78931
--- /dev/null
+++ b/tools/layoutlib/bridge/src/android/graphics/drawable/AnimatedVectorDrawable_VectorDrawableAnimatorRT_Delegate.java
@@ -0,0 +1,28 @@
+/*
+ * 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.graphics.drawable;
+
+import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
+
+import android.graphics.drawable.AnimatedVectorDrawable.VectorDrawableAnimatorRT;
+
+public class AnimatedVectorDrawable_VectorDrawableAnimatorRT_Delegate {
+    @LayoutlibDelegate
+    /*package*/ static boolean useLastSeenTarget(VectorDrawableAnimatorRT thisDrawableAnimator) {
+        return true;
+    }
+}
diff --git a/tools/layoutlib/bridge/src/android/graphics/drawable/VectorDrawable_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/drawable/VectorDrawable_Delegate.java
new file mode 100644
index 0000000..90b84f8
--- /dev/null
+++ b/tools/layoutlib/bridge/src/android/graphics/drawable/VectorDrawable_Delegate.java
@@ -0,0 +1,1196 @@
+/*
+ * 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.graphics.drawable;
+
+import com.android.layoutlib.bridge.impl.DelegateManager;
+import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
+
+import android.annotation.NonNull;
+import android.content.res.Resources;
+import android.content.res.Resources.Theme;
+import android.content.res.TypedArray;
+import android.graphics.Canvas_Delegate;
+import android.graphics.Color;
+import android.graphics.Matrix;
+import android.graphics.Paint;
+import android.graphics.Paint.Cap;
+import android.graphics.Paint.Join;
+import android.graphics.Paint_Delegate;
+import android.graphics.Path;
+import android.graphics.PathMeasure;
+import android.graphics.Path_Delegate;
+import android.graphics.Rect;
+import android.graphics.Region.Op;
+import android.util.ArrayMap;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.util.MathUtils;
+import android.util.PathParser_Delegate;
+
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.FloatBuffer;
+import java.util.ArrayList;
+import java.util.function.Consumer;
+
+import static android.graphics.Canvas.CLIP_SAVE_FLAG;
+import static android.graphics.Canvas.MATRIX_SAVE_FLAG;
+import static android.graphics.Paint.Cap.BUTT;
+import static android.graphics.Paint.Cap.ROUND;
+import static android.graphics.Paint.Cap.SQUARE;
+import static android.graphics.Paint.Join.BEVEL;
+import static android.graphics.Paint.Join.MITER;
+import static android.graphics.Paint.Style;
+
+/**
+ * Delegate used to provide new implementation of a select few methods of {@link VectorDrawable}
+ * <p>
+ * Through the layoutlib_create tool, the original  methods of VectorDrawable have been replaced by
+ * calls to methods of the same name in this delegate class.
+ */
+@SuppressWarnings("unused")
+public class VectorDrawable_Delegate {
+    private static final String LOGTAG = VectorDrawable_Delegate.class.getSimpleName();
+    private static final boolean DBG_VECTOR_DRAWABLE = false;
+
+    private static final DelegateManager<VNativeObject> sPathManager =
+            new DelegateManager<>(VNativeObject.class);
+
+    /**
+     * Obtains styled attributes from the theme, if available, or unstyled resources if the theme is
+     * null.
+     */
+    private static TypedArray obtainAttributes(
+            Resources res, Theme theme, AttributeSet set, int[] attrs) {
+        if (theme == null) {
+            return res.obtainAttributes(set, attrs);
+        }
+        return theme.obtainStyledAttributes(set, attrs, 0, 0);
+    }
+
+    private static int applyAlpha(int color, float alpha) {
+        int alphaBytes = Color.alpha(color);
+        color &= 0x00FFFFFF;
+        color |= ((int) (alphaBytes * alpha)) << 24;
+        return color;
+    }
+
+    @LayoutlibDelegate
+    static long nCreateRenderer(long rootGroupPtr) {
+        VGroup_Delegate rootGroup = VNativeObject.getDelegate(rootGroupPtr);
+        return sPathManager.addNewDelegate(new VPathRenderer_Delegate(rootGroup));
+    }
+
+    @LayoutlibDelegate
+    static void nSetRendererViewportSize(long rendererPtr, float viewportWidth,
+            float viewportHeight) {
+        VPathRenderer_Delegate nativePathRenderer = VNativeObject.getDelegate(rendererPtr);
+        nativePathRenderer.mViewportWidth = viewportWidth;
+        nativePathRenderer.mViewportHeight = viewportHeight;
+    }
+
+    @LayoutlibDelegate
+    static boolean nSetRootAlpha(long rendererPtr, float alpha) {
+        VPathRenderer_Delegate nativePathRenderer = VNativeObject.getDelegate(rendererPtr);
+        nativePathRenderer.setRootAlpha(alpha);
+
+        return true;
+    }
+
+    @LayoutlibDelegate
+    static float nGetRootAlpha(long rendererPtr) {
+        VPathRenderer_Delegate nativePathRenderer = VNativeObject.getDelegate(rendererPtr);
+
+        return nativePathRenderer.getRootAlpha();
+    }
+
+    @LayoutlibDelegate
+    static void nSetAllowCaching(long rendererPtr, boolean allowCaching) {
+        // ignored
+    }
+
+    @LayoutlibDelegate
+    static void nDraw(long rendererPtr, long canvasWrapperPtr,
+            long colorFilterPtr, Rect bounds, boolean needsMirroring, boolean canReuseCache) {
+        VPathRenderer_Delegate nativePathRenderer = VNativeObject.getDelegate(rendererPtr);
+
+        Canvas_Delegate.native_save(canvasWrapperPtr, MATRIX_SAVE_FLAG | CLIP_SAVE_FLAG);
+        Canvas_Delegate.native_translate(canvasWrapperPtr, bounds.left, bounds.top);
+
+        if (needsMirroring) {
+            Canvas_Delegate.native_translate(canvasWrapperPtr, bounds.width(), 0);
+            Canvas_Delegate.native_scale(canvasWrapperPtr, -1.0f, 1.0f);
+        }
+
+        // At this point, canvas has been translated to the right position.
+        // And we use this bound for the destination rect for the drawBitmap, so
+        // we offset to (0, 0);
+        bounds.offsetTo(0, 0);
+        nativePathRenderer.draw(canvasWrapperPtr, colorFilterPtr, bounds.width(), bounds.height());
+
+        Canvas_Delegate.native_restore(canvasWrapperPtr, true);
+    }
+
+    @LayoutlibDelegate
+    static long nCreateFullPath() {
+        return sPathManager.addNewDelegate(new VFullPath_Delegate());
+    }
+
+    @LayoutlibDelegate
+    static long nCreateFullPath(long nativeFullPathPtr) {
+        VFullPath_Delegate original = VNativeObject.getDelegate(nativeFullPathPtr);
+
+        return sPathManager.addNewDelegate(new VFullPath_Delegate(original));
+    }
+
+    @LayoutlibDelegate
+    static boolean nGetFullPathProperties(long pathPtr, byte[] propertiesData,
+            int length) {
+        VFullPath_Delegate path = VNativeObject.getDelegate(pathPtr);
+
+        ByteBuffer properties = ByteBuffer.wrap(propertiesData);
+        properties.order(ByteOrder.nativeOrder());
+
+        properties.putFloat(VFullPath_Delegate.STROKE_WIDTH_INDEX * 4, path.getStrokeWidth());
+        properties.putInt(VFullPath_Delegate.STROKE_COLOR_INDEX * 4, path.getStrokeColor());
+        properties.putFloat(VFullPath_Delegate.STROKE_ALPHA_INDEX * 4, path.getStrokeAlpha());
+        properties.putInt(VFullPath_Delegate.FILL_COLOR_INDEX * 4, path.getFillColor());
+        properties.putFloat(VFullPath_Delegate.FILL_ALPHA_INDEX * 4, path.getStrokeAlpha());
+        properties.putFloat(VFullPath_Delegate.TRIM_PATH_START_INDEX * 4, path.getTrimPathStart());
+        properties.putFloat(VFullPath_Delegate.TRIM_PATH_END_INDEX * 4, path.getTrimPathEnd());
+        properties.putFloat(VFullPath_Delegate.TRIM_PATH_OFFSET_INDEX * 4,
+                path.getTrimPathOffset());
+        properties.putInt(VFullPath_Delegate.STROKE_LINE_CAP_INDEX * 4, path.getStrokeLineCap());
+        properties.putInt(VFullPath_Delegate.STROKE_LINE_JOIN_INDEX * 4, path.getStrokeLineJoin());
+        properties.putFloat(VFullPath_Delegate.STROKE_MITER_LIMIT_INDEX * 4,
+                path.getStrokeMiterlimit());
+
+        return true;
+    }
+
+    @LayoutlibDelegate
+    static void nUpdateFullPathProperties(long pathPtr, float strokeWidth,
+            int strokeColor, float strokeAlpha, int fillColor, float fillAlpha, float trimPathStart,
+            float trimPathEnd, float trimPathOffset, float strokeMiterLimit, int strokeLineCap,
+            int strokeLineJoin) {
+        VFullPath_Delegate path = VNativeObject.getDelegate(pathPtr);
+
+        path.setStrokeWidth(strokeWidth);
+        path.setStrokeColor(strokeColor);
+        path.setStrokeAlpha(strokeAlpha);
+        path.setFillColor(fillColor);
+        path.setFillAlpha(fillAlpha);
+        path.setTrimPathStart(trimPathStart);
+        path.setTrimPathEnd(trimPathEnd);
+        path.setTrimPathOffset(trimPathOffset);
+        path.setStrokeMiterlimit(strokeMiterLimit);
+        path.setStrokeLineCap(strokeLineCap);
+        path.setStrokeLineJoin(strokeLineJoin);
+    }
+
+    @LayoutlibDelegate
+    static void nUpdateFullPathFillGradient(long pathPtr, long fillGradientPtr) {
+        VFullPath_Delegate path = VNativeObject.getDelegate(pathPtr);
+
+        path.setFillGradient(fillGradientPtr);
+    }
+
+    @LayoutlibDelegate
+    static void nUpdateFullPathStrokeGradient(long pathPtr, long strokeGradientPtr) {
+        VFullPath_Delegate path = VNativeObject.getDelegate(pathPtr);
+
+        path.setStrokeGradient(strokeGradientPtr);
+    }
+
+    @LayoutlibDelegate
+    static long nCreateClipPath() {
+        return sPathManager.addNewDelegate(new VClipPath_Delegate());
+    }
+
+    @LayoutlibDelegate
+    static long nCreateClipPath(long clipPathPtr) {
+        VClipPath_Delegate original = VNativeObject.getDelegate(clipPathPtr);
+        return sPathManager.addNewDelegate(new VClipPath_Delegate(original));
+    }
+
+    @LayoutlibDelegate
+    static long nCreateGroup() {
+        return sPathManager.addNewDelegate(new VGroup_Delegate());
+    }
+
+    @LayoutlibDelegate
+    static long nCreateGroup(long groupPtr) {
+        VGroup_Delegate original = VNativeObject.getDelegate(groupPtr);
+        return sPathManager.addNewDelegate(
+                new VGroup_Delegate(original, new ArrayMap<String, Object>()));
+    }
+
+    @LayoutlibDelegate
+    static void nSetName(long nodePtr, String name) {
+        VNativeObject group = VNativeObject.getDelegate(nodePtr);
+        group.setName(name);
+    }
+
+    @LayoutlibDelegate
+    static boolean nGetGroupProperties(long groupPtr, float[] propertiesData,
+            int length) {
+        VGroup_Delegate group = VNativeObject.getDelegate(groupPtr);
+
+        FloatBuffer properties = FloatBuffer.wrap(propertiesData);
+
+        properties.put(VGroup_Delegate.ROTATE_INDEX, group.getRotation());
+        properties.put(VGroup_Delegate.PIVOT_X_INDEX, group.getPivotX());
+        properties.put(VGroup_Delegate.PIVOT_Y_INDEX, group.getPivotY());
+        properties.put(VGroup_Delegate.SCALE_X_INDEX, group.getScaleX());
+        properties.put(VGroup_Delegate.SCALE_Y_INDEX, group.getScaleY());
+        properties.put(VGroup_Delegate.TRANSLATE_X_INDEX, group.getTranslateX());
+        properties.put(VGroup_Delegate.TRANSLATE_Y_INDEX, group.getTranslateY());
+
+        return true;
+    }
+    @LayoutlibDelegate
+    static void nUpdateGroupProperties(long groupPtr, float rotate, float pivotX,
+            float pivotY, float scaleX, float scaleY, float translateX, float translateY) {
+        VGroup_Delegate group = VNativeObject.getDelegate(groupPtr);
+
+        group.setRotation(rotate);
+        group.setPivotX(pivotX);
+        group.setPivotY(pivotY);
+        group.setScaleX(scaleX);
+        group.setScaleY(scaleY);
+        group.setTranslateX(translateX);
+        group.setTranslateY(translateY);
+    }
+
+    @LayoutlibDelegate
+    static void nAddChild(long groupPtr, long nodePtr) {
+        VGroup_Delegate group = VNativeObject.getDelegate(groupPtr);
+        group.mChildren.add(VNativeObject.getDelegate(nodePtr));
+    }
+
+    @LayoutlibDelegate
+    static void nSetPathString(long pathPtr, String pathString, int length) {
+        VPath_Delegate path = VNativeObject.getDelegate(pathPtr);
+        path.setPathData(PathParser_Delegate.createNodesFromPathData(pathString));
+    }
+
+    /**
+     * The setters and getters below for paths and groups are here temporarily, and will be removed
+     * once the animation in AVD is replaced with RenderNodeAnimator, in which case the animation
+     * will modify these properties in native. By then no JNI hopping would be necessary for VD
+     * during animation, and these setters and getters will be obsolete.
+     */
+    // Setters and getters during animation.
+    @LayoutlibDelegate
+    static float nGetRotation(long groupPtr) {
+        VGroup_Delegate group = VNativeObject.getDelegate(groupPtr);
+        return group.getRotation();
+    }
+
+    @LayoutlibDelegate
+    static void nSetRotation(long groupPtr, float rotation) {
+        VGroup_Delegate group = VNativeObject.getDelegate(groupPtr);
+        group.setRotation(rotation);
+    }
+
+    @LayoutlibDelegate
+    static float nGetPivotX(long groupPtr) {
+        VGroup_Delegate group = VNativeObject.getDelegate(groupPtr);
+        return group.getPivotX();
+    }
+
+    @LayoutlibDelegate
+    static void nSetPivotX(long groupPtr, float pivotX) {
+        VGroup_Delegate group = VNativeObject.getDelegate(groupPtr);
+        group.setPivotX(pivotX);
+    }
+
+    @LayoutlibDelegate
+    static float nGetPivotY(long groupPtr) {
+        VGroup_Delegate group = VNativeObject.getDelegate(groupPtr);
+        return group.getPivotY();
+    }
+
+    @LayoutlibDelegate
+    static void nSetPivotY(long groupPtr, float pivotY) {
+        VGroup_Delegate group = VNativeObject.getDelegate(groupPtr);
+        group.setPivotY(pivotY);
+    }
+
+    @LayoutlibDelegate
+    static float nGetScaleX(long groupPtr) {
+        VGroup_Delegate group = VNativeObject.getDelegate(groupPtr);
+        return group.getScaleX();
+    }
+
+    @LayoutlibDelegate
+    static void nSetScaleX(long groupPtr, float scaleX) {
+        VGroup_Delegate group = VNativeObject.getDelegate(groupPtr);
+        group.setScaleX(scaleX);
+    }
+
+    @LayoutlibDelegate
+    static float nGetScaleY(long groupPtr) {
+        VGroup_Delegate group = VNativeObject.getDelegate(groupPtr);
+        return group.getScaleY();
+    }
+
+    @LayoutlibDelegate
+    static void nSetScaleY(long groupPtr, float scaleY) {
+        VGroup_Delegate group = VNativeObject.getDelegate(groupPtr);
+        group.setScaleY(scaleY);
+    }
+
+    @LayoutlibDelegate
+    static float nGetTranslateX(long groupPtr) {
+        VGroup_Delegate group = VNativeObject.getDelegate(groupPtr);
+        return group.getTranslateX();
+    }
+
+    @LayoutlibDelegate
+    static void nSetTranslateX(long groupPtr, float translateX) {
+        VGroup_Delegate group = VNativeObject.getDelegate(groupPtr);
+        group.setTranslateX(translateX);
+    }
+
+    @LayoutlibDelegate
+    static float nGetTranslateY(long groupPtr) {
+        VGroup_Delegate group = VNativeObject.getDelegate(groupPtr);
+        return group.getTranslateY();
+    }
+
+    @LayoutlibDelegate
+    static void nSetTranslateY(long groupPtr, float translateY) {
+        VGroup_Delegate group = VNativeObject.getDelegate(groupPtr);
+        group.setTranslateY(translateY);
+    }
+
+    @LayoutlibDelegate
+    static void nSetPathData(long pathPtr, long pathDataPtr) {
+        VPath_Delegate path = VNativeObject.getDelegate(pathPtr);
+        path.setPathData(PathParser_Delegate.getDelegate(pathDataPtr).getPathDataNodes());
+    }
+
+    @LayoutlibDelegate
+    static float nGetStrokeWidth(long pathPtr) {
+        VFullPath_Delegate path = VNativeObject.getDelegate(pathPtr);
+        return path.getStrokeWidth();
+    }
+
+    @LayoutlibDelegate
+    static void nSetStrokeWidth(long pathPtr, float width) {
+        VFullPath_Delegate path = VNativeObject.getDelegate(pathPtr);
+        path.setStrokeWidth(width);
+    }
+
+    @LayoutlibDelegate
+    static int nGetStrokeColor(long pathPtr) {
+        VFullPath_Delegate path = VNativeObject.getDelegate(pathPtr);
+        return path.getStrokeColor();
+    }
+
+    @LayoutlibDelegate
+    static void nSetStrokeColor(long pathPtr, int strokeColor) {
+        VFullPath_Delegate path = VNativeObject.getDelegate(pathPtr);
+        path.setStrokeColor(strokeColor);
+    }
+
+    @LayoutlibDelegate
+    static float nGetStrokeAlpha(long pathPtr) {
+        VFullPath_Delegate path = VNativeObject.getDelegate(pathPtr);
+        return path.getStrokeAlpha();
+    }
+
+    @LayoutlibDelegate
+    static void nSetStrokeAlpha(long pathPtr, float alpha) {
+        VFullPath_Delegate path = VNativeObject.getDelegate(pathPtr);
+        path.setStrokeAlpha(alpha);
+    }
+
+    @LayoutlibDelegate
+    static int nGetFillColor(long pathPtr) {
+        VFullPath_Delegate path = VNativeObject.getDelegate(pathPtr);
+        return path.getFillColor();
+    }
+
+    @LayoutlibDelegate
+    static void nSetFillColor(long pathPtr, int fillColor) {
+        VFullPath_Delegate path = VNativeObject.getDelegate(pathPtr);
+        path.setFillColor(fillColor);
+    }
+
+    @LayoutlibDelegate
+    static float nGetFillAlpha(long pathPtr) {
+        VFullPath_Delegate path = VNativeObject.getDelegate(pathPtr);
+        return path.getFillAlpha();
+    }
+
+    @LayoutlibDelegate
+    static void nSetFillAlpha(long pathPtr, float fillAlpha) {
+        VFullPath_Delegate path = VNativeObject.getDelegate(pathPtr);
+        path.setFillAlpha(fillAlpha);
+    }
+
+    @LayoutlibDelegate
+    static float nGetTrimPathStart(long pathPtr) {
+        VFullPath_Delegate path = VNativeObject.getDelegate(pathPtr);
+        return path.getTrimPathStart();
+    }
+
+    @LayoutlibDelegate
+    static void nSetTrimPathStart(long pathPtr, float trimPathStart) {
+        VFullPath_Delegate path = VNativeObject.getDelegate(pathPtr);
+        path.setTrimPathStart(trimPathStart);
+    }
+
+    @LayoutlibDelegate
+    static float nGetTrimPathEnd(long pathPtr) {
+        VFullPath_Delegate path = VNativeObject.getDelegate(pathPtr);
+        return path.getTrimPathEnd();
+    }
+
+    @LayoutlibDelegate
+    static void nSetTrimPathEnd(long pathPtr, float trimPathEnd) {
+        VFullPath_Delegate path = VNativeObject.getDelegate(pathPtr);
+        path.setTrimPathEnd(trimPathEnd);
+    }
+
+    @LayoutlibDelegate
+    static float nGetTrimPathOffset(long pathPtr) {
+        VFullPath_Delegate path = VNativeObject.getDelegate(pathPtr);
+        return path.getTrimPathOffset();
+    }
+
+    @LayoutlibDelegate
+    static void nSetTrimPathOffset(long pathPtr, float trimPathOffset) {
+        VFullPath_Delegate path = VNativeObject.getDelegate(pathPtr);
+        path.setTrimPathOffset(trimPathOffset);
+    }
+
+    /**
+     * Base class for all the internal Delegates that does two functions:
+     * <ol>
+     *     <li>Serves as base class to store all the delegates in one {@link DelegateManager}
+     *     <li>Provides setName for all the classes. {@link VPathRenderer_Delegate} does actually
+     *     not need it
+     * </ol>
+     */
+    interface VNativeObject {
+        @NonNull
+        static <T> T getDelegate(long nativePtr) {
+            //noinspection unchecked
+            T vNativeObject = (T) sPathManager.getDelegate(nativePtr);
+
+            assert vNativeObject != null;
+            return vNativeObject;
+        }
+
+        void setName(String name);
+    }
+
+    private static class VClipPath_Delegate extends VPath_Delegate {
+        private VClipPath_Delegate() {
+            // Empty constructor.
+        }
+
+        private VClipPath_Delegate(VClipPath_Delegate copy) {
+            super(copy);
+        }
+
+        @Override
+        public boolean isClipPath() {
+            return true;
+        }
+    }
+
+    static class VFullPath_Delegate extends VPath_Delegate {
+        // These constants need to be kept in sync with their values in VectorDrawable.VFullPath
+        private static final int STROKE_WIDTH_INDEX = 0;
+        private static final int STROKE_COLOR_INDEX = 1;
+        private static final int STROKE_ALPHA_INDEX = 2;
+        private static final int FILL_COLOR_INDEX = 3;
+        private static final int FILL_ALPHA_INDEX = 4;
+        private static final int TRIM_PATH_START_INDEX = 5;
+        private static final int TRIM_PATH_END_INDEX = 6;
+        private static final int TRIM_PATH_OFFSET_INDEX = 7;
+        private static final int STROKE_LINE_CAP_INDEX = 8;
+        private static final int STROKE_LINE_JOIN_INDEX = 9;
+        private static final int STROKE_MITER_LIMIT_INDEX = 10;
+
+        private static final int LINECAP_BUTT = 0;
+        private static final int LINECAP_ROUND = 1;
+        private static final int LINECAP_SQUARE = 2;
+
+        private static final int LINEJOIN_MITER = 0;
+        private static final int LINEJOIN_ROUND = 1;
+        private static final int LINEJOIN_BEVEL = 2;
+
+        @NonNull
+        public Consumer<Float> getFloatPropertySetter(int propertyIdx) {
+            switch (propertyIdx) {
+                case STROKE_ALPHA_INDEX:
+                    return this::setStrokeAlpha;
+                case FILL_ALPHA_INDEX:
+                    return this::setFillAlpha;
+                case TRIM_PATH_START_INDEX:
+                    return this::setTrimPathStart;
+                case TRIM_PATH_END_INDEX:
+                    return this::setTrimPathEnd;
+                case TRIM_PATH_OFFSET_INDEX:
+                    return this::setTrimPathOffset;
+            }
+
+            throw new IllegalArgumentException("Invalid VFullPath_Delegate property index "
+                    + propertyIdx);
+        }
+
+        @NonNull
+        public Consumer<Integer> getIntPropertySetter(int propertyIdx) {
+            switch (propertyIdx) {
+                case STROKE_COLOR_INDEX:
+                    return this::setStrokeColor;
+                case FILL_COLOR_INDEX:
+                    return this::setFillColor;
+            }
+
+            throw new IllegalArgumentException("Invalid VFullPath_Delegate property index "
+                    + propertyIdx);
+        }
+
+        /////////////////////////////////////////////////////
+        // Variables below need to be copied (deep copy if applicable) for mutation.
+
+        int mStrokeColor = Color.TRANSPARENT;
+        float mStrokeWidth = 0;
+
+        int mFillColor = Color.TRANSPARENT;
+        long mStrokeGradient = 0;
+        long mFillGradient = 0;
+        float mStrokeAlpha = 1.0f;
+        float mFillAlpha = 1.0f;
+        float mTrimPathStart = 0;
+        float mTrimPathEnd = 1;
+        float mTrimPathOffset = 0;
+
+        Cap mStrokeLineCap = BUTT;
+        Join mStrokeLineJoin = MITER;
+        float mStrokeMiterlimit = 4;
+
+        private VFullPath_Delegate() {
+            // Empty constructor.
+        }
+
+        private VFullPath_Delegate(VFullPath_Delegate copy) {
+            super(copy);
+
+            mStrokeColor = copy.mStrokeColor;
+            mStrokeWidth = copy.mStrokeWidth;
+            mStrokeAlpha = copy.mStrokeAlpha;
+            mFillColor = copy.mFillColor;
+            mFillAlpha = copy.mFillAlpha;
+            mTrimPathStart = copy.mTrimPathStart;
+            mTrimPathEnd = copy.mTrimPathEnd;
+            mTrimPathOffset = copy.mTrimPathOffset;
+
+            mStrokeLineCap = copy.mStrokeLineCap;
+            mStrokeLineJoin = copy.mStrokeLineJoin;
+            mStrokeMiterlimit = copy.mStrokeMiterlimit;
+
+            mStrokeGradient = copy.mStrokeGradient;
+            mFillGradient = copy.mFillGradient;
+        }
+
+        private int getStrokeLineCap() {
+            switch (mStrokeLineCap) {
+                case BUTT:
+                    return LINECAP_BUTT;
+                case ROUND:
+                    return LINECAP_ROUND;
+                case SQUARE:
+                    return LINECAP_SQUARE;
+                default:
+                    assert false;
+            }
+
+            return -1;
+        }
+
+        private void setStrokeLineCap(int cap) {
+            switch (cap) {
+                case LINECAP_BUTT:
+                    mStrokeLineCap = BUTT;
+                    break;
+                case LINECAP_ROUND:
+                    mStrokeLineCap = ROUND;
+                    break;
+                case LINECAP_SQUARE:
+                    mStrokeLineCap = SQUARE;
+                    break;
+                default:
+                    assert false;
+            }
+        }
+
+        private int getStrokeLineJoin() {
+            switch (mStrokeLineJoin) {
+                case MITER:
+                    return LINEJOIN_MITER;
+                case ROUND:
+                    return LINEJOIN_ROUND;
+                case BEVEL:
+                    return LINEJOIN_BEVEL;
+                default:
+                    assert false;
+            }
+
+            return -1;
+        }
+
+        private void setStrokeLineJoin(int join) {
+            switch (join) {
+                case LINEJOIN_BEVEL:
+                    mStrokeLineJoin = BEVEL;
+                    break;
+                case LINEJOIN_MITER:
+                    mStrokeLineJoin = MITER;
+                    break;
+                case LINEJOIN_ROUND:
+                    mStrokeLineJoin = Join.ROUND;
+                    break;
+                default:
+                    assert false;
+            }
+        }
+
+        private int getStrokeColor() {
+            return mStrokeColor;
+        }
+
+        private void setStrokeColor(int strokeColor) {
+            mStrokeColor = strokeColor;
+        }
+
+        private float getStrokeWidth() {
+            return mStrokeWidth;
+        }
+
+        private void setStrokeWidth(float strokeWidth) {
+            mStrokeWidth = strokeWidth;
+        }
+
+        private float getStrokeAlpha() {
+            return mStrokeAlpha;
+        }
+
+        private void setStrokeAlpha(float strokeAlpha) {
+            mStrokeAlpha = strokeAlpha;
+        }
+
+        private int getFillColor() {
+            return mFillColor;
+        }
+
+        private void setFillColor(int fillColor) {
+            mFillColor = fillColor;
+        }
+
+        private float getFillAlpha() {
+            return mFillAlpha;
+        }
+
+        private void setFillAlpha(float fillAlpha) {
+            mFillAlpha = fillAlpha;
+        }
+
+        private float getTrimPathStart() {
+            return mTrimPathStart;
+        }
+
+        private void setTrimPathStart(float trimPathStart) {
+            mTrimPathStart = trimPathStart;
+        }
+
+        private float getTrimPathEnd() {
+            return mTrimPathEnd;
+        }
+
+        private void setTrimPathEnd(float trimPathEnd) {
+            mTrimPathEnd = trimPathEnd;
+        }
+
+        private float getTrimPathOffset() {
+            return mTrimPathOffset;
+        }
+
+        private void setTrimPathOffset(float trimPathOffset) {
+            mTrimPathOffset = trimPathOffset;
+        }
+
+        private void setStrokeMiterlimit(float limit) {
+            mStrokeMiterlimit = limit;
+        }
+
+        private float getStrokeMiterlimit() {
+            return mStrokeMiterlimit;
+        }
+
+        private void setStrokeGradient(long gradientPtr) {
+            mStrokeGradient = gradientPtr;
+        }
+
+        private void setFillGradient(long gradientPtr) {
+            mFillGradient = gradientPtr;
+        }
+    }
+
+    static class VGroup_Delegate implements VNativeObject {
+        // This constants need to be kept in sync with their definitions in VectorDrawable.Group
+        private static final int ROTATE_INDEX = 0;
+        private static final int PIVOT_X_INDEX = 1;
+        private static final int PIVOT_Y_INDEX = 2;
+        private static final int SCALE_X_INDEX = 3;
+        private static final int SCALE_Y_INDEX = 4;
+        private static final int TRANSLATE_X_INDEX = 5;
+        private static final int TRANSLATE_Y_INDEX = 6;
+
+        public Consumer<Float> getPropertySetter(int propertyIdx) {
+            switch (propertyIdx) {
+                case ROTATE_INDEX:
+                    return this::setRotation;
+                case PIVOT_X_INDEX:
+                    return this::setPivotX;
+                case PIVOT_Y_INDEX:
+                    return this::setPivotY;
+                case SCALE_X_INDEX:
+                    return this::setScaleX;
+                case SCALE_Y_INDEX:
+                    return this::setScaleY;
+                case TRANSLATE_X_INDEX:
+                    return this::setTranslateX;
+                case TRANSLATE_Y_INDEX:
+                    return this::setTranslateY;
+            }
+
+            throw new IllegalArgumentException("Invalid VGroup_Delegate property index "
+                    + propertyIdx);
+        }
+
+        /////////////////////////////////////////////////////
+        // Variables below need to be copied (deep copy if applicable) for mutation.
+        final ArrayList<Object> mChildren = new ArrayList<>();
+        // mStackedMatrix is only used temporarily when drawing, it combines all
+        // the parents' local matrices with the current one.
+        private final Matrix mStackedMatrix = new Matrix();
+        // mLocalMatrix is updated based on the update of transformation information,
+        // either parsed from the XML or by animation.
+        private final Matrix mLocalMatrix = new Matrix();
+        private float mRotate = 0;
+        private float mPivotX = 0;
+        private float mPivotY = 0;
+        private float mScaleX = 1;
+        private float mScaleY = 1;
+        private float mTranslateX = 0;
+        private float mTranslateY = 0;
+        private int mChangingConfigurations;
+        private String mGroupName = null;
+
+        private VGroup_Delegate(VGroup_Delegate copy, ArrayMap<String, Object> targetsMap) {
+            mRotate = copy.mRotate;
+            mPivotX = copy.mPivotX;
+            mPivotY = copy.mPivotY;
+            mScaleX = copy.mScaleX;
+            mScaleY = copy.mScaleY;
+            mTranslateX = copy.mTranslateX;
+            mTranslateY = copy.mTranslateY;
+            mGroupName = copy.mGroupName;
+            mChangingConfigurations = copy.mChangingConfigurations;
+            if (mGroupName != null) {
+                targetsMap.put(mGroupName, this);
+            }
+
+            mLocalMatrix.set(copy.mLocalMatrix);
+
+            final ArrayList<Object> children = copy.mChildren;
+            //noinspection ForLoopReplaceableByForEach
+            for (int i = 0; i < children.size(); i++) {
+                Object copyChild = children.get(i);
+                if (copyChild instanceof VGroup_Delegate) {
+                    VGroup_Delegate copyGroup = (VGroup_Delegate) copyChild;
+                    mChildren.add(new VGroup_Delegate(copyGroup, targetsMap));
+                } else {
+                    VPath_Delegate newPath;
+                    if (copyChild instanceof VFullPath_Delegate) {
+                        newPath = new VFullPath_Delegate((VFullPath_Delegate) copyChild);
+                    } else if (copyChild instanceof VClipPath_Delegate) {
+                        newPath = new VClipPath_Delegate((VClipPath_Delegate) copyChild);
+                    } else {
+                        throw new IllegalStateException("Unknown object in the tree!");
+                    }
+                    mChildren.add(newPath);
+                    if (newPath.mPathName != null) {
+                        targetsMap.put(newPath.mPathName, newPath);
+                    }
+                }
+            }
+        }
+
+        private VGroup_Delegate() {
+        }
+
+        private void updateLocalMatrix() {
+            // The order we apply is the same as the
+            // RenderNode.cpp::applyViewPropertyTransforms().
+            mLocalMatrix.reset();
+            mLocalMatrix.postTranslate(-mPivotX, -mPivotY);
+            mLocalMatrix.postScale(mScaleX, mScaleY);
+            mLocalMatrix.postRotate(mRotate, 0, 0);
+            mLocalMatrix.postTranslate(mTranslateX + mPivotX, mTranslateY + mPivotY);
+        }
+
+        /* Setters and Getters, used by animator from AnimatedVectorDrawable. */
+        private float getRotation() {
+            return mRotate;
+        }
+
+        private void setRotation(float rotation) {
+            if (rotation != mRotate) {
+                mRotate = rotation;
+                updateLocalMatrix();
+            }
+        }
+
+        private float getPivotX() {
+            return mPivotX;
+        }
+
+        private void setPivotX(float pivotX) {
+            if (pivotX != mPivotX) {
+                mPivotX = pivotX;
+                updateLocalMatrix();
+            }
+        }
+
+        private float getPivotY() {
+            return mPivotY;
+        }
+
+        private void setPivotY(float pivotY) {
+            if (pivotY != mPivotY) {
+                mPivotY = pivotY;
+                updateLocalMatrix();
+            }
+        }
+
+        private float getScaleX() {
+            return mScaleX;
+        }
+
+        private void setScaleX(float scaleX) {
+            if (scaleX != mScaleX) {
+                mScaleX = scaleX;
+                updateLocalMatrix();
+            }
+        }
+
+        private float getScaleY() {
+            return mScaleY;
+        }
+
+        private void setScaleY(float scaleY) {
+            if (scaleY != mScaleY) {
+                mScaleY = scaleY;
+                updateLocalMatrix();
+            }
+        }
+
+        private float getTranslateX() {
+            return mTranslateX;
+        }
+
+        private void setTranslateX(float translateX) {
+            if (translateX != mTranslateX) {
+                mTranslateX = translateX;
+                updateLocalMatrix();
+            }
+        }
+
+        private float getTranslateY() {
+            return mTranslateY;
+        }
+
+        private void setTranslateY(float translateY) {
+            if (translateY != mTranslateY) {
+                mTranslateY = translateY;
+                updateLocalMatrix();
+            }
+        }
+
+        @Override
+        public void setName(String name) {
+            mGroupName = name;
+        }
+    }
+
+    public static class VPath_Delegate implements VNativeObject {
+        protected PathParser_Delegate.PathDataNode[] mNodes = null;
+        String mPathName;
+        int mChangingConfigurations;
+
+        public VPath_Delegate() {
+            // Empty constructor.
+        }
+
+        public VPath_Delegate(VPath_Delegate copy) {
+            mPathName = copy.mPathName;
+            mChangingConfigurations = copy.mChangingConfigurations;
+            mNodes = PathParser_Delegate.deepCopyNodes(copy.mNodes);
+        }
+
+        public void toPath(Path path) {
+            path.reset();
+            if (mNodes != null) {
+                PathParser_Delegate.PathDataNode.nodesToPath(mNodes,
+                        Path_Delegate.getDelegate(path.mNativePath));
+            }
+        }
+
+        @Override
+        public void setName(String name) {
+            mPathName = name;
+        }
+
+        public boolean isClipPath() {
+            return false;
+        }
+
+        private void setPathData(PathParser_Delegate.PathDataNode[] nodes) {
+            if (!PathParser_Delegate.canMorph(mNodes, nodes)) {
+                // This should not happen in the middle of animation.
+                mNodes = PathParser_Delegate.deepCopyNodes(nodes);
+            } else {
+                PathParser_Delegate.updateNodes(mNodes, nodes);
+            }
+        }
+    }
+
+    static class VPathRenderer_Delegate implements VNativeObject {
+        /* Right now the internal data structure is organized as a tree.
+         * Each node can be a group node, or a path.
+         * A group node can have groups or paths as children, but a path node has
+         * no children.
+         * One example can be:
+         *                 Root Group
+         *                /    |     \
+         *           Group    Path    Group
+         *          /     \             |
+         *         Path   Path         Path
+         *
+         */
+        // Variables that only used temporarily inside the draw() call, so there
+        // is no need for deep copying.
+        private final Path mPath;
+        private final Path mRenderPath;
+        private final Matrix mFinalPathMatrix = new Matrix();
+        private final VGroup_Delegate mRootGroup;
+        private float mViewportWidth = 0;
+        private float mViewportHeight = 0;
+        private float mRootAlpha = 1.0f;
+        private Paint mStrokePaint;
+        private Paint mFillPaint;
+        private PathMeasure mPathMeasure;
+
+        private VPathRenderer_Delegate(VGroup_Delegate rootGroup) {
+            mRootGroup = rootGroup;
+            mPath = new Path();
+            mRenderPath = new Path();
+        }
+
+        private float getRootAlpha() {
+            return mRootAlpha;
+        }
+
+        void setRootAlpha(float alpha) {
+            mRootAlpha = alpha;
+        }
+
+        private void drawGroupTree(VGroup_Delegate currentGroup, Matrix currentMatrix,
+                long canvasPtr, int w, int h, long filterPtr) {
+            // Calculate current group's matrix by preConcat the parent's and
+            // and the current one on the top of the stack.
+            // Basically the Mfinal = Mviewport * M0 * M1 * M2;
+            // Mi the local matrix at level i of the group tree.
+            currentGroup.mStackedMatrix.set(currentMatrix);
+            currentGroup.mStackedMatrix.preConcat(currentGroup.mLocalMatrix);
+
+            // Save the current clip information, which is local to this group.
+            Canvas_Delegate.native_save(canvasPtr, MATRIX_SAVE_FLAG | CLIP_SAVE_FLAG);
+            // Draw the group tree in the same order as the XML file.
+            for (int i = 0; i < currentGroup.mChildren.size(); i++) {
+                Object child = currentGroup.mChildren.get(i);
+                if (child instanceof VGroup_Delegate) {
+                    VGroup_Delegate childGroup = (VGroup_Delegate) child;
+                    drawGroupTree(childGroup, currentGroup.mStackedMatrix,
+                            canvasPtr, w, h, filterPtr);
+                } else if (child instanceof VPath_Delegate) {
+                    VPath_Delegate childPath = (VPath_Delegate) child;
+                    drawPath(currentGroup, childPath, canvasPtr, w, h, filterPtr);
+                }
+            }
+            Canvas_Delegate.native_restore(canvasPtr, true);
+        }
+
+        public void draw(long canvasPtr, long filterPtr, int w, int h) {
+            // Traverse the tree in pre-order to draw.
+            drawGroupTree(mRootGroup, Matrix.IDENTITY_MATRIX, canvasPtr, w, h, filterPtr);
+        }
+
+        private void drawPath(VGroup_Delegate VGroup, VPath_Delegate VPath, long canvasPtr,
+                int w,
+                int h,
+                long filterPtr) {
+            final float scaleX = w / mViewportWidth;
+            final float scaleY = h / mViewportHeight;
+            final float minScale = Math.min(scaleX, scaleY);
+            final Matrix groupStackedMatrix = VGroup.mStackedMatrix;
+
+            mFinalPathMatrix.set(groupStackedMatrix);
+            mFinalPathMatrix.postScale(scaleX, scaleY);
+
+            final float matrixScale = getMatrixScale(groupStackedMatrix);
+            if (matrixScale == 0) {
+                // When either x or y is scaled to 0, we don't need to draw anything.
+                return;
+            }
+            VPath.toPath(mPath);
+            final Path path = mPath;
+
+            mRenderPath.reset();
+
+            if (VPath.isClipPath()) {
+                mRenderPath.addPath(path, mFinalPathMatrix);
+                Canvas_Delegate.native_clipPath(canvasPtr, mRenderPath.mNativePath, Op
+                        .INTERSECT.nativeInt);
+            } else {
+                VFullPath_Delegate fullPath = (VFullPath_Delegate) VPath;
+                if (fullPath.mTrimPathStart != 0.0f || fullPath.mTrimPathEnd != 1.0f) {
+                    float start = (fullPath.mTrimPathStart + fullPath.mTrimPathOffset) % 1.0f;
+                    float end = (fullPath.mTrimPathEnd + fullPath.mTrimPathOffset) % 1.0f;
+
+                    if (mPathMeasure == null) {
+                        mPathMeasure = new PathMeasure();
+                    }
+                    mPathMeasure.setPath(mPath, false);
+
+                    float len = mPathMeasure.getLength();
+                    start = start * len;
+                    end = end * len;
+                    path.reset();
+                    if (start > end) {
+                        mPathMeasure.getSegment(start, len, path, true);
+                        mPathMeasure.getSegment(0f, end, path, true);
+                    } else {
+                        mPathMeasure.getSegment(start, end, path, true);
+                    }
+                    path.rLineTo(0, 0); // fix bug in measure
+                }
+                mRenderPath.addPath(path, mFinalPathMatrix);
+
+                if (fullPath.mFillColor != Color.TRANSPARENT) {
+                    if (mFillPaint == null) {
+                        mFillPaint = new Paint();
+                        mFillPaint.setStyle(Style.FILL);
+                        mFillPaint.setAntiAlias(true);
+                    }
+
+                    final Paint fillPaint = mFillPaint;
+                    fillPaint.setColor(applyAlpha(fullPath.mFillColor, fullPath.mFillAlpha));
+                    Paint_Delegate fillPaintDelegate = Paint_Delegate.getDelegate(fillPaint
+                            .getNativeInstance());
+                    // mFillPaint can not be null at this point so we will have a delegate
+                    assert fillPaintDelegate != null;
+                    fillPaintDelegate.setColorFilter(filterPtr);
+                    fillPaintDelegate.setShader(fullPath.mFillGradient);
+                    Canvas_Delegate.native_drawPath(canvasPtr, mRenderPath.mNativePath, fillPaint
+                            .getNativeInstance());
+                }
+
+                if (fullPath.mStrokeColor != Color.TRANSPARENT) {
+                    if (mStrokePaint == null) {
+                        mStrokePaint = new Paint();
+                        mStrokePaint.setStyle(Style.STROKE);
+                        mStrokePaint.setAntiAlias(true);
+                    }
+
+                    final Paint strokePaint = mStrokePaint;
+                    if (fullPath.mStrokeLineJoin != null) {
+                        strokePaint.setStrokeJoin(fullPath.mStrokeLineJoin);
+                    }
+
+                    if (fullPath.mStrokeLineCap != null) {
+                        strokePaint.setStrokeCap(fullPath.mStrokeLineCap);
+                    }
+
+                    strokePaint.setStrokeMiter(fullPath.mStrokeMiterlimit);
+                    strokePaint.setColor(applyAlpha(fullPath.mStrokeColor, fullPath.mStrokeAlpha));
+                    Paint_Delegate strokePaintDelegate = Paint_Delegate.getDelegate(strokePaint
+                            .getNativeInstance());
+                    // mStrokePaint can not be null at this point so we will have a delegate
+                    assert strokePaintDelegate != null;
+                    strokePaintDelegate.setColorFilter(filterPtr);
+                    final float finalStrokeScale = minScale * matrixScale;
+                    strokePaint.setStrokeWidth(fullPath.mStrokeWidth * finalStrokeScale);
+                    strokePaintDelegate.setShader(fullPath.mStrokeGradient);
+                    Canvas_Delegate.native_drawPath(canvasPtr, mRenderPath.mNativePath, strokePaint
+                            .getNativeInstance());
+                }
+            }
+        }
+
+        private float getMatrixScale(Matrix groupStackedMatrix) {
+            // Given unit vectors A = (0, 1) and B = (1, 0).
+            // After matrix mapping, we got A' and B'. Let theta = the angel b/t A' and B'.
+            // Therefore, the final scale we want is min(|A'| * sin(theta), |B'| * sin(theta)),
+            // which is (|A'| * |B'| * sin(theta)) / max (|A'|, |B'|);
+            // If  max (|A'|, |B'|) = 0, that means either x or y has a scale of 0.
+            //
+            // For non-skew case, which is most of the cases, matrix scale is computing exactly the
+            // scale on x and y axis, and take the minimal of these two.
+            // For skew case, an unit square will mapped to a parallelogram. And this function will
+            // return the minimal height of the 2 bases.
+            float[] unitVectors = new float[]{0, 1, 1, 0};
+            groupStackedMatrix.mapVectors(unitVectors);
+            float scaleX = MathUtils.mag(unitVectors[0], unitVectors[1]);
+            float scaleY = MathUtils.mag(unitVectors[2], unitVectors[3]);
+            float crossProduct = MathUtils.cross(unitVectors[0], unitVectors[1],
+                    unitVectors[2], unitVectors[3]);
+            float maxScale = MathUtils.max(scaleX, scaleY);
+
+            float matrixScale = 0;
+            if (maxScale > 0) {
+                matrixScale = MathUtils.abs(crossProduct) / maxScale;
+            }
+            if (DBG_VECTOR_DRAWABLE) {
+                Log.d(LOGTAG, "Scale x " + scaleX + " y " + scaleY + " final " + matrixScale);
+            }
+            return matrixScale;
+        }
+
+        @Override
+        public void setName(String name) {
+        }
+    }
+}
diff --git a/tools/layoutlib/bridge/src/android/util/PathParser_Delegate.java b/tools/layoutlib/bridge/src/android/util/PathParser_Delegate.java
index d3af837..6c34c70 100644
--- a/tools/layoutlib/bridge/src/android/util/PathParser_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/util/PathParser_Delegate.java
@@ -24,7 +24,6 @@
 import android.annotation.NonNull;
 import android.graphics.Path_Delegate;
 
-import java.awt.geom.Path2D;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.logging.Level;
@@ -52,10 +51,18 @@
     @NonNull
     private PathDataNode[] mPathDataNodes;
 
+    public static PathParser_Delegate getDelegate(long nativePtr) {
+        return sManager.getDelegate(nativePtr);
+    }
+
     private PathParser_Delegate(@NonNull PathDataNode[] nodes) {
         mPathDataNodes = nodes;
     }
 
+    public PathDataNode[] getPathDataNodes() {
+        return mPathDataNodes;
+    }
+
     @LayoutlibDelegate
     /*package*/ static boolean nParseStringForPath(long pathPtr, @NonNull String pathString, int
             stringLength) {
@@ -64,7 +71,7 @@
             return false;
         }
         assert pathString.length() == stringLength;
-        PathDataNode.nodesToPath(createNodesFromPathData(pathString), path_delegate.getJavaShape());
+        PathDataNode.nodesToPath(createNodesFromPathData(pathString), path_delegate);
         return true;
     }
 
@@ -75,7 +82,7 @@
         if (source == null || path_delegate == null) {
             return;
         }
-        PathDataNode.nodesToPath(source.mPathDataNodes, path_delegate.getJavaShape());
+        PathDataNode.nodesToPath(source.mPathDataNodes, path_delegate);
     }
 
     @LayoutlibDelegate
@@ -124,8 +131,11 @@
             out.mPathDataNodes = new PathDataNode[length];
         }
         for (int i = 0; i < length; i++) {
+            if (out.mPathDataNodes[i] == null) {
+                out.mPathDataNodes[i] = new PathDataNode(from.mPathDataNodes[i]);
+            }
             out.mPathDataNodes[i].interpolatePathDataNode(from.mPathDataNodes[i],
-                    to.mPathDataNodes[i], fraction);
+                        to.mPathDataNodes[i], fraction);
         }
         return true;
     }
@@ -137,9 +147,13 @@
 
     @LayoutlibDelegate
     /*package*/ static boolean nCanMorph(long fromDataPtr, long toDataPtr) {
-        Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED, "morphing path data isn't " +
-                "supported", null, null);
-        return false;
+        PathParser_Delegate fromPath = PathParser_Delegate.getDelegate(fromDataPtr);
+        PathParser_Delegate toPath = PathParser_Delegate.getDelegate(toDataPtr);
+        if (fromPath == null || toPath == null || fromPath.getPathDataNodes() == null || toPath
+                .getPathDataNodes() == null) {
+            return true;
+        }
+        return PathParser_Delegate.canMorph(fromPath.getPathDataNodes(), toPath.getPathDataNodes());
     }
 
     @LayoutlibDelegate
@@ -158,7 +172,7 @@
      * @return an array of the PathDataNode.
      */
     @NonNull
-    private static PathDataNode[] createNodesFromPathData(@NonNull String pathData) {
+    public static PathDataNode[] createNodesFromPathData(@NonNull String pathData) {
         int start = 0;
         int end = 1;
 
@@ -186,7 +200,7 @@
      * @return a deep copy of the <code>source</code>.
      */
     @NonNull
-    private static PathDataNode[] deepCopyNodes(@NonNull PathDataNode[] source) {
+    public static PathDataNode[] deepCopyNodes(@NonNull PathDataNode[] source) {
         PathDataNode[] copy = new PathDataNode[source.length];
         for (int i = 0; i < source.length; i++) {
             copy[i] = new PathDataNode(source[i]);
@@ -194,6 +208,45 @@
         return copy;
     }
 
+    /**
+     * @param nodesFrom The source path represented in an array of PathDataNode
+     * @param nodesTo The target path represented in an array of PathDataNode
+     * @return whether the <code>nodesFrom</code> can morph into <code>nodesTo</code>
+     */
+    public static boolean canMorph(PathDataNode[] nodesFrom, PathDataNode[] nodesTo) {
+        if (nodesFrom == null || nodesTo == null) {
+            return false;
+        }
+
+        if (nodesFrom.length != nodesTo.length) {
+            return false;
+        }
+
+        for (int i = 0; i < nodesFrom.length; i ++) {
+            if (nodesFrom[i].mType != nodesTo[i].mType
+                    || nodesFrom[i].mParams.length != nodesTo[i].mParams.length) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    /**
+     * Update the target's data to match the source.
+     * Before calling this, make sure canMorph(target, source) is true.
+     *
+     * @param target The target path represented in an array of PathDataNode
+     * @param source The source path represented in an array of PathDataNode
+     */
+    public static void updateNodes(PathDataNode[] target, PathDataNode[] source) {
+        for (int i = 0; i < source.length; i ++) {
+            target[i].mType = source[i].mType;
+            for (int j = 0; j < source[i].mParams.length; j ++) {
+                target[i].mParams[j] = source[i].mParams[j];
+            }
+        }
+    }
+
     private static int nextStart(@NonNull String s, int end) {
         char c;
 
@@ -330,7 +383,7 @@
      * Each PathDataNode represents one command in the "d" attribute of the svg file. An array of
      * PathDataNode can represent the whole "d" attribute.
      */
-    private static class PathDataNode {
+    public static class PathDataNode {
         private char mType;
         @NonNull
         private float[] mParams;
@@ -355,12 +408,13 @@
         }
 
         /**
-         * Convert an array of PathDataNode to Path.
+         * Convert an array of PathDataNode to Path. Reset the passed path as needed before
+         * calling this method.
          *
          * @param node The source array of PathDataNode.
          * @param path The target Path object.
          */
-        private static void nodesToPath(@NonNull PathDataNode[] node, @NonNull Path2D path) {
+        public static void nodesToPath(@NonNull PathDataNode[] node, @NonNull Path_Delegate path) {
             float[] current = new float[6];
             char previousCommand = 'm';
             //noinspection ForLoopReplaceableByForEach
@@ -387,24 +441,32 @@
         }
 
         @SuppressWarnings("PointlessArithmeticExpression")
-        private static void addCommand(@NonNull Path2D path, float[] current, char cmd,
-                char lastCmd, @NonNull float[] val) {
+        private static void addCommand(@NonNull Path_Delegate path, float[] current,
+                char previousCmd, char cmd, @NonNull float[] val) {
 
             int incr = 2;
-
-            float cx = current[0];
-            float cy = current[1];
-            float cpx = current[2];
-            float cpy = current[3];
-            float loopX = current[4];
-            float loopY = current[5];
+            float currentX = current[0];
+            float currentY = current[1];
+            float ctrlPointX = current[2];
+            float ctrlPointY = current[3];
+            float currentSegmentStartX = current[4];
+            float currentSegmentStartY = current[5];
+            float reflectiveCtrlPointX;
+            float reflectiveCtrlPointY;
 
             switch (cmd) {
                 case 'z':
                 case 'Z':
-                    path.closePath();
-                    cx = loopX;
-                    cy = loopY;
+                    path.close();
+                    // Path is closed here, but we need to move the pen to the
+                    // closed position. So we cache the segment's starting position,
+                    // and restore it here.
+                    currentX = currentSegmentStartX;
+                    currentY = currentSegmentStartY;
+                    ctrlPointX = currentSegmentStartX;
+                    ctrlPointY = currentSegmentStartY;
+                    path.moveTo(currentX, currentY);
+                    break;
                 case 'm':
                 case 'M':
                 case 'l':
@@ -432,185 +494,206 @@
                 case 'a':
                 case 'A':
                     incr = 7;
+                    break;
             }
 
             for (int k = 0; k < val.length; k += incr) {
-                boolean reflectCtrl;
-                float tempReflectedX, tempReflectedY;
-
                 switch (cmd) {
-                    case 'm':
-                        cx += val[k + 0];
-                        cy += val[k + 1];
+                    case 'm': // moveto - Start a new sub-path (relative)
+                        currentX += val[k + 0];
+                        currentY += val[k + 1];
+
                         if (k > 0) {
                             // According to the spec, if a moveto is followed by multiple
                             // pairs of coordinates, the subsequent pairs are treated as
                             // implicit lineto commands.
-                            path.lineTo(cx, cy);
+                            path.rLineTo(val[k + 0], val[k + 1]);
                         } else {
-                            path.moveTo(cx, cy);
-                            loopX = cx;
-                            loopY = cy;
+                            path.rMoveTo(val[k + 0], val[k + 1]);
+                            currentSegmentStartX = currentX;
+                            currentSegmentStartY = currentY;
                         }
                         break;
-                    case 'M':
-                        cx = val[k + 0];
-                        cy = val[k + 1];
+                    case 'M': // moveto - Start a new sub-path
+                        currentX = val[k + 0];
+                        currentY = val[k + 1];
+
                         if (k > 0) {
                             // According to the spec, if a moveto is followed by multiple
                             // pairs of coordinates, the subsequent pairs are treated as
                             // implicit lineto commands.
-                            path.lineTo(cx, cy);
+                            path.lineTo(val[k + 0], val[k + 1]);
                         } else {
-                            path.moveTo(cx, cy);
-                            loopX = cx;
-                            loopY = cy;
+                            path.moveTo(val[k + 0], val[k + 1]);
+                            currentSegmentStartX = currentX;
+                            currentSegmentStartY = currentY;
                         }
                         break;
-                    case 'l':
-                        cx += val[k + 0];
-                        cy += val[k + 1];
-                        path.lineTo(cx, cy);
+                    case 'l': // lineto - Draw a line from the current point (relative)
+                        path.rLineTo(val[k + 0], val[k + 1]);
+                        currentX += val[k + 0];
+                        currentY += val[k + 1];
                         break;
-                    case 'L':
-                        cx = val[k + 0];
-                        cy = val[k + 1];
-                        path.lineTo(cx, cy);
+                    case 'L': // lineto - Draw a line from the current point
+                        path.lineTo(val[k + 0], val[k + 1]);
+                        currentX = val[k + 0];
+                        currentY = val[k + 1];
                         break;
-                    case 'z':
-                    case 'Z':
-                        path.closePath();
-                        cx = loopX;
-                        cy = loopY;
+                    case 'h': // horizontal lineto - Draws a horizontal line (relative)
+                        path.rLineTo(val[k + 0], 0);
+                        currentX += val[k + 0];
                         break;
-                    case 'h':
-                        cx += val[k + 0];
-                        path.lineTo(cx, cy);
+                    case 'H': // horizontal lineto - Draws a horizontal line
+                        path.lineTo(val[k + 0], currentY);
+                        currentX = val[k + 0];
                         break;
-                    case 'H':
-                        path.lineTo(val[k + 0], cy);
-                        cx = val[k + 0];
+                    case 'v': // vertical lineto - Draws a vertical line from the current point (r)
+                        path.rLineTo(0, val[k + 0]);
+                        currentY += val[k + 0];
                         break;
-                    case 'v':
-                        cy += val[k + 0];
-                        path.lineTo(cx, cy);
+                    case 'V': // vertical lineto - Draws a vertical line from the current point
+                        path.lineTo(currentX, val[k + 0]);
+                        currentY = val[k + 0];
                         break;
-                    case 'V':
-                        path.lineTo(cx, val[k + 0]);
-                        cy = val[k + 0];
-                        break;
-                    case 'c':
-                        path.curveTo(cx + val[k + 0], cy + val[k + 1], cx + val[k + 2],
-                                cy + val[k + 3], cx + val[k + 4], cy + val[k + 5]);
-                        cpx = cx + val[k + 2];
-                        cpy = cy + val[k + 3];
-                        cx += val[k + 4];
-                        cy += val[k + 5];
-                        break;
-                    case 'C':
-                        path.curveTo(val[k + 0], val[k + 1], val[k + 2], val[k + 3],
+                    case 'c': // curveto - Draws a cubic Bézier curve (relative)
+                        path.rCubicTo(val[k + 0], val[k + 1], val[k + 2], val[k + 3],
                                 val[k + 4], val[k + 5]);
-                        cx = val[k + 4];
-                        cy = val[k + 5];
-                        cpx = val[k + 2];
-                        cpy = val[k + 3];
-                        break;
-                    case 's':
-                        reflectCtrl = (lastCmd == 'c' || lastCmd == 's' || lastCmd == 'C' ||
-                                lastCmd == 'S');
-                        path.curveTo(reflectCtrl ? 2 * cx - cpx : cx, reflectCtrl ? 2
-                                * cy - cpy : cy, cx + val[k + 0], cy + val[k + 1], cx
-                                + val[k + 2], cy + val[k + 3]);
 
-                        cpx = cx + val[k + 0];
-                        cpy = cy + val[k + 1];
-                        cx += val[k + 2];
-                        cy += val[k + 3];
+                        ctrlPointX = currentX + val[k + 2];
+                        ctrlPointY = currentY + val[k + 3];
+                        currentX += val[k + 4];
+                        currentY += val[k + 5];
+
                         break;
-                    case 'S':
-                        reflectCtrl = (lastCmd == 'c' || lastCmd == 's' || lastCmd == 'C' ||
-                                lastCmd == 'S');
-                        path.curveTo(reflectCtrl ? 2 * cx - cpx : cx, reflectCtrl ? 2
-                                        * cy - cpy : cy, val[k + 0], val[k + 1], val[k + 2],
-                                val[k + 3]);
-                        cpx = (val[k + 0]);
-                        cpy = (val[k + 1]);
-                        cx = val[k + 2];
-                        cy = val[k + 3];
+                    case 'C': // curveto - Draws a cubic Bézier curve
+                        path.cubicTo(val[k + 0], val[k + 1], val[k + 2], val[k + 3],
+                                val[k + 4], val[k + 5]);
+                        currentX = val[k + 4];
+                        currentY = val[k + 5];
+                        ctrlPointX = val[k + 2];
+                        ctrlPointY = val[k + 3];
                         break;
-                    case 'q':
-                        path.quadTo(cx + val[k + 0], cy + val[k + 1], cx + val[k + 2],
-                                cy + val[k + 3]);
-                        cpx = cx + val[k + 0];
-                        cpy = cy + val[k + 1];
-                        // Note that we have to update cpx first, since cx will be updated here.
-                        cx += val[k + 2];
-                        cy += val[k + 3];
+                    case 's': // smooth curveto - Draws a cubic Bézier curve (reflective cp)
+                        reflectiveCtrlPointX = 0;
+                        reflectiveCtrlPointY = 0;
+                        if (previousCmd == 'c' || previousCmd == 's'
+                                || previousCmd == 'C' || previousCmd == 'S') {
+                            reflectiveCtrlPointX = currentX - ctrlPointX;
+                            reflectiveCtrlPointY = currentY - ctrlPointY;
+                        }
+                        path.rCubicTo(reflectiveCtrlPointX, reflectiveCtrlPointY,
+                                val[k + 0], val[k + 1],
+                                val[k + 2], val[k + 3]);
+
+                        ctrlPointX = currentX + val[k + 0];
+                        ctrlPointY = currentY + val[k + 1];
+                        currentX += val[k + 2];
+                        currentY += val[k + 3];
                         break;
-                    case 'Q':
+                    case 'S': // shorthand/smooth curveto Draws a cubic Bézier curve(reflective cp)
+                        reflectiveCtrlPointX = currentX;
+                        reflectiveCtrlPointY = currentY;
+                        if (previousCmd == 'c' || previousCmd == 's'
+                                || previousCmd == 'C' || previousCmd == 'S') {
+                            reflectiveCtrlPointX = 2 * currentX - ctrlPointX;
+                            reflectiveCtrlPointY = 2 * currentY - ctrlPointY;
+                        }
+                        path.cubicTo(reflectiveCtrlPointX, reflectiveCtrlPointY,
+                                val[k + 0], val[k + 1], val[k + 2], val[k + 3]);
+                        ctrlPointX = val[k + 0];
+                        ctrlPointY = val[k + 1];
+                        currentX = val[k + 2];
+                        currentY = val[k + 3];
+                        break;
+                    case 'q': // Draws a quadratic Bézier (relative)
+                        path.rQuadTo(val[k + 0], val[k + 1], val[k + 2], val[k + 3]);
+                        ctrlPointX = currentX + val[k + 0];
+                        ctrlPointY = currentY + val[k + 1];
+                        currentX += val[k + 2];
+                        currentY += val[k + 3];
+                        break;
+                    case 'Q': // Draws a quadratic Bézier
                         path.quadTo(val[k + 0], val[k + 1], val[k + 2], val[k + 3]);
-                        cx = val[k + 2];
-                        cy = val[k + 3];
-                        cpx = val[k + 0];
-                        cpy = val[k + 1];
+                        ctrlPointX = val[k + 0];
+                        ctrlPointY = val[k + 1];
+                        currentX = val[k + 2];
+                        currentY = val[k + 3];
                         break;
-                    case 't':
-                        reflectCtrl = (lastCmd == 'q' || lastCmd == 't' || lastCmd == 'Q' ||
-                                lastCmd == 'T');
-                        tempReflectedX = reflectCtrl ? 2 * cx - cpx : cx;
-                        tempReflectedY = reflectCtrl ? 2 * cy - cpy : cy;
-                        path.quadTo(tempReflectedX, tempReflectedY, cx + val[k + 0],
-                                cy + val[k + 1]);
-                        cpx = tempReflectedX;
-                        cpy = tempReflectedY;
-                        cx += val[k + 0];
-                        cy += val[k + 1];
+                    case 't': // Draws a quadratic Bézier curve(reflective control point)(relative)
+                        reflectiveCtrlPointX = 0;
+                        reflectiveCtrlPointY = 0;
+                        if (previousCmd == 'q' || previousCmd == 't'
+                                || previousCmd == 'Q' || previousCmd == 'T') {
+                            reflectiveCtrlPointX = currentX - ctrlPointX;
+                            reflectiveCtrlPointY = currentY - ctrlPointY;
+                        }
+                        path.rQuadTo(reflectiveCtrlPointX, reflectiveCtrlPointY,
+                                val[k + 0], val[k + 1]);
+                        ctrlPointX = currentX + reflectiveCtrlPointX;
+                        ctrlPointY = currentY + reflectiveCtrlPointY;
+                        currentX += val[k + 0];
+                        currentY += val[k + 1];
                         break;
-                    case 'T':
-                        reflectCtrl = (lastCmd == 'q' || lastCmd == 't' || lastCmd == 'Q' ||
-                                lastCmd == 'T');
-                        tempReflectedX = reflectCtrl ? 2 * cx - cpx : cx;
-                        tempReflectedY = reflectCtrl ? 2 * cy - cpy : cy;
-                        path.quadTo(tempReflectedX, tempReflectedY, val[k + 0], val[k + 1]);
-                        cx = val[k + 0];
-                        cy = val[k + 1];
-                        cpx = tempReflectedX;
-                        cpy = tempReflectedY;
+                    case 'T': // Draws a quadratic Bézier curve (reflective control point)
+                        reflectiveCtrlPointX = currentX;
+                        reflectiveCtrlPointY = currentY;
+                        if (previousCmd == 'q' || previousCmd == 't'
+                                || previousCmd == 'Q' || previousCmd == 'T') {
+                            reflectiveCtrlPointX = 2 * currentX - ctrlPointX;
+                            reflectiveCtrlPointY = 2 * currentY - ctrlPointY;
+                        }
+                        path.quadTo(reflectiveCtrlPointX, reflectiveCtrlPointY,
+                                val[k + 0], val[k + 1]);
+                        ctrlPointX = reflectiveCtrlPointX;
+                        ctrlPointY = reflectiveCtrlPointY;
+                        currentX = val[k + 0];
+                        currentY = val[k + 1];
                         break;
-                    case 'a':
+                    case 'a': // Draws an elliptical arc
                         // (rx ry x-axis-rotation large-arc-flag sweep-flag x y)
-                        drawArc(path, cx, cy, val[k + 5] + cx, val[k + 6] + cy,
-                                val[k + 0], val[k + 1], val[k + 2], val[k + 3] != 0,
+                        drawArc(path,
+                                currentX,
+                                currentY,
+                                val[k + 5] + currentX,
+                                val[k + 6] + currentY,
+                                val[k + 0],
+                                val[k + 1],
+                                val[k + 2],
+                                val[k + 3] != 0,
                                 val[k + 4] != 0);
-                        cx += val[k + 5];
-                        cy += val[k + 6];
-                        cpx = cx;
-                        cpy = cy;
-
+                        currentX += val[k + 5];
+                        currentY += val[k + 6];
+                        ctrlPointX = currentX;
+                        ctrlPointY = currentY;
                         break;
-                    case 'A':
-                        drawArc(path, cx, cy, val[k + 5], val[k + 6], val[k + 0],
-                                val[k + 1], val[k + 2], val[k + 3] != 0,
+                    case 'A': // Draws an elliptical arc
+                        drawArc(path,
+                                currentX,
+                                currentY,
+                                val[k + 5],
+                                val[k + 6],
+                                val[k + 0],
+                                val[k + 1],
+                                val[k + 2],
+                                val[k + 3] != 0,
                                 val[k + 4] != 0);
-                        cx = val[k + 5];
-                        cy = val[k + 6];
-                        cpx = cx;
-                        cpy = cy;
+                        currentX = val[k + 5];
+                        currentY = val[k + 6];
+                        ctrlPointX = currentX;
+                        ctrlPointY = currentY;
                         break;
-
                 }
-                lastCmd = cmd;
+                previousCmd = cmd;
             }
-            current[0] = cx;
-            current[1] = cy;
-            current[2] = cpx;
-            current[3] = cpy;
-            current[4] = loopX;
-            current[5] = loopY;
-
+            current[0] = currentX;
+            current[1] = currentY;
+            current[2] = ctrlPointX;
+            current[3] = ctrlPointY;
+            current[4] = currentSegmentStartX;
+            current[5] = currentSegmentStartY;
         }
 
-        private static void drawArc(@NonNull Path2D p, float x0, float y0, float x1,
+        private static void drawArc(@NonNull Path_Delegate p, float x0, float y0, float x1,
                 float y1, float a, float b, float theta, boolean isMoreThanHalf,
                 boolean isPositiveArc) {
 
@@ -707,7 +790,7 @@
          * @param start The start angle of the arc on the ellipse
          * @param sweep The angle (positive or negative) of the sweep of the arc on the ellipse
          */
-        private static void arcToBezier(@NonNull Path2D p, double cx, double cy, double a,
+        private static void arcToBezier(@NonNull Path_Delegate p, double cx, double cy, double a,
                 double b, double e1x, double e1y, double theta, double start,
                 double sweep) {
             // Taken from equations at:
@@ -744,8 +827,12 @@
                 double q2x = e2x - alpha * ep2x;
                 double q2y = e2y - alpha * ep2y;
 
-                p.curveTo((float) q1x, (float) q1y, (float) q2x, (float) q2y,
-                        (float) e2x, (float) e2y);
+                p.cubicTo((float) q1x,
+                        (float) q1y,
+                        (float) q2x,
+                        (float) q2y,
+                        (float) e2x,
+                        (float) e2y);
                 eta1 = eta2;
                 e1x = e2x;
                 e1y = e2y;
diff --git a/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java b/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
index 8d1b124..62f91f7 100644
--- a/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
+++ b/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
@@ -20,6 +20,7 @@
 import android.graphics.Rect;
 import com.android.internal.app.IAssistScreenshotReceiver;
 import com.android.internal.os.IResultReceiver;
+import com.android.internal.policy.IShortcutService;
 import com.android.internal.view.IInputContext;
 import com.android.internal.view.IInputMethodClient;
 
@@ -348,7 +349,7 @@
     }
 
     @Override
-    public void notifyAppStopped(IBinder token) throws RemoteException {
+    public void notifyAppStopped(IBinder token, boolean stopped) throws RemoteException {
         // TODO Auto-generated method stub
     }
 
@@ -560,10 +561,18 @@
     }
 
     @Override
+    public void setDockedStackDividerTouchRegion(Rect touchableRegion) throws RemoteException {
+    }
+
+    @Override
     public void requestAppKeyboardShortcuts(IResultReceiver receiver) throws RemoteException {
     }
 
     @Override
     public void getStableInsets(Rect outInsets) throws RemoteException {
     }
+
+    @Override
+    public void registerShortcutKey(long shortcutCode, IShortcutService service)
+        throws RemoteException {}
 }
diff --git a/tools/layoutlib/bridge/src/com/android/internal/view/animation/NativeInterpolatorFactoryHelper_Delegate.java b/tools/layoutlib/bridge/src/com/android/internal/view/animation/NativeInterpolatorFactoryHelper_Delegate.java
new file mode 100644
index 0000000..0f39e80
--- /dev/null
+++ b/tools/layoutlib/bridge/src/com/android/internal/view/animation/NativeInterpolatorFactoryHelper_Delegate.java
@@ -0,0 +1,128 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.view.animation;
+
+import com.android.layoutlib.bridge.impl.DelegateManager;
+import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
+
+import android.util.MathUtils;
+import android.view.animation.AccelerateDecelerateInterpolator;
+import android.view.animation.AccelerateInterpolator;
+import android.view.animation.AnticipateInterpolator;
+import android.view.animation.AnticipateOvershootInterpolator;
+import android.view.animation.BaseInterpolator;
+import android.view.animation.BounceInterpolator;
+import android.view.animation.CycleInterpolator;
+import android.view.animation.DecelerateInterpolator;
+import android.view.animation.Interpolator;
+import android.view.animation.LinearInterpolator;
+import android.view.animation.OvershootInterpolator;
+
+/**
+ * Delegate used to provide new implementation of a select few methods of {@link
+ * NativeInterpolatorFactoryHelper}
+ * <p>
+ * Through the layoutlib_create tool, the original  methods of NativeInterpolatorFactoryHelper have
+ * been replaced by calls to methods of the same name in this delegate class.
+ */
+@SuppressWarnings("unused")
+public class NativeInterpolatorFactoryHelper_Delegate {
+    private static final DelegateManager<Interpolator> sManager = new DelegateManager<>
+            (Interpolator.class);
+
+    public static Interpolator getDelegate(long nativePtr) {
+        return sManager.getDelegate(nativePtr);
+    }
+
+    @LayoutlibDelegate
+    /*package*/ static long createAccelerateDecelerateInterpolator() {
+        return sManager.addNewDelegate(new AccelerateDecelerateInterpolator());
+    }
+
+    @LayoutlibDelegate
+    /*package*/ static long createAccelerateInterpolator(float factor) {
+        return sManager.addNewDelegate(new AccelerateInterpolator(factor));
+    }
+
+    @LayoutlibDelegate
+    /*package*/ static long createAnticipateInterpolator(float tension) {
+        return sManager.addNewDelegate(new AnticipateInterpolator(tension));
+    }
+
+    @LayoutlibDelegate
+    /*package*/ static long createAnticipateOvershootInterpolator(float tension) {
+        return sManager.addNewDelegate(new AnticipateOvershootInterpolator(tension));
+    }
+
+    @LayoutlibDelegate
+    /*package*/ static long createBounceInterpolator() {
+        return sManager.addNewDelegate(new BounceInterpolator());
+    }
+
+    @LayoutlibDelegate
+    /*package*/ static long createCycleInterpolator(float cycles) {
+        return sManager.addNewDelegate(new CycleInterpolator(cycles));
+    }
+
+    @LayoutlibDelegate
+    /*package*/ static long createDecelerateInterpolator(float factor) {
+        return sManager.addNewDelegate(new DecelerateInterpolator(factor));
+    }
+
+    @LayoutlibDelegate
+    /*package*/ static long createLinearInterpolator() {
+        return sManager.addNewDelegate(new LinearInterpolator());
+    }
+
+    @LayoutlibDelegate
+    /*package*/ static long createOvershootInterpolator(float tension) {
+        return sManager.addNewDelegate(new OvershootInterpolator(tension));
+    }
+
+    private static class LutInterpolator extends BaseInterpolator {
+        private final float[] mValues;
+        private final int mSize;
+
+        private LutInterpolator(float[] values) {
+            mValues = values;
+            mSize = mValues.length;
+        }
+
+        @Override
+        public float getInterpolation(float input) {
+            float lutpos = input * mSize;
+            if (lutpos >= (mSize - 1)) {
+                return mValues[mSize - 1];
+            }
+
+            int ipart = (int) lutpos;
+            float weight = lutpos - ipart;
+
+            int i1 = ipart;
+            int i2 = Math.min(i1 + 1, mSize - 1);
+
+            assert i1 >= 0 && i2 >= 0 : "Negatives in the interpolation";
+
+            return MathUtils.lerp(mValues[i1], mValues[i2], weight);
+        }
+    }
+
+    @LayoutlibDelegate
+    /*package*/ static long createLutInterpolator(float[] values) {
+        return sManager.addNewDelegate(new LutInterpolator(values));
+    }
+}
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 17ab2ff5..c7ae6fc 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
@@ -52,11 +52,11 @@
 import android.content.pm.PackageManager;
 import android.content.res.AssetManager;
 import android.content.res.BridgeAssetManager;
-import android.content.res.BridgeResources;
 import android.content.res.BridgeTypedArray;
 import android.content.res.Configuration;
 import android.content.res.Resources;
 import android.content.res.Resources.Theme;
+import android.content.res.Resources_Delegate;
 import android.database.DatabaseErrorHandler;
 import android.database.sqlite.SQLiteDatabase;
 import android.database.sqlite.SQLiteDatabase.CursorFactory;
@@ -168,8 +168,8 @@
         RTL_ATTRS.put("?android:attr/paddingRight", "paddingEnd");
         RTL_ATTRS.put("?android:attr/layout_marginLeft", "layout_marginStart");
         RTL_ATTRS.put("?android:attr/layout_marginRight", "layout_marginEnd");
-        RTL_ATTRS.put("?android:attr/layout_toLeft", "layout_toStartOf");
-        RTL_ATTRS.put("?android:attr/layout_toRight", "layout_toEndOf");
+        RTL_ATTRS.put("?android:attr/layout_toLeftOf", "layout_toStartOf");
+        RTL_ATTRS.put("?android:attr/layout_toRightOf", "layout_toEndOf");
         RTL_ATTRS.put("?android:attr/layout_alignParentLeft", "layout_alignParentStart");
         RTL_ATTRS.put("?android:attr/layout_alignParentRight", "layout_alignParentEnd");
         RTL_ATTRS.put("?android:attr/drawableLeft", "drawableStart");
@@ -224,7 +224,7 @@
     public void initResources() {
         AssetManager assetManager = AssetManager.getSystem();
 
-        mSystemResources = BridgeResources.initSystem(
+        mSystemResources = Resources_Delegate.initSystem(
                 this,
                 assetManager,
                 mMetrics,
@@ -237,7 +237,7 @@
      * Disposes the {@link Resources} singleton.
      */
     public void disposeResources() {
-        BridgeResources.disposeSystem();
+        Resources_Delegate.disposeSystem();
     }
 
     public void setBridgeInflater(BridgeInflater inflater) {
@@ -706,8 +706,8 @@
 
         List<Pair<String, Boolean>> attributeList = searchAttrs(attrs);
 
-        BridgeTypedArray ta = ((BridgeResources) mSystemResources).newTypeArray(attrs.length,
-                isPlatformFile);
+        BridgeTypedArray ta =
+                Resources_Delegate.newTypeArray(mSystemResources, attrs.length, isPlatformFile);
 
         // look for a custom style.
         String customStyle = null;
@@ -941,7 +941,7 @@
 
         List<Pair<String, Boolean>> attributes = searchAttrs(attrs);
 
-        BridgeTypedArray ta = ((BridgeResources) mSystemResources).newTypeArray(attrs.length,
+        BridgeTypedArray ta = Resources_Delegate.newTypeArray(mSystemResources, attrs.length,
                 false);
 
         // for each attribute, get its name so that we can search it in the style
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 fcfbad2..4039cdf 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
@@ -24,7 +24,6 @@
 import android.content.IntentSender;
 import android.content.pm.ActivityInfo;
 import android.content.pm.ApplicationInfo;
-import android.content.pm.ContainerEncryptionParams;
 import android.content.pm.EphemeralApplicationInfo;
 import android.content.pm.FeatureInfo;
 import android.content.pm.IPackageDataObserver;
@@ -43,7 +42,6 @@
 import android.content.pm.ProviderInfo;
 import android.content.pm.ResolveInfo;
 import android.content.pm.ServiceInfo;
-import android.content.pm.VerificationParams;
 import android.content.pm.VerifierDeviceIdentity;
 import android.content.res.Resources;
 import android.content.res.XmlResourceParser;
@@ -486,6 +484,12 @@
     }
 
     @Override
+    public Drawable getManagedUserBadgedDrawable(Drawable drawable, Rect badgeLocation,
+        int badgeDensity) {
+        return null;
+    }
+
+    @Override
     public Drawable getUserBadgedIcon(Drawable icon, UserHandle user) {
         return null;
     }
@@ -555,40 +559,11 @@
     }
 
     @Override
-    public void installPackageWithVerification(Uri packageURI, IPackageInstallObserver observer,
-            int flags, String installerPackageName, Uri verificationURI,
-            ContainerEncryptionParams encryptionParams) {
-    }
-
-    @Override
-    public void installPackageWithVerificationAndEncryption(Uri packageURI,
-            IPackageInstallObserver observer, int flags, String installerPackageName,
-            VerificationParams verificationParams, ContainerEncryptionParams encryptionParams) {
-    }
-
-    @Override
     public void installPackage(Uri packageURI, PackageInstallObserver observer, int flags,
             String installerPackageName) {
     }
 
     @Override
-    public void installPackageAsUser(Uri packageURI, PackageInstallObserver observer,int flags,
-            String installerPackageName, int userId) {
-    }
-
-    @Override
-    public void installPackageWithVerification(Uri packageURI, PackageInstallObserver observer,
-            int flags, String installerPackageName, Uri verificationURI,
-            ContainerEncryptionParams encryptionParams) {
-    }
-
-    @Override
-    public void installPackageWithVerificationAndEncryption(Uri packageURI,
-            PackageInstallObserver observer, int flags, String installerPackageName,
-            VerificationParams verificationParams, ContainerEncryptionParams encryptionParams) {
-    }
-
-    @Override
     public int installExistingPackage(String packageName) throws NameNotFoundException {
         return 0;
     }
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java
index 99af226..53f1912 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java
@@ -60,6 +60,7 @@
 import android.graphics.Bitmap;
 import android.graphics.Bitmap_Delegate;
 import android.graphics.Canvas;
+import android.os.Looper;
 import android.preference.Preference_Delegate;
 import android.view.AttachInfo_Accessor;
 import android.view.BridgeInflater;
@@ -1398,6 +1399,14 @@
     }
 
     public void dispose() {
+        boolean createdLooper = false;
+        if (Looper.myLooper() == null) {
+            // Detaching the root view from the window will try to stop any running animations.
+            // The stop method checks that it can run in the looper so, if there is no current
+            // looper, we create a temporary one to complete the shutdown.
+            Bridge.prepareThread();
+            createdLooper = true;
+        }
         AttachInfo_Accessor.detachFromWindow(mViewRoot);
         if (mCanvas != null) {
             mCanvas.release();
@@ -1412,5 +1421,9 @@
         mImage = null;
         mViewRoot = null;
         mContentRoot = null;
+
+        if (createdLooper) {
+            Bridge.cleanupThread();
+        }
     }
 }
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 c72eeb1..494b3d2 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
@@ -33,7 +33,11 @@
 import org.xmlpull.v1.XmlPullParserException;
 
 import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.content.res.ColorStateList;
+import android.content.res.ComplexColor;
+import android.content.res.ComplexColor_Accessor;
+import android.content.res.GradientColor;
 import android.content.res.Resources.Theme;
 import android.graphics.Bitmap;
 import android.graphics.Bitmap_Delegate;
@@ -47,6 +51,7 @@
 
 import java.io.File;
 import java.io.FileInputStream;
+import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.io.InputStream;
 import java.net.MalformedURLException;
@@ -119,54 +124,128 @@
         throw new NumberFormatException();
     }
 
-    public static ColorStateList getColorStateList(ResourceValue resValue, BridgeContext context) {
+    /**
+     * Returns a {@link ComplexColor} from the given {@link ResourceValue}
+     *
+     * @param resValue the value containing a color value or a file path to a complex color
+     * definition
+     * @param context the current context
+     * @param theme the theme to use when resolving the complex color
+     * @param allowGradients when false, only {@link ColorStateList} will be returned. If a {@link
+     * GradientColor} is found, null will be returned.
+     */
+    @Nullable
+    private static ComplexColor getInternalComplexColor(@NonNull ResourceValue resValue,
+            @NonNull BridgeContext context, @Nullable Theme theme, boolean allowGradients) {
         String value = resValue.getValue();
-        if (value != null && !RenderResources.REFERENCE_NULL.equals(value)) {
-            // first check if the value is a file (xml most likely)
+        if (value == null || RenderResources.REFERENCE_NULL.equals(value)) {
+            return null;
+        }
+
+        // first check if the value is a file (xml most likely)
+        XmlPullParser parser = context.getLayoutlibCallback().getXmlFileParser(value);
+        if (parser == null) {
             File f = new File(value);
             if (f.isFile()) {
+                // let the framework inflate the color from the XML file, by
+                // providing an XmlPullParser
                 try {
-                    // let the framework inflate the ColorStateList from the XML file, by
-                    // providing an XmlPullParser
-                    XmlPullParser parser = ParserFactory.create(f);
-
-                    BridgeXmlBlockParser blockParser = new BridgeXmlBlockParser(
-                            parser, context, resValue.isFramework());
-                    try {
-                        return ColorStateList.createFromXml(context.getResources(), blockParser);
-                    } finally {
-                        blockParser.ensurePopped();
-                    }
-                } catch (XmlPullParserException e) {
-                    Bridge.getLog().error(LayoutLog.TAG_BROKEN,
-                            "Failed to configure parser for " + value, e, null /*data*/);
-                    // we'll return null below.
-                } catch (Exception e) {
-                    // this is an error and not warning since the file existence is
-                    // checked before attempting to parse it.
+                    parser = ParserFactory.create(f);
+                } catch (XmlPullParserException | FileNotFoundException e) {
                     Bridge.getLog().error(LayoutLog.TAG_RESOURCES_READ,
                             "Failed to parse file " + value, e, null /*data*/);
-
-                    return null;
-                }
-            } else {
-                // try to load the color state list from an int
-                try {
-                    int color = ResourceHelper.getColor(value);
-                    return ColorStateList.valueOf(color);
-                } catch (NumberFormatException e) {
-                    Bridge.getLog().error(LayoutLog.TAG_RESOURCES_FORMAT,
-                            "Failed to convert " + value + " into a ColorStateList", e,
-                            null /*data*/);
-                    return null;
                 }
             }
         }
 
+        if (parser != null) {
+            try {
+                BridgeXmlBlockParser blockParser = new BridgeXmlBlockParser(
+                        parser, context, resValue.isFramework());
+                try {
+                    // Advance the parser to the first element so we can detect if it's a
+                    // color list or a gradient color
+                    int type;
+                    //noinspection StatementWithEmptyBody
+                    while ((type = blockParser.next()) != XmlPullParser.START_TAG
+                            && type != XmlPullParser.END_DOCUMENT) {
+                        // Seek parser to start tag.
+                    }
+
+                    if (type != XmlPullParser.START_TAG) {
+                        throw new XmlPullParserException("No start tag found");
+                    }
+
+                    final String name = blockParser.getName();
+                    if (allowGradients && "gradient".equals(name)) {
+                        return ComplexColor_Accessor.createGradientColorFromXmlInner(
+                                context.getResources(),
+                                blockParser, blockParser,
+                                theme);
+                    } else if ("selector".equals(name)) {
+                        return ComplexColor_Accessor.createColorStateListFromXmlInner(
+                                context.getResources(),
+                                blockParser, blockParser,
+                                theme);
+                    }
+                } finally {
+                    blockParser.ensurePopped();
+                }
+            } catch (XmlPullParserException e) {
+                Bridge.getLog().error(LayoutLog.TAG_BROKEN,
+                        "Failed to configure parser for " + value, e, null /*data*/);
+                // we'll return null below.
+            } catch (Exception e) {
+                // this is an error and not warning since the file existence is
+                // checked before attempting to parse it.
+                Bridge.getLog().error(LayoutLog.TAG_RESOURCES_READ,
+                        "Failed to parse file " + value, e, null /*data*/);
+
+                return null;
+            }
+        } else {
+            // try to load the color state list from an int
+            try {
+                int color = getColor(value);
+                return ColorStateList.valueOf(color);
+            } catch (NumberFormatException e) {
+                Bridge.getLog().error(LayoutLog.TAG_RESOURCES_FORMAT,
+                        "Failed to convert " + value + " into a ColorStateList", e,
+                        null /*data*/);
+            }
+        }
+
         return null;
     }
 
     /**
+     * Returns a {@link ColorStateList} from the given {@link ResourceValue}
+     *
+     * @param resValue the value containing a color value or a file path to a complex color
+     * definition
+     * @param context the current context
+     */
+    @Nullable
+    public static ColorStateList getColorStateList(@NonNull ResourceValue resValue,
+            @NonNull BridgeContext context) {
+        return (ColorStateList) getInternalComplexColor(resValue, context, context.getTheme(),
+                false);
+    }
+
+    /**
+     * Returns a {@link ComplexColor} from the given {@link ResourceValue}
+     *
+     * @param resValue the value containing a color value or a file path to a complex color
+     * definition
+     * @param context the current context
+     */
+    @Nullable
+    public static ComplexColor getComplexColor(@NonNull ResourceValue resValue,
+            @NonNull BridgeContext context) {
+        return getInternalComplexColor(resValue, context, context.getTheme(), true);
+    }
+
+    /**
      * Returns a drawable from the given value.
      * @param value The value that contains a path to a 9 patch, a bitmap or a xml based drawable,
      * or an hexadecimal color
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/util/NinePatchInputStream.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/util/NinePatchInputStream.java
new file mode 100644
index 0000000..96b795a
--- /dev/null
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/util/NinePatchInputStream.java
@@ -0,0 +1,50 @@
+/*
+ * 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.layoutlib.bridge.util;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+
+/**
+ * Simpler wrapper around FileInputStream. This is used when the input stream represent
+ * not a normal bitmap but a nine patch.
+ * This is useful when the InputStream is created in a method but used in another that needs
+ * to know whether this is 9-patch or not, such as BitmapFactory.
+ */
+public class NinePatchInputStream extends FileInputStream {
+    private boolean mFakeMarkSupport = true;
+    public NinePatchInputStream(File file) throws FileNotFoundException {
+        super(file);
+    }
+
+    @Override
+    public boolean markSupported() {
+        if (mFakeMarkSupport) {
+            // this is needed so that BitmapFactory doesn't wrap this in a BufferedInputStream.
+            return true;
+        }
+
+        return super.markSupported();
+    }
+
+    public void disableFakeMarkSupport() {
+        // disable fake mark support so that in case codec actually try to use them
+        // we don't lie to them.
+        mFakeMarkSupport = false;
+    }
+}
diff --git a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/vector_drawable.png b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/vector_drawable.png
index 72b87ab..47cb042 100644
--- a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/vector_drawable.png
+++ b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/vector_drawable.png
Binary files differ
diff --git a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/res/color/gradient.xml b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/res/color/gradient.xml
new file mode 100644
index 0000000..fc0afa6
--- /dev/null
+++ b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/res/color/gradient.xml
@@ -0,0 +1,24 @@
+<!--
+  ~ 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.
+  -->
+
+
+<gradient xmlns:android="http://schemas.android.com/apk/res/android"
+          android:startX="10"
+          android:startY="10"
+          android:endX="50"
+          android:endY="50"
+          android:startColor="#ffff0000"
+          android:endColor="#ff00ff00" />
diff --git a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/res/drawable/multi_path.xml b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/res/drawable/multi_path.xml
index ffc70dc..5c19b08 100644
--- a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/res/drawable/multi_path.xml
+++ b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/res/drawable/multi_path.xml
@@ -53,6 +53,16 @@
             android:trimPathStart="0.2"
             android:trimPathEnd="0.8"
         />
+
+        <!--
+            Draw a line with gradient stroke color
+        -->
+        <path
+            android:strokeWidth="1"
+            android:strokeColor="#FF00FF"
+            android:fillColor="@color/gradient"
+            android:pathData="M-20,-20 l0, 10 l10, 0 l0, -10 l-10,0 "
+        />
     </group>
 
 </vector>
\ 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 6b23da7..2726042 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
@@ -335,7 +335,7 @@
                 .setNavigation(Navigation.NONAV);
 
         SessionParams params = getSessionParams(parser, customConfigGenerator,
-                layoutLibCallback, "Theme.Material.NoActionBar.Fullscreen", false,
+                layoutLibCallback, "Theme.Material.Light.NoActionBar.Fullscreen", false,
                 RenderingMode.V_SCROLL, 22);
 
         renderAndVerify(params, "expand_vert_layout.png");
@@ -348,7 +348,7 @@
         parser = new LayoutPullParser(APP_TEST_RES + "/layout/" +
                 "expand_horz_layout.xml");
         params = getSessionParams(parser, customConfigGenerator,
-                layoutLibCallback, "Theme.Material.NoActionBar.Fullscreen", false,
+                layoutLibCallback, "Theme.Material.Light.NoActionBar.Fullscreen", false,
                 RenderingMode.H_SCROLL, 22);
 
         renderAndVerify(params, "expand_horz_layout.png");
diff --git a/tools/layoutlib/create/create.iml b/tools/layoutlib/create/create.iml
index b2b14b4..368b46b 100644
--- a/tools/layoutlib/create/create.iml
+++ b/tools/layoutlib/create/create.iml
@@ -22,6 +22,6 @@
         </SOURCES>
       </library>
     </orderEntry>
-    <orderEntry type="library" scope="TEST" name="JUnit4" level="application" />
+    <orderEntry type="library" scope="TEST" name="junit" level="project" />
   </component>
 </module>
\ No newline at end of file
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 5b99a6b..3b37612 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
@@ -367,6 +367,10 @@
 
         ClassVisitor cv = cw;
 
+        // FIXME Generify
+        if ("android/content/res/Resources".equals(className)) {
+            cv = new FieldInjectorAdapter(cv);
+        }
         if (mReplaceMethodCallsClasses.contains(className)) {
             cv = new ReplaceMethodCallsAdapter(cv, className);
         }
@@ -445,4 +449,5 @@
         }
         return buffer.toByteArray();
     }
+
 }
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 8a23e4b..bd37665 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
@@ -155,6 +155,31 @@
      */
     public final static String[] DELEGATE_METHODS = new String[] {
         "android.app.Fragment#instantiate", //(Landroid/content/Context;Ljava/lang/String;Landroid/os/Bundle;)Landroid/app/Fragment;",
+        "android.content.res.Resources#getAnimation",
+        "android.content.res.Resources#getBoolean",
+        "android.content.res.Resources#getColor",
+        "android.content.res.Resources#getColorStateList",
+        "android.content.res.Resources#getDimension",
+        "android.content.res.Resources#getDimensionPixelOffset",
+        "android.content.res.Resources#getDimensionPixelSize",
+        "android.content.res.Resources#getDrawable",
+        "android.content.res.Resources#getIntArray",
+        "android.content.res.Resources#getInteger",
+        "android.content.res.Resources#getLayout",
+        "android.content.res.Resources#getResourceEntryName",
+        "android.content.res.Resources#getResourceName",
+        "android.content.res.Resources#getResourceTypeName",
+        "android.content.res.Resources#getString",
+        "android.content.res.Resources#getStringArray",
+        "android.content.res.Resources#getText",
+        "android.content.res.Resources#getTextArray",
+        "android.content.res.Resources#getValue",
+        "android.content.res.Resources#getXml",
+        "android.content.res.Resources#loadXmlResourceParser",
+        "android.content.res.Resources#obtainAttributes",
+        "android.content.res.Resources#obtainTypedArray",
+        "android.content.res.Resources#openRawResource",
+        "android.content.res.Resources#openRawResourceFd",
         "android.content.res.Resources$Theme#obtainStyledAttributes",
         "android.content.res.Resources$Theme#resolveAttribute",
         "android.content.res.Resources$Theme#resolveAttributes",
@@ -164,6 +189,7 @@
         "android.content.res.TypedArray#obtain",
         "android.graphics.BitmapFactory#finishDecode",
         "android.graphics.BitmapFactory#setDensityFromOptions",
+        "android.graphics.drawable.AnimatedVectorDrawable$VectorDrawableAnimatorRT#useLastSeenTarget",
         "android.graphics.drawable.GradientDrawable#buildRing",
         "android.graphics.Typeface#getSystemFontConfigLocation",
         "android.graphics.Typeface#makeFamilyFromParsed",
@@ -269,12 +295,15 @@
         "android.graphics.SweepGradient",
         "android.graphics.Typeface",
         "android.graphics.Xfermode",
+        "android.graphics.drawable.AnimatedVectorDrawable",
+        "android.graphics.drawable.VectorDrawable",
         "android.os.SystemClock",
         "android.os.SystemProperties",
         "android.text.AndroidBidi",
         "android.text.StaticLayout",
         "android.util.PathParser",
         "android.view.Display",
+        "com.android.internal.view.animation.NativeInterpolatorFactoryHelper",
         "libcore.icu.ICU",
     };
 
@@ -312,7 +341,7 @@
             // Use android.icu.text versions of DateFormat and SimpleDateFormat since the
             // original ones do not match the Android implementation
             "java.text.DateFormat",                            "android.icu.text.DateFormat",
-            "java.text.SimpleDateFormat",                      "android.icu.text.SimpleDateFormat"
+            "java.text.SimpleDateFormat",                      "android.icu.text.SimpleDateFormat",
         };
 
     private final static String[] EXCLUDED_CLASSES =
@@ -321,7 +350,12 @@
             "org.kxml2.io.KXmlParser"
         };
 
+    /**
+     * List of fields for which we will update the visibility to be public. This is sometimes
+     * needed when access from the delegate classes is needed.
+     */
     private final static String[] PROMOTED_FIELDS = new String[] {
+        "android.graphics.drawable.VectorDrawable#mVectorState",
         "android.view.Choreographer#mLastFrameTimeNanos"
     };
 
diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/FieldInjectorAdapter.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/FieldInjectorAdapter.java
new file mode 100644
index 0000000..4608a84
--- /dev/null
+++ b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/FieldInjectorAdapter.java
@@ -0,0 +1,40 @@
+/*
+ * 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.tools.layoutlib.create;
+
+import org.objectweb.asm.ClassVisitor;
+import org.objectweb.asm.Opcodes;
+
+/**
+ * Injects fields in a class.
+ * <p>
+ * TODO: Generify
+ */
+public class FieldInjectorAdapter extends ClassVisitor {
+    public FieldInjectorAdapter(ClassVisitor cv) {
+        super(Opcodes.ASM4, cv);
+    }
+
+    @Override
+    public void visitEnd() {
+        super.visitField(Opcodes.ACC_PUBLIC, "mLayoutlibCallback",
+                "Lcom/android/ide/common/rendering/api/LayoutlibCallback;", null, null);
+        super.visitField(Opcodes.ACC_PUBLIC, "mContext",
+                "Lcom/android/layoutlib/bridge/android/BridgeContext;", null, null);
+        super.visitEnd();
+    }
+}
diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/RefactorClassAdapter.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/RefactorClassAdapter.java
index 91161f5..024e32f 100644
--- a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/RefactorClassAdapter.java
+++ b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/RefactorClassAdapter.java
@@ -16,9 +16,11 @@
 
 package com.android.tools.layoutlib.create;
 
+import java.util.Arrays;
 import java.util.HashMap;
 
 import org.objectweb.asm.ClassVisitor;
+import org.objectweb.asm.MethodVisitor;
 
 public class RefactorClassAdapter extends AbstractClassAdapter {
 
@@ -30,6 +32,14 @@
     }
 
     @Override
+    public MethodVisitor visitMethod(int access, String name, String desc, String signature,
+            String[] exceptions) {
+        MethodVisitor mw = super.visitMethod(access, name, desc, signature, exceptions);
+
+        return new RefactorStackMapAdapter(mw);
+    }
+
+    @Override
     protected String renameInternalType(String oldClassName) {
         if (oldClassName != null) {
             String newName = mRefactorClasses.get(oldClassName);
@@ -46,4 +56,49 @@
         }
         return oldClassName;
     }
+
+    /**
+     * A method visitor that renames all references from an old class name to a new class name in
+     * the stackmap of the method.
+     */
+    private class RefactorStackMapAdapter extends MethodVisitor {
+
+        private RefactorStackMapAdapter(MethodVisitor mv) {
+            super(Main.ASM_VERSION, mv);
+        }
+
+
+        private Object[] renameFrame(Object[] elements) {
+            if (elements == null) {
+                return null;
+            }
+
+            // The input array cannot be modified. We only copy the source array on write
+            boolean copied = false;
+            for (int i = 0; i < elements.length; i++) {
+                if (!(elements[i] instanceof String)) {
+                    continue;
+                }
+
+                if (!copied) {
+                    elements = Arrays.copyOf(elements, elements.length);
+                    copied = true;
+                }
+
+                String type = (String)elements[i];
+                if (type.indexOf(';') > 0) {
+                    elements[i] = renameTypeDesc(type);
+                } else {
+                    elements[i] = renameInternalType(type);
+                }
+            }
+
+            return elements;
+        }
+
+        @Override
+        public void visitFrame(int type, int nLocal, Object[] local, int nStack, Object[] stack) {
+            super.visitFrame(type, nLocal, renameFrame(local), nStack, renameFrame(stack));
+        }
+    }
 }
diff --git a/tools/layoutlib/create/tests/com/android/tools/layoutlib/create/DelegateClassAdapterTest.java b/tools/layoutlib/create/tests/com/android/tools/layoutlib/create/DelegateClassAdapterTest.java
index 0912fb1..afaa399 100644
--- a/tools/layoutlib/create/tests/com/android/tools/layoutlib/create/DelegateClassAdapterTest.java
+++ b/tools/layoutlib/create/tests/com/android/tools/layoutlib/create/DelegateClassAdapterTest.java
@@ -53,12 +53,10 @@
 
     private MockLog mLog;
 
-    private static final String NATIVE_CLASS_NAME = ClassWithNative.class.getCanonicalName();
-    private static final String OUTER_CLASS_NAME = OuterClass.class.getCanonicalName();
-    private static final String INNER_CLASS_NAME = OuterClass.class.getCanonicalName() + "$" +
-                                                   InnerClass.class.getSimpleName();
-    private static final String STATIC_INNER_CLASS_NAME =
-            OuterClass.class.getCanonicalName() + "$" + StaticInnerClass.class.getSimpleName();
+    private static final String NATIVE_CLASS_NAME = ClassWithNative.class.getName();
+    private static final String OUTER_CLASS_NAME = OuterClass.class.getName();
+    private static final String INNER_CLASS_NAME = InnerClass.class.getName();
+    private static final String STATIC_INNER_CLASS_NAME = StaticInnerClass.class.getName();
 
     @Before
     public void setUp() throws Exception {
@@ -69,12 +67,12 @@
     /**
      * Tests that a class not being modified still works.
      */
-    @SuppressWarnings("unchecked")
     @Test
     public void testNoOp() throws Throwable {
         // create an instance of the class that will be modified
         // (load the class in a distinct class loader so that we can trash its definition later)
         ClassLoader cl1 = new ClassLoader(this.getClass().getClassLoader()) { };
+        @SuppressWarnings("unchecked")
         Class<ClassWithNative> clazz1 = (Class<ClassWithNative>) cl1.loadClass(NATIVE_CLASS_NAME);
         ClassWithNative instance1 = clazz1.newInstance();
         assertEquals(42, instance1.add(20, 22));
diff --git a/tools/layoutlib/create/tests/com/android/tools/layoutlib/create/StubMethodAdapterTest.java b/tools/layoutlib/create/tests/com/android/tools/layoutlib/create/StubMethodAdapterTest.java
new file mode 100644
index 0000000..3db3e23
--- /dev/null
+++ b/tools/layoutlib/create/tests/com/android/tools/layoutlib/create/StubMethodAdapterTest.java
@@ -0,0 +1,132 @@
+/*
+ * 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.tools.layoutlib.create;
+
+import com.android.tools.layoutlib.create.dataclass.StubClass;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.objectweb.asm.ClassReader;
+import org.objectweb.asm.ClassVisitor;
+import org.objectweb.asm.ClassWriter;
+import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.Opcodes;
+import org.objectweb.asm.Type;
+
+import java.lang.reflect.Method;
+import java.util.function.BiPredicate;
+import java.util.function.Consumer;
+
+import static org.junit.Assert.*;
+
+public class StubMethodAdapterTest {
+
+    private static final String STUB_CLASS_NAME = StubClass.class.getName();
+
+    /**
+     * Load a dummy class, stub one of its method and ensure that the modified class works as
+     * intended.
+     */
+    @Test
+    public void testBoolean() throws Exception {
+        final String methodName = "returnTrue";
+        // First don't change the method and assert that it returns true
+        testBoolean((name, type) -> false, Assert::assertTrue, methodName);
+        // Change the method now and assert that it returns false.
+        testBoolean((name, type) -> methodName.equals(name) &&
+                Type.BOOLEAN_TYPE.equals(type.getReturnType()), Assert::assertFalse, methodName);
+    }
+
+    /**
+     * @param methodPredicate tests if the method should be replaced
+     */
+    private void testBoolean(BiPredicate<String, Type> methodPredicate, Consumer<Boolean> assertion,
+            String methodName) throws Exception {
+        ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_MAXS);
+        // Always rename the class to avoid conflict with the original class.
+        String newClassName = STUB_CLASS_NAME + '_';
+        new ClassReader(STUB_CLASS_NAME).accept(
+                new ClassAdapter(newClassName, writer, methodPredicate), 0);
+        MyClassLoader myClassLoader = new MyClassLoader(newClassName, writer.toByteArray());
+        Class<?> aClass = myClassLoader.loadClass(newClassName);
+        assertTrue("StubClass not loaded by the classloader. Likely a bug in the test.",
+                myClassLoader.findClassCalled);
+        Method method = aClass.getMethod(methodName);
+        Object o = aClass.newInstance();
+        assertion.accept((Boolean) method.invoke(o));
+    }
+
+    private static class ClassAdapter extends ClassVisitor {
+
+        private final String mClassName;
+        private final BiPredicate<String, Type> mMethodPredicate;
+
+        private ClassAdapter(String className, ClassVisitor cv,
+                BiPredicate<String, Type> methodPredicate) {
+            super(Main.ASM_VERSION, cv);
+            mClassName = className.replace('.', '/');
+            mMethodPredicate = methodPredicate;
+        }
+
+        @Override
+        public void visit(int version, int access, String name, String signature, String superName,
+                String[] interfaces) {
+            super.visit(version, access, mClassName, signature, superName,
+                    interfaces);
+        }
+
+        @Override
+        public MethodVisitor visitMethod(int access, String name, String desc, String signature,
+                String[] exceptions) {
+            // Copied partly from
+            // com.android.tools.layoutlib.create.DelegateClassAdapter.visitMethod()
+            // but not generating the _Original method.
+            boolean isStatic = (access & Opcodes.ACC_STATIC) != 0;
+            boolean isNative = (access & Opcodes.ACC_NATIVE) != 0;
+            MethodVisitor originalMethod =
+                    super.visitMethod(access, name, desc, signature, exceptions);
+            Type descriptor = Type.getMethodType(desc);
+            if (mMethodPredicate.test(name, descriptor)) {
+                String methodSignature = mClassName + "#" + name;
+                String invokeSignature = methodSignature + desc;
+                return new StubMethodAdapter(originalMethod, name, descriptor.getReturnType(),
+                        invokeSignature, isStatic, isNative);
+            }
+            return originalMethod;
+        }
+    }
+
+    private static class MyClassLoader extends ClassLoader {
+        private final String mName;
+        private final byte[] mBytes;
+        private boolean findClassCalled;
+
+        private MyClassLoader(String name, byte[] bytes) {
+            mName = name;
+            mBytes = bytes;
+        }
+
+        @Override
+        protected Class<?> findClass(String name) throws ClassNotFoundException {
+            if (name.equals(mName)) {
+                findClassCalled = true;
+                return defineClass(name, mBytes, 0, mBytes.length);
+            }
+            return super.findClass(name);
+        }
+    }
+}
diff --git a/media/mca/effect/java/android/media/effect/package-info.java b/tools/layoutlib/create/tests/com/android/tools/layoutlib/create/dataclass/StubClass.java
similarity index 63%
copy from media/mca/effect/java/android/media/effect/package-info.java
copy to tools/layoutlib/create/tests/com/android/tools/layoutlib/create/dataclass/StubClass.java
index b2c14ff..3ae8e47 100644
--- a/media/mca/effect/java/android/media/effect/package-info.java
+++ b/tools/layoutlib/create/tests/com/android/tools/layoutlib/create/dataclass/StubClass.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2011 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.
@@ -14,15 +14,17 @@
  * limitations under the License.
  */
 
+package com.android.tools.layoutlib.create.dataclass;
 
-package android.media.effect;
+import com.android.tools.layoutlib.create.StubMethodAdapterTest;
 
 /**
- * <h1>Effect Framework</h1>
- *
- * This package includes a collection of high-performance visual effects that make use of the
- * mobile filter framework subsystem.
- *
- * TODO: More Documentation
- *
+ * Used by {@link StubMethodAdapterTest}
  */
+@SuppressWarnings("unused")
+public class StubClass {
+
+    public boolean returnTrue() {
+        return true;
+    }
+}
diff --git a/wifi/java/android/net/wifi/RttManager.java b/wifi/java/android/net/wifi/RttManager.java
index 59416b8..13abaff 100644
--- a/wifi/java/android/net/wifi/RttManager.java
+++ b/wifi/java/android/net/wifi/RttManager.java
@@ -300,7 +300,7 @@
                 try {
                     mRttCapabilities = mService.getRttCapabilities();
                 } catch (RemoteException e) {
-                    Log.e(TAG, "Can not get RTT Capabilities");
+                    throw e.rethrowFromSystemServer();
                 }
             }
             return mRttCapabilities;
@@ -1132,7 +1132,7 @@
                     Log.d(TAG, "Get the messenger from " + mService);
                     messenger = mService.getMessenger();
                 } catch (RemoteException e) {
-                    /* do nothing */
+                    throw e.rethrowFromSystemServer();
                 } catch (SecurityException e) {
                     /* do nothing */
                 }
diff --git a/wifi/java/android/net/wifi/ScanResult.java b/wifi/java/android/net/wifi/ScanResult.java
index a46aaec..a9259fa 100644
--- a/wifi/java/android/net/wifi/ScanResult.java
+++ b/wifi/java/android/net/wifi/ScanResult.java
@@ -305,9 +305,12 @@
      */
     public static class InformationElement {
         public static final int EID_SSID = 0;
+        public static final int EID_SUPPORTED_RATES = 1;
         public static final int EID_TIM = 5;
         public static final int EID_BSS_LOAD = 11;
+        public static final int EID_ERP = 42;
         public static final int EID_RSN = 48;
+        public static final int EID_EXTENDED_SUPPORTED_RATES = 50;
         public static final int EID_HT_OPERATION = 61;
         public static final int EID_INTERWORKING = 107;
         public static final int EID_ROAMING_CONSORTIUM = 111;
diff --git a/wifi/java/android/net/wifi/WifiConfiguration.java b/wifi/java/android/net/wifi/WifiConfiguration.java
index ddd8f43..7dc8049 100644
--- a/wifi/java/android/net/wifi/WifiConfiguration.java
+++ b/wifi/java/android/net/wifi/WifiConfiguration.java
@@ -1357,6 +1357,7 @@
                 append(" PROVIDER-NAME: ").append(this.providerFriendlyName).
                 append(" BSSID: ").append(this.BSSID).append(" FQDN: ").append(this.FQDN)
                 .append(" PRIO: ").append(this.priority)
+                .append(" HIDDEN: ").append(this.hiddenSSID)
                 .append('\n');
 
 
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index 4921073..a5bfd3c 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -39,9 +39,9 @@
 import android.util.Log;
 import android.util.SparseArray;
 
-import com.android.internal.annotations.GuardedBy;
 import com.android.internal.util.AsyncChannel;
 import com.android.internal.util.Protocol;
+import com.android.server.net.NetworkPinner;
 
 import java.net.InetAddress;
 import java.util.ArrayList;
@@ -678,11 +678,6 @@
     private static int sThreadRefCount;
     private static HandlerThread sHandlerThread;
 
-    @GuardedBy("sCM")
-    // TODO: Introduce refcounting and make this a per-process static callback, instead of a
-    // per-WifiManager callback.
-    private PinningNetworkCallback mNetworkCallback;
-
     /**
      * Create a new WifiManager instance.
      * Applications will almost always want to use
@@ -723,8 +718,7 @@
         try {
             return mService.getConfiguredNetworks();
         } catch (RemoteException e) {
-            Log.w(TAG, "Caught RemoteException trying to get configured networks: " + e);
-            return null;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -734,7 +728,7 @@
         try {
             return mService.getPrivilegedConfiguredNetworks();
         } catch (RemoteException e) {
-            return null;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -744,7 +738,7 @@
         try {
             return mService.getConnectionStatistics();
         } catch (RemoteException e) {
-            return null;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -758,7 +752,7 @@
         try {
             return mService.getMatchingWifiConfig(scanResult);
         } catch (RemoteException e) {
-            return null;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -818,7 +812,7 @@
         try {
             return mService.addOrUpdateNetwork(config);
         } catch (RemoteException e) {
-            return -1;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -832,7 +826,7 @@
         try {
             return mService.addPasspointManagementObject(mo);
         } catch (RemoteException e) {
-            return -1;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -848,7 +842,7 @@
         try {
             return mService.modifyPasspointManagementObject(fqdn, mos);
         } catch (RemoteException e) {
-            return -1;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -862,6 +856,7 @@
         try {
             mService.queryPasspointIcon(bssid, fileName);
         } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -875,7 +870,7 @@
         try {
             return mService.matchProviderWithCurrentNetwork(fqdn);
         } catch (RemoteException e) {
-            return -1;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -889,28 +884,11 @@
         try {
             mService.deauthenticateNetwork(holdoff, ess);
         } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
         }
     }
 
     /**
-     * Sets whether or not the given network is metered from a network policy
-     * point of view. A network should be classified as metered when the user is
-     * sensitive to heavy data usage on that connection due to monetary costs,
-     * data limitations or battery/performance issues. A typical example would
-     * be a wifi connection where the user was being charged for usage.
-     * @param netId the integer that identifies the network configuration
-     * to the supplicant.
-     * @param isMetered True to mark the network as metered.
-     * @return {@code true} if the operation succeeded.
-     * @hide
-     */
-    @SystemApi
-    public boolean setMetered(int netId, boolean isMetered) {
-        // TODO(jjoslin): Implement
-        return false;
-    }
-
-    /**
      * Remove the specified network from the list of configured networks.
      * This may result in the asynchronous delivery of state change
      * events.
@@ -922,7 +900,7 @@
         try {
             return mService.removeNetwork(netId);
         } catch (RemoteException e) {
-            return false;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -955,18 +933,22 @@
     public boolean enableNetwork(int netId, boolean disableOthers) {
         final boolean pin = disableOthers && mTargetSdkVersion < Build.VERSION_CODES.LOLLIPOP;
         if (pin) {
-            registerPinningNetworkCallback();
+            NetworkRequest request = new NetworkRequest.Builder()
+                    .clearCapabilities()
+                    .addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
+                    .build();
+            NetworkPinner.pin(mContext, request);
         }
 
         boolean success;
         try {
             success = mService.enableNetwork(netId, disableOthers);
         } catch (RemoteException e) {
-            success = false;
+            throw e.rethrowFromSystemServer();
         }
 
         if (pin && !success) {
-            unregisterPinningNetworkCallback();
+            NetworkPinner.unpin();
         }
 
         return success;
@@ -983,7 +965,7 @@
         try {
             return mService.disableNetwork(netId);
         } catch (RemoteException e) {
-            return false;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -997,7 +979,7 @@
             mService.disconnect();
             return true;
         } catch (RemoteException e) {
-            return false;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1012,7 +994,7 @@
             mService.reconnect();
             return true;
         } catch (RemoteException e) {
-            return false;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1027,7 +1009,7 @@
             mService.reassociate();
             return true;
         } catch (RemoteException e) {
-            return false;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1042,7 +1024,7 @@
         try {
             return mService.pingSupplicant();
         } catch (RemoteException e) {
-            return false;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1090,7 +1072,7 @@
         try {
             return mService.getSupportedFeatures();
         } catch (RemoteException e) {
-            return 0;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1216,9 +1198,8 @@
                 return mService.reportActivityInfo();
             }
         } catch (RemoteException e) {
-            Log.e(TAG, "getControllerActivityEnergyInfo: " + e);
+            throw e.rethrowFromSystemServer();
         }
-        return null;
     }
 
     /**
@@ -1232,7 +1213,7 @@
             mService.startScan(null, null);
             return true;
         } catch (RemoteException e) {
-            return false;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1243,7 +1224,7 @@
             mService.startScan(null, workSource);
             return true;
         } catch (RemoteException e) {
-            return false;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1299,7 +1280,7 @@
         try {
             return mService.getWpsNfcConfigurationToken(netId);
         } catch (RemoteException e) {
-            return null;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1311,7 +1292,7 @@
         try {
             return mService.getConnectionInfo();
         } catch (RemoteException e) {
-            return null;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1328,7 +1309,7 @@
         try {
             return mService.getScanResults(mContext.getOpPackageName());
         } catch (RemoteException e) {
-            return new ArrayList<ScanResult>();
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1344,7 +1325,7 @@
         try {
             return mService.isScanAlwaysAvailable();
         } catch (RemoteException e) {
-            return false;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1361,7 +1342,7 @@
         try {
             return mService.saveConfiguration();
         } catch (RemoteException e) {
-            return false;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1375,7 +1356,9 @@
     public void setCountryCode(String country, boolean persist) {
         try {
             mService.setCountryCode(country, persist);
-        } catch (RemoteException e) { }
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
     }
 
     /**
@@ -1387,9 +1370,9 @@
     public String getCountryCode() {
        try {
            String country = mService.getCountryCode();
-           return(country);
+           return country;
        } catch (RemoteException e) {
-           return null;
+           throw e.rethrowFromSystemServer();
        }
     }
 
@@ -1405,7 +1388,9 @@
     public void setFrequencyBand(int band, boolean persist) {
         try {
             mService.setFrequencyBand(band, persist);
-        } catch (RemoteException e) { }
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
     }
 
     /**
@@ -1421,7 +1406,7 @@
         try {
             return mService.getFrequencyBand();
         } catch (RemoteException e) {
-            return -1;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1434,7 +1419,7 @@
         try {
             return mService.isDualBandSupported();
         } catch (RemoteException e) {
-            return false;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1447,7 +1432,7 @@
         try {
             return mService.getDhcpInfo();
         } catch (RemoteException e) {
-            return null;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1461,7 +1446,7 @@
         try {
             return mService.setWifiEnabled(enabled);
         } catch (RemoteException e) {
-            return false;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1476,7 +1461,7 @@
         try {
             return mService.getWifiEnabledState();
         } catch (RemoteException e) {
-            return WIFI_STATE_UNKNOWN;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1553,7 +1538,7 @@
             mService.setWifiApEnabled(wifiConfig, enabled);
             return true;
         } catch (RemoteException e) {
-            return false;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1571,7 +1556,7 @@
         try {
             return mService.getWifiApEnabledState();
         } catch (RemoteException e) {
-            return WIFI_AP_STATE_FAILED;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1598,7 +1583,7 @@
         try {
             return mService.getWifiApConfiguration();
         } catch (RemoteException e) {
-            return null;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1612,8 +1597,7 @@
         try {
             return mService.buildWifiConfig(uriString, mimeType, data);
         } catch (RemoteException e) {
-            Log.w(TAG, "Caught RemoteException trying to build wifi config: " + e);
-            return null;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1629,7 +1613,7 @@
             mService.setWifiApConfiguration(wifiConfig);
             return true;
         } catch (RemoteException e) {
-            return false;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1646,7 +1630,7 @@
             mService.addToBlacklist(bssid);
             return true;
         } catch (RemoteException e) {
-            return false;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1663,7 +1647,7 @@
             mService.clearBlacklist();
             return true;
         } catch (RemoteException e) {
-            return false;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1692,7 +1676,7 @@
         try {
             mService.enableTdls(remoteIPAddress.getHostAddress(), enable);
         } catch (RemoteException e) {
-            // Just ignore the exception
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1706,7 +1690,7 @@
         try {
             mService.enableTdlsWithMacAddress(remoteMacAddress, enable);
         } catch (RemoteException e) {
-            // Just ignore the exception
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -2012,100 +1996,6 @@
                 "No permission to access and change wifi or a bad initialization");
     }
 
-    private void initConnectivityManager() {
-        // TODO: what happens if an app calls a WifiManager API before ConnectivityManager is
-        // registered? Can we fix this by starting ConnectivityService before WifiService?
-        if (sCM == null) {
-            sCM = (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
-            if (sCM == null) {
-                throw new IllegalStateException("Bad luck, ConnectivityService not started.");
-            }
-        }
-    }
-
-    /**
-     * A NetworkCallback that pins the process to the first wifi network to connect.
-     *
-     * We use this to maintain compatibility with pre-M apps that call WifiManager.enableNetwork()
-     * to connect to a Wi-Fi network that has no Internet access, and then assume that they will be
-     * able to use that network because it's the system default.
-     *
-     * In order to maintain compatibility with apps that call setProcessDefaultNetwork themselves,
-     * we try not to set the default network unless they have already done so, and we try not to
-     * clear the default network unless we set it ourselves.
-     *
-     * This should maintain behaviour that's compatible with L, which would pin the whole system to
-     * any wifi network that was created via enableNetwork(..., true) until that network
-     * disconnected.
-     *
-     * Note that while this hack allows network traffic to flow, it is quite limited. For example:
-     *
-     * 1. setProcessDefaultNetwork only affects this process, so:
-     *    - Any subprocesses spawned by this process will not be pinned to Wi-Fi.
-     *    - If this app relies on any other apps on the device also being on Wi-Fi, that won't work
-     *      either, because other apps on the device will not be pinned.
-     * 2. The behaviour of other APIs is not modified. For example:
-     *    - getActiveNetworkInfo will return the system default network, not Wi-Fi.
-     *    - There will be no CONNECTIVITY_ACTION broadcasts about TYPE_WIFI.
-     *    - getProcessDefaultNetwork will not return null, so if any apps are relying on that, they
-     *      will be surprised as well.
-     */
-    private class PinningNetworkCallback extends NetworkCallback {
-        private Network mPinnedNetwork;
-
-        @Override
-        public void onPreCheck(Network network) {
-            if (sCM.getProcessDefaultNetwork() == null && mPinnedNetwork == null) {
-                sCM.setProcessDefaultNetwork(network);
-                mPinnedNetwork = network;
-                Log.d(TAG, "Wifi alternate reality enabled on network " + network);
-            }
-        }
-
-        @Override
-        public void onLost(Network network) {
-            if (network.equals(mPinnedNetwork) && network.equals(sCM.getProcessDefaultNetwork())) {
-                sCM.setProcessDefaultNetwork(null);
-                Log.d(TAG, "Wifi alternate reality disabled on network " + network);
-                mPinnedNetwork = null;
-                unregisterPinningNetworkCallback();
-            }
-        }
-    }
-
-    private void registerPinningNetworkCallback() {
-        initConnectivityManager();
-        synchronized (sCM) {
-            if (mNetworkCallback == null) {
-                // TODO: clear all capabilities.
-                NetworkRequest request = new NetworkRequest.Builder()
-                        .addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
-                        .removeCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
-                        .build();
-                mNetworkCallback = new PinningNetworkCallback();
-                try {
-                    sCM.registerNetworkCallback(request, mNetworkCallback);
-                } catch (SecurityException e) {
-                    Log.d(TAG, "Failed to register network callback", e);
-                }
-            }
-        }
-    }
-
-    private void unregisterPinningNetworkCallback() {
-        initConnectivityManager();
-        synchronized (sCM) {
-            if (mNetworkCallback != null) {
-                try {
-                    sCM.unregisterNetworkCallback(mNetworkCallback);
-                } catch (SecurityException e) {
-                    Log.d(TAG, "Failed to unregister network callback", e);
-                }
-                mNetworkCallback = null;
-            }
-        }
-    }
-
     /**
      * Connect to a network with the given configuration. The network also
      * gets added to the supplicant configuration.
@@ -2219,6 +2109,7 @@
         try {
             mService.disableEphemeralNetwork(SSID);
         } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -2259,7 +2150,7 @@
         try {
             return mService.getWifiServiceMessenger();
         } catch (RemoteException e) {
-            return null;
+            throw e.rethrowFromSystemServer();
         } catch (SecurityException e) {
             return null;
         }
@@ -2274,7 +2165,7 @@
         try {
             return mService.getConfigFile();
         } catch (RemoteException e) {
-            return null;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -2340,7 +2231,8 @@
                             }
                             mActiveLockCount++;
                         }
-                    } catch (RemoteException ignore) {
+                    } catch (RemoteException e) {
+                        throw e.rethrowFromSystemServer();
                     }
                     mHeld = true;
                 }
@@ -2367,7 +2259,8 @@
                         synchronized (WifiManager.this) {
                             mActiveLockCount--;
                         }
-                    } catch (RemoteException ignore) {
+                    } catch (RemoteException e) {
+                        throw e.rethrowFromSystemServer();
                     }
                     mHeld = false;
                 }
@@ -2427,6 +2320,7 @@
                     try {
                         mService.updateWifiLockWorkSource(mBinder, mWorkSource);
                     } catch (RemoteException e) {
+                        throw e.rethrowFromSystemServer();
                     }
                 }
             }
@@ -2456,7 +2350,8 @@
                         synchronized (WifiManager.this) {
                             mActiveLockCount--;
                         }
-                    } catch (RemoteException ignore) {
+                    } catch (RemoteException e) {
+                        throw e.rethrowFromSystemServer();
                     }
                 }
             }
@@ -2572,7 +2467,8 @@
                             }
                             mActiveLockCount++;
                         }
-                    } catch (RemoteException ignore) {
+                    } catch (RemoteException e) {
+                        throw e.rethrowFromSystemServer();
                     }
                     mHeld = true;
                 }
@@ -2611,7 +2507,8 @@
                         synchronized (WifiManager.this) {
                             mActiveLockCount--;
                         }
-                    } catch (RemoteException ignore) {
+                    } catch (RemoteException e) {
+                        throw e.rethrowFromSystemServer();
                     }
                     mHeld = false;
                 }
@@ -2685,7 +2582,7 @@
         try {
             return mService.isMulticastEnabled();
         } catch (RemoteException e) {
-            return false;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -2698,7 +2595,7 @@
             mService.initializeMulticastFiltering();
             return true;
         } catch (RemoteException e) {
-             return false;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -2736,7 +2633,7 @@
         try {
             return mService.getVerboseLoggingLevel();
         } catch (RemoteException e) {
-            return 0;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -2748,7 +2645,7 @@
         try {
             mService.enableAggressiveHandover(enabled);
         } catch (RemoteException e) {
-
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -2761,7 +2658,7 @@
         try {
             return mService.getAggressiveHandover();
         } catch (RemoteException e) {
-            return 0;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -2773,7 +2670,7 @@
         try {
             mService.setAllowScansWithTraffic(enabled);
         } catch (RemoteException e) {
-
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -2785,7 +2682,7 @@
         try {
             return mService.getAllowScansWithTraffic();
         } catch (RemoteException e) {
-            return 0;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -2798,6 +2695,7 @@
         try {
             mService.factoryReset();
         } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -2810,7 +2708,7 @@
         try {
             return mService.getCurrentNetwork();
         } catch (RemoteException e) {
-            return null;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -2824,7 +2722,7 @@
         try {
             return mService.enableAutoJoinWhenAssociated(enabled);
         } catch (RemoteException e) {
-            return false;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -2836,7 +2734,7 @@
         try {
             return mService.getEnableAutoJoinWhenAssociated();
         } catch (RemoteException e) {
-            return false;
+            throw e.rethrowFromSystemServer();
         }
     }
     /**
@@ -2847,7 +2745,7 @@
         try {
             mService.setHalBasedAutojoinOffload(enabled);
         } catch (RemoteException e) {
-
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -2859,7 +2757,7 @@
         try {
             return mService.getHalBasedAutojoinOffload();
         } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
         }
-        return 0;
     }
 }
diff --git a/wifi/java/android/net/wifi/WifiScanner.java b/wifi/java/android/net/wifi/WifiScanner.java
index 69e179d..c5e7bff 100644
--- a/wifi/java/android/net/wifi/WifiScanner.java
+++ b/wifi/java/android/net/wifi/WifiScanner.java
@@ -169,6 +169,13 @@
         public int band;
         /** list of channels; used when band is set to WIFI_BAND_UNSPECIFIED */
         public ChannelSpec[] channels;
+        /**
+         * list of networkId's of hidden networks to scan for.
+         * These Id's should correspond to the wpa_supplicant's networkId's and will be used
+         * in connectivity scans using wpa_supplicant.
+         * {@hide}
+         * */
+        public int[] hiddenNetworkIds;
         /** period of background scan; in millisecond, 0 => single shot scan */
         public int periodInMs;
         /** must have a valid REPORT_EVENT value */
@@ -192,6 +199,11 @@
          * for a given period
          */
         public int stepCount;
+        /**
+         * Flag to indicate if the scan settings are targeted for PNO scan.
+         * {@hide}
+         */
+        public boolean isPnoScan;
 
         /** Implement the Parcelable interface {@hide} */
         public int describeContents() {
@@ -207,10 +219,9 @@
             dest.writeInt(maxScansToCache);
             dest.writeInt(maxPeriodInMs);
             dest.writeInt(stepCount);
-
+            dest.writeInt(isPnoScan ? 1 : 0);
             if (channels != null) {
                 dest.writeInt(channels.length);
-
                 for (int i = 0; i < channels.length; i++) {
                     dest.writeInt(channels[i].frequency);
                     dest.writeInt(channels[i].dwellTimeMS);
@@ -219,13 +230,13 @@
             } else {
                 dest.writeInt(0);
             }
+            dest.writeIntArray(hiddenNetworkIds);
         }
 
         /** Implement the Parcelable interface {@hide} */
         public static final Creator<ScanSettings> CREATOR =
                 new Creator<ScanSettings>() {
                     public ScanSettings createFromParcel(Parcel in) {
-
                         ScanSettings settings = new ScanSettings();
                         settings.band = in.readInt();
                         settings.periodInMs = in.readInt();
@@ -234,17 +245,17 @@
                         settings.maxScansToCache = in.readInt();
                         settings.maxPeriodInMs = in.readInt();
                         settings.stepCount = in.readInt();
+                        settings.isPnoScan = in.readInt() == 1;
                         int num_channels = in.readInt();
                         settings.channels = new ChannelSpec[num_channels];
                         for (int i = 0; i < num_channels; i++) {
                             int frequency = in.readInt();
-
                             ChannelSpec spec = new ChannelSpec(frequency);
                             spec.dwellTimeMS = in.readInt();
                             spec.passive = in.readInt() == 1;
                             settings.channels[i] = spec;
                         }
-
+                        settings.hiddenNetworkIds = in.createIntArray();
                         return settings;
                     }
 
@@ -436,6 +447,158 @@
                 };
     }
 
+    /** {@hide} */
+    public static final String PNO_PARAMS_PNO_SETTINGS_KEY = "PnoSettings";
+    /** {@hide} */
+    public static final String PNO_PARAMS_SCAN_SETTINGS_KEY = "ScanSettings";
+    /**
+     * PNO scan configuration parameters to be sent to {@link #startPnoScan}.
+     * Note: This structure needs to be in sync with |wifi_epno_params| struct in gscan HAL API.
+     * {@hide}
+     */
+    public static class PnoSettings implements Parcelable {
+        /**
+         * Pno network to be added to the PNO scan filtering.
+         * {@hide}
+         */
+        public static class PnoNetwork {
+            /*
+             * Pno flags bitmask to be set in {@link #PnoNetwork.flags}
+             */
+            /** Whether directed scan needs to be performed (for hidden SSIDs) */
+            public static final byte FLAG_DIRECTED_SCAN = (1 << 0);
+            /** Whether PNO event shall be triggered if the network is found on A band */
+            public static final byte FLAG_A_BAND = (1 << 1);
+            /** Whether PNO event shall be triggered if the network is found on G band */
+            public static final byte FLAG_G_BAND = (1 << 2);
+            /**
+             * Whether strict matching is required
+             * If required then the firmware must store the network's SSID and not just a hash
+             */
+            public static final byte FLAG_STRICT_MATCH = (1 << 3);
+            /**
+             * If this SSID should be considered the same network as the currently connected
+             * one for scoring.
+             */
+            public static final byte FLAG_SAME_NETWORK = (1 << 4);
+
+            /*
+             * Code for matching the beacon AUTH IE - additional codes. Bitmask to be set in
+             * {@link #PnoNetwork.authBitField}
+             */
+            /** Open Network */
+            public static final byte AUTH_CODE_OPEN = (1 << 0);
+            /** WPA_PSK or WPA2PSK */
+            public static final byte AUTH_CODE_PSK = (1 << 1);
+            /** any EAPOL */
+            public static final byte AUTH_CODE_EAPOL = (1 << 2);
+
+            /** SSID of the network */
+            public String ssid;
+            /** Network ID in wpa_supplicant */
+            public int networkId;
+            /** Assigned priority for the network */
+            public int priority;
+            /** Bitmask of the FLAG_XXX */
+            public byte flags;
+            /** Bitmask of the ATUH_XXX */
+            public byte authBitField;
+
+            /**
+             * default constructor for PnoNetwork
+             */
+            public PnoNetwork(String ssid) {
+                this.ssid = ssid;
+                flags = 0;
+                authBitField = 0;
+            }
+        }
+
+        /** Connected vs Disconnected PNO flag {@hide} */
+        public boolean isConnected;
+        /** Minimum 5GHz RSSI for a BSSID to be considered */
+        public int min5GHzRssi;
+        /** Minimum 2.4GHz RSSI for a BSSID to be considered */
+        public int min24GHzRssi;
+        /** Maximum score that a network can have before bonuses */
+        public int initialScoreMax;
+        /**
+         *  Only report when there is a network's score this much higher
+         *  than the current connection.
+         */
+        public int currentConnectionBonus;
+        /** score bonus for all networks with the same network flag */
+        public int sameNetworkBonus;
+        /** score bonus for networks that are not open */
+        public int secureBonus;
+        /** 5GHz RSSI score bonus (applied to all 5GHz networks) */
+        public int band5GHzBonus;
+        /** Pno Network filter list */
+        public PnoNetwork[] networkList;
+
+        /** Implement the Parcelable interface {@hide} */
+        public int describeContents() {
+            return 0;
+        }
+
+        /** Implement the Parcelable interface {@hide} */
+        public void writeToParcel(Parcel dest, int flags) {
+            dest.writeInt(isConnected ? 1 : 0);
+            dest.writeInt(min5GHzRssi);
+            dest.writeInt(min24GHzRssi);
+            dest.writeInt(initialScoreMax);
+            dest.writeInt(currentConnectionBonus);
+            dest.writeInt(sameNetworkBonus);
+            dest.writeInt(secureBonus);
+            dest.writeInt(band5GHzBonus);
+            if (networkList != null) {
+                dest.writeInt(networkList.length);
+                for (int i = 0; i < networkList.length; i++) {
+                    dest.writeString(networkList[i].ssid);
+                    dest.writeInt(networkList[i].networkId);
+                    dest.writeInt(networkList[i].priority);
+                    dest.writeByte(networkList[i].flags);
+                    dest.writeByte(networkList[i].authBitField);
+                }
+            } else {
+                dest.writeInt(0);
+            }
+        }
+
+        /** Implement the Parcelable interface {@hide} */
+        public static final Creator<PnoSettings> CREATOR =
+                new Creator<PnoSettings>() {
+                    public PnoSettings createFromParcel(Parcel in) {
+                        PnoSettings settings = new PnoSettings();
+                        settings.isConnected = in.readInt() == 1;
+                        settings.min5GHzRssi = in.readInt();
+                        settings.min24GHzRssi = in.readInt();
+                        settings.initialScoreMax = in.readInt();
+                        settings.currentConnectionBonus = in.readInt();
+                        settings.sameNetworkBonus = in.readInt();
+                        settings.secureBonus = in.readInt();
+                        settings.band5GHzBonus = in.readInt();
+                        int numNetworks = in.readInt();
+                        settings.networkList = new PnoNetwork[numNetworks];
+                        for (int i = 0; i < numNetworks; i++) {
+                            String ssid = in.readString();
+                            PnoNetwork network = new PnoNetwork(ssid);
+                            network.networkId = in.readInt();
+                            network.priority = in.readInt();
+                            network.flags = in.readByte();
+                            network.authBitField = in.readByte();
+                            settings.networkList[i] = network;
+                        }
+                        return settings;
+                    }
+
+                    public PnoSettings[] newArray(int size) {
+                        return new PnoSettings[size];
+                    }
+                };
+
+    }
+
     /**
      * interface to get scan events on; specify this on {@link #startBackgroundScan} or
      * {@link #startScan}
@@ -456,6 +619,18 @@
         public void onFullResult(ScanResult fullScanResult);
     }
 
+    /**
+     * interface to get PNO scan events on; specify this on {@link #startDisconnectedPnoScan} and
+     * {@link #startConnectedPnoScan}.
+     * {@hide}
+     */
+    public interface PnoScanListener extends ScanListener {
+        /**
+         * Invoked when one of the PNO networks are found in scan results.
+         */
+        void onPnoNetworkFound(ScanResult[] results);
+    }
+
     /** start wifi scan in background
      * @param settings specifies various parameters for the scan; for more information look at
      * {@link ScanSettings}
@@ -521,6 +696,75 @@
         sAsyncChannel.sendMessage(CMD_STOP_SINGLE_SCAN, 0, key);
     }
 
+    private void startPnoScan(ScanSettings scanSettings, PnoSettings pnoSettings, int key) {
+        // Bundle up both the settings and send it across.
+        Bundle pnoParams = new Bundle();
+        if (pnoParams == null) return;
+        // Set the PNO scan flag.
+        scanSettings.isPnoScan = true;
+        pnoParams.putParcelable(PNO_PARAMS_SCAN_SETTINGS_KEY, scanSettings);
+        pnoParams.putParcelable(PNO_PARAMS_PNO_SETTINGS_KEY, pnoSettings);
+        sAsyncChannel.sendMessage(CMD_START_PNO_SCAN, 0, key, pnoParams);
+    }
+    /**
+     * Start wifi connected PNO scan
+     * @param scanSettings specifies various parameters for the scan; for more information look at
+     * {@link ScanSettings}
+     * @param pnoSettings specifies various parameters for PNO; for more information look at
+     * {@link PnoSettings}
+     * @param listener specifies the object to report events to. This object is also treated as a
+     *                 key for this scan, and must also be specified to cancel the scan. Multiple
+     *                 scans should also not share this object.
+     * {@hide}
+     */
+    public void startConnectedPnoScan(ScanSettings scanSettings, PnoSettings pnoSettings,
+            PnoScanListener listener) {
+        Preconditions.checkNotNull(listener, "listener cannot be null");
+        Preconditions.checkNotNull(pnoSettings, "pnoSettings cannot be null");
+        int key = addListener(listener);
+        if (key == INVALID_KEY) return;
+        validateChannel();
+        pnoSettings.isConnected = true;
+        startPnoScan(scanSettings, pnoSettings, key);
+    }
+    /**
+     * Start wifi disconnected PNO scan
+     * @param scanSettings specifies various parameters for the scan; for more information look at
+     * {@link ScanSettings}
+     * @param pnoSettings specifies various parameters for PNO; for more information look at
+     * {@link PnoSettings}
+     * @param listener specifies the object to report events to. This object is also treated as a
+     *                 key for this scan, and must also be specified to cancel the scan. Multiple
+     *                 scans should also not share this object.
+     * {@hide}
+     */
+    public void startDisconnectedPnoScan(ScanSettings scanSettings, PnoSettings pnoSettings,
+            PnoScanListener listener) {
+        Preconditions.checkNotNull(listener, "listener cannot be null");
+        Preconditions.checkNotNull(pnoSettings, "pnoSettings cannot be null");
+        int key = addListener(listener);
+        if (key == INVALID_KEY) return;
+        validateChannel();
+        pnoSettings.isConnected = false;
+        startPnoScan(scanSettings, pnoSettings, key);
+    }
+    /**
+     * Stop an ongoing wifi PNO scan
+     * @param pnoSettings specifies various parameters for PNO; for more information look at
+     * {@link PnoSettings}
+     * @param listener specifies which scan to cancel; must be same object as passed in {@link
+     *  #startPnoScan}
+     * TODO(rpius): Check if we can remove pnoSettings param in stop.
+     * {@hide}
+     */
+    public void stopPnoScan(PnoSettings pnoSettings, ScanListener listener) {
+        Preconditions.checkNotNull(listener, "listener cannot be null");
+        int key = removeListener(listener);
+        if (key == INVALID_KEY) return;
+        validateChannel();
+        sAsyncChannel.sendMessage(CMD_STOP_PNO_SCAN, 0, key, pnoSettings);
+    }
+
     /** specifies information about an access point of interest */
     public static class BssidInfo {
         /** bssid of the access point; in XX:XX:XX:XX:XX:XX format */
@@ -824,6 +1068,12 @@
     public static final int CMD_STOP_SINGLE_SCAN            = BASE + 22;
     /** @hide */
     public static final int CMD_SINGLE_SCAN_COMPLETED       = BASE + 23;
+    /** @hide */
+    public static final int CMD_START_PNO_SCAN              = BASE + 24;
+    /** @hide */
+    public static final int CMD_STOP_PNO_SCAN               = BASE + 25;
+    /** @hide */
+    public static final int CMD_PNO_NETWORK_FOUND           = BASE + 26;
 
     private Context mContext;
     private IWifiScanner mService;
@@ -1110,6 +1360,10 @@
                     if (DBG) Log.d(TAG, "removing listener for single scan");
                     removeListener(msg.arg2);
                     break;
+                case CMD_PNO_NETWORK_FOUND:
+                    ((PnoScanListener) listener).onPnoNetworkFound(
+                            ((ParcelableScanResults) msg.obj).getResults());
+                    return;
                 default:
                     if (DBG) Log.d(TAG, "Ignoring message " + msg.what);
                     return;
diff --git a/wifi/java/android/net/wifi/nan/WifiNanManager.java b/wifi/java/android/net/wifi/nan/WifiNanManager.java
index 667c4b1..1b78beb 100644
--- a/wifi/java/android/net/wifi/nan/WifiNanManager.java
+++ b/wifi/java/android/net/wifi/nan/WifiNanManager.java
@@ -75,7 +75,7 @@
             }
             mService.connect(mBinder, listener.callback, events);
         } catch (RemoteException e) {
-            Log.w(TAG, "connect RemoteException (FYI - ignoring): " + e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -94,7 +94,7 @@
             mService.disconnect(mBinder);
             mBinder = null;
         } catch (RemoteException e) {
-            Log.w(TAG, "disconnect RemoteException (FYI - ignoring): " + e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -116,7 +116,7 @@
         try {
             mService.requestConfig(configRequest);
         } catch (RemoteException e) {
-            Log.w(TAG, "requestConfig RemoteException (FYI - ignoring): " + e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -173,8 +173,7 @@
             if (DBG) Log.d(TAG, "publish: session created - sessionId=" + sessionId);
             mService.publish(sessionId, publishData, publishSettings);
         } catch (RemoteException e) {
-            Log.w(TAG, "createSession/publish RemoteException: " + e);
-            return null;
+            throw e.rethrowFromSystemServer();
         }
 
         return new WifiNanPublishSession(this, sessionId);
@@ -200,7 +199,7 @@
         try {
             mService.publish(sessionId, publishData, publishSettings);
         } catch (RemoteException e) {
-            Log.w(TAG, "publish RemoteException: " + e);
+            throw e.rethrowFromSystemServer();
         }
     }
     /**
@@ -256,8 +255,7 @@
             if (DBG) Log.d(TAG, "subscribe: session created - sessionId=" + sessionId);
             mService.subscribe(sessionId, subscribeData, subscribeSettings);
         } catch (RemoteException e) {
-            Log.w(TAG, "createSession/subscribe RemoteException: " + e);
-            return null;
+            throw e.rethrowFromSystemServer();
         }
 
         return new WifiNanSubscribeSession(this, sessionId);
@@ -286,7 +284,7 @@
         try {
             mService.subscribe(sessionId, subscribeData, subscribeSettings);
         } catch (RemoteException e) {
-            Log.w(TAG, "subscribe RemoteException: " + e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -299,7 +297,7 @@
         try {
             mService.stopSession(sessionId);
         } catch (RemoteException e) {
-            Log.w(TAG, "stopSession RemoteException (FYI - ignoring): " + e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -312,7 +310,7 @@
         try {
             mService.destroySession(sessionId);
         } catch (RemoteException e) {
-            Log.w(TAG, "destroySession RemoteException (FYI - ignoring): " + e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -328,7 +326,7 @@
             }
             mService.sendMessage(sessionId, peerId, message, messageLength, messageId);
         } catch (RemoteException e) {
-            Log.w(TAG, "subscribe RemoteException (FYI - ignoring): " + e);
+            throw e.rethrowFromSystemServer();
         }
     }
 }
diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pManager.java b/wifi/java/android/net/wifi/p2p/WifiP2pManager.java
index 6409450..8d5cf63 100644
--- a/wifi/java/android/net/wifi/p2p/WifiP2pManager.java
+++ b/wifi/java/android/net/wifi/p2p/WifiP2pManager.java
@@ -1362,8 +1362,8 @@
     public void setMiracastMode(int mode) {
         try {
             mService.setMiracastMode(mode);
-        } catch(RemoteException e) {
-           // ignore
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1378,7 +1378,7 @@
         try {
             return mService.getMessenger();
         } catch (RemoteException e) {
-            return null;
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1393,7 +1393,7 @@
         try {
             return mService.getP2pStateMachineMessenger();
         } catch (RemoteException e) {
-            return null;
+            throw e.rethrowFromSystemServer();
         }
     }